Secure Communication with Stunnel
Originally published in the LinuxGazette.net, October 2004, Issue 107.1. Introduction
Stunnel is an SSL encryption wrapper that allows what are normally plain text and insecure communications to be encrypted during transmission. Stunnel recently went through some major changes and the current version (4.x) has a completely different architecture than previous versions. In this article I will be dealing exclusively with the new version.One of Stunnel's most common uses is encrypting communications between POP or IMAP mail servers and e-mail clients. Both of these protocols require users to authenticate themselves with a username and a password. In the majority of cases, these usernames and passwords are the same ones as they would use for logging into the machine locally or remotely via SSH. Without using Stunnel to encrypt this data, anyone intercepting the transmission could now log into your server and gain elevated privileges much easier than a local exploit would require.
2. Getting and Installing Stunnel
Stunnel is generally included as a precompiled package with most common distributions and is possibly already installed on your system. If not, locate the package on your distribution's installation CDs or download it from the distribution's website.The source code is released under the GNU General Public License and, as such, is freely available for download and installation. The current version (which at time of going to press was 4.05) can be downloaded from ftp://stunnel.mirt.net/stunnel/. To compile and install Stunnel, download the source code tarball from here and then execute the following commands:
$ tar zxf stunnel-4.XX.tar.gz $ cd stunnel-4.XX $ ./configure $ make $ make install (as root)
3. Generating a Self-Signed Certificate
In order to use Stunnel we must first have a certificate-key pair. If you compiled from sources then such a pair will have been created for you automatically (stunnel.pem
). Some pre-built binary packages may
include a certificate-key pair, some may generate one as part of the
installation procedure and others may leave it up to the user to generate one.
The easiest way of generating a certificate-key pair is by using a script provided with Stunnel's source code. If you're compiling from the tarball, just issue the following additional commands in the source directory:
$ cd tools $ make stunnel.pemI have decided to put the specific details outside the scope of this article, but if you are interested in the actual details then have a look at the
Makefile
in the "tools" directory.
4. Using Stunnel to Encrypt POP3/IMAP
This method can be used to encrypt any similar service where SSL-enabled clients exist and are readily available. Most e-mail clients are SSL-enabled for POP3, IMAP and SMTP, most internet clients (web browsers) are enabled for HTTPS, etc.
Once Stunnel is installed and you have generated a certificate-key pair, you are only a simple configuration file away from using Stunnel to encrypt your communications. A simple one that would encrypt POP3 and IMAP communications would be:
# Sample stunnel configuration file for POP3/IMAP # Provide the full path to your certificate-key pair file cert = /usr/local/etc/stunnel/stunnel.pem # lock the process into a chroot jail chroot = /usr/local/var/run/stunnel/ # and create the PID file in this jail pid = /stunnel.pid # change the UID and GID of the process for security reasons setuid = nobody setgid = nobody # Configure our secured POP3 and IMAP services [pop3s] accept = 995 connect = 110 [imaps] accept = 993 connect = 143
Using this configuration, any encrypted connection coming in on port 995 (POP3s) will be decrypted and forwarded to the local service (POP3) on port 110. When the local POP3 service responds, it will be encrypted by Stunnel and transmitted back through port 995. Similarly for IMAPs on port 993.
Stunnel operates as a daemon service by default, so to start it off with this configuration we can simply execute:
stunnel stunnel-secure-email.confwhere
stunnel-secure-email.conf
is the text file containing the
above configuration; ensure you change the paths so that they are correct
for your system.
We can set up Stunnel to start during boot-up by placing the appropriate
command in the rc.local
file that is usually contained in
/etc/rc.d/
. This file is the last file executed during a system
boot and it is generally used by system administrators for their own
initialisation stuff. When placing commands in this script, use fully
qualified paths such as:
/path/to/stunnel /path/to/the/configuration-fileFor Debian and similar distros without an 'rc.local', the procedure varies slightly: modify a copy of "/etc/init.d/skeleton" (named, e.g., "/etc/init.d/stunnel") to run the above and create a link to it from the appropriate runlevel (usually /etc/rc2.d/).
Stunnel can also be used with (x
)inetd
if
preferred. You can find further details in Stunnel's man page.
5. Using Stunnel to Encrypt MySQL Transactions
This method can be used to encrypt any service where neither the server nor the client are SSL-enabled. Common examples include CVS, MySQL, etc.
In the example with POP3 and IMAP above, we were only concerned with providing the server with SSL encryption as the clients generally have this built in. However, neither the standard MySQL server nor client have SSL capabilities - but we can still use Stunnel to provide this.
It involves using a Stunnel daemon on both the server's machine and the client's machine. The configuration for the server side is similar to the one we used above for POP3/IMAP. The default MySQL port is 3306, and since no port is reserved for secure MySQL connections, I will use 3307:
# Sample stunnel configuration file for securing MySQL (server side) # Provide the full path to your certificate-key pair file cert = /usr/local/etc/stunnel/stunnel.pem # lock the process into a chroot jail chroot = /usr/local/var/run/stunnel/ # and create the PID file in this jail pid = /stunnel.pid # change the UID and GID of the process for security reasons setuid = nobody setgid = nobody # Configure our secured MySQL server [mysqls] accept = 3307 connect = 3306I can now start the Stunnel daemon on the server machine with:
$ stunnel stunnel-mysql-server.confwhere
stunnel-mysql-server.conf
is a text file containing the
above configuration. We also need to set up an Stunnel daemon on the client
machine with the following configuration:
# Sample stunnel configuration file for securing MySQL (client side) # Provide the full path to your certificate-key pair file cert = /usr/local/etc/stunnel/stunnel.pem # lock the process into a chroot jail chroot = /usr/local/var/run/stunnel/ # and create the PID file in this jail pid = /stunnel.pid # change the UID and GID of the process for security reasons setuid = nobody setgid = nobody # enable client mode client = yes # Configure our secured MySQL client [mysqls] accept = 3306 connect = 1.2.3.4:3307You'll notice that I have used a new option:
client = yes
- this
enables "client mode" which lets Stunnel know that the remote service uses
SSL. Our local Stunnel daemon will now listen for connections on the local
MySQL port (3306), encrypt them and forward them to our MySQL server machine (say
1.2.3.4) where another Stunnel is listening on port 3307. The remote Stunnel
will decrypt the transmission and forward it to the MySQL server listening on
port 3306 of the same machine. All responses will be sent back through the
same encrypted channel.
Save the client configuration as stunnel-mysql-client.conf
and
start off Stunnel with:
$ stunnel stunnel-mysql-client.confand then you can connect to the remote MySQL server through the encrypted channel by connecting to the local Stunnel daemon (which is listening on MySQL's 3306 port):
$ mysql -h 127.0.0.1 -u username -p
6. Trouble Shooting
Stunnel can be a bit tricky about permissions - especially when using a chroot jail and reducing your user and group ID tonobody
(some
systems might need nogroup
for setgid
). Ensure your
chrooted directory is writable by the nobody
user and/or the
nobody
(or nogroup
) group.
Stunnel runs in the background by default and doesn't show any error
messages. This means you won't know if it worked or not from the command
line! You can check that the process is running by searching the output of
the ps
command:
$ ps -ef | grep stunnel nobody 21769 [...] /usr/local/sbin/stunnel ./stunnel-mysql-server.conf
Stunnel can also be instructed to run in the foreground by adding the following command to the configuration file (above the service configuration):
foreground = yes
As with all services, the best method of diagnosing problems is through the service's log messages. You can enable Stunnel's logging facilities by adding the following commands to the configuration file (above the service configuration):
debug = 7 output = /tmp/stunnel.log
If you are running in the foreground for testing/debugging, then you might prefer to send the log messages to standard out:
debug = 7 output = /dev/stdout
7. Further Reading/References
There are many other commands that can be used in the configuration files and these are all listed in Stunnel's man page (STUNNEL(8)
).
The following websites may also prove useful:
- The official Stunnel homepage: http://stunnel.mirt.net/
- Stunnel.org: http://www.stunnel.org/
- The OpenSSL project: http://www.openssl.org/
- SSL certificates HOWTO: http://www.tldp.org/HOWTO/SSL-Certificates-HOWTO/
As always, I appreciate any feedback on this or previous articles and suggestions/requests for future ones. You'll find my e-mail address on my contact details page.
Copyright © 2004, Barry O'Donovan. Released under the Open Publication license.