Sometimes you have some firewall that don’t allows you to accept connection other than some specific ports let’s say that you can connect on your VPS or remote server only on the ports 80 (http) and 443 (https), but you need a port also for ssh to manage your vps/server but the port 443 is used by your Web server with its https protocol, so what can you do ?
This is where sslh comes in. It’s a really simple tool that wraps incoming connections to a port and then depending on protocol redirects it onto sshd back on port 22, or to your web server on localhost:443.
sslh lets one accept both HTTPS and SSH connections on the same port. It makes it possible to connect to an SSH server on port 443 (e.g. from inside a corporate firewall, which almost never block port 443) while still serving HTTPS on that port.
The idea is to have sslh listen to the external 443 port, accept the incoming connections, work out what type of connection it is, and then forward to the proper server.
Sslh it’s implemented in C for better performance and supports privilege dropping.
Protocol detection
The protocol detection is made based on a small difference between SSL and SSH: an SSL client connecting to a server speaks first, where an SSH client expects the SSH server to speak first (announcing itself with a banner). sslh waits for some time for the incoming connection to send data. If it does before the timeout occurs, it is supposed to be an SSL connection. Otherwise, it is supposed to be an SSH connection.
Installation
sslh has been packaged for Debian, Ubuntu, Gentoo, FreeBSD and many other operating systems, so check out your favourite package repository before installing by hand, that is possible downloading the source tarball
Configuration
In Debian and Ubuntu the configuration file is located in /etc/default/sslh. These are environement variables loaded by the start-up script (/etc/init.d/sslh) and passed to sslh as command-line arguments, but before looking at sshl we have to configure our 2 backend servers
Configure SSH
No special configuration on ssh, you can configure the SSH-server so it is listening on the normal SSH-port (22).
Configure HTTPS-server
Now configure your HTTPS-server (Apache?) so it is listening for HTTPS/SSL connections on an unused port. In this example I’ll use the 8080 which is reserved for alternative HTTP-traffic but this is an arbitrary choice. Or as alternative you can tell to the the webserver to listen only on localhost (not on the public IP address).
Configure SSLH
Now it’s time to edit the file /etc/default/sslh, this is a configuration file taken from Ubuntu.
Change:
RUN=yes #Tell that the daemon must be started DAEMON_OPTS="--user sslh --listen 0.0.0.0:443 --ssh 127.0.0.1:22 --ssl 127.0.0.1:8080" |
This is an explanations of the options:
-user sslh
Requires to run under this specified username
-p 0.0.0.0:443
Listening address – SSLH is listening on port 443 on all available interfaces.
-s 127.0.0.1:22
Target address for SSH – Route SSH traffic to port 22 on the localhost.
-l 127.0.0.1:8080
Target address for SSL – Route HTTPS/SSL traffic to port 8080 on the localhost
Now you can restart the 3 daemons and reach from port 443 both backend servers.
Conclusions
This is an easy solution for a common problem, and once again with our trusted Penguin we can have a valid solution in less than 10 minutes.
Popular Posts:
- None Found
Very awesome. Thankfully I only have to deal with port 80 being blocked – but wow – this is getting bookmarked. Been in many spots this would have been great to have.
Great stuff,
I have an https web server behind this and it workd great except that the remote-ip header info gets changed by sslh to 127.0.0.1
the solution (as far as i can tell) is to use the –transparent option in DAEMON_OPTS
Plus some further changes to iptables.
If anyone actually figures it out I’d like to know!