Hack 76 Encrypt and Tunnel Traffic with SSL

figs/moderate.gif figs/hack76.gif

Use stunnel to add SSL encryption to any network service.

Stunnel (http://www.stunnel.org) is a powerful and flexible program that, using SSL, encrypts traffic to and from any TCP port in several different ways. It can tunnel connections, much like SSH can, by providing a local port to connect to. It will encrypt the traffic sent to this port, forward it to a remote system, decrypt the traffic, and finally forward it to a local port on that system. Stunnel can also provide transparent SSL support for inetd-compatible services.

To install stunnel, simply run ./configure from the directory that was created when you unpacked the archive file that you downloaded. Since stunnel requires OpenSSL (http://www.openssl.org), download and install that first if it is not already installed. If you would like to compile stunnel with TCP wrappers support or install OpenSSL in a nonstandard location, you'll probably want to make use of the --with-tcp-wrappers or --with-ssl command-line options for configure.

For example, this will configure stunnel to include TCP wrapper support, using the OpenSSL installation under /opt/:

$ ./configure --with-tcp-wrappers --with-ssl=/opt/openssl

After the script runs, you'll need to run make to actually compile stunnel. You will then be prompted for information to create a self-signed certificate. Not only will this certificate be self-signed, but it is valid for only one year. If this is not what you want, you should create your own certificate and Certificate Authority [Hack #45] .

With the older 3.x versions of stunnel, it was possible to configure all options from the command line. The newer 4.x versions make use of a configuration file, stunnel.conf. A sample configuration file can usually be found in either /etc/stunnel/stunnel.conf-sample or /usr/local/etc/stunnel/stunnel.conf-sample.

Let's take a look at the basic form of a configuration file used to forward a local port to a remote port with stunnel.

The client side:

pid = 

client = yes

[<server port>]

accept = <forwarded port>

connect = <remote address>:<server port>

The server side:

cert = /etc/stunnel/stunnel.pem

pid = 

client = no

[<forwarded port>]

accept = <server port>

connect = <forwarded port>

You can use the default configuration file or choose another file. If you want to use the default configuration file, you can start stunnel without any arguments. Otherwise, you can specify the configuration file as the first argument to stunnel.

With this setup, a program will be able to connect to <forwarded port> on the client side. Then stunnel will encrypt the traffic it receives on this port and send it to <server port> on the remote system specified by <remote address>. On the remote system, stunnel will decrypt the traffic that it receives on this port and forward it to the program that is listening on <forwarded port> on the remote system.

The equivalent ssh port-forwarding command would be:

ssh -f -N -L <forwarded port>:<remote address>:<forwarded port> \

<remote address>

If you wish to specify a PID file, you can set the pid variable to whatever filename you wish. Leaving the pid variable in the configuration file without giving it a value causes stunnel to not create a PID file. However, if you leave out the pid variable completely, stunnel will try to create either /var/run/stunnel.pid or /usr/local/var/run/stunnel.pid (i.e., $prefix/var/run/stunnel.pid), depending on how you configured it at compile time.

In addition to providing SSH-style port forwarding, stunnel can also be used to add SSL capabilities to inetd-style services. This is perfect for adding SSL capabilities to email or other services that don't have native SSL functionality.

Here's an inetd.conf entry for SWAT, Samba's web-based configuration tool:

swat stream tcp nowait.400 root /usr/local/samba/bin/swat swat

To add SSL support to SWAT, you first need to create a configuration file for stunnel to use. Let's call it swat.conf and put it in /etc/stunnel:

cert = /etc/stunnel/swat.pem

exec = /usr/local/samba/bin/swat 

execargs = swat

Now modify the entry in inetd.conf to look like this:

swat stream tcp nowait.400 root /usr/sbin/stunnel stunnel \


Now you can access SWAT securely with your favorite SSL-enabled web browser.

Alternatively, you can do away with inetd altogether and have stunnel listen for connections from clients and then spawn the service process itself. To do this, create a configuration file with contents similar to this:

cert = /etc/stunnel/swat.pem


accept = 901

exec = /usr/local/samba/bin/swat

execargs = swat

Then start stunnel with the path to the configuration file:

# stunnel /etc/stunnel/swat.conf

In addition, you can start it at boot time by putting the previous command in your startup scripts (i.e., /etc/rc.local).

Stunnel is a very powerful tool: not only can it forward connections through an encrypted tunnel, but it can also be used to add SSL capabilities to common services. This is especially nice when clients with SSL support for these services already exist. Thus, you can use stunnel solely on the server side, enabling encryption for the service with no need for the client to install any extra software.