sslh: A protocol multiplexer that allows services like HTTPS, SSH, and OpenVPN to share the same port

sslh: A protocol multiplexer that allows services like HTTPS, SSH, and OpenVPN to share the same port

I run sslh on more than one of my own internet-facing boxes, and I’ve used it in authorized engagements too — it solves a very specific, very common problem: you only have one externally reachable port (usually 443, since it’s rarely blocked by any firewall), but you want to run several different services — HTTPS, SSH, OpenVPN — that would normally each need their own port. sslh sits in front of all of them and intelligently routes each incoming connection to the right backend service based on the actual protocol being spoken, not just the port number.

What sslh Is and How It Works

sslh is a protocol multiplexer (sometimes called a “port demultiplexer”). It listens on a single port and, for each incoming connection:

  1. Peeks at the first few bytes of the connection (without fully consuming them) to identify which protocol is being used — the TLS ClientHello, the SSH version banner, an OpenVPN handshake, and various other supported protocols each have distinguishable signatures
  2. Based on that identification, transparently forwards the connection to the correct backend service listening on its own internal port (e.g., real SSH on 22, real HTTPS on 8443, OpenVPN on 1194)
  3. From that point on, sslh gets out of the way — the connection proceeds directly between the client and the actual backend service, with sslh having only handled the initial protocol-sniffing and redirection

This is exactly the mechanism that lets someone connect to your server on port 443 with an SSH client, and have it “just work” as an SSH connection, while a browser connecting to that same port 443 gets routed to your actual HTTPS web server — all without either client needing to know anything special.

Installing sslh

On Debian/Ubuntu:

sudo apt update
sudo apt install -y sslh

Verify:

sslh --version

Building from source for the latest features:

sudo apt install -y build-essential libconfig-dev libwrap0-dev libpcre3-dev
git clone https://github.com/yrutschle/sslh.git
cd sslh
make
sudo make install

Basic Configuration and Syntax

sslh’s config file typically lives at /etc/sslh/sslh.cfg (or /etc/default/sslh on some Debian-based systems for simpler setups):

listen:
(
  { host: "0.0.0.0"; port: "443"; }
);

protocols:
(
  { name: "ssh"; host: "localhost"; port: "22"; },
  { name: "openvpn"; host: "localhost"; port: "1194"; },
  { name: "tls"; host: "localhost"; port: "8443"; }
);

Running it manually for testing:

sudo sslh -F /etc/sslh/sslh.cfg -f

Or via systemd once configured:

sudo systemctl enable --now sslh

Real Example (Authorized Lab Environment)

Setup: real SSH daemon moved to listen on port 22 internally (unchanged), a real HTTPS web server on 8443, and sslh listening publicly on 443.

$ sudo sslh -f -F /etc/sslh/sslh.cfg
sslh[1234]: main.c:612 sslh: Listening on 0.0.0.0:443

From a client machine, connecting via SSH to port 443 instead of the usual 22:

$ ssh -p 443 user@labserver.local
user@labserver.local's password:

And a browser hitting https://labserver.local (default port 443) transparently reaches the actual web server instead — both connections share the exact same externally exposed port.

Real-World Use Cases

Bypassing restrictive outbound firewalls in authorized testing — validating whether a corporate network that only allows outbound traffic on 443 still permits an SSH tunnel to reach an authorized external jump host, as part of an egress-filtering assessment.

Consolidating exposed services on personal or client infrastructure — running SSH, a VPN, and a web server all through a single externally reachable port, reducing the exposed attack surface to one port instead of several.

Red team infrastructure setup — configuring command-and-control or authorized remote access tooling to blend in on port 443 alongside a legitimate-looking HTTPS front end, for realistic detection/response exercises with a client’s blue team.

Integration with Other Tools

  • stunnel — sslh often sits in front of an stunnel instance, routing TLS-tagged traffic to stunnel for termination and decryption, while other protocols get routed elsewhere on the same port.
  • OpenVPN/WireGuard — commonly multiplexed behind sslh alongside SSH and HTTPS so a VPN service doesn’t need its own dedicated exposed port.
  • fail2ban — since sslh forwards the real client IP (with proper configuration, e.g., using the PROXY protocol or --transparent mode), downstream services like SSH can still apply their own IP-based protections correctly.

Performance and Troubleshooting

  • By default, sslh performs simple NAT-style forwarding where backend services may see connections as coming from localhost; enable --transparent mode (requires additional iptables/kernel configuration) if backend services need to see the real client IP for logging or security controls.
  • If a protocol isn’t being detected correctly, check sslh’s probe order and configuration — some protocols with ambiguous initial bytes can occasionally be misidentified; adjusting the order of protocol definitions in the config can resolve edge cases.
  • A mistake I’ve made: forgetting to move the real SSH daemon off port 22 (or otherwise properly separate it) before pointing sslh’s own listener at port 443 while also trying to keep SSH on 22 — the two must be cleanly separated in the config to avoid port conflicts.

Best Practices

  • Use --transparent mode carefully and only after testing that the required iptables rules work correctly in your environment; misconfiguration can break connectivity entirely.
  • Keep backend services (SSH, HTTPS, VPN) bound only to localhost or internal interfaces so the only externally reachable entry point is sslh’s multiplexed port.
  • Log and monitor sslh’s own connection routing decisions in addition to each backend service’s own logs for complete visibility.

FAQ

Does sslh decrypt or inspect encrypted traffic content? No — it only inspects the initial handshake bytes needed to identify the protocol; it doesn’t decrypt or read the actual encrypted payload of TLS/SSH sessions.

Can sslh multiplex more than three protocols? Yes — it supports a range of protocols beyond SSH/HTTPS/OpenVPN, including HTTP, XMPP, and generic TLS-based services, configurable in the same protocols list.

Is sslh a security risk by itself? Used correctly, it just multiplexes existing services onto one port; the security of the setup still depends entirely on the backend services’ own authentication and hardening.

Summary

sslh is a small tool that solves a real, everyday infrastructure problem — letting SSH, HTTPS, and VPN traffic all share a single externally reachable port by intelligently detecting each protocol’s handshake. Whether I’m consolidating my own server’s exposed ports or evaluating a client’s egress filtering during an authorized assessment, it’s a clean, well-tested solution.

References

  • GitHub repository: https://github.com/yrutschle/sslh
  • Man page: man sslh
Total
0
Shares

Leave a Reply

Previous Post
pwnat: A NAT traversal tool for reverse shells and remote control via NATed networks

pwnat: A NAT traversal tool for reverse shells and remote control via NATed networks

Next Post
stunnel4: A tool for creating secure SSL/TLS tunnels to protect unencrypted services

stunnel4: A tool for creating secure SSL/TLS tunnels to protect unencrypted services

Related Posts