diff --git a/bin/gt.js b/bin/gt.js index 589a3b1..9082a8e 100755 --- a/bin/gt.js +++ b/bin/gt.js @@ -76,6 +76,12 @@ const { argv } = yargs default: true, }) + .option('tls-record-fragmentation', { + type: 'boolean', + describe: 'enable TLS record fragmentation', + default: false + }) + .example('$0') .example('$0 --ip 127.0.0.1 --port 8000') .example('$0 --dns-server https://doh.securedns.eu/dns-query') @@ -128,6 +134,7 @@ async function main() { port: argv['dns-port'] }, source: 'CLI', + 'tlsRecordFragmentation': argv['tls-record-fragmentation'] }); const exitTrap = async () => { diff --git a/src/handlers/https.js b/src/handlers/https.js index b13a0b9..e7a8a96 100644 --- a/src/handlers/https.js +++ b/src/handlers/https.js @@ -43,7 +43,7 @@ export default async function handleHTTPS(clientSocket, firstChunk, proxy) { // -- clientSocket -- clientSocket.once('data', clientHello => { - const chunks = bufferToChunks(clientHello, proxy.config.clientHelloMTU); + const chunks = bufferToChunks(clientHello, proxy.config.clientHelloMTU, proxy.config.tlsRecordFragmentation); for (const chunk of chunks) { logger.debug(`[HTTPS HELLO] ${url.host} (length: ${chunk.length})`); tryWrite(serverSocket, chunk, close); diff --git a/src/utils/buffer.js b/src/utils/buffer.js index 14bf3d8..7933e26 100644 --- a/src/utils/buffer.js +++ b/src/utils/buffer.js @@ -1,4 +1,5 @@ -export function bufferToChunks(buffer, chunkSize) { +export function bufferToChunks(buffer, chunkSize, recordFragmentation) { + if(recordFragmentation) buffer=tlsRecordFragmentation(buffer, chunkSize) const result = []; const len = buffer.length; let i = 0; @@ -9,3 +10,26 @@ export function bufferToChunks(buffer, chunkSize) { return result; } +/** + * @param {Buffer} buffer + * @param {number} chunkSize + */ +function tlsRecordFragmentation(buffer, chunkSize) { + const list = [] + const header = buffer.subarray(0,3) + const fullRecord = buffer.subarray(5) + const len = fullRecord.length + let i = 0 + + while (i < len) { + const record = fullRecord.subarray(i, i+chunkSize) + const recordLength = record.length + const buf = Buffer.alloc(recordLength+5) + header.copy(buf) + buf.writeUInt16BE(recordLength,3) + record.copy(buf,5) + list.push(buf) + i+=chunkSize + } + return Buffer.concat(list) +}