Tired of not being able to play on the company's QII server from home ?
Irritated by sysadmins blocking your Quake II packets ?
Have a machine on the other side of the firewall lying around doing nothing ?
You need...

RQProxy - Richard's Quake II Proxy

By Richard Watts, Richard.Watts@cl.cam.ac.uk

This is a Quake II proxy (for UNIX systems only, I'm afraid) which proxies packets out of the local network, across a TCP connection, and then masquerades as the client at the other end. It may also work for other games, but I haven't tested them. In fact, this is rather more general than a Quake II proxy: it's a general UDP proxy which can be used to tunnel (and masquerade) UDP over TCP, but Quake II is the most popular application I can think of :-). What this proxy will do:

What this proxy will not do: There are reasons for this: see the technical details section at the end. Problems, questions, pieces of cheese, etc., should be sent to Richard.Watts@cl.cam.ac.uk.

You can get the latest version of the proxy from the RQProxy home pageThis README contains the following sections:


Quick Start

Unpack the distribution, cd to the src directory and do make to build the client and server.

Find a machine you want to play quake on - A - a machine on the same subnet running UNIX - B (A and B can be the same), and a machine - C -which can talk to B via TCP and to the Quake 2 game server - D. On C, do:

$ q2srv 15004 27910 B D
On B do

$ q2clnt A 27910  B 15004
And on A, go to console and do:

] connect B
And there you go. If you get something like `address already in use' with 15004, try some other number between 1025 and 32767.

Please mail me (Richard.Watts@cl.cam.ac.uk) if you have any problems, or notice any bugs.

More detailed explanations

The source code for four programs is shipped:

q2srv
This is the Quake II proxy server. It accepts UDP packets over a TCP connection, extracts them from the TCP stream, and resends them to a destination given on the command line. Its syntax is:

q2srv [listen port] [fwd port] [source ip] [target ip]
Listen port and source ip are the IP address the TCP stream will come from and the port to listen on, respectively, and fwd port and target ip are the port to forward and the host to forward it to.

q2clnt
This is the proxy client: it takes UDP from given machine and port and wraps them into a TCP connection to the server. Its syntax is:

q2clnt [listen address] [listen port] [proxy ip] [proxy port]
Listen address is the machine to listen to, listen port is the port to listen to, proxy ip is the address of the machine the server is running on, and proxy port is the port the server is listening on.

q2s
Syntax:

q2s [port]
Listens on a UDP port and prints out all packets that arrive at that port.

q2c
Syntax:

q2c [host] [port]
Sends a packet containing the data Hello, World! to the given host and (UDP) port once a second until interrupted.

Proxying a Quake II Game

BE SURE TO DISCONNECT YOUR QUAKE II CLIENT BEFORE CHANGING THE QUAKE II SERVER YOU'RE PROXYING TO, OR BOTH YOUR CLIENT AND THE SERVER WILL BECOME TERRIBLY CONFUSED.

Suppose you have a machine inside a firewall called maui.foo.bar, and a machine outside the firewall called epona.zoop.eep (this will be called the outside proxy machine). You want to play a game of Quake II on maui and you want to forward the traffic through epona to a quake server called quake2.games.foo.bar.net.

You need a Linux machine which packets from maui will reach - we'll call it aztlan.foo.bar (the inside proxy machine). If maui is running Linux, you can probably run the proxy server on it. or your game may slow down (the proxy is quite CPU intensive). You can't run a Quake II server on the internal proxy machin (aztlan).

You only need regular user priveleges on aztlan and epona: root priveleges are NOT required. A typical Quake II game will generate about 2k/s of traffic (ie. it'll saturate a 28k8 baud modem).

Note that, due to the rather odd things the proxy has to do, you can't play Quake II on aztlan whilst it's proxying for maui. See the Technical Details section for more info.

First, start the proxy server on epona:

epona$ q2srv 15004 27910 aztlan.foo.bar quake2.games.foo.bar.net
The 15004 is just a random free port (>1024): if this doesn't work for you (you'll get something like `port already in use'), try some other large number. 27910 is the port on which Quake II servers listen.

You'll get something like:

Binding port 15004 (accepting from XXXXXXXX (aztlan.foo.bar))...
Listening for connections...
Now q2srv is ready to take packets from the client, and send them as if they came from epona. So, we start the client on aztlan:

aztlan$ q2clnt maui.foo.bar 27910 epona.zoop.eep 15004
The 27910 is the UDP port to proxy for (this is the port maui will try to contact to get to the Quake II server), and the 15004 is just the same number you gave the server.

You should get something like:

Binding TCP socket to any old address.
Trying to connect to XXXXXXXX (epona.zoop.eep), port 15004
Connected TCP. Opening UDP socket 27910... 
Waiting for first packet from 820fe880 ...
Now, start up Quake II on maui, bring up the console and do:

] connect aztlan.foo.bar
Note that you can't use Quake II's address book: I don't know why, but I suspect it's something to do with Quake trying to match up the hostname of the inside proxy and the hostname of the game server and failing.

