我有一个Web应用程序安装(ClockingIT),基于使用的子域名。 因为我们想要使用SSL并且没有通配符证书,所以这对我们来说不是很方便:-)所以我想到了使用Apache的mod_proxy和mod_rewritefunction。
更确切地说,我希望URL Xttps://example.com/cit/(external)显示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/
test.example.com未在DNS服务器上定义,但在/ etc / hosts中设置为映射到127.0.0.1。 如果我在服务器上执行“w3m Xttp://test.example.com:3000 /”,我会得到正确的网页。 但是,如果我在桌面浏览器上访问https://example.com/cit/ ,则无法获得正确的网页。 networking应用程序收到请求,但似乎认为请求是为example.com域,并提供默认页面,而不是预期的子域“testing”的内容。 似乎不知何故代理不传递test.example.com域,虽然根据文档它应该。 而不是RewriteRule,我也尝试了ProxyPass指令,但结果相同。
有什么我失踪?
(如果相关,ClockingIT是通过Mongrel服务的Ruby on Rails应用程序)
PS:s / Xttp / http / g – ServerFault不喜欢我使用http冒号斜线斜杠不止一次在我的问题;-)
编辑:
在使用tcpflow查看stream量数据之后,问题似乎是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
使用“telnet localhost 3000”并粘贴上面,我得到一个redirect。 如果我重复这一点,省略X-Forwarded-Host:行,我得到预期的页面。 所以我的设置实际上是工作,但ClockingIT似乎基于X-Forwarded-Host值的决定。 任何方式,我可以防止这被列入?
我被这个咬了 这是一个非常讨厌的奇怪的。
Apache的mod_proxy将头部x-forwarded-host附加到所有出站请求。 它不能被HeaderRequest unset x-forwarding-host,ProxyVia和ProxyPreseveHost禁用。 我也找不到其他的东西。
当Rails看到这个头部时,它使用它来构build任何HTTP响应的Location:头部。 作为参考,在供应商Webistrano 1.4(使用mod_proxy跳过我的应用程序)的Rails版本中,相关代码似乎在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>
看到问题? 这是PPR线..
因为Rails / ActionPack / dasFramework正在试图通过“修正”Location:头来帮助你,PPR的后半部分是不正确的:而不是匹配
Location: http://app1host.internal/redirected/path
mod_proxy会实际看到
Location: http://proxy.domain.tld/redirected/path
幸运的是,修复很容易 – 将上面的vhostconfiguration更改为:
<VirtualHost *:80> ServerName proxy.domain.tld ProxyPass /app1/ http://app1host.internal/ ProxyPassReverse /app1/ http://proxy.domain.tld/ </VirtualHost>
如果您在虚拟主机中有多个代理应用程序,请注意,您至less需要将PPR放在“位置”部分中以区分它们。
Apache 2.4和更高版本有一个指令来删除X-Forwarded- *标头。
ProxyAddHeaders off
https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxyaddheaders
你可能会发现使用ProxyPass而不是mod_rewrite来做你想做的事更容易。 它可能无法解决您的问题,但它肯定会使您的configuration文件更清洁一点:
ProxyPass / cit / http://test.example.com:3000/ ProxyPassReverse / cit / http://test.example.com:3000/
你可能想尝试使用类似tcpflow或wireshark的东西来查看Apache正在使用什么头来代理请求。
你确定ProxyPreserveHost
指令没有改变吗? 如果打开,那么来自初始请求的主机头将被保存在对后端服务器的请求中,这就是你所描述的。
看到:
http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypreservehost