关于Nginx:在从Apache调用的PHP-FPM中设置正确的REMOTE_ADDR

Set correct REMOTE_ADDR in PHP-FPM called from Apache

我们想在Apache服务器上从mod_php切换到fastCGI PHP-FPM。

除了一件事,我们一切都准备就绪,正在工作:

我们的$ _SERVER [\\'REMOTE_ADDR \\']中的值始终为127.0.0.1,而不是客户端的IP。有什么方法可以配置服务器以将此变量设置为客户端真实IP吗?

我们在X-Forwarded-For标头中有客户端真实IP(从代理传递)

基本上,我们需要Apache替代nginx的配置:

1
fastcgi_param REMOTE_ADDR $http_x_forwarded_for;

(如此处所述Nginx用X-Forwarded-For替换REMOTE_ADDR)


通过在php.ini中添加指令来解决:

1
auto_prepend_file = /etc/php5/rpaf.php

允许执行此简单的PHP脚本以标准化标头:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?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];
    }
  }
}


如果要在日志中查看真实IP,请在access.format指令中使用%{REMOTE_ADDR}。在您池的php-fpm.conf中。


对于apache 2.4,您可以使用apache的mod_remoteip模块。它将在apache日志中设置预期的客户端IP,并将该信息转发到php-fpm,而无需更改php-fpm。已使用官方httpdphp-fpm泊坞窗映像进行测试。

这是httpd.conf

的示例配置部分

1
2
3
4
5
6
LoadModule remoteip_module modules/mod_remoteip.so

RemoteIPHeader X-Forwarded-For
RemoteIPProxiesHeader X-Forwarded-By
# 0.0.0.0/0 is not accepted
RemoteIPInternalProxy 172.0.0.0/8

否则,提到的mod_rpaf在Apache 2.4中不再可用。


由于我只是花了好几个小时,因此我想指出,当使用mod_proxy mod_proxy_fcgi代替mod_fcgi(至少在Debian Jessie上)时,mod_rpaf似乎无法正常工作。

虽然正确配置了mod_rpaf和负载均衡器后,mod_rpaf确实可以修复apache访问日志,但遗憾的是,它不会修复PHP $ _SERVER ['REMOTE_ADDR']变量。

有人建议使用以下方法手动覆盖REMOTE_ADDR:

1
2
SetEnvIf X-Real-IP"^(\\d{1,3}+\\.\\d{1,3}+\\.\\d{1,3}+\\.\\d{1,3}+).*" REMOTE_ADDR=$1
RequestHeader set REMOTE-ADDR %{REMOTE_ADDR}e env=REMOTE_ADDR

并且尽管您可以通过这种方式将自定义条目添加到$ _SERVER(带有和不带有HTTP前缀),但不适用于REMOTE_ADDR ...

另一方面,使用mod_remoteip将正确的ip传递给$ _SERVER ['REMOTE_ADDR'] ,但似乎apache访问日志再次显示了负载均衡器ip ... <铅>

[编辑:没关系,在访问日志格式定义(apache2.conf)中将%h替换为%a,并且有效]


在nginx配置中进行设置。

1
2
3
4
# Set the client remote address to the one sent in the X_FORWARDED_FOR header from trusted addresses.
set_real_ip_from                127.0.0.1;
real_ip_header                  X-Forwarded-For;
real_ip_recursive               on;

来源:http://nginx.org/en/docs/http/ngx_http_realip_module.html

-

Apache的更新

对于Apache,请安装模块mod_rpaf,然后进行配置。

1
2
3
4
5
6
7
LoadModule              rpaf_module modules/mod_rpaf.so
RPAF_Enable             On
RPAF_ProxyIPs           127.0.0.1 10.0.0.0/24
RPAF_SetHostName        On
RPAF_SetHTTPS           On
RPAF_SetPort            On
RPAF_ForbidIfNotProxy   Off

来源:https://github.com/gnif/mod_rpaf