KGS Issue - HTTP Tunnel
revo: I always wanted to play on KGS from my workplace, but unfortunately we have a massive firewall through which I can get only via a HTTP proxy, so even ssh tunneling won't work (if your firewall has some open ports, it's easier to use a KGS Issue - SSH Tunnel).
So I decided to develop my own KGS over HTTP tunneling system. It works like this:
- CGoban connects to my inner tunnel end (called wrapper) instead of KGS. The wrapper takes the data from CGoban and wraps it as a header field into a HTTP request. This request is send to
- the outer tunnel end (called unwrapper) via the proxy server. The proxy server doesn't care about the extra data, because it's a simple HTTP header and the data is base64 encoded. Now the unwrapper decodes the KGS data, establishes the connection to KGS and holds it.
The wrapper is a service that runs on my work (windows) pc. When it receives a connection from CGoban, it starts a thread for this connection.
This thread receives the first data packet from CGoban and creates a HTTP request that looks something like this:
GET http://mydyndnsname.dyndns.org:xxxx HTTP/1.0 User-Agent: KGSHTTPTunnel v1.0 x-RVKGSHW-SessionID: 0 x-RVKGSHW-TargetHost: goserver.igoweb.org x-RVKGSHW-TargetPort: 2379 x-RVKGSHW-Data: BA==
The URL in the first line is the address of the host my unwrapper runs on. This host must - of course - stand somewhere in the internet. I think you'll understand that I don't post my real URL here.
The xxxx stands for the port the unwrapper listens on.
The other headers mean:
- x-RVKGSHW-SessionID - this is the session ID for the session between the wrapper and the unwrapper. It is given by the unwrapper, so at first it is set to zero.
- x-RVKGSHW-TargetHost - this header specifies the host the unwrapper should connect to, which is mostly the KGS go server.
- x-RVKGSHW-TargetPort - port of the target host.
- x-RVKGSHW-Data - this header contains the base64 encoded data that CGoban wanted to send to KGS.
This packet is sent to the proxy server which will forward it to the unwrapper's host. On success the unwrapper answers us providing a session ID and probably the first bytes of KGS's answer. The answer may look like this:
200 OK Content-Length: 0 x-RVKGSHW-SessionID: 512 x-RVKGSHW-Data: [base64-encoded-KGS-data]
Now we have a session ID. The KGS data will be decoded and sent back to CGoban. Now the real work begins:
From now on the thread permanently checks the socket for incoming data from CGoban. If a certain amount of data (currently 10 bytes) is received or a certain amount of time (currently 1sec) is elapsed, we create a new request like the one above, but now with our session ID and without the - now useless - target host and port information.
This request again is send to the unwrapper via the proxy server. Now we wait for the answer which hopefully will contain the data our unwrapper received from KGS in the meantime.
And as above, we decode the received data and send it back to CGoban.
We keep on doing this until CGoban closes the connection. There is currently a bug in the process of disconnecting from KGS, but I'm sure I will fix it soon.
Now let's see what our unwrapper does all the time.
The unwrapper is a daemon on my debian server. I'm using a DSL connection and dyndns. So this host is always reachable for me.
When the unwrapper receives a connection (from our proxy server), it starts a new client process that receives the "HTTP" request.
If the session ID in this request is zero, this process will read out the target host information and establish the connection to KGS. Then the first data packet is decoded and sent to the go server.
The HTTP request is answered as stated above with the process's pid as session ID.
Now we wait for data from KGS and store it in a buffer. Let's call this process the session process.
If the session ID of the request is not zero, we know that there's is already a session process holding the connection to KGS. So we decode the data header and store the information in a file named id.xchg. Then we signal the responsible session process (we know its pid since it's our session ID) that it can read this file. Let's call this process the request process.
When the session process gets signaled, it reads out the xchg file and sends its content to KGS. After this it writes the data from its buffer into the file and signals the request process again.
Now the request process can read the KGS data from the file, encode it via base64 and send the HTTP answer back via the proxy.
At the current state of development, this is nearly everything my two little programs do, so there are some problems left (beside some real bugs, I think :)).
Most critical is the process of disconnecting, since neither of my programs care about what kind of data is transfered and so they don't realize the connection is to be aborted.
Since I also never cared about the real KGS protocol, I'm not sure what really happens. But I keep on developing and will surely update this page when improvements are made.
If you are interested in this solution, you may contact me on KGS, I'm revo. Please understand that I won't post an email address here:)
revo: I fixed some bugs and now it seems to work well and even to disconnect properly (I'm still not sure if the whole protocol is transfered until the end :)
The latest tests didn't show big problems anymore. However, it's only as fast as a HTTP based tunnel can be.
ZeroKun: Mind if I have access so I can get on at my school? :)
Check out http://www.http-tunnel.com/html/solutions/http_tunnel/client.asp - this seems to do much the same thing. Free for data rates below 40kbps which should be more than adequate for KGS. I haven't tried it. If you do, please report you experience with it.
ehubin: I Tried this tunnel from behind the firewall at work. Works fine!
IanDavis: Both these sites are behind our work firewall *sob*
uxs: Whoa, it works. I'm using your-freedom. First I was trying to tunnel from work to home and then to kgs, but that didn't work. Then I tried it directly, which did work. Settings as follows:
- Proxy settings: nothing too difficult here, just fill them in. The Wizard detected most of it, I just had to supply a login and password.
- Ports: On the "ports" tab, add a local port forward: fill in 2379 for both ports, and goserver.igoweb.org as the remote address. You can turn off the socks and web proxy services on this tab, if you want.
- Finally, go to the "status" tab and press "Start connection".
- In the kgs client configuration, replace "goserver.igoweb.org" in the host field with "localhost".
- Play !
Addendum: Connection works ok, but I'm getting disconnected every 5 minutes. No idea why, maybe it's the proxy.
More: I'm starting to suspect that they limit connections to 5 minutes for the free client. I'm not blaming my loss in my most recent KGS game on getting disconnected 4 times, but, well, maybe I do. So it's not really usable in this state. I tried http-tunnel too, but that doesn't seem to work at all.
tuabiht? (28/09/2007) I tried your-freedom also, and it works fine for me. No disconnection after 5 minutes. I just need to click once in an hour to keep the connection running.
I've found http://www.htthost.com/ - this is also http-tunneling software, with 2 options: you can use a free public server as the end-point, or you can setup your own host outside the firewall. The public server seems very slow, so I'm going to install the "host" server on my own PC and see how the speed is. If that doesn't work, I'm probably giving up. (For now.)
uxs: HttPort + HttHost work. I've been connected for 15 minutes now.
Allan: Hello this article is interesting, but where can we find your program ?
Arsene: I am interested in this program. But I can't contact you on KGS. There is no way now for me to login to KGS, for I am behind the proxy server, which do not allow any program have access to the internet directly. So my KGS client is blocked. Revo, is there any other way to contact you? Many thanks