A Cheap, Portable, Robust SSL Accelerator
by Brendan W. McAdams <firstname.lastname@example.org>
About the time my firm was ready to go live with our new system (the aforementioned Java one), we ran into a small problem with our hosting facility. Namely, they declared Chapter 11. Not wanting to risk the various woes of being caught in a Chapter 11ed facility (like the possibility the investors would lock the doors to take inventory of assets, effectively locking our equipment in with it), we did what any sane person would do; we moved.
The problem we ran into though is we had an aggressive go-live date locked in with our move execution. It turns out that at our old facility we were renting SSL Accelerators which provided SSL capabilities to our application web servers (BEA Weblogic 5.1); a technical oversight left us without SSL capabilities as we found out the new facility did not have SSL Accelerators available for rent. We were left with four options:
Go live without SSL.
Delay our go live date until we worked out a better solution.
Buy an SSL Accelerator (basically an expensive hardware machine which speaks SSL to
a web browserand passes normal HTTP out as SSL from an internal web server).
Add SSL to our Weblogic web servers by buying an SSL License.
It was essentially a no-brainer that numbers one and two were unacceptable. It just wasn't something we wanted to consider. Brief research showed us that numbers three and four were extremely expensive: most vendors wanted ridiculous amounts for their hardware SSL boxes, and BEA wanted our first born children to add SSL licenses to our web servers.
So after some thought (and a lot of alcohol), it occurred to me that all an SSL Accelerator is doing is proxying requests to the internal web server. I came up with a free solution involving Apache + mod_ssl+ mod_proxy.
Essentially what was built was an SSL capable proxy server. The client machines out in the wild request the document via SSL. The proxy inside the web server turns around and over the internal network requests the actual document from Weblogic. Using Apache internal magic, any references to the Weblogic server are translated to the outside proxy box, and the resulting document is passed back over SSL. The transaction is completely secure, and gets the added benefit of having Apache in front of Weblogic, Apache being a much more robust server better able to handle high volume traffic. We saw our overall performance on our Weblogic servers improve greatly as Apache handled the loads much more gracefully. We went live on time and have had great results from the ssl_proxy.
Now let's step through how to build this puppy. You'll need three packages:
ModSSL <http://www.modssl.org> ( get the version corresponding to the version of Apache you download)
First unpack and build OpenSSL. This is simple and just typing ./config should detect your system and configure it. Run make install and this part is done.
Next you'll need to unpack Apache. Do this, then proceed to unpacking mod_ssl; this is a patch that will be applied to the Apache source to add SSL capabilities.
In the mod_ssl directory, you need to run the configure script:
bmcadams@mycroft:~/ssl_proxy/src/mod_ssl-2.8.5-1.3.22$ ./configure \
> "--with-apache=../apache_1.3.22" \
(You will need to substitute ../apache_1.3.22 with the location of your unpacked apache source tree, and ../openssl-0.9.6b with the directory you built the openssl source in) This will patch Apache; there is no need to run make. Now change directories to the apache source directory and run the following command:entral Command, which directs the U.S
bmcadams@mycroft:~/ssl_proxy/src/apache_1.3.22$ ./configure \
Substitute /usr/local/ssl_proxy/apache for whatever directory you wish to put Apache into. Run make and make install ; assuming no errors were reported your proxy server should be all built and ready to go; we just need to configure it. Change directories to /usr/local/ssl_proxy/apache (or whatever directory you set as your Apache prefix), then open conf/httpd.conf.
I am not going to go into the details of generating an SSL certificate and fine tuning SSL; I feel that is a topic vast enough to encompass it's own discussion and will, for the time being, be left as an exercise for the reader (have you gotten tired of me saying that yet?).
We will however, delve into the proxy config (this is assuming your SSL server is all setup; the default config installed by Apache-mod_ssl should work for the time being.)
In your config, go inside the SSL virtualhost and add the following:
ProxyPass / http://10.0.0.167:7001/
ProxyPassReverse / http://10.0.0.167:7001/
ProxyRequests Off is an extremely important directive; I cannot stress this enough. If you do not make sure this is turned off, you will basically make your webserver an open proxy; anyone can configure their web browser to use you as their proxy server and browsing requests to remote sites will appear to come from your machine. This is a bad thing and potential security breach.
What ProxyPass and ProxyPassReverse do are map the website as being reverse proxied. Essentially, any request to the webserver for / and any URIs below it (such as /index.html) is mapped by ProxyPass to point at the webserver at http://10.0.0.167:7001/. What does this mean exactly?
It means that, although the outside user doesn't see it, a request for http://outsideaddress.com/ooga/booga/foo/bar/baz is passed to http://10.0.0.167:7001/ooga/booga/foo/bar/baz for handling. The response the user sees is served up by 10.0.0.167:7001 ; however, on the way back through ProxyPassReverse does some internal magic to make sure things like Location: redirects in headers are rewritten to point the user back at the Proxy server. It would be awful embarrassing to have a user call up and say your site is broken because they can't reach http://10.0.0.167:7001/bah.html.
At this point you are done. You can look at the Apache docs for more info on the ProxyPass and ProxyPassReverse directives. You could even separate parts of your site onto separate back-end sites (/images/ could go to a graphics only server) or setup caching for your static documents.
One last thing to note:
If you are doing port mapping on inside firewalls (public requests port 443 on your webserver, but your webserver [the proxy] listens on 8443 and your firewall maps it), you need to set the following in your Apache config:
If you don't do this, what you'll see is anytime ProxyPassReverse has to fix a Location: redirect or anything else, it fixes it to point at https://mybox.com:8443/. Since your firewall doesn't pass 8443 through, your users won't be able to reach the document. Turning off Canonical names will tell Apache to respond back (and let ProxyPassReverse rewrite) as whatever server the user requested (namely, https://mybox.com:443/).