Integración7 min de lectura

Usar un proxy con curl: -x, variables de entorno, SOCKS5 y auth

Cómo usar un proxy con curl: la opción -x, las variables http_proxy y https_proxy, SOCKS5 con socks5h, autenticación del proxy y cómo leer los errores CONNECT y 407.

En esta página

El punto de partida

Todas las formas en que curl elige un proxy, desde una sola opción -x hasta las variables de entorno, con los detalles de autenticación, SOCKS5 y túnel que deciden si la petición tiene éxito.

Configurar un proxy para una sola petición con -x

La opción -x, cuya forma larga es --proxy, enruta una sola petición de curl a través de un proxy. Indícale el esquema, el host y el puerto del proxy. Cuando se omite el esquema, curl asume http://, y cuando se omite el puerto asume 1080, así que escribe ambos de forma explícita.

El esquema describe la conexión con el proxy, no con el destino. Un destino https:// a través de un proxy HTTP ordinario sigue usando -x http://host:port; curl abre un túnel CONNECT a través de él. Escribe -x https://host:port solo cuando el proveedor termina el TLS en el propio proxy. curl también acepta aquí socks4://, socks4a://, socks5:// y socks5h://.

El comando de abajo conserva dos hábitos del resto de esta guía: --disable ignora un curlrc que podría añadir su propio proxy, y --noproxy '' cancela cualquier exclusión no_proxy heredada, de modo que la petición pase de verdad por el gateway que indicaste. proxy.example.invalid no se puede resolver a propósito; sustitúyelo por el gateway de tu proveedor.

curl -x · una petición a través de un proxy

sh
curl --disable --noproxy '' \
  -x http://proxy.example.invalid:8080 \
  https://example.com/

Autenticación del proxy: -U, --proxy-user y 407

Las credenciales del proxy son independientes de las credenciales del destino. -U o --proxy-user las envía al proxy; -u o --user las envía al destino. Mezclar las dos produce un 407 del proxy o un 401 del destino aunque la contraseña sea correcta.

También puedes incrustar las credenciales en la URL del proxy como http://user:password@host:port. Codifica primero con porcentaje los caracteres reservados: una @ en la contraseña debe convertirse en %40 o curl la interpretará como el inicio del host. Basic es el esquema de autenticación de proxy por defecto; --proxy-digest, --proxy-ntlm y --proxy-anyauth seleccionan otros cuando el proveedor los documenta.

Cualquiera de las dos formas pone la contraseña en la lista de argumentos del proceso y en el historial del shell. Léela desde una variable en su lugar, o usa la forma --variable y --expand-proxy-user de curl 8.3 que se muestra en el script de diagnóstico más abajo, que importa el secreto sin exponerlo como argumento.

  • connect=407 o el mensaje Received HTTP code 407 from proxy after CONNECT significa que el proxy rechazó las credenciales o no recibió ninguna. Revisa el valor de -U, la codificación y el formato de nombre de usuario del proveedor.
  • Un 401 del destino cuando el túnel tuvo éxito es un problema del destino; el paso del proxy ya está funcionando.
  • Muchos proveedores codifican opciones de país, sesión o protocolo en el nombre de usuario. Sigue exactamente el formato documentado por el proveedor; curl pasa la cadena sin cambios.

curl --proxy-user · credenciales desde el entorno

sh
: "${PROXY_USERNAME:?}" "${PROXY_PASSWORD:?}"
curl --disable --noproxy '' \
  -x http://proxy.example.invalid:8080 \
  --proxy-user "$PROXY_USERNAME:$PROXY_PASSWORD" \
  https://example.com/

Variables de entorno: http_proxy, https_proxy, no_proxy y .curlrc

Sin -x, curl busca un proxy en el entorno. Lee http_proxy solo en minúsculas, porque el nombre en mayúsculas puede ser establecido por cabeceras de petición CGI; acepta https_proxy o HTTPS_PROXY, all_proxy o ALL_PROXY, y no_proxy o NO_PROXY. La variable se elige según el esquema del destino: un destino https:// usa https_proxy, así que exportar solo http_proxy deja el tráfico HTTPS en directo, sin proxy.

no_proxy es una lista separada por comas de nombres de host o sufijos de dominio que evitan el proxy, y un solo * desactiva el proxy por completo. -x en la línea de comandos siempre gana sobre el entorno, y --noproxy en la línea de comandos siempre gana sobre no_proxy.

Un archivo ~/.curlrc puede establecer proxy = "http://host:port" para cada invocación, lo cual es cómodo en una estación de trabajo y sorprendente dentro de un contenedor o un trabajo de CI. Ejecuta curl con --disable, o su forma corta -q como primer argumento, cuando un script deba ignorarlo.

http_proxy y https_proxy · sesión de shell

sh
export http_proxy='http://proxy.example.invalid:8080'
export https_proxy='http://proxy.example.invalid:8080'
export no_proxy='localhost,127.0.0.1,.internal.example'
curl https://example.com/         # uses https_proxy
curl --noproxy '*' https://example.com/   # bypasses the proxy once

SOCKS5 con curl: socks5 frente a socks5h

