说服Apache的原始客户端协议

gre*_*con 11 apache ssl haproxy

所以我有一个相对直接的服务器堆栈,利用SSL卸载和HTTP负载均衡器.设置看起来像这样:

(client) -> (SSL offload - stud) -> (balancer - haproxy) -> (http server - apache)
Run Code Online (Sandbox Code Playgroud)

我的问题不是关于堵塞这一切.它运作得很好,老实说,我很清楚它是如何直接设置它的.我还要补充说,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
Run Code Online (Sandbox Code Playgroud)

并且服务器响应

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
Run Code Online (Sandbox Code Playgroud)

所以Apache mod_dir正在使用尾部斜杠向同一个URL发送重定向.这样做是正确的.那不是问题.问题是HTTPS协议丢失了.同样,我认为Apache重定向到HTTP URL是正确的,毕竟,从上述堆栈接收的连接是常规的HTTP连接.

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

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

我想出的唯一的事情就是重写Location内部HAProxy的转发的连接来取代HTTPS头http://https://,但我真的不认为这种做法是很优雅.我更喜欢Apache(并且(不要伤害我)PHP进一步向下)以获得通知并将连接视为普通的HTTPS连接.

请帮忙!

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

JW.*_*JW. 10

您可以通过在ServerName指令中包含协议来完成此操作:

ServerName https://my-server-name
Run Code Online (Sandbox Code Playgroud)

根据Apache 文档:

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

  • 如果您希望应用程序有多个入口点(其中一个是 https://,另一个是 http://),则此方法不起作用。mod_dir 将*始终*使用 ServerName 指令中指定的方案。在某些情况下,生产 URL 将具有 https:// 但内部 url(用于测试等)可能具有 http,特别是在您想要直接测试/监控 Apache 实例的 SSL/TLS 卸载情况下。现在,“非规范”URL 是否无法正确生成重定向可能并不重要,但它很混乱:/ (2认同)

小智 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]
    
    Run Code Online (Sandbox Code Playgroud)

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

  2. 至于使PHP像普通HTTPS连接一样处理连接,请将环境变量设置HTTPSon:

    SetEnvIf X-Forwarded-Proto https HTTPS=on
    
    Run Code Online (Sandbox Code Playgroud)