Comparativa8 min de lectura

socks5 vs socks5h: qué envían realmente seis clientes al proxy

socks5:// no significa DNS local en todos los clientes. Registramos qué envían curl, Requests, HTTPX, aiohttp, Playwright y Node a un proxy SOCKS5 con cada esquema.

En esta página

En curl, socks5:// resuelve el nombre de host del destino en tu máquina y socks5h:// le entrega el nombre al proxy. Otros clientes no siguen esa regla: en esta prueba, tres de seis enviaron el nombre de host con un socks5:// normal, y dos de ellos rechazaron socks5h:// antes de conectarse.

Cliente (versión probada)socks5:// envía al proxysocks5h://
curl 8.22.0una dirección IPv4 (resuelta en local)el nombre de host
Requests 2.34.2 + PySocks 1.7.1una dirección IPv4 (resuelta en local)el nombre de host
HTTPX 0.28.1 + socksio 1.0.0el nombre de hostel nombre de host
aiohttp 3.14.3 + aiohttp-socks 0.12.0el nombre de hostValueError, sin conexión
Playwright 1.63.0 (Chromium 153.0.8010.12)el nombre de hostnet::ERR_NO_SUPPORTED_PROXIES, sin conexión
Node.js 24.20.0 + socks-proxy-agent 10.1.0una dirección IPv4 (resuelta en local)el nombre de host

Cada celda es lo que recibió un servidor SOCKS5 con registro en 127.0.0.1 cuando se le pidió al cliente http://dnsprobe.example/, un nombre que solo existe en el archivo hosts local como 127.0.0.2. «Una dirección IPv4» significa que el proxy vio 127.0.0.2 y nunca conoció el nombre. «El nombre de host» significa que recibió dnsprobe.example y tendría que resolverlo él. Todos los clientes dieron el mismo resultado con un destino https://.

Por qué importa el tipo de dirección

Una petición SOCKS5 lleva una sola dirección de destino, y su byte ATYP indica de qué tipo es: X'01' para IPv4, X'03' para un nombre de dominio, X'04' para IPv6. RFC 1928, sección 4 Un cliente que envía un nombre de dominio deja el DNS en manos del proxy. Un cliente que envía una dirección IP ya hizo la consulta por su cuenta. Eso tiene tres consecuencias:

  1. Tu propio resolvedor ve la consulta. La consulta DNS del destino va al resolvedor configurado en tu máquina, fuera de la conexión con el proxy. La documentación de Requests lo dice directamente: socks5 «causes the DNS resolution to happen on the client, rather than on the proxy server». Requests: SOCKS
  2. La respuesta puede ser para otro lugar. El RFC 7871 señala que muchos servidores de nombres autoritativos «return different responses based on the perceived topological location of the user», y la deducen de la dirección desde la que llega la consulta, que normalmente es tu resolvedor. RFC 7871, sección 1 Por eso un nombre de CDN resuelto en local puede apuntar a un servidor elegido para tu red, y el proxy se conecta exactamente a esa dirección. La IP de salida está en la región que pediste, pero el servidor al que llegó se eligió para la tuya, así que el contenido puede ser el de otra región. Esto se deduce de cómo se construye la petición; la prueba en loopback no midió ninguna CDN.
  3. Los nombres que solo el proxy puede resolver fallan. Con un nombre que no se resuelve en local, curl 8.22.0 se detuvo en curl: (6) Could not resolve host: dnsprobe-missing.example, Requests lanzó un ConnectionError que contenía [Errno -2] Name or service not known, y socks-proxy-agent falló con getaddrinfo ENOTFOUND dnsprobe-missing.example. Ninguno envió una petición al proxy. Con socks5h://, los tres enviaron el nombre al proxy.

La guía de HTTP frente a SOCKS5 explica dónde encaja la ubicación del DNS al elegir un protocolo de proxy. El resto de este artículo trata de acertar con el esquema en cada cliente.

Qué poner en tu configuración

