SSL with HAProxy and PHP: Forwarding HTTPS header.

The other day, I had to configure SSL termination on a HAProxy load balancer. The HAProxy load balancer in question was configured to receive HTTPS requests on port 443 and then forward them to one of my Nginx / PHP web servers.

SSL ends at the load balancer.

With SSL termination, the SSL connection only exists between the client and the load balancer. i.e. The secure connection ends at the load balancer. The connection between the load balancer and the web server is not secure. This means that your web server will receive the request on port 80, as per usual. Therefore, it won’t know that the client connected via HTTPS.

I needed my PHP code to be able to distinguish between regular HTTP connections and secure HTTPS connections. There was a piece of PHP code that generated URLs for links and images and it needed to know what protocol was being used.

Forwarding the header.

In my case, I had to configure HAProxy to forward a custom header if the request was being made via SSL. I did this by adding the following to my haproxy.cfg file:

option http-keep-alive
option forwardfor
http-request set-header X-Forwarded-Proto HTTPS_ON if { ssl_fc }

Above, I am forwarding a custom header called X-Forwarded-Proto if the request is being made via HTTPS. This custom header will contain the string “HTTPS_ON”.

PHP.

Then, in my PHP, I simply check to see if this header value exists in the $_SERVER array like so:

$httpProtocol = "http";
if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'HTTPS_ON'){
    $httpProtocol = 'https';
}

If it doesn’t exist, I assume that it is an insecure connection and that regular old HTTP should be used. If it does exist, then my code uses the HTTPS protocol for URLs.

Pretty simple, eh?

Hopefully, you found this post to be useful!