Note: this package depend on git HEAD version of conduit library .
Introduction
The problem this program solves described here (in chinese): http://blog.codingnow.com/2011/05/xtunnel.html , and here is a solution written in golang: http://blog.codingnow.com/cloud/XTunnel .
The basic idea is this:
client => local agent ->-GFW->- remote agent => target server
The local agent pass all the tcp requests received to a remote agent, the remote agent pass them to our target server. Mantain only one persistent connection between local agent and remote agent. All the messages passed through the GFW need to be encrypted for well known reason.
Run as local agent: tcptunnel local remote-host remote-port ;
Run as remote agent: tcptunnel remote bind-host bind-port ;
remote-port and bind-port should be the same.
This solution demonstrates it's very convinient to build highly concurrent system using haskell lightweight threads, it also demonstrates multiple thread communication mechanism: IORef with atomicModifyIORef, MVar, STM. Also, persistent data structure -- IntMap in this case -- is important for concurrency.
It also takes advantage of multiple high quality haskell libraries:
- bytestring and blaze-builder provides fast buffer management and construction.
- attoparsec to parse streamlined network protocol, although the message format in this case is too simple to show the real strength of it.
- cereal to parse binary data, manually handling correct byte-order is a pain.
- conduit is a stream processing framework, this concept maight be rare in some languages, if you find it strange, you can find great documentation here: Conduits in Five Minutes .
- network-conduit provides a clean and complete tcp server/client interface to work with.
TODO
- send close message when local client disconnect.
- proper timeout handling.