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:
We check that it has been compiled with the necessary 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:
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.