我如何检测一个TCP连接是否已经从一个SSL连接转发?

我正在处理的特定场景是尝试连接到AWS弹性负载均衡器后面的websocket连接,同时实施https / ssl而不是http / tcp。

要从http / s启用TCP / SSL升级,负载平衡器上的协议必须已设置为TCP,而不是端口80和HTTP上的HTTP,而不是443上的HTTPS,两者都转发到80端口上TCP。

但是,将协议设置为TCP / SSL的一个副作用是x-forwarded-proto头文件不再被设置,如下所示:

Amazon Elastic负载均衡器不会填充x-forward-proto头

这使得使用http / tcp到https / ssl 301来传入请求的下一个挑战有点问题,因为这通常依赖于检查x-forwarded-proto头。

关于具体情况的更多细节:存在一个Docker容器,其中运行的Meteor.js进程依次驻留在AWS Elastic Beanstalk应用程序中(默认情况下具有Nginx代理层,但这不是由于使用docker工具,只需从docker集线器中取出一个集装箱定义就可以访问),位于上述ELB之后。

最终,我会在请求通过ELB,Nginx和Docker代理层时检查我的应用程序可用的头文件,试图解决客户端提出的原始请求是以http还是https

传入https://请求标题:

 { host: 'whatever.elasticbeanstalk.com', 'x-real-ip': '999.99.99.99', 'x-forwarded-for': '999.99.99.99', 'cache-control': 'max-age=0', accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'upgrade-insecure-requests': '1', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36', 'accept-encoding': 'gzip, deflate, sdch', 'accept-language': 'en-US,en;q=0.8' } 

传入的http://请求标题:

 { host: 'whatever.elasticbeanstalk.com', 'x-real-ip': '999.99.99.99', 'x-forwarded-for': '999.99.99.99', 'cache-control': 'max-age=0', accept: 'image/webp,image/*,*/*;q=0.8', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36', 'accept-encoding': 'gzip, deflate, sdch', 'accept-language': 'en-US,en;q=0.8', 'if-none-match': '"141699-1446507991000"', 'if-modified-since': 'Mon, 02 Nov 2015 23:46:31 GMT' } 

这些看起来模糊的唯一一个是upgrade-insecure-requests头,但是基于这个

什么是“升级 – 不安全 – 请求”HTTP头?

我很确定这不是。

也许我失去了一些东西,但…

当你使用TCP时,ELB将不会注入HTTP头,例如x-forwarded-proto或x-forwarded-for。 您可以通过configuration代理协议来获得所需的内容。

如果问题实际上是“我怎样才能确保任何人通过http访问我的网站被redirect到https / ssl” (事实上​​,这是我的意思),这是可能的

  1. 设置Elastic Load Balancer将80上的HTTP转发到实例上的HTTP(而不是80上的TCP),然后将443上的HTTPS转发给80上的TCP。

  2. 在检测协议的过程中“假设HTTPS / SSL”:即检查是否存在一个x-forwarded-proto ,如果是的话,它来自一个http请求,因此是301到https。 如果一个不存在,假设它是https,不要redirect它(实际上,我觉得我不妨检查以确保在redirect之前协议是http,但在目前的设置中,我非常肯定这是唯一的情况可能会发生)。