Stunnel

Some protocols, such as LDAP or Telnet, do not support encryption. Even if the protocol can be encrypted, it may not be supported by a client or a server. Data is sent in clear text and can be seen by malicious users.

Stunnel can fix this issue and offer encryption for all protocols based on TCP. It cannot be used for protocols that use port redirection (such as Oracle TNS or clamav [see Chapter 16]) or that use both a control channel and data channel (such as FTP, which uses TCP ports 21 and 20).

Stunnel does not directly encrypt traffic—rather, it relies the OpenSSL libraries. It can be used in four modes:

Client encryption

Stunnel runs on the client that does not support encryption natively. The traffic is encrypted by Stunnel to a server that supports SSL encryption.

Server encryption

If the client supports encryption, but the server does not, Stunnel can decrypt the incoming encrypted traffic before it reaches the server application.

Client and server encryption

If neither server or client support encryption, Stunnel can run on both ends to encrypt and decrypt traffic.

Transparent proxy

Unencrypted traffic can be intercepted, encrypted, and forwarded to a server that supports encryption or that also runs Stunnel. It is transparent to the client. Such a proxy can be placed at the edge of the network to ensure that all traffic leaving the local network for the Internet is encrypted.

In addition to Unix platforms, Stunnel works on Windows. It can be downloaded from the official Stunnel web site at http://www.stunnel.org. It comes with OpenSSL and works as is for testing purpose. It can also be run as a Windows Service.

Application layer encryption includes both SSL and TLS. The latest versions are respectively SSL 3.0 and TLS 1.0. TLS is an extension to SSL 3.0 and was created to become a standard. In the real world, SSL is used more often than TLS. The main use case for TLS is SMTP with encryption. The major difference between the two protocols is the ability of TLS to negotiate encryption in band. Therefore, you will mostly encounter SSL support on a different port number (i.e., POP3 on port 110 but SSL POP3 on port 995) while TLS would encrypt the traffic using the same port as the regular service (TLS SMTP on port 25).

Since Stunnel uses SSL, an X.509 certificate (see the earlier section "X.509 Certificate") is required. You can create your own certificate. The first step is to generate keys. For example, you can create a 1024-byte RSA key:

