Drupal

Running Drupal Secure Pages behind a proxy

If you plan to use the securepages module behind a proxy that terminates SSL, there are some additional server configuration steps you need to take. In order to detect what the protocol is in use, securepages tests the value of...


This article is one of Metal Toad's Top 20 Drupal Tips. Enjoy!

If you plan to use the securepages module behind a proxy that terminates SSL, there are some additional server configuration steps you need to take.

In order to detect what the protocol is in use, securepages tests the value of $_SERVER['HTTPS']. Out of the box, this merely reflects the immediate connection to your proxy. If this protocol differs from that used by the original client, then securepages can't work (the most likely outcome is a redirect loop).

To resolve this, you'll need to ask your proxy to send the X-Forwarded-Proto header. While you're free to use any header label you choose, X-Forwarded-Proto seems to have become the de facto standard.

Configure your web server

There are several possible approaches here; which one you choose is largely a matter of taste.

Apache SetEnvIf

I personally like this approach specifically because it doesn't require any changes to the application code, and makes the SSL proxy appear completely transparent to Drupal. The SetEnvIf directive can be placed in httpd.conf, a vhost configuration file, or in your .htaccess file.

SetEnvIf X_FORWARDED_PROTO https HTTPS=on

One note of caution: environment variables set this way work fine in PHP (and therefore the Secure Pages module), but are not accessible in RewriteCond directives due to the order in which rewrites are evaluated.

Modify $_SERVER directly

This approach involves directly modifying $_SERVER['HTTPS'] in settings.php. Since this file is loaded very early in the request (during DRUPAL_BOOTSTRAP_CONFIGURATION), any changes here will kick in before securepages initializes.

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
  $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
  $_SERVER['HTTPS'] = 'on';
}

Configure your proxy

What happens next depends entirely on what proxy software you have. Here are some some hints for several popular proxies (we use f5 load balancers at Metal Toad; the others have been collected from around the web but not tested):

Amazon Elastic Load Balancer (ELB)

ELBs support X-Forwarded headers by default.

f5

Inside an iRule:

when HTTP_REQUEST {
  if {([TCP::local_port] == 80) and !( [HTTP::header "X-Forwarded-Proto"] eq "http") }{
    HTTP::header insert X-Forwarded-Proto "http"
  } elseif {([TCP::local_port] == 443) and !( [HTTP::header "X-Forwarded-Proto"] eq "https") } {
    HTTP::header insert X-Forwarded-Proto "https"
  }
}

Pound

Inside a ListenHTTP / ListenHTTPS directive:

ListenHttp
  HeadRemove "X-Forwarded-Proto"
  AddHeader "X-Forwarded-Proto: http"
  ...
ListenHttps
  HeadRemove "X-Forwarded-Proto"
  AddHeader "X-Forwarded-Proto: https"
  ...

Apache

Inside a virtual host config:

<VirtualHost default:80>
RequestHeader set X-Forwarded-Proto "http"
...
</VirtualHost>
<VirtualHost default:443>
RequestHeader set X-Forwarded-Proto "https"
...
</VirtualHost>

nginx

Inside a location directive:

proxy_set_header X-Forwarded-Proto $scheme;

A note about forged headers

When using a proxy it's generally good advice to keep your web servers firewalled from the greater internet, and make sure headers such as this can't be forged. I've attempted to give examples that always override any value set by a mischief-making client.

That said, in this particular case I don't think a forged X-Forwarded-Proto creates any new vulnerabilities. While it might at first seem to make SSL stripping easier, the unfortunate reality is that SSL stripping will succeed either way.

Similar posts

Get notified on new marketing insights

Be the first to know about new B2B SaaS Marketing insights to build or refine your marketing function with the tools and knowledge of today’s industry.