Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set correct REMOTE_ADDR in PHP-FPM called from Apache

We want to switch from mod_php to fastCGI + PHP-FPM on our Apache server.

We got everyhting in place and working except one thing:

Value in our $_SERVER['REMOTE_ADDR'] is always 127.0.0.1 not IP of client. Is there any way how to configure server to set this variable to client real IP?

We have client real IP in X-Forwarded-For header (passed from proxy)

Basically we need Apache alternative for nginx config:

fastcgi_param REMOTE_ADDR $http_x_forwarded_for;

( as described here Nginx replace REMOTE_ADDR with X-Forwarded-For)

like image 897
Martin Mystik Jonáš Avatar asked May 04 '15 18:05

Martin Mystik Jonáš


People also ask

Can you use PHP-FPM with Apache?

FPM is a process manager to manage the FastCGI in PHP. Apache ships with mod_php by default and works with all major web servers.

Can $_ server Remote_addr be spoofed?

Any $_SERVER variable can be spoofed - e.g. curl_setopt( $ch, CURLOPT_HTTPHEADER, array("REMOTE_ADDR: $ip", "HTTP_X_FORWARDED_FOR: $ip")); So it depends entirely on the context: if the attacker is expecting a response, it will go back to $ip. If they don't care about the response, they can certainly spoof the header.

What is the default port for PHP-FPM?

By default, php-fpm will respond to CGI requests listening on localhost http port 9000. Therefore php-fpm expects your webserver to forward all requests for '. php' files to port 9000 and you should edit your webserver configuration file appropriately.


1 Answers

Solved by adding directive to php.ini:

auto_prepend_file = /etc/php5/rpaf.php

which enable execution of this simple PHP script to normalize headers:

<?php

$trustedProxies = array(
  '127.0.0.1'  
);

$remote = $_SERVER['REMOTE_ADDR'];

$allowedHeaders = array(
  'HTTP_X_FORWARDED_FOR' => 'REMOTE_ADDR',
  'HTTP_X_REAL_IP' => 'REMOTE_HOST',
  'HTTP_X_FORWARDED_PORT' => 'REMOTE_PORT',
  'HTTP_X_FORWARDED_HTTPS' => 'HTTPS',
  'HTTP_X_FORWARDED_SERVER_ADDR' => 'SERVER_ADDR',
  'HTTP_X_FORWARDED_SERVER_NAME' => 'SERVER_NAME',
  'HTTP_X_FORWARDED_SERVER_PORT' => 'SERVER_PORT',
);

if(in_array($remote, $trustedProxies)) {
  foreach($allowedHeaders as $header => $serverVar) {
    if(isSet($_SERVER[$header])) {
      if(isSet($_SERVER[$serverVar])) {
        $_SERVER["ORIGINAL_$serverVar"] = $_SERVER[$serverVar];
      }
      $_SERVER[$serverVar] = $_SERVER[$header];
    }
  }
}
like image 156
Martin Mystik Jonáš Avatar answered Sep 16 '22 15:09

Martin Mystik Jonáš