I had been tasked with finding a way to load balance UDP on AWS. Normally we would use ipvsadm in at layer 4 DR but because of the limitations in EC2 this is not possible so another method was needed.
So this is a short guide on how to get a simple UDP load balancer running. We will be using pen, it is described as a simple tcp load balancer and has been around for a while.

UPDATE:

Our current version of Enterprise AWS for EC2 now fully supports UDP load balancing in high performance layer 4 NAT mode.

Even though it is described as a TCP loadbalancer the Zen loadbalancer project has written a patch which will allow pen to load balance UDP which you can download from http://sourceforge.net/projects/zenloadbalancer/files/zenlb_pen_c.patch/

Once you have downloaded the source code, patch and uncompressed them in the same folder you will need to apply the patch by simply running.

root@penudp:~/pen-0.18.0# patch pen.c zenlb_pen_c.patch

From here it is just the normal build.

./configure
make
make install

And that's it, so now if we run pen we see it now has UDP support.

root@penudp:~/pen-0.18.0# pen
usage:
pen [-C addr:port] [-X] [-b sec] [-S N] [-c N] [-e host[:port]]
[-t sec] [-x N] [-w dir] [-HPWadfhrs]
[-o option]
[-E certfile] [-K keyfile]
[-G cacertfile] [-A cacertdir]
[-Z] [-R] [-L protocol]
[host:]port h1[:p1[:maxc1[:hard1[:weight1[:prio1]]]]] [h2[:p2[:maxc2[:hard2[:weight2[:prio2]]]]]] ...
-B host:port abuse server for naughty clients
-C port control port
-T sec tracking time in seconds (0 = forever) [0]
-H add X-Forwarded-For header in http requests
-U use udp protocol support

Now to test this I have just brought up a couple of DNS servers running bind.
These have the address 192.168.74.221 and 192.168.74.222. So we start pen by running:

root@penudp:/# pen -r -U 53 192.168.74.221:53 192.168.74.222

This will start pen listening on port 53 and balance the servers 192.168.74.221 and 192.168.74.222 in round robin mode.

We can then check its running with:

root@penudp:/# netstat -tnulp | grep pen
udp 0 0 0.0.0.0:53 0.0.0.0:* 29661/pen

To test it is working I have enabled logging on the DNS servers and will use dig and specify the pen server as the name server.

root@penudp:/# dig @127.0.0.1 bbc.com
root@penudp:/# dig @127.0.0.1 microsoft.com

Then looking at the bind logs we can see that the connections are being correctly made to each server.

ben@bindd1:~$ tail -n 1 /var/log/syslog
Aug 22 12:42:57 bindd1 named[1372]: client 192.168.65.219#44048: query: bbc.com IN A +E (192.168.74.221)
root@bind2:/home/ben# tail -n 1 /var/log/syslog
Aug 22 12:43:07 bind2 named[6827]: client 192.168.65.219#57100: query: microsoft.com IN A +E (192.168.74.222)