Score:0

Get Apache2 to also use no port for self-referencing URLs when Host header has no port

de flag

I need to install a reverse proxy in front of an Apache2 installation on a customer's server. The job of that reverse proxy is to proxy some additional applications (internally running on other ports) under subdomains, handle SSL termination and a few other things. The existing application URLs should still work, so it also has to proxy the existing Apache. That server is quite old and is running Apache 2.4.7.

My problem is this: I have set up Caddy as reverse proxy and configured it to be transparent, so the Host header is forwarded.

I then configured Apache to listen on port 81 instead of 80, so Caddy can listen on 80 instead and forward the requests to 81.

The issue is that when Apache builds a self-referencing URL, such as when redirecting to a trailing slash, then it will still include :81 in the URL (and in PHP the SERVER_PORT is also 81). I already set UseCanonicalPhysicalPort off and UseCanonicalName off, but it still happens (the hostname is correct but the port is not).

Note that if I put the reverse proxy on a non-standard port like 2015 (so Host headers will now also include :2015 at the end), then it actually works and Apache returns URLs that redirect also to 2015 (and PHP also sees SERVER_PORT as 2015 and not 81), but not if the port is 80 and therefore there is no port in the Host header. It seems that if there is no port in the Host header, Apache falls back to the physical port instead of simply also omitting the port (and reporting 80 to PHP). The docs say it should consider the port in ServerName first, but even if I add :80 at the end there, it makes no difference.

What can I do about this?

(I'm also worried what will happen with SSL later, but I'm not there yet.)


apache2ctl -S output:

VirtualHost configuration:
*:81                   localhost (/etc/apache2/apache2.conf:277)
ServerRoot: "/etc/apache2"
Main DocumentRoot: "/var/www"
Main ErrorLog: "/var/log/apache2/error.log"
Mutex watchdog-callback: using_defaults
Mutex rewrite-map: using_defaults
Mutex ssl-stapling: using_defaults
Mutex ssl-cache: using_defaults
Mutex default: dir="/var/lock/apache2" mechanism=fcntl
Mutex mpm-accept: using_defaults
PidFile: "/var/run/apache2/apache2.pid"
Define: DUMP_VHOSTS
Define: DUMP_RUN_CFG
User: name="www-data" id=33
Group: name="www-data" id=33

I have a workaround, but this is an unusual configuration which will probably trip up the next person working on this server, and I also don't usually configure things this way so I'm not sure what unexpected problems it may bring somewhere... But for what it's worth: I can set Caddy to bind only on the external IP and Apache to bind only on localhost and then have them both on port 80, but on different interfaces. Then it works. - Still, I'd like to solve the underlying problem.

ezra-s avatar
ru flag
Not sure what Caddy does is but if Apache httpd was the proxy you use ProxyPassReverse directive to catch those "backend redirects"and set the correct url to the one the client original requested (which is that in the frontend). Perhaps there is something similar in Caddy.
CherryDT avatar
de flag
I think not and unfortunately that would not solve the full problem anyway because PHP may also create such URLs and put them somewhere on the page.
ezra-s avatar
ru flag
Your opinion is fine but what you describe is typical from reverse proxies, and this is the approach to deal with internal redirects for internal urls from the reverse proxy on top.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.