published on in IT scripting
tags: SSL stunnel web

Proof of Concept: Build my own Web Provider at home (III) – Stunnel

Stunnel

Please note latest versions of HAProxy can support Stunnels features with higher performance and lower complexity.

stunnel

The stunnel software is awesome. It allows you to encrypt any connection between local or remote systems. We will use it to perform the SSL Offloading for our system. This tool will take care of all the SSL encryption, releasing that burden from the web servers, because web servers are … well, web servers, not SSL managers.

We will use stunnel to:

  1. Listen for secure SSL connections on port 443 of our external IPs
  2. Manage the encryption/decryption
  3. Request (without encryption) the web page from the Web servers
  4. Send the request back to the client encrypted

 

From the Stunnel web page:

The stunnel program is designed to work as an SSL encryption wrapper between remote client and local (inetd-startable) or remote server. It can be used to add SSL functionality to commonly used inetd daemons like POP2, POP3, and IMAP servers without any changes in the programs’ code. Stunnel uses OpenSSL libraries for cryptography, so it supports whatever cryptographic algorithms you compiled into your library.

Stunnel can benefit from FIPS 140-2 certification of the OpenSSL library, as long as the building process meets its Security Policy.

Stunnel is a free software authored by Michal Trojnara. Although distributed under GNU GPL version 2 or later with OpenSSL exception, stunnel is not a community project. We retain the copyright of the source code. Please contact us for support or non-GPL licenses.

The obsolete 3.x branch is no longer maintained. Use stunnel3 perl script as a drop-in replacement for backward compatibility.

Ideally you could run your own farm of TLS/SSL Offloaders using their own hardware (in combination with a balancing  software tools like HAproxy / Wackamole / Spread  / UltraMonkey you can have your own home made High Availability Load Balancer). As mentioned before, this would allow you to release the encryption load from the Web tier.

Our certificate

But first, we need an TLS/SSL certificate. You can build your own self signed certificate (but it will generate a warnign alert as it is officially signed by a real CA) or buy one from any of the Certificates Authorities (CA).

An important concept: You can only have 1 SSL certificate per IP (in other words, you need to have as many IPs as different SSL domains you have). Why? Simple, the certificate needs to be sent as soon as the HTTP connection is established and at that point the Client still has not sent to the Server which FQDN (domain) they want to get. You have the Apache explanation here. There is a relative exception here. If you use subdomains (sub1.kus.es sub2.kus.es etc) then you can use a wild-card certificate (a cert that is valid for *.kus.es).

The tool

I recommend you to download Stunnel software from source, apply the ‘xforwaredefor’ patch from the HAproxy site and install it. Why? Because this patch will allow Stunnel to send the source IP to the next tier, in this case, to HAproxy. This is a cut&paste from the HAproxy site:

X-Forwarded-For support for Stunnel

Stunnel currently makes a perfect complement to provide SSL client-side support to HAProxy. However, since Stunnel is a proxy an has no knowledge of HTTP, the client’s IP address was lost, which is somewhat annoying. A few patches were available on the Net to add the X-Forwarded-For header, but they introduced an undesirable buffer overflow. So I took my courage and wrote a reliable and secure patch to implement this useful feature. I sent it to Stunnel’s authors but got no feedback. So the patch is provided here for various versions from Stunnel-4.14 and above in the hope it will be useful to some people. At least it seems to be the case, considering the number of people who send updates 🙂 Note that this patch does not work with keep-alive, see send-proxy below for that.

Get the patches from Exceliance’s public patch repository

 The setup

Ok, now thatyou have Stunnel compiled & installed, let’s set up our stunnel instance. The following configuration file defines some basic settings for the SSL encryption: it forces Stunnel to use only ‘good’ ciphers, don’t use SSLv2, TCP timeouts, etc. I do recommend you to check the Stunnel documentation for

