stunnel – encryption and security

stunnel – encryption and security

I’m about to enter into a business relationship with a west coast hosting company. They actually
gave me the box just over two months ago, but various things have prevented us from completing the
deal. For the most part, the delay has been because of other commitments and project planning.
It’s only a matter of timing now. I will still retain a box at iStop,
but my primary websites will be moved to this new server (which is fast. VERY fast!).

I want to create a tunnel from this box to my home LAN. I will use stunnel to do that.
It was November when the first article on stunnel appeared on this website.
For more information on stunnel, please refer to Stunnel — Universal SSL Wrapper.
This tunnel will use SSL, which is a secure encrypted method for communicating between two sites. I will be using
this tunnel for my cvsup’ing my website from my cvsup server at home. But the example should provide sufficient
detail for your particular situation. If this article does not supply enough information, I urge you to read the
examples on the stunnel website.

NOTE: If you upgrade from v3 to v4, the the stunnel invocation has changed! The program no longer accepts
command-line options, but is controlled by a config file instead.
Please refer to the stunnel(8) manual page for more information.
See Upgrading to stunnel 4 for more information.

Creating the server tunnel

I started with the first stunnel article. That allowed me to install stunnel and get it running.
The latest port of stunnel will create an SSL certificate for you. This will be sufficient for most people.
The port installs the certificate to /usr/local/etc/stunnel.pem. The first step was the
install on the server. Actually, this step is the same on both client and server. I created a certificate on
both boxes, but it’s not really needed on the client. But I did it anyway.


# cd /usr/ports/security/stunnel
# make install

As mentioned previously, you will be asked to create a certificate. I just followed the prompts, and a certificate
was created. Easy.

Here is the command for starting the server side of the tunnel:


# /usr/local/sbin/stunnel -p /usr/local/etc/stunnel.pem -d 6000 -r localhost:5999

The options are:

  • -p /usr/local/etc/stunnel.pem : the private key and certificate chain PEM file.
  • -d 6000 : listen for connections on this port. This is what your client tunnel
    will connect it. It is not necessarily what your client application will connect to.
  • localhost:5999 : the host and port to which the listening connections should be redirected.
    This is where your server is actually listening. In this case, I am directing the tunnel to my local cvs
    server. You will find that number, 5999, in /etc/services, next to cvs.

The client tunnel

I followed the same instructions on the client as for the server. The client tunnel is created this way:


$ /usr/local/sbin/stunnel -c -d localhost:5999 -r cvsup.example.org:6000

These client options are:

  • -c : client mode (remote service uses SSL) which indicates we are the client, not the server.
  • -d localhost:5999 : listen for connections on this port. This is the port that your local client
    application will connect to.
  • -r cvsup.example.org:6000 : This is the other end of the tunnel. This is what your client tunnel
    will connect to. cvsup.example.org is your server. This port number is not necessarily what
    your server will be listening too. In fact, in most cases, it’s not.

Testing the tunnel

Here’s what I did on the client:


# telnet 127.0.0.1 5999
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
OK 17 0 SNAP_16_1f CVSup server ready

Here is what I found on the server:


Mar 8 23:07:56 xeon stunnel[57784]: FD_SETSIZE=1024, file ulimit=957 -> 467 clients allowed
Mar 8 23:08:24 xeon stunnel[57784]: localhost.5999 connected from 192.168.0.91:1513

The first entry is stunnel starting up. The second command is the incoming connection.

/etc/hosts.allow is your friend

In addition to a firewall, I also make use of /etc/hosts.allow. It allows
you to restrict connections to daemons/services which are started from inetd.
If you see this message on the client, I bet you have a host.allow issue:


# telnet 127.0.0.1 5999
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.

This pretty much means you need to add an entry to your hosts.allow in order to permit your remote client
to attach. My intial thoughts were “I need to add an entry for cvs”. I was wrong. Read
Examples of TCP wrapper service names for stunnel
for details.

But your first clue is in /var/log/message. Look for this:


Mar 8 23:19:06 xeon stunnel[59154]: twist 192.168.0.91.example.org to /bin/echo "You are not welcome to use localhost.5999 from 192.168.0.91.example.org."

