SSLH(8)

πŸ“¦ version 2.3.1, in arch rolling

πŸ’… SSLH(8) β€” like, the sslh manual but make it make sense πŸŽ€

okay bestie, buckle up πŸ’– this is sslh(8), and yes it's a whole vibe. it's a protocol demultiplexer, which sounds scary but is literally just a switchboard for your network. iykyk ✨


🌸 NAME 🌸

sslh β€” protocol demultiplexer. that's it. that's the whole name. slay πŸ’…


🌈 SYNOPSIS 🌈

sslh [-Fconfig file] [-t num] [--transparent] [-p listening address [-p
listening address ...]  [--tls target address for TLS] [--ssh target
address for SSH] [--openvpn target address for OpenVPN] [--http target
address for HTTP] [--xmpp target address for XMPP] [--tinc target
address for TINC] [--anyprot default target address] [--on-timeout
protocol name] [-u username] [-C chroot] [-P pidfile] [-v n] [-i] [-V]
[-f] [-n]

like, yes, that's a lot of brackets. she's high-maintenance but she's worth it πŸ’œ


✨ DESCRIPTION ✨

so here's the tea β˜• sslh accepts connections on the ports you tell her about, and then forwards them further based on tests performed on the first data packet sent by the remote client. literally: she peeks at the first bytes and goes "oh, this one's an SSH girlie" and routes accordingly. main character energy πŸŽ€

Probes for HTTP, TLS, SSH, OpenVPN, tinc, XMPP are implemented, and any other protocol that can be tested using a regular expression can be recognised. no cap, regex goes brrr πŸ”₯

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. iconic. the firewall literally cannot tell πŸ‘‘

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. so the name is like... a portmanteau. she invented the portmanteau πŸ¦‹

🫢 Libwrap support 🫢

one drawback of sslh is that the servers do not see the original IP address of the client anymore, as the connection is forwarded through sslh. sad but true 😭 the servers are like "who dis" and sslh is like "it's me, your proxy."

for this reason, sslh can be compiled with libwrap to check accesses defined in /etc/hosts.allow and /etc/hosts.deny. Libwrap services can be defined using the configuration file. very gatekeep-y of her, honestly πŸ’…

πŸŽ€ Configuration file πŸŽ€

a configuration file can be supplied to sslh. Command line arguments override file settings. (say it with me: command line wins, periodt.)

sslh uses libconfig to parse the configuration file, so the general file format is indicated in http://www.hyperrealm.com/libconfig/libconfig_manual.html. please refer to the example configuration file provided with sslh for the specific format (Options have the same names as on the command line, except for the list of listen ports and the list of protocols). 🌸

the configuration file makes it possible to specify protocols using regular expressions: a list of regular expressions is given as the regex_patterns parameter, and if the first packet received from the client matches any of these expressions, sslh connects to that protocol. regex girlies rise up ✨

πŸ¦‹ Probing protocols πŸ¦‹

when receiving an incoming connection, sslh will read the first bytes sent by the connecting client. it will then probe for the protocol in the order specified on the command line (or the configuration file). therefore --anyprot should alway be used last, as it always succeeds and further protocols will never be tried.

(yes, the original says "alway". we're keeping it. typos are canon now πŸ™ˆ)

if no data is sent by the client, sslh will eventually time out and connect to the protocol specified with --on-timeout, or ssh if none is specified. so like, she's patient, but not that patient πŸ’€

πŸ”₯ Logging πŸ”₯

as a security/authorization program, sslh logs to the LOG_AUTH facility, with priority LOG_INFO for normal connections and LOG_ERR for failures. she's keeping receipts, always πŸ§ΎπŸ’œ


πŸ’… OPTIONS πŸ’…

  • -Ffilename, --config filename β€” Uses filename as configuration file. If other command-line options are specified, they will override the configuration file's settings. (cmdline stays winning, fr fr)
  • -t num, --timeout num β€” Timeout before forwarding the connection to the timeout protocol (which should usually be SSH). Default is 2s. two seconds of silence and she's moving on ⭐
  • --on-timeout protocol name β€” Name of the protocol to connect to after the timeout period is over. Default is to forward to the first specified protocol. It usually makes sense to specify 'ssh' as the timeout protocol, as the SSH specification does not tell who is supposed to speak first and a large number of SSH clients wait for the server to send its banner. (ssh clients are just sitting there waiting to be perceived 😭)
  • --transparent β€” Makes sslh behave as a transparent proxy, i.e. the receiving service sees the original client's IP address. This works on Linux only and involves iproute2 settings. In some cases also iptables/nftables settings are needed. Refer to the README or https://github.com/ftasnetamot/sslh/blob/2014-08-16--close-filehandles-with-detach/doc/simple_transparent_proxy.md for more information. 🐧
  • -p listening address, --listen listening address β€” Interface and port on which to listen, e.g. foobar:443, where foobar is the name of an interface (typically the IP address on which the Internet connection ends up).

This can be specified several times to bind sslh to several addresses. she's multitalented πŸ’–

  • --tls target address β€” Interface and port on which to forward SSL connection, typically localhost:443.

Note that you can set sslh to listen on ext_ip:443 and httpd to listen on localhost:443: this allows clients inside your network to just connect directly to httpd. smart, honestly πŸ‘‘

Also, sslh probes for TLS handshakes and will reject connections from clients requesting SSLv2. This is compliant with RFC6176 which prohibits the usage of SSLv2. If you wish to accept SSLv2, use --anyprot instead. (SSLv2 is, like, so 1995. we don't do that here πŸ’€)

  • --ssh target address β€” Interface and port on which to forward SSH connections, typically localhost:22.
  • --openvpn target address β€” Interface and port on which to forward OpenVPN connections, typically localhost:1194.
  • --xmpp target address β€” Interface and port on which to forward XMPP connections, typically localhost:5222.
  • --http target address β€” Interface and port on which to forward HTTP connections, typically localhost:80.
  • --tinc target address β€” Interface and port on which to forward tinc connections, typically localhost:655.
This is experimental. If you use this feature, please report the results (even if it works!) β€” yes, even the successes. she wants the data 🧚
  • --anyprot target address β€” Interface and port on which to forward if no other protocol has been found. Because sslh tries protocols in the order specified on the command line, this should be specified last. If no default is specified, sslh will forward unknown protocols to the first protocol specified. the catch-all, the safety net, the bestie who says "you can sit with us" 🫢
  • -v, --verbose n β€” Override all verboseness. Refer to example.cfg for all verbose sub-options.
  • -n, --numeric β€” Do not attempt to resolve hostnames: logs will contain IP addresses. This is mostly useful if the system's DNS is slow and running the sslh-select variant, as DNS requests will hang all connections. (slow DNS = the enemy of the people 😀)
  • -V β€” Prints sslh version. short king.
  • -u username, --user username β€” Requires to run under the specified username.
  • -C chroot, --chroot chroot β€” Requires to run under the specified chroot. very "contain yourself" of her πŸ”’
  • -P pidfile, --pidfile pidfile β€” Specifies a file in which to write the PID of the main server.
  • -i, --inetd β€” Runs as an inetd server. Options -P (PID file), -p (listen address), -u (user) are ignored. (not me ignoring three whole options πŸ™ˆ)
  • -f, --foreground β€” Runs in foreground. The server will not fork and will remain connected to the terminal. Messages normally sent to syslog will also be sent to stderr. she stays right there. watching. πŸ’œ
  • --background β€” Runs in background. This overrides foreground if set in the configuration file (or on the command line, but there is no point setting both on the command line unless you have a personality disorder). and honestly? valid. we contain multitudes πŸ’€

πŸ“ FILES πŸ“

  • /etc/init.d/sslh β€” Start-up script. The standard actions start, stop and restart are supported. the holy trinity πŸ™
  • /etc/default/sslh β€” Server configuration. These are environment variables loaded by the start-up script and passed to sslh as command-line arguments. Refer to the OPTIONS section for a detailed explanation of the variables used by sslh.

πŸ” SEE ALSO πŸ”

the latest version is available from https://github.com/yrutschle/sslh. there you can find a more detailed and recent documentation. go read it, she's thorough ✨


πŸ‘‘ AUTHOR πŸ‘‘

Written by Yves Rutschle. (ty for your service, king 🫑)


⭐ and that's the page, bestie! this gorgeous little doc is from version 2.3.1-1, dated 2026-04-21 β€” yes, a future date, she's ahead of her time πŸ’…βœ¨ no cap. go forth and demultiplex πŸ¦‹πŸ’–

πŸ“¦ where this page comes from