Preventing ip conflicts in xen
Lately I was playing with stock xen kernel and virtualization, and I came across one relatively big problem. Let’s say I want to share my guest machines to, let’s say clients. You must give them root… because that’s whats VPS-es all all about, having root access to OS without having to purchase expensive hardware. Having that in mind they are by default untrusted and unpredictable, they can do god knows what in there!
So what caught my eye?
By default xen, and available management tools, don’t really have a way of sorting out IP conflicts in bridged mode. Basically you have bunch of scripts that will provision VPS alongside with IP address. Looking at the conf files you have vif and IP declarations in vm_xen.conf file.
But what is really preventing clients from entering:
ifconfig eth0 xxx.xxx.xxx.xxx
where xxx is ip of some super important server in same netmask?
Luckily, I came across this problem while still in testing, here’s what I found and came up with after 3 days intensive googling.
Xen supports IP declaration in vif statment of domU config file like this:
vif = ['ip=xxx.xxx.xxx.xxx, more parametars here....']
Also you can declare multiple IP's by simply putting space between them, like this:
vif = ['ip=xxx.xxx.xxx.xx1 xxx.xxx.xxx.xx2, more parametars here....']
For the purpose of IP conflict prevention make sure you declare unique mac address in vif section to.
So what does this IP thingy in vif do? Absolutely nothing (at least not yet)!
Next step is to install ebtables (http://ebtables.sourceforge.net/) on your distro. Then all we need to do is patch up a vif-bridge script located in /etc/xen/scripts/
So here’s the diff:
--- vif-bridge-org 2008-07-30 21:26:16.000000000 +0200 +++ vif-bridge 2008-07-30 21:30:59.000000000 +0200 @@ -57,15 +57,35 @@ online) setup_bridge_port "$vif" add_to_bridge "$bridge" "$vif" - ;; - + ebtables -N $vif + ebtables -P $vif DROP + ebtables -A INPUT -i $vif -j $vif + ebtables -A FORWARD -i $vif -j $vif + ebtables -A $vif -p ARP --arp-opcode 1 -j ACCEPT + + if [ ! -z "$ip" ] + then + for oneip in $ip + do + ebtables -A $vif -p IPv4 --ip-src $oneip -j ACCEPT + ebtables -A $vif -p IPv4 --ip-dst $oneip -j ACCEPT + ebtables -A $vif -p ARP --arp-opcode 2 --arp-ip-src $oneip -j ACCEPT + done + ebtables -A $vif --log-prefix="arp-drop" --log-arp -j DROP + fi + ;; + offline) do_without_error brctl delif "$bridge" "$vif" do_without_error ifconfig "$vif" down - ;; + do_without_error ebtables -D INPUT -i $vif -j $vif + do_without_error ebtables -D FORWARD -i $vif -j $vif + do_without_error ebtables -F $vif + do_without_error ebtables -X $vif + ;; esac-handle_iptable +#handle_iptable log debug "Successful vif-bridge $command for $vif, bridge $bridge." if [ "$command" == "online" ]
Asuming you use bridging scripts this effectively restricts IP address(es) from "vif = ['ip=xxx.xxx.xxx.xxx']" list to mac addresses in vif list. Restrictoins are done while booting up VPS and removed when powering it off. This way untrusted user is limited only to IP addresses defined in xen guest conf file. Trying to change existing IP address into another IP on network will only render that machine unresponsive.