在 apache 中将 REMOTE_ADDR 设置为 X-Forwarded-For
Posted
技术标签:
【中文标题】在 apache 中将 REMOTE_ADDR 设置为 X-Forwarded-For【英文标题】:Set REMOTE_ADDR to X-Forwarded-For in apache 【发布时间】:2011-01-15 21:11:43 【问题描述】:在 Apache 位于反向代理(例如 Squid)之后的情况下,cgi 环境变量 REMOTE_ADDR
获取代理的地址而不是客户端的地址。
但是,代理会设置一个名为 X-Forwarded-For
的标头来包含客户端的原始 IP 地址,以便 Apache 可以看到它。
问题是,我们如何让 Apache 将 REMOTE_ADDR
替换为 X-Forwarded-For
标头中的值,以便所有 Web 应用程序都能透明地看到正确的地址?
【问题讨论】:
【参考方案1】:您可以为此使用 mod_rpaf。 http://stderr.net/apache/rpaf/
【讨论】:
我正在为此 +1,但要注意显然 rpaf 不占用网络范围。因此,如果您的提供商正在为您进行平衡,您必须希望他们永远不会更改其平衡器 IP。此外,ubuntu 12.04 无法正确加载 conf,您必须在 rpaf.conf 中注释掉请记住,此值可能会被欺骗。请参阅 http://blog.c22.cc/2011/04/22/surveymonkey-ip-spoofing/ 了解具有跨站点脚本后果的真实示例。
【讨论】:
这就是为什么我看到的每个执行此翻译的机制(包括 maciekb 提到的非常有用的 rpaf 模块)都使用 REMOTE_HOST 白名单,以便您知道您来自受信任的代理。 【参考方案3】:请注意,如果请求已遍历多个代理,则 X-Forwarded-For 标头可能包含 IP 地址的列表。在这种情况下,您通常需要最左边的 IP。您可以使用 SetEnvIf 提取它:
SetEnvIf X-Forwarded-For "^(\d1,3+\.\d1,3+\.\d1,3+\.\d1,3+).*" XFFCLIENTIP=$1
注意使用 $1 来设置 XFFCLIENTIP 环境变量以保存正则表达式中第一组的内容(在括号中)。
然后您可以使用环境变量的值来设置标头(或在 Apache 日志格式中使用它,以便日志包含实际的客户端 IP)。
【讨论】:
我认为您的正则表达式不正确:您想获取X-Forwarded-For
标头中最右侧的IP 地址,而不是最左侧的IP 地址。你的表达应该是"^.*?(\d1,3+\.\d1,3+\.\d1,3+\.\d1,3+$"
。
我知道***是权威来源,但它目前指出最左边的 IP 是客户端:en.wikipedia.org/wiki/X-Forwarded-For
那么,我应该相信谁? :)
所以最左边的确实是客户端的IP,但是,之后的每个IP地址都应该被检查和验证为所谓的可信代理。作为先决条件,您必须验证这些代理中的每一个是否还检查他们的请求是否有意义。他们应该检查的是客户端欺骗,从而发送X-Forwarded-By
标头。【参考方案4】:
除了前面提到的mod_rpaf,mod_extract_forwarded 似乎也将执行此功能。
mod_extract_forwarded
的一个优点是它可以从EPEL 用于 RHEL/CentOS 服务器,而mod_rpaf
不可用。
这两个模块似乎都不允许您将整个代理服务器子网列入白名单,这就是 CloudFlare 人员创建自己的插件的原因:mod_cloudflare,应该注意的是,不是 em> 像其他两个一样的通用工具;它包含一个硬编码的 CloudFlare 子网列表。
【讨论】:
【参考方案5】:是的,我们可以做到。
只需在您的 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 宽度 RemoteIPHeader X-Real-IP
的 MOD_REMOTEIP。
干杯,
吉雷马赫
【讨论】:
我看不到 OP 提到了关于 PHP 的任何内容。如果你不知道的话,除了 PHP 还有其他的服务器端技术。 你缺少explode(',')、end()和trim()【参考方案6】:很遗憾,
在撰写本文时,freshports.org、people.apache.org 或 gist.github.com 的反向移植和分支都没有工作。它们都基于 apache httpd 2.3 的早期 alpha 版本,既不兼容当前版本的 2.2 也不兼容 2.4。
因此,在浪费时间尝试调整后向端口以创建真正的 httpd 2.2 工作后,我决定迁移到 httpd 2.4。在 httpd 2.4 中,mod_remoteip 工作顺利,即使负载均衡器具有永久保持连接,它用于将来自不同实际客户端 IP 地址的请求代理到后端。我不确定其他模块是否可以处理这种情况(在同一连接中更改每个请求的客户端 IP 地址)。
【讨论】:
【参考方案7】:您可以安装模块 mod_extract_forwarded 并将 MEFaccept 参数设置为 all。
【讨论】:
【参考方案8】:目前推荐使用 apache 模块 mod_remoteip 来执行此操作; rpaf 没有得到可靠的维护,可能会导致问题。
【讨论】:
【参考方案9】:从 Apache 2.4 开始,有 mod_remoteip 内置模块可以做到这一点。
启用mod_remoteip
(例如a2enmod remoteip
)
创建受信任 IP 范围的列表(您接受远程 IP 标头的 IP)。你可以把它们放在像conf/trusted-ranges.txt
这样的文件中
将此行添加到 Apache 配置中:
RemoteIPTrustedProxyList conf/trusted-ranges.txt
更改您的日志文件格式以使用 %a
而不是 %h
来记录客户端 IP。
对于 Cloudflare,您需要信任他们的所有 IP 范围并使用自定义标头 CF-Connecting-IP
:
RemoteIPHeader CF-Connecting-IP
您可以像这样获得 Cloudflare 范围:
curl https://www.cloudflare.com/ips-v4 > trusted-ranges.txt
curl https://www.cloudflare.com/ips-v6 >> trusted-ranges.txt
【讨论】:
以上是关于在 apache 中将 REMOTE_ADDR 设置为 X-Forwarded-For的主要内容,如果未能解决你的问题,请参考以下文章