【问题标题】:AWS CLB/ELB + HTTP/2 supportAWS CLB/ELB + HTTP/2 支持
【发布时间】:2017-08-11 17:37:54
【问题描述】:

目标是在一个简单的堆栈中包含 HTTP/2 支持:部署在多个 EC2 实例中的 Web 应用 + 启用 PROXY 协议策略的传输级 CLB (SSL:443 ➝ TCP:80) 以卸载 SSL/TLS 并平衡传入的 HTTPS 流量。

PROXY 协议的几个原因:(1)地理定位逻辑的执行; (2) 执行简单的访问控制规则; (3) 日志记录。所有这些功能都需要访问可靠(即不易伪造)的客户端 IP 地址。 AWS 中 PROXY 协议的唯一替代方案是切换到应用程序级平衡并使用 XFF 标头提取客户端的远程 IP 地址。但是这是不可接受的:任何人都可以简单地更改其 IP 地址,只需在传入的 HTTPS 请求中注入一个虚假的 XFF 标头。 AFAIK,AWS CLB/ELB 不会注入包含客户端远程 IP 的标头(例如 the True-Client-IP header in Akamai 之类的东西)。

因此,如何将 H2 支持添加到堆栈中?经过一些研究,所有可能的选择看起来都不令人满意:

  • 当前架构无效,因为 SSL/TLS 在 CLB 中终止,但 CLB 没有为 announce H2 support through ALPN 提供任何选项。

  • 使用 CLB 的替代方法是停止使用 SSL/TLS 卸载功能并将其移至 EC2 实例(即 TCP:443 ➝ TCP:443)。这样,可以在 SSL/TLS 握手期间宣布 H2 支持,但此选项需要升级 EC2 实例以支持额外的 SSL/TSL 工作负载。类似的选择:

    • TCP:443 ➝ SSL:443:类似于 TCP:443 ➝ TCP:443,但允许使用可信赖的公钥证书列表进行后端身份验证。
    • SSL:443 ➝ SSL:443:类似于 TCP:443 ➝ SSL:443 的端到端加密。不是一个真正的选项:(1)PROXY 协议是not supported for this combination(并且使用 XFF 也不是一个选项,因为这是传输级平衡); (2) 客户端 SSL/TLS 握手在 CLB 中执行,因此不会公布 H2。
  • 其他选项是将 CLB 替换为 ELB (HTTPS ➝ HTTP)。 ELB 支持 H2。但是(1)我们需要依靠 XFF 来提取客户端 IP 地址(已经解释了为什么这是一个问题); (2) ELB 和 EC2 实例之间的流量是 H1(我们想让未加密的 H2 流量到达 EC2 实例)。换句话说,这不是一个选项。

总而言之,所有选项都有问题。恕我直言,理想的解决方案是保留原始 CLB(SSL:443 ➝ TCP:80;平衡 + SSL/TLS 卸载 + PROXY 协议)并允许在 CLB 中启用策略以通过 ALPN 宣布 H2 支持。但是,恐怕这在 AWS 中是不可能的。 CLB TCP:443 ➝ TCP:443 方法的任何替代方案?