ClienteEnvía el nombre de host al proxyEvita
curlsocks5h:// o --socks5-hostnamesocks5:// y --socks5 resuelven en local
Requests + PySockssocks5h://socks5:// resuelve en local
HTTPX + socksiosocks5:// o socks5h://socks:// lanza ValueError
aiohttp + aiohttp-sockssocks5://socks5h:// lanza ValueError
Playwright Chromiumsocks5://socks5h:// falla al navegar
Node socks-proxy-agentsocks5h:// o socks://socks5:// resuelve en local

No hay una única URL correcta para los seis. Si un mismo ajuste PROXY_URL alimenta varias herramientas, socks5h:// rompe aiohttp-socks y Playwright, y socks5:// hace que curl, Requests y socks-proxy-agent resuelvan en local. Define el esquema por cliente.

Los dos clientes que rechazan socks5h:// fallan en momentos distintos. aiohttp-socks lanza la excepción desde ProxyConnector.from_url(), antes de abrir ningún socket:

code
ValueError: Invalid scheme component: socks5h

Playwright acepta el proxy en chromium.launch() y falla en la primera navegación, sin contactar con el proxy:

code
page.goto: net::ERR_NO_SUPPORTED_PROXIES at http://dnsprobe.example/

La documentación de Playwright da socks5://myproxy.com:3128 como la forma SOCKS de la opción server. Playwright: opción proxy La guía de proxy en Playwright recoge el resto de ajustes de lanzamiento y de contexto.

El esquema socks:// a secas es igual de inconsistente. Chromium y socks-proxy-agent lo trataron como SOCKS5 y enviaron el nombre de host. curl abrió con un saludo SOCKS4 (primer byte 0x04), que un servidor solo SOCKS5 no puede responder. Requests lanzó ValueError: Unable to determine SOCKS version from socks://127.0.0.1:11080, HTTPX lanzó ValueError: Unknown scheme for proxy URL URL('socks://127.0.0.1:11080') y aiohttp-socks lanzó ValueError: Invalid scheme component: socks.

Dos detalles de instalación en Python: Requests necesita el extra requests[socks] y HTTPX necesita httpx[socks]. Sin ellos Requests lanza Missing dependencies for SOCKS support y HTTPX lanza un ImportError que nombra socksio; la solución para ambos cubre también el caso en que la URL del proxy viene de ALL_PROXY. La guía de proxy con Python Requests y la guía de proxy asíncrono con HTTPX muestran el código completo del cliente.

En esta prueba la URL del proxy se pasó a cada cliente de forma explícita. Si la tuya viene de ALL_PROXY o HTTPS_PROXY, confirma primero qué variable lee el cliente; la guía de variables de entorno de proxy lo detalla por cliente, y NO_PROXY matching, tested muestra que las reglas de exclusión también difieren entre clientes.

Cómo comprobar tu propia configuración

No necesitas una cuenta de proxy para ver qué envía tu cliente. Descarga socks5_log.py, un script de Python de 42 líneas sin dependencias. Completa el saludo SOCKS5, imprime el tipo de dirección y la dirección de cada petición y después responde «general SOCKS server failure», así que no se reenvía nada.

Dale a tu máquina un nombre de prueba que solo conozca el archivo hosts. No uses localhost: Chromium envía las peticiones a nombres de localhost directamente en lugar de pasarlas por el proxy. Chromium: implicit bypass rules Añade esta línea a /etc/hosts:

code
127.0.0.2 dnsprobe.example

Arranca el servidor en una terminal y envía una petición por esquema desde otra:

sh
python3 socks5_log.py 1080
curl -x socks5://127.0.0.1:1080 http://dnsprobe.example/
curl -x socks5h://127.0.0.1:1080 http://dnsprobe.example/

Con curl 8.18.0 el servidor imprimió:

code
LISTENING 127.0.0.1:1080
CMD=1 IPv4 127.0.0.2 port=80
CMD=1 DOMAIN dnsprobe.example port=80

