set_real_ip_from behavior

Andrei lagged at gmail.com
Tue Jul 2 09:12:22 UTC 2019


Hello,

I'm having some issues with getting X-Forwarded-For set consistently for
upstream proxy requests. The server runs Nginx/OpenResty in front of
Apache, and has domains hosted behind Cloudflare as well as direct. The
ones behind Cloudflare show the correct X-Forwarded-For header being set,
using (snippet):

http {
set_real_ip_from 167.114.56.190/32;
[..]
set_real_ip_from 167.114.56.191/32;
real_ip_header X-Forwarded-For;
server {
location ~ .* {
[..]
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
}

However, when I receive a direct request, which does not include
X-Forwarded-For,  $http_x_forwarded_for, $proxy_add_x_forwarded_for,
$http_x_real_ip are empty, and I'm unable to set the header to $remote_addr
(which shows the correct IP). If I try adding this in the server {} block:

if ($http_x_forwarded_for = '') {
    set $http_x_forwarded_for $remote_addr;
}

I get:

nginx: [emerg] the duplicate "http_x_forwarded_for" variable in
/usr/local/openresty/nginx/conf/nginx.conf:131
nginx: configuration file /usr/local/openresty/nginx/conf/nginx.conf test
failed

The above works to set $http_x_real_ip, but then I end up with direct
connections passing Apache the client IP through X-Real-IP, and proxied
connections (from Cloudflare) set X-Forwarded-For.

The log format I'm using to verify both $http_x_forwarded_for and
$http_x_real_ip is:

log_format json_combined escape=json
  '{'
    '"id":"$zid",'
    '"upstream_cache_status":"$upstream_cache_status",'
    '"remote_addr":"$remote_addr",'
    '"remote_user":"$remote_user",'
    '"stime":"$msec",'
    '"timestamp":"$time_local",'
    '"host":"$host",'
    '"server_addr":"$server_addr",'
    '"server_port":"$proxy_port",'
    '"request":"$request",'
    '"status": "$status",'
    '"body_bytes_sent":"$body_bytes_sent",'
    '"http_referer":"$http_referer",'
    '"http_user_agent":"$http_user_agent",'
    '"http_x_forwarded_for":"$http_x_forwarded_for",'
    '"http_x_real_ip":"$http_x_real_ip",'
    '"request_type":"$request_type",'
    '"upstream_addr":"$upstream_addr",'
    '"upstream_status":"$upstream_status",'
    '"upstream_connect_time":"$upstream_connect_time",'
    '"upstream_header_time":"$upstream_header_time",'
    '"upstream_response_time":"$upstream_response_time",'
    '"country":"$country_code",'
    '"request_time":"$request_time"'
  '}';

How can I consistently pass the backend service an X-Forwarded-For header,
with the client IP, regardless of it being a direct request or proxied
through Cloudflare/some other CDN?

Thanks!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx/attachments/20190702/059110a9/attachment.html>


More information about the nginx mailing list