Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convince Apache of the original client protocol

So I have a relatively straight forward server stack utilizing a SSL offloading and an HTTP load balancer. The setup looks something like this:

(client) -> (SSL offload - stud) -> (balancer - haproxy) -> (http server - apache)

My question isn't about plugging all this up. It works great, and I'm honestly blown away at how straight forward it has been to set this up. I'll also add that HTTP clients connect directly to haproxy, thereby bypassing the SSL offloaded. And for the record, there are redundant partners for each of the above pieces.

The problem is somewhat abstract. I'll start with a demonstration. The client makes a request through the setup to https://myserver.tld/scp (some headers removed to keep things clear)

GET /scp HTTP/1.1
Host: myserver.tld
(headers added by haproxy)
X-Forwarded-For: [original::client:ip]
X-Forwarded-Proto: https

And the server responds with

HTTP/1.1 301 Moved Permanently
Date: Wed, 03 Jul 2013 03:16:25 GMT
Server: Apache/2.2.15 (CentOS)
Location: http://myserver.tld/scp/
Content-Length: 344
Content-Type: text/html; charset=iso-8859-1

So Apache mod_dir is sending a redirect to the same URL with a trailing slash. It's proper to do so. That isn't the issue. The issue is that the HTTPS protocol was lost. Again, I think Apache is correct to redirect to an HTTP URL, after all, the connection it received from the aforementioned stack is a regular HTTP connection.

So from the perspective of Apache, the client requested a regular HTTP connection. The HTTPS flag is off, along with all other SSL information, because the SSL part of the session is handled by stud.

Although (inside Apache) I have a valid X-Forwarded-Proto header, I cannot find a way to tell Apache that the original client connection was HTTPS and that the directory slash redirect by mod_dir should use the https:// protocol. What am I missing?

The only thing I've come up with is to rewrite the Location header inside haproxy for the HTTPS forwarded connections to replace http:// with https://, but I really don't think that approach is very elegant. I would prefer for Apache (and (don't hurt me) PHP further down the chain) to be informed and treat the connection like a normal HTTPS connection.

Please help!

PS - I've heard it said before if you have to ask, then you're doing it wrong. Perhaps that's the root issue here, but this seems like such a simple dilemma and I feel like the only one ever to have arrived here.

like image 717
greezybacon Avatar asked Jul 03 '13 03:07

greezybacon


1 Answers

You can do this by including the protocol in the ServerName directive:

ServerName https://my-server-name

According to the Apache docs:

Sometimes, the server runs behind a device that processes SSL, such as a reverse proxy, load balancer or SSL offload appliance. When this is the case, specify the https:// scheme and the port number to which the clients connect in the ServerName directive to make sure that the server generates the correct self-referential URLs.

like image 112
JW. Avatar answered Sep 30 '22 20:09

JW.