La primera petición llegó como dirección IP, así que curl resolvió el nombre en local. La segunda llegó como nombre. Los dos comandos de curl terminan con curl: (97) cannot complete SOCKS5 connection to dnsprobe.example. (1), que es la negativa del servidor y es lo esperado. Sustituye curl por tu propio cliente y tu ajuste de proxy, y lee los mismos dos campos. Si no aparece ninguna línea, el cliente rechazó el esquema o se saltó el proxy.

Opciones de DNS remoto además del esquema

Algunos clientes ofrecen la misma elección como opción, normalmente llamada rdns:

  • curl: en la prueba, --socks5-hostname host:port se comportó como socks5h:// y --socks5 host:port como socks5://. curl man page
  • Requests: no hay una opción aparte. El gestor SOCKS de urllib3 fija el indicador rdns de PySocks según el esquema: False para socks5, True para socks5h. Código fuente de urllib3 El propio PySocks, usado directamente, acepta rdns en set_proxy() y documenta True como valor por defecto. PySocks README
  • aiohttp-socks: ProxyConnector acepta rdns, y su README indica «default is True for socks5». aiohttp-socks README En la prueba, ProxyConnector.from_url("socks5://127.0.0.1:11080", rdns=False) envió 127.0.0.2 y rdns=True envió el nombre de host.
  • HTTPX: la versión 0.28.1 dirige socks5 y socks5h al mismo transporte SOCKS, así que el esquema no cambia nada. Código fuente de HTTPX
  • socks-proxy-agent: solo el esquema fija su indicador lookup: socks5 y socks4 resuelven en local; socks5h, socks4a y socks no. Código fuente de socks-proxy-agent
  • Chromium: no hay opción. Su documentación dice que para SOCKSv5 «name resolution is always done proxy side». Documentación de red de Chromium

Método y límites

Registrado el 4 de octubre de 2026 en Ubuntu 26.04 (x86_64) con Python 3.14.4 y Node.js 24.20.0. Las versiones son las de la primera tabla, más urllib3 2.8.0, httpcore 1.0.9, python-socks 3.1.1 y el paquete socks 2.8.10. curl 8.18.0 se ejecutó junto a 8.22.0 y envió las mismas direcciones. Un nombre que solo se resuelve a IPv6 llegó como dirección IPv6 desde curl, Requests y socks-proxy-agent, y como nombre de host desde los otros tres.

El laboratorio es un único servidor en loopback que rechaza todas las peticiones. No dice nada sobre ningún servicio de proxy, sobre SOCKS5 con autenticación o UDP, ni sobre macOS, Windows, Firefox o WebKit. Los valores por defecto de las bibliotecas cambian, así que comprueba las versiones que uses. El archivo del laboratorio contiene el servidor, los seis scripts de cliente, el ejecutor y un README; la salida en bruto de los 62 casos está en results.json.

Relacionado

ipvolt está construyendo infraestructura de proxies para desarrolladores y agentes. Únete a la lista de espera para recibir un correo cuando se abra el acceso.

Fuentes

  1. curl man page: --proxy (socks5:// and socks5h://)
  2. RFC 1928: SOCKS Protocol Version 5, section 4 (address types)
  3. Requests: SOCKS proxies
  4. urllib3 2.8.0 source: contrib/socks.py (scheme to rdns)
  5. PySocks README: set_proxy and rdns
  6. HTTPX: SOCKS proxies
  7. HTTPX 0.28.1 source: proxy schemes in _transports/default.py
  8. aiohttp-socks 0.12.0 README: ProxyConnector and rdns
  9. python-socks 3.1.1 source: parse_proxy_url schemes
  10. socks-proxy-agent source: parseSocksURL
  11. Chromium network docs: SOCKSv5 proxy scheme and implicit bypass rules
  12. Playwright: browserType.launch proxy option
  13. RFC 7871: Client Subnet in DNS Queries, section 1

Etiquetas:ProxiesTroubleshooting