SocksClient.createConnection devuelve un flujo conectado al destino solicitado. Para HTTPS, ese flujo aún necesita un handshake TLS antes de transportar la petición HTTP.

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

La lista de proxies SOCKS5 proporciona candidatos para el host y el puerto del proxy. onTransportError y onResponseBytes pertenecen a la aplicación existente; el segundo debe analizar el flujo de respuesta HTTP. Los fragmentos de datos TLS no son mensajes HTTP completos de forma independiente.

El servername es el nombre DNS del destino. El tls.connect de bajo nivel de Node no activa SNI de forma predeterminada, y el nombre de host del proxy no es la identidad del certificado del sitio.

Mantén activada la verificación del certificado. Proporcionar el socket conectado evita abrir una conexión directa separada al sitio y conserva su identidad TLS.

El tiempo de espera de SOCKS acota esa negociación. El intercambio posterior de TLS y de la aplicación sigue necesitando el tiempo de espera, la cancelación y la política de limpieza previstos por quien llama.

Artículos relacionados