【问题讨论】:

    标签: amazon-web-services amazon-ec2 amazon-elb http2


    【解决方案1】:

    这个答案并没有提供一个出色的解决方案,因为可能没有,但我相信您对 AWS Application Load Balancer(ALB,也称为 ELB/2.0)的理解存在差距。

    任何人都可以简单地更改其 IP 地址,只需在传入的 HTTPS 请求中注入一个虚假的 XFF 标头。 AFAIK,AWS CLB/ELB 不会注入包含客户端远程 IP 的标头

    这两种情况都不正确。

    客户端的远程 IP 是 X-Forwarded-For 中最右边的 IP 地址,由平衡器发送到实例。这不能被欺骗。如果客户端在 XFF 中包含一个或多个地址,它们会被平衡器根据处理 HTTP 标头的规则(从左到右,从第一个到最后一个)标准化为单个标头,并且它们出现在实际的左侧客户端 IP。

    示例请求:我在请求中注入了两个欺骗性的 X-Forwarded-For 标头,一个带有 2 个值,一个带有 1...这是 curl 发送的内容:

    $ curl -v http://cx-xxxxxxxx-xxxx-xxxxxxxxxx.us-east-1.elb.amazonaws.com/test/dump/headers \
           -H 'X-Forwarded-For: 192.168.254.252, 10.10.10.10' \
           -H 'X-Forwarded-For: 172.16.16.16'
    * Hostname was NOT found in DNS cache
    *   Trying 52.x.x.x...
    * Connected to cx-xxxxxxxx-xxxx-xxxxxxxxxx.us-east-1.elb.amazonaws.com (52.x.x.x) port 80 (#0)
    > GET /test/dump/headers HTTP/1.1
    > User-Agent: curl/7.35.0
    > Host: cx-xxxxxxxx-xxxx-xxxxxxxxxx.us-east-1.elb.amazonaws.com
    > Accept: */*
    > X-Forwarded-For: 192.168.254.252, 10.10.10.10
    > X-Forwarded-For: 172.16.16.16
    >
    < HTTP/1.1 200 OK
    

    但这是我的实例所看到的:

    GET /test/dump/headers HTTP/1.1
    X-Forwarded-For: 192.168.254.252, 10.10.10.10, 172.16.16.16, 203.0.113.1
    X-Forwarded-Proto: http
    X-Forwarded-Port: 80
    Host: cx-xxxxxxxx-xxxx-xxxxxxxxxx.us-east-1.elb.amazonaws.com
    X-Amzn-Trace-Id: Root=1-58d0704b-557517de784f5exxxxxxxxxx
    User-Agent: curl/7.35.0
    Accept: */*
    

    我发送的标头已由平衡器标准化,X-Forwarded-For 中最右边的值已由平衡器添加——它是我运行 curl 的机器的 IP 地址,它建立了传入连接。¹

    这就是它始终与 ALB 一起工作的方式。如果客户端提供了任何 XFF,那么这些当然是不可信的(尽管您仍然应该记录或保存它们,因为如果客户端使用正确识别客户端的代理,它们可能很有用),但最后一个右边的总是外部机器的地址,从外部建立到你的 ALB 的连接。

    这是您始终解释 X-Forwarded-For: 的方式——从标题的底部,向上,然后从右到左,因为这是任何行为正常的代理(在本例中为 ALB)处理它们的方式-- 通过将其客户端的 IP 地址(从其网络堆栈报告)附加到右侧(或通过在任何其他方法之后添加额外的 X-Forwarded-For 标头 - 任何一种方式在语义上都是有效的,但 ALB 不使用后一种方法) .解析时,当您遇到第一个不属于您自己的地址时,您会停下来——这是您唯一可以信任的地址。

    此外,如果客户端在使用 http 连接时注入 X-Forwarded-Proto: https —— 试图欺骗他们在实际上没有建立与平衡器的安全连接时—— ALB 会丢弃它。实例只看到真相:X-Forwarded-Proto: http


    此外,您可能忽略了这样一个事实,即在使用 HTTP/1.1 连接到实例时,平衡器会执行其他非常有用的操作:

    您可以将 HTTP/2 与 HTTPS 侦听器一起使用。您可以使用一个 HTTP/2 连接并行发送多达 128 个请求。负载均衡器将这些请求转换为单独的 HTTP/1.1 请求,并使用循环路由算法将它们分发到目标组中的健康目标。

    http://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html

    据我估计,该功能将负载平衡的概念提升到了一个全新的水平。


    ¹ 我正在运行 curl 的机器的 IP 地址。 精明的观察者会注意到这实际上是来自 RFC-5737 的 IP 地址,但它被报告给实例作为我的家里的IP地址。除了清理目的之外,我没有以其他方式更改实例所看到的请求标头。否则,原来的顺序和内容都被精确地保留在这里了。

    【讨论】:

    • 关于 XFF 欺骗部分:您完全正确,您的解释也适用于应用程序级 CLB。这意味着我的问题中的代理协议要求并不那么重要(尽管我仍然喜欢传输级负载平衡的想法)。
    • 关于 H2 部分:我知道使用 H2 时 ELB 的好处 - 现在我知道 XFF 不能被欺骗 - 我同意 ELB 是增加 H2 支持同时保持LB 中的 SSL/TLS 卸载。就我个人而言,我更喜欢在传输级 LB 中进行 SSL/TLS 卸载,让未加密的 H2 到达 EC2 实例,但恐怕这个选项根本不存在。
    猜你喜欢
    • 2016-01-31
    • 1970-01-01
    • 2016-11-22
    • 1970-01-01
    • 2019-03-31
    • 1970-01-01
    • 2017-01-03
    • 1970-01-01
    • 2015-06-27
    相关资源
    最近更新 更多