Playing Multiplayer Games over a VPN
by Anthony Volodkin (anthonyv@brainlink.com

Update 08/13/04: Before you do anything, check out the VPN Gaming FAQ

Introduction
Almost every single Virtual Private Network implementation complies with a widely accepted standard that prevents any routing device from forwarding broadcast packets. This is absolutely essential to the proper operation of routers; however, it is often required to forward broadcast packets across VPN connections to achieve true LAN functionality. There are many applications that require these packets to be transmitted to the other hosts on the network.

The ability to send and receive broadcast packets is absolutely crucial in multiplayer gaming. The majority of modern games feature a LAN gaming option which allows mutiple players to play together if they are connected over a network. This does not work over most common VPN setups because nearly all of the games use UDP broadcasts to initiate games, send chat messages to other players, and announce other information; and those packets are not transmitted over VPNs.

Although most games also feature an Internet game mode that is usually adequate for playing another random person or group of people over the Internet, it is quite cumbersome to use if one wants to play a game with a few friends. The game servers are often unreliable and impose all sorts of restrictions on the users. Issues with latency and network speed also arise when a poorly connected host participates in a multiplayer game. Performance usually degrades for all other players, as the result. When one plays with a few friends however, all of the latency and performance issues can usually be brought under control. Hence, if one is only interested in playing with a small group of friends, a VPN solution is necessary.

Windows file sharing is another application that can take advantage of this setup, however I will focus on the uses of VPN technology in gaming. After configuring your VPN to work with games, modifying the setup to work with Windows printing and file sharing is trivial.

Our example VPN setup uses a FreeBSD 4.7-RELEASE machine running mpd 3.12 in order to provide PPTP connections to Windows XP and 2000 clients. In addition to this software we use a custom perl script and module designed to rewrite UDP broadcasts into routable packets and send them to appropriate machines. It's also important to note that to simplify the implementation of this system we use a machine that already functions as a network gateway to the outside world.

Preparation
Before configuring any VPN server software we assume that your machine is already configured to be a functional gateway using natd and ipfw. If for some reason your machine is not a network gateway, it is still necessary to compile the FreeBSD kernel with the IPFIREWALL and DIVERT options enabled.

Configuring mpd
First, we install mpd 3.12 from ports. It is found in /usr/ports/net/mpd. After compiling it, we must edit several files in the /usr/local/etc/mpd/ directory.

First file we edit is mpd.links where we setup the type of link we will use.

pptp1:
   set link type pptp
   set pptp self 200.1.1.1
   set pptp enable incoming
   set pptp disable originate

This configures a pptp link that listens on the IP address of 200.1.1.1 and only accepts incoming connections. We expect to have multiple simultaneous users so we also made identical entries while changing the labels to “pptp2”, “pptp3”, etc.

The next step is to setup the mpd.conf file. Here is a sample entry that configures all of the settings of the pptp connection:

default:
   load pptp1 # Makes mpd load this connection at start
pptp_standard:
   set ipcp dns 200.1.1.230 # Sets the dns server supplied to clients. This is optional.
   set iface disable on-demand
   set iface enable proxy-arp 
   set iface idle 1800
   set bundle disable multilink
   set link yes acfcomp protocomp
   set link no pap
   set link enable chap
   set link keep-alive 10 60
   set ipcp yes vjcomp
   set bundle enable compression
   set ccp no mppc # Disables Microsoft encryption
   set ccp no mpp-e40 # Disable 40-bit encryption
   set ccp no mpp-e128 # Disable 128-bit encryption
   set ccp no mpp-stateless # Disable the stateless encryption mode
   set iface up-script /usr/local/etc/mpd/set_routes.pl 
pptp1:
   new -i ng0 pptp1 pptp1  # Creates a new netgraph device
	set ipcp ranges 192.168.1.1/32 192.168.1.0/24
load pptp_standard # Uses the settings from the above template.

The above config tells mpd to load the connection 'pptp1' as soon as the program is started. It then configures pptp1 to use the netgraph device ng0 and specifies the subnet from which to assign IP addresses. Then it loads the remaining settings from the pptp_standard template. This allows us to make additional connections (pptp2, pptp3, etc) to allow for simultaneously connected clients. The set_routes.pl script is needed to set routes for the connecting players. The details are discussed in the next section. Consult the mpd manual in /usr/local/share/doc/mpd/ for the explanation of other settings used here.

Finally, we have to set the username and password the client has to use, in mpd.secret:

joe "password" 192.168.1.101
The above line assigns 192.168.1.101 to user Joe. In this particular application it is important to allocate a static IP address for each user since we also need to automatically configure routes for some of those users.

Setting up routing
More configuration is necessary in order to allow games running on client machines to see each other. When players connect to your VPN, several scenarios are possible:

Forwarding Broadcasts
As mentioned earlier, UDP broadcasts are not forwarded across interfaces. To resolve this problem we can use a PERL script found here. This script requires NetPacket::IP, NetPacket::UDP and a modified version of the Net::Divert module which can be found here until the author integrates these changes into the official distribution. The script listens for packets on a specified port and upon receiving them, rewrites the destination field in the packet's header and then sends a copy to all of the hosts in a list. To figure out what IP to add to the list of recipients, we have to find out what IP the game uses to announce itself. Since this is what we did when setting up routing, we can just refer to that data. Note that all players should be added in this file independent of whether they needed static routes or not. In addition to executing the script, we also have to add ipfw rules to forward broadcasts that we receive from the VPN clients to our script.

ipfw add divert 9999 udp from any to 255.255.255.255 via fxp0
ipfw add divert 9999 udp from any to 255.255.255.255 via ng0
ipfw add divert 9999 udp from any to 255.255.255.255 via ng1

The above rules divert all broadcasts received on the internal network interface fxp0 and on the vpn interfaces ng0 and ng1 to the script. If we expect more players we should add corresponding entries for ng2, ng3 and so on. At this point you should be able to play a LAN game with any number of remote players along with LAN players that use the VPN server as their network gateway.

Comments or corrections are welcome at anthonyv@brainlink.com . Special thanks to Nathan J. Yoder for his input. Last Updated 4/8/2003