[julien@asus ˜]$ openssl genrsa -des3 -out server.key 1024
Generating RSA private key, 1024 bit long modulus ......
..............++++++ .++++++ e is 65537 (0x10001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:

The passphrase is used to encrypt the private key. This means that every time Stunnel is launched, the passphrase must be typed manually. It is possible to remove the 3DES encryption to not encrypt the private key with a passphrase:

[julien@asus ˜]$ openssl genrsa -out server.key 1024
Generating RSA private key, 1024 bit long modulus .........
...........++++++ .++++++ e is 65537 (0x10001)

You can then create a Certificate Signing Request (CSR) with this key. You can think about it as an unsigned and uncertified X.509 certificate. It contains your public key and the public information that is available on the final certificate:

[julien@asus ˜]$ openssl req -new -key server.key -out server.csr
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----

The following information will be part of your final certificate:

Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:California
Locality Name (eg, city) []:San Jose
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Domain.com
Organizational Unit Name (eg, section) []:Website
Common Name (eg, YOUR name) []:www.domain.com
email Address []:webmaster@domain.com
Please enter the following 'extra' attributes to be sent with your
certificate request A challenge password []:
An optional company name []:

Warning

The common name is very important. It must match the domain name accessed by the client. For example, if the certificate is issued to access https://www.domain.com, the common name must be www.domain.com. If it is used to access an SMTP server at the address http://smtp.domain.com, the common name must be smtp.domain.com.

A wildcard character can be used in the common name. A wildcard character is a special character that matches different characters; e.g., * is a valid wildcard character for a subdomain. You can use *.domain.com to obtain a certificate valid for www.domain.com, smtp.domain.com, or pop3.domain.com. You can get one certificate to cover the entire domain instead of having one different certificate for each subdomain.

The challenge password should be left blank. Having a challenge password requires you to enter it interactively whenever the certificate is used, which is not possible with Stunnel.

The CSR is generated as server.csr. It must now be signed to become a useable certificate. You can sign your own certificate yourself, but the users will be warned that the certificate is not trusted. I like to sign my certificates to test my CSR before sending them to the CA (see the earlier section "Certificate Authority" for examples of free CAs), so that I can fully test them before I pay any fee to a CA. It also allows you to test Stunnel before you receive the CA for production.

The following command creates an X.509 certificate valid for 365 days:

[julien@asus ˜]$ openssl x509 -req -days 365 -in server.csr -signkey
server.key -out sobrier.crt
Signature ok subject=/C=US/ST=California/L=San Jose/O=Julien
Sobrier/OU=Julien Sobrier/CN=*.domain.com/emailAddress=webmaster@domain.com
Getting Private key

The certificate should be renamed HASH.0, where HASH is the hash of the certificate to be used with Stunnel. You can get the hash with the following command:

[julien@asus ˜]$ openssl x509 -hash -noout -insobrier.crt
c9bc75ba

On my Linux distribution, Stunnel looks for certificates in /etc/ssl/stunnel/. You can copy your certificate into this directory. The private key needs to be copied in the same directory.

[julien@asus ˜]$ mv sobrier.crt /etc/ssl/stunnel/c9bc75ba.0
[julien@asus ˜]$ cp sobrier.key /etc/ssl/stunnel

The Windows version comes with a default certificate and key. They should be used for testing purposes only. A real certificate can be created following the same steps as above in Cygwin.

The server might support encryption, but a particular client application might not. For example, an application to fill your blog or check the changes on a web page may support HTTP, but not HTTPS (HTTP over SSL). You can run Stunnel on your machine to send encrypted traffic with the same tool. Stunnel can run on the client to encrypt data going out and to decrypt data coming in, as shown in Figure 15-17.

The default port for HTTPS is 443. On the client, we need to reserve a port to redirect all connections to this HTTPS server. We should use a port that is not used by other servers we need to access, such as 8080.

First, we need to create a configuration file to create the redirection from port 8080 to the http server www.domain.com:443:

; Client configuration file

; Global variables
client  =       yes

; Do not verify the Certificate chain
verify  =       0

; Do not fork into the bakcground
foreground =    yes

; Print all debug information into /tmp/stunnel.debug
debug   =       debug
output  =       /tmp/stunnel.debug

; Path of the certificates
CApath  =       /etc/ssl/stunnel/

; Redirection from http://localhost:8080/ to https://www.domain.com/
[https]
accept  =       8080
connect =       www.domain.com:443

; Never close the tunnel
TIMEOUTclose =  0

Tip

Stunnel 4.x requires the use of a configuration file. Previous versions can use command-line arguments to specify the redirection; this feature is no longer available.

In case the web server requires user authentication, you can add your login and password to the configuration file, which will be automatically provided by Stunnel to the server:

protocolCredentials = username:password

If you save the configuration file to /etc/ssl/stunnel/client.conf, you can run Stunnel with the following command:

[julien@asus ˜]$ stunnel /etc/ssl/stunnel/client.conf

Now, if you type the address http://localhost:8080/ in your web, you will actually access http://www.domain.com:443/. You can check the file /tmp/stunnel.debug if it does not seem to work.

Stunnel can be very useful to debug an HTTPS server. If you need to look at the headers sent by the server, you cannot capture the HTTPS traffic: everything is encrypted and you cannot see the headers. You can run Stunnel with the above configuration to look at the unencrypted server reply:

[julien@asus ˜]$ telnet localhost 8080
Trying 127.0.0.1...
Connected to asus.secteam.juniper.net (127.0.0.1).
Escape character is '^]'.
GET /index.html HTTP/1.1
Host: domain.com

HTTP/1.1 404 Not Found
Date: Mon, 21 Aug 2006 18:15:31 GMT
Server: Apache/1.3.33 Ben-SSL/1.55 (Debian GNU/Linux) mod_gzip/1.3.26.1a PHP/4.3
.10-16
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-1

11d
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>404 Not Found</TITLE>
</HEAD><BODY>
<H1>Not Found</H1>
The requested URL /index.html was not found on this server.<P>
<HR>
<ADDRESS>Apache/1.3.33 Ben-SSL/1.55 Server at domain.com Port 445</ADDRESS>
</BODY></HTML>

0"

Some people think a web server is protected because it uses SSL. Unfortunately, this is not true. Using Stunnel, any exploit that works with HTTP will work with HTTPS, as we have just seen.

Stunnel is very handy to add SSL support to existing services available on a server. If you have already installed an SMTP or HTTP server, all you need is Stunnel to add SMTPS and HTTPS without having to reconfigure these services again. For HTTPS and SMTP, the configuration file is:

; Server configuration file
; Global variables
client  =       no

; Do not verify the Certificate chain
verify  =       0

; Fork into the bakcground
foreground =    no

; Print all debug information into /tmp/stunnel.debug
debug   =       debug
output  =       /tmp/stunnel.debug

; Path of the certificate
cert  =       /etc/ssl/stunnel/server.pem

; Redirection from port 443 to 80
[https]
accept  =       443
connect =       80
TIMEOUTclose =  0

; Redirection from port 465 to 25
[smtps]
accept  =       465
connect =       25
TIMEOUTclose =  0

The certificate /etc/ssl/stunnel/server.pem should follow this format:

-----BEGIN RSA PRIVATE KEY-----
<key>
-----END RSA PRIVATE KEY-----
<empty line>
-----BEGIN CERTIFICATE-----
<certificate>
-----END CERTIFICATE-----

It can be created from the certificate and private key generated previously:

[julien@asus ˜]$ cat server.key > server.pem && echo >>
server.pem && cat sobrier.crt >> server.pem && chmod 600 server.pem

The server can be securely accessed at the address https://www.domain.com/.

On Linux, it is possible to integrate Stunnel with inetd or xinetd. This allows Stunnel to start automatically when a new connection requires a redirection. To add SMTPS to a server with an existing SMTP server, add the following line to /etc/inetd.conf:

smtps stream tcp nowait root /usr/local/sbin/stunnel /etc/ssl/stunnel/smtps.conf

For xinetd, add to the file /etc/xinetd.d/smtps:

service smtps
{
        socket_type             = stream
        wait                    = no
        log_on_success          += USERID
        log_on_failure          += USERID
        server                  = /usr/local/sbin/stunnel
        server_args               = /etc/ssl/stunnel/smtps.conf
        user                    = root
        disable                 = no
}

One configuration file must be created for each service. It is similar to the file created earlier, with two differences:

  1. The line [smtps] must be removed (or commented out with a leading ";").

  2. The name of the program to run for the given service must be added. For SMTP, add the line exec = /usr/sbin/smtpd.

It is better to run Stunnel on the command line rather than with inetd or xinet, which requires initializing SSL for every new connection. Stunnel with inetd/xinetd makes sense only for services that are rarely accessed.

If neither client nor server supports encryption, you can run Stunnel on both machines as shown in Figure 15-18. To encrypt HTTP traffic, you can run stunnel client.conf on the client and stunnel server.conf on the server.

You can also compress sent data by adding this line to both client.conf and server.conf in the global options section:

compression = zlib

Stunnel can run on separate machines as a transparent proxy, rewriting the IP address to appear as if there was a direct connection between the client and server. In this configuration, Stunnel must be installed on the gateway between the client and server. This is often used to force encryption over part of the network that is not secured. A setup similar to Figure 15-19 can be used.

On the gateway, Stunnel should use a configuration file similar to client.conf used in the earlier section "Client Encryption," with the additional line:

Transparent = yes

Warning

Transparent mode works only on Linux.