0

I run a nginx reverse proxy server in the docker container. And the backend is a apache server running on the host, which is listening 10082 port. Laravel handle the request. And I use

$request->getClientIp()

to get real ip. However, the result of visiting the server by http://myip:10082 directly without proxy conflicts with the result of visiting it by reverse proxy.

The test code in laravel:

echo $request->ip().'<br>';
echo $request->headers->get('X-Real-IP').'<br>';
echo $request->getClientIp().'<br>';

The result with proxy:

192.168.80.2
218.205.17.167
192.168.80.2

The result without proxy(the XX.XXX.236.29 is my real ip):

XX.XXX.236.29

XX.XXX.236.29

The configuration of nginx:

server { 
    listen       80; 
    server_name  myserver.com; 

    access_log  logs/myserver.access.log  main;


    location / { 
        proxy_pass http://myip:10082;
        proxy_set_header   Host    $host; 
        proxy_set_header   X-Real-IP   $remote_addr; 
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for; 
    }

}

I'm so confused. Could someone help me solve it. Thanks!

William wei
  • 261
  • 2
  • 12
  • Check out: http://stackoverflow.com/a/41748592/7377984 and https://github.com/fideloper/TrustedProxy – Paras Feb 06 '17 at 19:54

2 Answers2

1

Since you have set the X-Real-IP header in your nginx proxy, it's the real ip.

0

I've had the same issue and spent quite some time on it.

The problem is triggered is by the request having to pass the docker-proxy on its way to your containers. The IP is changed and basically you'll receive the gateway IP for your docker-network instead of the physical server one.

The latest editions of Laravel includes TrustProxies, but that helps nothing if the REMOTE_ADDR you receive isn't your server IP.

Hardcoding it isn't a solution either, since that IP can change the next time you reboot your server/recreate the containers.

I've solved this for myself by assuming that - when my server IP has 3 bytes in common with the REMOTE_ADDR and the latter ends with .1, it is safe to use as a trusted proxy:

In your TrustProxies-middleware's handle()-function:

$remoteAddr = $request->server->get('REMOTE_ADDR');
$serverAddr = $request->server->get('SERVER_ADDR');
if ($serverAddr && $remoteAddr) {
   $lastDot = strrpos($serverAddr, '.');
   if ($lastDot !== false && 
       substr($remoteAddr, $lastDot) === '.1' && 
       strpos($remoteAddr, substr($remoteAddr, 0, $lastDot+1)) === 0) {
      $this->proxies[] = $remoteAddr;
   }
}
Blizz
  • 8,082
  • 2
  • 33
  • 53