Esta pagina se ve mejor con JavaScript habilitado

Haproxy - Nginx ProxyProtocol

 ·  🎃 kr0m

Como ya comentamos en un artículo anterior el protocolo ProxyProtocol resulta muy útil cuando estamos balanceando tráfico mediante un HaProxy, de este modo recibiremos la ip del cliente y no la del balanceador en el servidor final. Anteriormente configuramos HaProxy y Apache, en esta ocasión configuraremos Nginx.

Para poder utilizar ProxyProtocol con Nginx necesitamos el módulo RealIp, este viene habilitado en las opciones de compilación por defecto así que compilamos e instalamos Nginx directamente:

emerge -av www-servers/nginx

Comprobamos que se haya compilado con el módulo necesario:

nginx -V 2>&1 | grep – ‘http_realip_module’

configure arguments: --prefix=/usr --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error_log --pid-path=/run/nginx.pid --lock-path=/run/lock/nginx.lock --with-cc-opt=-I/usr/include --with-ld-opt=-L/usr/lib64 --http-log-path=/var/log/nginx/access_log --http-client-body-temp-path=/var/lib/nginx/tmp/client --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --with-compat --with-http_v2_module --with-pcre --with-http_realip_module --with-http_ssl_module --without-stream_access_module --without-stream_geo_module --without-stream_limit_conn_module --without-stream_map_module --without-stream_return_module --without-stream_split_clients_module --without-stream_upstream_hash_module --without-stream_upstream_least_conn_module --without-stream_upstream_zone_module --without-mail_imap_module --without-mail_pop3_module --without-mail_smtp_module --user=nginx --group=nginx

Configuramos Nginx para que acepte ProxyProtocol, le indicamos la ip del HaProxy, que sustituya la ip del HaProxy por la recibida por ProxyProtocol, que asigne las variables correctas y que guarde los logs con las variables nuevas:

vi /etc/nginx/nginx.conf

http {
    proxy_set_header X-Real-IP       $proxy_protocol_addr;
    proxy_set_header X-Forwarded-For $proxy_protocol_addr;

    log_format proxyprotocollogformat
            '$proxy_protocol_addr - $remote_user [$time_local] '
            '"$request" $status $body_bytes_sent '
            '"$http_referer" "$http_user_agent"';

    server {
        listen 80   proxy_protocol;
        set_real_ip_from HA_IP/MASK;
        real_ip_header proxy_protocol;
        access_log /var/log/nginx/localhost.access_log proxyprotocollogformat;
    }
}

Los logs obtenidos ahora tendrán la ip del cliente:

CLIENT_IP - - [19/May/2020:10:21:19 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; FreeBSD amd64; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"

Si lo único que vemos en los logs son entradas como estas:

- - - [02/Jan/2021:20:22:23 +0100] "PROXY TCP4 192.168.69.11 192.168.69.10 12308 443" 400 157 "-" "-"  
- - - [02/Jan/2021:20:22:25 +0100] "\x00" 400 157 "-" "-"

Es que no hemos configurado correctamente la línea listen de la sección server de Nginx, falta el parámetro proxy_protocol.

NOTA: Si se habilita ProxyProtocol queda habilitado de forma global, no se puede configurar por Vhost. Otra opción podría ser habilitar ProxyProtocol pero en un puerto distinto y configurar el HaProxy acorde a estos puertos.

Si te ha gustado el artículo puedes invitarme a un RedBull aquí