Rewriting URLs for X-Forwarded-Proto and Reverse Proxies

Aug 13 2012

Reverse proxies and web servers sometimes forward HTTPS traffic to their backends using HTTP. (In other words, they handle the SSL with the client, and the backend only has to handle HTTP). This can provide a speed boost, and is generally a good thing. But smart backend code may need to ensure that the remote client is only making HTTPS requests. (See this Drupal issue, which suggests that the problem impacts Drupal, and that it will not be solved in core).

Some such reverse proxies (I know of Zeus, Stackato, and Nginx) will set a special HTTP header, typically X-Forwarded-Proto or X-Forwarded_Proto. This will have the value https if the client request was over HTTPS, and http if the client used HTTP.

Here's a simple way that a backend Apache server can rewrite a client request to instruct it to only connect via HTTPS:

  RewriteEngine on

  # Rewrite to SSL for anything coming off of a proxy.
  RewriteCond %{HTTP:X-Forwarded_Proto} ^http$
  RewriteRule ^(.*) https://%{SERVER_NAME}/$1 [L,R=301]

Of course, the value may also be accessed in PHP using $_SERVER['HTTP_X_FORWARDED_PROTO']. <!--break-->