[libvirt] [RFC] Proposal for introduction of network traffic filtering capabilities for filtering of network traffic from and to VMs

Hello! The following is a proposal to introduce network traffic filtering capabilities for the network traffic originating from and destined to virtual machines. Libvirt's capabilities will be extended to allow users to describe what traffic filtering rules are to be applied on a virtual machine (using XML) and libvirt then creates the appropriate ebtables and iptables rules and applies those on the host when the virtual machine starts up, resumes after suspension or resumes on a new host after migration. libvirt tears down the traffic filtering rules when the virtual machine shuts down, suspends, or a VM is migrated to another host. It will also be possible to modify the filtering rules while a virtual machine is running. In this architecture we apply the firewall rules on the outside of the virtual machines on the Linux host and make use of the fact that virtual machines can be configured by libvirt to have their network traffic pass through the host and the host exposes (tap) 'backend' interfaces on which the firewall rules can be applied. The application of the firewall rules is optional and those who do not want to introduce a raw network throughput performance hit on their system due to the evaluation of every packet passing through the filtering chains, do not have to use these capabilities. An initial implementation would be done for libvirt's Qemu support. As stated above, the application of firewall rules on virtual machines will require some form of XML description that lets the user choose what type of filtering is to be performed. In effect the user needs to be able to tell libvirt which ebtables and iptables rules to generate so that the appropriate filtering can be done. We realize that ebtables and iptables have lots of capabilities but think that we need to restrict which capabilities can actually be 'reached' through this XML. The following proposal is based on an XML as defined by the DMTF ( http://www.dmtf.org/standards/cim/cim_schema_v2230/CIM_Network.pdf, slide 10) with extensions for processing of ARP packets.It gives control over the evaluation of Ethernet (MAC) frames, ARP packet data and IP header information. A (draft) XML skeleton in this case could look as follows: <FilterEntry> <Action>DROP|ACCEPT</Action> <!-- from FilterEntry --> <TrafficType>incoming [to VM]|outgoing [from VM]</TrafficType> <Hdr8021Filter> <HdrSrcMACAddr8021> </HdrSrcMACAddr8021> <HdrSrcMACMask8021> </HdrSrcMACMask8021> <HdrDestMACAddr8021> </HdrDestMACAddr8021> <HdrDestMACMask8021> </HdrDestMACMask8021> <HdrProtocolID8021> numeric and/or string? </HdrProtocolID8021> <HdrPriorityValue8021></HdrPriorityValue8021> <HdrVLANID8021> </HdrVLANID8021> </Hdr8021Filter> <ARPFilter> <HWType> </HWType> <ProtocolType> </ProtocolType> <OPCode> </OPCode> <SrcMACAddr> </SrcMACAddr> <SrcIPAddr> </SrcIPAddr> <DestMACAddr> </DestMACAddr> <DestIPAddr> </DestIPAddr> </ARPFilter> <IPHeadersFilter> <HdrIPVersion> </HdrIPVersion> <HdrSrcAddress> </HdrSrcAddress> <HdrSrcMask> </HdrSrcMask> <HdrDestAddress> </HdrDestAddress> <HdrDestMask> </HdrDestMask> <HdrProtocolID> numeric and/or string? </HdrProtocolID> <HdrSrcPortStart> </HdrSrcPortStart> <HdrSrcPortEnd> </HdrSrcPortEnd> <HdrDestPortStart> </HdrDestPortStart> <HdrDestPortEnd> </HdrDestPortEnd> <HdrDSCP> </HdrDSCP> </IPHeadersFilter> </FilterEntry> Since the ebtables and iptables command cannot accept all possible parameters at the same time, only a certain subset of the above parameters may be set for any given filter command. Higher level application writers will likely use a library that lets them choose which features they would want to have enforced, such as no-broadcast or no-multicast, enforcement of MAC spoofing prevention or ARP poisoning prevention, which then generates this lower level XML rules in the appropriate order of the rules. Further, we will introduce filter pools where a collection of the above filter rules can be stored and referenced to by virtual machines' individual interface. A reference to such a filter pool entry will be given in the interface description and may look as in the following draft XML: <interface type='bridge'> <source bridge='virbr0'/> <script path='vif-bridge'/> <firewall> <reference profile='generic-layer2' ip_address='10.0.0.1'/> <reference profile='VM-specific-layer3'/> </firewall> </interface> The above XML has one reference to a generic layer2 filter template XML that should be usable by multiple virtual machines but would need to be customized with interface-specific parameters. In this case, the IP address of the interface is explicitly provided in order to make the filter XML template a concrete XML for the particular interface. The MAC address of the interface is not explicitly provided since it will already have been randomly generated by libvirt at the point when this layer2 filter XML needs to be converted into concrete ebtables commands/rules. We still need to determine how the format of a template should look like, though an idea would be to indicate a placeholder for a VM's MAC address using THIS_MAC and similarly for the IP address with THIS_IP as placeholder. Further, we would introduce the management of filter 'pools'. Considering existing functionality in libvirt and CLI commands for similar type of management functionality, the following CLI commands would be added: virsh nwfilter-create <file> virsh nwfilter-destroy <profile name> virsh nwfilter-list <options> virsh nwfilter-dumpxml <profile name> virsh nwfilter-update <filename> (performs an update on an existing profile replacing all rules) possibly also: virsh nwfilter-edit <profile name> virsh nwfilter-create-from <profile name> Please let us know what you think of this proposal. Regards Stefan, Gerhard and Vivek

On Mon, Jan 11, 2010 at 12:55:27PM -0500, Stefan Berger wrote:
Hello!
The following is a proposal to introduce network traffic filtering capabilities for the network traffic originating from and destined to virtual machines. Libvirt's capabilities will be extended to allow users to describe what traffic filtering rules are to be applied on a virtual machine (using XML) and libvirt then creates the appropriate ebtables and iptables rules and applies those on the host when the virtual machine starts up, resumes after suspension or resumes on a new host after migration. libvirt tears down the traffic filtering rules when the virtual machine shuts down, suspends, or a VM is migrated to another host. It will also be possible to modify the filtering rules while a virtual machine is running. In this architecture we apply the firewall rules on the outside of the virtual machines on the Linux host and make use of the fact that virtual machines can be configured by libvirt to have their network traffic pass through the host and the host exposes (tap) 'backend' interfaces on which the firewall rules can be applied. The application of the firewall rules is optional and those who do not want to introduce a raw network throughput performance hit on their system due to the evaluation of every packet passing through the filtering chains, do not have to use these capabilities. An initial implementation would be done for libvirt's Qemu support.
It's relatively clear that this would not work with devices exposed natively to the domain, say though PCI passthough. I'm wondering what other case of limitiations could be found. Also this may not map well for other kind of hypervisors like VMWare, right ?
As stated above, the application of firewall rules on virtual machines will require some form of XML description that lets the user choose what type of filtering is to be performed. In effect the user needs to be able to tell libvirt which ebtables and iptables rules to generate so that the appropriate filtering can be done. We realize that ebtables and iptables have lots of capabilities but think that we need to restrict which capabilities can actually be 'reached' through this XML.
The following proposal is based on an XML as defined by the DMTF ( http://www.dmtf.org/standards/cim/cim_schema_v2230/CIM_Network.pdf, slide 10) with extensions for processing of ARP packets.It gives control over the evaluation of Ethernet (MAC) frames, ARP packet data and IP header information. A (draft) XML skeleton in this case could look as follows:
Humpf, extending astandard XML schemas is really bad practice. Even if you think that the extension may be accepted later, it may have different semantic for the same construct and that's a disaster. I would at least put the new elements in a separate namespace to avoid something insane if DMTF extends its specification.
<FilterEntry> <Action>DROP|ACCEPT</Action> <!-- from FilterEntry -->
<TrafficType>incoming [to VM]|outgoing [from VM]</TrafficType>
<Hdr8021Filter> <HdrSrcMACAddr8021> </HdrSrcMACAddr8021> <HdrSrcMACMask8021> </HdrSrcMACMask8021> <HdrDestMACAddr8021> </HdrDestMACAddr8021> <HdrDestMACMask8021> </HdrDestMACMask8021> <HdrProtocolID8021> numeric and/or string? </HdrProtocolID8021> <HdrPriorityValue8021></HdrPriorityValue8021> <HdrVLANID8021> </HdrVLANID8021> </Hdr8021Filter>
<ARPFilter> <HWType> </HWType> <ProtocolType> </ProtocolType> <OPCode> </OPCode> <SrcMACAddr> </SrcMACAddr> <SrcIPAddr> </SrcIPAddr> <DestMACAddr> </DestMACAddr> <DestIPAddr> </DestIPAddr> </ARPFilter>
<IPHeadersFilter> <HdrIPVersion> </HdrIPVersion> <HdrSrcAddress> </HdrSrcAddress> <HdrSrcMask> </HdrSrcMask> <HdrDestAddress> </HdrDestAddress> <HdrDestMask> </HdrDestMask> <HdrProtocolID> numeric and/or string? </HdrProtocolID> <HdrSrcPortStart> </HdrSrcPortStart> <HdrSrcPortEnd> </HdrSrcPortEnd> <HdrDestPortStart> </HdrDestPortStart> <HdrDestPortEnd> </HdrDestPortEnd> <HdrDSCP> </HdrDSCP> </IPHeadersFilter>
</FilterEntry>
hum the types for each values should be made explicit if possible, But in general I find that extremely bulky for a single entry, while I would expect any domain to have a dozen filters or so just for simple stuff. I wonder if empty default should just be dropped, so that basically if you're filtering on a MAC address you don't carry a bunch of unused fields.
Since the ebtables and iptables command cannot accept all possible parameters at the same time, only a certain subset of the above parameters may be set for any given filter command. Higher level application writers will likely use a library that lets them choose which features they would want to have enforced, such as no-broadcast or no-multicast, enforcement of MAC spoofing prevention or ARP poisoning prevention, which then generates this lower level XML rules in the appropriate order of the rules.
I wonder if a tailored set of simpler XML matching what is actually possible and getting away from the DMTF records wouldn't be better, since the original spec is extended on the feature side and the applicability is restricted on the implementation side, I'm not sure I see the point of trying to be compatible.
Further, we will introduce filter pools where a collection of the above filter rules can be stored and referenced to by virtual machines' individual interface. A reference to such a filter pool entry will be given in the interface description and may look as in the following draft XML:
<interface type='bridge'> <source bridge='virbr0'/> <script path='vif-bridge'/> <firewall> <reference profile='generic-layer2' ip_address='10.0.0.1'/> <reference profile='VM-specific-layer3'/> </firewall> </interface>
the devil is in the details, basically how you would template the profiles based on the strings in the reference. I.e. what the profile would look like and how for example ip_address='10.0.0.1' would be instancied in the profile use.
The above XML has one reference to a generic layer2 filter template XML that should be usable by multiple virtual machines but would need to be customized with interface-specific parameters. In this case, the IP address of the interface is explicitly provided in order to make the filter XML template a concrete XML for the particular interface. The MAC address of the interface is not explicitly provided since it will already have been randomly generated by libvirt at the point when this layer2 filter XML needs to be converted into concrete ebtables commands/rules. We still need to determine how the format of a template should look like, though an idea would be to indicate a placeholder for a VM's MAC address using THIS_MAC and similarly for the IP address with THIS_IP as placeholder.
Further, we would introduce the management of filter 'pools'. Considering existing functionality in libvirt and CLI commands for similar type of management functionality, the following CLI commands would be added:
virsh nwfilter-create <file> virsh nwfilter-destroy <profile name> virsh nwfilter-list <options> virsh nwfilter-dumpxml <profile name> virsh nwfilter-update <filename> (performs an update on an existing profile replacing all rules)
possibly also:
virsh nwfilter-edit <profile name> virsh nwfilter-create-from <profile name>
Please let us know what you think of this proposal.
The feature looks interesting ! It looks it should be applicable to at least qemu and xen, I'm not so sure about LXC or VirtualBox, and looks unlikely for VMWare unless they have a matching capability (might be possible since it's based at least partly on DMTF). I'm not sure reusing the DMTF format actually helps much, it also has its risks due to the extension. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Wed, Jan 13, 2010 at 06:03:22PM +0100, Daniel Veillard wrote:
On Mon, Jan 11, 2010 at 12:55:27PM -0500, Stefan Berger wrote:
As stated above, the application of firewall rules on virtual machines will require some form of XML description that lets the user choose what type of filtering is to be performed. In effect the user needs to be able to tell libvirt which ebtables and iptables rules to generate so that the appropriate filtering can be done. We realize that ebtables and iptables have lots of capabilities but think that we need to restrict which capabilities can actually be 'reached' through this XML.
The following proposal is based on an XML as defined by the DMTF ( http://www.dmtf.org/standards/cim/cim_schema_v2230/CIM_Network.pdf, slide 10) with extensions for processing of ARP packets.It gives control over the evaluation of Ethernet (MAC) frames, ARP packet data and IP header information. A (draft) XML skeleton in this case could look as follows:
Humpf, extending astandard XML schemas is really bad practice. Even if you think that the extension may be accepted later, it may have different semantic for the same construct and that's a disaster. I would at least put the new elements in a separate namespace to avoid something insane if DMTF extends its specification.
<FilterEntry> <Action>DROP|ACCEPT</Action> <!-- from FilterEntry -->
<TrafficType>incoming [to VM]|outgoing [from VM]</TrafficType>
<Hdr8021Filter> <HdrSrcMACAddr8021> </HdrSrcMACAddr8021> <HdrSrcMACMask8021> </HdrSrcMACMask8021> <HdrDestMACAddr8021> </HdrDestMACAddr8021> <HdrDestMACMask8021> </HdrDestMACMask8021> <HdrProtocolID8021> numeric and/or string? </HdrProtocolID8021> <HdrPriorityValue8021></HdrPriorityValue8021> <HdrVLANID8021> </HdrVLANID8021> </Hdr8021Filter>
<ARPFilter> <HWType> </HWType> <ProtocolType> </ProtocolType> <OPCode> </OPCode> <SrcMACAddr> </SrcMACAddr> <SrcIPAddr> </SrcIPAddr> <DestMACAddr> </DestMACAddr> <DestIPAddr> </DestIPAddr> </ARPFilter>
<IPHeadersFilter> <HdrIPVersion> </HdrIPVersion> <HdrSrcAddress> </HdrSrcAddress> <HdrSrcMask> </HdrSrcMask> <HdrDestAddress> </HdrDestAddress> <HdrDestMask> </HdrDestMask> <HdrProtocolID> numeric and/or string? </HdrProtocolID> <HdrSrcPortStart> </HdrSrcPortStart> <HdrSrcPortEnd> </HdrSrcPortEnd> <HdrDestPortStart> </HdrDestPortStart> <HdrDestPortEnd> </HdrDestPortEnd> <HdrDSCP> </HdrDSCP> </IPHeadersFilter>
</FilterEntry>
hum the types for each values should be made explicit if possible, But in general I find that extremely bulky for a single entry, while I would expect any domain to have a dozen filters or so just for simple stuff. I wonder if empty default should just be dropped, so that basically if you're filtering on a MAC address you don't carry a bunch of unused fields.
Since the ebtables and iptables command cannot accept all possible parameters at the same time, only a certain subset of the above parameters may be set for any given filter command. Higher level application writers will likely use a library that lets them choose which features they would want to have enforced, such as no-broadcast or no-multicast, enforcement of MAC spoofing prevention or ARP poisoning prevention, which then generates this lower level XML rules in the appropriate order of the rules.
I wonder if a tailored set of simpler XML matching what is actually possible and getting away from the DMTF records wouldn't be better, since the original spec is extended on the feature side and the applicability is restricted on the implementation side, I'm not sure I see the point of trying to be compatible.
In addition the DMTF XML format illustrated above is seriously ugly and not following the style of other libvirt XML formats. The use of UPPERCASE alone is reason enough to create a native libvirt format for this. We should of course ensure that whatever we do can be reliably mapped into the DMTF format via a simple XSL transform. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Wed, 2010-01-13 at 17:36 +0000, Daniel P. Berrange wrote:
In addition the DMTF XML format illustrated above is seriously ugly and not following the style of other libvirt XML formats. The use of UPPERCASE alone is reason enough to create a native libvirt format for this. We should of course ensure that whatever we do can be reliably mapped into the DMTF format via a simple XSL transform.
Daniel
Hi, we have been thinking about the comments regarding the XML format and hope the following is more in line with other libvirt XML formats: As Stefan proposed originally, the guest interface has an additional firewall. The firewall can have several filters, some of which are generic and template based and some are guest specific. The template filters can take parameters. The filters contain rules, currently for mac, arp, vlan and ip. A rule is applied if the conditions specified by the attributes and their values are true and the specified action will happen. The match attribute can be used to specify that the action should happen if the condition is not true. If an attribute is supplied on a rule but its value is empty (''), the supplied parameter for a template or the respective value for the current interface is used. This will need a few more examples to verify it is sufficient, but here is the current status: The guest xml file: ------------------- <domain type='kvm'> <name>demo</name> <memory>256000</memory> <devices> <interface type="bridge"> <firewall> <filter template='drop-all'/> <filter template='no-arp-spoofing' srcipaddr='10.0.0.1'/> <filter template='no-mac-spoofing'/> <filter template='no-ip-spoofing srcipaddr='10.0.0.1'/> <filter> <!-- allow outgoing IPV4 packets with the guest mac addr and vlanid 3 --> <rule action='allow' direction='out'> <mac srcmacaddr='' /> <vlan id='3'/> <ip version='4'/> </rule> <!-- only accept non-IPV6 packets from 'aa:bb:cc:dd:ee:ff' --> <rule action='allow' direction='in'> <mac srcmacaddr='aa:bb:cc:dd:ee:ff' /> <vlan id='3'/> <ip match='no' version='6'/> </rule> <!-- no access to port 25 allowed --> <rule action='allow' direction='in'> <ip match='no' dstportstart = '25' dstportend = '25' /> </rule> </filter> </firewall> </interface> </devices> </domain> The template xml files could be similar to this: ------------------------------------------------ <firewall> <!-- by default drop everything --> <template name='drop-all'> <filter policy='drop' /> </template> <template name='no-arp-spoofing'> <filter name='ARP' policy='drop'> <!-- no arp spoofing --> <!-- drop if ipaddr or macaddr does not belong to guest --> <rule action='drop' direction='out'> <arp match='no' srcmacaddr=''/> <arp match='no' srcipaddr='' /> </rule> <!-- drop if ipaddr or macaddr does not belong to guest --> <rule action='drop' direction='in'> <arp match='no' dstmacaddr=' '/> <arp match='no' dstipaddr='' /> </rule> <!-- allow all other request or reply packets --> <rule action='allow' direction='inout'> <arp opcode='request'/> <arp opcode='reply'/> </rule> </filter> </template> <template name='no-mac-spoofing'> <filter name='DLFT'> <!-- no mac spoofing --> <rule action='drop' direction='out'> <mac match='no' srcmacaddr=''/> </rule> </filter> </template> <template name='no-ip-spoofing'> <filter name='IPv4'> <!-- no ip spoofing --> <rule action='drop' direction='out'> <ip match='no' srcipaddr=''/> </rule> </filter> </template> Fully populated elements for schema generation: <filter name='IPv4' table='filter' priority='1'> <rule action='drop' direction='out'> <mac match='yes' srcmacaddr='aa:bb:cc:dd:ee:ff' srcmacmask='ff:ff:ff:ff:ff:ff' dstmacaddr='aa:bb:cc:dd:ee:fe' dstmacmask='ff:ff:ff:ff:ff:ff' /> <vlan id='3' protocol ='1' priority ='1'/> <arp match='yes' hwtype='1' protocoltype='IPv4' opcode='request' srcmacaddr='aa:bb:cc:dd:ee:ff' srcipaddr='192.168.0.1' dstmacaddr='aa:bb:cc:dd:ee:fe' dstipaddr='192.168.0.1'/> </rule> <rule action='accept' direction='inout'> <ip match='no' version = '4' srcipaddr = '192.168.0.1' srcipmask = '255.255.255.255' dstipaddr = '192.168.0.2' dstipmask = '255.255.255.255' protocol = '6' srcportstart = '100' srcportend = '200' dstportstart = '101' dstportend = '201' hdrdscp = '12345678' /> </rule> </filter> The (generated) schema looks currently like this. This will need of course additional manual rework once we can agree on the basic approach: <?xml version="1.0" encoding="UTF-8"?> <grammar ns="" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start> <element name="firewall"> <oneOrMore> <element name="template"> <attribute name="name"> <data type="NCName"/> </attribute> <ref name="filter"/> </element> </oneOrMore> <ref name="filter"/> </element> </start> <define name="filter"> <element name="filter"> <optional> <attribute name="name"> <data type="NCName"/> </attribute> </optional> <optional> <attribute name="policy"> <data type="NCName"/> </attribute> </optional> <optional> <attribute name="priority"> <data type="integer"/> </attribute> </optional> <optional> <attribute name="table"> <data type="NCName"/> </attribute> </optional> <zeroOrMore> <element name="rule"> <attribute name="action"> <data type="NCName"/> </attribute> <attribute name="direction"> <data type="NCName"/> </attribute> <optional> <element name="mac"> <optional> <attribute name="dstmacaddr"> <data type="NMTOKEN"/> </attribute> </optional> <optional> <attribute name="dstmacmask"> <data type="NMTOKEN"/> </attribute> </optional> <attribute name="match"> <data type="NCName"/> </attribute> <attribute name="srcmacaddr"> <data type="anyURI"/> </attribute> <optional> <attribute name="srcmacmask"> <data type="NMTOKEN"/> </attribute> </optional> </element> </optional> <optional> <element name="vlan"> <attribute name="id"> <data type="integer"/> </attribute> <attribute name="priority"> <data type="integer"/> </attribute> <attribute name="protocol"> <data type="integer"/> </attribute> </element> </optional> <choice> <element name="ip"> <optional> <attribute name="dstipaddr"> <data type="NMTOKEN"/> </attribute> </optional> <optional> <attribute name="dstipmask"> <data type="NMTOKEN"/> </attribute> </optional> <optional> <attribute name="dstportend"> <data type="integer"/> </attribute> </optional> <optional> <attribute name="dstportstart"> <data type="integer"/> </attribute> </optional> <optional> <attribute name="hdrdscp"> <data type="integer"/> </attribute> </optional> <attribute name="match"> <data type="NCName"/> </attribute> <optional> <attribute name="protocol"> <data type="integer"/> </attribute> </optional> <attribute name="srcipaddr"/> <optional> <attribute name="srcipmask"> <data type="NMTOKEN"/> </attribute> </optional> <optional> <attribute name="srcportend"> <data type="integer"/> </attribute> </optional> <optional> <attribute name="srcportstart"> <data type="integer"/> </attribute> </optional> <optional> <attribute name="version"> <data type="integer"/> </attribute> </optional> </element> <zeroOrMore> <element name="arp"> <optional> <attribute name="dstipaddr"/> </optional> <optional> <attribute name="dstmacaddr"> <data type="anyURI"/> </attribute> </optional> <optional> <attribute name="hwtype"> <data type="integer"/> </attribute> </optional> <optional> <attribute name="match"> <data type="NCName"/> </attribute> </optional> <optional> <attribute name="opcode"> <data type="NCName"/> </attribute> </optional> <optional> <attribute name="protocoltype"> <data type="NCName"/> </attribute> </optional> <optional> <attribute name="srcipaddr"/> </optional> <optional> <attribute name="srcmacaddr"> <data type="anyURI"/> </attribute> </optional> </element> </zeroOrMore> </choice> </element> </zeroOrMore> </element> </define> </grammar> -- Best regards, Gerhard Stenzel, ----------------------------------------------------------------------------------------------------------------------------------- IBM Deutschland Research & Development GmbH Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Dirk Wittkopp Sitz der Gesellschaft: Böblingen Registergericht: Amtsgericht Stuttgart, HRB 243294

On Fri, Jan 22, 2010 at 01:29:16PM +0100, Gerhard Stenzel wrote:
On Wed, 2010-01-13 at 17:36 +0000, Daniel P. Berrange wrote:
In addition the DMTF XML format illustrated above is seriously ugly and not following the style of other libvirt XML formats. The use of UPPERCASE alone is reason enough to create a native libvirt format for this. We should of course ensure that whatever we do can be reliably mapped into the DMTF format via a simple XSL transform.
Daniel
Hi, we have been thinking about the comments regarding the XML format and hope the following is more in line with other libvirt XML formats:
As Stefan proposed originally, the guest interface has an additional firewall. The firewall can have several filters, some of which are generic and template based and some are guest specific. The template filters can take parameters. The filters contain rules, currently for mac, arp, vlan and ip. A rule is applied if the conditions specified by the attributes and their values are true and the specified action will happen. The match attribute can be used to specify that the action should happen if the condition is not true. If an attribute is supplied on a rule but its value is empty (''), the supplied parameter for a template or the respective value for the current interface is used.
This will need a few more examples to verify it is sufficient, but here is the current status:
The guest xml file: ------------------- <domain type='kvm'> <name>demo</name> <memory>256000</memory> <devices> <interface type="bridge"> <firewall> <filter template='drop-all'/> <filter template='no-arp-spoofing' srcipaddr='10.0.0.1'/> <filter template='no-mac-spoofing'/> <filter template='no-ip-spoofing srcipaddr='10.0.0.1'/> <filter> <!-- allow outgoing IPV4 packets with the guest mac addr and vlanid 3 --> <rule action='allow' direction='out'> <mac srcmacaddr='' /> <vlan id='3'/> <ip version='4'/> </rule>
<!-- only accept non-IPV6 packets from 'aa:bb:cc:dd:ee:ff' --> <rule action='allow' direction='in'> <mac srcmacaddr='aa:bb:cc:dd:ee:ff' /> <vlan id='3'/> <ip match='no' version='6'/> </rule>
<!-- no access to port 25 allowed --> <rule action='allow' direction='in'> <ip match='no' dstportstart = '25' dstportend = '25' /> </rule> </filter> </firewall> </interface> </devices> </domain>
The shear size of the ruleset inside the <interface> element is rather alarming to me. Imagine if you have a guest with more than one NIC. I'm inclined to suggest that the <interface> element in the domain XML description should only have a single rule <filter name='BLAH'/> and if apps wish to construct a filter, from multiple independant sub-filters, then that should be done against the filter object's config, rather than the domain object's config.
The template xml files could be similar to this: ------------------------------------------------
<firewall> <!-- by default drop everything --> <template name='drop-all'> <filter policy='drop' /> </template>
<template name='no-arp-spoofing'> <filter name='ARP' policy='drop'> <!-- no arp spoofing --> <!-- drop if ipaddr or macaddr does not belong to guest --> <rule action='drop' direction='out'> <arp match='no' srcmacaddr=''/> <arp match='no' srcipaddr='' /> </rule> <!-- drop if ipaddr or macaddr does not belong to guest --> <rule action='drop' direction='in'> <arp match='no' dstmacaddr=' '/> <arp match='no' dstipaddr='' />
What was the idea with the empty attributes here ? Are those implying that the attribute value is to be filled in with the value from the domain XML ? If so I'd probably make that more explicit using something like $IP and $MAC to represent the guest configured IP/MAC
</rule> <!-- allow all other request or reply packets --> <rule action='allow' direction='inout'> <arp opcode='request'/> <arp opcode='reply'/> </rule> </filter> </template>
<template name='no-mac-spoofing'> <filter name='DLFT'> <!-- no mac spoofing --> <rule action='drop' direction='out'> <mac match='no' srcmacaddr=''/> </rule> </filter> </template>
<template name='no-ip-spoofing'> <filter name='IPv4'> <!-- no ip spoofing --> <rule action='drop' direction='out'> <ip match='no' srcipaddr=''/> </rule> </filter> </template>
I don't think that '<firewall>' is the top level object to be managed here. I would suggest that '<firewall>' and '<template>' elements are redundant, and that <filter> should be for the top level managed objects. The libvirt API would allow listing of existing filters, creating / deleting filters and updating the config. The <filter> element would allow some kind of <include> element to allow a complex filter to be built out of multiple simpler filters. Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, 2010-01-25 at 14:59 +0000, Daniel P. Berrange wrote:
On Fri, Jan 22, 2010 at 01:29:16PM +0100, Gerhard Stenzel wrote:
On Wed, 2010-01-13 at 17:36 +0000, Daniel P. Berrange wrote: ...
The shear size of the ruleset inside the <interface> element is rather alarming to me. Imagine if you have a guest with more than one NIC. I'm inclined to suggest that the <interface> element in the domain XML description should only have a single rule
<filter name='BLAH'/>
and if apps wish to construct a filter, from multiple independant sub-filters, then that should be done against the filter object's config, rather than the domain object's config.
...
What was the idea with the empty attributes here ? Are those implying that the attribute value is to be filled in with the value from the domain XML ? If so I'd probably make that more explicit using something like $IP and $MAC to represent the guest configured IP/MAC
...
I don't think that '<firewall>' is the top level object to be managed here. I would suggest that '<firewall>' and '<template>' elements are redundant, and that <filter> should be for the top level managed objects. The libvirt API would allow listing of existing filters, creating / deleting filters and updating the config. The <filter> element would allow some kind of <include> element to allow a complex filter to be built out of multiple simpler filters.
Regards, Daniel
Daniel, ok, trying to combine your suggestions: - guest contains a single filter reference per interface guest.xml: ---------- <domain type='kvm'> <name>demo</name> <memory>256000</memory> <devices> <interface type="bridge"> <filter name='demofilter' ipaddr='10.0.0.1'/> </interface> </devices> </domain> - complex filter include other filter and can contain rules complex demofilter.xml: ----------------------- <filter name='demofilter'> <include href='drop-all'/> <include href='no-arp-spoofing' srcipaddr='$IP'/> <include href='no-mac-spoofing'/> <include href='no-ip-spoofing' srcipaddr='$IP'/> <!-- no ip spoofing --> <rule action='drop' direction='out'> <ip match='no' srcipaddr='$IP'/> </rule> </filter> - simple filter contain only rules simple no-arp-spoofing.xml: --------------------------- <filter name='ARP' policy='drop'> <!-- no arp spoofing --> <!-- drop if ipaddr or macaddr does not belong to guest --> <rule action='drop' direction='out'> <arp match='no' srcmacaddr='$MAC'/> <arp match='no' srcipaddr='$IP' /> </rule> <!-- drop if ipaddr or macaddr does not belong to guest --> <rule action='drop' direction='in'> <arp match='no' dstmacaddr='$MAC'/> <arp match='no' dstipaddr='$IP' /> </rule> <!-- allow all other request or reply packets --> <rule action='allow' direction='inout'> <arp opcode='request'/> <arp opcode='reply'/> </rule> </filter> - $IP, $MAC represent the guests configured IP,MAC values If the above seems acceptable for the moment, I would suggest we verify that this is actually implementable or if we missed something. -- Best regards, Gerhard Stenzel, ----------------------------------------------------------------------------------------------------------------------------------- IBM Deutschland Research & Development GmbH Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Dirk Wittkopp Sitz der Gesellschaft: Böblingen Registergericht: Amtsgericht Stuttgart, HRB 243294

On Tue, Jan 26, 2010 at 02:24:43PM +0100, Gerhard Stenzel wrote:
On Mon, 2010-01-25 at 14:59 +0000, Daniel P. Berrange wrote:
On Fri, Jan 22, 2010 at 01:29:16PM +0100, Gerhard Stenzel wrote:
On Wed, 2010-01-13 at 17:36 +0000, Daniel P. Berrange wrote: ...
The shear size of the ruleset inside the <interface> element is rather alarming to me. Imagine if you have a guest with more than one NIC. I'm inclined to suggest that the <interface> element in the domain XML description should only have a single rule
<filter name='BLAH'/>
and if apps wish to construct a filter, from multiple independant sub-filters, then that should be done against the filter object's config, rather than the domain object's config.
...
What was the idea with the empty attributes here ? Are those implying that the attribute value is to be filled in with the value from the domain XML ? If so I'd probably make that more explicit using something like $IP and $MAC to represent the guest configured IP/MAC
...
I don't think that '<firewall>' is the top level object to be managed here. I would suggest that '<firewall>' and '<template>' elements are redundant, and that <filter> should be for the top level managed objects. The libvirt API would allow listing of existing filters, creating / deleting filters and updating the config. The <filter> element would allow some kind of <include> element to allow a complex filter to be built out of multiple simpler filters.
Regards, Daniel
Daniel,
ok, trying to combine your suggestions:
- guest contains a single filter reference per interface
guest.xml: ---------- <domain type='kvm'> <name>demo</name> <memory>256000</memory> <devices> <interface type="bridge"> <filter name='demofilter' ipaddr='10.0.0.1'/> </interface>
There's no need for ipaddr there - the XML schema already allows for a <ip address='10.0.0.1'/> within the <interface> tag here. We already have MAC address as a separate tag too. We could likely add VLAN in a similar way.
</devices> </domain>
- complex filter include other filter and can contain rules
complex demofilter.xml: ----------------------- <filter name='demofilter'> <include href='drop-all'/> <include href='no-arp-spoofing' srcipaddr='$IP'/> <include href='no-mac-spoofing'/> <include href='no-ip-spoofing' srcipaddr='$IP'/> <!-- no ip spoofing --> <rule action='drop' direction='out'> <ip match='no' srcipaddr='$IP'/> </rule> </filter>
- simple filter contain only rules
simple no-arp-spoofing.xml: --------------------------- <filter name='ARP' policy='drop'> <!-- no arp spoofing --> <!-- drop if ipaddr or macaddr does not belong to guest --> <rule action='drop' direction='out'> <arp match='no' srcmacaddr='$MAC'/> <arp match='no' srcipaddr='$IP' /> </rule> <!-- drop if ipaddr or macaddr does not belong to guest --> <rule action='drop' direction='in'> <arp match='no' dstmacaddr='$MAC'/> <arp match='no' dstipaddr='$IP' /> </rule> <!-- allow all other request or reply packets --> <rule action='allow' direction='inout'> <arp opcode='request'/> <arp opcode='reply'/> </rule> </filter>
- $IP, $MAC represent the guests configured IP,MAC values
If the above seems acceptable for the moment, I would suggest we verify that this is actually implementable or if we missed something.
Yes, those examples capture what I was trying to describe. Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Tue, 2010-01-26 at 13:35 +0000, Daniel P. Berrange wrote:
There's no need for ipaddr there - the XML schema already allows for a
<ip address='10.0.0.1'/>
within the <interface> tag here. We already have MAC address as a separate tag too. We could likely add VLAN in a similar way.
agreed. We will start with the implementation and send a patch or rather a series once we have them. Thanks. -- Best regards, Gerhard Stenzel, ----------------------------------------------------------------------------------------------------------------------------------- IBM Deutschland Research & Development GmbH Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Dirk Wittkopp Sitz der Gesellschaft: Böblingen Registergericht: Amtsgericht Stuttgart, HRB 243294

libvir-list-bounces@redhat.com wrote on 01/26/2010 08:35:36 AM:
On Tue, Jan 26, 2010 at 02:24:43PM +0100, Gerhard Stenzel wrote:
On Mon, 2010-01-25 at 14:59 +0000, Daniel P. Berrange wrote:
On Fri, Jan 22, 2010 at 01:29:16PM +0100, Gerhard Stenzel wrote:
On Wed, 2010-01-13 at 17:36 +0000, Daniel P. Berrange wrote: ...
The shear size of the ruleset inside the <interface> element is rather alarming to me. Imagine if you have a guest with more than one NIC. I'm inclined to suggest that the <interface> element in the domain XML description should only have a single rule
<filter name='BLAH'/>
and if apps wish to construct a filter, from multiple independant sub-filters, then that should be done against the filter object's config, rather than the domain object's config.
...
What was the idea with the empty attributes here ? Are those implying that the attribute value is to be filled in with the value from the domain XML ? If so I'd probably make that more explicit using something like $IP and $MAC to represent the guest configured IP/MAC
...
I don't think that '<firewall>' is the top level object to be
managed
here. I would suggest that '<firewall>' and '<template>' elements are redundant, and that <filter> should be for the top level managed objects. The libvirt API would allow listing of existing filters, creating / deleting filters and updating the config. The <filter> element would allow some kind of <include> element to allow a complex filter to be built out of multiple simpler filters.
Regards, Daniel
Daniel,
ok, trying to combine your suggestions:
- guest contains a single filter reference per interface
guest.xml: ---------- <domain type='kvm'> <name>demo</name> <memory>256000</memory> <devices> <interface type="bridge"> <filter name='demofilter' ipaddr='10.0.0.1'/> </interface>
There's no need for ipaddr there - the XML schema already allows for a
<ip address='10.0.0.1'/>
within the <interface> tag here. We already have MAC address as a separate tag too. We could likely add VLAN in a similar way.
A VM may be allowed to generate traffic on multiple VLANs (having multiple different VLAN interfaces inside the VM). For that we may need different rules per VLAN traffic that the VM is allowed to send traffic on. Since we only reference the filter in the interface XML, I suppose that we need to rely on higher layers to take care of migrating those filters and referenced sub(-sub)-filters to the target host. Correct? Stefan

On Tue, Jan 26, 2010 at 10:16:23AM -0500, Stefan Berger wrote:
libvir-list-bounces@redhat.com wrote on 01/26/2010 08:35:36 AM:
On Tue, Jan 26, 2010 at 02:24:43PM +0100, Gerhard Stenzel wrote:
On Mon, 2010-01-25 at 14:59 +0000, Daniel P. Berrange wrote:
On Fri, Jan 22, 2010 at 01:29:16PM +0100, Gerhard Stenzel wrote:
On Wed, 2010-01-13 at 17:36 +0000, Daniel P. Berrange wrote: ...
The shear size of the ruleset inside the <interface> element is rather alarming to me. Imagine if you have a guest with more than one NIC. I'm inclined to suggest that the <interface> element in the domain XML description should only have a single rule
<filter name='BLAH'/>
and if apps wish to construct a filter, from multiple independant sub-filters, then that should be done against the filter object's config, rather than the domain object's config.
...
What was the idea with the empty attributes here ? Are those implying that the attribute value is to be filled in with the value from the domain XML ? If so I'd probably make that more explicit using something like $IP and $MAC to represent the guest configured IP/MAC
...
I don't think that '<firewall>' is the top level object to be
managed
here. I would suggest that '<firewall>' and '<template>' elements are redundant, and that <filter> should be for the top level managed objects. The libvirt API would allow listing of existing filters, creating / deleting filters and updating the config. The <filter> element would allow some kind of <include> element to allow a complex filter to be built out of multiple simpler filters.
Regards, Daniel
Daniel,
ok, trying to combine your suggestions:
- guest contains a single filter reference per interface
guest.xml: ---------- <domain type='kvm'> <name>demo</name> <memory>256000</memory> <devices> <interface type="bridge"> <filter name='demofilter' ipaddr='10.0.0.1'/> </interface>
There's no need for ipaddr there - the XML schema already allows for a
<ip address='10.0.0.1'/>
within the <interface> tag here. We already have MAC address as a separate tag too. We could likely add VLAN in a similar way.
A VM may be allowed to generate traffic on multiple VLANs (having multiple different VLAN interfaces inside the VM). For that we may need different rules per VLAN traffic that the VM is allowed to send traffic on.
Since we only reference the filter in the interface XML, I suppose that we need to rely on higher layers to take care of migrating those filters and referenced sub(-sub)-filters to the target host. Correct?
Yes, management apps are responsible for ensuring that each host within a "migration pool" has the same configuration for all relevant areas, including storage mount points / device naming, network device naming, firewall configuration, etc, etc Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

libvir-list-bounces@redhat.com wrote on 01/26/2010 08:24:43 AM:
Daniel,
ok, trying to combine your suggestions:
- guest contains a single filter reference per interface
guest.xml: ---------- <domain type='kvm'> <name>demo</name> <memory>256000</memory> <devices> <interface type="bridge"> <filter name='demofilter' ipaddr='10.0.0.1'/> </interface> </devices> </domain>
As the implementation of this progresses and we make design decision, we now introduced attributes and values for the filters to be passed in the format of att%d='<attribute>' val%d='<value>' thus we would rewrite the above example to: <domain type='kvm'> <name>demo</name> <memory>256000</memory> <devices> <interface type="bridge"> <filter name='demofilter' att0='IP' val0='10.0.0.1'/> </interface> </devices> </domain> This allows us to pass any necessary parameters to the filters for instantiation in the respective environment. So, if a filter is to be instantiated and holds the variable XYZ, then one may add att1='XYZ' val1='<some value>'
- complex filter include other filter and can contain rules
complex demofilter.xml: ----------------------- <filter name='demofilter'> <include href='drop-all'/> <include href='no-arp-spoofing' srcipaddr='$IP'/>
--> <include href='no-arp-spoofing' att0='IP' val0='1.2.3.4'.
<include href='no-mac-spoofing'/> <include href='no-ip-spoofing' srcipaddr='$IP'/> <!-- no ip spoofing --> <rule action='drop' direction='out'> <ip match='no' srcipaddr='$IP'/> </rule> </filter>
So any referenced filter, also as shown above in the demofilter.xml, could hold environment-specific values for required variables. A filter requiring a variable that is not passed is not instantiated and will prevent interface creation / attachment or the start of the VM. Further, if an attribute value pair (IP) as shown here is passed from the domain XML and another value as shown here in the referenced filter is again set, the one from further 'up' is used, i.e., IP=10.0.0.1 rather than IP=1.2.3.4. Does this sound ok? Regards, Stefan

2010/2/18 Stefan Berger <stefanb@us.ibm.com>:
libvir-list-bounces@redhat.com wrote on 01/26/2010 08:24:43 AM:
Daniel,
ok, trying to combine your suggestions:
- guest contains a single filter reference per interface
guest.xml: ---------- <domain type='kvm'> <name>demo</name> <memory>256000</memory> <devices> <interface type="bridge"> <filter name='demofilter' ipaddr='10.0.0.1'/> </interface> </devices> </domain>
As the implementation of this progresses and we make design decision, we now introduced attributes and values for the filters to be passed in the format of
att%d='<attribute>' val%d='<value>'
thus we would rewrite the above example to:
<domain type='kvm'> <name>demo</name> <memory>256000</memory> <devices> <interface type="bridge"> <filter name='demofilter' att0='IP' val0='10.0.0.1'/> </interface> </devices> </domain>
This allows us to pass any necessary parameters to the filters for instantiation in the respective environment. So, if a filter is to be instantiated and holds the variable XYZ, then one may add
att1='XYZ' val1='<some value>'
Passing parameters this way seems a bit unexpected for XML. How about something like this: <interface type="bridge"> <filter name='demofilter'> <parameter name='IP' value='10.0.0.1'/> </filter> </interface>
- complex filter include other filter and can contain rules
complex demofilter.xml: ----------------------- <filter name='demofilter'> <include href='drop-all'/> <include href='no-arp-spoofing' srcipaddr='$IP'/>
--> <include href='no-arp-spoofing' att0='IP' val0='1.2.3.4'.
And the same pattern for the includes: <include href='no-arp-spoofing'> <parameter name='IP' value='1.2.3.4'/> </include> Matthias

Matthias Bolte <matthias.bolte@googlemail.com> wrote on 02/18/2010 09:15:47 AM:
thus we would rewrite the above example to:
<domain type='kvm'> <name>demo</name> <memory>256000</memory> <devices> <interface type="bridge"> <filter name='demofilter' att0='IP' val0='10.0.0.1'/> </interface> </devices> </domain> This allows us to pass any necessary parameters to the filters for instantiation in the respective environment. So, if a filter is to be instantiated and holds the variable XYZ, then one may add
att1='XYZ' val1='<some value>'
Passing parameters this way seems a bit unexpected for XML. How about something like this:
<interface type="bridge"> <filter name='demofilter'> <parameter name='IP' value='10.0.0.1'/> </filter> </interface>
Also a possibility... Stefan

Matthias Bolte <matthias.bolte@googlemail.com> wrote on 02/18/2010 09:15:47 AM:
"Daniel P. Berrange", veillard, libvir-list, Vivek Kashyap
2010/2/18 Stefan Berger <stefanb@us.ibm.com>:
<domain type='kvm'> <name>demo</name> <memory>256000</memory> <devices> <interface type="bridge"> <filter name='demofilter' att0='IP' val0='10.0.0.1'/> </interface> </devices> </domain>
This allows us to pass any necessary parameters to the filters for instantiation in the respective environment. So, if a filter is to be instantiated and
holds
the variable XYZ, then one may add
att1='XYZ' val1='<some value>'
Passing parameters this way seems a bit unexpected for XML. How about something like this:
<interface type="bridge"> <filter name='demofilter'> <parameter name='IP' value='10.0.0.1'/> </filter> </interface>
I think we'll change this to ... <interface type="bridge"> <filterref ref='demofilter'> <parameter name='IP' value='10.0.0.1'/> </filter> </interface>
- complex filter include other filter and can contain rules
complex demofilter.xml: ----------------------- <filter name='demofilter'> <include href='drop-all'/> <include href='no-arp-spoofing' srcipaddr='$IP'/>
--> <include href='no-arp-spoofing' att0='IP' val0='1.2.3.4'.
And the same pattern for the includes:
... and this to ...
<include href='no-arp-spoofing'> <parameter name='IP' value='1.2.3.4'/> </include>
<filterref ref='no-arp-spoofing'> <parameter name='IP' value='1.2.3.4'/> </include> ... to be consistent. Thanks for feedback. Stefan
Matthias

On Thu, 2010-02-18 at 10:45 -0500, Stefan Berger wrote: ....
<filterref ref='no-arp-spoofing'> <parameter name='IP' value='1.2.3.4'/> </include>
... to be consistent.
Thanks for feedback.
Stefan
Matthias
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Hi, here is a preview of a chapter which is eventually intended for the libvirt application development guide. It is not final yet, but I feel now would be a good moment to gather some first feedback and to "finalise" the XML schema which is used in the examples. ------------------------------------------------------------------------ 1. Network Filter 1.1. Overview 1.2. XML Filter Description Format 1.2.1. Complex Filter 1.2.2. Simple Filters 1.3. Retrieving Information About Filter 1.3.1. TBD Chapter 1. Network Filter --------------------------- 1.1. Overview 1.2. XML Filter Description Format 1.2.1. Complex Filter 1.2.2. Simple Filters 1.3. Retrieving Information About Filter 1.3.1. TBD This section covers the management and definition of network filters using the libvirt API. 1.1. Overview -------------- The configuration of network filters can be examined and modified with functions in the virTBSL API. This is useful for setting up filter rules to control which network packets are allowed from and to a guest domains. Currently, filters for Ethernet (MAC) frames, ARP packet data and IP header information are possible. 1.2. XML Filter Description Format ----------------------------------- The current Relax NG schema definition of the XML that is produced/accepted by TBD can be found in the filter.rng. Filtering is currently enabled by adding a filterref element to the interface description of a domain XML file. The filterref element has a filter atttribute which references the corresponding filter definition like in the following example. <domain type='kvm' id='1'> <name>build1</name> <uuid>c7ac4ad9-e5ce-4c93-b380-013c85663e39</uuid> <memory>262144</memory> <currentMemory>262144</currentMemory> <vcpu>1</vcpu> <os> <type arch='x86_64' machine='pc-0.11'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <kernel>/etc/libvirt/qemu/bzImage</kernel> <initrd>/etc/libvirt/qemu/i686-rootfs.i686.cpio.gz</initrd> <cmdline>kvmguest=1</cmdline> <boot dev='hd'/> </os> <features> <acpi/> </features> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>destroy</on_crash> <devices> <emulator>/usr/bin/qemu-kvm</emulator> <disk type='file' device='disk'> <source file='/etc/libvirt/qemu/i686-rootfs.i686.ext2'/> <target dev='hda' bus='ide'/> <address type='drive' controller='0' bus='0' unit='0'/> </disk> <disk type='file' device='cdrom'> <target dev='hdc' bus='ide'/> <readonly/> <address type='drive' controller='0' bus='1' unit='0'/> </disk> <controller type='ide' index='0'/> <interface type='network'> <mac address='d0:0f:d0:0f:02:01'/> <source network='mynet'/> <model type='virtio'/> <filterref filter='demofilter'/> </interface> <serial type='pty'> <source path='/dev/pts/1'/> <target port='0'/> </serial> <console type='pty' tty='/dev/pts/1'> <source path='/dev/pts/1'/> <target port='0'/> </console> <input type='mouse' bus='ps2'/> <graphics type='vnc' port='5900' autoport='yes' listen='127.0.0.1'/> <video> <model type='cirrus' vram='9216' heads='1'/> </video> </devices> </domain> Example 1.1. XML definition for a guest. Network filters are specified using rules or by referencing other filters via filterref. This allows to construct complex filters from simpler, potentially predefined filters. 1.2.1. Complex Filter The named filters in the following examples are complex filters, which include other, potentially predefined, filters. Included filters can take parameters, which are specified via an attX-valX pair (X starts at 0). <filter name='demofilter'> <filterref filter='no-arp-spoofing'/> <filterref filter='no-mac-spoofing'/> <filterref filter='no-ip-spoofing'/> <filterref filter='no-mac-broadcast'/> <filterref filter='allow-dhcp'> <parameter name='DHCPSERVER' value='10.3.2.1'/> </filterref> <filterref filter='no-other-l2-traffic'/> </filter> Example 1.2. XML definition for a complex filetr. This is a pure Layer 2 filter configuration: <filter name='demofilter2'> <filterref filter='no-mac-spoofing'/> <filterref filter='no-mac-broadcast'/> <filterref filter='allow-arp'/> <filterref filter='allow-ipv4'/> <filterref filter='no-other-l2-traffic'/> </filter> Example 1.3. XML definition for another complex filetr. 1.2.2. Simple Filters The following examples of simple filters are predefined and address distint filter requirements. The predefined no-arp-spoofing filter drops all ARP packets * originating from the guest if they contain other than the guests IP or MAC address * destined for the guest if they contain other than the guests IP or MAC address It accepts all request or reply ARP packets. <filter name='no-arp-spoofing' chain='arp'> <uuid>f88f1932-debf-4aa1-9fbe-f10d3aa4bc95</uuid> <!-- no arp spoofing --> <!-- drop if ipaddr or macaddr does not belong to guest --> <rule action='drop' direction='out'> <arp match='no' srcmacaddr='$MAC'/> </rule> <rule action='drop' direction='out'> <arp match='no' srcipaddr='$IP' /> </rule> <!-- drop if ipaddr or macaddr odes not belong to guest --> <rule action='drop' direction='in'> <arp match='no' dstmacaddr='$MAC'/> </rule> <rule action='drop' direction='in'> <arp match='no' dstipaddr='$IP' /> </rule> <!-- accept only request or reply packets --> <rule action='accept' direction='inout'> <arp opcode='request'/> </rule> <rule action='accept' direction='inout'> <arp opcode='reply'/> </rule> <!-- drop everything else --> <rule action='drop' direction='inout'/> </filter> Example 1.4. XML definition to prevent ARP spoofing. The predefined no-mac-spoofing filter drops all ethernet packets from the guest containing other than the guests MAC address as the source MAC address. <filter name='no-mac-spoofing' chain='ipv4'> <rule action='drop' direction='out'> <mac match='no' srcmacaddr='$MAC' /> </rule> </filter> Example 1.5. XML definition to prevent MAC spoofing. The predefined no-ip-spoofing filter drops all IP packets from the guest containing other than the guests IP address as the source IP address. <filter name='no-ip-spoofing' chain='ipv4'> <!-- no ip spoofing --> <!-- drop if srcipaddr is not the address of the guest --> <rule action='drop' direction='out'> <ip match='no' srcipaddr='$IP' /> </rule> <!-- not doing anything with receiving side to prevent eavesdropping --> </filter> Example 1.6. XML definition to prevent IP spoofing. The predefined no-mac-broadcast filter drops all ethernet packets with the broadcast mac address as destination. <filter name='no-mac-broadcast' chain='ipv4'> <!-- drop if destination mac is bcast mac addr. --> <rule action='drop' direction='out'> <mac dstmacaddr='ff:ff:ff:ff:ff:ff' /> </rule> <!-- not doing anything with receiving side ... --> </filter> Example 1.7. XML definition to prevent outgoing broadcasts. The predefined allow-dhcp filter allows DHCP requests and replies from the specified DHCP server. <filter name='allow-dhcp' chain='ipv4'> <!-- accept outgoing DHCP requests --> <!-- not, this rule must be avaluated before general MAC broadcast traffic is discarded since DHCP requests use MAC broadcast --> <rule action='accept' direction='out'> <ip srcipaddr='0.0.0.0' dstipaddr='255.255.255.255' protocol='udp' srcportstart='68' dstportstart='67' /> </rule> <!-- accept incoming DHCP responses from a specific DHCP server parameter DHPCSERVER needs to be passed from where this filter is referenced --> <rule action='accept' direction='in'> <ip srcipaddr='$DHCPSERVER' protocol='udp' srcportstart='67' dstportstart='68'/> </rule> </filter> Example 1.8. XML definition to allow DHCP requests and replys. The predefined no-ip-multicast filter drops all ethernet packets with the multicast IP address as destination. <filter name='no-ip-multicast' chain='ipv4'> <!-- drop if destination IP address is in the 224.0.0.0/4 subnet --> <rule action='drop' direction='out'> <ip dstipaddr='224.0.0.0' dstipmask='4' /> </rule> <!-- not doing anything with receiving side ... --> </filter> Example 1.9. XML definition to prevent multicast The predefined no-other-l2-traffic filter drops all layer 2 packets which did not match other rules. <filter name='no-other-l2-traffic'> <!-- drop all other l2 traffic than for which rules have been written for Note: this rule should be the last on in the 'root' chain --> <rule action='drop' direction='inout'/> </filter> Example 1.10. XML definition to drop all other layer 2 traffic. <filter name='allow-arp' chain='arp'> <rule direction='inout' action='accept'/> </filter> Example 1.11. XML definition to allow arp traffic. <filter name='allow-ipv4' chain='ipv4'> <rule direction='inout' action='accept'/> </filter> Example 1.12. XML definition to allow IPV4 traffic. ------------------------------------------------------------------------ -- Best regards, Gerhard Stenzel, ----------------------------------------------------------------------------------------------------------------------------------- IBM Deutschland Research & Development GmbH Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Dirk Wittkopp Sitz der Gesellschaft: Böblingen Registergericht: Amtsgericht Stuttgart, HRB 243294

On Mon, Feb 22, 2010 at 01:45:20PM +0100, Gerhard Stenzel wrote:
Hi, here is a preview of a chapter which is eventually intended for the libvirt application development guide. It is not final yet, but I feel now would be a good moment to gather some first feedback and to "finalise" the XML schema which is used in the examples.
Thanks, this is a good idea !
------------------------------------------------------------------------
1. Network Filter
1.1. Overview
1.2. XML Filter Description Format
1.2.1. Complex Filter
1.2.2. Simple Filters
1.3. Retrieving Information About Filter
1.3.1. TBD
Chapter 1. Network Filter ---------------------------
1.1. Overview
1.2. XML Filter Description Format
1.2.1. Complex Filter
1.2.2. Simple Filters
1.3. Retrieving Information About Filter
1.3.1. TBD
This section covers the management and definition of network filters using the libvirt API.
1.2.2. Simple Filters
The following examples of simple filters are predefined and address distint filter requirements. The predefined no-arp-spoofing filter drops all ARP packets
* originating from the guest if they contain other than the guests IP or MAC address
* destined for the guest if they contain other than the guests IP or MAC address
It accepts all request or reply ARP packets.
<filter name='no-arp-spoofing' chain='arp'>
Perhaps we should call that 'chain' attribute 'protocol' instead since that appears to be what you're representing there. I'm wondering how this should interact with the <filterref> element. eg, you might have chain='ipv4' on the main filter, and then a <filterref> pointing to a chain='arp'. One way would be to declare that a <filter> can contain either <rule> or <filterref>, but not a mixture of both.
<uuid>f88f1932-debf-4aa1-9fbe-f10d3aa4bc95</uuid>
<!-- no arp spoofing --> <!-- drop if ipaddr or macaddr does not belong to guest --> <rule action='drop' direction='out'> <arp match='no' srcmacaddr='$MAC'/> </rule> <rule action='drop' direction='out'> <arp match='no' srcipaddr='$IP' /> </rule> <!-- drop if ipaddr or macaddr odes not belong to guest --> <rule action='drop' direction='in'> <arp match='no' dstmacaddr='$MAC'/> </rule> <rule action='drop' direction='in'> <arp match='no' dstipaddr='$IP' /> </rule> <!-- accept only request or reply packets --> <rule action='accept' direction='inout'> <arp opcode='request'/> </rule> <rule action='accept' direction='inout'> <arp opcode='reply'/> </rule> <!-- drop everything else --> <rule action='drop' direction='inout'/> </filter>
Generally, your proposal looks good to me. Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, 2010-01-25 at 14:59 +0000, Daniel P. Berrange wrote:
The shear size of the ruleset inside the <interface> element is rather alarming to me. Imagine if you have a guest with more than one NIC. I'm inclined to suggest that the <interface> element in the domain XML description should only have a single rule
<filter name='BLAH'/>
and if apps wish to construct a filter, from multiple independant sub-filters, then that should be done against the filter object's config, rather than the domain object's config.
Daniel, we could achieve something similar with the following construct: <xi:include href="demofilter.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> This would also have the advantage that the filter rules do not clutter up the domain xml, but the migration of the rules might be simpler to implement. What is your thinking about this approach? -- Best regards, Gerhard Stenzel, ----------------------------------------------------------------------------------------------------------------------------------- IBM Deutschland Research & Development GmbH Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Dirk Wittkopp Sitz der Gesellschaft: Böblingen Registergericht: Amtsgericht Stuttgart, HRB 243294

On Thu, Feb 04, 2010 at 01:07:59PM +0100, Gerhard Stenzel wrote:
On Mon, 2010-01-25 at 14:59 +0000, Daniel P. Berrange wrote:
The shear size of the ruleset inside the <interface> element is rather alarming to me. Imagine if you have a guest with more than one NIC. I'm inclined to suggest that the <interface> element in the domain XML description should only have a single rule
<filter name='BLAH'/>
and if apps wish to construct a filter, from multiple independant sub-filters, then that should be done against the filter object's config, rather than the domain object's config.
Daniel, we could achieve something similar with the following construct:
<xi:include href="demofilter.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
This would also have the advantage that the filter rules do not clutter up the domain xml, but the migration of the rules might be simpler to implement. What is your thinking about this approach?
This addresses the problem from the public facing XML point of view, but not from the internal implementation. If we have an explicitly separate filter that can be referenced from multiple places, then the internal libvirt implmentation can optimize this to only create 1 set of iptables rules that are used to apply to all guests referencing the filter. If by constrast you do the includes at the XML document level, then the internal implementation cannot practically use a shared set of rules and so you'll end up with the same rulesets having to be duplicated in iptables for each guest, which could cause scalability limitations Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

2010/2/4 Gerhard Stenzel <gstenzel@linux.vnet.ibm.com>:
On Mon, 2010-01-25 at 14:59 +0000, Daniel P. Berrange wrote:
The shear size of the ruleset inside the <interface> element is rather alarming to me. Imagine if you have a guest with more than one NIC. I'm inclined to suggest that the <interface> element in the domain XML description should only have a single rule
<filter name='BLAH'/>
and if apps wish to construct a filter, from multiple independant sub-filters, then that should be done against the filter object's config, rather than the domain object's config.
Daniel, we could achieve something similar with the following construct:
<xi:include href="demofilter.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
This would also have the advantage that the filter rules do not clutter up the domain xml, but the migration of the rules might be simpler to implement. What is your thinking about this approach?
-- Best regards,
Gerhard Stenzel,
Such an include mechanism was suggest by Dan before, but I don't think that XInclude is a good approach, because this will make the XML handling more complicated. The main libvirt functions to define/create a new guest are virDomainDefineXML and virDomainCreateXML. Both take the domain XML description a string. They don't take filenames. Using XInclude introduces the need for filenames to be able to reference them by the href attribute of an XInclude element. Even if libvirt stores the filter rules as files internally this should be considered as an implementation detail. IMHO exposing paths to internal files isn't a good design decision. The same is true for virDomainGetXMLDesc, it would have to expose paths to internal files to be read by management applications using libvirt. I think the best approach to handle the filter setup while being able build complex filter from simpler parts is an include mechanism, but not using XInclude or reference the filter parts by filename, but by filter name. <domain> <devices> <interface> <filter name='demofilter'/> </interface> </devices> </domain> <filter name='demofilter'> <include filter='dropall'/> ... </filter> <filter name='dropall'> ... </filter> libvirt would have API to handle filters by name and their XML description in string form, no file handling involved. Maybe something like this in line with the rest of the libvirt API: virConnectListFilters to list all known filters virFilterDefineXML to define a filter from an XML description in string form virFilterUndefine to undefine an existing filter virFilterGetXMLDesc to get the XML description in string form of an existing filter virFilterLookupByName to find a filter by name ... Matthias

libvir-list-bounces@redhat.com wrote on 02/04/2010 08:50:29 AM:
libvir-list, Gerhard Stenzel, Vivek Kashyap
2010/2/4 Gerhard Stenzel <gstenzel@linux.vnet.ibm.com>:
On Mon, 2010-01-25 at 14:59 +0000, Daniel P. Berrange wrote:
The shear size of the ruleset inside the <interface> element is rather alarming to me. Imagine if you have a guest with more than one NIC. I'm inclined to suggest that the <interface> element in the domain XML description should only have a single rule
<filter name='BLAH'/>
and if apps wish to construct a filter, from multiple independant sub-filters, then that should be done against the filter object's config, rather than the domain object's config.
Daniel, we could achieve something similar with the following construct:
<xi:include href="demofilter.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
This would also have the advantage that the filter rules do not
clutter
up the domain xml, but the migration of the rules might be simpler to implement. What is your thinking about this approach?
-- Best regards,
Gerhard Stenzel,
Such an include mechanism was suggest by Dan before, but I don't think that XInclude is a good approach, because this will make the XML handling more complicated.
The main libvirt functions to define/create a new guest are virDomainDefineXML and virDomainCreateXML. Both take the domain XML description a string. They don't take filenames. Using XInclude introduces the need for filenames to be able to reference them by the href attribute of an XInclude element. Even if libvirt stores the filter rules as files internally this should be considered as an implementation detail. IMHO exposing paths to internal files isn't a good design decision. The same is true for virDomainGetXMLDesc, it would have to expose paths to internal files to be read by management applications using libvirt.
I think the best approach to handle the filter setup while being able build complex filter from simpler parts is an include mechanism, but not using XInclude or reference the filter parts by filename, but by filter name.
The problem with the references is the migratability. In my opinion, the filters attached to a virtual machine's interface should migrate to a destination host completely transparently using 'virsh migrate' and allow migration to fail if the instantiation of the rule fails due to for example a missing ebtables/iptables support module, but not due to missing filter XML. This means that in the simple case where the VM had a filter rule no-ip-spoofing active on an interface on the source this same filtering should become active on the destination. However, most VMs will have much more complex rules and may use references to existing templates and add their own interface specific rules on top of that. Now how do you migrate that? How do you handle cases where a template on the source was referenced and may be missing on the destination or if the template on the destination is different (ignore it?). I guess the more involved solution would be to migrate the whole tree of referenced filters and using internal APIs to again make them available on the host, failing if filters with same names already exists, succeeding for others. Not sure whether the migration protocol can handle that...
<domain> <devices> <interface> <filter name='demofilter'/> </interface> </devices> </domain>
<filter name='demofilter'> <include filter='dropall'/> ... </filter>
<filter name='dropall'> ... </filter>
libvirt would have API to handle filters by name and their XML description in string form, no file handling involved. Maybe something like this in line with the rest of the libvirt API:
virConnectListFilters to list all known filters virFilterDefineXML to define a filter from an XML description in string
form
virFilterUndefine to undefine an existing filter virFilterGetXMLDesc to get the XML description in string form of an existing filter virFilterLookupByName to find a filter by name ...
Yes, initial prototype provides similar functions but does not solve the migration problem ... Stefan
Matthias
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On Mon, 25 Jan 2010, Daniel P. Berrange wrote:
Date: Mon, 25 Jan 2010 14:59:04 +0000 From: Daniel P. Berrange <berrange@redhat.com> To: Gerhard Stenzel <gstenzel@linux.vnet.ibm.com> Cc: libvir-list@redhat.com, Gerhard Stenzel <gerhard.stenzel@de.ibm.com>, Vivek Kashyap <vivk@us.ibm.com> Subject: Re: [libvirt] [RFC] Proposal for introduction of network traffic filtering capabilities for filtering of network traffic from and to VMs
On Fri, Jan 22, 2010 at 01:29:16PM +0100, Gerhard Stenzel wrote:
On Wed, 2010-01-13 at 17:36 +0000, Daniel P. Berrange wrote:
In addition the DMTF XML format illustrated above is seriously ugly and not following the style of other libvirt XML formats. The use of UPPERCASE alone is reason enough to create a native libvirt format for this. We should of course ensure that whatever we do can be reliably mapped into the DMTF format via a simple XSL transform.
Daniel
Hi, we have been thinking about the comments regarding the XML format and hope the following is more in line with other libvirt XML formats:
As Stefan proposed originally, the guest interface has an additional firewall. The firewall can have several filters, some of which are generic and template based and some are guest specific. The template filters can take parameters. The filters contain rules, currently for mac, arp, vlan and ip. A rule is applied if the conditions specified by the attributes and their values are true and the specified action will happen. The match attribute can be used to specify that the action should happen if the condition is not true. If an attribute is supplied on a rule but its value is empty (''), the supplied parameter for a template or the respective value for the current interface is used.
This will need a few more examples to verify it is sufficient, but here is the current status:
The guest xml file: ------------------- <domain type='kvm'> <name>demo</name> <memory>256000</memory> <devices> <interface type="bridge"> <firewall> <filter template='drop-all'/> <filter template='no-arp-spoofing' srcipaddr='10.0.0.1'/> <filter template='no-mac-spoofing'/> <filter template='no-ip-spoofing srcipaddr='10.0.0.1'/> <filter> <!-- allow outgoing IPV4 packets with the guest mac addr and vlanid 3 --> <rule action='allow' direction='out'> <mac srcmacaddr='' /> <vlan id='3'/> <ip version='4'/> </rule>
<!-- only accept non-IPV6 packets from 'aa:bb:cc:dd:ee:ff' --> <rule action='allow' direction='in'> <mac srcmacaddr='aa:bb:cc:dd:ee:ff' /> <vlan id='3'/> <ip match='no' version='6'/> </rule>
<!-- no access to port 25 allowed --> <rule action='allow' direction='in'> <ip match='no' dstportstart = '25' dstportend = '25' /> </rule> </filter> </firewall> </interface> </devices> </domain>
The shear size of the ruleset inside the <interface> element is rather alarming to me. Imagine if you have a guest with more than one NIC. I'm inclined to suggest that the <interface> element in the domain XML description should only have a single rule
<filter name='BLAH'/>
Yes,that would be cleaner. It can be done with the above xml if the rules are organised in such a way. Or, are you suggesting that it must always be that there is only one entry referring to a separate filter object.
and if apps wish to construct a filter, from multiple independant sub-filters, then that should be done against the filter object's config, rather than the domain object's config.
The template xml files could be similar to this: ------------------------------------------------
<firewall> <!-- by default drop everything --> <template name='drop-all'> <filter policy='drop' /> </template>
<template name='no-arp-spoofing'> <filter name='ARP' policy='drop'> <!-- no arp spoofing --> <!-- drop if ipaddr or macaddr does not belong to guest --> <rule action='drop' direction='out'> <arp match='no' srcmacaddr=''/> <arp match='no' srcipaddr='' /> </rule> <!-- drop if ipaddr or macaddr does not belong to guest --> <rule action='drop' direction='in'> <arp match='no' dstmacaddr=' '/> <arp match='no' dstipaddr='' />
What was the idea with the empty attributes here ? Are those implying that the attribute value is to be filled in with the value from the domain XML ? If so I'd probably make that more explicit using something like $IP and $MAC to represent the guest configured IP/MAC
Yes, this is a good idea. We had originally thought of introducing a symbol like 'THIS_IP' for the specific domain.
</rule> <!-- allow all other request or reply packets --> <rule action='allow' direction='inout'> <arp opcode='request'/> <arp opcode='reply'/> </rule> </filter> </template>
<template name='no-mac-spoofing'> <filter name='DLFT'> <!-- no mac spoofing --> <rule action='drop' direction='out'> <mac match='no' srcmacaddr=''/> </rule> </filter> </template>
<template name='no-ip-spoofing'> <filter name='IPv4'> <!-- no ip spoofing --> <rule action='drop' direction='out'> <ip match='no' srcipaddr=''/> </rule> </filter> </template>
I don't think that '<firewall>' is the top level object to be managed here. I would suggest that '<firewall>' and '<template>' elements are redundant, and that <filter> should be for the top level managed objects. The libvirt API would allow listing of existing filters, creating / deleting filters and updating the config. The <filter> element would allow some kind of <include> element to allow a complex filter to be built out of multiple simpler filters.
yes, that should be possible. thanks Vivek
Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
__ Vivek Kashyap Linux Technology Center, IBM

Daniel Veillard <veillard@redhat.com> wrote on 01/13/2010 12:03:22 PM:
On Mon, Jan 11, 2010 at 12:55:27PM -0500, Stefan Berger wrote:
Hello!
[...]
raw network throughput performance hit on their system due to the evaluation of every packet passing through the filtering chains, do not have to use these capabilities. An initial implementation would be done for libvirt's Qemu support.
It's relatively clear that this would not work with devices exposed natively to the domain, say though PCI passthough. I'm wondering what
Future SR-IOV devices may be programmable and provide at least a subset of the filtering that can be done with this XML. In that case we would probably need hardware specific drivers in libvirt that can issue proper ioctl()s with the proper parameters to activate the corresponding filtering.
other case of limitiations could be found. Also this may not map well for other kind of hypervisors like VMWare, right ?
I don't know much about the API that VMWare is exposing. Maybe only a certain subset of what would be possible with this XML could be applied to their API, if such functionality exist. Otherwise, if libvirt can run ebtables and iptables commands on their management VM and all traffic passes through VM=specific network interface (tap) in that VM, it *should* work as well.
As stated above, the application of firewall rules on virtual machines
will require some form of XML description that lets the user choose what type of filtering is to be performed. In effect the user needs to be able to tell libvirt which ebtables and iptables rules to generate so that
the
appropriate filtering can be done. We realize that ebtables and iptables have lots of capabilities but think that we need to restrict which capabilities can actually be 'reached' through this XML.
The following proposal is based on an XML as defined by the DMTF ( http://www.dmtf.org/standards/cim/cim_schema_v2230/CIM_Network.pdf, slide 10) with extensions for processing of ARP packets.It gives control over the evaluation of Ethernet (MAC) frames, ARP packet data and IP header
information. A (draft) XML skeleton in this case could look as follows:
Humpf, extending astandard XML schemas is really bad practice. Even if you think that the extension may be accepted later, it may have different semantic for the same construct and that's a disaster. I would at least put the new elements in a separate namespace to avoid something insane if DMTF extends its specification.
Yes, we could do that. As said, this was meant as a draft.
<FilterEntry> <Action>DROP|ACCEPT</Action> <!-- from FilterEntry -->
<TrafficType>incoming [to VM]|outgoing [from VM]</TrafficType>
<Hdr8021Filter> <HdrSrcMACAddr8021> </HdrSrcMACAddr8021> <HdrSrcMACMask8021> </HdrSrcMACMask8021> <HdrDestMACAddr8021> </HdrDestMACAddr8021> <HdrDestMACMask8021> </HdrDestMACMask8021> <HdrProtocolID8021> numeric and/or string? </HdrProtocolID8021> <HdrPriorityValue8021></HdrPriorityValue8021> <HdrVLANID8021> </HdrVLANID8021> </Hdr8021Filter>
<ARPFilter> <HWType> </HWType> <ProtocolType> </ProtocolType> <OPCode> </OPCode> <SrcMACAddr> </SrcMACAddr> <SrcIPAddr> </SrcIPAddr> <DestMACAddr> </DestMACAddr> <DestIPAddr> </DestIPAddr> </ARPFilter>
<IPHeadersFilter> <HdrIPVersion> </HdrIPVersion> <HdrSrcAddress> </HdrSrcAddress> <HdrSrcMask> </HdrSrcMask> <HdrDestAddress> </HdrDestAddress> <HdrDestMask> </HdrDestMask> <HdrProtocolID> numeric and/or string?
</HdrProtocolID>
<HdrSrcPortStart> </HdrSrcPortStart> <HdrSrcPortEnd> </HdrSrcPortEnd> <HdrDestPortStart> </HdrDestPortStart> <HdrDestPortEnd> </HdrDestPortEnd> <HdrDSCP> </HdrDSCP> </IPHeadersFilter>
</FilterEntry>
hum the types for each values should be made explicit if possible, But in general I find that extremely bulky for a single entry, while I would expect any domain to have a dozen filters or so just for simple stuff. I wonder if empty default should just be dropped, so that basically if you're filtering on a MAC address you don't carry a bunch of unused fields.
Of course empty XML elements would not be shown. The above XML is meant to show all the network packet 'elements' that can be tested and for which also ebtables and iptables support exists. Also only a certain combination of the above elements would be set for a specific corresponding ebtables command. An example for a (template) XML for testing against MAC spoofing could be this XML here, which drops all IPv4 packets that don't have the proper MAC address set. <FilterEntry> <Action>DROP</Action> <TrafficType>outgoing</TrafficType> <Hdr8021Filter> <HdrSrcMACAddr8021>![THIS_MAC]</HdrSrcMACAddr8021> </Hdr8021Filter> <IPHeadersFilter> <HdrIPVersion>4</HdrIPVersion> </IPHeadersFilter> </FilterEntry>
Since the ebtables and iptables command cannot accept all possible parameters at the same time, only a certain subset of the above
parameters
may be set for any given filter command. Higher level application writers will likely use a library that lets them choose which features they would want to have enforced, such as no-broadcast or no-multicast, enforcement of MAC spoofing prevention or ARP poisoning prevention, which then generates this lower level XML rules in the appropriate order of the rules.
I wonder if a tailored set of simpler XML matching what is actually possible and getting away from the DMTF records wouldn't be better, since the original spec is extended on the feature side and the applicability is restricted on the implementation side, I'm not sure I see the point of trying to be compatible.
If we want to give the user full control over the ebtables and iptables features, an XML as the one above would be necessary. A more higher level XML may look as follows: <firewall> <no-mac-spoofing/> <no-ip-spoofing address="9.59.241.151"/> <ether-allow protocols='ARP,IPv4'/> [...] </firewall> This XML only gives the user control over the features that have been explicitly implemented in libvirt, i.e., the driver would know what the corresponding ebtables commands are to enforce no-mac-spoofing, in which order the ebtable rules need to be organized and when to create new user defined ebtables (ebtables -N) to provide a more efficient evaluation of the filtering. The XSL trafo that Daniel Berrange mentioned would likely not be possible with this XML, since the ordering, depending on the chosen security features, may be tricky to support with a transformation. In the explicit XML above, the user would be expected to put the rules into proper order and likely would somehow need to provide user defined table names into which the individual rules need to be put. With this XML here, this would be automatically handled by the libvirt implementation.
Further, we will introduce filter pools where a collection of the
above
filter rules can be stored and referenced to by virtual machines' individual interface. A reference to such a filter pool entry will be given in the interface description and may look as in the following draft XML:
<interface type='bridge'> <source bridge='virbr0'/> <script path='vif-bridge'/> <firewall> <reference profile='generic-layer2' ip_address='10.0.0.1'/> <reference profile='VM-specific-layer3'/> </firewall> </interface>
the devil is in the details, basically how you would template the profiles based on the strings in the reference. I.e. what the profile would look like and how for example ip_address='10.0.0.1' would be instancied in the profile use.
We thought that maybe the HdrSrcMACAddr8021 XML element could have [THIS_MAC] as content, which would then need to become concrete when instantiated. Similarly we could put [THIS_IP] into the XML element testing for source (and destination) IP address. So the ip_address above would be passed into the function instantiating the rules for the VM.
Further, we would introduce the management of filter 'pools'.
Considering
existing functionality in libvirt and CLI commands for similar type of
management functionality, the following CLI commands would be added:
virsh nwfilter-create <file> virsh nwfilter-destroy <profile name> virsh nwfilter-list <options> virsh nwfilter-dumpxml <profile name> virsh nwfilter-update <filename> (performs an update on an existing profile replacing all rules)
possibly also:
virsh nwfilter-edit <profile name> virsh nwfilter-create-from <profile name>
Please let us know what you think of this proposal.
The feature looks interesting ! It looks it should be applicable to at least qemu and xen, I'm not so sure about LXC or VirtualBox, and looks unlikely for VMWare unless they have a matching capability (might be possible since it's based at least partly on DMTF).
It would work with any technology that uses an ethernet interface in the host, i.e., a tap or backend interface, through which all the VM's network traffic passes. All firewall rules would be conditioned on the VM's interface name and jump into a VM-specific rules tree. As for VirtualBox, since it is Qemu based and probably has a tap interface, this should also work. I have never used LXC, so I cannot say much about it, but it would also require a network interface in the host onto which ebtables and iptables could condition their rules on (ebtables -A ... -i <tap interface name> ...). One other thing to consider is whether pools should actually be used. The problem with the pools may arise when trying to migrate VMs. If the target host does not have the same named pool, then higher layer software would need to migrate the firewall rules first so the same rules can be enforced on the target as well. If, however, the rules are directly in the interface XML of the VM description, then migration would be done using 'virsh migrate', since the VM description migrates anyway. Regards, Stefan
I'm not sure reusing the DMTF format actually helps much, it also has its risks due to the extension.
Daniel
-- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

2010/1/13 Stefan Berger <stefanb@us.ibm.com>:
Daniel Veillard <veillard@redhat.com> wrote on 01/13/2010 12:03:22 PM:
On Mon, Jan 11, 2010 at 12:55:27PM -0500, Stefan Berger wrote:
Hello!
[...]
[...]
other case of limitiations could be found. Also this may not map well for other kind of hypervisors like VMWare, right ?
I don't know much about the API that VMWare is exposing. Maybe only a certain subset of what would be possible with this XML could be applied to their API, if such functionality exist. Otherwise, if libvirt can run ebtables and iptables commands on their management VM and all traffic passes through VM=specific network interface (tap) in that VM, it *should* work as well.
VMware ESX hosts allow to configure the host level firewall via the remote VI API. But AFAIK there is no virtual machine level firewall. You're not supposed to do something like that in the service console, doing anything in the service console is not supported in general. Also there is no libvirtd in the service console because of that and because it is not necessary. The ESX driver does everything using the remote VI API. Matthias

Note that this is the case for the standard VMware ESX vSwitch. However, the Cisco Nexus 1000v, which is an optional virtual switch for ESX, does appear to provide (guest) VM firewall capabilities. See for example the section on "isolation and protection" and ACLs in the link below: http://www.cisco.com/en/US/prod/collateral/switches/ps9441/ps9902/dmz_virtua... In terms of interfaces, the 1000v claims a CLI (likely similar to physical Cisco switches), support for SNMP and an XML API. Thanks, Dimitrios From: Matthias Bolte <matthias.bolte@googlemail.com> To: Stefan Berger/Watson/IBM@IBMUS Cc: Gerhard Stenzel <gerhard.stenzel@de.ibm.com>, libvir-list@redhat.com, Vivek Kashyap/Beaverton/IBM@IBMUS Date: 01/13/2010 05:43 PM Subject: Re: [libvirt] [RFC] Proposal for introduction of network traffic filtering capabilities for filtering of network traffic from and to VMs Sent by: libvir-list-bounces@redhat.com 2010/1/13 Stefan Berger <stefanb@us.ibm.com>:
Daniel Veillard <veillard@redhat.com> wrote on 01/13/2010 12:03:22 PM:
On Mon, Jan 11, 2010 at 12:55:27PM -0500, Stefan Berger wrote:
Hello!
[...]
[...]
other case of limitiations could be found. Also this may not map well for other kind of hypervisors like VMWare, right ?
I don't know much about the API that VMWare is exposing. Maybe only a certain subset of what would be possible with this XML could be applied to their API, if such functionality exist. Otherwise, if libvirt can run ebtables and iptables commands on their management VM and all traffic passes through VM=specific network interface (tap) in that VM, it *should* work as well.
VMware ESX hosts allow to configure the host level firewall via the remote VI API. But AFAIK there is no virtual machine level firewall. You're not supposed to do something like that in the service console, doing anything in the service console is not supported in general. Also there is no libvirtd in the service console because of that and because it is not necessary. The ESX driver does everything using the remote VI API. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

Le 14/01/2010 vers 01:09, dans le message intitulé "Re: [libvirt] [RFC] Proposal for introduction of network traffic filtering capabilities for filtering of network traffic from and to VMs", Dimitrios Pendarakis(Dimitrios Pendarakis <dimitris@us.ibm.com>) a écrit: Hi,
Note that this is the case for the standard VMware ESX vSwitch. However, the Cisco Nexus 1000v, which is an optional virtual switch for ESX, does appear to provide (guest) VM firewall capabilities.
OpenVswitch project (http://openvswitch.org/) seems to provide the same thing for KVM, Xen and Virtualbox. This should be wonderfull if the VM based filtering is done using OpenVswitch capabilities... -- http://www.glennie.fr If the only tool you have is hammer, you tend to see every problem as a nail.

The feature looks interesting ! It looks it should be applicable to at least qemu and xen, I'm not so sure about LXC or VirtualBox, and looks unlikely for VMWare unless they have a matching capability (might be possible since it's based at least partly on DMTF).
It would work with any technology that uses an ethernet interface in the host, i.e., a tap or backend interface, through which all the VM's network traffic passes. All firewall rules would be conditioned on the VM's interface name and jump into a VM-specific rules tree.
As for VirtualBox, since it is Qemu based and probably has a tap interface, this should also work. I have never used LXC, so I cannot say much about it, but it would also require a network interface in the host onto which ebtables and iptables could condition their rules on (ebtables -A ... -i <tap interface name> ...).
It should be applicable to lx. LXC networking (http://lxc.sourceforge.net/network/configuration.php) can be setup using virtual interfaces and bridge. I believe for VMware one would need to write a backend that can translate from this xml to the VMware APIs. The xml spec can stay the same since as you note it is derived from DMTF (and what is already supported in physical switches). Vivek __ Vivek Kashyap Linux Technology Center, IBM
participants (8)
-
Daniel P. Berrange
-
Daniel Veillard
-
Dimitrios Pendarakis
-
Gerhard Stenzel
-
Glennie Vignarajah
-
Matthias Bolte
-
Stefan Berger
-
Vivek Kashyap