Configuring Pound with SSL Support

Problem

You want to secure HTTP traffic to and from your Rails application using Secure Sockets Layer (SSL). Specifically, you want to use SSL with a cluster of Mongrel servers.

Solution

Use Pound to handle HTTPS requests, decrypting and passing them back to your Mongrel cluster as plain HTTP.

For Pound to handle HTTPS requests, you have configure it with SSL support at build-time. Do this by passing the --with-ssl option to configure, supplying the location of your OpenSSL header files (e.g., /usr/include/openssl).

$ cd /usr/local/src/Pound-2.0
$ ./configure --with-ssl=/usr/include/openssl
$ make
$ sudo make install

To verify that Pound has been built and configured successfully, you can always run:

$ pound -v -c
30/Jul/2006 22:22:10 -0700: starting...
Config file /usr/local/etc/pound.cfg is OK

Now, edit the Pound configuration file, adding a ListenHTTPS directive. Within that directive, specify port 443 and the location of your SSL certificate (e.g., /usr/local/etc/openssl/site-cert.pem).

/etc/pound/pound.cfg:

User "www-data"
Group "www-data"
LogLevel 3
Alive 30
ListenHTTPS
 Address 69.12.146.109
 Port 443
 Cert "/usr/local/etc/openssl/site-cert.pem"

 HeadRemove "X-Forwarded-Proto"
 AddHeader "X-Forwarded-Proto: https"
End Service
 BackEnd 
 Address 127.0.0.1
 Port 3303 
 End 
 BackEnd 
 Address 127.0.0.1
 Port 3304 
 End 
 Session 
 Type BASIC 
 TTL 300 
 End End
After restarting Pound, you should be able to visit your Rails application over SSL with URLs beginning with https://.

Discussion


The listener in the solution's configuration adds a header named "X-Forwarded-Proto" that indicates the original request was via HTTPS. Without this, there is no way for your Rails application to know if requests are being encrypted or not. Especially if you are processing highly sensitive information, such as credit card numbers, your actions need to be able to confirm that they are not sending and receiving this data in plain text, over the network.
By adding the "X-Forwarded-Proto: https" header to requests being passed to the Mongrel servers, you can use the Request#ssl? method to test for SSL. For example, the following call in one of your views will confirm that Pound is communicating with external clients via HTTPS:
ssl? <%= request.ssl? %>

See Also