The FreeBSD Diary

The FreeBSD Diary (TM)

Providing practical examples since 1998

If you buy from Amazon USA, please support us by using this link.
[ HOME | TOPICS | INDEX | WEB RESOURCES | BOOKS | CONTRIBUTE | SEARCH | FEEDBACK | FAQ | FORUMS ]
stunnel - encryption and security 10 March 2002
Need more help on this topic? Click here
This article has 8 comments
Show me similar articles

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.


Need more help on this topic? Click here
This article has 8 comments
Show me similar articles