How to SSH over 443 while Apache runs SSL with socat, stunnel4 and sslh
By Raymond Li (Raymo111), December 11th, 2019
Table of Contents
Step 0: Preparation
Note: Don't skip over this section! You could lose all access to your system if it is headless!
First open a lifesaver connection to your server via normal SSH. Get root access either with
sudo -s. Don't close this until the end of this tutorial.
Step 1: Server
Note: The following instructions need to be run on your SERVER, that is, the machine you want to SSH INTO.
On your server, install
Use letsencrypt to generate a certificate for apache. Follow the instructions carefully.
sudo certbot --apache
Now edit the
sudo nano /etc/stunnel/stunnel.conf
Use this config, replacing
<SERVER DOMAIN> with your server's domain or subdomain. (e.g.
pid = /var/run/stunnel.pid # Sets the Process ID of stunnel to stunnel.pid cert = /etc/letsencrypt/live/<SERVER DOMAIN>/fullchain.pem # Sets the certificate stunnel will use with your traffic key = /etc/letsencrypt/live/<SERVER DOMAIN>/privkey.pem # Sets the private key stunnel will use in decrypting your traffic [ssh] accept = 0.0.0.0:443 # 0.0.0.0 means any and all IP addresses connect = localhost:1022 # Accepts all traffic on port 443, regardless oforigin and connects it to port 1022
sudo nano /etc/default/stunnel4
sslh. Edit its config
sudo nano /etc/default/sslh
Put this in
# Default options for sslh initscript # sourced by /etc/init.d/sslh # Disabled by default, to force yourself # to read the configuration: # - /usr/share/doc/sslh/README.Debian (quick start) # - /usr/share/doc/sslh/README, at "Configuration" section # - sslh(8) via "man sslh" for more configuration details. # Once configuration ready, you *must* set RUN to yes here # and try to start sslh (standalone mode only) RUN=yes # Run sslh # binary to use: forked (sslh) or single-thread (sslh-select) version # systemd users: don't forget to modify /lib/systemd/system/sslh.service DAEMON=/usr/sbin/sslh # Customize this if you want. Uses the user sslh, listens on port 1022 (from stunnel, remember?), and after a bit of automagical analysis, redirects SSH traffic to port 22 and ssl (Apache/webserver/https) traffic to 443. Uses process id of sslh.pid DAEMON_OPTS="--user sslh --listen 127.0.0.1:1022 --ssh 127.0.0.1:22 --ssl 127.0.0.1:443 --pidfile /var/run/sslh/sslh.pid"
Now check your Apache ports config file
sudo nano /etc/apache2/ports.conf
And make sure only port 80 is uncommented. If not, just add a
# in the beginning of all the uncommented lines but
# If you just change the port or add more ports here, you will likely also # have to change the VirtualHost statement in # /etc/apache2/sites-enabled/000-default.conf Listen 80 #<IfModule ssl_module> # Listen 443 #</IfModule> #<IfModule mod_gnutls.c> # Listen 443 #</IfModule> # vim: syntax=apache ts=4 sw=4 sts=4 sr noet
Start and enable
sudo systemctl start stunnel4 sslh && sudo systemctl enable stunnel4 sslh
Enable gateway ports
sudo nano /etc/ssh/sshd_config
GatewayPorts and set it to
If there are any errors, you have messed something up. Recheck all the config files and make sure they match the ones above.
sudo systemctl restart stunnel4 sslh apache2
Step 2; Client
Note: The following instructions need to be run on your CLIENT, that is, the machine you want to SSH FROM.
Edit your SSH config
Put the following in, replacing with whatever you want, with your username on your SERVER and with your server's domain or subdomain.
Host <HOSTNAME> user <USERNAME> Proxycommand /usr/bin/socat - OPENSSL:<SERVER DOMAIN>:443.verify=0
Test out your setup!
You should be able to SSH through 443 now! Also check to make sure Apache is still running and you can still SSH normally BEFORE closing your lifesaver connection.