yiisoft/proxy-middleware

1.0.2 2024-08-06 12:10 UTC

This package is auto-updated.

Last update: 2024-09-06 12:24:48 UTC


README

Yii

Yii 代理中间件


Latest Stable Version Total Downloads Build status Code Coverage Mutation testing badge static analysis type-coverage psalm-level

该包提供了与代理相关的中间件类,这些类实现了 PSR-15

对于其他杂项中间件,有一个单独的包 - Yii Middleware.

有关如何在 Yii 框架 中使用中间件的更多信息,请参阅 Yii 中间件指南.

要求

  • PHP 8.0 或更高版本。

安装

可以使用 Composer 安装此包

composer require yiisoft/proxy-middleware

通用用法

TrustedHeaderProtocolResolver

Trusted header protocol resolver 根据您信任的特殊头部(如 X-Forwarded-Proto)设置服务器请求协议。

如果您的服务器位于信任的负载均衡器或代理后面,或者代理始终自行设置特殊头部并丢弃用户提供的任何头部值,则可以使用它。

use Yiisoft\Yii\Middleware\TrustedHeaderProtocolResolver;

/**
 * @var Psr\Http\Message\ServerRequestInterface $request
 * @var Psr\Http\Server\RequestHandlerInterface $handler
 */

$middleware = new TrustedHeaderProtocolResolver();

$middleware = $middleware->withAddedProtocolHeader('x-forwarded-proto', [
    'http' => ['http'],
    'https' => ['https', 'on'],
]);
// Disable earlier settings:
$middleware = $middleware->withoutProtocolHeader('x-forwarded-proto');

$response = $middleware->process($request, $handler);

TrustedHostsNetworkResolver

扫描整个连接链,并从转发头部解析数据,考虑到信任的 IP。此外,所有项目结构都经过彻底验证,因为头部数据不可信。解析以下数据

  • IP。
  • 协议
  • 主机。
  • 端口。
  • IP 标识符 - 未知混淆。与 Forwarded RFC 头部一起使用。

典型用例是在负载均衡器后面的应用程序。

信任的 IP

连接链中的信任 IP 列表。

代理的 IP,包括 $_SERVER['REMOTE_ADDR'] 中的 IP,必须在此处指定。例如,对于 $_SERVER['REMOTE_ADDR'] 值为 18.18.18.18 和 2 个其他代理 - 2.2.2.28.8.8.8,配置将是

use Yiisoft\ProxyMiddleware\TrustedHostsNetworkResolver;

/** @var TrustedHostsNetworkResolver $middleware */
$middleware = $middleware->withTrustedIps([['8.8.8.8', '2.2.2.2', '18.18.18.18']]);

IP 的顺序不重要。

转发头部组

要解析数据的头部组。通过将头部包含在此列表中,它们将自动信任。

默认值为

use Yiisoft\ProxyMiddleware\TrustedHostsNetworkResolver;

/** @var TrustedHostsNetworkResolver $middleware */
$middleware = $middleware->withForwardedHeaderGroups([    
    TrustedHostsNetworkResolver::FORWARDED_HEADER_GROUP_RFC,
    TrustedHostsNetworkResolver::FORWARDED_HEADER_GROUP_X_PREFIX,           
]);

这是另一种更简洁地编写此内容的途径

use Yiisoft\ProxyMiddleware\TrustedHostsNetworkResolver;

/** @var TrustedHostsNetworkResolver $middleware */
$middleware = $middleware->withForwardedHeaderGroups([    
    'forwarded',
    [
        'ip' => 'x-forwarded-for',
        'protocol' => 'x-forwarded-proto',
        'host' => 'x-forwarded-host',
        'port' => 'x-forwarded-port',    
    ],           
]);

接受的值是

  • TrustedHostsNetworkResolver::FORWARDED_HEADER_GROUP_RFC 字符串常量。根据 RFC 7239 解析单个 Forwarded 头部中的所有数据。
  • 数组。从具有 "X" 前缀的单独转发头部解析数据。与 RFC 变体不同,每个头部只存储一个数据单元(例如,IP)。带有 "X" 前缀的头部相当常见,尽管是非标准的

将按定义的顺序处理头部组。如果包含 IP 的头部存在且非空,则选择此组,并忽略后续组。

您可以为自定义头部添加支持或更改优先级

use Yiisoft\ProxyMiddleware\TrustedHostsNetworkResolver;

/** @var TrustedHostsNetworkResolver $middleware */
$middleware = $middleware->withForwardedHeaderGroups([    
    [
        'ip' => 'y-forwarded-for',
        'protocol' => 'y-forwarded-proto',
        'host' => 'y-forwarded-host',
        'port' => 'y-forwarded-port',    
    ],
    TrustedHostsNetworkResolver::FORWARDED_HEADER_GROUP_X_PREFIX,    
    TrustedHostsNetworkResolver::FORWARDED_HEADER_GROUP_RFC,               
]);

对于协议,也可以通过映射解决非标准值。

use Yiisoft\ProxyMiddleware\TrustedHostsNetworkResolver;

/** @var TrustedHostsNetworkResolver $middleware */
$middleware = $middleware->withForwardedHeaderGroups([
    TrustedHostsNetworkResolver::FORWARDED_HEADER_GROUP_RFC,    
    [
        'ip' => 'y-forwarded-for',
        'protocol' => [
            'front-end-https', 
            ['on' => 'https'],
        ],
        'host' => 'y-forwarded-host',
        'port' => 'y-forwarded-port',    
    ],
    TrustedHostsNetworkResolver::FORWARDED_HEADER_GROUP_X_PREFIX,               
]);

