Age of Empires has a very nice feature: two people can play the same civilization, as a single player. This is different from teaming up, because you can give conflicting orders to the villagers. My wife and I love to play this way, especially when we can play against... I mean, with... our other friends.

Unfortunately, if you want to play with multiple players behind a firewall, and at least one player outside the firewall, you're out of luck: DirectPlay doesn't allow you to remap the ports.

One solution is to set up a VPN. That way the players behind the firewall can keep their IP addresses, and the players outside the firewall look like they're on the local LAN. Businesses often use a VPN service, and one even comes with Windows (PPTP). I recently set up a gaming LAN with OpenVPN. Here's how.

VPN stands for Virtual Private Network. There are several kinds, and one even comes with Windows (PPTP). Unfortunately, the Windows version has been discovered to be insecure. Since my entire internal network would be exposed to the outside world, I needed good encryption. Besides, my firewall/gateway runs Linux -- and so do I, when I can. I needed something that would work on multiple platforms.

The games I was using didn't necessarily support TCP/IP, either. I needed a VPN solution that would send all the network traffic, not just the TCP traffic like a proxy.

OpenVPN does all that and more. It wasn't even difficult to set up.

What to Get

To make this work, you'll need an OpenVPN server for your platform. I'm running Debian Linux on my gateway, so I just used apt-get to pull down the official distribution and all its dependencies.

Each machine outside your network that you want to add to your VPN will need a client.

About Bridging

Since we're talking about a gaming VPN, we need to support more than TCP/IP. Stuff like IPX and UDP are common for multiplayer games. That means we can't use standard "tunnel" mode. We need "bridging" mode. Everything from the internal LAN and the connected machines will get copied across the Internet. Including your Windows shares, your network printers... everything. That's why we want encryption. Yes, you CAN turn off encryption to squeeze a bit of extra performance out, but then everything on your network is easily deciphered by outsiders. Don't do it!

That said, bridging will solve all our gaming problems. And it's easy to set up: just use "dev tap0" in your configuration file, as we'll see below.

Setting Up The Clients

By default, OpenVPN uses certificates for authentication. That's truly cool, because your friends can connect to your VPN without using a password. It's not as difficult as it sounds, either. The OpenVPN FAQ covers it pretty thoroughly.

In short, you use the utilities in the easy-rsa directory on the server to generate a server certificate and key, then you generate a certificate and key for each client you expect to connect. I signed all my certificates, since the FAQ didn't say not to.

Before we hand out the certificates, let's get our configurations correct. For the best gaming performance, your VPN should be tunnelled through a UDP connection. That's default. When your buddies install OpenVPN, it'll make a new "Local Connection" in Windows. They'll want to rename it to something understandable anyway; since OpenVPN uses the connection's name, if they all rename it to the same thing, like "GameVPN", it'll be easier to send them configuration files they can use. Finally, we'll assume the keys should go in a keys/ directory off the OpenVPN installation directory. The players can change this stuff if they want, but then they'll have to edit their config files. Their call.

So, now we make a configuration file. I modified the sample file provided with the OpenVPN installation. There were only 8 lines to change. I changed the mode from "tun" to "tap" for bridging, set the "dev-node" line to match the expected network connection name, added a "fragment" line to work around pissy ISPs, changed the "remote" line to point at my server, and pointed to the certificates I was going to hand out. Here's a list of all the changes, as they appear in the config file:

dev tap
;dev tun
dev-node GameVPN
fragment 1024
remote my-server.com 1194
ca ..\\keys\\ca.crt
cert ..\\keys\NAME.crt
key ..\\keys\\NAME.key
Substitute the name you used when you made the certificate for NAME. Don't forget to use double-backslashes for Windows. Then you're done.

For convenience, I made a zip file with this structure for each player:

config\GameVPN.ovpn
keys\ca.crt
keys\NAME.crt
keys\NAME.key
I zipped it with a password, since those keys are important. Then I mailed each player his own zip file with his own certificates, and told them each to unzip the file in the OpenVPN directory. Nobody had to make any changes, and it worked like a charm.

Setting Up The Server

This was a bit more complicated. First, I wanted a static name for my server. Since it runs on DSL, it's got a dynamic IP. FreeDNS is easy and has lots of domains to choose from. I downloaded one of their scripts and modified it for my own nefarious purposes, then stuck it in ppp/ip-up.d so my server would re-register whenever its IP changed.

Next, I installed OpenVPN. No problem there. I followed the instructions in the FAQ. I copied their sample server configuration, modified the "dev" line to match my bridge adapter, changed the certificate lines, and added the fragment and mssfix lines. Be careful here; the client and server configurations must match!

Next was the biggest pain of the entire installation: configuring the box to start with the bridge set up. The file to modify under Debian is /etc/network/interfaces. I made a backup before editing, just in case. Then I changed the "auto eth0" section to:

