支付宝扫一扫付款
微信扫一扫付款
(微信为保护隐私,不显示你的昵称)
当你部署程序时,可能会处在一个load balancer (如,一个AWS Elastic Load Balancer) 或一个反向代理 (如,缓存 时用的Varnish) 的后面。
多半而言,这不会对Symfony引发任何问题。但是,当通过代理传入请求时,特定的请求信息是由标准的 Forwarded
头或是特殊的非标 X-Forwarded-*
头来发送的。例如,若不读取 REMOTE_ADDR
头(它现在已是你的反向代理的IP地址),用户的真实IP将被存入一个标准的 Forwarded: for="..."
头或是一个非标准的 X-Forwarded-For
头。
如果你没有配置Symfony来寻找这些头,你会得到不正确的“客户端IP地址、客户端是否通过HTTPS来连接、正在请求的hostname和端口”等信息。
这没有问题 ,但你 确实 需要告诉Symfony“发生了什么”以及“哪个反向代理IP地址”将去做这一类事:
1 2 3 4 | # app/config/config.yml
# ...
framework:
trusted_proxies: [192.0.0.1, 10.0.0.0/8] |
1 2 3 4 5 6 7 8 9 10 11 12 | <!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<framework:config trusted-proxies="192.0.0.1, 10.0.0.0/8">
<!-- ... -->
</framework>
</container> |
本例中,说你的(多个)反向代理有一个IP地址是 192.0.0.1
或者匹配了一个使用了CIDR notation 10.0.0.0/8
的IP地址范围。更多细节,参考 framework.trusted_proxies 选项。
另外还说你信任了“代理并没有发送冲突头”,如,在相同的请求中同时发送了 X-Forwarded-For
和 Forwarded
。
就是这样!Symfony现在将寻找正确的头以获取诸如“客户端IP地址、host主机、端口,以及该请求是否使用了HTTPS”等信息。
某些反向代理(如Amazon的Elastic Load Balancers)并没有静态IP地址,甚至没有你可以用CIDR注释来锁定的地址范围。这种情形,你需要 - 非常小心地 - 信任 全部 代理。
配置你的web服务器(集群)不 对 任何 load balancer以外的客户端进行响应。对于AWS来说,这可以通过 security groups来完成。
一旦你确保了流量仅能从你所信任的反向代理中获得,就要配置Symfony 始终 信任到来的请求。这可以在你的前端控制器中完成:
1 2 3 4 5 6 7 | // web/app.php
// ...
Request::setTrustedProxies(array('127.0.0.1', $request->server->get('REMOTE_ADDR')));
$response = $kernel->handle($request);
// ... |
app/config/config.yml
中的trusted_proxies选项没有设置,或令其覆写上例中的 setTrustedProxies()
调用 。就是这样!防止流量来自所有的“非信任资源”,对你来说是超严苛的。如果你允许了外部流量,它们将 “欺诈模拟” 其真实IP地址为其他信息。
许多常用的代理程序,并不支持 Forwarded
头,而且默认时不过滤它。 理想情况是,你可以在自己的代理中配置它。万一无法实现,你应该告诉Symfony不要信任 Forwarded
头,但却仍然信任你自己代理的 X-Forwarded-For
头。
这可在前端控制器里完成:
1 2 3 4 5 6 7 | // web/app.php
// ...
Request::setTrustedHeaderName(Request::HEADER_FORWARDED, null);
$response = $kernel->handle($request);
// ... |
配置代理服务器的信任(proxy server trust)非常重要,因为不这么做将允许恶意用户来"spoof"(欺诈模拟)他们的IP地址。
虽然 RFC 7239 最近定义了一个标准的 Forwarded
头以暴露全部代理信息,多数反向代理还是把信息存入非标准的 X-Forwarded-*
头里。
但如果你的反向代理使用了其他非标准的头名称,你可以配置它们 (参考 "Trusting Proxies")。
实现此功能的代码应当出现在前端控制器中 (如 web/app.php
)。
本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。