13

所以我有一个使用 SSL 卸载和 HTTP 负载平衡器的相对简单的服务器堆栈。设置如下所示:

(client) -> (SSL offload - stud) -> (balancer - haproxy) -> (http server - apache)

我的问题不是要解决所有这些问题。它工作得很好,老实说,我对设置它的直接程度感到震惊。我还将添加 HTTP 客户端直接连接到 haproxy,从而绕过 SSL 卸载。并且为了记录,上述每个部分都有多余的合作伙伴。

这个问题有点抽象。我将从演示开始。客户端通过设置发出请求https://myserver.tld/scp(删除了一些标头以保持清晰)

GET /scp HTTP/1.1
Host: myserver.tld
(headers added by haproxy)
X-Forwarded-For: [original::client:ip]
X-Forwarded-Proto: https

服务器响应

HTTP/1.1 301 Moved Permanently
Date: Wed, 03 Jul 2013 03:16:25 GMT
Server: Apache/2.2.15 (CentOS)
Location: http://myserver.tld/scp/
Content-Length: 344
Content-Type: text/html; charset=iso-8859-1

因此 Apachemod_dir发送重定向到带有斜杠的相同 URL。这样做是正确的。那不是问题。问题是 HTTPS 协议丢失了。同样,我认为 Apache 重定向到 HTTP URL 是正确的,毕竟它从上述堆栈接收到的连接是常规 HTTP 连接。

所以从 Apache 的角度来看,客户端请求一个常规的 HTTP 连接。HTTPS 标志以及所有其他 SSL 信息都处于关闭状态,因为会话的 SSL 部分由 stud 处理。

尽管(在 Apache 内部)我有一个有效的X-Forwarded-Proto标头,但我找不到一种方法来告诉 Apache 原始客户端连接是 HTTPS 并且目录斜杠重定向mod_dir应该使用该https://协议。我错过了什么?

我想出的唯一方法是重写Locationhaproxy 中的标头,以替换 HTTPS 转发的连接http://https://但我真的不认为这种方法非常优雅。我希望 Apache(和(不要伤害我)PHP 更进一步)被告知并将连接视为正常的 HTTPS 连接。

请帮忙!

PS - 我之前听说过,如果你不得不问,那么你做错了。也许这就是这里的根本问题,但这似乎是一个如此简单的困境,我觉得这是唯一一个来到这里的人。

4

2 回答 2

10

您可以通过在 ServerName 指令中包含协议来做到这一点:

ServerName https://my-server-name

根据 Apache文档

有时,服务器在处理 SSL 的设备后面运行,例如反向代理、负载平衡器或 SSL 卸载设备。在这种情况下,请在 ServerName 指令中指定客户端连接的 https:// 方案和端口号,以确保服务器生成正确的自引用 URL。

于 2014-04-16T22:28:14.027 回答
9
  1. 目录斜线重定向:你想要的是mod_rewrite.

    RewriteEngine On
    RewriteCond %{HTTP:X-Forwarded-Proto} =https
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^(.+[^/])$          https://www.example.com/$1/  [R=301,L,QSA]
    

    如果标头设置为https并且请求的文件名是目录 ( -d),则重写该目录(替换example.com为您自己的域)。

  2. 至于让 PHP 将连接视为普通的 HTTPS 连接,请将环境变量设置HTTPSon

    SetEnvIf X-Forwarded-Proto https HTTPS=on
    
于 2013-11-26T12:55:18.067 回答