sshttp - hiding SSH servers behind HTTP
In case your FW policy forbids SSH access to the DMZ or internal
network from outside, but you still want to use ssh on machines
which only have one open port, e.g. HTTP, you can use
sshttpd can multiplex the following protocol pairs:
- SSH/SMTP (without SMTP multiline banners)
- HTTPS SNI multiplexing
- SSH/HTTPS with SNI multiplexing
Be sure you run recent Linux kernel and install
nf-conntrack as well
libcap-devel if you want to use the capability feature.
There is a new
splice branch inside the git.
git checkout splice
make, if you want to test this new branch. It implements
zero-copy in terms of the splice(2) system call which has a performance
benefit since it avoids copying the network data between user and kernel
land back and forth (read()/write()), which could also just be spliced kernel-internally
at the "extra cost" of two additional pipe descriptors per connection.
- Setup for single host
This paragraph describes the setup where all services run on the same host as sshttpd itself. The muxing happens to the same IP/IP6 address that the outside connects arrive to, so basically just the ports are changing per detected service.
sshttpd is an easy to use OSI-Layer5 switching daemon. It runs
transparently on HTTP(S) port (
-L switch, default 80) and decides
on incoming connections whether this is SSH or HTTP(S) traffic.
If its HTTP(S) traffic, it switches the traffic to the
-H, default 8080) and if its SSH traffic to
You need to edit
nf-setup script to match your network device and
are just fine for the SSH/HTTP case) and run it to install the proxy rules.
Your sshd has to run on
$SSH_PORT and your webserver on
Thats basically it. Go ahead and run sshttpd (as root) and it will layer5-switch
your traffic destinated to TCP port 80:
# ./nf-setup Using network device eth0 Setting up port 22 ... Setting up port 8080 ... # ./sshttpd -S 22 -L 80 -H 8080 -U nobody -R /var/empty sshttpd: Using HTTP_PORT=8080 SSH_PORT=22 and local port=80. Going background. Using caps/chroot. #
If you want to mux SMTP with sshttpd, just give
-H parameter, and setup your smtp daemon to listen on 2525. Then
nf-setup script to match these ports. In the
Makefile, change the
SSH_BANNER to your needs (
SSH_BANNER must match exactly
yours of the running sshd).
SMTP/SSH muxing was tested with OpenSSH client and Postfix client and server.
When muxing IPv6 connections, the setup is basically the same; just use the
script and invoke sshttpd with
- Transparent proxy setup
You can run sshttpd also on your gateway machine and transparently proxy/mux
all of your HTTP(S)/SSH traffic to your internal LAN. To do so, run sshttpd with
-T and use
nf-tproxy rather than
nf-setup as a template for your FW setup.
nf-tproxy so you dont lock yourself out of the network and all
the network devices and IP addresses match your setup.
- SNI Mux
With sshttpd you can also mux based on the HTTPS SNI. Just set up your
nf-setup to contain the SNI ports (there are already samples) and invoke
-N name:port e.g.
sshttpd -S 22 -H 4433 -L 443 -N drops.v2:7350
to hide a sshd on 22 and a drops setup on port 7350 behind port 443, and at the same time serving
your webserver from port 4433 to be visible to outside on port 443.
This works because drops sets the SNI of
drops.v2 in outgoing connects.
-N switches are allowed so you could mux a lot of services
via SNI. The ports/services must run all on the same machine where the original request
was destinated to. If you just want to mux based on SNI, you can set the SSH port to 0 via
You dont need to patch any of your ssh/web/smtp client or server software. It
works as is. sshttpd runs only on Linux and needs
It would work without, but by using
IP_TRANSPARENT it is possible to even
have unmodified syslogs, e.g. the original source IP/port of incoming connections
is passed as-is to the SSH/HTTP/SMTP servers.
Make sure the
nf_conntrack_ipv6 modules are loaded.
sshttpd is also a tricky anti-SSH0day (if ever:) and anti SSH-scanning/bruteforcing
sshttpd has small footprint and was optimized for speed so it also runs
on heavily loaded web servers.
Since version 0.24, sshttpd also supports multiple CPU cores. Unless
-n 1 is used as switch, sshttpd binds one thread per CPU core,
to better exploit the hardware if running on heavily used web servers.
It still runs this fixed number of threads no matter how many 1000s connection
it handles at the same time.
sshttpd runs as
nobody user inside a
chroot() (configurable via
if compiled with
USE_CAPS. It can also distinguish between SSH and SSL
sessions, you just have to use an
LOCAL_PORT (-L) of 443 or 4433 and change
HTTP_PORT in the
nf-setup script to match your webservers HTTPS port.
You cannot mix HTTP/SSH and HTTPS/SSH in one sshttpd instance but you can
run two sshttpd's to reach that goal: one on
LOCAL_PORT 80 and one on
- Alternative docu
As per 2017 it seems you have to provide alternative facts for everything, so here are some good writeups from other people for better understanding or in case my description was too brief: