Een SOCKS-socket met TLS omwikkelen in Node.js
Wikkel de bestemmingsstream die het socks-pakket teruggeeft om met tls.connect en behoud de hostnaam van de website voor SNI en certificaatverificatie.
SocksClient.createConnection retourneert een stream die met de gevraagde bestemming is verbonden. Voor HTTPS heeft die stream nog een TLS-handshake nodig voordat hij het HTTP-verzoek draagt.
import { SocksClient } from 'socks';
import tls from 'node:tls';
const targetHost = 'service.example';
const info = await SocksClient.createConnection({
proxy: { host: 'proxy.example', port: 1080, type: 5 },
command: 'connect',
destination: { host: targetHost, port: 443 },
timeout: 10000,
});
const secure = tls.connect({
socket: info.socket,
servername: targetHost,
});
secure.on('error', onTransportError);
secure.on('data', onResponseBytes);
secure.once('secureConnect', () => {
secure.write(
`GET /data HTTP/1.1\r\nHost: ${targetHost}\r\nConnection: close\r\n\r\n`
);
});
De SOCKS5-proxylijst levert kandidaten voor de proxyhost en -poort. onTransportError en onResponseBytes horen bij de bestaande applicatie; de laatste moet de HTTP-responsstream parseren. TLS-datablokken zijn geen op zichzelf volledige HTTP-berichten.
De servername is de DNS-naam van de bestemming. Nodes tls.connect op laag niveau schakelt SNI niet standaard in, en de proxyhostnaam is niet de certificaatidentiteit van de website.
Laat certificaatverificatie aanstaan. Door de verbonden socket mee te geven voorkom je een aparte directe verbinding met de website en blijft de TLS-identiteit behouden.
De SOCKS-timeout begrenst die onderhandeling. De latere TLS- en applicatie-uitwisseling heeft nog steeds de bedoelde timeout, annulering en opruimingspolicy van de aanroeper nodig.