在Apache坐在反向代理(例如Squid)后面的情况下,cgi环境变量REMOTE_ADDR
获取代理的地址而不是客户端。
但是,代理将设置一个名为X-Forwarded-For
的标头,以包含客户端的原始IP地址,以便Apache可以看到它。
问题是,我们如何让Apache用REMOTE_ADDR
标头中的值替换X-Forwarded-For
,以便所有Web应用程序都能透明地看到正确的地址?
答案 0 :(得分:14)
你可以使用mod_rpaf。 http://stderr.net/apache/rpaf/
答案 1 :(得分:6)
请注意,如果请求已遍历多个代理,则X-Forwarded-For标头可能包含列表的IP地址。在这种情况下,您通常需要最左边的IP。您可以使用SetEnvIf:
来提取它SetEnvIf X-Forwarded-For "^(\d{1,3}+\.\d{1,3}+\.\d{1,3}+\.\d{1,3}+).*" XFFCLIENTIP=$1
注意使用 $ 1 设置XFFCLIENTIP环境变量以保存正则表达式中第一个组的内容(在括号中)。
然后,您可以使用环境变量的值来设置标头(或以Apache日志格式使用它,以便日志包含实际的客户端IP)。
答案 2 :(得分:4)
除了前面提到的mod_rpaf之外,似乎mod_extract_forwarded也会执行此功能。
mod_extract_forwarded
的一个优点是,EPEL可用于RHEL / CentOS服务器,而mod_rpaf
则不可用。
这两个模块似乎都不允许您将代理服务器的整个子网列入白名单,这就是为什么CloudFlare人员创建了自己的插件:mod_cloudflare,应该注意的是,不是像其他两个一样的通用工具;它包含一个硬编码的CloudFlare子网列表。
答案 3 :(得分:3)
是的,我们可以做到这一点。
只需在PHP.ini中添加auto_prepend_file,例如auto_prepend_file = "c:/prepend.php"
并在此文件中添加:
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
您需要apache width RemoteIPHeader X-Real-IP
中的MOD_REMOTEIP。
干杯,
Guiremach
答案 4 :(得分:2)
不幸的是,
在撰写本文时,freshports.org,people.apache.org或gist.github.com上的后端和分叉都没有工作。它们都基于apache httpd 2.3的早期alpha版本,它既不兼容当前版本的2.2也不兼容2.4。
因此,在尝试调整backport以创建httpd 2.2的实际工作时间浪费时间后,我决定转移到httpd 2.4。在httpd 2.4中,mod_remoteip工作顺利,即使负载均衡器具有永久保持连接,它用于将来自不同实际客户端IP地址的请求代理到后端。我不确定其他模块是否可以处理这种情况(在同一连接中更改每个请求的客户端IP地址)。
答案 5 :(得分:1)
请记住,此值可能会被欺骗。有关跨站点脚本结果的真实示例,请参阅http://blog.c22.cc/2011/04/22/surveymonkey-ip-spoofing/。
答案 6 :(得分:1)
目前,建议使用apache模块mod_remoteip; rpaf维护不可靠,可能会引起问题。
答案 7 :(得分:0)
您可以安装模块 mod_extract_forwarded 并将 MEFaccept 参数设置为all。
答案 8 :(得分:0)
自 Apache 2.4 起,就有mod_remoteip内置模块可以执行此操作。
启用g++
(例如mod_remoteip
)
创建受信任IP范围(接受远程IP标头的IP)列表。您可以将它们放在a2enmod remoteip
将此行添加到Apache配置:
conf/trusted-ranges.txt
更改日志文件格式,以使用RemoteIPTrustedProxyList conf/trusted-ranges.txt
代替%a
记录客户端IP。
对于 Cloudflare ,您需要信任其所有IP范围,并且使用自定义标头%h
:
CF-Connecting-IP
您可以像这样获得Cloudflare范围:
RemoteIPHeader CF-Connecting-IP