September 10 2012 · http · tcp · tunneling · python

Tunnel TCP through HTTP - A Python Implementation

Sometimes you find yourself behind a restrictive firewall. It blocks any request with destination port other than 80. You can do little thing like browsing websites.

The solution, if you want to access an application at other ports, is to direct your traffic to a server outside the firewall listening at port 80. The server then forwards the data to your desired destination. It also returns any response from that destination, i.e, tunneling.

The tunneling can leverage on existing protocol, like HTTP. I have written a simple tunnel program in Python. It contains two components, tunnel client and tunnel server.

Tunnel Server

It is basically a HTTP server which should resides on the host machine outside the firewall. When the server received a request from client, it relies on the request's HTTP method to start the respective action sequence:

You can start the server with command:

python -p 80

The default port server listens to is 9999. Type python -h for help messages.

Tunnel Client

Tunnel Client resides on your local machine or any machine within the firewall. It follows the above mentioned protocol to talk to the Tunnel Server. It spawns separate threads to send and receive data from server (through HTTP PUT and GET respectively) and forward back to the local machine through socket.

To start the client:

python [target_host]:[target_port]


To test the Tunnel, for example, tunneling IRC connection, we use linux nc command:

First, start the tunnel service:

python -p 80
python -p 8889 -h localhost:80

Connect to the client using nc and send IRC messages:

nc localhost 8889 
NICK abcxyz
USER abcxyz abcxyz :abcxyz


#!shell-session NOTICE * :*** Looking up your hostname... NOTICE * :*** Checking Ident NOTICE * :*** Found your hostname NOTICE * :*** No Ident response
NICK abcxyz
USER abcxyz abcxyz :abcxyz 001 abcxyz :Welcome to the freenode Internet Relay Chat Network abcxyz 002 abcxyz :Your host is[], running version ircd-seven-1.1.3 003 abcxyz :This server was created Sun Dec 4 2011 at 14:42:47 CET 004 abcxyz ircd-seven-1.1.3 DOQRSZaghilopswz CFILMPQbcefgijklmnopqrstvz bkloveqjfI 005 abcxyz CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQcgimnprstz CHANLIMIT=#:120 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=freenode KNOCK STATUSMSG=@+ CALLERID=g :are supported by this server 005 abcxyz CASEMAPPING=rfc1459 CHARSET=ascii NICKLEN=16 CHANNELLEN=50 TOPICLEN=390 ETRACE CPRIVMSG CNOTICE DEAF=D MONITOR=100 FNC TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: :are supported by this server 005 abcxyz EXTBAN=$,arx WHOX CLIENTVER=3.0 SAFELIST ELIST=CTU :are supported by this server 251 abcxyz :There are 232 users and 70582 invisible on 31 servers 252 abcxyz 45 :IRC Operators online 253 abcxyz 10 :unknown connection(s) 254 abcxyz 34513 :channels formed 255 abcxyz :I have 6757 clients and 1 servers 265 abcxyz 6757 10768 :Current local users 6757, max 10768 266 abcxyz 70814 83501 :Current global users 70814, max 83501 250 abcxyz :Highest connection count: 10769 (10768 clients) (2194912 connections received)

It needs not be HTTP

Here I use tunneling tcp packages through HTTP protocol. It is an existing protocol, which gives the reusability to the program. But you can implement your own program on top of the tunneling TCP Connection. You just need to define your own application layer protocol on how the two end of the tunnel communicate, i.e, when to start sending data, when the data ends...

You can access the source code of the program here

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket