WordPress SSL Offloading

Understanding what’s happening

When your page is accessed over HTTPS, but the Load Balancer is performing SSL offloading and actually requesting your content on the non-SSL port 80, the webserver, PHP, or anything else for that matter, does not understand or see that it’s being accessed over https://.

The fix for this, is that Load Balancer sends the de-facto standard X-Forwareded-Proto HTTP header, which we can use to figure out which protocol the client is actually using on the other side of the Load Balancer.

With Apache 2.2, you could use something along the lines of:

<IfModule mod_setenvif.c>

SetEnvIf X-Forwarded-Proto “^https$” HTTPS

</IfModule>

This simply reads the X-Forwared-Proto header, and if it equals https then, sets the HTTPS environment variable to 1. PHP will see this environment variable, and eventually it will become $_SERVER[‘HTTPS’] that equals 1 — just like it would be for a “real” native SSL request.

The solution

Websites behind load balancers or reverse proxies that support HTTP_X_FORWARDED_PROTO can be fixed by adding the following code to the wp-config.php file

if ($_SERVER[‘HTTP_X_FORWARDED_PROTO’] == ‘https’)

$_SERVER[‘HTTPS’]=’on’;

Then to redirect any http requests to https, we need to define the following In the .htaccess file:

<IfModule mod_rewrite.c>

RewriteEngine On

RewriteCond %{HTTP:X-Forwarded-Proto} !https

RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

RewriteBase /

RewriteRule ^index\.php$ – [L]

RewriteCond %{REQUEST_FILENAME} !-f

RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule . /index.php [L]

</IfModule>

 

The important parts here are in bold. Under usual circumstances inside the .htaccess file the rewrite condition would be to check for https to be set to OFF:

RewriteCond %{HTTPS} off

When behind some forms of proxying, whereby the client is connecting via HTTPS to a proxy, load balancer, Passenger application, etc., the %{HTTPS} variable may never be on and cause a rewrite loop. This is because your application is actually receiving plain HTTP traffic even though the client and the proxy/load balancer are using HTTPS. In these cases, check the X-Forwarded-Proto header.

References:

http://stackoverflow.com/questions/452375/detecting-https-requests-in-php

http://stackoverflow.com/questions/13977851/htaccess-redirect-to-https-www