Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm setting up Apache2 as a reverse proxy for a remote site. Let's assume the remote site is Here is a snippet from my virtual host config:

ProxyPass /pxy/

So this should take a request like, and pass it through as

I am getting a "Bad request" when I try this. Based on the output in /var/log/apache2/error.log, it is doing the proxy correctly, but it looks like when it connects to the remote site it does so with its IP address. If I take that IP address (printed in error.log) and do a request with it, e.g. http://[IP address]/search?q=abc, I get the same "Bad request" error. My hypothesis is that the remote site is relying on the hostname to serve the request properly, but mod_proxy is not sending it over. I know about the ProxyPreserveHost setting, but this is for preserving the original hostname in the proxy request (in this case, which is not what I want.

Can anyone suggest a way for me to force mod_proxy to use the remote site's hostname in its request? Or, if my hypothesis does not make sense, point out what else might be going wrong?

share|improve this question
Please include the relevant parts of the access and error logs. – adaptr Apr 25 '12 at 15:46
Dumb mistake: I had ProxyPreserveHost On. The remote request was therefore going through with a hostname of Thanks to larsks for showing me how to use tcpdump, which enabled me to diagnose the problem. – jfrank Apr 25 '12 at 16:17
up vote 1 down vote accepted

Your hypothesis is probably incorrect. mod_proxy connects using the hostname you provide in the proxy URL.

If you request on the command line using curl, do you get the response you expect? If so, then a good place to start is looking at the difference between the request that curl produces vs. the request that mod_proxy is sending over.

To see what curl is doing, you can use the --trace-ascii <file> option, like this:

curl --trace-ascii trace.out

This will produce output in trace.out that looks something like:

== Info: About to connect() to port 80 (#0)
== Info:   Trying == Info: connected
== Info: Connected to ( 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/ zlib/1.2.3 libidn/1.18 libssh2/1.2.2
0084: Host:
0096: Accept: */*

Getting the same information out of Apache is a little trickier; I would use tcpdump, which is a packet capturing tool. Start capturing packets like this:

tcpdump -w packets -s 1500 port 80 and host

While tcpdump is running, make your request from a browser (or curl, or whatever), stop the tcpdump with ^C, and then examine the file like this:

strings packets

Which will get you something like:

{GET / HTTP/1.1
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/ zlib/1.2.3 libidn/1.18 libssh2/1.2.2
Accept: */*

This will show the URL being requested, the Host: header, and other useful information. See how it looks, and come back here if you don't spot something obvious.

share|improve this answer
Using curl does work, if I use the hostname, but not when I use the IP address. That is how I came to my hypothesis, since the response with curl using the IP address is the same "400" page that I get through proxying. I tried your suggestion of tcpdump (had to install binutils first) but there was no traffic reported to So my next move was to remove the "and host" from the tcpdump line, and this allowed me to figure out what was going wrong. As part of a different test, I had ProxyPreseverHost On, so the wrong host name was being sent. oooops – jfrank Apr 25 '12 at 16:14
Glad it helped! – larsks Apr 25 '12 at 16:16

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.