And you should be in business. The client will say something like:

malloc 804d220
Got from XXXXXXXX (27901)
Starting packet forwarding for XXXXXXXX (port 27901)..
From port now fixed at XXXXXXXX
And the server will print up some acknowledgement and start printing lines of the form:

1.621588 k/s (2411561 bytes, 2355 k total)
1.849273 k/s (2427960 bytes, 2371 k total)
1.768825 k/s (2444370 bytes, 2387 k total)
To terminate the connection, interrupt the server by pressing ^C at its console. It will then show you the total transfer time and the cost of your game at 2p/Mbyte:

Your game cost 2454071 bytes (2396 K, 2 Mbyte), or 4.680769 p at 2p/Mbyte
(2p/Mbyte is the cost of a transatlantic transfer over JANET outside 1am-6am).

Why should I want to use this ?

There are a few reasons you might actually find this program useful:

The proxy consumes almost no CPU (it's only a 2k/s proxy anyway), so there's no reason not to use it where it would be an elegant solution.

Technical Details

Herein is the wisdom I've carefully hoarded for, oh, at least fifteen minutes: it's probably mostly wrong.

Quake II is actually rather civilised about its networking requirements: everything is done over plain UDP.

Subsequent communication is in the form of small (c. 30-byte) UDP packets. These packets are exceptionally sensitive to latency, and throttling seems not to take place at all: if the client starts lagging, tough. It appears as though these packets are statements about the world.

The proxy works like this. We shall call the machine that picks up UDP packets and turns them into TCP (and runs the client) the inside proxy machine, and the machine that picks up the TCP (and runs the server) the outside proxy machine:

  1. When the server starts up, it opens a TCP server socket on the outside proxy machine to listen for the client.
  2. The client starts up, and opens its UDP proxy port (usually 27910) on the inside proxy machine. It monitors activity on this port until it gets a packet from the source machine (this isn't confused by other UDP traffic, because only UDP traffic to 27910 on the inside proxy will be monitored).
  3. The client then finds out what port that packet was sent from (typically 27901), opens a TCP connection to the server, and sends the port number down the wire.
  4. The server then attempts to open that UDP port number on the outside proxy machine.
  5. Subsequently, both sides listen for packets to their UDP ports, and transmit them over the TCP connection, and listen for packets on the TCP connection to proxy to their TCP ports. From the Quake II server's PoV, the server (running on the outside proxy) looks like the client, whereas from the client's PoV, the client (running on the inside proxy machine) looks like the server.

    Attempts to proxy servers from other ports (eg. proxy port 24000 -> quake2 server port 27910) have failed, as have attempts to use a different proxy port on the outside proxy machine: this is why you can't run a Quake II server on the inside proxy, or a client on the outside proxy. It's also why you need one IP address per server proxied. Sorry :-(.

    Implementation Detail

    The implementation of the client and server are actually quite subtle: they both have the same basic structure, but since Quake II never throttles, we have to make sure we don't queue packets. Both the server and the client are structured as poll loops, with a select() at the top to ease the CPU load:

    I apologise for the code: it was written between about 10pm and midnight, and therefore suffers from both my RSI and my caffeine addiction...

    Config File Defines

    You shouldn't need to worry about these unless you're modifying the proxy, but :

    MAX_PACKET_SZ
    The maximum size of a packet: if you get packet overflows, increase this (but given that the ethernet MTU is 1500 and the modem MTU is 576. UDP packets 8k long will tend to get dropped by the routing infrastructure anyway).
    DELAY
    Irrelevant and useless.
    TGT_OFFSET
    The number to add to the port number sent by the inner proxy to get the UDP port number for the outer proxy: connection fails if it's anything other than 0.
    FLIP_PORT
    don't change this. It's a debugging define.
    DEBUG
    If defined, print out debugging info.
    STATS
    If defined, print out more detailed statistics.
    TIMING
    If defined, print out timing information.
    OLD_THROTTLE
    If defined, include some old throttling code that doesn't do anything any more.

    Licencing

    The proxy is licenced under either Larry Wall's Artistic Licence or the LGPL, at your option. Mail me if you want to do anything else with it.

    You can get copies of those licences either from me or from the Perl and glibc distributions respectively.

    Have Fun

    :-) - and send me some feedback if you find this proxy useful: you never know, I may be bored again some day :-).

    Richard, Richard.Watts@cl.cam.ac.uk. (aka. Kosh: I may not be able to shoot straight, but I can write low-latency proxies in an evening, so there :-)).


    Richard Watts <Richard.Watts@cl.cam.ac.uk>
    Last modified: Wed Oct 21 02:32:56 GMT 1998