How to create a xen dom0 firewall for your DomU guests

How to create a xen dom0 firewall for your DomU guests

While working on my Enomalism SimpleFirewall module, I had some difficulties getting a reliable firewall up and running. It turns out that XEN firewalls are a little tricky to configure. Who knew.

So while you COULD use Enomalism to easily set up your virtual machines, some people INSIST on doing things the hard way, so here are some quick details...

When XEN creates a domain in it's default configuration (xen-bridge and vif-bridge), it creates a virtual interface with a particular numbering scheme. If you create a virtual machine named george, which starts as domid 2, it will have a virtual interface labelled as vif2.0 for it's network traffic. If you have a virtual machine that contains iptables (using either pygrub or HVM), you can easily configure iptables on the DomU to protect this machine. Sadly, this is not usually the case, and there are some SNAFUs if you are running a linux non pygrub machine (which is normally my preference).

The problem lies with the kernel, and it's built in iptables features, or the lack thereof. When you run non pygrub linux guests, it is really easy to upgrade the kernel, since you can share it among the various domu machines by specifying the same boot kernel as your dom0. Most of the time, however, there are modules that have to be loaded to enable iptables. Bummer. Unless you want to manually copy these very upgrade (or mount the modules as a read only NFS mount, yuck), you are going to need to firewall externally.

To firewall externally, the Dom0 is the easiest way to do it. First, we want to get the vif of the running machine.

$>xm list george
george    2   128     1     -b----      4.1

So george is domid 2... We should probably keep all of the "allow" rules in a separate chain for that DomU, so let's make one:

/sbin/iptables -N george
Now we will want to create a rule that diverts all of the packets from the FORWARD builtin chain to the george chain. What we are doing here is making sure that all traffic to vif2.0 gets run through the george chain to check for allowed packets, then we drop anything that was not explicitly allowed. Since we are dropping ALL packet types, even SYN scanning will fail, and hackers will need to actually attempt connections (which is slower) to scan for running services. Here are the commands:
$>#First we insert a rule that forwards ALL packets to the george chain when they are coming from peth0 and going to vif2.0:
$>iptables -I FORWARD -m physdev --physdev-in peth0 --physdev-out vif2.0 -j george
$>#Next we want to allow SSH traffic in the george chain. Note how I use RETURN instead of ALLOW.
$>iptables -A george -p tcp -m tcp --dport 22 -j RETURN
$>#Now we want to allow related stuff (bidirectional SSH traffic)
$>iptables -A george -p tcp -m state --state RELATED,ESTABLISHED -j RETURN 
$>#Now we add a rule to DROP everything else.
$>iptables -A george -j DROP
As you can imagine, this is pretty easy to script. Something like this:
#!/bin/bash
#run makefirewall.sh domUname
DOMID=/usr/sbin/xm list $1 | grep "$1" | awk '{print $2}'
/sbin/iptables -N "$1"
/sbin/iptables -I FORWARD -m physdev  --physdev-in peth0 --physdev-out vif${DOMID}.0 -j "$1"
/sbin/iptables -A "$1" -p tcp -j LOG 
/sbin/iptables -A "$1" -p tcp -m tcp --dport 22 -j RETURN 
/sbin/iptables -A "$1" -p tcp -m state --state RELATED,ESTABLISHED -j RETURN 
/sbin/iptables -A "$1" -p tcp -j DROP
echo "Done creating firewall for $1"

You could pretty easily add your script here to one of the startup scripts, or even append it to the start scripts with a little effort. You might want to create an iptables flush and delete script for shutdown as well. Sadly, there are no good python bindings that handle the bridging options at this time :(

Home Home
http://www.reaysmoving.com/