Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't get client's real IP when using Nginx reverse proxy

Problem description:
When I access Asp.net MVC Core 3.1 webpage that is supposed to return my remote client's ip address I instead get internal docker IP of Nginx container. I'm not sure if the problem is my code in asp.net core, the Nginx reverse proxy configuration not forwarding my client ip to Kestrel container, or something else.

Output:

::ffff:172.23.0.3

Desired Output (example using random ip):

231.43.6.124

Setup:

  • Remote VPS using Ubuntu and running Docker (i.e. not running locally)
  • Kestrel docker container that has no public access
  • Nginx Docker container that has public access on port 80 and forwards requests to backend kestrel server.

nginx.conf

http {
        upstream backendservers {
                server kestrel:80;
        }
        server {
                listen 80;
                location / {
                        proxy_pass http://backendservers/;
                        proxy_set_header Host $host;
                        proxy_set_header X-Real-IP $remote_addr; 
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        proxy_set_header X-Forwarded-Host $host:443;
                        proxy_set_header X-Forwarded-Server $host;
                        proxy_set_header X-Forwarded-Port 443;
                        proxy_set_header X-Forwarded-Proto https;
                }
        }
}

events {

}

asp.net core code

// controller
public IActionResult GetIP()
{
   var ip = HttpContext.Connection.RemoteIpAddress.ToString();
   ViewBag.ip = ip;
   return View();
}

// view
@{
    ViewData["Title"] = "Get IP";
}

<div class="text-center">
   <p>@ViewBag.ip</p>
</div>

Docker startup:

docker network create --driver=bridge stacknet
docker run -d --name=kestrel --restart=always -h kestrel.local --network=stacknet mykestrelimage
docker run -d --name=nginx --restart=always  -p 80:80 -h nginx.local --network=stacknet mynginximage

UPDATE 1: As a test I opened the Kestrel 80 port. I can get client IP when I hit Kestrel directly I just can't get it when it's coming via Nginx reverse proxy.

UPDATE 2: Added some lines to ngix.conf as per suggestion of one of replies below but didn't seem to make a difference.

like image 775
Anon Ymous Avatar asked Jun 30 '20 18:06

Anon Ymous


People also ask

How do you check if Nginx reverse proxy is working?

To check the status of Nginx, run systemctl status nginx . This command generates some useful information. As this screenshot shows, Nginx is in active (running) status, and the process ID of the Nginx instance is 8539.

Can Nginx do reverse proxy?

Reverse proxy is one of the most widely deployed use case for NGINX instance, providing an additional level of abstraction and control to ensure the smooth flow of network traffic between clients and servers.

What is Set_real_ip_from?

set_real_ip_from. real_ip_header. real_ip_recursive. Embedded Variables. The ngx_http_realip_module module is used to change the client address and optional port to those sent in the specified header field.


2 Answers

I had similar issue this is what i tried and it fixed my issue..

  1. go to /etc/nginx/sites-available/ you will found default file where you had configured your servers like this.
server{
  server_name example.com;
  location / {
    proxy_pass http://localhost:4000;
    proxy_set_header X-Real-IP $remote_addr; <---Add this line
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; <---this line too
  }

2.there will be one more file named proxy_params in /nginx folder make sure you have below lines in this file.

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  1. Most important in your back-end code get the IP like this.
const ipAddress = req.headers['x-forwarded-for'] as string;

You can also check the request ip through this command.

$ sudo tail -f /var/log/nginx/access.log
like image 96
Subham kuswa Avatar answered Oct 19 '22 07:10

Subham kuswa


You may need to forward the original IP. Here is NGinx's doc on the subject: https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/

And an example of the older x-forwarded-for from: https://plone.lucidsolutions.co.nz/web/reverseproxyandcache/setting-nginx-http-x-forward-headers-for-reverse-proxy

location / {
  proxy_pass              http://upstream/;
  proxy_set_header        Host               $host;
  proxy_set_header        X-Real-IP          $remote_addr;
  proxy_set_header        X-Forwarded-For    $proxy_add_x_forwarded_for;
  proxy_set_header        X-Forwarded-Host   $host:443;
  proxy_set_header        X-Forwarded-Server $host;
  proxy_set_header        X-Forwarded-Port   443;
  proxy_set_header        X-Forwarded-Proto  https;
}
like image 21
BookOfGreg Avatar answered Oct 19 '22 07:10

BookOfGreg