Nginx Access Log: log the real user’s IP instead of the proxy

Mattias Geniar, Sunday, December 11, 2011 - last modified: Friday, February 17, 2012

If you're running Nginx behind a proxy or a caching engine like Varnish or Squid, you'll see your access logs get filled with lines that mention your Proxy or Caching engine's IP instead of the real user's IP address.

To change that, add the following line in your general nginx.conf in the http {} section.

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

The change there is that the standard $remote_addr is replaced by $http_x_forwarded_for that your proxy/cache will pass along.

Somewhere along your config you'll have a line similar to this:

access_log      /var/www/site/logs/access.log main;

Add the main parameter at the end, to tell Nginx you're using that custom log format you created above.



Hi! My name is Mattias Geniar. I'm a Support Manager at Nucleus Hosting in Belgium, a general web geek & public speaker. Currently working on DNS Spy & Oh Dear!. Follow me on Twitter as @mattiasgeniar.

Share this post

Did you like this post? Will you help me share it on social media? Thanks!

Comments

Maurus Cuelenaere Monday, December 12, 2011 at 15:16 - Reply

I certainly hope you’re logging both $remote_addr and $http_x_forwarded_for, don’t forget that users can generate these headers too..


Niristotle Okram Monday, October 12, 2015 at 03:20 - Reply

With the above lines, the addresses are not printed now. The nginx access logs looks like this now.

- - - [12/Oct/2015:01:20:27 +0000] "GET /about HTTP/1.1" 200 61 "-" "ELB-HealthChecker/1.0"
54.241.XX.XX - - [12/Oct/2015:01:20:28 +0000] "GET /about HTTP/1.1" 200 61 "-" "Amazon Route 53 Health Check Service; ref:a04cdfe7-521e-4392-b959-60bb7cf38958; report http://amzn.to/1vsZADi"
- - - [12/Oct/2015:01:20:30 +0000] "GET /about HTTP/1.1" 200 61 "-" "ELB-HealthChecker/1.0"
54.248.XXX.XXX - - [12/Oct/2015:01:20:32 +0000] "GET /about HTTP/1.1" 200 61 "-" "Amazon Route 53 Health Check Service; ref:a04cdfe7-521e-4392-b959-60bb7cf38958; report http://amzn.to/1vsZADi"
54.232.XXX.XXX - - [12/Oct/2015:01:20:33 +0000] "GET /about HTTP/1.1" 200 61 "-" "Amazon Route 53 Health Check Service; ref:a04cdfe7-521e-4392-b959-60bb7cf38958; report http://amzn.to/1vsZADi"
- - - [12/Oct/2015:01:20:34 +0000] "\x04" 400 172 "-" "-"
107.23.XXX.XXX - - [12/Oct/2015:01:20:34 +0000] "GET /about HTTP/1.1" 200 61 "-" "Amazon Route 53 Health Check Service; ref:a04cdfe7-521e-4392-b959-60bb7cf38958; report http://amzn.to/1vsZADi"

For some reason, the ip for the AWS health checks shows ip but my browsers GET to the node shows — like this


    Mattias Geniar Monday, October 12, 2015 at 12:32 - Reply

    Keep in mind that the modified access logs will take the X-Forwarded-For header and log the value in there.

    If you browse directly to your webserver, without a middleware proxy like a load balancer, the X-Forwarded-For does not exist. That’s probably why Amazon’s load balancer health checks don’t log the IP either, since they don’t send the X-Forwarded-For header.

    Try the following, to also still log the connecting IP (this will nearly always be your load balancer).

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

Rodrigo Murillo Wednesday, September 7, 2016 at 20:38 - Reply

Perfect thanks


Leave a Reply

Your email address will not be published. Required fields are marked *