SSH across a Layer 7 Filter

Every once in a while, I find myself in a situation behind some sort of device that filters a lot of traffic.  Most often, it's on my laptop at some facility (e.g., coffee shop) that only allows HTTP/HTTPS out.  For a while, I just listened for SSH traffic on port 443 (HTTPS) to connect through port-based firewalls.  However, a few times now I've seen a connection reset immediately after the SSH handshake started (during the protocol&cipher negotation).  Looking at them through WireShark made it obvious it wasn't a server or client problem, but some intermediate device sending a RST.

At first, I just throught I would use Dag Wieers's method for tunneling SSH over HTTPS with Apache/mod_proxy.  Unfortunately, Apache bug 29744 causes CONNECT over HTTPS to fail.  I also didn't really want to add another application to my system just to do that via proxytunnel.

My method, I will note, does NOT allow you to run both an HTTPS server and allow these connections on the same port.  What it does do is prevent passive sniffers (including Layer 7 devices) from seeing the SSH session initialization.  It still uses SSH for authentication, and I don't believe it poses any special security risks.  You'll need a dedicated IP/port combination to run this on, and port 443 will have the easiest time getting out of the networks discussed at the beginning.

Yes, the double-encryption is unnecessary overhead, but it gives you the power of SSH while making the network see nothing more than a simple SSL connection.

So, let's get it done! First off, install stunnel4 on your server. My configuration looks something like this:

cert = /etc/ssl/somecert.pem
sslVersion = SSLv3
chroot = /var/lib/stunnel4/
setuid = stunnel4
setgid = stunnel4
pid = /stunnel4.pid
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1

[ssh]
# This address and port cannot be used for anything except this connection
accept = 203.0.113.2:443
connect = 127.0.0.1:22

On your client, you'll just need the standard openssl application.  OpenSSL is installed on (nearly ?) every Linux distribution by default, so no extra client application needed here. You'll find it easiest to set up a ~/.ssh/config file. In my config, I have a stanza like:

Host server.https
	Hostname 203.0.113.2
	Port 443
	ProxyCommand openssl s_client -connect %h:%p -quiet 2>/dev/null
	User username

Doing an "ssh server.https" should connect to the server via the SSL tunnel.