macromindonline / laravel-proxy
为Laravel设置可信代理
Requires
- php: >=5.4.0
- illuminate/contracts: ~5.0
Requires (Dev)
- illuminate/http: ~5.0
- mockery/mockery: ~0.9.3
- phpunit/phpunit: ^5.7
This package is not auto-updated.
Last update: 2024-09-20 02:46:09 UTC
README
Laravel 5.5
可信代理现在包含在Laravel 5.5中。要配置此版本的Laravel,请参阅:https://laravel.net.cn/docs/5.5/requests#configuring-trusted-proxies
Laravel 5.0 - 5.4
对于Laravel版本5.0 - 5.4,请继续阅读以下内容。
新功能包括
- 可信代理现在设置为HTTP中间件,这比之前的ServiceProvider更合理。如果你不确定这是什么意思,请记住“Just Trust Fideloper™”。
- 你现在可以设置可信头名称。这对于不使用常用
X-Forwarded-*头的代理很有用。有关示例和讨论,请参阅问题 #9和问题 #7。
要从Laravel 5项目目录运行以下命令以使用此功能
composer require fideloper/proxy
或者,当然,你可以直接编辑你的composer.json文件
{
"require": {
"fideloper/proxy": "^3.3"
}
}
Laravel 4
你仍然可以使用此包的Laravel 4版本。请参阅此存储库的最新v2标签,它与Laravel 4版本兼容。
WAT
设置可信代理允许在代理后面正确生成URL、重定向、处理会话和记录日志。
如果你的Web服务器位于负载均衡器、HTTP缓存或其他中间代理(反向代理)后面,这很有用。
TL;DR 设置
安装可信代理
$ composer require fideloper/proxy
添加服务提供商
'providers' => array( # other providers omitted 'Fideloper\Proxy\TrustedProxyServiceProvider', );
将包配置文件发布到config/trustedproxy.php
$ php artisan vendor:publish --provider="Fideloper\Proxy\TrustedProxyServiceProvider"
在文件app/Http/Kernel.php中注册HTTP中间件
protected $middleware = [ // Illuminate middlewares omitted for brevity 'Fideloper\Proxy\TrustProxies',
然后根据需要编辑已发布的配置文件config/trustedproxy.php。
以下示例将信任IP地址为192.168.10.10的代理,例如负载均衡器或Web缓存
<?php return [ 'proxies' => [ '192.168.10.10', ], // These are defaults already set in the config: 'headers' => [ (defined('Illuminate\Http\Request::HEADER_FORWARDED') ? Illuminate\Http\Request::HEADER_FORWARDED : 'forwarded') => 'FORWARDED', \Illuminate\Http\Request::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', \Illuminate\Http\Request::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', \Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', \Illuminate\Http\Request::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', ] ];
注意:如果你使用AWS Elastic Load Balancing或Heroku,FORWARDED和X_FORWARDED_HOST头应设置为null,因为目前不支持。
<?php return [ 'proxies' => [ '192.168.10.10', ], // These are defaults already set in the config: 'headers' => [ (defined('Illuminate\Http\Request::HEADER_FORWARDED') ? Illuminate\Http\Request::HEADER_FORWARDED : 'forwarded') => null, \Illuminate\Http\Request::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', \Illuminate\Http\Request::HEADER_CLIENT_HOST => null, \Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', \Illuminate\Http\Request::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', ] ];
这是做什么的?
如果你的网站位于负载均衡器、网关缓存或其他“反向代理”后面,每个Web请求都可能看起来总是来自那个代理,而不是客户端实际在网站上发起请求。
为了解决这个问题,此包允许你利用Symfony对代理的了解。关于“可信代理”的更多解释,请参阅以下内容。
稍长的安装说明
安装类似于Laravel 5包的典型安装
- 安装包
- 添加服务提供商
- 发布配置文件
- 添加中间件
- 配置你的可信代理
安装包
此包位于Packagist中,因此可以通过Composer轻松安装
方法一
$ composer require fideloper/proxy
方法二
{
"require": {
"fideloper/proxy": "^3.3"
}
}
添加后,运行$ composer update以下载文件。
如果你想开发这个,你需要dev依赖项,你可以通过在
composer require命令中添加--dev标志来获取这些依赖项。
添加服务提供商
安装的下一步是添加服务提供商。
编辑config/app.php并添加提供的Service Provider
'providers' => array( # other providers omitted Fideloper\Proxy\TrustedProxyServiceProvider::class, );
发布配置文件
此包期望配置文件trustedproxy.php位于/config/trustedproxy.php。你可以通过使用新的Laravel 5 artisan命令复制包配置文件来完成此操作
$ php artisan vendor:publish --provider="Fideloper\Proxy\TrustedProxyServiceProvider"
完成之后,将有一个新的配置文件在config/trustedproxy.php中等待编辑。
注册中间件
编辑 app/Http/Kernel.php 并添加提供的中间件
protected $middleware = [ // Illuminate middlewares omitted for brevity 'Fideloper\Proxy\TrustProxies',
配置受信任的代理
编辑新发布的 config/trustedproxy.php
<?php return [ /* * Set trusted proxy IP addresses. * * Both IPv4 and IPv6 addresses are * supported, along with CIDR notation. * * The "*" character is syntactic sugar * within TrustedProxy to trust any proxy * that connects directly to your server, * a requirement when you cannot know the address * of your proxy (e.g. if using Rackspace balancers). * * The "**" character is syntactic sugar within * TrustedProxy to trust not just any proxy that * connects directly to your server, but also * proxies that connect to those proxies, and all * the way back until you reach the original source * IP. It will mean that $request->getClientIp() * always gets the originating client IP, no matter * how many proxies that client's request has * subsequently passed through. */ 'proxies' => [ '192.168.1.10', ], /* * Or, to trust all proxies that connect * directly to your server, uncomment this: */ # 'proxies' => '*', /* * Or, to trust ALL proxies, including those that * are in a chain of forwarding, uncomment this: */ # 'proxies' => '**', /* * Default Header Names * * Change these if the proxy does * not send the default header names. * * Note that headers such as X-Forwarded-For * are transformed to HTTP_X_FORWARDED_FOR format. * * The following are Symfony defaults, found in * \Symfony\Component\HttpFoundation\Request::$trustedHeaders * * You may optionally set headers to 'null' here if you'd like * for them to be considered untrusted instead. Ex: * * Illuminate\Http\Request::HEADER_CLIENT_HOST => null, * * WARNING: If you're using AWS Elastic Load Balancing or Heroku, * the FORWARDED and X_FORWARDED_HOST headers should be set to null * as they are currently unsupported there. */ 'headers' => [ (defined('Illuminate\Http\Request::HEADER_FORWARDED') ? Illuminate\Http\Request::HEADER_FORWARDED : 'forwarded') => 'FORWARDED', Illuminate\Http\Request::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', Illuminate\Http\Request::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', Illuminate\Http\Request::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', ] ];
在上述示例中,我们假设我们有一个位于 192.168.1.10 的负载均衡器或其他代理。
注意:如果您使用Rackspace、Amazon AWS或其他PaaS“云”服务,这些服务提供负载均衡器,负载均衡器的IP地址可能未知。这意味着需要信任所有IP地址。
在这种情况下,可以将'proxies'变量设置为'*'
<?php return [ 'proxies' => '*', ];
使用*将告诉Laravel信任所有IP地址作为代理。
但是,如果您处于以下情况,例如,您有一个内容分发网络(如Amazon CloudFront)将其传递给负载均衡器(如Amazon ELB),那么您可能最终会有一系列未知的代理从一端转发到另一端。在这种情况下,上面的'*'只会匹配最终的代理(在本例中是负载均衡器),这意味着调用$request->getClientIp()将返回下一行代理的IP地址(在本例中是内容分发网络的一个IP地址),而不是原始客户端IP地址。要始终获取原始客户端IP地址,您需要信任请求路由中的所有代理。您可以通过以下方式做到这一点
在这种情况下,可以将'proxies'变量设置为'':**
<?php return [ 'proxies' => '**', ];
这将信任每个单独的IP地址。
更改X-Forwarded-*头名称
默认情况下,底层的Symfony Request类期望从代理发送以下头名称
- X-Forwarded-For
- X-Forwarded-Host
- X-Forwarded-Proto
- X-Forwarded-Port
某些代理可能会发送稍微不同的头。在这些情况下,您可以告诉Symfony Request类这些头的名称。
例如,HAProxy可能会发送一个X-Forwarded-Scheme头而不是X-Forwarded-Proto。我们可以通过以下配置调整Laravel(实际上是™,Symfony HTTP Request类)来修复这个问题
<?php return [ 'headers' => [ Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_SCHEME', ] ];
然后,我们的应用程序现在将知道如何处理X-Forwarded-Scheme头。
不用担心默认值是
IN_THIS_FORMAT,而我们将头设置为In-This-Format。所有这些都在底层被规范化。Symfony的HTTP类是炸裂的 💥。
某些服务不支持特定的头,因此您也可以将这些设置为null以取消信任它们。特别是,AWS ELB和Heroku不支持FORWARDED和X_FORWARDED_HOST,因此您应该将它们设置为null以防止用户欺骗受信任的IP地址。
<?php return [ 'headers' => [ (defined('Illuminate\Http\Request::HEADER_FORWARDED') ? Illuminate\Http\Request::HEADER_FORWARDED : 'forwarded') => null, \Illuminate\Http\Request::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', \Illuminate\Http\Request::HEADER_CLIENT_HOST => null, \Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', \Illuminate\Http\Request::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', ] ];
你知道CIDR吗,兄弟?
Symfony也接受用于配置受信任代理的CIDR 表示法。这意味着您可以设置受信任的代理为地址范围,如192.168.12.0/23。
这有什么意义?
如果您的网站位于负载均衡器等代理后面,您的Web应用程序可能存在以下问题
- 重定向和PHP生成的URL可能在网址、协议和/或端口方面不准确。
- 可能不会为每个用户创建唯一的会话,从而导致可能访问错误的账户,或用户无法登录。
- 日志或其他数据收集过程的数据可能看起来来自一个位置(代理本身),您无法区分单个客户端的流量/操作。
我们可以通过监听 X-Forwarded-* 标头来绕过这些问题。这些标头通常由代理添加,以便您的Web应用程序了解请求发起者的详细信息。
常见的标头包括:
- X-Forwarded-For - 客户端的IP地址
- X-Forwarded-Host - 浏览器中用于访问网站的域名
- X-Forwarded-Proto - 客户端使用的协议(http/https)
- X-Forwarded-Port - 客户端使用的端口号(通常是80或443)
Laravel使用Symfony来处理请求和响应。这些类有处理代理的能力。然而,出于安全考虑,它们必须在尝试读取X-Forwarded-*标头之前知道哪些代理是“可信的”。
Laravel默认没有提供简单的配置选项来“信任”代理。此软件包仅提供一个选项。
Symfony和Laravel中的代理
为了使Laravel能够检查转发IP地址、协议和端口,我们需要告诉Laravel我们代理的IP地址,这样应用程序就知道要“信任”它们。如果它发现收到的IP地址是可信的IP地址,它将查找X-Forwarded-*标头。否则,它将忽略。
如果我们没有告诉Laravel我们的代理(或代理)的IP地址,它将出于安全考虑而忽略它。
按服务分类的IP地址
这个维基页面列出了流行的服务及其服务器IP地址(如果可用)。欢迎更新或建议!