From charlesreid1

This page explains how to use stunnel in a Docker container to serve up different kinds of traffic over an encrypted SSL connection.

For passwordless SSH setup, see SSH#Passwordless Login

ssh traffic over port 443 using stunnel on docker

Let's start with an example of how to forward SSH traffic from a client to a server over stunnel.

The goal here is to be able to SSH to a local port on the client, and have that connection transparently forwarded to the server:

[client] $ ssh -p 2222 root@localhost

[server ~ via client] $ whoami

[server ~ via client] $ whoami

Set up client

Start by setting up the client. The client want s to ssh to local port 2222, so have stunnel listen for traffic on 2222. Next, we want to pass the traffic to the server using port 443, so we will use the notation <server IP>:<server port> to direct traffic to the stunnel server's port 443:

# client config,
# will ssh directly to local port 2222
# ssh -p 2222 root@localhost
# stunnel client connects to remote stunnel server at IP A.B.C.D over external port 443

output 	= /var/log/stunnel4/stunnel.log
cert 	= /etc/stunnel/stunnel.fullchain.pem
pid 	= /var/run/stunnel4/
client  = yes
accept 	= 2222
connect = A.B.C.D:443

The client will also need a copy of the server's certificate file, which can be securely copied from the server:

$ scp <server IP>:/path/to/{cert,privkey}.pem .
$ chown 600 *.pem

Then copy the .pem files to your stunnel directory.

$ # on unix:
$ cp *.pem /etc/stunnel/.

$ # on mac:
# cp *.pem /usr/local/etc/stunnel/.

Set up server

Start by setting up the server configuration file:

# server config,
# stunnel server will listen for stunnel clients connecting on port 443
# traffic will be decrypted and forwarded to local port 22

output	= /var/log/stunnel4/stunnel.log
cert	= /etc/stunnel/stunnel.fullchain.pem
key		= /etc/stunnel/stunnel.key.pem
pid		= /var/run/stunnel4/
client	= no
accept	= 443
connect =

Note that an SSH service should be listening on port 22 on the server.

Build Container

Here is the Dockerfile:

Now build:

$ docker build -t cmr_stunnel .

Run Container

Once the container is ready, we will specify two networking details (see Docker/Networking):

  • Use the host's network interface in the Docker container (this prevents the host machine from needing a dedicated listener for the Docker image on port 22 and port 443)
  • Map the host's port 443 and port 22 to the internal Docker container's port 443 and port 22
$ docker run \
	--network=host \
	-p 443:443 -p 22:22 \
	-ti cmr_stunnel \

The stunnel command should be run from inside the container. (This is something I am having an issue with.)

Connect via ssh over stunnel

Now from the client, start stunnel:

[client] $ stunnel

See the Stunnel/Client page for details on how to ensure stunnel is correctly running.

Once you execute this command, the stunnel instance on your client machine will connect to the stunnel server on your remote machine. You should now have an operational SSH tunnel.

[client] $ ssh -p 2222 root@localhost

[remote] # whoami

[remote] #


Passwordless SSH over Stunnel

To get the client passwordless access to the server over an encrypted, secure connection, you will need to add the client's SSH key to the remote server's trusted/authorized keys.

You need to do this using whichever username you want to SSH as.

If you want passwordless SSH access over stunnel, and you want to be root on the remote server, you will need to add the client's public SSH key to the root user's authorized keys file, located in /root/.ssh/authorized_keys. That's because you'll be SSHing through the stunnel connection and connecting as the root user.

If you want passwordless SSH access as a different user, like zappa, edit that user's authorized keys file, /home/zappa/.ssh/authorized_keys.

Passwordless SSH Setup


Start out on the client machine. First, generate a key for the client machine (you want passwordless access FROM this machine):

[client] $ ssh-keygen -t rsa
[client] $ cat ~/.ssh/

Now log into the server (where you want passwordless access TO), and edit the authorized keys file:

[remote] $ vi ~/.ssh/authorized_keys

Copy and paste the client's public key into the server's authorized keys file.


Now that we have this all set up, we can access the remote server by starting the SSH agent and loading the key that the remote server will trust:

[client] $ eval "$(ssh-agent -s)"
[client] $ ssh-add -K ~/.ssh/id_rsa

Now you'll be able to SSH into the remote server without a password:

[client] $ ssh zappa@remote

<user is not prompted for password>

[zappa@remote] $ 

Passwordless Access with Stunnel

Once you have set up passwordless login, you can use it tandem with stunnel to establish passwordless encrypted connections with a server.

This is an extremely handy configuration if you have a bunch of distributed nodes, like wifi sensors running on Rapsberry Pis, that can reach the remote server and need to transfer files or interact with the server.

It's particularly useful if those Raspberry Pi nodes need to do so from behind a restrictive, HTTP/HTTPS-only firewall.

In the context of stunnel trick, this will enable a passwordless and transparent connection to be made without user interaction (e.g., ON A HEADLESS SERVER, like the RaspberryPi):

[raspberrypi] $ ssh master@commandandcontrol

<raspberry pi is not prompted for password>

[master@commandandcontrol] $ 

Following the above steps and using the Raspberry Pis as the clients should allow you to set up connections with the remote server as soon as the Pis can connect to an open/public wifi network.