This page looks best with JavaScript enabled

Haproxy - Nginx ProxyProtocol

 ·  🎃 kr0m

As we mentioned in a previous article , the ProxyProtocol protocol is very useful when balancing traffic using HaProxy, so we will receive the client’s IP instead of the load balancer’s IP on the final server. Previously, we configured HaProxy and Apache, and this time we will configure Nginx.

To use ProxyProtocol with Nginx, we need the RealIp module, which is enabled by default in the compilation options, so we compile and install Nginx directly:

emerge -av www-servers/nginx

We check that it has been compiled with the necessary module:

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

We configure Nginx to accept ProxyProtocol, indicate the HaProxy IP, replace the HaProxy IP with the one received by ProxyProtocol, assign the correct variables, and save the logs with the new variables:

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;
    }
}

The obtained logs will now have the client’s IP:

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"

If all we see in the logs are entries like these:

- - - [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 "-" "-"

It means that we have not correctly configured the listen line of the Nginx server section, and the proxy_protocol parameter is missing.

NOTE: If ProxyProtocol is enabled, it is enabled globally, and it cannot be configured per Vhost. Another option could be to enable ProxyProtocol but on a different port and configure HaProxy accordingly to these ports.

If you liked the article, you can treat me to a RedBull here