我正在将 Apache2 设置为远程站点的反向代理。假设远程站点是http://app.remotesite.com。这是我的虚拟主机配置的一个片段:
ProxyPass /pxy/ http://app.remotesite.com/
因此这应该接受如下请求http://app.mysite.com/pxy/search?q=abc,并将其传递为http://app.remotesite.com/search?q=abc。
当我尝试这个时,我得到了一个“错误请求”。根据 /var/log/apache2/error.log 中的输出,它正确地执行了代理,但当它连接到远程站点时,它似乎使用其 IP 地址进行连接。如果我获取该 IP 地址(打印在 error.log 中)并使用它发出请求,例如http://[IPaddress]/search?q=abc,我得到了同样的“错误请求”错误。我的假设是远程站点依赖主机名来正确处理请求,但 mod_proxy 没有发送它。我知道 ProxyPreserveHost 设置,但这是为了在代理请求中保留原始主机名(在本例中为 app.mysite.com),这不是我想要的。
有人能建议我强制 mod_proxy 在请求中使用远程站点的主机名吗?或者,如果我的假设不合理,请指出可能还有哪些地方出了问题?
答案1
您的假设可能不正确。 mod_proxy
使用您在代理 URL 中提供的主机名进行连接。
如果您http://app.remotesite.com/search?q=abc
在命令行上使用发出请求curl
,您会得到预期的响应吗?如果是这样,那么一个好的起点是查看 curl 生成的请求与mod_proxy
发送的请求之间的差异。
要查看curl
正在执行的操作,您可以使用以下--trace-ascii <file>
选项,如下所示:
curl --trace-ascii trace.out http://app.remotesite.com/search?q=abc
这将产生trace.out
如下输出:
== Info: About to connect() to google.com port 80 (#0)
== Info: Trying 74.125.228.8... == Info: connected
== Info: Connected to google.com (74.125.228.8) port 80 (#0)
=> Send header, 165 bytes (0xa5)
0000: GET / HTTP/1.1
0010: User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7
0050: NSS/3.13.1.0 zlib/1.2.3 libidn/1.18 libssh2/1.2.2
0084: Host: google.com
0096: Accept: */*
00a3:
从 Apache 获取相同的信息有点棘手;我会使用tcpdump
,这是一个数据包捕获工具。开始捕获数据包,如下所示:
tcpdump -w packets -s 1500 port 80 and host app.remotesite.com
当 tcpdump 运行时,从浏览器(或 curl 或其他)发出请求,使用 停止tcpdump
,^C
然后像这样检查文件:
strings packets
这将给你类似这样的结果:
{GET / HTTP/1.1
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.13.1.0 zlib/1.2.3 libidn/1.18 libssh2/1.2.2
Host: google.com
Accept: */*
这将显示所请求的 URL、Host:
标头和其他有用信息。查看它的外观,如果您没有发现任何明显的问题,请返回此处。