Restoring Xen’s iptables rules

Those of you that use Xen may have noticed that, by default, Xen adds some iptables rules when a VM starts, so to ensure that some specific packets are actually forwarded to the virtual machines. If, for any reason, those rules are wiped away, it would be nice to recover them, wouldn't it?

I found out it's quite easy. The following script will just echo the iptables commands so you can safely test it on a running dom0. If it does something that you actually need, just wipe those echo's away!

#!/bin/bash

xm list | perl -alne 'next if not $F[1] > 0 ; print "@F[0,1]"' | while read VM ID 
do
  xm network-list $ID | perl -alne 'next if not $F[0] =~ m{^d+$} ; print $F[0]' | while read IFID
  do
    VIF="vif$ID.$IFID"
    echo iptables -A FORWARD -m physdev --physdev-in $VIF -s $VM -j ACCEPT
    echo iptables -A FORWARD -m physdev --physdev-in $VIF -p udp --sport bootpc --dport bootps -j ACCEPT
  done
done

I am using Perl here because I know it better than awk, but I am sure that awk can accomplish the same task as well as perl does.

Advertisement

It must be simpler than this…

I sat down scratching my head… that ntp client was syncing perfectly in unicast, and didn't create any association once configured in multicast. "Dah, the same old problem", I told to myself, "it's not getting the packets, setting a multicast route will fix it".

So I prepared the usual debugging set: one window running tcpdump 'dst port ntp', one window on the client running watch ntpq -c pe -c as, another one with tail -f /var/log/syslog | grep ntp and a free shell window. To my surprise, as soon as I fired up tcpdump, multicast ntp packets showed up. "What the…?!" I said. … Continue reading

Extracting information from iptables/fwbuilder logs

I use Firewall Builder for fast prototyping of my iptables configuration. When a firewall rule matches and logging for that rule is enabled, one line like this is added to /var/log/messages:

Sep  1 09:48:43 server kernel: [9490931.734574] RULE 12 -- DENY IN=eth0 OUT= MAC=a1:b2:c3:d4:e5:f6:00:11:22:33:44:55:66:77 SRC=1.2.3.4 DST=5.6.7.8 LEN=96 TOS=0x00 PREC=0x00 TTL=58 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=27754 SEQ=0 

(sensitive information has been forged, of course 🙂

Depending on the protocol, the same field is not always in the same position, e.g.: destination port (DPT) could be in position 23 or 24. So if you want to list, say, the inward interface, source address, destination address, protocol and destination port you need a smarter matching. This one-liner worked for me:

perl -alne 'if (m{RULE 12}) { my %field ; foreach $token (@F) { next unless $token =~ /=/ ; my ($k,$v) = split(/=/,$token,2) ; $field{$k} = $v } ; print qq{ @field{ qw{IN SRC DST PROTO DPT} } } }' /var/log/messages | sort | uniq -c | sort -nr   

That perl part means: if the line matches "RULE 12" then I initialize the %field hash. Then I go through the tokens and I select those that contain a "=", I split on the equal sign and fill the hash. Finally, when %field is ready, I print the interesting fields.

I don't need to worry about splitting the line and save the "tokens", because perl's autosplit (-a) takes care of it. And I don't need to bother about printing newlines, because -l takes care of it.

And the sort/uniq/sort dance is the old trick to count the occurrences of he same line in the output.