我们在 ELB 后面的 EC2 上有一些 PHP 服务器。我们想通过连接到我们服务器的客户端的 IP 地址来确定区域设置/区域。问题是 PHP 服务器只能看到 ELB 的 IP 地址。我们希望看到通过 ELB 的客户端的 IP 地址。
5 回答
根据AWS 文档,ELB 应该设置保留原始客户端 IP 地址的“X-Forwarded-For”HTTP 标头:
X-Forwarded-For 请求标头可帮助您识别客户端的 IP 地址。由于负载均衡器拦截客户端和服务器之间的流量,因此您的服务器访问日志仅包含负载均衡器的 IP 地址。要查看客户端的 IP 地址,请使用 X-Forwarded-For 请求标头。
您可以使用以下 PHP 代码(假设为 apache)访问它:
$http_headers = apache_request_headers();
$original_ip = $http_headers["X-Forwarded-For"];
如果您使用 Apache,请查看mod_remoteip模块。它包含在 Apache 2.4 和更新版本中,但也可以找到 2.2 的反向移植。
该模块使用 RemoteIPHeader 指令配置的请求标头中报告的用户代理 IP 地址覆盖连接的客户端 IP 地址。
一旦按照指示替换,此覆盖的用户代理 IP 地址将用于 mod_authz_host Require ip 功能,由 mod_status 报告,并由 mod_log_config %a 和 core %a 格式字符串记录。连接的底层客户端 IP 在 %{c}a 格式字符串中可用。
换句话说,您可以设置使用哪个标头(例如 X-Forwarded-For)以及哪些 IP 是可信的(例如您的负载平衡器)。受信任的 IP 从标头中删除,第一个不受信任的 IP 用作发起客户端。这个 IP 然后被 Apache 在内部用于其他模块,例如日志记录、主机身份验证等。
这使得它比只处理 PHP 中的 XFF 标头更有用,因为 mod_remoteip 负责整个堆栈,确保您的访问日志是正确的,等等。
注意:还有一个 mod_rpaf 模块,它是这个模块的前身。它的限制要多得多。例如,它无法处理受信任的 IP 范围。你需要这个,因为你事先不知道 ELB 的 IP。它也不能处理多个跃点,例如在 Varnish 之前的 ELB,在 Apache 之前。我建议跳过 rpaf 模块并改用 remoteip。
这是一个大问题,所以试试这个:D
<?php
if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
$real_client_ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
} else {
$real_client_ip = $_SERVER["REMOTE_ADDR"];
}
对于某些人来说,mod_cloudflare 似乎是一个更好的选择——尤其是 v2.2 用户在这个小伙子的博客上阅读更多内容:http: //knowledgevoid.com/blog/2012/01/13/logging-the-correct-ip-address-using- apache-2-2-x-and-amazons-elastic-load-balancer/
AWS ELB 背后的 PHP 应用程序的最佳解决方案:
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$commaPos = strrchr($_SERVER['HTTP_X_FORWARDED_FOR'], ',');
if ($commaPos === FALSE) $remote_addr = $_SERVER['HTTP_X_FORWARDED_FOR'];
else $remote_addr = trim(substr($_SERVER['HTTP_X_FORWARDED_FOR'], $commaPos + 1));
} else {
$remote_addr = $_SERVER['REMOTE_ADDR'];
}
注意:X-Forwarded-For可以是逗号分隔的代理列表,列表中的最后一个是连接到 AWS 的 ELB 的代理,因此我们可以相信它不会被欺骗。