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
root

[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/stunnel.pid
client  = yes
[ssh]
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/stunnel.pid
client	= no
[ssh]
accept	= 443
connect = 127.0.0.1:22

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

Build Container

Here is the Dockerfile: https://charlesreid1.com:3000/docker/d-stunnel/src/master/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 \
	/bin/bash

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
root

[remote] #

Bingo!

Passwordless SSH over Stunnel

DO THIS STEP ONCE

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

Generate a key:

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

Now log into the server, and edit the authorized keys file:

[remote] $ vi ~/.ssh/authorized_keys

Copy and paste the key into the authorized keys file.

END DO THIS STEP ONCE

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.

In the context of the 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):

[client] $ ssh -p 2222 root@localhost

<user does not enter any passwords>

[server] # 

Flags