User Tools

Site Tools


uso_de_sub_filter_en_nginx_como_proxy_reverso

Modulo ngx_http_sub_module + Multiple dominios + Proxy reverso Nginx (HTTP > HTTPS)

Cuando el servidor web Nginx está configurado como proxy reverso, este hace de intermediario entre navegador del cliente y el backend, el cual suele ser en la inmensa mayoría de casos otro servidor web. Se puede hacer por varios motivos, como simple redirecciones de puertos, balanceo de carga, capas de seguridad filtrando o analizando paquetes, autenticación HTTP, etc.

El módulo “ngx_http_sub_module” de Nginx es un filtro que modifica respuestas remplazando cadenas de texto. Si por ejemplo se desean convertir todos los enlaces hardcodeados de una determinada web de http a https, se puede hacer uso de dicho módulo.

En algunos entornos donde se debe usar además un dominio diferente para el backend (dominio del servidor detrás del proxy) que para el frontend (dominio del proxy) es necesario utilizar la opción “proxy_redirect” para cubrir el cambio de dominio en las cabeceras “Location” y “Refresh”.

El utilizar el módulo “ngx_http_sub_module” a la vez que se usa Nginx como proxy reverso, puede no funcionar si no se configura adecuadamente. Un problema común es el uso de compresión por parte de las solicitudes de los clientes usando la cabecera “Accept-Encoding”. Esta cabecera determina la codificación (compresión) que se espera de la respuesta. Valores comunes suelen ser “gzip”, “deflate” o “sdch”.

"Accept-Encoding: gzip,deflate,sdch"

Si Nginx le pasa al bakend dicha cabecera sin editar, la respuesta del backend estará comprimida (si el servidor bakend soporta compresión) y la directiva “sub_filter” no podrá sustituir las cadenas ya que el texto no viaja en claro.

Deshabilitar la compresión gzip para este tipo de entornos no serviría de nada porque la contestación es comprimida por el backend.

La solución más habitual en este tipo de casos es editar la cabecera que se enviará al servidor que está detrás del proxy para que este no comprima su respuesta.

proxy_set_header	 Accept-Encoding "";

De esta manera se recibirá una respuesta sin comprimir y la sustitución de cadenas por parte del módulo “ngx_http_sub_module” exitosa.

Ejemplo de configuración de Nginx como proxy reverso + ngx_http_sub_module + proxy_redirect.

En el puerto 8081 hay una aplicación web corriendo en Tomcat configurada con el dominio “dominio_backend” usando el protocolo http. Se quiere que el proxy reverso Nginx muestre su contenido usando https y además utilizando dominio diferente, “dominio_frontend”, el cual también debe estar presente en posibles enlaces que muestre la aplicación backend.

Resumiendo, no puede devolverse nada al cliente bajo “http://dominio_backend”.

server {
    listen       443;
    server_name  dominio_frontend;

    ssl_certificate           /etc/nginx/ssl.crt;
    ssl_certificate_key       /etc/nginx/ssl.key;

    ssl on;
    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;

    ############### REVERSE SSL PROXY ################

        location / { 

    ##################################################
    sub_filter_types *;
    sub_filter 'http://dominio_bakend' 'https://dominio_frontend';
    sub_filter_once off; 
    ##################################################
    
    proxy_pass 		 http://localhost:8081;
    proxy_set_header	 Accept-Encoding ""; # <--- Deshabilitar codificación en el backend.
    proxy_set_header 	 X-Forwarded-Host $host;
    proxy_set_header     Host $http_host;
    proxy_set_header 	 X-Forwarded-Server $host;
    proxy_set_header 	 X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header     X-Real-IP $remote_addr;
    client_max_body_size 20M;
    
    proxy_redirect https://dominio_bakend https://dominio_frontend; # <--- Cabeceras "Location" y "Refresh".
   }
}

Otra solución sin tocar Nginx sería deshabilitar en el bakend la compresión.

Comprobar que el no funcionamiento de ngx_http_sub_module es debido a compresión

# Devuelve una salida comprimida (No legible).
curl -L -k --header "Accept-Encoding: gzip,deflate,sdch" "https://dominio/"

# Devuelve una salida en texto claro.
curl -L -k --header "Accept-Encoding:" "https://dominio/"

Modificar las cabeceras “Location” y “Refresh” de las respuestas del servidor detrás del proxy (backend).

Si el servidor que está detrás del proxy tiene un dominio por defecto y no puede ser usado por el frontend, es necesario también modificar las cabeceras “Location” y “Refresh” en las respuestas del backend.

proxy_redirect https://dominio_bakend https://dominio_frontend;

Resumen.

Si se quiere tener un proxy con Nginx el cual sirva contenido de un backend que tiene otro dominio diferente al del frontend, posiblemente otro protocolo y enlaces hardcodeados (protocolo + dominio) que se deben modificar en tiempo real, las directivas “proxy_redirect”, “proxy_redirect” y dependiendo del caso “proxy_set_header” (Accept-Encoding), deben ser utilizadas como se mostró anteriormente.

uso_de_sub_filter_en_nginx_como_proxy_reverso.txt · Last modified: 2020/12/25 22:57 by 127.0.0.1