Xen and the Art of Consolidation Tom Eastep 2006-02-19 2006 Thomas M. Eastep Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover, and with no Back-Cover Texts. A copy of the license is included in the section entitled GNU Free Documentation License.
Before Xen Prior to adopting Xen, I had a home office crowded with 5 systems, three monitors a scanner and a printer. The systems were: Firewall Public Server in a DMZ (mail) Private Server (wookie) My personal Linux Desktop (ursa) My work system (docked laptop running Windows XP). The result was a very crowded and noisy room.
After Xen Xen has allowed me to reduce the noise and clutter considerably. I now have three systems with two monitors. I've also replaced the individual printer and scanner with a Multifunction FAX/Scanner/Printer. The systems now include: Combination Firewall/Public Server/Private Server using Xen (created by building out my Linux desktop system). My work system. My Linux desktop (which is actually the old public server) All of the Linux systems run SuSE 10.0. Here is a high-level diagram of our network. As shown in this diagram, the Xen system has three physical network interfaces. These are: eth0 -- conntected to the switch in my office. That switch is cabled to a second switch in my wife's office where there is my wife's desktop and her networked printer. eth1 -- connected to our DSL "Modem". eth2 -- connected to a Wireless Access Point (WAP) that interfaces to our wireless network. There are three Xen domains. Dom0 (ursa) is used as a file server. One DomU (which is usually Domain 1) is used as a firewall and the other (normally Domain 2) is used as a public Web/FTP/Mail/DNS server. Because Xen only supports three virtual interfaces per DomU, I also use ursa as a gateway for our wireless network. Shorewall runs in both Dom0 and in the firewall domain. I have 1.5GB of RAM so I allocate 512MB to each server and 448MB to the firewall (the remaining 64MB is used by Xen). Here are the relevant configuration files for the three domains:
/boot/grub/menu.lst — here is the entry that boots Xen in Dom0 title XEN root (hd0,1) kernel /boot/xen.gz dom0_mem=524288 sched=bvt module /boot/vmlinuz-xen root=/dev/hda2 vga=0x31a selinux=0 resume=/dev/hda1 splash=silent showopts loopback.nloopbacks=1 module /boot/initrd-xen /etc/xen/auto/01-gateway — configuration file for the firewall domain # -*- mode: python; -*- # configuration name: name = "gateway" # usable ram: memory = 448 # kernel and initrd: kernel = "/boot/vmlinuz-xen" ramdisk = "/boot/initrd-xen" # boot device: root = "/dev/hdb2" # boot to run level: extra = "loopback.nloopbacks=0 3" # network interface: vif = [ 'mac=aa:cc:00:00:00:02, bridge=xenbr0', 'mac=aa:cc:00:00:00:03, bridge=xenbr1' , 'mac=00:a0:cc:63:66:89, bridge=xenbr2' ] hostname = name # storage devices: disk = [ 'phy:hdb2,hdb2,w' ] /etc/xen/auto/02-server — configuration file for the lists domain # -*- mode: python; -*- # configuration name: name = "server" # usable ram: memory = 512 # kernel and initrd: kernel = "/boot/vmlinuz-xen" ramdisk = "/boot/initrd-xen" # boot device: root = "/dev/hda3" # boot to run level: extra = "loopback.nloopbacks=0 3" # network interface: vif = [ 'mac=aa:cc:00:00:00:01, bridge=xenbr1' ] hostname = name # storage devices: disk = [ 'phy:hda3,hda3,w' ]
With all three Xen domains up and running, the system looks as shown in the following diagram. The zones correspond to the Shorewall zones in the Dom0 configuration. SuSE 10.0 includes Xen 3.0 which does not support PCI delegation; I therefore used a bridged configuration with three briges (one for each network interface). When Shorewall starts during boot, it creates the three bridges and the tap device tap0 and adds tap0 to xenbr0. tap0 is used by OpenVPN to secure the Wifi zone. Here is /etc/shorewall/init in Dom0:
cat >&3 << __EOF__ ${INDENT}for bridge in xenbr0 xenbr1 xenbr2; do ${INDENT} if [ -z "\$(/sbin/brctl show 2> /dev/null | fgrep \$bridge)" ]; then ${INDENT} /sbin/brctl addbr \$bridge ${INDENT} /sbin/ip link set dev \$bridge up ${INDENT} case \$bridge in ${INDENT} xenbr2) ${INDENT} mac=`ip link show eth1 | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'` ${INDENT} [ "$mac" = "fe:ff:ff:ff:ff:ff" ] || /sbin/ip link set dev eth1 addr fe:ff:ff:ff:ff:ff ${INDENT} /sbin/ip link set dev eth1 up ${INDENT} /sbin/brctl addif xenbr2 eth1 ${INDENT} ;; ${INDENT} xenbr0) ${INDENT} if ! qt /sbin/ip link ls dev tap0; then ${INDENT} /usr/sbin/openvpn --mktun --dev tap0 ${INDENT} /sbin/ip link set dev tap0 up ${INDENT} /sbin/brctl addif xenbr0 tap0 ${INDENT} fi ${INDENT} ;; ${INDENT} esac ${INDENT} fi ${INDENT}done __EOF__
I run Shorewall 3.1 so this script runs at compile-time rather than at run time. The "\$"'s above cause evaluation of the variables or expressions to be deferred until run time. To use this script on earlier releases: Remove the first and last lines. Remove the leading "${INDENT}" from the remaining lines. Replace "\$/ with "$". The goals for the Shorewall configuration in Dom0 are as follows: Isolate the Wireless Network so that only VPN access to the local lan is allowed. Allow traffic to flow unrestricted through the three switches. Ensure that there is no stray traffic between the zones. The configuration is a simple one:
/etc/shorewall/zones: #ZONE TYPE OPTIONS IN OUT # OPTIONS OPTIONS fw firewall Wifi ipv4 loc ipv4 dmz ipv4 net ipv4 #LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE /etc/shorewall/policy: #SOURCE DEST POLICY LOG LIMIT:BURST # LEVEL Wifi all REJECT info dmz all REJECT info all dmz REJECT info net all REJECT info all net REJECT info all all ACCEPT #LAST LINE -- DO NOT REMOVE /etc/shorewall/interfaces: #ZONE INTERFACE BROADCAST OPTIONS Wifi eth2 192.168.3.255 dhcp,maclist loc xenbr0 192.168.1.255 dhcp,routeback dmz xenbr1 - routeback net xenbr2 - routeback #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE /etc/shorewall/rules: #ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ # PORT PORT(S) DEST LIMIT GROUP #SECTION ESTABLISHED #SECTION RELATED SECTION NEW ############################################################################################################# # # BS Address rules # DROP Wifi net:15.0.0.0/8 DROP Wifi net:16.0.0.0/8 # # Insecure Wireless to local network # ACCEPT Wifi loc udp 500 ACCEPT Wifi loc udp 53 ACCEPT Wifi loc udp 4500 Ping/ACCEPT Wifi loc # # Insecure Wireless to firewall # ACCEPT Wifi fw udp 123 #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE
In the firewall DomU, I run a conventional three-interface firewall with Proxy ARP DMZ -- it is very similar to the firewall described in the Shorewall Setup Guide. The firewall runs a routed OpenVPN server to provide roadwarrior access for our two laptops. Here is the firewall's view of the network: The Shorewall configuration files are shown below. All routing and secondary IP addresses are handled in the SuSE network configuration.
/etc/shorewall/shorewall.conf: TARTUP_ENABLED=Yes VERBOSITY=0 LOGFILE=/var/log/firewall LOGFORMAT="Shorewall:%s:%s:" LOGTAGONLY=No LOGRATE= LOGBURST= LOGALLNEW= BLACKLIST_LOGLEVEL= MACLIST_LOG_LEVEL=$LOG TCP_FLAGS_LOG_LEVEL=$LOG RFC1918_LOG_LEVEL=$LOG SMURF_LOG_LEVEL=$LOG LOG_MARTIANS=No IPTABLES=/usr/sbin/iptables PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin SHOREWALL_SHELL=/bin/bash SUBSYSLOCK= MODULESDIR= CONFIG_PATH=/etc/shorewall:/usr/share/shorewall RESTOREFILE=standard IPSECFILE=zones IP_FORWARDING=On ADD_IP_ALIASES=No ADD_SNAT_ALIASES=No RETAIN_ALIASES=No TC_ENABLED=Internal CLEAR_TC=Yes MARK_IN_FORWARD_CHAIN=Yes CLAMPMSS=Yes ROUTE_FILTER=No DETECT_DNAT_IPADDRS=Yes MUTEX_TIMEOUT=60 ADMINISABSENTMINDED=Yes BLACKLISTNEWONLY=Yes DELAYBLACKLISTLOAD=No MODULE_SUFFIX= DISABLE_IPV6=Yes BRIDGING=No DYNAMIC_ZONES=No PKTTYPE=No RFC1918_STRICT=Yes MACLIST_TTL=60 SAVE_IPSETS=No MAPOLDACTIONS=No FASTACCEPT=Yes BLACKLIST_DISPOSITION=DROP MACLIST_TABLE=mangle MACLIST_DISPOSITION=DROP TCP_FLAGS_DISPOSITION=DROP /etc/shorewall/zones: #ZONE TYPE OPTIONS IN OUT # OPTIONS OPTIONS fw firewall net ipv4 #Internet loc ipv4 #Local wired Zone dmz:loc ipv4 #DMZ -- server running in virtual machine at 206.124.146.177 vpn ipv4 #Open VPN clients #LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE /etc/shorewall/policy: #SOURCE DEST POLICY LOG LIMIT:BURST # LEVEL $FW $FW ACCEPT $FW net ACCEPT loc net ACCEPT $FW vpn ACCEPT vpn net ACCEPT vpn loc ACCEPT loc vpn ACCEPT $FW loc ACCEPT loc $FW REJECT $LOG net all DROP $LOG 10/sec:40 all all REJECT $LOG #LAST LINE -- DO NOT REMOVE /etc/shorewall/params (edited): MIRRORS=<comma-separated list of Shorewall mirrors> NTPSERVERS=<comma-separated list of NTP servers I sync with> POPSERVERS=<comma-separated list of server IP addresses> LOG=info INT_IF=eth0 DMZ_IF=eth1 EXT_IF=eth3 OMAK=<IP address at our second home> #LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE /etc/shorewall/interfaces: #ZONE INTERFACE BROADCAST OPTIONS net $EXT_IF 206.124.146.255 dhcp,norfc1918,logmartians,blacklist,tcpflags,nosmurfs dmz $DMZ_IF 192.168.0.255 logmartians loc $INT_IF 192.168.1.255 dhcp,routeback,logmartians vpn tun+ - #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE /etc/shorewall/nat: #EXTERNAL INTERFACE INTERNAL ALL LOCAL # INTERFACES 206.124.146.178 $EXT_IF 192.168.1.5 No No 206.124.146.180 $EXT_IF 192.168.1.6 No No #LAST LINE -- ADD YOUR ENTRIES ABOVE THIS LINE -- DO NOT REMOVE /etc/shorewall/masq: #INTERFACE SUBNET ADDRESS PROTO PORT(S) IPSEC +$EXT_IF:192.168.1.1 0.0.0.0/0 192.168.1.254 $EXT_IF 192.168.0.0/22 206.124.146.179 #LAST LINE -- ADD YOUR ENTRIES ABOVE THIS LINE -- DO NOT REMOVE /etc/shorewall/proxyarp: #ADDRESS INTERFACE EXTERNAL HAVEROUTE PERSISTENT 192.168.1.1 $EXT_IF $INT_IF yes 206.124.146.177 $DMZ_IF $EXT_IF yes #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE /etc/shorewall/actions: #ACTION Mirrors # Accept traffic from Shorewall Mirrors #LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE /etc/shorewall/action.Mirrors: #TARGET SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE # PORT PORT(S) DEST LIMIT ACCEPT $MIRRORS #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE /etc/shorewall/rules: SECTION NEW ############################################################################################################################################################################### #ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ # PORT PORT(S) DEST LIMIT GROUP ############################################################################################################################################################################### REJECT:$LOG loc net tcp 25 REJECT:$LOG loc net udp 1025:1031 # # Stop NETBIOS crap # REJECT loc net tcp 137,445 REJECT loc net udp 137:139 # # Stop my idiotic work laptop from sending to the net with an HP source/dest IP address # DROP loc:!192.168.0.0/22 net ############################################################################################################################################################################### # Local Network to Firewall # DROP loc:!192.168.0.0/22 fw # Silently drop traffic with an HP source IP from my XP box ACCEPT loc fw tcp 22 ACCEPT loc fw tcp time,631,8080 ACCEPT loc fw udp 161,ntp,631 ACCEPT loc:192.168.1.5 fw udp 111 DROP loc fw tcp 3185 #SuSE Meta pppd Ping/ACCEPT loc fw REDIRECT loc 3128 tcp 80 0 !192.168.0.7,206.124.146.177 ############################################################################################################################################################################### # Secure wireless to Firewall # REDIRECT vpn 3128 tcp 80 ############################################################################################################################################################################### # Road Warriors to Firewall # ACCEPT vpn fw tcp ssh,time,631,8080 ACCEPT vpn fw udp 161,ntp,631 Ping/ACCEPT vpn fw ############################################################################################################################################################################### # Road Warriors to DMZ # ACCEPT vpn dmz udp domain ACCEPT vpn dmz tcp www,smtp,smtps,domain,ssh,imap,https,imaps,ftp,10023,pop3 - Ping/ACCEPT vpn dmz ############################################################################################################################################################################### # Local network to DMZ # ACCEPT loc dmz udp domain LOG:$LOG loc:64.126.128.0/18 dmz tcp smtp ACCEPT loc dmz tcp ssh,smtps,www,ftp,imaps,domain,https - ACCEPT loc dmz tcp smtp Trcrt/ACCEPT loc dmz ############################################################################################################################################################################### # Internet to ALL -- drop NewNotSyn packets # dropNotSyn net fw tcp dropNotSyn net loc tcp dropNotSyn net dmz tcp ############################################################################################################################################################################### # Internet to DMZ # ACCEPT net dmz udp domain LOG:$LOG net:64.126.128.0/18 dmz tcp smtp ACCEPT net dmz tcp smtps,www,ftp,imaps,domain,https - ACCEPT net dmz tcp smtp - 206.124.146.177,206.124.146.178 ACCEPT net dmz udp 33434:33454 Mirrors net dmz tcp rsync Limit:$LOG:SSHA,3,60\ net dmz tcp 22 Trcrt/ACCEPT net dmz ############################################################################################################################################################################## # # Net to Local # # When I'm "on the road", the following two rules allow me VPN access back home using PPTP. # DNAT net loc:192.168.1.4 tcp 1729 DNAT net loc:192.168.1.4 gre # # Roadwarrior access to Ursa # ACCEPT net:$OMAK loc tcp 22 Limit:$LOG:SSHA,3,60\ net loc tcp 22 # # ICQ # ACCEPT net loc:192.168.1.3 tcp 113,4000:4100 # # Bittorrent # ACCEPT net loc:192.168.1.3 tcp 6881:6889,6969 ACCEPT net loc:192.168.1.3 udp 6881:6889,6969 # # Real Audio # ACCEPT net loc:192.168.1.3 udp 6970:7170 # Skype # ACCEPT net loc:192.168.1.6 tcp 1194 # # Traceroute # Trcrt/ACCEPT net loc:192.168.1.3 # # Silently Handle common probes # REJECT net loc tcp www,ftp,https DROP net loc icmp 8 ############################################################################################################################################################################### # DMZ to Internet # ACCEPT dmz net udp domain,ntp ACCEPT dmz net tcp echo,ftp,ssh,smtp,whois,domain,www,81,https,cvspserver,2702,2703,8080 ACCEPT dmz net:$POPSERVERS tcp pop3 Ping/ACCEPT dmz net # # Some FTP clients seem prone to sending the PORT command split over two packets. This prevents the FTP connection tracking # code from processing the command and setting up the proper expectation. The following rule allows active FTP to work in these cases # but logs the connection so I can keep an eye on this potential security hole. # ACCEPT:$LOG dmz net tcp 1024: 20 ############################################################################################################################################################################### # Local to DMZ # ACCEPT loc dmz udp domain,xdmcp ACCEPT loc dmz tcp www,smtp,smtps,domain,ssh,imap,rsync,https,imaps,ftp,10023,pop3,3128 Trcrt/ACCEPT loc dmz ############################################################################################################################################################################### # DMZ to Local # ACCEPT dmz net:192.168.1.254 udp 123 ACCEPT dmz loc:192.168.1.5 tcp 21 Ping/ACCEPT dmz loc ############################################################################################################################################################################### # DMZ to Firewall -- ntp & snmp, Silently reject Auth # ACCEPT dmz fw tcp 161,ssh ACCEPT dmz fw udp 161 REJECT dmz fw tcp auth Ping/ACCEPT dmz fw ############################################################################################################################################################################### # Internet to Firewall # REJECT net fw tcp www,ftp,https DROP net fw icmp 8 ACCEPT net fw udp 33434:33454 ACCEPT net:$OMAK fw udp ntp ACCEPT net fw tcp auth ACCEPT net:$OMAK fw tcp 22 Limit:$LOG:SSHA,3,60\ net fw tcp 22 Trcrt/ACCEPT net fw ############################################################################################################################################################################### # Firewall to DMZ # ACCEPT fw dmz tcp domain,www,ftp,ssh,smtp,https,993,465 ACCEPT fw dmz udp domain REJECT fw dmz udp 137:139 Ping/ACCEPT fw dmz ############################################################################################################################################################################## # Avoid logging Freenode.net probes # DROP net:82.96.96.3 all #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE