Volver al blog

Configuración de proxy para curl y wget: ejemplos prácticos para administradores de sistemas y DevOps

Guía completa para configurar proxies para curl y wget con ejemplos prácticos de código, soporte para SOCKS5, autenticación y automatización en pipelines de CI/CD.

📅3 de abril de 2026
```html

Si administras servidores, escribes scripts de automatización o despliegas aplicaciones en infraestructura corporativa, tarde o temprano te encontrarás con la necesidad de enviar tráfico de curl o wget a través de un proxy. Esto puede ser un proxy corporativo, eludir bloqueos geográficos al descargar paquetes, o rotar IPs al hacer solicitudes masivas a APIs externas. En este artículo, solo hay práctica: comandos, configuraciones, ejemplos de código sin rodeos.

1. Cómo funcionan curl y wget con proxies: mecanismos básicos

Antes de meterse en las configuraciones, es importante entender qué sucede bajo el capó. Ambas herramientas soportan dos protocolos de proxy principales: HTTP/HTTPS y SOCKS5. La mecánica es diferente, y esto afecta qué tipo de proxy elegir para una tarea específica.

Proxy HTTP actúa como intermediario a nivel de protocolo de aplicación. Cuando curl envía una solicitud a través de un proxy HTTP, le dice literalmente al servidor proxy: "haz una solicitud GET a esta URL en lugar de mí". Para el tráfico HTTPS se utiliza el método CONNECT: curl le pide al proxy que establezca un túnel hasta el host de destino, después de lo cual el apretón de manos TLS ocurre directamente entre el cliente y el servidor de destino. Esto es importante: el proxy en este caso no ve el contenido del tráfico HTTPS.

SOCKS5 opera a un nivel más bajo: proxy TCP/UDP sin estar atado a un protocolo de aplicación. Esto hace que SOCKS5 sea más versátil: puede manejar no solo HTTP/HTTPS, sino también otros protocolos. Además, SOCKS5 soporta la resolución DNS del lado del servidor proxy, lo cual es crítico para prevenir fugas de DNS.

💡 Diferencia clave para la práctica:

Si solo necesitas descargar un archivo o hacer una solicitud API, un proxy HTTP es suficiente. Si necesitas total anonimato, eludir fugas de DNS o trabajar con protocolos no estándar, utiliza SOCKS5.

curl soporta ambos protocolos de manera nativa desde versiones muy tempranas. wget históricamente ha tenido un soporte más limitado para SOCKS5: en versiones antiguas (hasta 1.19) no hay soporte para SOCKS5 en absoluto, solo para proxies HTTP. Esto debe tenerse en cuenta al escribir scripts que deben funcionar en diferentes distribuciones.

Puedes verificar la versión de wget con el comando wget --version. Para curl, usa curl --version, allí también podrás ver con qué protocolos se compiló la biblioteca libcurl.

2. Variables de entorno: la forma más rápida de configurar

La forma más elegante de configurar un proxy para curl y wget es a través de variables de entorno. Esto funciona a nivel del sistema: no necesitas cambiar cada script, solo establece las variables una vez en la sesión o agrégalas al perfil del usuario.

Ambas herramientas leen las mismas variables estándar:

# Para tráfico HTTP
export http_proxy="http://proxy.example.com:3128"

# Para tráfico HTTPS
export https_proxy="http://proxy.example.com:3128"

# Duplicamos en mayúsculas (algunos programas solo leen esto)
export HTTP_PROXY="http://proxy.example.com:3128"
export HTTPS_PROXY="http://proxy.example.com:3128"

# Para FTP (si es necesario)
export ftp_proxy="http://proxy.example.com:3128"

# Excepciones — direcciones que NO pasan por el proxy
export no_proxy="localhost,127.0.0.1,::1,192.168.0.0/16,.internal.company.com"

Un matiz importante: curl es sensible a las mayúsculas de las variables dependiendo de la versión. Para evitar sorpresas, siempre establece ambas versiones: en minúsculas y mayúsculas. Esta es una práctica estándar en DevOps.

Para que la configuración se aplique de manera constante para un usuario específico, agrega las líneas a ~/.bashrc o ~/.profile. Para scripts y servicios del sistema, en /etc/environment o en el archivo de unidad de systemd a través de la directiva Environment=.

# /etc/systemd/system/myservice.service
[Service]
Environment="http_proxy=http://proxy.example.com:3128"
Environment="https_proxy=http://proxy.example.com:3128"
Environment="no_proxy=localhost,127.0.0.1"
ExecStart=/usr/bin/myapp

Si el proxy requiere autenticación, el usuario y la contraseña se insertan directamente en la URL de la variable:

export http_proxy="http://username:[email protected]:3128"
export https_proxy="http://username:[email protected]:3128"

⚠️ Seguridad:

No almacenes contraseñas en texto claro en .bashrc o en variables de entorno en servidores de producción. Utiliza soluciones de vault (HashiCorp Vault, AWS Secrets Manager) o al menos limita los permisos del archivo con las variables.

3. Flags de curl para trabajar con proxies: análisis completo

curl proporciona un rico conjunto de flags para gestionar proxies directamente desde la línea de comandos. Esto es conveniente cuando necesitas hacer una solicitud única a través de un proxy sin cambiar la configuración del sistema.

El flag principal es -x o --proxy:

# Proxy HTTP básico
curl -x http://proxy.example.com:3128 https://api.example.com/data

# Forma corta
curl -x proxy.example.com:3128 https://api.example.com/data

# Con especificación explícita del protocolo
curl --proxy http://proxy.example.com:3128 https://api.example.com/data

# Verificar IP externa a través del proxy
curl -x http://proxy.example.com:3128 https://api.ipify.org

Para ignorar las variables de entorno y conectarse directamente (eludir el proxy configurado), se utiliza el flag --noproxy:

# Ignorar proxy para un host específico
curl --noproxy "internal.company.com" https://internal.company.com/api

# Ignorar proxy completamente (incluso si se establecen variables de entorno)
curl --noproxy "*" https://api.example.com/data

Flags útiles para depurar conexiones proxy:

# Modo verbose: se ven todos los encabezados, incluyendo CONNECT al proxy
curl -v -x http://proxy.example.com:3128 https://api.example.com/data

# Solo encabezados de respuesta
curl -I -x http://proxy.example.com:3128 https://api.example.com/data

# Mostrar tiempo de conexión a través del proxy
curl -w "Connect: %{time_connect}s\nTotal: %{time_total}s\n" \
  -x http://proxy.example.com:3128 \
  -o /dev/null -s https://api.example.com/data

Configurar el proxy a través del archivo de configuración ~/.curlrc es conveniente si no quieres escribir los flags cada vez:

# ~/.curlrc
proxy = http://proxy.example.com:3128
proxy-user = username:password
noproxy = localhost,127.0.0.1,.internal.company.com

Para scripts del sistema, puedes crear un archivo de configuración separado y especificarlo explícitamente a través de curl -K /path/to/config — esto permite tener diferentes perfiles de proxy para diferentes tareas.

4. Configuración de proxy en wget: flags y archivo de configuración

wget es menos flexible que curl, pero para tareas típicas — descargar archivos, espejar sitios recursivamente — sus capacidades son más que suficientes. El proxy en wget se puede configurar de tres maneras: a través de variables de entorno (ya discutidas), a través de flags de línea de comandos y a través del archivo de configuración ~/.wgetrc.

Flags de línea de comandos de wget para proxies:

# Proxy HTTP a través del flag
wget -e use_proxy=yes \
     -e http_proxy=http://proxy.example.com:3128 \
     https://example.com/file.tar.gz

# HTTPS a través del proxy
wget -e use_proxy=yes \
     -e https_proxy=http://proxy.example.com:3128 \
     https://example.com/file.tar.gz

# Con autenticación
wget -e use_proxy=yes \
     -e http_proxy=http://username:[email protected]:3128 \
     https://example.com/file.tar.gz

# Desactivar proxy para un comando específico (si se establecen variables de entorno)
wget --no-proxy https://internal.company.com/file.tar.gz

El archivo de configuración ~/.wgetrc es la forma preferida para configuraciones permanentes:

# ~/.wgetrc
use_proxy = on
http_proxy = http://proxy.example.com:3128
https_proxy = http://proxy.example.com:3128
ftp_proxy = http://proxy.example.com:3128
no_proxy = localhost,127.0.0.1,.internal.company.com

# Si el proxy requiere autenticación
proxy_user = username
proxy_password = secretpassword

Para aplicación a nivel del sistema (todos los usuarios), se utiliza /etc/wgetrc — el mismo formato, pero se aplica globalmente. Conveniente para servidores donde todas las operaciones de descarga deben ir a través de un proxy corporativo.

Un ejemplo práctico: descarga recursiva de un sitio a través de un proxy con limitación de profundidad y velocidad:

wget -e use_proxy=yes \
     -e http_proxy=http://proxy.example.com:3128 \
     --recursive \
     --level=2 \
     --limit-rate=500k \
     --wait=1 \
     --random-wait \
     --user-agent="Mozilla/5.0 (compatible; Googlebot/2.1)" \
     https://example.com/docs/

5. Proxy SOCKS5 en curl y wget: configuración y ejemplos

SOCKS5 es un protocolo más preferido para tareas donde la anonimidad o el trabajo con puertos no estándar son importantes. Para administradores de sistemas e ingenieros de DevOps, SOCKS5 se utiliza a menudo al trabajar a través de túneles SSH, así como al conectarse a proxies residenciales, que simulan el tráfico de usuarios reales.

En curl, SOCKS5 se soporta a través de un prefijo especial en la URL del proxy:

# SOCKS5 con resolución DNS del lado del cliente (¡puede haber fuga de DNS!)
curl --socks5 proxy.example.com:1080 https://api.example.com/data

# SOCKS5 con resolución DNS del lado del proxy (¡recomendado!)
curl --socks5-hostname proxy.example.com:1080 https://api.example.com/data

# A través del flag -x con especificación explícita del protocolo
curl -x socks5h://proxy.example.com:1080 https://api.example.com/data

# Con autenticación
curl -x socks5h://username:[email protected]:1080 https://api.example.com/data

# SOCKS5 a través de variable de entorno
export all_proxy="socks5h://proxy.example.com:1080"
curl https://api.example.com/data

📌 socks5 vs socks5h — ¿cuál es la diferencia?

socks5 — la consulta DNS se realiza localmente, solo se establece la conexión TCP a través del proxy por IP. Puede haber fuga de DNS.
socks5h (h = hostname) — la consulta DNS se realiza en el lado del servidor proxy. Total anonimato. Recomendado para la mayoría de las tareas.

Un escenario popular en DevOps es utilizar SSH como proxy SOCKS5 para tunelizar tráfico a través de un host bastión:

# Abrimos un túnel SSH con SOCKS5 en el puerto local 1080
ssh -D 1080 -f -C -q -N [email protected]

# Ahora usamos este túnel en curl
curl -x socks5h://localhost:1080 https://internal-api.private.network/data

# O a través de variable de entorno para todas las solicitudes en la sesión
export all_proxy="socks5h://localhost:1080"
wget https://internal-resource.private.network/file.tar.gz

wget soporta SOCKS5 desde la versión 1.19. En versiones más antiguas (CentOS 7, Ubuntu 16.04), tendrás que usar soluciones alternativas: proxychains, tsocks, o cambiar a curl para tareas que requieren SOCKS5.

6. Autenticación en el proxy: usuario y contraseña

La mayoría de los proxies comerciales y servidores proxy corporativos requieren autenticación. Hay varias formas de pasar las credenciales, cada una con sus pros y contras en términos de seguridad.

Método 1: Credenciales en la URL — simple, pero inseguro (la contraseña es visible en la lista de procesos):

curl -x http://user:p%[email protected]:3128 https://api.example.com/data
# Los caracteres especiales en la contraseña deben ser codificados en URL: @ → %40, : → %3A

Método 2: Flag --proxy-user en curl — la contraseña no necesita ser especificada en la línea de comandos, curl la solicitará interactivamente:

# Usuario y contraseña en el flag (aún visible en ps aux)
curl -x http://proxy.example.com:3128 \
     --proxy-user "username:password" \
     https://api.example.com/data

# Solo usuario — curl preguntará por la contraseña interactivamente
curl -x http://proxy.example.com:3128 \
     --proxy-user "username" \
     https://api.example.com/data

Método 3: A través del archivo .netrc — el más seguro para scripts:

# ~/.netrc
machine proxy.example.com
login username
password secretpassword

# Limitar los permisos del archivo
chmod 600 ~/.netrc

# Usar en curl
curl -x http://proxy.example.com:3128 --proxy-netrc https://api.example.com/data

Método 4: A través de variables de entorno desde un almacén secreto — recomendado para CI/CD y entornos de producción:

# En el script leemos las credenciales de las variables (que establece CI/CD)
#!/bin/bash
PROXY_URL="http://${PROXY_USER}:${PROXY_PASS}@proxy.example.com:3128"
curl -x "${PROXY_URL}" https://api.example.com/data

Tabla comparativa de métodos de autenticación:

Método Comodidad Seguridad Adecuado para
URL (user:pass@host) ⭐⭐⭐ Pruebas
Flag --proxy-user ⭐⭐⭐ ⭐⭐ Comandos únicos
Archivo .netrc ⭐⭐ ⭐⭐⭐ Scripts locales
Variables de entorno de vault ⭐⭐ ⭐⭐⭐⭐⭐ CI/CD, producción

7. Excepciones y no_proxy: cómo eludir el proxy para direcciones locales

En entornos corporativos y en la nube, a menudo se necesita una configuración fina: tráfico externo — a través del proxy, interno — directamente. La variable no_proxy (o NO_PROXY) permite establecer una lista de excepciones.

# Excepciones básicas
export no_proxy="localhost,127.0.0.1,::1"

# Excepción por dominio (con punto — todos los subdominios)
export no_proxy="localhost,127.0.0.1,.internal.company.com,.corp.local"

# Excepción por rango de IP (¡la notación CIDR no funciona en todas partes!)
export no_proxy="localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"

# Para AWS: excluimos el endpoint de metadatos y direcciones internas
export no_proxy="localhost,127.0.0.1,169.254.169.254,.amazonaws.com.internal"

⚠️ Característica importante de no_proxy:

La notación CIDR (10.0.0.0/8) no es soportada por todas las herramientas. curl la soporta desde la versión 7.86.0. wget — no la soporta en absoluto. Para compatibilidad, es mejor enumerar IPs específicas o máscaras como 10. (todo lo que comienza con 10.).

Un ejemplo práctico para un entorno Kubernetes, donde se necesita excluir el servidor API y servicios internos:

export no_proxy="localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/16,.cluster.local,.svc,.default"
export NO_PROXY="${no_proxy}"

8. Proxy en CI/CD: GitHub Actions, GitLab CI, Docker

Configurar proxies en pipelines de CI/CD es una de las tareas más comunes para ingenieros de DevOps que trabajan en redes corporativas o con acceso limitado a Internet. Analicemos configuraciones específicas para plataformas populares.

GitHub Actions

# .github/workflows/deploy.yml
name: Deploy

on: [push]

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      http_proxy: ${{ secrets.PROXY_URL }}
      https_proxy: ${{ secrets.PROXY_URL }}
      no_proxy: "localhost,127.0.0.1,.github.com"
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Download dependencies
        run: |
          curl -x "${http_proxy}" https://external-api.example.com/config.json -o config.json
          wget -e use_proxy=yes -e http_proxy="${http_proxy}" https://releases.example.com/app-v1.0.tar.gz

GitLab CI

# .gitlab-ci.yml
variables:
  http_proxy: "http://proxy.company.com:3128"
  https_proxy: "http://proxy.company.com:3128"
  no_proxy: "localhost,127.0.0.1,.gitlab.company.com"

build:
  stage: build
  script:
    - curl -x "${http_proxy}" https://registry.npmjs.org/package -o package.json
    - wget -e use_proxy=yes -e http_proxy="${http_proxy}" https://example.com/resource.tar.gz

Docker: proxy al construir imágenes

# Pasar el proxy a través de argumentos de construcción
docker build \
  --build-arg http_proxy=http://proxy.example.com:3128 \
  --build-arg https_proxy=http://proxy.example.com:3128 \
  --build-arg no_proxy=localhost,127.0.0.1 \
  -t myapp:latest .

# En Dockerfile usamos ARG para obtener las variables
# Dockerfile
FROM ubuntu:22.04

ARG http_proxy
ARG https_proxy
ARG no_proxy

ENV http_proxy=${http_proxy}
ENV https_proxy=${https_proxy}
ENV no_proxy=${no_proxy}

RUN apt-get update && apt-get install -y curl wget

RUN curl -x "${http_proxy}" https://example.com/setup.sh | bash

# Limpiamos las variables de proxy en la imagen final (opcional)
ENV http_proxy=""
ENV https_proxy=""

Configuración global de proxy para el daemon de Docker (para docker pull a través del proxy):

# /etc/systemd/system/docker.service.d/proxy.conf
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:3128"
Environment="HTTPS_PROXY=http://proxy.example.com:3128"
Environment="NO_PROXY=localhost,127.0.0.1,.internal.registry.com"

# Reiniciamos docker
systemctl daemon-reload
systemctl restart docker

9. Rotación de proxies en scripts bash

Si necesitas hacer una gran cantidad de solicitudes a APIs externas o servicios, la rotación de proxies permite distribuir la carga y evitar bloqueos por IP. Esto es especialmente relevante al monitorear precios, recopilar datos o probar la disponibilidad de recursos desde diferentes regiones.

Para tales tareas, los proxies de centros de datos son muy adecuados, ya que ofrecen alta velocidad y estabilidad en solicitudes masivas.

#!/bin/bash
# rotate_proxy.sh — rotación de proxies desde una lista

PROXY_LIST=(
  "http://user:[email protected]:3128"
  "http://user:[email protected]:3128"
  "http://user:[email protected]:3128"
  "http://user:[email protected]:3128"
)

URLS_FILE="urls.txt"
OUTPUT_DIR="./results"
mkdir -p "${OUTPUT_DIR}"

PROXY_COUNT=${#PROXY_LIST[@]}
INDEX=0

while IFS= read -r url; do
  PROXY="${PROXY_LIST[$INDEX]}"
  FILENAME=$(echo "${url}" | md5sum | cut -d' ' -f1)
  
  echo "Solicitando: ${url} a través del proxy $((INDEX + 1))/${PROXY_COUNT}"
  
  curl -x "${PROXY}" \
       --max-time 30 \
       --retry 3 \
       --retry-delay 2 \
       --silent \
       --output "${OUTPUT_DIR}/${FILENAME}.html" \
       "${url}"
  
  if [ $? -eq 0 ]; then
    echo "  ✓ Éxito"
  else
    echo "  ✗ Falló, intentando con el siguiente proxy..."
    INDEX=$(( (INDEX + 1) % PROXY_COUNT ))
    curl -x "${PROXY_LIST[$INDEX]}" \
         --max-time 30 \
         --silent \
         --output "${OUTPUT_DIR}/${FILENAME}.html" \
         "${url}"
  fi
  
  # Pasamos al siguiente proxy
  INDEX=$(( (INDEX + 1) % PROXY_COUNT ))
  
  # Pequeña pausa entre solicitudes
  sleep 0.5
  
done < "${URLS_FILE}"

echo "¡Hecho! Resultados guardados en ${OUTPUT_DIR}"

Una variante más avanzada es verificar la disponibilidad del proxy antes de usarlo:

#!/bin/bash
# check_proxy.sh — verificación de disponibilidad del proxy

check_proxy() {
  local proxy_url="$1"
  local test_url="https://api.ipify.org"
  
  result=$(curl -x "${proxy_url}" \
                --max-time 10 \
                --silent \
                --write-out "%{http_code}" \
                --output /dev/null \
                "${test_url}")
  
  if [ "${result}" -eq 200 ]; then
    echo "VIVO"
  else
    echo "MUERTO"
  fi
}

# Obtenemos la IP externa a través del proxy
get_proxy_ip() {
  local proxy_url="$1"
  curl -x "${proxy_url}" --max-time 10 --silent https://api.ipify.org
}

PROXY="http://user:[email protected]:3128"
STATUS=$(check_proxy "${PROXY}")
echo "Estado del proxy: ${STATUS}"

if [ "${STATUS}" == "VIVO" ]; then
  EXTERNAL_IP=$(get_proxy_ip "${PROXY}")
  echo "IP externa a través del proxy: ${EXTERNAL_IP}"
fi

10. Depuración y errores comunes

Trabajar con proxies inevitablemente conlleva errores, especialmente durante la configuración inicial. Analicemos los problemas más comunes y cómo diagnosticarlos.

Diagnóstico con modo verbose

# Salida de curl lo más detallada posible
curl -vvv -x http://proxy.example.com:3128 https://api.example.com/data 2>&1 | head -50

# Qué observar en la salida:
# * Conectado a proxy.example.com — conexión con el proxy establecida
# CONNECT api.example.com:443 — solicitud de túnel
# HTTP/1.1 200 Connection established — túnel abierto
# * SSL connection using TLS — TLS funciona

# Depuración de wget
wget -d -e use_proxy=yes -e http_proxy=http://proxy.example.com:3128 https://api.example.com/data

Errores comunes y soluciones

Error Causa Solución
407 Proxy Authentication Required No se proporcionaron credenciales Agregar user:pass en la URL del proxy o el flag --proxy-user
Connection refused Puerto incorrecto o proxy no disponible Verificar el puerto: nc -zv proxy.host 3128
SSL certificate error Proxy corporativo con inspección SSL Agregar CA corporativa: --cacert /path/to/ca.crt
Could not resolve proxy DNS no resuelve el nombre del proxy Usar IP en lugar de nombre o verificar DNS
Timeout Proxy lento o sobrecargado Aumentar el tiempo de espera: --max-time
```