Socat, sslh and stunnel to share https port 443

The instructions below assume you are using Ubuntu 16.04 but they will work for other Linuxes with minor modifications. The instructions below will also conflict with a webserver listening on port 443 ( https ) so you’ll need to disable it. Once the setup below is complete your https connections will get seamlessly forwarded to port 80.

Setup letsencrypt keys

For the SSL connection to be secure and trusted by browsers and other software you need to have a certificate signed by a recognised certificate authority. The easiest way to do this is to use letsencypt’s certbot. I’m not going to go into how to get the certificate as there are too many ways depending on your configuration. Just follow letsencrypt’s documentation to generate a key for your "servernname.com" that will get used in the rest of these instructions.

You could also use a self signed key but that may cause you problems with stateful firewalls.

Setup stunnel

With your certificate installed on the server you can now setup stunnel to use it. crow shows a partial setup here. I think he’s limited the ciphers for increased security but I found it was not necessary.

Install stunnel4

sudo apt-get install stunnel4

So the setup in /etc/stunnel/stunnel.conf I am using looks like this

pid = /var/run/stunnel.pid
cert = /etc/letsencrypt/live/servername.com/fullchain.pem
key = /etc/letsencrypt/live/servername.com/privkey.pem
[ssh]
accept = servername.com:443
connect = localhost:80

You also need to enable stunnel in /etc/default/stunnel4.conf by setting ENABLED=1

restart stunnel to use the new configuration.

systemctl restart stunnel4

At this point you can test the stunnel setup by going to “http://servername.com” with your browser and you will have a secure connection to your http server.

To prep for the sslh configuration change

connect = localhost:80

in /etc/stunnel/stunnel.conf to

connect = localhost:1022

and then restart stunnel again.

Setup sslh

sslh will redirect the sessions decrypted by stunnel to the correct port on your server.

You need to install sslh

sudo apt-get install sslh

The minimum services I wanted are ssh and http so my configuration in /etc/default/sslh looks like this.

RUN=yes

# binary to use: forked (sslh) or single-thread (sslh-select) version
DAEMON=/usr/sbin/sslh

DAEMON_OPTS="--user sslh --listen 127.0.0.1:1022 --http 127.0.0.1:80 --ssh 127.0.0.1:22 --pidfile /var/run/sslh/sslh.pid"

The sslh documentation says that OpenVPN, tinc, XMPP are also supported but I didn’t need those so my configuration doesn’t support them. You can now restart sslh

sudo systemctl restart sslh

This would be another good time to test the stunnel -> sslh -> httpd redirection by visiting “http://servername.com” in your browser.

Client side ssh setup

Once all of the above is complete and assuming that you have an ssh server that you can connect to on port 22 of your server the ssh client can be setup to use the ssl tunnel. The ssh session needs to wrapped in the ssl session to be able to connect to the server so I used the ssh ProxyCommand to accomplish this. Add the section below to your ~/.ssh/config on your client machine

Host servername.com
ProxyCommand /usr/bin/socat - OPENSSL:servername.com:443

From the client you should now be able to connect to your server by doing

ssh servername.com

If you get errors from ProxyCommand about your keys or if you used a self signed certificate you will need to turn off key verification.

Host servername.com
ProxyCommand /usr/bin/socat - OPENSSL:servername.com:443,verify=0

There is usually one other modification I have in my ssh config and that is a DynamicProxy so that stateful packet inspection doesn’t interfere. So the final configuration looks like this.

Host servername.com
DynamicForward localhost:2121
ProxyCommand /usr/bin/socat - OPENSSL:servername.com:443

The interested reader should look into FoxyProxy to see how this might be used.