[libvirt] [PATCH v4 00/15] Network filtering (ACL) extensions for libvirt

Stefan Berger stefanb at us.ibm.com
Thu Mar 25 17:45:58 UTC 2010


This is a repost of this set of patches with some of the suggested fixes
applied and ipv6 support on the ebtables layer added.

Between V3 and V4 of this patch series the following changes were made:
- occurrences of typo 'scp' were changed to 'sctp'
- the root ebtables chain for each interface now has the previx of 'libvirt-'
- additional calls into tear-down functions in case something goes wrong
  while starting the qemu/kvm VM in 2nd level error paths
- additional functions in the driver interface to split up the application
  of firewall rules into 
  - creation of new firewall rules 'tree'
  - switch-over to new firewall rules 'tree', tear down of old one and
    renaming of new firewall 'tree'
  - tear down of new firewall rules 'tree' in case an error happend
    during update of several VMs.
- additional patch with example filters

The following set of patches add network filtering (ACL) extensions to
libvirt and enable network traffic filtering for VMs using ebtables and,
depending on the networking technology being used (tap, but not
macvtap), also iptables. Usage of either is optional and controlled
through filters that a VM is referencing.

The ebtables-level filtering is based on the XML derived from the CIM
network slide 10 (filtering) from the DMTF website
The XML we derived from this was discussed on the list before. On the
ebtables level we currently handle filtering of IPv4 and ARP traffic. 

  The iptables-level filtering is based on similar XML where XML nodes
described the particular protocol to filter for. Its extensions enable
the filtering of traffic using iptables for tcp, udp, icmp, igmp, sctp
and 'all' types of traffic. This list of protocols maps to the features
supported by iptables and only excludes protocols like 'esp', 'ah' and
'udplite'. Currently only bridging mode is supported and based on 
availability of the physdev match.

The filtering framework adds new libvirt virsh commands for managing
the filters. The 5 new commands are:
  - virsh nwfilter-list
  - virsh nwfilter-dumpxml <name of filter>
  - virsh nwfilter-define <name of file containing filter desc.>
  - virsh nwfilter-undefine <name of filter>
  - virsh nwfilter-edit <name of filter>

Above commands are similar to commands for already existing pools and as
such much of the code directly related to the above commands could be
borrowed from other drivers.

The network filters can either contain rules using the above mentioned
XML or contain references to other filters in order to build more
complex filters that form some sort of filter tree or can contain both.
An example for a filter referencing other filters would be this one

<filter name='demofilter4' chain='root'>
  <filterref filter='no-mac-spoofing'/>
  <filterref filter='no-mac-broadcast'/>
  <filterref filter='no-arp-spoofing'/>
  <filterref filter='allow-dhcp'>
    <parameter name='DHCPSERVER' value=''/>
  <filterref filter='no-other-l2-traffic'/>
  <filterref filter='recv-only-vm-ipaddress'/>
  <filterref filter='recv-only-vm-macaddress'/>
  <filterref filter='l3-test'/>
  <filterref filter='ipv6test'/>

A filter containing actual rules would look like this:

<filter name='no-mac-broadcast' chain='ipv4'>
  <rule action='drop' direction='out' priority='500'>
    <mac dstmacaddr='ff:ff:ff:ff:ff:ff'/>

The filter XML now also holds a priority attribute in the rule. This
provides control over the ordering of the applied ebtables/iptables
rules beyond their appearance in the XML.

The domain XML has been extended to reference a top level filter from
within each <interface> XML node. A valid reference to such a top level
filter looks like this: 

<interface type='bridge'>
  <source bridge='static'/>
  <filterref filter='demofilter4'>
    <parameter name='IP' value=''/>

In this XML a parameter IP is passed for instantiation of the referenced
filters, that may require the availability of this parameter. In the
above case the IP parameter's value describes the value of the IP
address of the VM and allows to enable those filters to be instantiated
that require this 'IP' variable. If a filter requires a parameter that
is not provided, the VM will not start or the interface will not attach
to a running VM. Any names of parameters can be provided for
instantiation of filters and their names and values only need to pass a
regular expression test. In a subsequent patch we will be adding
capability to allow users to omit the IP parameter (only) and enable
libvirt to learn the IP address of the VM and have it instantiate the
filter once it knows it. 

While virtual machines are running, it is possible to update their
filters. For that all running VMs' filter 'trees' are traversed to
detect whether the updated filter is referenced by the VM. If so, its
ebtables/iptable rules are applied. If one of the VMs' update fails
allupdates are rolled back and the filter XML update is rejected.

One comment about the instantiation of the rules: Since the XML allows
to create nearly any possible combination of parameters to ebtables or
iptables commands, I haven't used the ebtables or iptables wrappers.
Instead, I am writing ebtables/iptables command into a buffer, add
command line options to each one of them as described in the rule's XML,
write the buffer into a file and run it as a script. For those commands
that are not allowed to fail I am using the following format to run

cmd="ebtables <some options>"
if [ $? -ne 0 ]; then
echo "Failure in command ${cmd}."
exit 1


If one of the command fails in such a batch, the libvirt code is going
pick up the error code '1', tear down anything previously established
and report an error back. The actual error message shown above is
currently not reported back, but can be later on with some changes to
the commands running external programs that need to read the script's

One comment to patch 14: It currently #include's a .c file into a .c
file only for the reason so I don't have to change too much code once I
change code in the underlying patch. So this has to be changed. The
patch series works without patch 13, but then only supports ebtables.

The patches apply to the current tip. They pass 'make syntax-check' and
have been frequently run in valgrind for memory leak checks.

Looking forward to your feedback on the patches. 

Thanks and regards,
    Stefan and Gerhard

More information about the libvir-list mailing list