Einen SOCKS-Socket in Node.js mit TLS umhüllen
Umhülle den Zielstream des socks-Pakets mit tls.connect und bewahre den Hostnamen der Website für SNI und Zertifikatsprüfung.
SocksClient.createConnection liefert einen Stream, der mit dem angeforderten Ziel verbunden ist. Für HTTPS braucht dieser Stream noch einen TLS-Handshake, bevor er die HTTP-Anfrage überträgt.
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`
);
});
Die SOCKS5-Proxy-Liste liefert Kandidaten für Proxy-Host und -Port. onTransportError und onResponseBytes gehören zur bestehenden Anwendung; letzteres muss den HTTP-Antwortstream auswerten. TLS-Datenblöcke sind keine eigenständig vollständigen HTTP-Nachrichten.
Der servername ist der DNS-Name des Ziels. Nodes tls.connect auf niedriger Ebene aktiviert SNI nicht standardmäßig, und der Proxy-Hostname ist nicht die Zertifikatsidentität der Website.
Lass die Zertifikatsprüfung aktiv. Der übergebene verbundene Socket vermeidet eine separate direkte Verbindung zur Website und bewahrt zugleich deren TLS-Identität.
Der SOCKS-Timeout begrenzt diese Aushandlung. Der spätere TLS- und Anwendungsaustausch braucht weiterhin den vorgesehenen Timeout, Abbruch und die Aufräumrichtlinie des Aufrufers.