Mamun Sardar
Mamun Sardar

Reputation: 2729

Remote IP in tomcat webapp running behind nginx proxy

Using nginx/1.10.2 proxy and tomcat7 I'm trying to get the actual remote ip address in java webapp by request.getRemoteAddr() but always getting 127.0.0.1. Here's what I did:

CentOS proxy pass: setsebool -P httpd_can_network_connect true
& No config on tomcat7 other than the http/ajp port change.

Nginx config:

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

    access_log  off;

    client_body_in_file_only clean;
    client_body_buffer_size 32K;

    client_max_body_size 50M;

    sendfile            on;
    send_timeout        300s;

    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /var/www/html;
        index index.php index.html index.htm;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
            try_files $uri $uri/ =404;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }

        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
    }
}



Nginx proxy config:

upstream my_tomcat {
        server 127.0.0.1:81;
}
server {
        listen  80;
        server_name     sub.domain.com;
        location / {
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_http_version 1.1;
                proxy_set_header Connection "";
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-NginX-Proxy true;
                proxy_pass http://my_tomcat;
                proxy_redirect off;

                proxy_connect_timeout       300;
                proxy_send_timeout          300;
                proxy_read_timeout          300;
                send_timeout                300;
        }
}
server {
        listen  80;
        server_name     www.sub.domain.com;
        location / {
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_http_version 1.1;
                proxy_set_header Connection "";
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-NginX-Proxy true;
                proxy_pass http://my_tomcat;
                proxy_redirect off;

                proxy_connect_timeout       300;
                proxy_send_timeout          300;
                proxy_read_timeout          300;
                send_timeout                300;
        }
}

Upvotes: 3

Views: 5571

Answers (4)

Robert Newton
Robert Newton

Reputation: 1611

Tomcat 7/8/9 has a Valve for this very purpose, the Remote IP Valve.

By default it will examine the request header for "X-Forwarded-For", which is the standard header that a proxy will add. Then when request.getRemoteAddr() is called it returns the actual remote address.

For example, place the following in server.xml in the <Engine> level:

  <!-- Replaces the apparent client remote IP address and hostname for
       the request with the IP address list presented by a proxy or a
       load balancer -->
  <Valve className="org.apache.catalina.valves.RemoteIpValve"
         requestAttributesEnabled="true"
         internalProxies="127\.0\.0\.1" />

NOTE: if you want the actual remote address used in the access logs, you also need the to configure the AccessLogValve: add requestAttributesEnabled="true" to it.

Upvotes: 1

Grigory Kislin
Grigory Kislin

Reputation: 18010

Accoding Remote IP address from Nginx set IP to header:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

after that it available at application with

req.getHeader("X-Forwarded-For")

Also may be useful: blacklist IPs in NGINX and check blacklisted IP

Upvotes: 3

herokingsley
herokingsley

Reputation: 403

You should use the HTTP header X-Real-IP to get the real remote ip.

The 'how' is written below

request.getHeader("X-Real-IP")

The 'why' is that, the proxy adds the real client-ip in the http header X-Real-IP as part of the proxying process.

Upvotes: 4

Jim Garrison
Jim Garrison

Reputation: 86774

Unless things have changed a lot since I last looked, your use of request.getRemoteAddr() will always return the address of the proxy host. You must examine the headers added by the proxy server to extract the actual host identity. What you get (hostname or IP address) will depend on what the nginx proxy does.

Upvotes: 1

Related Questions