Posted in Security



What Does Stunnel Do?

Stunnel is a tool for creating SSL tunnels between a client and a server.

Creating SSL connections is a general task that is very useful. In particular, any packet of any protocol can always be wrapped in an additional SSL layer, with packets embedded within packets, so this means you can wrap arbitrary traffic protocols in SSL using Stunnel.

Stunnel requires a client and a server on either end of the tunnel.

This writeup assumes access to both the server and the client. If you don't have access to the client, the server certificate needs to be signed by a certificate authority that the client trusts. You can either:

  • Shell out big bucks for a certificate signed by a certificate authority company, thereby contributing to the ongoing racketeering of said companies;

  • Use a LetsEncrypt certificate, signed by a certificate authority for free; or

  • Use a self-signed certificate and install the certificate authority onto the client computer.

(These are all difficult and confusing processes, compounded by OpenSSL's lack of documentation and a proliferation of incorrect terminology. Good luck.)

How Does Stunnel Work?

The client stunnel instance will encrypt traffic, and the server stunnel instance will decrypt traffic.

When encrypting traffic, stunnel accepts incoming traffic by listening on a port (almost always a local port). It will wrap the traffic in an encrypted SSL layer (TCP wrapping) using the SSL certificate/key that is shared between the client and the server. The client then sends out the encrypted traffic over an external connection, and on to the stunnel server.

When decrypting traffic, stunnel will listen on an external connection for incoming, encrypted SSL traffic. It will use its SSL certificate/key to decrypt the traffic and unwrap the SSL layer. It will then forward this traffic on to another (usually local) port.

Stunnel flowchart schematic

Setting Up an Stunnel Server

Stunnel servers can listen on any port, and the port you choose depends on the application. The configuration we're showing here is intended to bypass a network that is tightly controlled and locked down except for HTTP and HTTPS traffic (ports 80 and 443).

Consider an example of connecting a local service on local port 8443 (not open to the outside world) to an stunnel server listening on port 443 (open to the outside world).

stunnel will listen on port 443, open to external traffic, for SSL-encrypted stunnel traffic. This means that only stunnel can listen on 443 (so this cannot be a server for an HTTPS web site - if a user points their browser to stunnel will not understand the HTTPS request and will discard it). We can use stunnel on any port that we want, but communicating between stunnel clients and servers on port 443 allows us to disguise arbitrary traffic (HTTP, HTTPS, SSH, database, etc.) as legitimate HTTPS.

This is very useful if we have a firewall that is actively inspecting the type of traffic inside of packets, and dropping packets with particular protocols like SSH or OpenVPN. By wrapping that traffic in an SSL layer, there is no way for the firewall to inspect the contents of the packet, so it just looks like ordinary HTTPS traffic. The firewall can't decrypt the packet contents, so it doesn't know if you are visiting your bank, checking your email, or sneaking SSH/OpenVPN traffic through the firewall.

(Note that other services like Iodine allow you to do similar things with other protocols, like disguising network connections using encrypted DNS on port 53.)

Typically, stunnel is forwarding that traffic on to a local port, something like 8443. (The common scenario is if you have a service only exposed to LOCAL traffic from localhost or and not bound to an EXTERNAL ip address like Resources for Stunnel Servers

The wiki has an extensive guide to setting up an Stunnel server:

The git server has several repositories with configuration files for setting up an stunnel server:

  • d-stunnel repository - repo containing Docker configuration files, for creating a Docker container that runs an stunnel server. This repository contains example stunnel configuration files for running a number of different protocols over stunnel (ssh, http, and rsync).

Setting Up an Stunnel Client

Running an stunnel client requires installing stunnel and setting up a configuration file just like if you were setting up an Stunnel/Server, except swapping the accept and connect ports, since we want the client to accept local traffic (e.g., on port 8443) and send it on to the server that it connects to with SSL (e.g., on port 443). Resources for Stunnel Clients

The wiki has an extensive guide to setting up an Stunnel client:

The git server has several repositories with configuration files for setting up an stunnel client:

Example Protocols

One of the most beautiful aspects of networking is that packets can be wrapped within other packets - so theoretically it can be packets all the way down. This allows us to use stunnel's SSL TCP wrappers to wrap just about any traffic we want. This means we can run various services (encrypted or not) through stunnel, including but not limited to:

  • SSH (secure shell)

  • SCP (secure copy)

  • OpenVPN (virtual network)

  • Rsync (file transfer)

  • MongoDB (NoSQL database)

  • Redis (local-only NoSQL database)

While stunnel has a few pre-configured services that it can deal with, users can also define their own custom protocols, over whatever port they please.

The wiki details stunnel configuration for all of the above protocols, excepting MongoDB and redis. Here are links to pages specifying how to configure stunnel for each protocol:

The Rsync over stunnel page, in particular, details the steps needed to define your own custom protocol and have stunnel wrap it in an SSL layer correctly.

Stunnel with Docker

Docker is a useful way of managing services in a self-contained and reproducible manner. Running stunnel through a Docker container is surprisingly easy: once you've installed stunnel into the docker container, you just need to map the incoming port (containing incoming encrypted traffic from the client, linked to the external network interface) to the outgoing port (containing decrypted traffic from stunnel, linked to a local-only service on a closed port).

The wiki details how to create set up SSH over stunnel at the following page: *

The git server has an stunnel docker repository with configuration files for running a Docker stunnel server, along with several example stunnel server configuration files for handling protocols like rsync, ssh, and http: * d-stunnel repository

Troubleshooting Stunnel Connections

In the d-stunnel repository is a document called that contains a number of techniques for debugging an stunnel connection.

Here is the direct link to

The techniques covered include:

  • Configuring stunnel to run in the foreground (print log messages to console instead of to log file)

  • Configuring stunnel to output debugging information

  • Poking the stunnel server with telnet

  • Inspecting open ports with nmap

  • Watching /var/log/syslog for activity

See for details.


  1. "Stunnel". wiki. 30 April 2017. <>

  2. "Category: Stunnel". wiki. 30 April 2017. <>

  3. "Stunnel/Server". wiki. 30 April 2017. <>

  4. "Stunnel/Client". wiki. 30 April 2017. <>

  5. "Stunnel/Docker". wiki. 30 April 2017. <>

  6. "Stunnel/Certificates". wiki. 30 April 2017. <>

  7. "Stunnel/Rsync". wiki. 30 April 2017. <>

  8. "Stunnel/SSH". wiki. 30 April 2017. <>

  9. "Stunnel/Scp". wiki. 30 April 2017. <>

  10. "Stunnel/OpenVPN". wiki. 30 April 2017. <>

Tags:    stunnel    SSL    encryption    SSH    networking    OpenVPN