如何检测是否已从 ssl 连接转发了 tcp 连接?

How can I detect if a tcp connection has been forwarded from a ssl connection?

我正在处理的具体情况是尝试连接到 AWS 弹性负载均衡器后面的 websocket 连接,同时强制执行 https/ssl 而不是 http/tcp。

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

但是,将协议设置为 TCP/SSL 的一个副作用是 x-forwarded-proto header 不再设置,如此处所示:

Amazon Elastic load balancer is not populating x-forwarded-proto header

这使得使用 http/tcp 到 https/ssl 对任何传入请求进行 301 处理的下一个挑战有些问题,因为这通常依赖于检查 x-forwarded-proto header。

关于具体情况的更多细节:存在一个 docker 容器,其中有一个 Meteor.js 进程 运行,它又位于 AWS Elastic 中Beanstalk 应用程序(默认情况下有一个 Nginx 代理层,但由于使用 docker 只是从 docker 集线器中提取容器定义而无法访问),它位于上述 ELB 后面。

最终,当请求通过 ELB、Nginx 和 docker 代理层时,我将检查可供我的应用程序使用的 headers,试图计算出如果客户端发出的原始请求以 http 或 https

开头

传入 https:// 请求 headers:

{
    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:// 请求 headers:

{
    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 header,但基于此

我很确定不是。

也许我遗漏了什么...

当您使用 TCP 时,ELB 不会注入 HTTP headers,例如 x-forwarded-proto 或 x-forwarded-for。您也许可以在 configuring Proxy Protocol.

之前得到您需要的东西

如果问题实际上是"How can I ensure anyone visiting my website via http is redirected to https/ssl"(事实证明这就是我的意思),这可以通过

  1. 设置 Elastic Load Balancer 将 80 上的 HTTP 转发到实例上 80 上的 HTTP(而不是像以前那样在 80 上转发 TCP),然后将 443 上的 HTTPS 转发到实例上 80 上的 TCP实例.

  2. "Assuming HTTPS/SSL" 在检测协议时:即检查是否存在x-forwarded-proto,如果存在,则来自http请求,因此301到https。如果不存在,假设它是 https,不要重定向它(实际上我觉得我最好在重定向之前检查以确保协议是 http,但在当前设置中我很确定这是唯一的情况这可能会发生)。