What is sslh?
sslh probes for HTTP, TLS/SSL (including SNI and ALPN), SSH, OpenVPN, tinc, XMPP are implemented, and any other protocol that can be tested using a regular expression, can be recognized and then forwards based on its findings to where it needs to go.
Quick overview
The reason I wanted to use sslh was to use a bunch of different processes to run over port 443 so I could check lots of information about my home server from anywhere and perform admin tasks if needed without being subject to restrictive firewalls. But, I was very concerned that with 15+ websites, sslh would not know which website to go to. So, instead of just worrying, I just “turned it on” to see what would happen…
First off, keep all your websites running on ports 80 and 443. I am doing it this way because I did not want to change all of my configurations which would have sucked to do. Run sslh on a different port, for this guide I used 4443, but you can use whatever port you like (that isn’t in use anyway: netstat -peanut | grep LISTEN
). Then, on your router, forward all 443 traffic to the port you choose for sslh. So in this example, 443 -> 4443.
This is how it works in a nutshell, and I hope this guide helps you configure it and gets you up and running!
Word of caution
I would say that this set up isn’t exactly the most secure one. I ran all the commands below as an admin and if I could do it over again, would probably have made a dedicated user. I also would like to eventually (not any time soon), make the systemd service file more secure and add in the ability to know what IP are actually connecting to my web services. For now, all they show are localhost connections… so secure from that perspective, but not useful if you have bots, spam, etc. and need the ability to block and/or use this information.
Install sslh on Ubuntu 18.04 Server
Install conf2struct
cpan Conf::Libconfig
- Type
yes
to have perl autoconfig as much as possible git clone https://github.com/yrutschle/conf2struct.git&&cd conf2struct
make
make install
Install sslh
apt install libwrap0-dev libconfig-dev libbsd-dev
git clone https://github.com/yrutschle/sslh.git&&cd sslh
make
Get an error like:
sslh-conf.c:39:10: fatal error: pcreposix.h: No such file or directory
apt install libpcre3-dev
If no errors, or after installing the package above and after runningmake
again:make install
Configure your system(d)
cp scripts/etc.init.d.sslh /etc/init.d/sslh
update-rc.d sslh defaults
Make a sslh config file
nano /etc/sslh.cfg
- Replace what you will use here (and use your external IP for the listen section OR local ip [just not 127.0.0.1]):
verbose: 1;
foreground: false;
inetd: false;
numeric: false;
transparent: false;
timeout: 5;
user: "nobody";
pidfile: "/var/run/sslh.pid";
chroot: "/var/empty";
listen:
(
{ host: "pub.lic.ip.addr"; port: "443"; }
);
protocols:
(
{ name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; fork: true; },
#{ name: "openvpn"; host: "localhost"; port: "1194"; },
#{ name: "xmpp"; host: "localhost"; port: "5222"; },
#{ name: "http"; host: "localhost"; port: "80"; },
#{ name: "ssl"; host: "localhost"; port: "443"; log_level: 0; },
#{ name: "anyprot"; host: "localhost"; port: "443"; }
);
- This is the “bare minimum” file that you need to make sure everything is up and running.
- For a more advanced file to configure everything in your wildest dreams see this file.
- Ultimately, the config I used when everything was said and done:
verbose: 1;
foreground: false;
inetd: false;
numeric: false;
transparent: false;
timeout: 3;
user: "nobody";
pidfile: "/var/run/sslh.pid";
chroot: "/var/empty";
# Change "192.168.2.28" to your local ip address `ifconfig` (untested in this guide, but use your public ip address here).
listen:
(
{ host: "192.168.2.28"; port: "4443"; }
);
protocols:
(
{ name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; keepalive: true; fork: true; log_level: 0; tfo_ok: true },
{ name: "openvpn"; host: "localhost"; port: "1194"; log_level: 0; },
# { name: "regex"; host: "localhost"; port: "1194"; regex_patterns: [ "^\x00[\x0D-\xFF]$", "^\x00[\x0D-\xFF]\x38" ]; },
{ name: "tls"; host: "localhost"; port: "443"; alpn_protocols: [ "h2", "http/1.1", "h2c" ]; log_level: 1; tfo_ok: true },
# { name: "tls"; host: "localhost"; port: "443"; alpn_protocols: [ "webrtc", "c-webrtc" ]; sni_hostnames: [ "im.somethingelse.net" ]; log_level: 0; tfo_ok: true },
{ name: "tls"; host: "localhost"; port: "5349"; alpn_protocols: [ "stun.turn" ]; log_level: 0; tfo_ok: true }, #not working...#
{ name: "tls"; host: "localhost"; port: "443"; log_level: 1; tfo_ok: true },
{ name: "anyprot"; host: "localhost"; port: "443"; },
{ name: "timeout"; service: "daytime"; host: "localhost"; port: "daytime"; }
);
# Optionally, specify to which protocol to connect in case of timeout (defaults to "ssh").
on-timeout: "timeout";
# ADDITIONAL PROTOCOL EXAMPLES
# just match ALPN { name: "tls"; host: "localhost"; port: "xmpp-client"; alpn_protocols: [ "xmpp-client" ]; log_level: 0; tfo_ok: true },
# just match SNI { name: "tls"; host: "localhost"; port: "xmpp-client"; sni_hostnames: [ "im.rutschle.net", "im.englishintoulouse.com" ]; log_level: 0; tfo_ok: true },
# Let's Encrypt (tls-alpn-* challenges) { name: "tls"; host: "localhost"; port: "letsencrypt-client"; alpn_protocols: [ "acme-tls/1" ]; log_level: 0;},
# OpenVPN { name: "regex"; host: "localhost"; port: "1194"; regex_patterns: [ "^\x00[\x0D-\xFF]$", "^\x00[\x0D-\xFF]\x38" ]; },
# Jabber { name: "regex"; host: "localhost"; port: "5222"; regex_patterns: [ "jabber" ]; minlength: 60; # Won't even try to match the regex if we don't have that many bytes },
# Catch-all (but better use 'anyprot') { name: "regex"; host: "localhost"; port: "443"; regex_patterns: [ "" ]; },
Start sslh
systemctl start sslh
- You’ll more than likely get a lot of errors like:
sslh[16209]: /etc/init.d/sslh: 30: /etc/init.d/sslh: /sbin/sslh: not found
and/or
sslh[16885]: chrooting into /var/empty
sslh[16885]: common.c:818:chroot: No such file or directory
- For the first error
nano /etc/init.d/sslh
and my PREFIX was empty. I typedwhich sslh
to find out sslh install path, and put/usr
in PREFIX. - Reload the changes
systemctl daemon-reload
- For the second error, create the empty directory and change permissions to nobody:
mkdir /var/empty
chown -R nobody:nobody /var/empty
- For any other errors, just use:
journalctl -xe -u sslh
- After you have fixed all the errors (if any), start the server
systemctl start sslh
- Ensure that it is actually running using either
systemctl status sslh
ornetstat -peanut | grep :443
Change traffic from router
- Every router is different, but basically, change your port forward from your existing rule of 443 -> 443 to 443 -> 4443.
- If you have any existing connections, you will more than likely need to reboot your router in order to disconnect them, and enable your new rule.
GOOD LUCK!!!
And I hope this guide helped you.
If you need any help, there are several ways to get a hold of me:
diaspora*: danieldoubet@nota.404.mn
Matrix: daniel@dou.bet
Other
The featured imaged was retrieved from HackerNoon at 9:54AM on October 14, 2019.