¿Tu pipeline falla con el error 403 Forbidden o Connection refused al intentar acceder a una API externa o descargar una dependencia? Lo más probable es que el problema sea que la dirección IP de tu servidor CI/CD está bloqueada por el recurso. Un proxy soluciona este problema: enrutas el tráfico a través de la IP adecuada y el pipeline funciona sin interrupciones. En este artículo, encontrarás instrucciones paso a paso para GitHub Actions, GitLab CI y Jenkins.
¿Por qué usar un proxy en CI/CD: escenarios reales?
Los pipelines de CI/CD funcionan en servidores con direcciones IP fijas: runners en la nube de GitHub, GitLab o en agentes de Jenkins propios. Estas IP son bien conocidas, y muchos servicios externos las bloquean o limitan la cantidad de solicitudes. Aquí hay situaciones específicas en las que un proxy es indispensable:
Acceso a recursos geográficamente restringidos
Muchos registros npm corporativos, repositorios Maven y APIs internas solo están disponibles desde ciertos países o rangos de IP. Si tu runner de GitHub Actions se encuentra en una región bloqueada a nivel de firewall del servicio objetivo, el pipeline no podrá descargar dependencias o enviar datos. Un proxy con la geolocalización adecuada resuelve esta tarea sin cambiar la infraestructura.
Limitación de tasa y bloqueos por IP
Los runners en la nube de GitHub Actions utilizan IP de rangos de Microsoft Azure. Muchas APIs públicas conocen estos rangos y aplican límites estrictos o bloqueos totales. Por ejemplo, el análisis de datos públicos, solicitudes a APIs externas durante pruebas, descarga de distribuciones desde CDN restringidos: todo esto se rompe regularmente debido a las IP de los runners en la nube. La rotación a través de un proxy permite eludir la limitación de tasa.
Pruebas de integración con sitios reales
Si tus pruebas de integración acceden a sitios web reales o marketplaces (Wildberries, Ozon, Avito, Amazon), estos sitios ven la misma IP del runner en cada ejecución y rápidamente la bloquean. Un proxy con rotación de IP permite que las pruebas se realicen de manera estable sin CAPTCHAs ni bloqueos.
Acceso a recursos corporativos internos
Las redes corporativas a menudo están cerradas al mundo exterior. Si el pipeline debe desplegar en un servidor interno o acceder a una API cerrada, un proxy (o túnel SOCKS5) dentro de la red corporativa se convierte en un puente entre el runner en la nube y la infraestructura cerrada.
Pruebas de integraciones publicitarias y de marketing
Los equipos que trabajan con la API de Facebook Ads, la API de TikTok Ads o la API de Google Ads a menudo automatizan la creación de campañas a través de CI/CD. Estas plataformas tienen reglas estrictas sobre IP: las solicitudes desde IP de centros de datos pueden ser bloqueadas o requerir verificación adicional. Los proxies residenciales en el pipeline hacen que las solicitudes se parezcan al tráfico de usuarios normales.
Qué tipo de proxy elegir para el pipeline
La elección del tipo de proxy depende de la tarea. Para los pipelines de CI/CD, hay tres opciones relevantes, cada una con sus ventajas y limitaciones:
| Tipo de proxy | Velocidad | Confianza de los sitios | Mejor para |
|---|---|---|---|
| Proxies de centros de datos | Muy alta | Media | Descarga de dependencias, repositorios internos, APIs rápidas sin verificaciones estrictas |
| Proxies residenciales | Media | Alta | Pruebas de integración con sitios reales, APIs publicitarias (Facebook, TikTok), marketplaces |
| Proxies móviles | Media | Máxima | Pruebas de APIs móviles, trabajo con plataformas con máximas protecciones anti-bot |
Regla práctica:
Si la tarea es descargar paquetes o acceder a un servicio interno, elige proxies de centros de datos: son rápidos y más baratos. Si la tarea son pruebas en sitios reales o trabajo con plataformas publicitarias, se necesitan proxies residenciales. El protocolo SOCKS5 es preferible al HTTP/HTTPS, ya que funciona de manera más transparente con puertos y protocolos no estándar.
Configuración de un proxy en GitHub Actions
GitHub Actions es la herramienta de CI/CD más popular en la actualidad. La configuración del proxy aquí se realiza a través de variables de entorno y secretos del repositorio. Vamos a desglosarlo paso a paso.
Paso 1: Agregar datos del proxy a los secretos del repositorio
Nunca escribas el nombre de usuario y la contraseña del proxy directamente en el archivo YAML del workflow. Utiliza GitHub Secrets:
- Abre el repositorio → Settings → Secrets and variables → Actions
- Haz clic en New repository secret
- Crea un secreto
PROXY_URLcon el valor en el formatohttp://user:[email protected]:port
Paso 2: Utiliza variables de entorno en el workflow
La mayoría de las herramientas (curl, wget, npm, pip, Maven) capturan automáticamente las variables de entorno estándar HTTP_PROXY, HTTPS_PROXY y NO_PROXY. Ejemplo de workflow:
name: Build with Proxy
on: [push]
env:
HTTP_PROXY: ${{ secrets.PROXY_URL }}
HTTPS_PROXY: ${{ secrets.PROXY_URL }}
NO_PROXY: localhost,127.0.0.1,internal.company.com
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Run integration tests
run: npm test
- name: Call external API
run: |
curl -v https://api.example.com/data
Paso 3: Proxy SOCKS5 en GitHub Actions
Si utilizas SOCKS5 (recomendado para la mayoría de las tareas), las variables de entorno estándar no son suficientes: se necesita un túnel local. Utiliza la herramienta proxychains o configura microsocks:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Setup SOCKS5 proxy tunnel
run: |
sudo apt-get install -y proxychains4
echo "socks5 proxy.host 1080 user password" >> /etc/proxychains4.conf
- name: Run command through SOCKS5
run: proxychains4 curl https://restricted-resource.com/api
Configuración del proxy para herramientas específicas
Algunas herramientas ignoran las variables del sistema y requieren configuración adicional:
| Herramienta | Cómo configurar el proxy |
|---|---|
| npm / yarn | npm config set proxy http://user:pass@host:port |
| pip (Python) | pip install --proxy http://user:pass@host:port package |
| Maven | A través de settings.xml sección <proxies> |
| Gradle | systemProp.https.proxyHost=host en gradle.properties |
| Git | git config --global http.proxy http://user:pass@host:port |
| Docker build | --build-arg HTTP_PROXY=http://user:pass@host:port |
Configuración de un proxy en GitLab CI
GitLab CI proporciona varios niveles para establecer variables de entorno: a nivel de proyecto, grupo o instancia. Esto hace que la gestión del proxy sea más flexible en comparación con GitHub Actions.
Paso 1: Agregar variables en GitLab CI/CD Variables
- Abre el proyecto → Settings → CI/CD → sección Variables
- Haz clic en Add variable
- Agrega la variable
PROXY_URLcon el tipo Masked (oculta el valor en los logs) - Valor:
http://user:[email protected]:port
Paso 2: Utiliza las variables en .gitlab-ci.yml
variables:
HTTP_PROXY: $PROXY_URL
HTTPS_PROXY: $PROXY_URL
NO_PROXY: "localhost,127.0.0.1,.internal.company.com"
stages:
- build
- test
- deploy
build:
stage: build
image: node:20-alpine
script:
- npm ci
- npm run build
integration_tests:
stage: test
image: python:3.11
script:
- pip install -r requirements.txt
- pytest tests/integration/
deploy:
stage: deploy
script:
- curl -X POST https://api.external-service.com/deploy
-H "Authorization: Bearer $DEPLOY_TOKEN"
-d '{"version": "$CI_COMMIT_SHA"}'
Proxy solo para trabajos específicos
Si el proxy no es necesario en todas partes (por ejemplo, solo para pruebas de integración, pero no para la construcción), establece las variables a nivel de trabajo específico, no globalmente:
integration_tests:
stage: test
variables:
HTTP_PROXY: $PROXY_URL
HTTPS_PROXY: $PROXY_URL
script:
- pytest tests/integration/
build:
stage: build
# Aquí no se ha establecido el proxy — conexión directa
script:
- npm ci && npm run build
GitLab Runner autoalojado: configuración del proxy a nivel de runner
Si utilizas un GitLab Runner propio, puedes establecer el proxy globalmente en la configuración del runner. Abre el archivo /etc/gitlab-runner/config.toml y agrega en la sección [runners.env]:
[[runners]]
name = "my-runner"
url = "https://gitlab.com/"
token = "TOKEN"
executor = "docker"
environment = [
"HTTP_PROXY=http://user:[email protected]:port",
"HTTPS_PROXY=http://user:[email protected]:port",
"NO_PROXY=localhost,127.0.0.1"
]
Esto es conveniente cuando todos los pipelines en este runner deben usar el proxy: no es necesario especificarlo en cada .gitlab-ci.yml.
Configuración de un proxy en Jenkins
Jenkins es el más flexible de las tres herramientas, pero también el más complicado de configurar. Aquí, el proxy se puede establecer en varios niveles: globalmente para todo Jenkins, para un Pipeline específico o para un paso individual.
Método 1: Configuración global del proxy en Jenkins
- Abre Manage Jenkins → System
- Encuentra la sección HTTP Proxy Configuration
- Completa los campos: Server, Port, Username, Password
- En el campo No Proxy Host indica las direcciones internas separadas por comas
- Haz clic en Test URL para verificar y guarda
Esta configuración afecta la carga de plugins y actualizaciones de Jenkins, pero no se transmite automáticamente al entorno de ejecución de los pipelines. Se necesita una configuración separada para los pipelines.
Método 2: Proxy en Declarative Pipeline a través de environment
pipeline {
agent any
environment {
HTTP_PROXY = credentials('proxy-url-credential')
HTTPS_PROXY = credentials('proxy-url-credential')
NO_PROXY = 'localhost,127.0.0.1,internal.company.com'
}
stages {
stage('Build') {
steps {
sh 'npm ci'
sh 'npm run build'
}
}
stage('Integration Tests') {
steps {
sh 'pytest tests/integration/'
}
}
stage('Deploy') {
steps {
sh '''
curl -X POST https://api.external-service.com/deploy \
-H "Authorization: Bearer ${DEPLOY_TOKEN}" \
-d "version=${GIT_COMMIT}"
'''
}
}
}
}
Paso 3: Agregar credenciales del proxy en Jenkins Credentials
- Abre Manage Jenkins → Credentials → System → Global credentials
- Haz clic en Add Credentials
- Tipo: Secret text
- ID:
proxy-url-credential - Secret:
http://user:[email protected]:port
Método 3: Proxy a través de parámetros JVM para proyectos Java
Si tu pipeline construye un proyecto Java (Maven, Gradle), las variables de entorno del sistema pueden no funcionar: la JVM utiliza sus propias propiedades del sistema. Agrégalas a JAVA_OPTS:
environment {
JAVA_OPTS = '-Dhttps.proxyHost=proxy.host -Dhttps.proxyPort=8080 -Dhttps.proxyUser=user -Dhttps.proxyPassword=password -Dhttp.nonProxyHosts=localhost|127.0.0.1|*.internal.com'
}
Proxy dentro de contenedores Docker en el pipeline
La mayoría de los pipelines modernos de CI/CD ejecutan pasos dentro de contenedores Docker. Pasar el proxy al contenedor es una tarea separada que se puede resolver de varias maneras.
Pasar el proxy a través de --build-arg al construir la imagen
Si el proxy solo es necesario durante la construcción de la imagen Docker (por ejemplo, para instalar paquetes dentro del Dockerfile), utiliza argumentos de construcción:
# En .github/workflows/build.yml o .gitlab-ci.yml
docker build \
--build-arg HTTP_PROXY=$HTTP_PROXY \
--build-arg HTTPS_PROXY=$HTTPS_PROXY \
--build-arg NO_PROXY=$NO_PROXY \
-t myapp:latest .
# En Dockerfile
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
RUN npm ci
⚠️ Importante: seguridad al construir imágenes
Las variables establecidas a través de ARG y ENV en el Dockerfile se almacenan en los metadatos de la imagen y son visibles a través de docker inspect. Si el proxy requiere autenticación, asegúrate de que la imagen final no se publique en un registro público; de lo contrario, las credenciales estarán disponibles públicamente.
Configuración global del daemon de Docker para el proxy
En runners autoalojados, se puede configurar el proxy para todo el daemon de Docker: así, todos los contenedores recibirán automáticamente el proxy sin cambios en el Dockerfile:
# /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://user:[email protected]:port"
Environment="HTTPS_PROXY=http://user:[email protected]:port"
Environment="NO_PROXY=localhost,127.0.0.1,registry.internal.com"
# Aplicar cambios:
# systemctl daemon-reload
# systemctl restart docker
Seguridad: cómo almacenar credenciales del proxy
Las credenciales del proxy son secretos como las claves API o las contraseñas de bases de datos. Su filtración significa que cualquiera podrá usar tu proxy a tu costa. Aquí hay reglas para un almacenamiento seguro:
Lista de verificación de seguridad
- ✅ Nunca escribas el nombre de usuario/contraseña del proxy directamente en los archivos YAML del pipeline
- ✅ Utiliza Masked variables en GitLab y Encrypted secrets en GitHub: se ocultan en los logs
- ✅ En Jenkins, utiliza el tipo Secret text o Username with password en el Credentials Store
- ✅ Agrega
NO_PROXYpara direcciones internas: el tráfico a tu infraestructura no debe pasar por el proxy - ✅ Rota regularmente las contraseñas del proxy: actualiza solo en el almacén de secretos, sin cambiar el código del pipeline
- ✅ Utiliza autenticación IP del proxy (whitelist de IP del runner) donde sea compatible: es más seguro que una contraseña
- ✅ Revisa los logs del proxy en busca de actividad inusual
Formato de URL del proxy: qué poner dónde
| Protocolo | Formato de URL | Cuándo usar |
|---|---|---|
| HTTP | http://user:pass@host:port |
La mayoría de las herramientas, npm, pip, curl |
| HTTPS | https://user:pass@host:port |
Conexión cifrada con el servidor proxy |
| SOCKS5 | socks5://user:pass@host:port |
Puertos no estándar, tráfico UDP, máxima compatibilidad |
Errores comunes y cómo solucionarlos
Incluso después de una configuración correcta, pueden surgir problemas. Aquí están los errores más comunes y sus soluciones:
Error: Proxy Authentication Required (407)
Razón: Nombre de usuario o contraseña incorrectos, o no se están transmitiendo por la herramienta.
Solución: Verifica el formato de la URL: los caracteres especiales en la contraseña deben estar codificados en URL. Por ejemplo, p@ss#word → p%40ss%23word. También asegúrate de que la variable de entorno se esté transmitiendo realmente en el paso: imprímela con echo $HTTP_PROXY (los primeros caracteres) para verificar.
Error: SSL Certificate Verification Failed
Razón: El proxy realiza inspección SSL (MITM) y reemplaza el certificado. El cliente no confía en el certificado del proxy.
Solución: Agrega el certificado raíz del proxy a los confiables. Para curl: --cacert /path/to/proxy-ca.crt. Para npm: npm config set cafile /path/to/proxy-ca.crt. O utiliza un proxy sin inspección SSL: esto es preferible para CI/CD.
Error: Connection Timeout a través del proxy
Razón: El servidor proxy no es accesible desde la IP del runner, o el puerto está bloqueado por el firewall.
Solución: Verifica la disponibilidad del proxy con el comando nc -zv proxy.host port en el paso del pipeline. Asegúrate de que la IP del runner esté en la lista blanca del proveedor del proxy (si se utiliza autenticación IP). Para los runners en la nube de GitHub Actions, los rangos de IP se publican en meta.github.com.
Error: La herramienta ignora las variables HTTP_PROXY
Razón: Algunas herramientas (especialmente las basadas en Java) no leen las variables de entorno del sistema.
Solución: Utiliza la configuración nativa del proxy para la herramienta específica (ver tabla anterior). Para Java, agrega propiedades de la JVM a través de JAVA_OPTS. Para curl, utiliza la bandera -x http://proxy:port explícitamente.
Error: Los servicios internos también pasan por el proxy
Razón: La variable NO_PROXY no está establecida o está establecida incorrectamente.
Solución: Especifica todos los dominios y IP internos en NO_PROXY. Usa comodines para los dominios: NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,.internal.company.com. Ten en cuenta: algunas herramientas soportan notación CIDR, otras solo dominios exactos.
Conclusión
Configurar un proxy en el pipeline de CI/CD no es una tarea única, sino parte de una arquitectura adecuada de automatización. Hemos revisado tres herramientas principales: GitHub Actions (a través de Secrets y variables de entorno), GitLab CI (a través de Variables con enmascaramiento) y Jenkins (a través de Credentials Store y Declarative Pipeline). Los principios clave son los mismos para todos: nunca almacenar credenciales en el código, usar NO_PROXY para direcciones internas y elegir el tipo de proxy según la tarea específica.
La elección del tipo de proxy adecuado es crítica para la estabilidad del pipeline. Para descargar dependencias y acceder a APIs estándar, son suficientes los rápidos proxies de centros de datos. Sin embargo, si tu pipeline realiza pruebas de integración en sitios reales, trabaja con plataformas publicitarias (API de Facebook Ads, API de TikTok Ads) o accede a marketplaces, utiliza proxies residenciales: sus IP son percibidas como tráfico de usuarios normales y rara vez son bloqueadas o limitadas.
La regla principal: prueba el proxy en un paso separado al inicio del pipeline: esto permitirá diagnosticar problemas rápidamente y no perder tiempo buscando errores al final de una larga construcción. Agrega un paso curl -v https://api.ipify.org justo después de configurar el proxy: mostrará la IP desde la que se envían las solicitudes y confirmará que el proxy está funcionando correctamente.