我安装了一个基于使用的子域的 Web 应用程序 (ClockingIT)。由于我们想使用 SSL 并且没有通配符证书,这对我们来说不是很方便:-) 所以我考虑使用 Apache 的 mod_proxy 和 mod_rewrite 功能。
更准确地说,我希望 URL Xttps://example.com/cit/(外部)显示 Xttp://test.example.com:3000/(内部)的内容。
这是我的设置:
<VirtualHost *:443>
ServerName example.com
(SSL setup, etc)
SSLProxyEngine On
UseCanonicalName Off
ProxyRequests Off
ProxyPreserveHost Off # or On, makes no difference
RewriteEngine On
RewriteRule ^/cit$ Xttp://test.example.com:3000/ [P,NC]
RewriteRule ^/cit/(.*)$ Xttp://test.example.com:3000/$1 [P,NC]
ProxyPassReverse /cit/ Xttp://test.example.com:3000/
Run Code Online (Sandbox Code Playgroud)
test.example.com 未在 DNS 服务器上定义,但在 /etc/hosts 中设置以映射到 127.0.0.1。如果我在服务器上执行“w3m Xttp://test.example.com:3000/”,我会得到正确的网页。但是,如果我在桌面浏览器上访问https://example.com/cit/,则无法获得正确的网页。Web 应用程序收到请求,但它似乎认为请求是针对 example.com 域的,并提供默认页面而不是预期的子域“测试”内容。似乎代理没有通过 test.example.com 域,尽管根据文档它应该。我还尝试了 ProxyPass 指令,而不是 RewriteRule,但结果相同。
有什么我想念的吗?
(如果相关,ClockingIT 是通过 Mongrel 提供的 Ruby on Rails 应用程序)
PS:s/Xttp/http/g - ServerFault 不喜欢我在我的问题中不止一次使用 http 冒号斜杠 ;-)
编辑:
使用 tcpflow 查看流量数据后,问题似乎是 Apache 将以下内容发送到端口 3000:
GET / HTTP/1.1
Host: test.example.com:3000
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
Cookie: _session_id=99f5f70d684c2186e64c5ebb8f69d574
Via: 1.1 example.com
X-Forwarded-For: 1.2.3.4
X-Forwarded-Host: example.com
X-Forwarded-Server: example.com
Run Code Online (Sandbox Code Playgroud)
使用“telnet localhost 3000”并粘贴上面的内容,我得到了一个重定向。如果我重复此操作并省略 X-Forwarded-Host: 行,我将获得预期的页面。所以我的设置实际上是有效的,但 ClockingIT 似乎基于 X-Forwarded-Host 值做出决定。有什么办法可以防止它被包括在内?
小智 6
Apache 2.4 及更高版本具有删除 X-Forwarded-* 标头的指令。
ProxyAddHeaders off
https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxyaddheaders
小智 5
我被这个咬了。这是一个非常烦人的奇怪的。
Apache 的 mod_proxy 将标题 x-forwarded-host 附加到所有出站请求。它不能被 HeaderRequest unset x-forwarded-host、ProxyVia 和 ProxyPreseveHost 禁用。也没有我能找到的任何其他东西。
当 Rails 看到该标头时,它会使用它来构造任何 HTTP 响应的 Location: 标头。作为参考,在 Rails vendor'd with Webistrano 1.4(用 mod_proxy 绊倒我的应用程序)的版本中,相关代码似乎在 vendor/rails/actionpack/lib/action_controller/cgi_process.rb 的第 88 行,里面函数 host_with_port_without_standard_port_handling。
现在看看网络上随处可见的 ProxyPass 和 ProxyPassReverse 的典型示例- 包括(基本上)您的问题和此处给出的替代答案:
<VirtualHost *:80>
ServerName proxy.domain.tld
ProxyPass /app1/ http://app1host.internal/
ProxyPassReverse /app1/ http://app1host.internal/
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)
看到问题了吗?这是PPR线..
因为 Rails/ActionPack/dasFramework 在它的智慧中试图通过“更正” Location: 标题来帮助您,所以 PPR 行的后半部分不正确:而不是匹配
Location: http://app1host.internal/redirected/path
Run Code Online (Sandbox Code Playgroud)
mod_proxy实际上会看到
Location: http://proxy.domain.tld/redirected/path
Run Code Online (Sandbox Code Playgroud)
幸运的是,修复很容易 - 将上面的 vhost 配置更改为:
<VirtualHost *:80>
ServerName proxy.domain.tld
ProxyPass /app1/ http://app1host.internal/
ProxyPassReverse /app1/ http://proxy.domain.tld/
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)
如果您在 vhost 中代理了多个应用程序,请注意您至少需要将 PPR 放在 Location 部分中以区分它们。
小智 0
您确定该ProxyPreserveHost指令没有影响吗?如果打开,初始请求中的主机标头将保留在向后端服务器发出的请求中,这就是您所描述的。
看:
http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypreservehost
| 归档时间: |
|
| 查看次数: |
16449 次 |
| 最近记录: |