2017-03-20 67 views
1

目标是在简单堆栈中包含HTTP/2支持:部署在多个EC2实例中的web应用+启用PROXY协议策略的传输级CLB(SSL :443➝TCP:80),以卸载SSL/TLS并平衡传入的HTTPS流量。 (1)地理定位逻辑的执行;(2)地理定位逻辑的执行;(2) (2)执行简单的访问控制规则;和(3)记录。所有这些功能都需要访问可靠的(即不可微不足道的)客户端IP地址。 AWS中PROXY协议的唯一替代方案是切换到应用程序级平衡并使用XFF标头提取客户端的远程IP地址。然而,这是不可接受的:任何人都可以简单地改变其IP地址,只需在传入的HTTPS请求中注入假XFF头。 AFAIK,AWS CLBs/ELBs不会注入包含客户端远程IP的标头(例如类似the True-Client-IP header in Akamai的东西)。AWS CLB/ELB + HTTP/2支持

因此,如何将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不会被公布。
  • 其他选项将由一个ELB(HTTPS➝HTTP)被替换CLB。 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方法?

回答

2

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

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

这两个数字都不正确。

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

请求示例:我注射2欺骗X-Forwarded-For头到请求,一个有2个值,一个具有1 ...这里是卷曲发:

$ 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最右边的值规已通过平衡器增加 - 这就是我跑卷曲机的IP地址,即成立传入的连接。 ¹

这就是它总是与ALB一起工作的方式。如果客户端提供了任何XFF,那么当然不会信任这些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

据我估计,这种能力需要负载均衡到一个全新的水平概念。在这里我跑卷曲机的


¹ IP地址。敏感的观察者会注意到这实际上是一个从RFC-5737的IP地址,但它在家里被报告给我的IP地址。除了消毒目的外,我没有另外更改实例所看到的请求标头。否则,在这里,原始的顺序和内容被精确地保留下来。

+0

关于XFF欺骗部分:您对此绝对正确,您的解释对于应用程序级CLB也是如此。这意味着我的问题中的PROXY协议要求并不重要(尽管我仍然喜欢传输级负载平衡的想法)。 –

+0

关于H2部分:我知道ELB在使用H2时的好处和 - 现在我知道XFF不能被欺骗 - 我同意ELBs是为了添加H2支持而保持SSL/TLS在LB中卸载的方式。就个人而言,我宁愿在传输级别的LB中进行SSL/TLS卸载,让未加密的H2到达EC2实例,但恐怕这个选项根本不存在。 –