Nginx – X-Real-IP header empty with nginx behind a load balancer

load balancingnginx

We have two webservers (nginx) sitting behind a load balancer (storm on demand load balancer, not managed by our group). By default, the ip we receive is the load balancer ip. We tried to use the real ip module in nginx, but it looks like the load balancer isn't forwarding the real ip.

Nginx config (we have a default virtual host that just redirects to a static html page for test and that inherits everything from http directive):

http {

# x.x.x.x is the IP of the load balancer
set_real_ip_from   x.x.x.x;
real_ip_header     X-Real-IP;

# also tried:
#real_ip_recursive on;
#set_real_ip_from x.x.x.0/24;
#set_real_ip_from 0.0.0.0:0;

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_real_ip" "$http_x_forwarded_for"';

Nginx version & compiled modules:

nginx -V
nginx version: nginx/1.2.1
built by gcc 4.4.4 20100726 (Red Hat 4.4.4-13) (GCC) 
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx/ --sbin-path=/usr/sbin/nginx
--conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log 
--http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid 
--lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp 
--http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp 
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp 
--http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module 
--with-http_realip_module --with-http_addition_module --with-http_sub_module 
--with-http_dav_module --with-http_flv_module --with-http_mp4_module 
--with-http_gzip_static_module --with-http_random_index_module 
--with-http_secure_link_module --with-http_stub_status_module --with-mail 
--with-mail_ssl_module --with-file-aio --with-ipv6 --with-cc-opt='-O2 -g'

Example of log:

x.x.x.x - - [19/Jul/2012:05:07:17 -0400] "GET /fr/ HTTP/1.1" 200 11110 "-"
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.43 Safari/536.11"
"-" "-"

As you see from the log file, the headers HTTP-X-REAL-IP and HTTP-X-FORWARDED-FOR are empty (represented by "-" at the end of the log). We tried different configurations (recursive, 0.0.0.0:0), to no avail.

The support staff of the load balancer is saying that the problem is on our end, but we do not think so because of the empty headers.

Would a misconfiguration of nginx/real ip module cause the headers to be empty or is the load balancer at fault here (or a third option?)?

Best Answer

It should be sufficient to merely add

server {
  set_real_ip_from x.x.x.x/x;
  real_ip_header X-Forwarded-For;

To the opening lines of your vhost configuration.

Looking at the Storm on Demand load balancer service, it seems they use Zeus load balancers - which use the X-Cluster-Client-Ip header for the real/source IP. So I would suggest trying,

server {
  set_real_ip_from x.x.x.x/x;
  real_ip_header X-Cluster-Client-Ip;