Proxy inverso con Apache2 y Nginx
Introducción al proxy inverso
Un proxy inverso es un tipo de servidor que actúa como intermediario entre los clientes externos y uno o varios servidores internos (backends). Cuando un cliente realiza una petición (normalmente por HTTP o HTTPS), el proxy la recibe, la reenvía al servidor interno y devuelve la respuesta al cliente como si procediera del propio proxy.
Este mecanismo se utiliza principalmente para:
- Proteger los servidores internos, que no son accesibles directamente desde el exterior.
 - Centralizar el acceso a varias aplicaciones internas bajo un único dominio.
 - Distribuir carga entre varios backends (balanceo).
 - Terminar conexiones HTTPS (TLS termination).
 - Añadir cabeceras o filtros de seguridad, compresión o autenticación.
 - Reescribir rutas o redirecciones para adaptarlas al espacio público.
 
Esquema general:
Cliente (HTTP/HTTPS)
        │
        ▼
 Proxy inverso (80/443)
        │
        ▼
Servidor interno (p.ej. 10.0.0.2:8080)
Apache2 como proxy inverso
Apache2 puede actuar como proxy inverso mediante el módulo mod_proxy y sus submódulos especializados (por ejemplo, mod_proxy_http para HTTP).
Para habilitar esta funcionalidad:
sudo a2enmod proxy proxy_http
sudo systemctl reload apache2
Proxy desde la raíz (/)
Configuración básica en un VirtualHost para redirigir todas las peticiones entrantes (/) a un servidor interno:
<VirtualHost *:80>
    ServerName proxy.example.org
    ProxyPass "/" "http://interno.example.org/"
    ProxyPassReverse "/" "http://interno.example.org/"
    ErrorLog ${APACHE_LOG_DIR}/proxy_error.log
    CustomLog ${APACHE_LOG_DIR}/proxy_access.log combined
</VirtualHost>
Explicación de las directivas:
ProxyPass: redirige las solicitudes entrantes hacia el servidor interno (backend).ProxyPassReverse: reescribe las cabeceras de respuesta (Location,Content-Location) para que las URLs devueltas sean las públicas.
Problema de redirecciones
Cuando el backend responde con una redirección HTTP (cabecera Location), suele incluir su propio dominio interno, por ejemplo:
Location: http://interno.example.org/login
El cliente, al recibir esa cabecera, intentará acceder directamente a la dirección interna, que no es accesible desde el exterior.
Solución:
ProxyPassReverse reescribe esas cabeceras, reemplazando la URL interna por la pública, de modo que el cliente vea:
Location: http://proxy.example.org/login
Esto garantiza que las redirecciones funcionen correctamente desde el exterior.
Proxy inverso usando una ruta
También es posible publicar una aplicación interna bajo una subruta específica del dominio público:
ProxyPass "/web/" "http://interno.example.org/"
ProxyPassReverse "/web/" "http://interno.example.org/"
El cliente accederá a http://proxy.example.org/web/, mientras Apache reenviará internamente las peticiones a http://interno.example.org/.
Este enfoque permite ofrecer varios servicios desde el mismo dominio (por ejemplo /api/, /web/, /admin/).
Envío de cabeceras
Cuando Apache actúa como proxy inverso, puede modificar, añadir o conservar cabeceras HTTP para transmitir al servidor interno información sobre la petición original del cliente.
Propósito del envío de cabeceras
El envío de cabeceras adicionales permite que el backend conozca:
- el dominio público al que accedió el cliente (
Host); - la IP real del cliente, no la del proxy;
 - el protocolo original (
httpohttps); - y los proxys intermedios por los que pasó la solicitud.
 
Esto es esencial para:
- registrar correctamente la IP de los usuarios;
 - generar redirecciones o URLs correctas desde el backend;
 - aplicar reglas de autenticación o seguridad dependientes del dominio o protocolo.
 