curl habla SOCKS a través de la misma opción -x. socks5:// resuelve el nombre de host del destino en tu máquina y envía al proxy una dirección IP. socks5h:// envía el nombre de host y deja que el proxy lo resuelva, que es lo que quieres cuando el destino debe resolverse desde la red del proxy o cuando el DNS local no debe ver el destino en absoluto. Las opciones largas --socks5 y --socks5-hostname son equivalentes.

La autenticación con nombre de usuario y contraseña para SOCKS5 usa la misma opción --proxy-user. SOCKS no tiene un estado CONNECT, así que un handshake rechazado aparece como el código de salida 97 de curl con un motivo breve, en lugar de como un 407.

curl socks5h · DNS del lado del proxy

sh
curl --disable --noproxy '' \
  -x socks5h://proxy.example.invalid:1080 \
  --proxy-user "$PROXY_USERNAME:$PROXY_PASSWORD" \
  https://example.com/

Destinos HTTPS: el túnel CONNECT y -v

Para un destino https:// a través de un proxy HTTP, curl envía primero CONNECT example.com:443 al proxy. Solo después de que el proxy responda 200, curl inicia el TLS con el destino dentro del túnel, de modo que el proxy nunca ve la petición descifrada. Ejecuta con -v para observar ambos pasos; la respuesta al CONNECT llega antes que cualquier cabecera del destino. -p o --proxytunnel fuerza el mismo túnel para un destino http:// plano.

Para un destino http:// plano no hay túnel. curl envía la URL completa al proxy, el proxy la obtiene, y las cabeceras de respuesta que ves pueden proceder de cualquiera de las dos partes. Cuando haya que atribuir un código de estado a una capa, prefiere el caso con túnel y lee el estado del CONNECT por separado con la variable de salida %{http_connect} de --write-out.

Con un proxy https://, curl verifica el certificado del proxy además del certificado del destino. --proxy-cacert proporciona un paquete de confianza privado para el proxy; mantén ambas verificaciones activadas en lugar de recurrir a --proxy-insecure o -k.

Envía una petición acotada como línea base

Guarda esto como proxy-check.sh y ejecútalo con sh proxy-check.sh. Requiere curl 8.3 o posterior y autenticación de proxy HTTP Basic. Haz que tu gestor de secretos rellene PROXY_USERNAME y PROXY_PASSWORD, y establece PROXY_URL con el gateway de tu proveedor, con su esquema y puerto; https://proxy.example.invalid:8443 es un valor ilustrativo que a propósito no puede conectar.

curl importa las credenciales por sí mismo, de modo que la contraseña expandida nunca es un argumento del shell. El comando imprime el estado del destino, el estado del CONNECT y el tiempo transcurrido, y descarta el cuerpo de la respuesta. Conserva esta línea base antes de añadir un navegador, concurrencia o código de aplicación.

proxy-check.sh · curl 8.3+

sh
: "${PROXY_URL:?Set your provider proxy URL}"
curl --disable --silent --show-error --fail \
  --noproxy '' \
  --proxy "$PROXY_URL" \
  --variable %PROXY_USERNAME \
  --variable %PROXY_PASSWORD \
  --expand-proxy-user '{{PROXY_USERNAME}}:{{PROXY_PASSWORD}}' \
  --connect-timeout 10 --max-time 30 \
  --output /dev/null \
  --write-out 'http=%{http_code} connect=%{http_connect} seconds=%{time_total}\n' \
  'https://example.com/'

Lee los códigos de salida de curl y encuentra la capa que falla

Una respuesta correcta demuestra que esta petición se completó; no establece un país de salida ni un operador concretos. Para eso, usa el endpoint de diagnóstico documentado por tu proveedor o un endpoint que controles y que informe de la dirección de origen observada.

Mantén el mismo destino y las mismas credenciales cuando compares tu aplicación con curl. Cambiar tres ajustes a la vez hace difícil explicar un reintento exitoso. Comparte con soporte el código de salida, los tiempos y el estado sin datos sensibles, en lugar de una traza detallada que contenga datos de autenticación.

  • Salida 5, could not resolve proxy: el nombre de host del gateway es incorrecto o el DNS local no puede verlo.
  • Salida 7, failed to connect: el host del proxy se resolvió pero el puerto está cerrado, filtrado o inalcanzable desde esta red.
  • Salida 28, operation timed out: aumenta --connect-timeout o --max-time una vez para confirmar, y trata una repetición como un problema de enrutamiento o de capacidad.
  • Salida 56 con Received HTTP code 407 from proxy after CONNECT: la autenticación del proxy falló; corrige -U antes de tocar las cabeceras del destino.
  • Salida 97, proxy handshake error: el handshake SOCKS fue rechazado; revisa el esquema socks5 frente a socks5h y las credenciales.
  • Salida 35 o 60, fallo de TLS: revisa el nombre de host, la cadena de confianza y el reloj. Mantén activada la verificación de certificados.

Antes de pasar a producción

  • Usa un gateway real de tu proveedor, con el esquema y el puerto que documenta.
  • Inyecta las credenciales de forma privada; no pegues secretos en el historial del shell.
  • Registra una línea base acotada antes de probar tráfico en paralelo.
  • Anota si el fallo vino del paso CONNECT o del destino antes de cambiar ajustes.

Fuentes y lecturas adicionales

Referencias técnicas usadas para esta guía. Consulta la documentación de tu versión instalada y la configuración compatible de tu proveedor.