I was recently asked to help someone configure NAT for VMs running on Xen with OpenSuse 13. I don’t have a ton of experience with Xen, but I must say this was much more difficult than I anticipated. I believe the trouble stems from the recent change to the xl toolstack for Xen and the lack of support within OpenSuse for it although I’d be open to anyone with more experience correcting me on the subject. I did eventually get it working and I’ve detailed the solution below.
First, verify that virtual bridge 0 or a similair bridge exists, if not create it because we will need this bridge to perform the NAT.
brctl addbr virbr0
Don’t expect to see any interfaces under virbr0, just make sure it exists.
Give it an IP address on the private network, this address is being assigned to the host and will be used as the default gateway on the VMs
ifconfig virbr0 192.168.10.1
Determine if ip forwarding is enabled because it is required for NAT
If the command responds with a zero ( 0 ) then it is disabled, a 1 for enabled.
If not enable it:
echo 1 > /proc/sys/net/ipv4/ip_forward
The above command only enables it until a reboot, to enable it permanently then edit the file /etc/sysctl.conf:
/etc/sysctl.conf: net.ipv4.ip_forward = 1
NAT is accomplished by altering rules within the iptables Linux firewall.
This command adds a rule into the INPUT chain of the filter table that allows packets sourced by the network 192.168.10.0/24 (Our private network for virtual machines) to be accepted. For more information on the iptables tables and chains see this write up: http://www.thegeekstuff.com/2011/01/iptables-fundamentals/
iptables --table filter --insert INPUT --source 192.168.10.0/255.255.255.0 --jump ACCEPT
This command adds a rule to the FORWARD chain of the filter table that allows our private network, so we accept the packet, then we forward the packet.
iptables --table filter --insert FORWARD --source 192.168.10.0/255.255.255.0 --jump ACCEPT
This command adds a rule in the FORWARD chain of the filter table to allow return packets back to the private network if the TCP state is established, so this is basically stateful firewalling to our private network.
iptables --table filter --insert FORWARD --destination 192.168.10.0/255.255.255.0 --match state --state ESTABLISHED,RELATED --jump ACCEPT
Finally this command inserts a rule into the POSTROUTING chain of the nat table to actually translate the outgoing (and incoming packets) to our private network.
iptables --table nat --insert POSTROUTING --source 192.168.10.0/255.255.255.0 --destination 192.168.10.0/255.255.255.0--jump MASQUERADE
You can see all of the iptables rules including the ones you just added using this command:
All of these commands can be added to a script, or the iptables rules can be added to a file named /etc/sysconfig/scripts/SuSEfirewall2-custom then edit /etc/sysconfig/SuSEfirewall2
Now that networking is setup on the host, we need to define the VM under the xl toolset. I have not been able to get this to work under virt-manager yet but if someone has, please comment to this post.
Edit a file we will call it vm-2.xl and add the following, I’m using inx 1.1 for this demo available here: http://inx.maincontent.net/name = “vm-2” uuid = “db6f4bac-c17f-8856-3b1e-2b249206e28f” maxmem = 1024 memory = 1024 vcpus = 1 builder = “hvm” kernel = “/usr/lib/xen/boot/hvmloader” boot = “d” pae = 1 acpi = 1 apic = 1 hap = 0 viridian = 0 rtc_timeoffset = 0 localtime = 0 on_poweroff = “destroy” on_reboot = “restart” on_crash = “restart” device_model = “/usr/lib64/xen/bin/qemu-dm” sdl = 0 vnc = 1 vncunused = 1 keymap = “en-us” disk = [ “file:/inx-1.1.iso,hdc:cdrom,r”] vif = [ ‘bridge=virbr0,ip=10.0.0.2,”mac=01:0c:29:3f:00:d8’] parallel = “none” serial = “pty” soundhw = “es1370”
You can export your virt-manager, virsh created VMs to xl using this command:
virsh -c xen:/// domxml-to-native xen-xm /etc/libvirt/libxl/vm-2.xml > vm-2.xl
Of course you will want to edit the resulting file so as to be like the listing above for my working VM.
This command instantiates the VM:
xl create vm-2.xl
You may get a couple of errors relating to the choices I made in the VM configuration file, but if it does not error out you should be able to check which interfaces are created with ifconfig.
You should have two interfaces vif2.0 and vif2.0-emu that are part of a bridge virbr0 or something similiar
If you sniff on vif2.0-emu you should see traffic from the VM
tcpdump -i vif2.0-emu
Of course the VM needs to be configured with an IP address like 192.168.10.x/24 and a gateway of 192.168.10.1 and set the DNS in /etc/resolv.conf
Run the following command to get a console on your VM
xl vncviewer vm-2
sudo ifconfig eth0 192.168.10.10 netmask 255.255.255.0 sudo route add -net default gw 192.168.10.1
If all goes well, you should be able to ping google from the VM and get a response:
64 bytes from 18.104.22.168: icmp_seq=1 ttl=47 time=46.063 ms 64 bytes from 22.214.171.124: icmp_seq=2 ttl=47 time=46.178 ms 64 bytes from 126.96.36.199: icmp_seq=3 ttl=47 time=49.135 ms 64 bytes from 188.8.131.52: icmp_seq=4 ttl=47 time=46.251 ms