; Protocol version (all but not SSLv2)
sslVersion = all
options = NO_SSLv2
;PID location
pid = /var/run/stunnel4.pid
; TCP settings
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
TIMEOUTclose = 0
TIMEOUTbusy = 180
TIMEOUTconnect = 30
TIMEOUTidle = 60
;Location of the Common Authorities certificates
CApath = /etc/ssl/certs
;Logging. Set debug to 7 for debugging
debug = 0
output = /var/log/stunnel4/stunnel.log
;Use only strong ciphers
ciphers = HIGH:MEDIUM:!ADH
;libwrap = yes
;Number of sessions to manage (in concordance with the haproxy setup)
session = 300

;Specific settings for kus.es
[https-kus.es]
;Certificate files location, for automatic startup remove the passphrase from the key
cert=/etc/ssl/certs/kus.es.crt
key=/etc/ssl/certs/kus.es.key
;where lo listen, change external-ip with your real external IP
accept=external-ip:443
;where is haproxy listeing for Stunnel requests
connect=127.0.0.1:8443
;send the source IP to haproxy via the X-Forwarded-For header
xforwardedfor=yes

With this setup, you tell Stunnel to listen on the external IP of your server in the port 443 (accept=external-ip:443). Once it gets a request, it will use the certificate (cert=/etc/ssl/certs/kus.es.crt) to set up the SSL handshake and encrypt the connection and will connect to HAproxy (connect=127.0.0.1:8443) to obtain the web page the user has requested. Once it gets the page, it will be encrypted and sent back to the client.

Yes, we need to have haproxy listening on the port 8443 of the loopback interface. We will see why and how on the next chapter…

Useful commands

Remove the  passphrase from the certificate key

Careful here, if you remove the passphrase from the key, anyone with access to it maybe be able to use your certificate. If you do this, make sure  you secure the key file:

openssl rsa -in server-with-pass.key -out server-without-pass.key

From crt to pem formats (option I)

Ugly way:

openssl x509 -in input.crt -out input.der -outform DER

openssl x509 -in input.der -inform DER -out output.pem -outform PEM

From crt to pem formats (option II)

This one embeddds the key in the pem file, needed by some LB software as pound

openssl x509 -in server.crt -out server.pem

openssl rsa -in server.key >> server.pem

Compile stunnel from source

#Create a temporary directory /home/yourser/src
cd && mkdir src && cd src<br />

#Download the Stunnel source (in this case, version 4.44) and extract it
wget -c http://mirrors.zerg.biz/stunnel/archive/4.x/stunnel-4.44.tar.gz<br />
tar zxvf stunnel-4.44.tar.gz<br />

#Download the X-Forwarded-For patch and apply it
wget -c http://www.exceliance.fr/download/free/patches/stunnel/x-forwarded-for/stunnel-4.44-xforwarded-for.diff
patch -p0 < stunnel-4.44-xforwarded-for.diff

#Configure and compile it based on your needs (I like to install it in /opt)
cd stunnel-4.44
./configure --prefix=/opt/stunnel-4.44 --enable-static --with-gnu-ld --with-threads=pthread
make
sudo make install
sudo ln -s /opt/stunnel-4.44 /opt/stunnel
sudo ln -s /opt/stunnel/bin/stunnel /opt/stunnel/bin/stunnel4

Patch to modify the default’s Ubuntu startup file /etc/init.d/stunnel4

If you have patched Stunnel tool, you need to modify the startup scripts to use the new binary, that is located at /opt/stunnel/bin/stunnel4. You can directly edit your /etc/init.d/stunnel4 or you can apply this patch:

--- stunnel4.dpkg-dist	2009-12-22 08:57:08.000000000 +0100
+++ stunnel4	2011-11-22 20:11:18.000000000 +0100
@@ -11,7 +11,7 @@
 ### END INIT INFO

 DEFAULTPIDFILE="/var/run/stunnel4.pid"
-DAEMON=/usr/bin/stunnel4
+DAEMON=/opt/stunnel/bin/stunnel4
 NAME=stunnel
 DESC="SSL tunnels"
 FILES="/etc/stunnel/*.conf"

Update

Do not miss the excellent benchmark between stunnel and stud, a new and promising alternative to stunnel.

Previous: SSH

Next: HAProxy

 

comments powered by Disqus