或者通过可调用。

use Yiisoft\ProxyMiddleware\TrustedHostsNetworkResolver;

/** @var TrustedHostsNetworkResolver $middleware */
$middleware = $middleware->withForwardedHeaderGroups([
    TrustedHostsNetworkResolver::FORWARDED_HEADER_GROUP_RFC,    
    [
        'ip' => 'y-forwarded-for',
        'protocol' => [
            'front-end-https', 
            static fn (string $protocol): ?string => $protocol === 'On' ? 'https': 'http',,
        ],
        'host' => 'y-forwarded-host',
        'port' => 'y-forwarded-port',    
    ],
    TrustedHostsNetworkResolver::FORWARDED_HEADER_GROUP_X_PREFIX,               
]);

限制默认头部组仅限于数据的有保证来源也是一个好主意。

use Yiisoft\ProxyMiddleware\TrustedHostsNetworkResolver;

/** @var TrustedHostsNetworkResolver $middleware */
$middleware = $middleware->withForwardedHeaderGroups([    
    TrustedHostsNetworkResolver::FORWARDED_HEADER_GROUP_RFC,           
]);

典型转发头部

与转发相关的头部列表。

默认值为

use Yiisoft\ProxyMiddleware\TrustedHostsNetworkResolver;

/** @var TrustedHostsNetworkResolver $middleware */
$middleware = $middleware->withTypicalForwardedHeaders([
    // RFC
    'forwarded',

    // "X" prefix
    'x-forwarded-for',
    'x-forwarded-host',
    'x-forwarded-proto',
    'x-forwarded-port',

    // Microsoft
    'front-end-https',
]);

在此列表中存在但与匹配的转发头部组中缺失的头部将被从请求中删除,因为这些头部可能不安全,并且很可能没有被代理服务器传递。

例如,使用默认的转发头部组配置

use Yiisoft\ProxyMiddleware\TrustedHostsNetworkResolver;

/** @var TrustedHostsNetworkResolver $middleware */
$middleware = $middleware->withForwardedHeaderGroups([
    TrustedHostsNetworkResolver::FORWARDED_HEADER_GROUP_RFC,
    TrustedHostsNetworkResolver::FORWARDED_HEADER_GROUP_X_PREFIX,
]);

并且传递以下请求头部

[
    'Forwarded' => [
        'for="9.9.9.9:8013";proto=http;host=example13.com',
        'for="8.8.8.8:8012";proto=http;host=example12.com',
        'for="2.2.2.2:8011";proto=http;host=example11.com',
    ],
    'X-Forwarded-For' => 'not-secure',
    'X-Forwarded-Host' => 'not-secure',
    'X-Forwarded-Proto' => 'not-secure',
    'X-Forwarded-Port' => 'not-secure',
    'Front-End-Https' => 'not-secure',
    'Non-Forwarded' => 'not-typical',
];

中间件将从请求中删除这些头部

  • x-forwarded-for.
  • x-forwarded-host.
  • x-forwarded-proto.
  • x-forwarded-port.
  • front-end-https.

因为RFC组匹配,其余的无法信任。未声明为典型转发头部的头部将保持原样(如上例中的Non-Forwarded)。

访问解析数据

解析的IP保存到特殊的请求属性中

use Psr\Http\Message\ServerRequestInterface;

/** @var ServerRequestInterface $request */
$ip = $request->getAttribute(TrustedHostsNetworkResolver::ATTRIBUTE_REQUEST_CLIENT_IP);

还有一个额外的属性可以检索所有之前验证和信任的连接链项。这需要显式配置

use Psr\Http\Message\ServerRequestInterface;
use Yiisoft\ProxyMiddleware\TrustedHostsNetworkResolver;

/** @var TrustedHostsNetworkResolver $middleware */
$middleware = $middleware->withConnectionChainItemsAttribute('connectionChainItems');
// ...
/** @var ServerRequestInterface $request */
$connectionChainItems = $request->getAttribute('connectionChainItems');

内容示例

[
    [
        'ip' => '18.18.18.18',
        'protocol' => null,
        'host' => null,
        'port' => null,
        'ipIdentifier' => null,
    ],
    [
        'ip' => '2.2.2.2',
        'protocol' => 'http',
        'host' => 'example1.com',
        'port' => null,
        'ipIdentifier' => '_obfuscated1',
    ]
],

反向混淆IP标识符

您可以通过扩展中间件类并提供混淆IP标识符的反向混淆逻辑。

use Yiisoft\ProxyMiddleware\TrustedHostsNetworkResolver;

class MyTrustedHostsNetworkResolver extends TrustedHostsNetworkResolver
{
    protected function reverseObfuscateIpIdentifier(
        string $ipIdentifier,
        array $validatedConnectionChainItems,
        array $remainingConnectionChainItems,
        RequestInterface $request,
    ): ?array
    {
        return match ($ipIdentifier) {
            '_obfuscated1' => ['2.2.2.2', null], // Without port
            '_obfuscated2' => ['5.5.5.5', '8082'], // With port
            default => null, // Unable to resolve (default)
        };
    }
}

文档

如果您需要帮助或有任何问题,Yii 论坛是一个好去处。您还可以查看其他Yii 社区资源

许可证

Yii代理中间件是免费软件。它根据BSD许可证的条款发布。有关更多信息,请参阅LICENSE

Yii软件维护。

支持项目

Open Collective

关注更新

Official website Twitter Telegram Facebook Slack