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.
This commit is contained in:
dumbmoron 2024-06-15 15:59:37 +00:00
parent 1d5fa62271
commit fea4f71768
No known key found for this signature in database
2 changed files with 32 additions and 0 deletions

View File

@ -10,6 +10,7 @@ import loc from "../localization/manager.js";
import { createResponse, normalizeRequest, getIP } from "../modules/processing/request.js"; import { createResponse, normalizeRequest, getIP } from "../modules/processing/request.js";
import { verifyStream, getInternalStream } from "../modules/stream/manage.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 { extract } from "../modules/processing/url.js";
import match from "../modules/processing/match.js"; import match from "../modules/processing/match.js";
import stream from "../modules/stream/stream.js"; import stream from "../modules/stream/stream.js";
@ -215,6 +216,9 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) {
res.redirect('/api/serverInfo') res.redirect('/api/serverInfo')
}) })
randomizeCiphers();
setInterval(randomizeCiphers, 1000 * 60 * 30); // shuffle ciphers every 30 minutes
app.listen(env.apiPort, env.listenAddress, () => { app.listen(env.apiPort, env.listenAddress, () => {
console.log(`\n` + console.log(`\n` +
`${Cyan("cobalt")} API ${Bright(`v.${version}-${gitCommit} (${gitBranch})`)}\n` + `${Cyan("cobalt")} API ${Bright(`v.${version}-${gitCommit} (${gitBranch})`)}\n` +

View File

@ -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);
}