Listen SSH, OpenVPN, HTTPS on same port using sslh

Use case

Sometimes when I'm behind a corporate firewall I want to get my connection secure and private against any traffic inspection. The quickest way is by using SSH as SOCKS5 proxy or a VPN but the firewall blocks my SSH and VPN ports! After a quick scan, the open ports are 53, 80 and 443. Ah ha! that's it, just change my SSH or VPN port to 443 since that port is common and less suspicious but you can't just changing the SSH/VPN port to 443 as you have a website running through that port. So this is where sslh comes in handy.

Introduction

sslh is a program that allows you to run sereval programs on port 443. Mainly it allows SSH server and web server to share same port.

sslh accepts connections on specified ports(443) and forwards them further based on test performed on the first data packet sent by the remote client.

It probes for HTTP, SSL, SSH, OpenVPN, tinc, XMPP are implemented, and any other protocol that can be tested using a regular expression, can be recognised. A typical use case is to allow serving several services on port 443 (e.g. to connect to SSH from inside a corporate firewall, which almost never block port 443) while still serving HTTPS on that port.

Hence sslh acts as a protocol demultiplexer, or a switchboard. Its name comes from its original function to serve SSH and HTTPS on the same port.

source: github.com

This guide will show you how to install and setup sslh to use SSH, OpenVPN, and HTTPS webserver running on the same port.

Prerequisites

Before following this guide, I assume you already have Nginx webserver with HTTPS, OpenSSH, and OpenVPN installed.

Install

Install sslh in your server via apt install. In my opinion, the best is to install from package distribution not to compile from source as installing from apt can keep track of the package, easy to uninstall and upgrade the package.

sudo apt install sslh

When it ask you how sslh to be run, choose standalone.

Configure

There's not much to configure. I keep the same port 22 on SSH so that I can connect SSH normally via port 22 and 443 via sslh, and OpenVPN on 8080/TCP. Important to make sure your OpenVPN on any TCP port not UDP. The things to change is the SSL listener port on Nginx.

Change OpenVPN to listen to TCP

If your OpenVPN already listen to TCP port, skip this. Open /etc/openvpn/server.conf

sudo nano /etc/openvpn/server.conf

Change your port to something else and proto TCP

# Which TCP/UDP port should OpenVPN listen on?
# If you want to run multiple OpenVPN instances
# on the same machine, use a different port
# number for each one.  You will need to
# open up this port on your firewall.
port 1194

# TCP or UDP server?
proto tcp
;proto udp

Save and close.

Changing Nginx SSL listener port

Find somewhere on your nginx config files that listen to port 443 for SSL and change that to something else like 4433.

# usually:
listen 443 ssl;
    
# change that to:
listen 127.0.0.1:4433 ssl;

We make nginx to listen to localhost on port 4433. By using sslh we will redirect https port 443 to nginx 4433.

Configure SSLH

Once you have made the webservers to listen on local interface only, edit SSLH bashconfig file:

sudo nano /etc/default/sslh

find the following line:

Run=no

and change it to:

Run=yes

Then, scroll a little bit down and modify the following line to allow SSLH to listen on port 443 on all available interfaces (Eg. 0.0.0.0:443).

DAEMON_OPTS="--user sslh --listen 0.0.0.0:443 --ssh 127.0.0.1:22 --ssl 127.0.0.1:4433 --openvpn 127.0.0.1:1194 --pidfile /var/run/sslh/sslh.pid --timeout 5"

Where,
--user sslh : Requires to run under this specified username.
--listen 0.0.0.0:443 : SSLH is listening on port 443 on all available interfaces.
--ssh 127.0.0.1:22 : Route SSH traffic to port 22 on the localhost.
--ssl 127.0.0.1:4433 : Route HTTPS/SSL traffic to port 4433 on the localhost.
--openvpn 127.0.0.1:1194 : Route OpenVPN traffic to port 1194 on the localhost.
--timeout 5 : Give sslh a timeout for 5sec. To be use when your OpenVPN connect to HTTP proxy.

Save and close the file.

Finally, enable and start sslh service to update the changes.

sudo systemctl enable sslh
sudo service sslh start
sudo service openvpn restart
sudo service sshd restart
sudo service nginx restart

Testing

Check if the sslh daemon is running and listening to 443. Your output is probably same like me.

ps -ef | grep sslh
sslh      1187     1  0 Jan01 ?        00:00:00 /usr/sbin/sslh --foreground --user sslh --listen 0.0.0.0 443 --ssh 127.0.0.1 22 --openvpn 127.0.0.1 1194 --ssl 127.0.0.1 4433 --pidfile /var/run/sslh/sslh.pid --timeout 5
sslh      1188  1187  0 Jan01 ?        00:00:00 /usr/sbin/sslh --foreground --user sslh --listen 0.0.0.0 443 --ssh 127.0.0.1 22 --openvpn 127.0.0.1 1194 --ssl 127.0.0.1 4433 --pidfile /var/run/sslh/sslh.pid --timeout 5
sslh     29544  1188  0 16:40 ?        00:00:00 /usr/sbin/sslh --foreground --user sslh --listen 0.0.0.0 443 --ssh 127.0.0.1 22 --openvpn 127.0.0.1 1194 --ssl 127.0.0.1 4433 --pidfile /var/run/sslh/sslh.pid --timeout 5
user  29599 29586  0 16:41 pts/0    00:00:00 grep --color=auto sslh

Check your webserver

Open your browser and try to browse to your website over https.

Connect to SSH to port 443

Try connect SSH to your VPS from port 443:

ssh -p 443 [email protected]ample.com

Now, you can access your remote server via SSH using port 443. You may want to use the SSH connection as SOCKS5 proxy. Check it out here.

Connect OpenVPN

Edit the protocol and remote address port in your client.ovpn file.

# Are we connecting to a TCP or
# UDP server?  Use the same setting as
# on the server.
proto tcp
;proto udp

# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote {your_vpn_server_ip} 443

Save and close the file. Try to connect to VPN:

sudo openvpn --config client.ovpn

Conclusion

See? I can now be able to access the remote server via SSH even if the default SSH port 22 is blocked. As you see in the above example, I have used the https port 443 for SSH connection and OpenVPN. For more details, check the project’s website URL given below.

Cheers!

Reference: http://www.rutschle.net/tech/sslh.shtml
Github: https://github.com/yrutschle/sslh