@incizzle/mytls
Version:
Mimic TLS/JA3 fingerprint inside Node with help from Go
142 lines (141 loc) • 5.6 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const child_process_1 = require("child_process");
const path_1 = __importDefault(require("path"));
const events_1 = require("events");
const ws_1 = require("ws");
let child;
const cleanExit = (message) => {
if (message)
console.log(message);
child.kill();
process.exit();
};
process.on('SIGINT', () => cleanExit());
process.on('SIGTERM', () => cleanExit());
class Golang extends events_1.EventEmitter {
constructor(port, debug) {
super();
this.server = new ws_1.Server({ port });
let executableFilename;
if (process.platform == 'win32') {
executableFilename = 'index.exe';
}
else if (process.platform == 'linux') {
executableFilename = 'index';
}
else if (process.platform == 'darwin') {
executableFilename = 'index-mac';
}
else {
cleanExit(new Error('Operating system not supported'));
}
child = child_process_1.spawn(path_1.default.join(__dirname, executableFilename), {
env: { WS_PORT: port.toString() },
shell: true,
windowsHide: true,
});
child.stderr.on('data', (stderr) => {
if (stderr.toString().includes('Request_Id_On_The_Left')) {
const splitRequestIdAndError = stderr.toString().split('Request_Id_On_The_Left');
const [requestId, error] = splitRequestIdAndError;
this.emit(requestId, { error: new Error(error) });
}
else {
debug
? cleanExit(new Error(stderr))
: cleanExit(new Error('Invalid JA3 hash. Exiting... (Golang wrapper exception)'));
}
});
this.server.on('connection', (ws) => {
this.emit('ready');
ws.on('message', (data) => {
const message = JSON.parse(data);
this.emit(message.RequestID, message.Response);
});
});
}
request(requestId, options) {
[...this.server.clients][0].send(JSON.stringify({ requestId, options }));
}
}
const initMyTls = async (initOptions = {}) => {
return new Promise((resolveReady) => {
let { port, debug } = initOptions;
if (!port)
port = 9119;
if (!debug)
debug = false;
const instance = new Golang(port, debug);
instance.on('ready', () => {
const mytls = (() => {
const MyTls = async (url, options, method = 'get') => {
return new Promise((resolveRequest, rejectRequest) => {
const requestId = `${url}${Math.floor(Date.now() * Math.random())}`;
if (!options.ja3)
options.ja3 =
'771,255-49195-49199-49196-49200-49171-49172-156-157-47-53,0-10-11-13,23-24,0';
if (!options.body)
options.body = '';
if (!options.proxy)
options.proxy = '';
instance.request(requestId, {
url,
...options,
method,
});
instance.once(requestId, (response) => {
if (response.error)
return rejectRequest(response.error);
const { Status: status, Body: body, Headers: headers } = response;
if (headers['Set-Cookie'])
headers['Set-Cookie'] = headers['Set-Cookie'].split('/,/');
resolveRequest({
status,
body,
headers,
});
});
});
};
MyTls.head = (url, options) => {
return MyTls(url, options, 'head');
};
MyTls.get = (url, options) => {
return MyTls(url, options, 'get');
};
MyTls.post = (url, options) => {
return MyTls(url, options, 'post');
};
MyTls.put = (url, options) => {
return MyTls(url, options, 'put');
};
MyTls.delete = (url, options) => {
return MyTls(url, options, 'delete');
};
MyTls.trace = (url, options) => {
return MyTls(url, options, 'trace');
};
MyTls.options = (url, options) => {
return MyTls(url, options, 'options');
};
MyTls.connect = (url, options) => {
return MyTls(url, options, 'options');
};
MyTls.patch = (url, options) => {
return MyTls(url, options, 'patch');
};
return MyTls;
})();
resolveReady(mytls);
});
});
};
exports.default = initMyTls;
// CommonJS support for default export
module.exports = initMyTls;
module.exports.default = initMyTls;
module.exports.__esModule = true;