Apache RewriteRule代理

我有一个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