The clue is in bold. It is localhost.5999 which you want to add to /etc/hosts.allow.
Not cvs, or ftpd, or whatever. If you use the -D 7 option when you start the server tunnel, you can
obtain some very useful information:


Mar 8 23:25:08 xeon stunnel[59915]: Using 'localhost.5999' as tcpwrapper service name
Mar 8 23:25:08 xeon stunnel[59915]: PRNG seeded successfully
Mar 8 23:25:08 xeon stunnel[59915]: stunnel 3.22 on i386-portbld-freebsd4.5 PTHREAD+LIBWRAP with OpenSSL 0.9.6a 5 Apr 2001
Mar 8 23:25:08 xeon stunnel[59916]: FD_SETSIZE=1024, file ulimit=957 -> 467 clients allowed

In this case, the entry for /etc/hosts.allow is:


localhost.5999 : 192.168.0.91.example.org : allow

where 192.168.0.91.example.org is your client machine.

Selecting the service name

Of note is the -N option:


# /usr/local/sbin/stunnel -p /usr/local/etc/stunnel.pem -d 6000 -r localhost:5999 -N mycvsserver -D 7

which will produce:


Mar 8 23:27:45 xeon stunnel[60297]: Using 'mycvsserver' as tcpwrapper service name
Mar 8 23:27:45 xeon stunnel[60297]: PRNG seeded successfully
Mar 8 23:27:45 xeon stunnel[60297]: stunnel 3.22 on i386-portbld-freebsd4.5 PTHREAD+LIBWRAP with OpenSSL 0.9.6a 5 Apr 2001
Mar 8 23:27:45 xeon stunnel[60298]: FD_SETSIZE=1024, file ulimit=957 -> 467 clients allowed

In this case, the name of the server is mycvsserver, which can be used in /etc/hosts.allow instead of localhost:5999.

I actually haven’t used the tunnel for anything more than what you see above.

Using it for the intended purpose

The original intention of this tunnel was to allow me to use a remote cvs server but at the same time, ensure the
traffic was secure and encrypted. For the cvsup, you would specify localhost as the host
(*default host=localhost. And it just works…


$ cvsup ~/freebsddiary-supfile
Connected to localhost
Updating collection freebsddiary-www/cvs
Checkout www/.htaccess
Checkout www/about.php

[ship]

Checkout www/xfrnets.php
Checkout www/xntpd.php
Checkout www/zones.php
Finished successfully

That should get you going.

Other things to consider

In all of these examples, you’ve seen the server stunnel running as root. That does not have to be.
In fact, it is probably a good idea to not run it as root. See the -s and
-g options. When you do that, you should also change the permissions
on the .pem file.

You should also notice that the client tunel I opened was not run as root. If you leave the
tunnel around for a while, you should use another user. Perhaps one dedicated to the task of
tunnelling.

8 thoughts on “stunnel – encryption and security”

    1. You’re the one telling the story. Why use scp?

      scp is for copying files around. Not for tunnelling. I can’t issue my cvsup command and get it to use scp.

  1. OpenSSH can take advantage of port forwarding too, and does it with compression. For instance I cvsup’d over a proxied ssh session from my office through the company firewall off my home machine to the cvsup mirror with:
    ssh -C -L 5999:cvsup11.freebsd.org:5999 -N ssh-server

    Then on the computer I wanted to cvsup:
    cvsup -g -L 2 -h localhost /path/to/stable-supfile

    It just works! I can take advantage of an already installed (stronger, too) crypto program to take advantage of port forwarding.

    1. If you read elsewhere on this site, you’ll see that I did use SSH at one time. But I find stunnel better suited to my needs. ssh requires an account on the destination machine. stunnel does not.

  2. great article, but the stunnel coders went and fucked @!#$ up. Now you have to use the conf file and place your server args there, and have a seperate stunnel.conf for the client with its own args

    1. I view the configuration file as a great improvement. With it comes greatly increased flexibility. Try not to take out your frustrations at people who have done a fine job.

Leave a Comment

Scroll to Top