From fea4f717680beaa6d0721749800a029683b49451 Mon Sep 17 00:00:00 2001 From: dumbmoron Date: Sat, 15 Jun 2024 15:59:37 +0000 Subject: [PATCH] api: randomize cipherlist for making requests to services this makes cobalt less prone to TLS client fingerprinting, as it avoids having the default node.js TLS fingerprint that is shared by all node.js applications. --- src/core/api.js | 4 ++++ src/modules/sub/randomize-ciphers.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/modules/sub/randomize-ciphers.js diff --git a/src/core/api.js b/src/core/api.js index c90f78f7..a366ad09 100644 --- a/src/core/api.js +++ b/src/core/api.js @@ -10,6 +10,7 @@ import loc from "../localization/manager.js"; import { createResponse, normalizeRequest, getIP } from "../modules/processing/request.js"; import { verifyStream, getInternalStream } from "../modules/stream/manage.js"; +import { randomizeCiphers } from '../modules/sub/randomize-ciphers.js'; import { extract } from "../modules/processing/url.js"; import match from "../modules/processing/match.js"; import stream from "../modules/stream/stream.js"; @@ -215,6 +216,9 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) { res.redirect('/api/serverInfo') }) + randomizeCiphers(); + setInterval(randomizeCiphers, 1000 * 60 * 30); // shuffle ciphers every 30 minutes + app.listen(env.apiPort, env.listenAddress, () => { console.log(`\n` + `${Cyan("cobalt")} API ${Bright(`v.${version}-${gitCommit} (${gitBranch})`)}\n` + diff --git a/src/modules/sub/randomize-ciphers.js b/src/modules/sub/randomize-ciphers.js new file mode 100644 index 00000000..e11e1ee2 --- /dev/null +++ b/src/modules/sub/randomize-ciphers.js @@ -0,0 +1,28 @@ +import tls from 'node:tls'; +import { randomBytes } from 'node:crypto'; + +const ORIGINAL_CIPHERS = tls.DEFAULT_CIPHERS; + +// How many ciphers from the top of the list to shuffle. +// The remaining ciphers are left in the original order. +const TOP_N_SHUFFLE = 8; + +// Modified variation of https://stackoverflow.com/a/12646864 +const shuffleArray = (array) => { + for (let i = array.length - 1; i > 0; i--) { + const j = randomBytes(4).readUint32LE() % array.length; + [array[i], array[j]] = [array[j], array[i]]; + } + + return array; +} + +export const randomizeCiphers = () => { + do { + const cipherList = ORIGINAL_CIPHERS.split(':'); + const shuffled = shuffleArray(cipherList.slice(0, TOP_N_SHUFFLE)); + const retained = cipherList.slice(TOP_N_SHUFFLE); + + tls.DEFAULT_CIPHERS = [ ...shuffled, ...retained ].join(':'); + } while (tls.DEFAULT_CIPHERS === ORIGINAL_CIPHERS); +}