# The VPN interface, with default settings for 10.x.x.x
auto br0
iface br0 inet static
        # First bring up the OpenVPN interface so we can bridge it
        pre-up /usr/sbin/openvpn --mktun --dev tap0
        # Copied from eth0
        address 10.10.10.127 # Gateway's inside static IP
        netmask 255.0.0.0
        network 10.0.0.0
        broadcast 10.255.255.255
        # New options
        #
        bridge_ports eth0 tap0
        # Forward delay in seconds
        bridge_fd 1
        bridge_stp off
        # DNS setup copied from eth0, too
        # dns-* options are implemented by the resolvconf package, if installed
        dns-nameservers 205.152.144.23 205.152.37.23 205.152.111.254
        dns-search default.net
        # And bring it down again when we're done
        post-down /usr/sbin/openvpn --rmtun --dev tap0

Since I had changed my connection from eth0 to br0, I had to change my firewall to use the new connection. No biggie; basically just changed a variable to br0 instead of eth0. But then, I built my firewall script by hand, so I made it easy to work with. I used ifconfig ppp0 to find the outside IP address, then used PPP_LOCAL=that_ip ./0firewall to reload my IPTables rules. A little testing assured me that my inside network could still do web and mail just fine.

Special Cases

Tunneling TCP Over SSH

To test my VPN, I wanted to connect from work. Another certificate, another email, and ten minutes later I was ready. Until I discovered that my work firewall, like most other firewalls, doesn't pass UDP.

Luckily, it did pass TCP, on both web and telnet ports. Why telnet, the least secure protocol ever? I don't know. But I've used this in the past to connect to my home network. I just run an SSH server on that port instead of a telnet server.

So I used PuTTY, a free SSH client, to log on to my firewall and add an additional OpenVPN server. How? I copied the GameVPN.conf file to WorkVPN.conf, changed the "proto udp" line to "proto tcp", removed the "fragment" and "mssfix" lines (since they don't work with TCP anyway), and changed "tap0" to "tap1". Four changes, all told. Then I added tap1 to my bridge in /etc/network/interfaces, opened up TCP port 1194 in my firewall, and rebooted.

Five minutes later I used PuTTY again to log in and verify that my bridges were configured as expected. (I just used ifconfig and made sure everything was reported.) Then I configured PuTTY to tunnel localhost:1194 to my-server.com:1194. Finally, I modified my GameVPN.ovpn file to use "remote 127.0.0.1 1194".

Worked like a charm. So I was tunnelling my network traffic through OpenVPN TCP, which was itself tunnelling through SSH. Weird, but working through the work firewall! And while SSH won't tunnel anything but TCP, OpenVPN was wrapping all the traffic in TCP packets. I could see shared drives on my home computers from work.

Proxy Servers

Then I found an easier way. The work firewall supported a proxy; all I had to do was change my "remote" line back to my dynamic DNS hostname and enable the "http-proxy" line. I filled it out with my proxy server and port, just like it shows in the sample. Boom! I was connected and using the VPN again. And this time, I wasn't slowed down by tunneling over SSH.

Troubleshooting

The Odd Man Out

Everybody was fine, except one of my buddies just couldn't connect. We went through loads of testing: we turned off all his firewalls, we tried to modify his routing tables, we pinged him over the normal net... we just couldn't figure it out. It started getting worse, too: his TeamSpeak server started disconnecting at irregular intervals. Turned out, his cable was so badly frayed it was disconnecting whenever it swayed in the wind. That fixed, we could use his TeamSpeak server again. Then we tried OpenVPN again.

The Odd Man Out, Part 2

Still no luck. He could see our games, but couldn't join. We tried letting him host, with identical results. Then I noticed my firewall going crazy on port 2300. The DirectPlay port. Ah-ha! But the IP was from his server to my server; not over the VPN. Why wasn't he redirecting all traffic to the VPN?

The nice thing about having friends is that they can compare their configurations. We were about to do some crazy routing stuff when we discovered that the broken connection had the same routing as a working one. So we stopped and tried something else. We copied a configuration file from a working connection, since we had been trying some crazy stuff with his. Still no dice. Then it hit me: maybe his computer wasn't doing the redirection. Maybe his ROUTER was. We disabled the configuration on his cable router for Age Of Empires serving; that might have helped, but not immediately. But as soon as we disabled all those other VPN configurations (PPTP, so on and so forth), we could immediately ping him.

Conclusion

So, there you have it; how I got an OpenVPN server running on my Linux box, allowing all my friends to connect to my home LAN for gaming. We've been running a Friday night "LAN" party ever since, occasionaly extending our VPN between Kansas and Florida.

We eventually switched to Hamachi, because it's designed for gaming, and provides better performance in some cases. Its configuration is much easier, since it's preset to use their servers (and it uses a little magic to bypass the server when possible). It even has a Linux version, so it has become the de-facto VPN for our Friday night "LAN" party.