Wednesday, February 18, 2009

SSL Offloading using Apache2 and reverse proxies

Where I work we have a decent size mod perl app which is quite heavy in memory usage...which then limits us how many apache children we can spawn before running out of memory.

So we have in place reverse proxies (squid) to handle static requests...this works great until we have to deal with SSL. So effectively as soon as someone hits SSL on a site the proxies are irrelevant, so even serving up static images ties up way too many apache children. So what to do about this?

SSL Offloading!

Now I could just purchase an expensive hardware SSL offloader...meh, so we decided to have apache2 do it.
Now what you will need is Apache 2 and mode-proxy-html + enable a few modules.
apt-get install apache2 libapache2-mod-proxy-html
a2enmod rewrite
a2enmod proxy
a2enmod proxy_html
a2enmod proxy_http
a2enmod ssl
Then we create a new virtual host in apache:
echo "Listen 443" > /etc/apache2/ports.conf
vi /etc/apache2/sites-available/ssloffloader
What we want is the following contents:

ServerAdmin some@emailaddress.com
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile /etc/apache2/ssl/somecertificate.crt
SSLCertificateKeyFile /etc/apache2/ssl/somecertificate.key
BrowserMatch ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
RewriteEngine on
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [P]

Order allow,deny
Allow from all


Replace somecert with your certificate/key
Now we need to enable the new virtualhost and restart apache to listen on port 443.
a2ensite ssloffloader
/etc/init.d/apache2 restart
With the above config what this basically does is take the request from ssl decrypt it then make a proxy request to the original host on port 80....this might sound silly at this point because port 80 would be on the same server right?....wrong.

Now lets say this is my ip layout for the servers i have:
webserver ip: 10.0.0.1
proxy ip: 10.0.0.2
ssloffloader ip: 10.0.0.3
firewall sits on 10.0.0.254

Then lets say i have www.somedomain.com pointing to 10.0.0.1

On the firewall you will need to dynamic NAT 10.0.0.1:443 to 10.0.0.3:443
so in iptables you would accomplish this by doing:
iptables -t nat -A PREROUTING -i bond0 -p tcp -d 10.0.0.1 --dport 443 -j DNAT --to 10.0.0.3:443
bond0 should be your external interface on your firewall. The firewall doesnt need to be iptables it can be any type that can do dynamic nats.

So when a request for www.somedomain.com comes in to our firewall requesting 10.0.0.1:443 the firewall nats that request to our ssl offloader on 10.0.0.3:443, which then makes a proxy request to www.somedomain.com:80 which is 10.0.0.1:80 which then returns the data to the offloader which then returns it to the firewall which then returns it to the client which is now none the wiser....(takes a breath).


Now if we want to put the squid in as a reverse proxy we need to either do more nat's or use /etc/hosts to hijack the ip for the hostname:

Nat Way:
on the ssloffloader: iptables -t nat -A PREROUTING -p tcp -d 10.0.0.1 --dport 80 -j DNAT --to 10.0.0.2:80
/etc/hosts way:
on the ssloffloader: /etc/hosts contains a line: 10.0.0.2 www.somedomain.com

Now some of you still might shudder at doing a nat like that on the firewall or you may not have that as an option.
The alternative is having the ip that the www.somedomain.com points to be on the ssloffloader, and you have to duplicate the :443 virtual host for :80, and obviously remove the ssl info on the port 80 virtual host.
You would then need to either nat from the ssl offloader to your proxy/webserver or use /etc/hosts on the ssl offloader AND the proxy as we cant rely on the dns

The other way you could do it is instead of using: RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [P]
You could change this to be: RewriteRule ^(.*)$ http://10.0.0.1/$1 [P]

The reason i DONT do this is that your making a specific request to 10.0.0.1 as the url which is bad if your using virtual hosts on your webserver.

1 comment:

  1. A similar but alternative approach I've posted on http://www.invantive.com/about-invantive/news/entryid/897/ssl-offloading-for-apache-tomcat. Good luck!

    ReplyDelete