Search code examples
phpcurlnginxreal-ip

nginx real client ip not working


i have nginx, php7 and http_realip_module installed.

i have 1 server that serves 2 websites.

site 1 nginx config:

server {
    ...
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        fastcgi_read_timeout 300;

        proxy_set_header REMOTE_ADDR $http_x_real_ip;
        proxy_set_header X-Forwarded-For $http_x_real_ip;
    }
}

this populates the client's IP address when i dump $_SERVER['REMOTE_ADDR"].

site 1 connects to site 2 using curl like a simply api.

$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_URL, $serverUrl);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    "REMOTE_ADDR: ".$_SERVER['REMOTE_ADDR'], 
    "HTTP_X_FORWARDED_FOR: ".$_SERVER['REMOTE_ADDR'],
));
$result = curl_exec($ch);

site 2 nginx config:

server {
    ...
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        fastcgi_read_timeout 300;

        set_real_ip_from 127.0.0.1;
        real_ip_header    X-Forwarded-For;
        real_ip_recursive on;

    }
}

i can see that the script on site 2 gets called, but when i check the $_SERVER['REMOTE_ADDR'] variable in PHP it comes up with the server's IP address rather than the client's ip address. is the nginx setup correct here?

how can i get this to work correctly?


Solution

  • After some discussion and some trial/error below, we've found the best solution was to simply pass it through a $_GET parameter.

    Try using a completely custom header:

    curl_setopt($ch, CURLOPT_URL, $serverUrl . '?client_ip=' . $_SERVER['REMOTE_ADDR']);
    

    Because you're simply forwarding this variable on, it's not really necessary to try and tailor it to a header.

    After even further discussion, I found that nginx strips headers with underscores by default. Simply changing the underscores to dashes allows the end host to get the headers:

    curl_setopt($ch, CURLOPT_HTTPHEADER, array( 
        "X-CLIENT-REMOTE-IP: " . $_SERVER['REMOTE_ADDR']
    ));