Hack 77 Tunnel Connections Inside HTTP

figs/moderate.gif figs/hack77.gif

Break through draconian firewalls by using httptunnel.

If you've ever been on the road and found yourself in a place where the only connectivity to the outside world is through an incredibly restrictive firewall, you probably know the pain of trying to do anything other than sending and receiving email or basic web browsing.

Here's where httptunnel (http://www.nocrew.org/software/httptunnel.html) comes to the rescue. Httptunnel is a program that allows you to tunnel arbitrary connections through the HTTP protocol to a remote host. This is especially useful in situations like the one mentioned earlier, when web access is allowed but all other services are denied. Of course, you could just use any kind of tunneling software and configure it to use port 80, but where would that leave you if the firewall is actually a web proxy? This is roughly the same as an application-layer firewall, and will accept only valid HTTP requests. Fortunately, httptunnel can deal with these as well.

To compile httptunnel, download the tarball and run configure and make:

$ tar xfz httptunnel-3.3.tar.gz 

$ cd httptunnel-3.3

$ ./configure && make

Install it by running make install, which will install everything under /usr/local. If you want to install it somewhere else, you can use the standard --prefix= option to the configure script.

The httptunnel client program is called htc, and the server is hts. As with ssh [Hack #76], httptunnel can be used to listen on a local TCP port for connections, forward the traffic that it receives on this port to a remote server, and then decrypt and forward the traffic to another port outside of the tunnel.

Try tunneling an SSH connection over HTTP. On the server, run a command like this:

# hts -F localhost:22 80

Now, run a command like this on the client:

# htc -F 2222 colossus:80

In this case, colossus is the remote server, and htc is listening on port 2222. You can use the standard port 22 if you aren't running a local sshd. If you're curious, you can verify that htc is now listening on port 2222 by using lsof:

# /usr/sbin/lsof -i | grep htc

htc       2323   root    6u  IPv4 0x02358a30      0t0    TCP *:2222 (LISTEN)

And now to try out the tunnel:

[andrew@kryten andrew]$ ssh -p 2222 localhost

andrew@localhost's password: 

[andrew@colossus andrew]$

You can also forward connections to machines other than the one that you're running hts on. To do this, just replace the localhost in the hts command with whatever remote host you wish to forward to.

For instance, to forward the connection to oceana.ingsoc.net instead of colossus, you could run this command:

# hts -F oceana.ingsoc.net:22 80

If you're curious to see what an SSH connection tunneled through the HTTP protocol looks like, you can take a look at it with a packet sniffer. Here's the initial portion of the TCP stream that is sent to the httptunnel server by the client:

POST /index.html?crap=1071364879 HTTP/1.1

Host: linux-vm:80

Content-Length: 102400

Connection: close



SSH-2.0-OpenSSH_3.6.1p1+CAN-2003-0693

If your tunnel needs to go through a web proxy, no additional configuration is needed as long as the proxy is transparent and does not require authentication. If the proxy is not transparent, you can specify it with the -P switch. Additionally, if you do need to authenticate with the proxy, you'll want to make use of the -A or --proxy-authorization options, which allow you to specify a username and password to authenticate with.

Here's how to use these options:

htc -P myproxy:8000 -A andrew:mypassword -F 22 colossus:80

If the port that the proxy listens on is the standard web proxy port (8080), then you can just specify the proxy by using its IP address or hostname.