Conservación y envío de cabeceras
Para controlar el envío de cabeceras, Apache usa el módulo mod_headers.
Podemos conservar el Host original y añadir cabeceras adicionales como sigue:
# Conservar el dominio solicitado por el cliente
ProxyPreserveHost On
# Añadir cabeceras informativas al backend
RequestHeader set X-Real-IP "%{REMOTE_ADDR}s"
RequestHeader add X-Forwarded-For "%{REMOTE_ADDR}s"
RequestHeader set X-Forwarded-Proto "http"
RequestHeader set X-Forwarded-Host "%{HTTP_HOST}s"
Cabeceras comunes y su propósito:
| Cabecera | Propósito | 
|---|---|
Host | 
      Dominio solicitado originalmente | 
X-Real-IP | 
      IP real del cliente | 
X-Forwarded-For | 
      Lista de IPs de proxies intermedios | 
X-Forwarded-Proto | 
      Protocolo del cliente (HTTP o HTTPS) | 
X-Forwarded-Host | 
      Host solicitado originalmente (similar a Host) | 
    
Estas cabeceras ayudan a que el servidor interno tenga una visión completa del contexto real de la solicitud, especialmente útil cuando hay varios niveles de proxy o balanceo de carga.
Nginx como proxy inverso
Nginx incorpora de forma nativa la funcionalidad de proxy inverso y balanceo de carga, sin módulos adicionales.
Proxy desde la raíz (/)
Configuración básica:
server {
    listen 80;
    server_name proxy.example.org;
    location / {
        proxy_pass http://interno.example.org/;
        include proxy_params;
    }
    access_log /var/log/nginx/proxy_access.log;
    error_log /var/log/nginx/proxy_error.log;
}
El archivo /etc/nginx/proxy_params contiene los parámetros estándar de reenvío de cabeceras (se detalla más adelante).
Problema de redirecciones
Al igual que en Apache, las redirecciones del backend pueden apuntar a la URL interna.
Para corregirlo, se utiliza la directiva proxy_redirect:
proxy_redirect http://interno.example.org/ /;
Esto reescribe las cabeceras Location y Refresh en las respuestas del backend, sustituyendo las rutas internas por las del proxy público.
Proxy inverso usando una ruta
Para ofrecer un servicio interno bajo una ruta específica (por ejemplo /web/):
location /web/ {
    proxy_pass http://interno.example.org/;
    include proxy_params;
}
El cliente accede a http://proxy.example.org/web/, mientras Nginx redirige las peticiones internamente al backend.
Envío de cabeceras
Nginx envía automáticamente varias cabeceras al backend para conservar información sobre el cliente.
Estas se definen en /etc/nginx/proxy_params (archivo incluido en la mayoría de configuraciones):
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
Cabeceras estándar:
| Cabecera | Propósito | Variable | 
|---|---|---|
Host | 
      Host solicitado por el cliente | $http_host | 
    
X-Real-IP | 
      IP real del cliente | $remote_addr | 
    
X-Forwarded-For | 
      Cadena de IPs de los proxies intermedios | $proxy_add_x_forwarded_for | 
    
X-Forwarded-Proto | 
      Protocolo usado por el cliente (HTTP/HTTPS) | $scheme | 
    
Estas cabeceras permiten que el servidor interno conozca el contexto de la solicitud original y genere respuestas coherentes (por ejemplo, URLs correctas en redirecciones o registros de auditoría con la IP real del usuario).
Resumen comparativo
| Aspecto | Apache2 | Nginx | 
|---|---|---|
| Módulos necesarios | mod_proxy, mod_proxy_http | 
      Nativo | 
| Reescritura de redirecciones | ProxyPassReverse | 
      proxy_redirect | 
    
| Proxy en subruta | ProxyPass /ruta/ http://... | 
      location /ruta/ { proxy_pass ...; } | 
    
Conserva cabecera Host | 
      ProxyPreserveHost On | 
      proxy_set_header Host $http_host | 
    
| Envío de cabeceras del cliente | RequestHeader set/add ... | 
      proxy_set_header ... | 
    
| Archivo de configuración común | /etc/apache2/sites-available/... | 
      /etc/nginx/proxy_params |