Sebastian Krahmer (@steaIth, c-skills) made and released a nice SSH/HTTP(S) multiplexer: sshttp. Such a program is needed when you want to share your HTTP (or HTTPS) port with SSH to be able to use SSH when behind a network that only allows outbound connections to HTTP (or HTTPS) and does not bother to do protocol inspection. Learn more by reading the readme.
I was previously using sslh but sshttp has a killer feature: it uses Linux IP_TRANSPARENT feature with netfilter trickery (marking + specific routing table) to pass the original IP to destination (sshd or httpd). Since it's a great program, not necessarily easy to set up (not yet? packaged), in this post I'm sharing my setup.
Note: different file names and no hardlink or start-stop-daemon is unhappy...
Add dedicated user accounts for the two daemons:
Debian-like init scripts /etc/init.d/sshttp and /etc/init.d/sshttps:
Install them with the new dependency-based init:
Or old-school:
It's simple:
Next is to configure iptables, marking and routing. I use ferm (for Easy Rule Making) as a frontend to iptables and I highly recommend it. As long as you are familiar with iptables, it gives you the power to do a complex set of rules easily and ships with an easy init script to safely start/stop/reload the firewall. Much better in so many ways than those manual iptables.sh scripts.
So here are the sshttp rules to integrate with your /etc/init.d/ferm.conf. Note the hooks at the beginning to add the marking rule (with sh+true to avoid ferm failing if one of the commands does not exit with 0) and local routing table when marked.
Finally, open the sshttp dedicated ssh port by adding in /etc/ssh/sshd_config:
If I did not forget anything, you should be ready to use your http/https ports with ssh and still have your webserver running and serving smoothly. Enjoy!
I was previously using sslh but sshttp has a killer feature: it uses Linux IP_TRANSPARENT feature with netfilter trickery (marking + specific routing table) to pass the original IP to destination (sshd or httpd). Since it's a great program, not necessarily easy to set up (not yet? packaged), in this post I'm sharing my setup.
How does it work?
With HTTP the client speaks first (GET/POST/etc. request) whereas with SSH the server speaks first (banner). Similarly, HTTPS uses the SSL/TLS protocol where the client speaks first (ClientHello). Using this property and by waiting a little time, the multiplexer is able to determine whether the traffic should be sent to SSH server or HTTP/HTTPS server.Setup
I have a main router/firewall in front of the LAN where the server with ssh/http/https is. I keep my webserver running on default ports (80/443), ssh as well (22). I want multiplexing on both http and https, so I'll have two daemons running on 2280 and 2244. Since sshttp requires an INPUT DROP on the ports where traffic is redirected, and I want to keep normal ssh access on port 22, I open a second port for ssh at 222 only for sshttp.1 2 3 4 5 6 7 8 9 10 | [HTTP] _____ ______ port 80 | | port 2280 | | --------> | NAT | ----------> | serv | sshttp listening on 2280 |_____| |______| || /- multiplex -\ / \ http server ssh server listening on 80 listening on 222 |
1 2 3 4 5 6 7 8 9 10 | [HTTPS] _____ ______ port 443 | | port 2244 | | --------> | NAT | ----------> | serv | sshttps listening on 2244 |_____| |______| || /- multiplex -\ / \ https server ssh server listening on 443 listening on 222 |
Installation
Compile from source on github:1 2 3 4 5 6 | $ cd /usr/local/src $ git clone https: //github .com /stealth/sshttp $ cd sshttp $ make $ cp sshttpd /usr/local/sbin/sshttp $ cp sshttpd /usr/local/sbin/sshttps |
Add dedicated user accounts for the two daemons:
1 2 3 4 | $ adduser --system --ingroup nogroup \ --home /var/run/sshttp --no-create-home sshttp $ adduser --system --ingroup nogroup \ --home /var/run/sshttps --no-create-home sshttps |
Debian-like init scripts /etc/init.d/sshttp and /etc/init.d/sshttps:
1 2 3 | $ cd /etc/init .d $ wget https: //raw .github.com /StalkR/misc/master/sshttp/etc/init .d /sshttp $ wget https: //raw .github.com /StalkR/misc/master/sshttp/etc/init .d /sshttps |
1 2 | $ insserv sshttp $ insserv sshttps |
1 2 | $ update-rc.d sshttp defaults $ update-rc.d sshttps defaults |
Configuration
Default configuration for both /etc/default/sshttp /etc/default/sshttps:1 2 3 | $ cd /etc/default $ wget https: //raw .github.com /StalkR/misc/master/sshttp/etc/default/sshttp $ wget https: //raw .github.com /StalkR/misc/master/sshttp/etc/default/sshttps |
1 2 3 4 5 6 | $ cat /etc/default/sshttp SSH_PORT=222 HTTP_PORT=80 LISTEN_PORT=2280 USER=sshttp CHROOT=/var/run/sshttp |
1 2 3 4 5 6 | $ cat /etc/default/sshttps SSH_PORT=222 HTTP_PORT=443 LISTEN_PORT=2244 USER=sshttps CHROOT=/var/run/sshttps |
Next is to configure iptables, marking and routing. I use ferm (for Easy Rule Making) as a frontend to iptables and I highly recommend it. As long as you are familiar with iptables, it gives you the power to do a complex set of rules easily and ships with an easy init script to safely start/stop/reload the firewall. Much better in so many ways than those manual iptables.sh scripts.
So here are the sshttp rules to integrate with your /etc/init.d/ferm.conf. Note the hooks at the beginning to add the marking rule (with sh+true to avoid ferm failing if one of the commands does not exit with 0) and local routing table when marked.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @hook pre "sh -c 'ip rule del fwmark 22 lookup 22 2>/dev/null; true'" ; @hook pre "ip rule add fwmark 22 lookup 22" ; @hook pre "sh -c 'ip route add local 0.0.0.0/0 dev lo table 22 2>/dev/null; true'" ; domain ip { table filter { chain INPUT { proto tcp dport (80 443 222) DROP; proto tcp dport (2280 2244) ACCEPT; } } table mangle { chain OUTPUT { proto tcp outerface eth0 sport (80 443 222) jump SSHTTP; } chain PREROUTING { proto tcp mod socket jump SSHTTP; } chain SSHTTP { MARK set -mark 22; ACCEPT; } } } |
Finally, open the sshttp dedicated ssh port by adding in /etc/ssh/sshd_config:
1 | Port 222 |
Run
Reload firewall, ssh and start multiplexers:1 2 3 4 | $ invoke-rc.d ferm reload $ invoke-rc.d ssh reload $ invoke-rc.d sshttp start $ invoke-rc.d sshttps start |
If I did not forget anything, you should be ready to use your http/https ports with ssh and still have your webserver running and serving smoothly. Enjoy!
No comments:
Post a Comment