From: Pavel Hrdina <phrdina(a)redhat.com>
Also adjust direct links from other pages.
Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
docs/firewall.rst | 2 +-
docs/formatdomain.rst | 3 +-
docs/formatnwfilter.html.in | 2471 -----------------------------------
docs/formatnwfilter.rst | 1789 +++++++++++++++++++++++++
docs/meson.build | 2 +-
5 files changed, 1793 insertions(+), 2474 deletions(-)
delete mode 100644 docs/formatnwfilter.html.in
create mode 100644 docs/formatnwfilter.rst
diff --git a/docs/firewall.rst b/docs/firewall.rst
index adda0ef1f4..eff9de5a89 100644
--- a/docs/firewall.rst
+++ b/docs/firewall.rst
@@ -250,7 +250,7 @@ source IP address ``!= $IP`` like this:
I'm not going to go into details on all the other protocol matches you can do,
because it'll take far too much space. You can read about the options
-`here <formatnwfilter.html#nwfelemsRulesProto>`__.
+`here <formatnwfilter.html#supported-protocols>`__.
Out of the box in RHEL6/Fedora rawhide, libvirt ships with a set of default
useful rules:
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 24fbfd8670..552b5364f8 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -5845,7 +5845,8 @@ complete details.
The ``filter`` attribute specifies the name of the nwfilter to use. Optional
``<parameter>`` elements may be specified for passing additional info to the
nwfilter via the ``name`` and ``value`` attributes. See the
-`nwfilter <formatnwfilter.html#nwfconceptsvars>`__ docs for info on parameters.
+`nwfilter <formatnwfilter.html#usage-of-variables-in-filters>`__ docs for info
+on parameters.
:anchor:`<a id="elementsInput"/>`
diff --git a/docs/formatnwfilter.html.in b/docs/formatnwfilter.html.in
deleted file mode 100644
index 04aeda06ec..0000000000
--- a/docs/formatnwfilter.html.in
+++ /dev/null
@@ -1,2471 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html>
-<html
xmlns="http://www.w3.org/1999/xhtml">
- <body>
- <h1>Network Filters</h1>
-
- <ul id="toc">
- </ul>
-
- <p>
- This page provides an introduction to libvirt's network filters,
- their goals, concepts and XML format.
- </p>
-
- <h2><a id="goals">Goals and background</a></h2>
-
- <p>
- The goal of the network filtering XML is to enable administrators
- of a virtualized system to configure and enforce network traffic
- filtering rules on virtual
- machines and manage the parameters of network traffic that
- virtual machines
- are allowed to send or receive.
- The network traffic filtering rules are
- applied on the host when a virtual machine is started. Since the
- filtering rules
- cannot be circumvented from within
- the virtual machine, it makes them mandatory from the point of
- view of a virtual machine user.
- <br/><br/>
- The network filter subsystem allows each virtual machine's network
- traffic filtering rules to be configured individually on a per
- interface basis. The rules are
- applied on the host when the virtual machine is started and can be modified
- while the virtual machine is running. The latter can be achieved by
- modifying the XML description of a network filter.
- <br/><br/>
- Multiple virtual machines can make use of the same generic network filter.
- When such a filter is modified, the network traffic filtering rules
- of all running virtual machines that reference this filter are updated.
- <br/><br/>
- Network filtering support is available <span class="since">since
0.8.1
- (QEMU, KVM)</span>
- </p>
-
- <h2><a id="nwfconcepts">Concepts</a></h2>
- <p>
- The network traffic filtering subsystem enables configuration
- of network traffic filtering rules on individual network
- interfaces that are configured for certain types of
- network configurations. Supported network types are
- </p>
- <ul>
- <li><code>network</code></li>
- <li><code>ethernet</code> -- must be used in bridging
mode</li>
- <li><code>bridge</code></li>
- </ul>
- <p>
- The interface XML is used to reference a top-level filter. In the
- following example, the interface description references
- the filter <code>clean-traffic</code>.
- </p>
-<pre>
-...
-<devices>
- <interface type='bridge'>
- <mac address='00:16:3e:5d:c7:9e'/>
- <filterref filter='clean-traffic'/>
- </interface>
-</devices>
-...</pre>
-
- <p>
- Network filters are written in XML and may either contain references
- to other filters, contain rules for traffic filtering, or
- hold a combination of both. The above referenced filter
- <code>clean-traffic </code> is a filter that only contains references to
- other filters and no actual filtering rules. Since references to
- other filters can be used, a <i>tree</i> of filters can be built.
- The <code>clean-traffic</code> filter can be viewed using the
- command <code>virsh nwfilter-dumpxml clean-traffic</code>.
- <br/><br/>
- As previously mentioned, a single network filter can be referenced
- by multiple virtual machines. Since interfaces will typically
- have individual parameters associated with their respective traffic
- filtering rules, the rules described in a filter XML can
- be parameterized with variables. In this case, the variable name
- is used in the filter XML and the name and value are provided at the
- place where the filter is referenced. In the
- following example, the interface description has been extended with
- the parameter <code>IP</code> and a dotted IP address as value.
- </p>
-<pre>
-...
-<devices>
- <interface type='bridge'>
- <mac address='00:16:3e:5d:c7:9e'/>
- <filterref filter='clean-traffic'>
- <parameter name='IP' value='10.0.0.1'/>
- </filterref>
- </interface>
-</devices>
-...</pre>
-
- <p>
- In this particular example, the <code>clean-traffic</code> network
- traffic filter will be instantiated with the IP address parameter
- 10.0.0.1 and enforce that the traffic from this interface will
- always be using 10.0.0.1 as the source IP address, which is
- one of the purposes of this particular filter.
- <br/><br/>
- </p>
-
- <h3><a id="nwfconceptschains">Filtering
chains</a></h3>
- <p>
- Filtering rules are organized in filter chains. These chains can be
- thought of as having a tree structure with packet
- filtering rules as entries in individual chains (branches). <br/>
- Packets start their filter evaluation in the <code>root</code> chain
- and can then continue their evaluation in other chains, return from
- those chains back into the <code>root</code> chain or be
- dropped or accepted by a filtering rule in one of the traversed chains.
- <br/>
- Libvirt's network filtering system automatically creates individual
- <code>root</code> chains for every virtual machine's network
interface
- on which the user chooses to activate traffic filtering.
- The user may write filtering rules that are either directly instantiated
- in the <code>root</code> chain or may create protocol-specific
- filtering chains for efficient evaluation of protocol-specific rules.
- The following chains exist:
- </p>
- <ul>
- <li>root</li>
- <li>mac <span class="since">(since
0.9.8)</span></li>
- <li>stp (spanning tree protocol)
- <span class="since">(since 0.9.8)</span></li>
- <li>vlan (802.1Q) <span class="since">(since
0.9.8)</span></li>
- <li>arp, rarp</li>
- <li>ipv4</li>
- <li>ipv6</li>
- </ul>
- <p>
- <span class="since">Since 0.9.8</span> multiple chains
evaluating the
- <code>mac</code>, <code>stp</code>,
<code>vlan</code>,
- <code>arp</code>, <code>rarp</code>,
<code>ipv4</code>, or
- <code>ipv6</code> protocol can be created using
- the protocol name only as a prefix in the chain's name. This for
- examples allows chains with names <code>arp-xyz</code> or
- <code>arp-test</code> to be specified and have ARP protocol packets
- evaluated in those chains.
- <br/><br/>
- The following filter shows an example of filtering ARP traffic
- in the <code>arp</code> chain.
- </p>
-<pre>
-<filter name='no-arp-spoofing' chain='arp'
priority='-500'>
- <uuid>f88f1932-debf-4aa1-9fbe-f10d3aa4bc95</uuid>
- <rule action='drop' direction='out'
priority='300'>
- <mac match='no' srcmacaddr='$MAC'/>
- </rule>
- <rule action='drop' direction='out'
priority='350'>
- <arp match='no' arpsrcmacaddr='$MAC'/>
- </rule>
- <rule action='drop' direction='out'
priority='400'>
- <arp match='no' arpsrcipaddr='$IP'/>
- </rule>
- <rule action='drop' direction='in'
priority='450'>
- <arp opcode='Reply'/>
- <arp match='no' arpdstmacaddr='$MAC'/>
- </rule>
- <rule action='drop' direction='in'
priority='500'>
- <arp match='no' arpdstipaddr='$IP'/>
- </rule>
- <rule action='accept' direction='inout'
priority='600'>
- <arp opcode='Request'/>
- </rule>
- <rule action='accept' direction='inout'
priority='650'>
- <arp opcode='Reply'/>
- </rule>
- <rule action='drop' direction='inout'
priority='1000'/>
-</filter>
-</pre>
- <p>
- The consequence of putting ARP-specific rules in the <code>arp</code>
- chain, rather than for example in the <code>root</code> chain, is that
- packets for any other protocol than ARP do not need to be evaluated by
- ARP protocol-specific rules. This improves the efficiency
- of the traffic filtering. However, one must then pay attention to only
- put filtering rules for the given protocol into the chain since
- any other rules will not be evaluated, i.e., an IPv4 rule will not
- be evaluated in the ARP chain since no IPv4 protocol packets will
- traverse the ARP chain.
- <br/><br/>
- </p>
- <h3><a id="nwfconceptschainpriorities">Filtering chain
priorities</a></h3>
- <p>
- All chains are connected to the <code>root</code> chain. The order in
- which those chains are accessed is influenced by the priority of the
- chain. The following table shows the chains that can be assigned a
- priority and their default priorities.
- </p>
- <table class="top_table">
- <tr>
- <th> Chain (prefix) </th>
- <th> Default priority </th>
- </tr>
- <tr>
- <td>stp</td><td>-810</td>
- </tr>
- <tr>
- <td>mac</td><td>-800</td>
- </tr>
- <tr>
- <td>vlan</td><td>-750</td>
- </tr>
- <tr>
- <td>ipv4</td><td>-700</td>
- </tr>
- <tr>
- <td>ipv6</td><td>-600</td>
- </tr>
- <tr>
- <td>arp</td><td>-500</td>
- </tr>
- <tr>
- <td>rarp</td><td>-400</td>
- </tr>
- </table>
- <p>
- A chain with a lower priority value is accessed before one with a
- higher value.
- <br/>
- <span class="since">Since 0.9.8</span> the above listed
chains
- can be assigned custom priorities by writing a value in the
- range [-1000, 1000] into the priority (XML) attribute in the filter
- node. The above example filter shows the default priority of -500
- for <code>arp</code> chains.
- </p>
- <h3><a id="nwfconceptsvars">Usage of variables in
filters</a></h3>
- <p>
-
- Two variables names have so far been reserved for usage by the
- network traffic filtering subsystem: <code>MAC</code> and
- <code>IP</code>.
- <br/><br/>
- <code>MAC</code> is the MAC address of the
- network interface. A filtering rule that references this variable
- will automatically be instantiated with the MAC address of the
- interface. This works without the user having to explicitly provide
- the MAC parameter. Even though it is possible to specify the MAC
- parameter similar to the IP parameter above, it is discouraged
- since libvirt knows what MAC address an interface will be using.
- <br/><br/>
- The parameter <code>IP</code> represents the IP address
- that the operating system inside the virtual machine is expected
- to use on the given interface. The <code>IP</code> parameter
- is special in so far as the libvirt daemon will try to determine
- the IP address (and thus the IP parameter's value) that is being
- used on an interface if the parameter
- is not explicitly provided but referenced.
- For current limitations on IP address detection, consult the
- <a href="#nwflimits">section on limitations</a> on how to use
this
- feature and what to expect when using it.
- <br/><br/>
- The above-shown network filer <code>no-arp-spoofing</code>
- is an example of
- a network filter XML referencing the <code>MAC</code> and
- <code>IP</code> variables.
- <br/><br/>
- Note that referenced variables are always prefixed with the
- $ (dollar) sign. The format of the value of a variable
- must be of the type expected by the filter attribute in the
- XML. In the above example, the <code>IP</code> parameter
- must hold a dotted IP address in decimal numbers format.
- Failure to provide the correct
- value type will result in the filter not being instantiatable
- and will prevent a virtual machine from starting or the
- interface from attaching when hotplugging is used. The types
- that are expected for each XML attribute are shown
- below.
- <br/><br/>
- <span class="since">Since 0.9.8</span> variables can contain
lists of
- elements, e.g., the variable <code>IP</code> can contain multiple IP
- addresses that are valid on a particular interface. The notation for
- providing multiple elements for the IP variable is:
- </p>
-<pre>
-...
-<devices>
- <interface type='bridge'>
- <mac address='00:16:3e:5d:c7:9e'/>
- <filterref filter='clean-traffic'>
- <parameter name='IP' value='10.0.0.1'/>
- <parameter name='IP' value='10.0.0.2'/>
- <parameter name='IP' value='10.0.0.3'/>
- </filterref>
- </interface>
-</devices>
-...</pre>
- <p>
- This then allows filters to enable multiple IP addresses
- per interface. Therefore, with the list
- of IP address shown above, the following rule will create 3
- individual filtering rules, one for each IP address.
- </p>
-<pre>
-...
-<rule action='accept' direction='in'
priority='500'>
- <tcp srpipaddr='$IP'/>
-</rule>
-...
-</pre>
- <p>
- <span class="since">Since 0.9.10</span> it is possible to
access
- individual elements of a variable holding a list of elements.
- A filtering rule like the following accesses the 2nd element
- of the variable DSTPORTS.
- </p>
-<pre>
-...
-<rule action='accept' direction='in'
priority='500'>
- <udp dstportstart='$DSTPORTS[1]'/>
-</rule>
-...
-</pre>
- <p>
- <span class="since">Since 0.9.10</span> it is possible to
create
- filtering rules that instantiate all combinations of rules from
- different lists using the notation of
- <code>$VARIABLE[@<iterator ID>]</code>.
- The following rule allows a virtual machine to
- receive traffic on a set of ports, which are specified in DSTPORTS,
- from the set of source IP address specified in SRCIPADDRESSES.
- The rule generates all combinations of elements of the variable
- DSTPORT with those of SRCIPADDRESSES by using two independent
- iterators to access their elements.
- </p>
-<pre>
-...
-<rule action='accept' direction='in'
priority='500'>
- <ip srcipaddr='$SRCIPADDRESSES[@1]'
dstportstart='$DSTPORTS[@2]'/>
-</rule>
-...
-</pre>
-
- <p>
- In an example we assign concrete values to SRCIPADDRESSES and DSTPORTS
- </p>
-<pre>
-SRCIPADDRESSES = [ 10.0.0.1, 11.1.2.3 ]
-DSTPORTS = [ 80, 8080 ]
-</pre>
- <p>
- Accessing the variables using $SRCIPADDRESSES[@1] and $DSTPORTS[@2] would
- then result in all combinations of addresses and ports being created:
- </p>
-<pre>
-10.0.0.1, 80
-10.0.0.1, 8080
-11.1.2.3, 80
-11.1.2.3, 8080
-</pre>
- <p>
- Accessing the same variables using a single iterator, for example by using
- the notation $SRCIPADDRESSES[@1] and $DSTPORTS[@1], would result in
- parallel access to both lists and result in the following combinations:
- </p>
-<pre>
-10.0.0.1, 80
-11.1.2.3, 8080
-</pre>
- <p>
- Further, the notation of $VARIABLE is short-hand for $VARIABLE[@0]. The
- former notation always assumes the iterator with Id '0'.
- </p>
-
- <h3><a id="nwfelemsRulesAdvIPAddrDetection">Automatic IP
address detection</a></h3>
- <p>
- The detection of IP addresses used on a virtual machine's interface
- is automatically activated if the variable <code>IP</code> is
referenced
- but no value has been assigned to it.
- <span class="since">Since 0.9.13</span>
- the variable <code>CTRL_IP_LEARNING</code> can be used to specify
- the IP address learning method to use. Valid values are
<code>any</code>,
- <code>dhcp</code>, or <code>none</code>.
- <br/><br/>
- The value <code>any</code> means that libvirt may use any packet to
- determine the address in use by a virtual machine, which is the default
- behavior if the variable <code>CTRL_IP_LEARNING</code> is not set.
This method
- will only detect a single IP address on an interface.
- Once a VM's IP address has been detected, its IP network traffic
- will be locked to that address, if for example IP address spoofing
- is prevented by one of its filters. In that case the user of the VM
- will not be able to change the IP address on the interface inside
- the VM, which would be considered IP address spoofing.
- When a VM is migrated to another host or resumed after a suspend operation,
- the first packet sent by the VM will again determine the IP address it can
- use on a particular interface.
- <br/>
- A value of <code>dhcp</code> specifies that libvirt should only honor
DHCP
- server-assigned addresses with valid leases. This method supports the detection
- and usage of multiple IP address per interface.
- When a VM is resumed after a suspend operation, still valid IP address leases
- are applied to its filters. Otherwise the VM is expected to again use DHCP to
obtain new
- IP addresses. The migration of a VM to another physical host requires that
- the VM again runs the DHCP protocol.
- <br/><br/>
- Use of <code>CTRL_IP_LEARNING=dhcp</code> (DHCP snooping) provides
additional
- anti-spoofing security, especially when combined with a filter allowing
- only trusted DHCP servers to assign addresses. To enable this, set the
- variable <code>DHCPSERVER</code> to the IP address of a valid DHCP
server
- and provide filters that use this variable to filter incoming DHCP responses.
- <br/><br/>
- When DHCP snooping is enabled and the DHCP lease expires,
- the VM will no longer be able to use the IP address until it acquires a
- new, valid lease from a DHCP server. If the VM is migrated, it must get
- a new valid DHCP lease to use an IP address (e.g., by
- bringing the VM interface down and up again).
- <br/><br/>
- Note that automatic DHCP detection listens to the DHCP traffic
- the VM exchanges with the DHCP server of the infrastructure. To avoid
- denial-of-service attacks on libvirt, the evaluation of those packets
- is rate-limited, meaning that a VM sending an excessive number of DHCP
- packets per second on an interface will not have all of those packets
- evaluated and thus filters may not get adapted. Normal DHCP client
- behavior is assumed to send a low number of DHCP packets per second.
- Further, it is important to setup appropriate filters on all VMs in
- the infrastructure to avoid them being able to send DHCP
- packets. Therefore VMs must either be prevented from sending UDP and TCP
- traffic from port 67 to port 68 or the <code>DHCPSERVER</code>
- variable should be used on all VMs to restrict DHCP server messages to
- only be allowed to originate from trusted DHCP servers. At the same
- time anti-spoofing prevention must be enabled on all VMs in the subnet.
- <br/><br/>
- If <code>CTRL_IP_LEARNING</code> is set to
<code>none</code>, libvirt does not do
- IP address learning and referencing <code>IP</code> without assigning
it an
- explicit value is an error.
- <br/><br/>
- The following XML provides an example for the activation of IP address learning
- using the DHCP snooping method:
- </p>
-<pre>
-<interface type='bridge'>
- <source bridge='virbr0'/>
- <filterref filter='clean-traffic'>
- <parameter name='CTRL_IP_LEARNING' value='dhcp'/>
- </filterref>
-</interface>
-</pre>
-
- <h3><a id="nwfelemsReservedVars">Reserved
Variables</a></h3>
- <p>
- The following table lists reserved variables in use by libvirt.
- </p>
- <table class="top_table">
- <tr>
- <th> Variable Name </th>
- <th> Semantics </th>
- </tr>
- <tr>
- <td> MAC </td>
- <td> The MAC address of the interface </td>
- </tr>
- <tr>
- <td> IP </td>
- <td> The list of IP addresses in use by an interface </td>
- </tr>
- <tr>
- <td> IPV6 </td>
- <td> The list of IPV6 addresses in use by an interface </td>
- </tr>
- <tr>
- <td> DHCPSERVER </td>
- <td> The list of IP addresses of trusted DHCP servers</td>
- </tr>
- <tr>
- <td> DHCPSERVERV6 </td>
- <td> Not currently implemented:
- The list of IPv6 addresses of trusted DHCP servers</td>
- </tr>
- <tr>
- <td> CTRL_IP_LEARNING </td>
- <td> The choice of the IP address detection mode </td>
- </tr>
- </table>
-
- <h2><a id="nwfelems">Element and attribute
overview</a></h2>
-
- <p>
- The root element required for all network filters is
- named <code>filter</code> with two possible attributes. The
- <code>name</code> attribute provides a unique name of the
- given filter. The <code>chain</code> attribute is optional but
- allows certain filters to be better organized for more efficient
- processing by the firewall subsystem of the underlying host.
- Currently the system only supports the chains <code>root,
- ipv4, ipv6, arp and rarp</code>.
- </p>
-
- <h3><a id="nwfelemsRefs">References to other
filters</a></h3>
- <p>
- Any filter may hold references to other filters. Individual
- filters may be referenced multiple times in a filter tree but
- references between filters must not introduce loops (directed
- acyclic graph).
- <br/><br/>
- The following shows the XML of the <code>clean-traffic</code>
- network filter referencing several other filters.
- </p>
-<pre>
-<filter name='clean-traffic'>
- <uuid>6ef53069-ba34-94a0-d33d-17751b9b8cb1</uuid>
- <filterref filter='no-mac-spoofing'/>
- <filterref filter='no-ip-spoofing'/>
- <filterref filter='allow-incoming-ipv4'/>
- <filterref filter='no-arp-spoofing'/>
- <filterref filter='no-other-l2-traffic'/>
- <filterref filter='qemu-announce-self'/>
-</filter>
-</pre>
-
- <p>
- To reference another filter, the XML node <code>filterref</code>
- needs to be provided inside a <code>filter</code> node. This
- node must have the attribute <code>filter</code> whose value contains
- the name of the filter to be referenced.
- <br/><br/>
- New network filters can be defined at any time and
- may contain references to network filters that are
- not known to libvirt, yet. However, once a virtual machine
- is started or a network interface
- referencing a filter is to be hotplugged, all network filters
- in the filter tree must be available. Otherwise the virtual
- machine will not start or the network interface cannot be
- attached.
- </p>
-
- <h3><a id="nwfelemsRules">Filter rules</a></h3>
- <p>
- The following XML shows a simple example of a network
- traffic filter implementing a rule to drop traffic if
- the IP address (provided through the value of the
- variable IP) in an outgoing IP packet is not the expected
- one, thus preventing IP address spoofing by the VM.
- </p>
-<pre>
-<filter name='no-ip-spoofing' chain='ipv4'>
- <uuid>fce8ae33-e69e-83bf-262e-30786c1f8072</uuid>
- <rule action='drop' direction='out'
priority='500'>
- <ip match='no' srcipaddr='$IP'/>
- </rule>
-</filter>
-</pre>
-
- <p>
- A traffic filtering rule starts with the <code>rule</code>
- node. This node may contain up to three attributes
- </p>
- <ul>
- <li>
- action -- mandatory; must either be <code>drop</code>
- (matching the rule silently discards the packet with no
- further analysis),
- <code>reject</code> (matching the rule generates an ICMP
- reject message with no further analysis) <span
class="since">(since
- 0.9.0)</span>, <code>accept</code> (matching the rule accepts
- the packet with no further analysis), <code>return</code>
- (matching the rule passes this filter, but returns control to
- the calling filter for further
- analysis) <span class="since">(since 0.9.7)</span>,
- or <code>continue</code> (matching the rule goes on to the next
- rule for further analysis) <span class="since">(since
- 0.9.7)</span>.
- </li>
- <li>
- direction -- mandatory; must either be <code>in</code>,
<code>out</code> or
- <code>inout</code> if the rule is for incoming,
- outgoing or incoming-and-outgoing traffic
- </li>
- <li>
- priority -- optional; the priority of the rule controls the order in
- which the rule will be instantiated relative to other rules.
- Rules with lower value will be instantiated before rules with higher
- values.
- Valid values are in the range of 0 to 1000.
- <span class="since">Since 0.9.8</span> this has been
extended to cover
- the range of -1000 to 1000. If this attribute is not
- provided, priority 500 will automatically be assigned.
- <br/>
- Note that filtering rules in the <code>root</code> chain are sorted
- with filters connected to the <code>root</code> chain following
- their priorities. This allows to interleave filtering rules with
- access to filter chains.
- (See also section on
- <a href="#nwfconceptschainpriorities">
- filtering chain priorities
- </a>.)
- </li>
- <li>
- statematch -- optional; possible values are '0' or 'false' to
- turn the underlying connection state matching off; default is 'true'
- <br/>
- Also read the section on <a href="#nwfelemsRulesAdv">advanced
configuration</a>
- topics.
- </li>
- </ul>
- <p>
- The above example indicates that the traffic of type <code>ip</code>
- will be associated with the chain 'ipv4' and the rule will have
- priority 500. If for example another filter is referenced whose
- traffic of type <code>ip</code> is also associated with the chain
- 'ipv4' then that filter's rules will be ordered relative to the
priority
- 500 of the shown rule.
- <br/><br/>
- A rule may contain a single rule for filtering of traffic. The
- above example shows that traffic of type <code>ip</code> is to be
- filtered.
- </p>
-
- <h4><a id="nwfelemsRulesProto">Supported
protocols</a></h4>
- <p>
- The following sections enumerate the list of protocols that
- are supported by the network filtering subsystem. The
- type of traffic a rule is supposed to filter on is provided
- in the <code>rule</code> node as a nested node. Depending
- on the traffic type a rule is filtering, the attributes are
- different. The above example showed the single
- attribute <code>srcipaddr</code> that is valid inside the
- <code>ip</code> traffic filtering node. The following sections
- show what attributes are valid and what type of data they are
- expecting. The following datatypes are available:
- </p>
- <ul>
- <li>UINT8 : 8 bit integer; range 0-255</li>
- <li>UINT16: 16 bit integer; range 0-65535</li>
- <li>MAC_ADDR: MAC address in dotted decimal format, i.e.,
00:11:22:33:44:55</li>
- <li>MAC_MASK: MAC address mask in MAC address format, i.e.,
FF:FF:FF:FC:00:00</li>
- <li>IP_ADDR: IP address in dotted decimal format, i.e., 10.1.2.3</li>
- <li>IP_MASK: IP address mask in either dotted decimal format (255.255.248.0)
or CIDR mask (0-32)</li>
- <li>IPV6_ADDR: IPv6 address in numbers format, i.e., FFFF::1</li>
- <li>IPV6_MASK: IPv6 mask in numbers format (FFFF:FFFF:FC00::) or CIDR mask
(0-128)</li>
- <li>STRING: A string</li>
- <li>BOOLEAN: 'true', 'yes', '1' or 'false',
'no', '0'</li>
- <li>IPSETFLAGS: The source and destination flags of the ipset described
- by up to 6 'src' or 'dst' elements selecting features from
either
- the source or destination part of the packet header; example:
- src,src,dst. The number of 'selectors' to provide here depends
- on the type of ipset that is referenced.</li>
- </ul>
- <p>
- <br/><br/>
- Every attribute except for those of type IP_MASK or IPV6_MASK can
- be negated using the <code>match</code>
- attribute with value <code>no</code>. Multiple negated attributes
- may be grouped together. The following
- XML fragment shows such an example using abstract attributes.
- </p>
-<pre>
-[...]
-<rule action='drop' direction='in'>
- <protocol match='no' attribute1='value1'
attribute2='value2'/>
- <protocol attribute3='value3'/>
-</rule>
-[...]
-</pre>
- <p>
- Rules perform a logical AND evaluation on all values of the given
- protocol attributes. Thus, if a single attribute's value does not match
- the one given in the rule, the whole rule will be skipped during
- evaluation. Therefore, in the above example incoming traffic
- will only be dropped if
- the protocol property attribute1 does not match value1 AND
- the protocol property attribute2 does not match value2 AND
- the protocol property attribute3 matches value3.
- <br/><br/>
- </p>
-
-
- <h5><a id="nwfelemsRulesProtoMAC">MAC
(Ethernet)</a></h5>
- <p>
- Protocol ID: <code>mac</code>
- <br/>
- Note: Rules of this type should go into the <code>root</code> chain.
- </p>
- <table class="top_table">
- <tr>
- <th> Attribute </th>
- <th> Datatype </th>
- <th> Semantics </th>
- </tr>
- <tr>
- <td>srcmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of sender</td>
- </tr>
- <tr>
- <td>srcmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of sender</td>
- </tr>
- <tr>
- <td>dstmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of destination</td>
- </tr>
- <tr>
- <td>dstmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of destination</td>
- </tr>
- <tr>
- <td>protocolid</td>
- <td>UINT16 (0x600-0xffff), STRING</td>
- <td>Layer 3 protocol ID</td>
- </tr>
- <tr>
- <td>comment <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>text with max. 256 characters</td>
- </tr>
- </table>
- <p>
- Valid Strings for <code>protocolid</code> are: arp, rarp, ipv4, ipv6
- </p>
-<pre>
-[...]
-<mac match='no' srcmacaddr='$MAC'/>
-[...]
-</pre>
-
- <h5><a id="nwfelemsRulesProtoVLAN">VLAN (802.1Q)</a>
- <span class="since">(Since 0.9.8)</span>
- </h5>
- <p>
- Protocol ID: <code>vlan</code>
- <br/>
- Note: Rules of this type should go either into the <code>root</code>
or
- <code>vlan</code> chain.
- </p>
- <table class="top_table">
- <tr>
- <th> Attribute </th>
- <th> Datatype </th>
- <th> Semantics </th>
- </tr>
- <tr>
- <td>srcmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of sender</td>
- </tr>
- <tr>
- <td>srcmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of sender</td>
- </tr>
- <tr>
- <td>dstmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of destination</td>
- </tr>
- <tr>
- <td>dstmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of destination</td>
- </tr>
- <tr>
- <td>vlanid</td>
- <td>UINT16 (0x0-0xfff, 0 - 4095)</td>
- <td>VLAN ID</td>
- </tr>
- <tr>
- <td>encap-protocol</td>
- <td>UINT16 (0x03c-0xfff), String</td>
- <td>Encapsulated layer 3 protocol ID</td>
- </tr>
- <tr>
- <td>comment </td>
- <td>STRING</td>
- <td>text with max. 256 characters</td>
- </tr>
- </table>
- <p>
- Valid Strings for <code>encap-protocol</code> are: arp, ipv4, ipv6
- </p>
-
- <h5><a id="nwfelemsRulesProtoSTP">STP (Spanning Tree
Protocol)</a>
- <span class="since">(Since 0.9.8)</span>
- </h5>
- <p>
- Protocol ID: <code>stp</code>
- <br/>
- Note: Rules of this type should go either into the <code>root</code>
or
- <code>stp</code> chain.
- </p>
- <table class="top_table">
- <tr>
- <th> Attribute </th>
- <th> Datatype </th>
- <th> Semantics </th>
- </tr>
- <tr>
- <td>srcmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of sender</td>
- </tr>
- <tr>
- <td>srcmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of sender</td>
- </tr>
- <tr>
- <td>type</td>
- <td>UINT8</td>
- <td>Bridge Protocol Data Unit (BPDU) type</td>
- </tr>
- <tr>
- <td>flags</td>
- <td>UINT8</td>
- <td>BPDU flag</td>
- </tr>
- <tr>
- <td>root-priority</td>
- <td>UINT16</td>
- <td>Root priority (range start)</td>
- </tr>
- <tr>
- <td>root-priority-hi</td>
- <td>UINT16</td>
- <td>Root priority range end</td>
- </tr>
- <tr>
- <td>root-address</td>
- <td>MAC_ADDRESS</td>
- <td>Root MAC address</td>
- </tr>
- <tr>
- <td>root-address-mask</td>
- <td>MAC_MASK</td>
- <td>Root MAC address mask</td>
- </tr>
- <tr>
- <td>root-cost</td>
- <td>UINT32</td>
- <td>Root path cost (range start)</td>
- </tr>
- <tr>
- <td>root-cost-hi</td>
- <td>UINT32</td>
- <td>Root path cost range end</td>
- </tr>
- <tr>
- <td>sender-priority</td>
- <td>UINT16</td>
- <td>Sender priority (range start)</td>
- </tr>
- <tr>
- <td>sender-priority-hi</td>
- <td>UINT16</td>
- <td>Sender priority range end</td>
- </tr>
- <tr>
- <td>sender-address</td>
- <td>MAC_ADDRESS</td>
- <td>BPDU sender MAC address</td>
- </tr>
- <tr>
- <td>sender-address-mask</td>
- <td>MAC_MASK</td>
- <td>BPDU sender MAC address mask</td>
- </tr>
- <tr>
- <td>port</td>
- <td>UINT16</td>
- <td>Port identifier (range start)</td>
- </tr>
- <tr>
- <td>port_hi</td>
- <td>UINT16</td>
- <td>Port identifier range end</td>
- </tr>
- <tr>
- <td>msg-age</td>
- <td>UINT16</td>
- <td>Message age timer (range start)</td>
- </tr>
- <tr>
- <td>msg-age-hi</td>
- <td>UINT16</td>
- <td>Message age timer range end</td>
- </tr>
- <tr>
- <td>max-age</td>
- <td>UINT16</td>
- <td>Maximum age timer (range start)</td>
- </tr>
- <tr>
- <td>max-age-hi</td>
- <td>UINT16</td>
- <td>Maximum age timer range end</td>
- </tr>
- <tr>
- <td>hello-time</td>
- <td>UINT16</td>
- <td>Hello time timer (range start)</td>
- </tr>
- <tr>
- <td>hello-time-hi</td>
- <td>UINT16</td>
- <td>Hello time timer range end</td>
- </tr>
- <tr>
- <td>forward-delay</td>
- <td>UINT16</td>
- <td>Forward delay (range start)</td>
- </tr>
- <tr>
- <td>forward-delay-hi</td>
- <td>UINT16</td>
- <td>Forward delay range end</td>
- </tr>
- <tr>
- <td>comment</td>
- <td>STRING</td>
- <td>text with max. 256 characters</td>
- </tr>
- </table>
-
- <h5><a
id="nwfelemsRulesProtoARP">ARP/RARP</a></h5>
- <p>
- Protocol ID: <code>arp</code> or <code>rarp</code>
- <br/>
- Note: Rules of this type should either go into the
- <code>root</code> or <code>arp/rarp</code> chain.
- </p>
- <table class="top_table">
- <tr>
- <th> Attribute </th>
- <th> Datatype </th>
- <th> Semantics </th>
- </tr>
- <tr>
- <td>srcmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of sender</td>
- </tr>
- <tr>
- <td>srcmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of sender</td>
- </tr>
- <tr>
- <td>dstmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of destination</td>
- </tr>
- <tr>
- <td>dstmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of destination</td>
- </tr>
- <tr>
- <td>hwtype</td>
- <td>UINT16</td>
- <td>Hardware type</td>
- </tr>
- <tr>
- <td>protocoltype</td>
- <td>UINT16</td>
- <td>Protocol type</td>
- </tr>
- <tr>
- <td>opcode</td>
- <td>UINT16, STRING</td>
- <td>Opcode</td>
- </tr>
- <tr>
- <td>arpsrcmacaddr</td>
- <td>MAC_ADDR</td>
- <td>Source MAC address in ARP/RARP packet</td>
- </tr>
- <tr>
- <td>arpdstmacaddr</td>
- <td>MAC_ADDR</td>
- <td>Destination MAC address in ARP/RARP packet</td>
- </tr>
- <tr>
- <td>arpsrcipaddr</td>
- <td>IP_ADDR</td>
- <td>Source IP address in ARP/RARP packet</td>
- </tr>
- <tr>
- <td>arpsrcipmask <span class="since">(Since
1.2.3)</span></td>
- <td>IP_MASK</td>
- <td>Source IP mask</td>
- </tr>
- <tr>
- <td>arpdstipaddr</td>
- <td>IP_ADDR</td>
- <td>Destination IP address in ARP/RARP packet</td>
- </tr>
- <tr>
- <td>arpdstipmask <span class="since">(Since
1.2.3)</span></td>
- <td>IP_MASK</td>
- <td>Destination IP mask</td>
- </tr>
- <tr>
- <td>comment <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>text with max. 256 characters</td>
- </tr>
- <tr>
- <td>gratuitous <span class="since">(Since
0.9.2)</span></td>
- <td>BOOLEAN</td>
- <td>boolean indicating whether to check for gratuitous ARP
packet</td>
- </tr>
- </table>
- <p>
- Valid strings for the <code>Opcode</code> field are:
- Request, Reply, Request_Reverse, Reply_Reverse, DRARP_Request,
- DRARP_Reply, DRARP_Error, InARP_Request, ARP_NAK
- <br/><br/>
- </p>
-
- <h5><a id="nwfelemsRulesProtoIP">IPv4</a></h5>
- <p>
- Protocol ID: <code>ip</code>
- <br/>
- Note: Rules of this type should either go into the
- <code>root</code> or <code>ipv4</code> chain.
- </p>
- <table class="top_table">
- <tr>
- <th> Attribute </th>
- <th> Datatype </th>
- <th> Semantics </th>
- </tr>
- <tr>
- <td>srcmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of sender</td>
- </tr>
- <tr>
- <td>srcmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of sender</td>
- </tr>
- <tr>
- <td>dstmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of destination</td>
- </tr>
- <tr>
- <td>dstmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of destination</td>
- </tr>
- <tr>
- <td>srcipaddr</td>
- <td>IP_ADDR</td>
- <td>Source IP address</td>
- </tr>
- <tr>
- <td>srcipmask</td>
- <td>IP_MASK</td>
- <td>Mask applied to source IP address</td>
- </tr>
- <tr>
- <td>dstipaddr</td>
- <td>IP_ADDR</td>
- <td>Destination IP address</td>
- </tr>
- <tr>
- <td>dstipmask</td>
- <td>IP_MASK</td>
- <td>Mask applied to destination IP address</td>
- </tr>
- <tr>
- <td>protocol</td>
- <td>UINT8, STRING</td>
- <td>Layer 4 protocol identifier</td>
- </tr>
- <tr>
- <td>srcportstart</td>
- <td>UINT16</td>
- <td>Start of range of valid source ports; requires
<code>protocol</code></td>
- </tr>
- <tr>
- <td>srcportend</td>
- <td>UINT16</td>
- <td>End of range of valid source ports; requires
<code>protocol</code></td>
- </tr>
- <tr>
- <td>dstportstart</td>
- <td>UINT16</td>
- <td>Start of range of valid destination ports; requires
<code>protocol</code></td>
- </tr>
- <tr>
- <td>dstportend</td>
- <td>UINT16</td>
- <td>End of range of valid destination ports; requires
<code>protocol</code></td>
- </tr>
- <tr>
- <td>dscp</td>
- <td>UINT8 (0x0-0x3f, 0 - 63)</td>
- <td>Differentiated Services Code Point</td>
- </tr>
- <tr>
- <td>comment <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>text with max. 256 characters</td>
- </tr>
- </table>
- <p>
- Valid strings for <code>protocol</code> are:
- tcp, udp, udplite, esp, ah, icmp, igmp, sctp
- <br/><br/>
- </p>
-
-
- <h5><a id="nwfelemsRulesProtoIPv6">IPv6</a></h5>
- <p>
- Protocol ID: <code>ipv6</code>
- <br/>
- Note: Rules of this type should either go into the
- <code>root</code> or <code>ipv6</code> chain.
- </p>
- <table class="top_table">
- <tr>
- <th> Attribute </th>
- <th> Datatype </th>
- <th> Semantics </th>
- </tr>
- <tr>
- <td>srcmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of sender</td>
- </tr>
- <tr>
- <td>srcmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of sender</td>
- </tr>
- <tr>
- <td>dstmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of destination</td>
- </tr>
- <tr>
- <td>dstmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of destination</td>
- </tr>
- <tr>
- <td>srcipaddr</td>
- <td>IPV6_ADDR</td>
- <td>Source IPv6 address</td>
- </tr>
- <tr>
- <td>srcipmask</td>
- <td>IPV6_MASK</td>
- <td>Mask applied to source IPv6 address</td>
- </tr>
- <tr>
- <td>dstipaddr</td>
- <td>IPV6_ADDR</td>
- <td>Destination IPv6 address</td>
- </tr>
- <tr>
- <td>dstipmask</td>
- <td>IPV6_MASK</td>
- <td>Mask applied to destination IPv6 address</td>
- </tr>
- <tr>
- <td>protocol</td>
- <td>UINT8</td>
- <td>Layer 4 protocol identifier</td>
- </tr>
- <tr>
- <td>srcportstart</td>
- <td>UINT16</td>
- <td>Start of range of valid source ports; requires
<code>protocol</code></td>
- </tr>
- <tr>
- <td>srcportend</td>
- <td>UINT16</td>
- <td>End of range of valid source ports; requires
<code>protocol</code></td>
- </tr>
- <tr>
- <td>dstportstart</td>
- <td>UINT16</td>
- <td>Start of range of valid destination ports; requires
<code>protocol</code></td>
- </tr>
- <tr>
- <td>dstportend</td>
- <td>UINT16</td>
- <td>End of range of valid destination ports; requires
<code>protocol</code></td>
- </tr>
- <tr>
- <td>type<span class="since">(Since
1.2.12)</span></td>
- <td>UINT8</td>
- <td>ICMPv6 type; requires <code>protocol</code> to be set to
<code>icmpv6</code></td>
- </tr>
- <tr>
- <td>typeend<span class="since">(Since
1.2.12)</span></td>
- <td>UINT8</td>
- <td>ICMPv6 type end of range; requires <code>protocol</code>
to be set to <code>icmpv6</code></td>
- </tr>
- <tr>
- <td>code<span class="since">(Since
1.2.12)</span></td>
- <td>UINT8</td>
- <td>ICMPv6 code; requires <code>protocol</code> to be set to
<code>icmpv6</code></td>
- </tr>
- <tr>
- <td>code<span class="since">(Since
1.2.12)</span></td>
- <td>UINT8</td>
- <td>ICMPv6 code end of range; requires <code>protocol</code>
to be set to <code>icmpv6</code></td>
- </tr>
- <tr>
- <td>comment <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>text with max. 256 characters</td>
- </tr>
- </table>
- <p>
- Valid strings for <code>protocol</code> are:
- tcp, udp, udplite, esp, ah, icmpv6, sctp
- <br/><br/>
- </p>
-
- <h5><a
id="nwfelemsRulesProtoTCP-ipv4">TCP/UDP/SCTP</a></h5>
- <p>
- Protocol ID: <code>tcp</code>, <code>udp</code>,
<code>sctp</code>
- <br/>
- Note: The chain parameter is ignored for this type of traffic
- and should either be omitted or set to <code>root</code>.
- </p>
- <table class="top_table">
- <tr>
- <th> Attribute </th>
- <th> Datatype </th>
- <th> Semantics </th>
- </tr>
- <tr>
- <td>srcmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of sender</td>
- </tr>
- <tr>
- <td>srcipaddr</td>
- <td>IP_ADDR</td>
- <td>Source IP address</td>
- </tr>
- <tr>
- <td>srcipmask</td>
- <td>IP_MASK</td>
- <td>Mask applied to source IP address</td>
- </tr>
- <tr>
- <td>dstipaddr</td>
- <td>IP_ADDR</td>
- <td>Destination IP address</td>
- </tr>
- <tr>
- <td>dstipmask</td>
- <td>IP_MASK</td>
- <td>Mask applied to destination IP address</td>
- </tr>
-
- <tr>
- <td>srcipfrom</td>
- <td>IP_ADDR</td>
- <td>Start of range of source IP address</td>
- </tr>
- <tr>
- <td>srcipto</td>
- <td>IP_ADDR</td>
- <td>End of range of source IP address</td>
- </tr>
- <tr>
- <td>dstipfrom</td>
- <td>IP_ADDR</td>
- <td>Start of range of destination IP address</td>
- </tr>
- <tr>
- <td>dstipto</td>
- <td>IP_ADDR</td>
- <td>End of range of destination IP address</td>
- </tr>
-
- <tr>
- <td>srcportstart</td>
- <td>UINT16</td>
- <td>Start of range of valid source ports</td>
- </tr>
- <tr>
- <td>srcportend</td>
- <td>UINT16</td>
- <td>End of range of valid source ports</td>
- </tr>
- <tr>
- <td>dstportstart</td>
- <td>UINT16</td>
- <td>Start of range of valid destination ports</td>
- </tr>
- <tr>
- <td>dstportend</td>
- <td>UINT16</td>
- <td>End of range of valid destination ports</td>
- </tr>
- <tr>
- <td>dscp</td>
- <td>UINT8 (0x0-0x3f, 0 - 63)</td>
- <td>Differentiated Services Code Point</td>
- </tr>
- <tr>
- <td>comment <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>text with max. 256 characters</td>
- </tr>
- <tr>
- <td>state <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>comma separated list of NEW,ESTABLISHED,RELATED,INVALID or
NONE</td>
- </tr>
- <tr>
- <td>flags <span class="since">(Since
0.9.1)</span></td>
- <td>STRING</td>
- <td>TCP-only: format of mask/flags with mask and flags each being a comma
separated list of SYN,ACK,URG,PSH,FIN,RST or NONE or ALL</td>
- </tr>
- <tr>
- <td>ipset <span class="since">(Since
0.9.13)</span></td>
- <td>STRING</td>
- <td>The name of an IPSet managed outside of libvirt</td>
- </tr>
- <tr>
- <td>ipsetflags <span class="since">(Since
0.9.13)</span></td>
- <td>IPSETFLAGS</td>
- <td>flags for the IPSet; requires ipset attribute</td>
- </tr>
- </table>
- <p>
- <br/><br/>
- </p>
-
-
- <h5><a id="nwfelemsRulesProtoICMP">ICMP</a></h5>
- <p>
- Protocol ID: <code>icmp</code>
- <br/>
- Note: The chain parameter is ignored for this type of traffic
- and should either be omitted or set to <code>root</code>.
- </p>
- <table class="top_table">
- <tr>
- <th> Attribute </th>
- <th> Datatype </th>
- <th> Semantics </th>
- </tr>
- <tr>
- <td>srcmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of sender</td>
- </tr>
- <tr>
- <td>srcmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of sender</td>
- </tr>
- <tr>
- <td>dstmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of destination</td>
- </tr>
- <tr>
- <td>dstmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of destination</td>
- </tr>
- <tr>
- <td>srcipaddr</td>
- <td>IP_ADDR</td>
- <td>Source IP address</td>
- </tr>
- <tr>
- <td>srcipmask</td>
- <td>IP_MASK</td>
- <td>Mask applied to source IP address</td>
- </tr>
- <tr>
- <td>dstipaddr</td>
- <td>IP_ADDR</td>
- <td>Destination IP address</td>
- </tr>
- <tr>
- <td>dstipmask</td>
- <td>IP_MASK</td>
- <td>Mask applied to destination IP address</td>
- </tr>
-
- <tr>
- <td>srcipfrom</td>
- <td>IP_ADDR</td>
- <td>Start of range of source IP address</td>
- </tr>
- <tr>
- <td>srcipto</td>
- <td>IP_ADDR</td>
- <td>End of range of source IP address</td>
- </tr>
- <tr>
- <td>dstipfrom</td>
- <td>IP_ADDR</td>
- <td>Start of range of destination IP address</td>
- </tr>
- <tr>
- <td>dstipto</td>
- <td>IP_ADDR</td>
- <td>End of range of destination IP address</td>
- </tr>
- <tr>
- <td>type</td>
- <td>UINT16</td>
- <td>ICMP type</td>
- </tr>
- <tr>
- <td>code</td>
- <td>UINT16</td>
- <td>ICMP code</td>
- </tr>
- <tr>
- <td>dscp</td>
- <td>UINT8 (0x0-0x3f, 0 - 63)</td>
- <td>Differentiated Services Code Point</td>
- </tr>
- <tr>
- <td>comment <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>text with max. 256 characters</td>
- </tr>
- <tr>
- <td>state <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>comma separated list of NEW,ESTABLISHED,RELATED,INVALID or
NONE</td>
- </tr>
- <tr>
- <td>ipset <span class="since">(Since
0.9.13)</span></td>
- <td>STRING</td>
- <td>The name of an IPSet managed outside of libvirt</td>
- </tr>
- <tr>
- <td>ipsetflags <span class="since">(Since
0.9.13)</span></td>
- <td>IPSETFLAGS</td>
- <td>flags for the IPSet; requires ipset attribute</td>
- </tr>
- </table>
- <p>
- <br/><br/>
- </p>
-
- <h5><a id="nwfelemsRulesProtoMisc">IGMP, ESP, AH, UDPLITE,
'ALL'</a></h5>
- <p>
- Protocol ID: <code>igmp</code>, <code>esp</code>,
<code>ah</code>, <code>udplite</code>,
<code>all</code>
- <br/>
- Note: The chain parameter is ignored for this type of traffic
- and should either be omitted or set to <code>root</code>.
- </p>
- <table class="top_table">
- <tr>
- <th> Attribute </th>
- <th> Datatype </th>
- <th> Semantics </th>
- </tr>
- <tr>
- <td>srcmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of sender</td>
- </tr>
- <tr>
- <td>srcmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of sender</td>
- </tr>
- <tr>
- <td>dstmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of destination</td>
- </tr>
- <tr>
- <td>dstmacmask</td>
- <td>MAC_MASK</td>
- <td>Mask applied to MAC address of destination</td>
- </tr>
- <tr>
- <td>srcipaddr</td>
- <td>IP_ADDR</td>
- <td>Source IP address</td>
- </tr>
- <tr>
- <td>srcipmask</td>
- <td>IP_MASK</td>
- <td>Mask applied to source IP address</td>
- </tr>
- <tr>
- <td>dstipaddr</td>
- <td>IP_ADDR</td>
- <td>Destination IP address</td>
- </tr>
- <tr>
- <td>dstipmask</td>
- <td>IP_MASK</td>
- <td>Mask applied to destination IP address</td>
- </tr>
-
- <tr>
- <td>srcipfrom</td>
- <td>IP_ADDR</td>
- <td>Start of range of source IP address</td>
- </tr>
- <tr>
- <td>srcipto</td>
- <td>IP_ADDR</td>
- <td>End of range of source IP address</td>
- </tr>
- <tr>
- <td>dstipfrom</td>
- <td>IP_ADDR</td>
- <td>Start of range of destination IP address</td>
- </tr>
- <tr>
- <td>dstipto</td>
- <td>IP_ADDR</td>
- <td>End of range of destination IP address</td>
- </tr>
- <tr>
- <td>dscp</td>
- <td>UINT8 (0x0-0x3f, 0 - 63)</td>
- <td>Differentiated Services Code Point</td>
- </tr>
- <tr>
- <td>comment <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>text with max. 256 characters</td>
- </tr>
- <tr>
- <td>state <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>comma separated list of NEW,ESTABLISHED,RELATED,INVALID or
NONE</td>
- </tr>
- <tr>
- <td>ipset <span class="since">(Since
0.9.13)</span></td>
- <td>STRING</td>
- <td>The name of an IPSet managed outside of libvirt</td>
- </tr>
- <tr>
- <td>ipsetflags <span class="since">(Since
0.9.13)</span></td>
- <td>IPSETFLAGS</td>
- <td>flags for the IPSet; requires ipset attribute</td>
- </tr>
- </table>
- <p>
- <br/><br/>
- </p>
-
-
- <h5><a id="nwfelemsRulesProtoTCP-ipv6">TCP/UDP/SCTP over
IPV6</a></h5>
- <p>
- Protocol ID: <code>tcp-ipv6</code>, <code>udp-ipv6</code>,
<code>sctp-ipv6</code>
- <br/>
- Note: The chain parameter is ignored for this type of traffic
- and should either be omitted or set to <code>root</code>.
- </p>
- <table class="top_table">
- <tr>
- <th> Attribute </th>
- <th> Datatype </th>
- <th> Semantics </th>
- </tr>
- <tr>
- <td>srcmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of sender</td>
- </tr>
- <tr>
- <td>srcipaddr</td>
- <td>IPV6_ADDR</td>
- <td>Source IP address</td>
- </tr>
- <tr>
- <td>srcipmask</td>
- <td>IPV6_MASK</td>
- <td>Mask applied to source IP address</td>
- </tr>
- <tr>
- <td>dstipaddr</td>
- <td>IPV6_ADDR</td>
- <td>Destination IP address</td>
- </tr>
- <tr>
- <td>dstipmask</td>
- <td>IPV6_MASK</td>
- <td>Mask applied to destination IP address</td>
- </tr>
-
- <tr>
- <td>srcipfrom</td>
- <td>IPV6_ADDR</td>
- <td>Start of range of source IP address</td>
- </tr>
- <tr>
- <td>srcipto</td>
- <td>IPV6_ADDR</td>
- <td>End of range of source IP address</td>
- </tr>
- <tr>
- <td>dstipfrom</td>
- <td>IPV6_ADDR</td>
- <td>Start of range of destination IP address</td>
- </tr>
- <tr>
- <td>dstipto</td>
- <td>IPV6_ADDR</td>
- <td>End of range of destination IP address</td>
- </tr>
-
- <tr>
- <td>srcportstart</td>
- <td>UINT16</td>
- <td>Start of range of valid source ports</td>
- </tr>
- <tr>
- <td>srcportend</td>
- <td>UINT16</td>
- <td>End of range of valid source ports</td>
- </tr>
- <tr>
- <td>dstportstart</td>
- <td>UINT16</td>
- <td>Start of range of valid destination ports</td>
- </tr>
- <tr>
- <td>dstportend</td>
- <td>UINT16</td>
- <td>End of range of valid destination ports</td>
- </tr>
- <tr>
- <td>dscp</td>
- <td>UINT8 (0x0-0x3f, 0 - 63)</td>
- <td>Differentiated Services Code Point</td>
- </tr>
- <tr>
- <td>comment <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>text with max. 256 characters</td>
- </tr>
- <tr>
- <td>state <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>comma separated list of NEW,ESTABLISHED,RELATED,INVALID or
NONE</td>
- </tr>
- <tr>
- <td>flags <span class="since">(Since
0.9.1)</span></td>
- <td>STRING</td>
- <td>TCP-only: format of mask/flags with mask and flags each being a comma
separated list of SYN,ACK,URG,PSH,FIN,RST or NONE or ALL</td>
- </tr>
- <tr>
- <td>ipset <span class="since">(Since
0.9.13)</span></td>
- <td>STRING</td>
- <td>The name of an IPSet managed outside of libvirt</td>
- </tr>
- <tr>
- <td>ipsetflags <span class="since">(Since
0.9.13)</span></td>
- <td>IPSETFLAGS</td>
- <td>flags for the IPSet; requires ipset attribute</td>
- </tr>
- </table>
- <p>
- <br/><br/>
- </p>
-
-
- <h5><a
id="nwfelemsRulesProtoICMPv6">ICMPv6</a></h5>
- <p>
- Protocol ID: <code>icmpv6</code>
- <br/>
- Note: The chain parameter is ignored for this type of traffic
- and should either be omitted or set to <code>root</code>.
- </p>
- <table class="top_table">
- <tr>
- <th> Attribute </th>
- <th> Datatype </th>
- <th> Semantics </th>
- </tr>
- <tr>
- <td>srcmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of sender</td>
- </tr>
- <tr>
- <td>srcipaddr</td>
- <td>IPV6_ADDR</td>
- <td>Source IPv6 address</td>
- </tr>
- <tr>
- <td>srcipmask</td>
- <td>IPV6_MASK</td>
- <td>Mask applied to source IPv6 address</td>
- </tr>
- <tr>
- <td>dstipaddr</td>
- <td>IPV6_ADDR</td>
- <td>Destination IPv6 address</td>
- </tr>
- <tr>
- <td>dstipmask</td>
- <td>IPV6_MASK</td>
- <td>Mask applied to destination IPv6 address</td>
- </tr>
-
- <tr>
- <td>srcipfrom</td>
- <td>IPV6_ADDR</td>
- <td>Start of range of source IP address</td>
- </tr>
- <tr>
- <td>srcipto</td>
- <td>IPV6_ADDR</td>
- <td>End of range of source IP address</td>
- </tr>
- <tr>
- <td>dstipfrom</td>
- <td>IPV6_ADDR</td>
- <td>Start of range of destination IP address</td>
- </tr>
- <tr>
- <td>dstipto</td>
- <td>IPV6_ADDR</td>
- <td>End of range of destination IP address</td>
- </tr>
-
- <tr>
- <td>type</td>
- <td>UINT16</td>
- <td>ICMPv6 type</td>
- </tr>
- <tr>
- <td>code</td>
- <td>UINT16</td>
- <td>ICMPv6 code</td>
- </tr>
- <tr>
- <td>dscp</td>
- <td>UINT8 (0x0-0x3f, 0 - 63)</td>
- <td>Differentiated Services Code Point</td>
- </tr>
- <tr>
- <td>comment <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>text with max. 256 characters</td>
- </tr>
- <tr>
- <td>state <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>comma separated list of NEW,ESTABLISHED,RELATED,INVALID or
NONE</td>
- </tr>
- <tr>
- <td>ipset <span class="since">(Since
0.9.13)</span></td>
- <td>STRING</td>
- <td>The name of an IPSet managed outside of libvirt</td>
- </tr>
- <tr>
- <td>ipsetflags <span class="since">(Since
0.9.13)</span></td>
- <td>IPSETFLAGS</td>
- <td>flags for the IPSet; requires ipset attribute</td>
- </tr>
- </table>
- <p>
- <br/><br/>
- </p>
-
- <h5><a id="nwfelemsRulesProtoMiscv6">ESP, AH, UDPLITE,
'ALL' over IPv6</a></h5>
- <p>
- Protocol ID: <code>esp-ipv6</code>, <code>ah-ipv6</code>,
<code>udplite-ipv6</code>, <code>all-ipv6</code>
- <br/>
- Note: The chain parameter is ignored for this type of traffic
- and should either be omitted or set to <code>root</code>.
- </p>
- <table class="top_table">
- <tr>
- <th> Attribute </th>
- <th> Datatype </th>
- <th> Semantics </th>
- </tr>
- <tr>
- <td>srcmacaddr</td>
- <td>MAC_ADDR</td>
- <td>MAC address of sender</td>
- </tr>
- <tr>
- <td>srcipaddr</td>
- <td>IPV6_ADDR</td>
- <td>Source IPv6 address</td>
- </tr>
- <tr>
- <td>srcipmask</td>
- <td>IPV6_MASK</td>
- <td>Mask applied to source IPv6 address</td>
- </tr>
- <tr>
- <td>dstipaddr</td>
- <td>IPV6_ADDR</td>
- <td>Destination IPv6 address</td>
- </tr>
- <tr>
- <td>dstipmask</td>
- <td>IPV6_MASK</td>
- <td>Mask applied to destination IPv6 address</td>
- </tr>
-
- <tr>
- <td>srcipfrom</td>
- <td>IPV6_ADDR</td>
- <td>Start of range of source IP address</td>
- </tr>
- <tr>
- <td>srcipto</td>
- <td>IPV6_ADDR</td>
- <td>End of range of source IP address</td>
- </tr>
- <tr>
- <td>dstipfrom</td>
- <td>IPV6_ADDR</td>
- <td>Start of range of destination IP address</td>
- </tr>
- <tr>
- <td>dstipto</td>
- <td>IPV6_ADDR</td>
- <td>End of range of destination IP address</td>
- </tr>
- <tr>
- <td>dscp</td>
- <td>UINT8 (0x0-0x3f, 0 - 63)</td>
- <td>Differentiated Services Code Point</td>
- </tr>
- <tr>
- <td>comment <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>text with max. 256 characters</td>
- </tr>
- <tr>
- <td>state <span class="since">(Since
0.8.5)</span></td>
- <td>STRING</td>
- <td>comma separated list of NEW,ESTABLISHED,RELATED,INVALID or
NONE</td>
- </tr>
- <tr>
- <td>ipset <span class="since">(Since
0.9.13)</span></td>
- <td>STRING</td>
- <td>The name of an IPSet managed outside of libvirt</td>
- </tr>
- <tr>
- <td>ipsetflags <span class="since">(Since
0.9.13)</span></td>
- <td>IPSETFLAGS</td>
- <td>flags for the IPSet; requires ipset attribute</td>
- </tr>
- </table>
- <p>
- <br/><br/>
- </p>
-
- <h3><a id="nwfelemsRulesAdv">Advanced Filter Configuration
Topics</a></h3>
- <p>
- The following sections discuss advanced filter configuration
- topics.
- </p>
-
- <h4><a id="nwfelemsRulesAdvTracking">Connection
tracking</a></h4>
- <p>
- The network filtering subsystem (on Linux) makes use of the connection
- tracking support of iptables. This helps in enforcing the
- directionality of network traffic (state match) as well as
- counting and limiting the number of simultaneous connections towards
- a VM. As an example, if a VM has TCP port 8080
- open as a server, clients may connect to the VM on port 8080.
- Connection tracking and enforcement of directionality then prevents
- the VM from initiating a connection from
- (TCP client) port 8080 to the host back to a remote host.
- More importantly, tracking helps to prevent
- remote attackers from establishing a connection back to a VM. For example,
- if the user inside the VM established a connection to
- port 80 on an attacker site, then the attacker will not be able to
- initiate a connection from TCP port 80 back towards the VM.
- By default the connection state match that enables connection tracking
- and then enforcement of directionality of traffic is turned on. <br/>
- The following shows an example XML fragment where this feature has been
- turned off for incoming connections to TCP port 12345.
- </p>
-<pre>
-[...]
-<rule direction='in' action='accept'
statematch='false'>
- <tcp dstportstart='12345'/>
-</rule>
-[...]
-</pre>
- <p>
- This now allows incoming traffic to TCP port 12345, but would also
- enable the initiation from (client) TCP port 12345 within the VM,
- which may or may not be desirable.
- </p>
-
- <h4><a id="nwfelemsRulesAdvLimiting">Limiting Number of
Connections</a></h4>
- <p>
- To limit the number of connections a VM may establish, a rule must
- be provided that sets a limit of connections for a given
- type of traffic. If for example a VM
- is supposed to be allowed to only ping one other IP address at a time
- and is supposed to have only one active incoming ssh connection at a
- time, the following XML fragment can be used to achieve this.
- </p>
-<pre>
-[...]
-<rule action='drop' direction='in' priority='400'>
- <tcp connlimit-above='1'/>
-</rule>
-<rule action='accept' direction='in'
priority='500'>
- <tcp dstportstart='22'/>
-</rule>
-<rule action='drop' direction='out'
priority='400'>
- <icmp connlimit-above='1'/>
-</rule>
-<rule action='accept' direction='out'
priority='500'>
- <icmp/>
-</rule>
-<rule action='accept' direction='out'
priority='500'>
- <udp dstportstart='53'/>
-</rule>
-<rule action='drop' direction='inout'
priority='1000'>
- <all/>
-</rule>
-[...]
-</pre>
- <p>
- Note that the rule for the limit has to logically appear
- before the rule for accepting the traffic.<br/>
- An additional rule for letting DNS traffic to port 22
- go out the VM has been added to avoid ssh sessions not
- getting established for reasons related to DNS lookup failures
- by the ssh daemon. Leaving this rule out may otherwise lead to
- fun-filled debugging joy (symptom: ssh client seems to hang
- while trying to connect).
- <br/><br/>
- Lot of care must be taken with timeouts related
- to tracking of traffic. An ICMP ping that
- the user may have terminated inside the VM may have a long
- timeout in the host's connection tracking system and therefore
- not allow another ICMP ping to go through for a while. Therefore,
- the timeouts have to be tuned in the host's sysfs, i.e.,
- </p>
-
-<pre>
-echo 3 > /proc/sys/net/netfilter/nf_conntrack_icmp_timeout
-</pre>
- <p>
- sets the ICMP connection tracking timeout to 3 seconds. The
- effect of this is that once one ping is terminated, another
- one can start after 3 seconds.<br/>
- Further, we want to point out that a client that for whatever
- reason has not properly closed a TCP connection may cause a
- connection to be held open for a longer period of time,
- depending to what timeout the <code>TCP established</code> state
- timeout has been set to on the host. Also, idle connections may time
- out in the connection tracking system but can be reactivated once
- packets are exchanged. However, a newly initiated connection may force
- an idle connection into TCP backoff if the number of allowed connections
- is set to a too low limit, the new connection is established
- and hits (not exceeds) the limit of allowed connections and for
- example a key is pressed on the old ssh session, which now has become
- unresponsive due to its traffic being dropped.
- Therefore, the limit of connections should be rather high so that
- fluctuations in new TCP connections don't cause odd
- traffic behavior in relation to idle connections.
- </p>
-
- <h2><a id="nwfcli">Command line tools</a></h2>
- <p>
- The libvirt command line tool <code>virsh</code> has been extended
- with life-cycle support for network filters. All commands related
- to the network filtering subsystem start with the prefix
- <code>nwfilter</code>. The following commands are available:
- </p>
- <ul>
- <li>nwfilter-list : list UUIDs and names of all network filters</li>
- <li>nwfilter-define : define a new network filter or update an existing
one</li>
- <li>nwfilter-undefine : delete a network filter given its name; it must not be
currently in use</li>
- <li>nwfilter-dumpxml : display a network filter given its name</li>
- <li>nwfilter-edit : edit a network filter given its name</li>
- </ul>
-
- <h2><a id="nwfexamples">Pre-existing network
filters</a></h2>
- <p>
- The following is a list of example network filters that are
- automatically installed with libvirt.</p>
- <table class="top_table">
- <tr>
- <th> Name </th>
- <th> Description </th>
- </tr>
- <tr>
- <td> no-arp-spoofing </td>
- <td> Prevent a VM from spoofing ARP traffic; this filter
- only allows ARP request and reply messages and enforces
- that those packets contain the MAC and IP addresses
- of the VM.</td>
- </tr>
- <tr>
- <td> allow-arp </td>
- <td> Allow ARP traffic in both directions</td>
- </tr>
- <tr>
- <td> allow-ipv4 </td>
- <td> Allow IPv4 traffic in both directions</td>
- </tr>
- <tr>
- <td> allow-ipv6 </td>
- <td> Allow IPv6 traffic in both directions</td>
- </tr>
- <tr>
- <td> allow-incoming-ipv4 </td>
- <td> Allow incoming IPv4 traffic</td>
- </tr>
- <tr>
- <td> allow-incoming-ipv6 </td>
- <td> Allow incoming IPv6 traffic</td>
- </tr>
- <tr>
- <td> allow-dhcp </td>
- <td> Allow a VM to request an IP address via DHCP (from any
- DHCP server)</td>
- </tr>
- <tr>
- <td> allow-dhcpv6 </td>
- <td> Similar to allow-dhcp, but for DHCPv6 </td>
- </tr>
- <tr>
- <td> allow-dhcp-server </td>
- <td> Allow a VM to request an IP address from a specified
- DHCP server. The dotted decimal IP address of the DHCP
- server must be provided in a reference to this filter.
- The name of the variable must be <i>DHCPSERVER</i>.</td>
- </tr>
- <tr>
- <td> allow-dhcpv6-server </td>
- <td> Similar to allow-dhcp-server, but for DHCPv6 </td>
- </tr>
- <tr>
- <td> no-ip-spoofing </td>
- <td> Prevent a VM from sending of IPv4 packets with
- a source IP address different from the one
- in the packet. </td>
- </tr>
- <tr>
- <td> no-ipv6-spoofing </td>
- <td> Similar to no-ip-spoofing, but for IPv6 </td>
- </tr>
- <tr>
- <td> no-ip-multicast </td>
- <td> Prevent a VM from sending IP multicast packets. </td>
- </tr>
- <tr>
- <td> no-ipv6-multicast </td>
- <td> Similar to no-ip-multicast, but for IPv6 </td>
- </tr>
- <tr>
- <td> clean-traffic </td>
- <td> Prevent MAC, IP and ARP spoofing. This filter references
- several other filters as building blocks. </td>
- </tr>
- </table>
- <p>
- Note that most of the above filters are only building blocks and
- require a combination with other filters to provide useful network
- traffic filtering.
- The most useful one in the above list is the <i>clean-traffic</i>
- filter. This filter itself can for example be combined with the
- <i>no-ip-multicast</i>
- filter to prevent virtual machines from sending IP multicast traffic
- on top of the prevention of packet spoofing.
- </p>
-
- <h2><a id="nwfwrite">Writing your own
filters</a></h2>
-
- <p>
- Since libvirt only provides a couple of example networking filters, you
- may consider writing your own. When planning on doing so
- there are a couple of things
- you may need to know regarding the network filtering subsystem and how
- it works internally. Certainly you also have to know and understand
- the protocols very well that you want to be filtering on so that
- no further traffic than what you want can pass and that in fact the
- traffic you want to allow does pass.
- <br/><br/>
- The network filtering subsystem is currently only available on
- Linux hosts and only works for QEMU and KVM type of virtual machines.
- On Linux
- it builds upon the support for <code>ebtables</code>,
<code>iptables
- </code> and <code>ip6tables</code> and makes use of their
features.
- From the above list of supported protocols the following ones are
- implemented using <code>ebtables</code>:
- </p>
- <ul>
- <li>mac</li>
- <li>stp (spanning tree protocol)</li>
- <li>vlan (802.1Q)</li>
- <li>arp, rarp</li>
- <li>ipv4</li>
- <li>ipv6</li>
- </ul>
-
- <p>
- All other protocols over IPv4 are supported using iptables, those over
- IPv6 are implemented using ip6tables.
- <br/><br/>
- On a Linux host, all traffic filtering instantiated by libvirt's network
- filter subsystem first passes through the filtering support implemented
- by ebtables and only then through iptables or ip6tables filters. If
- a filter tree has rules with the protocols <code>mac</code>,
- <code>stp</code>, <code>vlan</code>
- <code>arp</code>, <code>rarp</code>,
<code>ipv4</code>,
- or <code>ipv6</code> ebtables rules will automatically be instantiated.
- <br/>
- The role of the <code>chain</code> attribute in the network filter
- XML is that internally a new user-defined ebtables table is created
- that then for example receives all <code>arp</code> traffic coming
- from or going to a virtual machine if the chain <code>arp</code>
- has been specified. Further, a rule is generated in an interface's
- <code>root</code> chain that directs all ipv4 traffic into the
- user-defined chain. Therefore, all ARP traffic rules should then be
- placed into filters specifying this chain. This type of branching
- into user-defined tables is only supported with filtering on the ebtables
- layer.
- <br/>
- <span class="since">Since 0.9.8</span> multiple chains for the
same
- protocol can be created. For this the name of the chain must have
- a prefix of one of the previously enumerated protocols. To create an
- additional chain for handling of ARP traffic, a chain with name
- <code>arp-test</code> can be specified.
- <br/>
- As an example, it is
- possible to filter on UDP traffic by source and destination ports using
- the <code>ip</code> protocol filter and specifying attributes for the
- protocol, source and destination IP addresses and ports of UDP packets
- that are to be accepted. This allows
- early filtering of UDP traffic with ebtables. However, once an IP or IPv6
- packet, such as a UDP packet,
- has passed the ebtables layer and there is at least one rule in a filter
- tree that instantiates iptables or ip6tables rules, a rule to let
- the UDP packet pass will also be necessary to be provided for those
- filtering layers. This can be
- achieved with a rule containing an appropriate <code>udp</code> or
- <code>udp-ipv6</code> traffic filtering node.
- </p>
-
- <h3><a id="nwfwriteexample">Example custom
filter</a></h3>
- <p>
- As an example we want to now build a filter that fulfills the following
- list of requirements:
- </p>
- <ul>
- <li>prevents a VM's interface from MAC, IP and ARP spoofing</li>
- <li>opens only TCP ports 22 and 80 of a VM's interface</li>
- <li>allows the VM to send ping traffic from an interface
- but not let the VM be pinged on the interface</li>
- <li>allows the VM to do DNS lookups (UDP towards port 53)</li>
- </ul>
- <p>
- The requirement to prevent spoofing is fulfilled by the existing
- <code>clean-traffic</code> network filter, thus we will reference this
- filter from our custom filter.
- <br/>
- To enable traffic for TCP ports 22 and 80 we will add 2 rules to
- enable this type of traffic. To allow the VM to send ping traffic
- we will add a rule for ICMP traffic. For simplicity reasons
- we allow general ICMP traffic to be initiated from the VM, not
- just ICMP echo request and response messages. To then
- disallow all other traffic to reach or be initiated by the
- VM we will then need to add a rule that drops all other traffic.
- Assuming our VM is called <i>test</i> and
- the interface we want to associate our filter with is called
<i>eth0</i>,
- we name our filter <i>test-eth0</i>.
- The result of these considerations is the following network filter XML:
- </p>
-<pre>
-<filter name='test-eth0'>
- <!-- reference the clean traffic filter to prevent
- MAC, IP and ARP spoofing. By not providing
- and IP address parameter, libvirt will detect the
- IP address the VM is using. -->
- <filterref filter='clean-traffic'/>
-
- <!-- enable TCP ports 22 (ssh) and 80 (http) to be reachable -->
- <rule action='accept' direction='in'>
- <tcp dstportstart='22'/>
- </rule>
-
- <rule action='accept' direction='in'>
- <tcp dstportstart='80'/>
- </rule>
-
- <!-- enable general ICMP traffic to be initiated by the VM;
- this includes ping traffic -->
- <rule action='accept' direction='out'>
- <icmp/>
- </rule>
-
- <!-- enable outgoing DNS lookups using UDP -->
- <rule action='accept' direction='out'>
- <udp dstportstart='53'/>
- </rule>
-
- <!-- drop all other traffic -->
- <rule action='drop' direction='inout'>
- <all/>
- </rule>
-
-</filter>
-</pre>
- <p>
- Note that none of the rules in the above XML contain the
- IP address of the VM as either source or destination address, yet
- the filtering of the traffic works correctly. The reason is that
- the evaluation of the rules internally happens on a
- per-interface basis and the rules are evaluated based on the knowledge
- about which (tap) interface has sent or will receive the packet rather
- than what their source or destination IP address may be.
- <br/><br/>
- An XML fragment for a possible network interface description inside
- the domain XML of the <code>test</code> VM could then look like this:
- </p>
-<pre>
-[...]
-<interface type='bridge'>
- <source bridge='mybridge'/>
- <filterref filter='test-eth0'/>
-</interface>
-[...]
-</pre>
-
- <p>
- To more strictly control the ICMP traffic and enforce that only
- ICMP echo requests can be sent from the VM
- and only ICMP echo responses be received by the VM, the above
- <code>ICMP</code> rule can be replaced with the following two rules:
- </p>
-<pre>
-<!-- enable outgoing ICMP echo requests-->
-<rule action='accept' direction='out'>
- <icmp type='8'/>
-</rule>
-
-<!-- enable incoming ICMP echo replies-->
-<rule action='accept' direction='in'>
- <icmp type='0'/>
-</rule>
-</pre>
-
- <h3><a id="nwfwriteexample2nd">Second example custom
filter</a></h3>
- <p>
- In this example we now want to build a similar filter as in the
- example above, but extend the list of requirements with an
- ftp server located inside the VM. Further, we will be using features
- that have been added in <span class="since">version
0.8.5</span>.
- The requirements for this filter are:
- </p>
- <ul>
- <li>prevents a VM's interface from MAC, IP and ARP spoofing</li>
- <li>opens only TCP ports 22 and 80 of a VM's interface</li>
- <li>allows the VM to send ping traffic from an interface
- but not let the VM be pinged on the interface</li>
- <li>allows the VM to do DNS lookups (UDP towards port 53)</li>
- <li>enable an ftp server (in active mode) to be run inside the VM</li>
- </ul>
- <p>
- The additional requirement of allowing an ftp server to be run inside
- the VM maps into the requirement of allowing port 21 to be reachable
- for ftp control traffic as well as enabling the VM to establish an
- outgoing tcp connection originating from the VM's TCP port 20 back to
- the ftp client (ftp active mode). There are several ways of how this
- filter can be written and we present 2 solutions.
- <br/><br/>
- The 1st solution makes use of the <code>state</code> attribute of
- the TCP protocol that gives us a hook into the connection tracking
- framework of the Linux host. For the VM-initiated ftp data connection
- (ftp active mode) we use the <code>RELATED</code> state that allows
- us to detect that the VM-initiated ftp data connection is a consequence of
- ( or 'has a relationship with' ) an existing ftp control connection,
- thus we want to allow it to let packets
- pass the firewall. The <code>RELATED</code> state, however, is only
- valid for the very first packet of the outgoing TCP connection for the
- ftp data path. Afterwards, the state to compare against is
- <code>ESTABLISHED</code>, which then applies equally
- to the incoming and outgoing direction. All this is related to the ftp
- data traffic originating from TCP port 20 of the VM. This then leads to
- the following solution
- <span class="since">(since 0.8.5 (QEMU, KVM))</span>:
- </p>
-<pre>
-<filter name='test-eth0'>
- <!-- reference the clean traffic filter to prevent
- MAC, IP and ARP spoofing. By not providing
- and IP address parameter, libvirt will detect the
- IP address the VM is using. -->
- <filterref filter='clean-traffic'/>
-
- <!-- enable TCP port 21 (ftp-control) to be reachable -->
- <rule action='accept' direction='in'>
- <tcp dstportstart='21'/>
- </rule>
-
- <!-- enable TCP port 20 for VM-initiated ftp data connection
- related to an existing ftp control connection -->
- <rule action='accept' direction='out'>
- <tcp srcportstart='20' state='RELATED,ESTABLISHED'/>
- </rule>
-
- <!-- accept all packets from client on the ftp data connection -->
- <rule action='accept' direction='in'>
- <tcp dstportstart='20' state='ESTABLISHED'/>
- </rule>
-
- <!-- enable TCP ports 22 (ssh) and 80 (http) to be reachable -->
- <rule action='accept' direction='in'>
- <tcp dstportstart='22'/>
- </rule>
-
- <rule action='accept' direction='in'>
- <tcp dstportstart='80'/>
- </rule>
-
- <!-- enable general ICMP traffic to be initiated by the VM;
- this includes ping traffic -->
- <rule action='accept' direction='out'>
- <icmp/>
- </rule>
-
- <!-- enable outgoing DNS lookups using UDP -->
- <rule action='accept' direction='out'>
- <udp dstportstart='53'/>
- </rule>
-
- <!-- drop all other traffic -->
- <rule action='drop' direction='inout'>
- <all/>
- </rule>
-
-</filter>
-</pre>
- <p>
- Before trying out a filter using the <code>RELATED</code> state,
- you have to make sure that the appropriate connection tracking module
- has been loaded into the host's kernel. Depending on the version of the
- kernel, you must run either one of the following two commands before
- the ftp connection with the VM is established.
- </p>
-<pre>
-modprobe nf_conntrack_ftp # where available or
-
-modprobe ip_conntrack_ftp # if above is not available
-</pre>
- <p>
- If other protocols than ftp are to be used in conjunction with the
- <code>RELATED</code> state, their corresponding module must be loaded.
- Modules exist at least for the protocols ftp, tftp, irc, sip,
- sctp, and amanda.
- </p>
- <p>
- The 2nd solution makes uses the state flags of connections more
- than the previous solution did.
- In this solution we take advantage of the fact that the
- <code>NEW</code> state of a connection is valid when the very
- first packet of a traffic flow is seen. Subsequently, if the very first
- packet of a flow is accepted, the flow becomes a connection and enters
- the <code>ESTABLISHED</code> state. This allows us to write a general
- rule for allowing packets of <code>ESTABLISHED</code> connections to
- reach the VM or be sent by the VM.
- We write specific rules for the very first packets identified by the
- <code>NEW</code> state and for which ports they are acceptable. All
- packets for ports that are not explicitly accepted will be dropped and
- therefore the connection will not go into the <code>ESTABLISHED</code>
- state and any subsequent packets be dropped.
- </p>
-
-<pre>
-<filter name='test-eth0'>
- <!-- reference the clean traffic filter to prevent
- MAC, IP and ARP spoofing. By not providing
- and IP address parameter, libvirt will detect the
- IP address the VM is using. -->
- <filterref filter='clean-traffic'/>
-
- <!-- let the packets of all previously accepted connections reach the VM
-->
- <rule action='accept' direction='in'>
- <all state='ESTABLISHED'/>
- </rule>
-
- <!-- let the packets of all previously accepted and related connections be sent
from the VM -->
- <rule action='accept' direction='out'>
- <all state='ESTABLISHED,RELATED'/>
- </rule>
-
- <!-- enable traffic towards port 21 (ftp), 22 (ssh) and 80 (http) -->
- <rule action='accept' direction='in'>
- <tcp dstportstart='21' dstportend='22'
state='NEW'/>
- </rule>
-
- <rule action='accept' direction='in'>
- <tcp dstportstart='80' state='NEW'/>
- </rule>
-
- <!-- enable general ICMP traffic to be initiated by the VM;
- this includes ping traffic -->
- <rule action='accept' direction='out'>
- <icmp state='NEW'/>
- </rule>
-
- <!-- enable outgoing DNS lookups using UDP -->
- <rule action='accept' direction='out'>
- <udp dstportstart='53' state='NEW'/>
- </rule>
-
- <!-- drop all other traffic -->
- <rule action='drop' direction='inout'>
- <all/>
- </rule>
-
-</filter>
-
-</pre>
-
- <h2><a id="nwflimits">Limitations</a></h2>
- <p>
- The following sections list (current) limitations of the network
- filtering subsystem.
- </p>
-
- <h3><a id="nwflimitsmigr">VM Migration</a></h3>
- <p>
- VM migration is only supported if the whole filter tree
- that is referenced by a virtual machine's top level filter
- is also available on the target host. The network filter
- <i>clean-traffic</i>
- for example should be available on all libvirt installations
- of version 0.8.1 or later and thus enable migration of VMs that
- for example reference this filter. All other
- custom filters must be migrated using higher layer software. It is
- outside the scope of libvirt to ensure that referenced filters
- on the source system are equivalent to those on the target system
- and vice versa.
- <br/><br/>
- Migration must occur between libvirt installations of version
- 0.8.1 or later in order not to lose the network traffic filters
- associated with an interface.
- </p>
- <h3><a id="nwflimitsvlan">VLAN filtering on
Linux</a></h3>
- <p>
- VLAN (802.1Q) packets, if sent by a virtual machine, cannot be filtered
- with rules for protocol IDs <code>arp</code>,
<code>rarp</code>,
- <code>ipv4</code> and <code>ipv6</code> but only
- with protocol IDs <code>mac</code> and <code>vlan</code>.
Therefore,
- the example filter <code>clean-traffic</code> will not work as
expected.
- </p>
- </body>
-</html>
diff --git a/docs/formatnwfilter.rst b/docs/formatnwfilter.rst
new file mode 100644
index 0000000000..434da5b1fd
--- /dev/null
+++ b/docs/formatnwfilter.rst
@@ -0,0 +1,1789 @@
+.. role:: since
+
+===============
+Network Filters
+===============
+
+.. contents::
+
+This page provides an introduction to libvirt's network filters, their goals,
+concepts and XML format.
+
+Goals and background
+--------------------
+
+The goal of the network filtering XML is to enable administrators of a
+virtualized system to configure and enforce network traffic filtering rules on
+virtual machines and manage the parameters of network traffic that virtual
+machines are allowed to send or receive. The network traffic filtering rules are
+applied on the host when a virtual machine is started. Since the filtering rules
+cannot be circumvented from within the virtual machine, it makes them mandatory
+from the point of view of a virtual machine user.
+
+The network filter subsystem allows each virtual machine's network traffic
+filtering rules to be configured individually on a per interface basis. The
+rules are applied on the host when the virtual machine is started and can be
+modified while the virtual machine is running. The latter can be achieved by
+modifying the XML description of a network filter.
+
+Multiple virtual machines can make use of the same generic network filter. When
+such a filter is modified, the network traffic filtering rules of all running
+virtual machines that reference this filter are updated.
+
+Network filtering support is available :since:`since 0.8.1 (QEMU, KVM)`
+
+Concepts
+--------
+
+The network traffic filtering subsystem enables configuration of network traffic
+filtering rules on individual network interfaces that are configured for certain
+types of network configurations. Supported network types are
+
+- ``network``
+
+- ``ethernet`` -- must be used in bridging mode
+
+- ``bridge``
+
+The interface XML is used to reference a top-level filter. In the following
+example, the interface description references the filter ``clean-traffic``.
+
+::
+
+ ...
+ <devices>
+ <interface type='bridge'>
+ <mac address='00:16:3e:5d:c7:9e'/>
+ <filterref filter='clean-traffic'/>
+ </interface>
+ </devices>
+ ...
+
+Network filters are written in XML and may either contain references to other
+filters, contain rules for traffic filtering, or hold a combination of both. The
+above referenced filter ``clean-traffic`` is a filter that only contains
+references to other filters and no actual filtering rules. Since references to
+other filters can be used, a *tree* of filters can be built. The
+``clean-traffic`` filter can be viewed using the command
+``virsh nwfilter-dumpxml clean-traffic``.
+
+As previously mentioned, a single network filter can be referenced by multiple
+virtual machines. Since interfaces will typically have individual parameters
+associated with their respective traffic filtering rules, the rules described in
+a filter XML can be parameterized with variables. In this case, the variable
+name is used in the filter XML and the name and value are provided at the place
+where the filter is referenced. In the following example, the interface
+description has been extended with the parameter ``IP`` and a dotted IP address
+as value.
+
+::
+
+ ...
+ <devices>
+ <interface type='bridge'>
+ <mac address='00:16:3e:5d:c7:9e'/>
+ <filterref filter='clean-traffic'>
+ <parameter name='IP' value='10.0.0.1'/>
+ </filterref>
+ </interface>
+ </devices>
+ ...
+
+In this particular example, the ``clean-traffic`` network traffic filter will be
+instantiated with the IP address parameter 10.0.0.1 and enforce that the traffic
+from this interface will always be using 10.0.0.1 as the source IP address,
+which is one of the purposes of this particular filter.
+
+Filtering chains
+~~~~~~~~~~~~~~~~
+
+Filtering rules are organized in filter chains. These chains can be thought of
+as having a tree structure with packet filtering rules as entries in individual
+chains (branches).
+
+Packets start their filter evaluation in the ``root`` chain and can then
+continue their evaluation in other chains, return from those chains back into
+the ``root`` chain or be dropped or accepted by a filtering rule in one of the
+traversed chains.
+
+Libvirt's network filtering system automatically creates individual ``root``
+chains for every virtual machine's network interface on which the user chooses
+to activate traffic filtering. The user may write filtering rules that are
+either directly instantiated in the ``root`` chain or may create
+protocol-specific filtering chains for efficient evaluation of protocol-specific
+rules. The following chains exist:
+
+- root
+
+- mac :since:`(since 0.9.8)`
+
+- stp (spanning tree protocol) :since:`(since 0.9.8)`
+
+- vlan (802.1Q) :since:`(since 0.9.8)`
+
+- arp, rarp
+
+- ipv4
+
+- ipv6
+
+:since:`Since 0.9.8` multiple chains evaluating the ``mac``, ``stp``, ``vlan``,
+``arp``, ``rarp``, ``ipv4``, or ``ipv6`` protocol can be created using the
+protocol name only as a prefix in the chain's name. This for examples allows
+chains with names ``arp-xyz`` or ``arp-test`` to be specified and have ARP
+protocol packets evaluated in those chains.
+
+The following filter shows an example of filtering ARP traffic in the ``arp``
+chain.
+
+::
+
+ <filter name='no-arp-spoofing' chain='arp'
priority='-500'>
+ <uuid>f88f1932-debf-4aa1-9fbe-f10d3aa4bc95</uuid>
+ <rule action='drop' direction='out' priority='300'>
+ <mac match='no' srcmacaddr='$MAC'/>
+ </rule>
+ <rule action='drop' direction='out' priority='350'>
+ <arp match='no' arpsrcmacaddr='$MAC'/>
+ </rule>
+ <rule action='drop' direction='out' priority='400'>
+ <arp match='no' arpsrcipaddr='$IP'/>
+ </rule>
+ <rule action='drop' direction='in' priority='450'>
+ <arp opcode='Reply'/>
+ <arp match='no' arpdstmacaddr='$MAC'/>
+ </rule>
+ <rule action='drop' direction='in' priority='500'>
+ <arp match='no' arpdstipaddr='$IP'/>
+ </rule>
+ <rule action='accept' direction='inout'
priority='600'>
+ <arp opcode='Request'/>
+ </rule>
+ <rule action='accept' direction='inout'
priority='650'>
+ <arp opcode='Reply'/>
+ </rule>
+ <rule action='drop' direction='inout'
priority='1000'/>
+ </filter>
+
+The consequence of putting ARP-specific rules in the ``arp`` chain, rather than
+for example in the ``root`` chain, is that packets for any other protocol than
+ARP do not need to be evaluated by ARP protocol-specific rules. This improves
+the efficiency of the traffic filtering. However, one must then pay attention to
+only put filtering rules for the given protocol into the chain since any other
+rules will not be evaluated, i.e., an IPv4 rule will not be evaluated in the ARP
+chain since no IPv4 protocol packets will traverse the ARP chain.
+
+Filtering chain priorities
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+All chains are connected to the ``root`` chain. The order in which those chains
+are accessed is influenced by the priority of the chain. The following table
+shows the chains that can be assigned a priority and their default priorities.
+
+============== ================
+Chain (prefix) Default priority
+============== ================
+stp -810
+mac -800
+vlan -750
+ipv4 -700
+ipv6 -600
+arp -500
+rarp -400
+============== ================
+
+A chain with a lower priority value is accessed before one with a higher value.
+
+:since:`Since 0.9.8` the above listed chains can be assigned custom priorities
+by writing a value in the range [-1000, 1000] into the priority (XML) attribute
+in the filter node. The above example filter shows the default priority of -500
+for ``arp`` chains.
+
+Usage of variables in filters
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Two variables names have so far been reserved for usage by the network traffic
+filtering subsystem: ``MAC`` and ``IP``.
+
+``MAC`` is the MAC address of the network interface. A filtering rule that
+references this variable will automatically be instantiated with the MAC address
+of the interface. This works without the user having to explicitly provide the
+MAC parameter. Even though it is possible to specify the MAC parameter similar
+to the IP parameter above, it is discouraged since libvirt knows what MAC
+address an interface will be using.
+
+The parameter ``IP`` represents the IP address that the operating system inside
+the virtual machine is expected to use on the given interface. The ``IP``
+parameter is special in so far as the libvirt daemon will try to determine the
+IP address (and thus the IP parameter's value) that is being used on an
+interface if the parameter is not explicitly provided but referenced. For
+current limitations on IP address detection, consult the section on
+`Limitations`_ on how to use this feature and what to expect when using it.
+
+The above-shown network filer ``no-arp-spoofing`` is an example of a network
+filter XML referencing the ``MAC`` and ``IP`` variables.
+
+Note that referenced variables are always prefixed with the $ (dollar) sign. The
+format of the value of a variable must be of the type expected by the filter
+attribute in the XML. In the above example, the ``IP`` parameter must hold a
+dotted IP address in decimal numbers format. Failure to provide the correct
+value type will result in the filter not being instantiatable and will prevent a
+virtual machine from starting or the interface from attaching when hotplugging
+is used. The types that are expected for each XML attribute are shown below.
+
+:since:`Since 0.9.8` variables can contain lists of elements, e.g., the variable
+``IP`` can contain multiple IP addresses that are valid on a particular
+interface. The notation for providing multiple elements for the IP variable is:
+
+::
+
+ ...
+ <devices>
+ <interface type='bridge'>
+ <mac address='00:16:3e:5d:c7:9e'/>
+ <filterref filter='clean-traffic'>
+ <parameter name='IP' value='10.0.0.1'/>
+ <parameter name='IP' value='10.0.0.2'/>
+ <parameter name='IP' value='10.0.0.3'/>
+ </filterref>
+ </interface>
+ </devices>
+ ...
+
+This then allows filters to enable multiple IP addresses per interface.
+Therefore, with the list of IP address shown above, the following rule will
+create 3 individual filtering rules, one for each IP address.
+
+::
+
+ ...
+ <rule action='accept' direction='in' priority='500'>
+ <tcp srpipaddr='$IP'/>
+ </rule>
+ ...
+
+:since:`Since 0.9.10` it is possible to access individual elements of a variable
+holding a list of elements. A filtering rule like the following accesses the 2nd
+element of the variable DSTPORTS.
+
+::
+
+ ...
+ <rule action='accept' direction='in' priority='500'>
+ <udp dstportstart='$DSTPORTS[1]'/>
+ </rule>
+ ...
+
+:since:`Since 0.9.10` it is possible to create filtering rules that instantiate
+all combinations of rules from different lists using the notation of
+``$VARIABLE[@<iterator ID>]``. The following rule allows a virtual machine to
+receive traffic on a set of ports, which are specified in DSTPORTS, from the set
+of source IP address specified in SRCIPADDRESSES. The rule generates all
+combinations of elements of the variable DSTPORT with those of SRCIPADDRESSES by
+using two independent iterators to access their elements.
+
+::
+
+ ...
+ <rule action='accept' direction='in' priority='500'>
+ <ip srcipaddr='$SRCIPADDRESSES[@1]'
dstportstart='$DSTPORTS[@2]'/>
+ </rule>
+ ...
+
+In an example we assign concrete values to SRCIPADDRESSES and DSTPORTS
+
+::
+
+ SRCIPADDRESSES = [ 10.0.0.1, 11.1.2.3 ]
+ DSTPORTS = [ 80, 8080 ]
+
+Accessing the variables using $SRCIPADDRESSES[@1] and $DSTPORTS[@2] would then
+result in all combinations of addresses and ports being created:
+
+::
+
+ 10.0.0.1, 80
+ 10.0.0.1, 8080
+ 11.1.2.3, 80
+ 11.1.2.3, 8080
+
+Accessing the same variables using a single iterator, for example by using the
+notation $SRCIPADDRESSES[@1] and $DSTPORTS[@1], would result in parallel access
+to both lists and result in the following combinations:
+
+::
+
+ 10.0.0.1, 80
+ 11.1.2.3, 8080
+
+Further, the notation of $VARIABLE is short-hand for $VARIABLE[@0]. The former
+notation always assumes the iterator with Id '0'.
+
+Automatic IP address detection
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The detection of IP addresses used on a virtual machine's interface is
+automatically activated if the variable ``IP`` is referenced but no value has
+been assigned to it. :since:`Since 0.9.13` the variable ``CTRL_IP_LEARNING`` can
+be used to specify the IP address learning method to use. Valid values are
+``any``, ``dhcp``, or ``none``.
+
+The value ``any`` means that libvirt may use any packet to determine the address
+in use by a virtual machine, which is the default behavior if the variable
+``CTRL_IP_LEARNING`` is not set. This method will only detect a single IP
+address on an interface. Once a VM's IP address has been detected, its IP
+network traffic will be locked to that address, if for example IP address
+spoofing is prevented by one of its filters. In that case the user of the VM
+will not be able to change the IP address on the interface inside the VM, which
+would be considered IP address spoofing. When a VM is migrated to another host
+or resumed after a suspend operation, the first packet sent by the VM will again
+determine the IP address it can use on a particular interface.
+
+A value of ``dhcp`` specifies that libvirt should only honor DHCP
+server-assigned addresses with valid leases. This method supports the detection
+and usage of multiple IP address per interface. When a VM is resumed after a
+suspend operation, still valid IP address leases are applied to its filters.
+Otherwise the VM is expected to again use DHCP to obtain new IP addresses. The
+migration of a VM to another physical host requires that the VM again runs the
+DHCP protocol.
+
+Use of ``CTRL_IP_LEARNING=dhcp`` (DHCP snooping) provides additional
+anti-spoofing security, especially when combined with a filter allowing only
+trusted DHCP servers to assign addresses. To enable this, set the variable
+``DHCPSERVER`` to the IP address of a valid DHCP server and provide filters that
+use this variable to filter incoming DHCP responses.
+
+When DHCP snooping is enabled and the DHCP lease expires, the VM will no longer
+be able to use the IP address until it acquires a new, valid lease from a DHCP
+server. If the VM is migrated, it must get a new valid DHCP lease to use an IP
+address (e.g., by bringing the VM interface down and up again).
+
+Note that automatic DHCP detection listens to the DHCP traffic the VM exchanges
+with the DHCP server of the infrastructure. To avoid denial-of-service attacks
+on libvirt, the evaluation of those packets is rate-limited, meaning that a VM
+sending an excessive number of DHCP packets per second on an interface will not
+have all of those packets evaluated and thus filters may not get adapted. Normal
+DHCP client behavior is assumed to send a low number of DHCP packets per second.
+Further, it is important to setup appropriate filters on all VMs in the
+infrastructure to avoid them being able to send DHCP packets. Therefore VMs must
+either be prevented from sending UDP and TCP traffic from port 67 to port 68 or
+the ``DHCPSERVER`` variable should be used on all VMs to restrict DHCP server
+messages to only be allowed to originate from trusted DHCP servers. At the same
+time anti-spoofing prevention must be enabled on all VMs in the subnet.
+
+If ``CTRL_IP_LEARNING`` is set to ``none``, libvirt does not do IP address
+learning and referencing ``IP`` without assigning it an explicit value is an
+error.
+
+The following XML provides an example for the activation of IP address learning
+using the DHCP snooping method:
+
+::
+
+ <interface type='bridge'>
+ <source bridge='virbr0'/>
+ <filterref filter='clean-traffic'>
+ <parameter name='CTRL_IP_LEARNING' value='dhcp'/>
+ </filterref>
+ </interface>
+
+Reserved Variables
+~~~~~~~~~~~~~~~~~~
+
+The following table lists reserved variables in use by libvirt.
+
++------------------+----------------------------------------------------------+
+| Variable Name | Semantics |
++==================+==========================================================+
+| MAC | The MAC address of the interface |
++------------------+----------------------------------------------------------+
+| IP | The list of IP addresses in use by an interface |
++------------------+----------------------------------------------------------+
+| IPV6 | The list of IPV6 addresses in use by an interface |
++------------------+----------------------------------------------------------+
+| DHCPSERVER | The list of IP addresses of trusted DHCP servers |
++------------------+----------------------------------------------------------+
+| DHCPSERVERV6 | Not currently implemented: The list of IPv6 addresses of |
+| | trusted DHCP servers |
++------------------+----------------------------------------------------------+
+| CTRL_IP_LEARNING | The choice of the IP address detection mode |
++------------------+----------------------------------------------------------+
+
+Element and attribute overview
+------------------------------
+
+The root element required for all network filters is named ``filter`` with two
+possible attributes. The ``name`` attribute provides a unique name of the given
+filter. The ``chain`` attribute is optional but allows certain filters to be
+better organized for more efficient processing by the firewall subsystem of the
+underlying host. Currently the system only supports the chains
+``root, ipv4, ipv6, arp and rarp``.
+
+References to other filters
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Any filter may hold references to other filters. Individual filters may be
+referenced multiple times in a filter tree but references between filters must
+not introduce loops (directed acyclic graph).
+
+The following shows the XML of the ``clean-traffic`` network filter referencing
+several other filters.
+
+::
+
+ <filter name='clean-traffic'>
+ <uuid>6ef53069-ba34-94a0-d33d-17751b9b8cb1</uuid>
+ <filterref filter='no-mac-spoofing'/>
+ <filterref filter='no-ip-spoofing'/>
+ <filterref filter='allow-incoming-ipv4'/>
+ <filterref filter='no-arp-spoofing'/>
+ <filterref filter='no-other-l2-traffic'/>
+ <filterref filter='qemu-announce-self'/>
+ </filter>
+
+To reference another filter, the XML node ``filterref`` needs to be provided
+inside a ``filter`` node. This node must have the attribute ``filter`` whose
+value contains the name of the filter to be referenced.
+
+New network filters can be defined at any time and may contain references to
+network filters that are not known to libvirt, yet. However, once a virtual
+machine is started or a network interface referencing a filter is to be
+hotplugged, all network filters in the filter tree must be available. Otherwise
+the virtual machine will not start or the network interface cannot be attached.
+
+Filter rules
+~~~~~~~~~~~~
+
+The following XML shows a simple example of a network traffic filter
+implementing a rule to drop traffic if the IP address (provided through the
+value of the variable IP) in an outgoing IP packet is not the expected one, thus
+preventing IP address spoofing by the VM.
+
+::
+
+ <filter name='no-ip-spoofing' chain='ipv4'>
+ <uuid>fce8ae33-e69e-83bf-262e-30786c1f8072</uuid>
+ <rule action='drop' direction='out' priority='500'>
+ <ip match='no' srcipaddr='$IP'/>
+ </rule>
+ </filter>
+
+A traffic filtering rule starts with the ``rule`` node. This node may contain up
+to three attributes
+
+- action -- mandatory; must either be ``drop`` (matching the rule silently
+ discards the packet with no further analysis), ``reject`` (matching the rule
+ generates an ICMP reject message with no further analysis) :since:`(since
+ 0.9.0)` , ``accept`` (matching the rule accepts the packet with no further
+ analysis), ``return`` (matching the rule passes this filter, but returns
+ control to the calling filter for further analysis) :since:`(since 0.9.7)` ,
+ or ``continue`` (matching the rule goes on to the next rule for further
+ analysis) :since:`(since 0.9.7)` .
+
+- direction -- mandatory; must either be ``in``, ``out`` or ``inout`` if the
+ rule is for incoming, outgoing or incoming-and-outgoing traffic
+
+- priority -- optional; the priority of the rule controls the order in which
+ the rule will be instantiated relative to other rules. Rules with lower value
+ will be instantiated before rules with higher values. Valid values are in the
+ range of 0 to 1000. :since:`Since 0.9.8` this has been extended to cover the
+ range of -1000 to 1000. If this attribute is not provided, priority 500 will
+ automatically be assigned.
+
+ Note that filtering rules in the ``root`` chain are sorted with filters
+ connected to the ``root`` chain following their priorities. This allows to
+ interleave filtering rules with access to filter chains. (See also section on
+ `Filtering chain priorities`_ .)
+
+- statematch -- optional; possible values are '0' or 'false' to turn
the
+ underlying connection state matching off; default is 'true'
+
+ Also read the section on `Advanced Filter Configuration Topics`_.
+
+The above example indicates that the traffic of type ``ip`` will be associated
+with the chain 'ipv4' and the rule will have priority 500. If for example
+another filter is referenced whose traffic of type ``ip`` is also associated
+with the chain 'ipv4' then that filter's rules will be ordered relative to
the
+priority 500 of the shown rule.
+
+A rule may contain a single rule for filtering of traffic. The above example
+shows that traffic of type ``ip`` is to be filtered.
+
+Supported protocols
+^^^^^^^^^^^^^^^^^^^
+
+The following sections enumerate the list of protocols that are supported by the
+network filtering subsystem. The type of traffic a rule is supposed to filter on
+is provided in the ``rule`` node as a nested node. Depending on the traffic type
+a rule is filtering, the attributes are different. The above example showed the
+single attribute ``srcipaddr`` that is valid inside the ``ip`` traffic filtering
+node. The following sections show what attributes are valid and what type of
+data they are expecting. The following datatypes are available:
+
+- UINT8 : 8 bit integer; range 0-255
+
+- UINT16: 16 bit integer; range 0-65535
+
+- MAC_ADDR: MAC address in dotted decimal format, i.e., 00:11:22:33:44:55
+
+- MAC_MASK: MAC address mask in MAC address format, i.e., FF:FF:FF:FC:00:00
+
+- IP_ADDR: IP address in dotted decimal format, i.e., 10.1.2.3
+
+- IP_MASK: IP address mask in either dotted decimal format (255.255.248.0) or
+ CIDR mask (0-32)
+
+- IPV6_ADDR: IPv6 address in numbers format, i.e., FFFF::1
+
+- IPV6_MASK: IPv6 mask in numbers format (FFFF:FFFF:FC00::) or CIDR mask
+ (0-128)
+
+- STRING: A string
+
+- BOOLEAN: 'true', 'yes', '1' or 'false', 'no',
'0'
+
+- IPSETFLAGS: The source and destination flags of the ipset described by up to
+ 6 'src' or 'dst' elements selecting features from either the source
or
+ destination part of the packet header; example: src,src,dst. The number of
+ 'selectors' to provide here depends on the type of ipset that is referenced.
+
+Every attribute except for those of type IP_MASK or IPV6_MASK can be negated
+using the ``match`` attribute with value ``no``. Multiple negated attributes may
+be grouped together. The following XML fragment shows such an example using
+abstract attributes.
+
+::
+
+ [...]
+ <rule action='drop' direction='in'>
+ <protocol match='no' attribute1='value1'
attribute2='value2'/>
+ <protocol attribute3='value3'/>
+ </rule>
+ [...]
+
+Rules perform a logical AND evaluation on all values of the given protocol
+attributes. Thus, if a single attribute's value does not match the one given in
+the rule, the whole rule will be skipped during evaluation. Therefore, in the
+above example incoming traffic will only be dropped if the protocol property
+attribute1 does not match value1 AND the protocol property attribute2 does not
+match value2 AND the protocol property attribute3 matches value3.
+
+MAC (Ethernet)
+''''''''''''''
+
+Protocol ID: ``mac``
+
+Note: Rules of this type should go into the ``root`` chain.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute | Datatype | Semantics |
++=========================+=========================+=========================+
+| srcmacaddr | MAC_ADDR | MAC address of sender |
++-------------------------+-------------------------+-------------------------+
+| srcmacmask | MAC_MASK | Mask applied to MAC |
+| | | address of sender |
++-------------------------+-------------------------+-------------------------+
+| dstmacaddr | MAC_ADDR | MAC address of |
+| | | destination |
++-------------------------+-------------------------+-------------------------+
+| dstmacmask | MAC_MASK | Mask applied to MAC |
+| | | address of destination |
++-------------------------+-------------------------+-------------------------+
+| protocolid | UINT16 (0x600-0xffff), | Layer 3 protocol ID |
+| | STRING | |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since | STRING | text with max. 256 |
+| 0.8.5)` | | characters |
++-------------------------+-------------------------+-------------------------+
+
+Valid Strings for ``protocolid`` are: arp, rarp, ipv4, ipv6
+
+::
+
+ [...]
+ <mac match='no' srcmacaddr='$MAC'/>
+ [...]
+
+VLAN (802.1Q) :since:`(Since 0.9.8)`
+''''''''''''''''''''''''''''''''''''
+
+Protocol ID: ``vlan``
+
+Note: Rules of this type should go either into the ``root`` or ``vlan`` chain.
+
++----------------+-----------------------------+-----------------------------+
+| Attribute | Datatype | Semantics |
++================+=============================+=============================+
+| srcmacaddr | MAC_ADDR | MAC address of sender |
++----------------+-----------------------------+-----------------------------+
+| srcmacmask | MAC_MASK | Mask applied to MAC address |
+| | | of sender |
++----------------+-----------------------------+-----------------------------+
+| dstmacaddr | MAC_ADDR | MAC address of destination |
++----------------+-----------------------------+-----------------------------+
+| dstmacmask | MAC_MASK | Mask applied to MAC address |
+| | | of destination |
++----------------+-----------------------------+-----------------------------+
+| vlanid | UINT16 (0x0-0xfff, 0 - | VLAN ID |
+| | 4095) | |
++----------------+-----------------------------+-----------------------------+
+| encap-protocol | UINT16 (0x03c-0xfff), | Encapsulated layer 3 |
+| | String | protocol ID |
++----------------+-----------------------------+-----------------------------+
+| comment | STRING | text with max. 256 |
+| | | characters |
++----------------+-----------------------------+-----------------------------+
+
+Valid Strings for ``encap-protocol`` are: arp, ipv4, ipv6
+
+STP (Spanning Tree Protocol) (Since 0.9.8)
+''''''''''''''''''''''''''''''''''''''''''
+
+Protocol ID: ``stp``
+
+Note: Rules of this type should go either into the ``root`` or ``stp`` chain.
+
+=================== =========== =====================================
+Attribute Datatype Semantics
+=================== =========== =====================================
+srcmacaddr MAC_ADDR MAC address of sender
+srcmacmask MAC_MASK Mask applied to MAC address of sender
+type UINT8 Bridge Protocol Data Unit (BPDU) type
+flags UINT8 BPDU flag
+root-priority UINT16 Root priority (range start)
+root-priority-hi UINT16 Root priority range end
+root-address MAC_ADDRESS Root MAC address
+root-address-mask MAC_MASK Root MAC address mask
+root-cost UINT32 Root path cost (range start)
+root-cost-hi UINT32 Root path cost range end
+sender-priority UINT16 Sender priority (range start)
+sender-priority-hi UINT16 Sender priority range end
+sender-address MAC_ADDRESS BPDU sender MAC address
+sender-address-mask MAC_MASK BPDU sender MAC address mask
+port UINT16 Port identifier (range start)
+port_hi UINT16 Port identifier range end
+msg-age UINT16 Message age timer (range start)
+msg-age-hi UINT16 Message age timer range end
+max-age UINT16 Maximum age timer (range start)
+max-age-hi UINT16 Maximum age timer range end
+hello-time UINT16 Hello time timer (range start)
+hello-time-hi UINT16 Hello time timer range end
+forward-delay UINT16 Forward delay (range start)
+forward-delay-hi UINT16 Forward delay range end
+comment STRING text with max. 256 characters
+=================== =========== =====================================
+
+ARP/RARP
+''''''''
+
+Protocol ID: ``arp`` or ``rarp``
+
+Note: Rules of this type should either go into the ``root`` or ``arp/rarp``
+chain.
+
++-----------------------------+----------------+-----------------------------+
+| Attribute | Datatype | Semantics |
++=============================+================+=============================+
+| srcmacaddr | MAC_ADDR | MAC address of sender |
++-----------------------------+----------------+-----------------------------+
+| srcmacmask | MAC_MASK | Mask applied to MAC address |
+| | | of sender |
++-----------------------------+----------------+-----------------------------+
+| dstmacaddr | MAC_ADDR | MAC address of destination |
++-----------------------------+----------------+-----------------------------+
+| dstmacmask | MAC_MASK | Mask applied to MAC address |
+| | | of destination |
++-----------------------------+----------------+-----------------------------+
+| hwtype | UINT16 | Hardware type |
++-----------------------------+----------------+-----------------------------+
+| protocoltype | UINT16 | Protocol type |
++-----------------------------+----------------+-----------------------------+
+| opcode | UINT16, STRING | Opcode |
++-----------------------------+----------------+-----------------------------+
+| arpsrcmacaddr | MAC_ADDR | Source MAC address in |
+| | | ARP/RARP packet |
++-----------------------------+----------------+-----------------------------+
+| arpdstmacaddr | MAC_ADDR | Destination MAC address in |
+| | | ARP/RARP packet |
++-----------------------------+----------------+-----------------------------+
+| arpsrcipaddr | IP_ADDR | Source IP address in |
+| | | ARP/RARP packet |
++-----------------------------+----------------+-----------------------------+
+| arpsrcipmask :since:`(Since | IP_MASK | Source IP mask |
+| 1.2.3)` | | |
++-----------------------------+----------------+-----------------------------+
+| arpdstipaddr | IP_ADDR | Destination IP address in |
+| | | ARP/RARP packet |
++-----------------------------+----------------+-----------------------------+
+| arpdstipmask :since:`(Since | IP_MASK | Destination IP mask |
+| 1.2.3)` | | |
++-----------------------------+----------------+-----------------------------+
+| comment :since:`(Since | STRING | text with max. 256 |
+| 0.8.5)` | | characters |
++-----------------------------+----------------+-----------------------------+
+| gratuitous :since:`(Since | BOOLEAN | boolean indicating whether |
+| 0.9.2)` | | to check for gratuitous ARP |
+| | | packet |
++-----------------------------+----------------+-----------------------------+
+
+Valid strings for the ``Opcode`` field are: Request, Reply, Request_Reverse,
+Reply_Reverse, DRARP_Request, DRARP_Reply, DRARP_Error, InARP_Request, ARP_NAK
+
+IPv4
+''''
+
+Protocol ID: ``ip``
+
+Note: Rules of this type should either go into the ``root`` or ``ipv4`` chain.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute | Datatype | Semantics |
++=========================+=========================+=========================+
+| srcmacaddr | MAC_ADDR | MAC address of sender |
++-------------------------+-------------------------+-------------------------+
+| srcmacmask | MAC_MASK | Mask applied to MAC |
+| | | address of sender |
++-------------------------+-------------------------+-------------------------+
+| dstmacaddr | MAC_ADDR | MAC address of |
+| | | destination |
++-------------------------+-------------------------+-------------------------+
+| dstmacmask | MAC_MASK | Mask applied to MAC |
+| | | address of destination |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr | IP_ADDR | Source IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipmask | IP_MASK | Mask applied to source |
+| | | IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr | IP_ADDR | Destination IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipmask | IP_MASK | Mask applied to |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| protocol | UINT8, STRING | Layer 4 protocol |
+| | | identifier |
++-------------------------+-------------------------+-------------------------+
+| srcportstart | UINT16 | Start of range of valid |
+| | | source ports; requires |
+| | | ``protocol`` |
++-------------------------+-------------------------+-------------------------+
+| srcportend | UINT16 | End of range of valid |
+| | | source ports; requires |
+| | | ``protocol`` |
++-------------------------+-------------------------+-------------------------+
+| dstportstart | UINT16 | Start of range of valid |
+| | | destination ports; |
+| | | requires ``protocol`` |
++-------------------------+-------------------------+-------------------------+
+| dstportend | UINT16 | End of range of valid |
+| | | destination ports; |
+| | | requires ``protocol`` |
++-------------------------+-------------------------+-------------------------+
+| dscp | UINT8 (0x0-0x3f, 0 - | Differentiated Services |
+| | 63) | Code Point |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since | STRING | text with max. 256 |
+| 0.8.5)` | | characters |
++-------------------------+-------------------------+-------------------------+
+
+Valid strings for ``protocol`` are: tcp, udp, udplite, esp, ah, icmp, igmp, sctp
+
+IPv6
+''''
+
+Protocol ID: ``ipv6``
+
+Note: Rules of this type should either go into the ``root`` or ``ipv6`` chain.
+
++--------------------------------+-----------+--------------------------------+
+| Attribute | Datatype | Semantics |
++================================+===========+================================+
+| srcmacaddr | MAC_ADDR | MAC address of sender |
++--------------------------------+-----------+--------------------------------+
+| srcmacmask | MAC_MASK | Mask applied to MAC address of |
+| | | sender |
++--------------------------------+-----------+--------------------------------+
+| dstmacaddr | MAC_ADDR | MAC address of destination |
++--------------------------------+-----------+--------------------------------+
+| dstmacmask | MAC_MASK | Mask applied to MAC address of |
+| | | destination |
++--------------------------------+-----------+--------------------------------+
+| srcipaddr | IPV6_ADDR | Source IPv6 address |
++--------------------------------+-----------+--------------------------------+
+| srcipmask | IPV6_MASK | Mask applied to source IPv6 |
+| | | address |
++--------------------------------+-----------+--------------------------------+
+| dstipaddr | IPV6_ADDR | Destination IPv6 address |
++--------------------------------+-----------+--------------------------------+
+| dstipmask | IPV6_MASK | Mask applied to destination |
+| | | IPv6 address |
++--------------------------------+-----------+--------------------------------+
+| protocol | UINT8 | Layer 4 protocol identifier |
++--------------------------------+-----------+--------------------------------+
+| srcportstart | UINT16 | Start of range of valid source |
+| | | ports; requires ``protocol`` |
++--------------------------------+-----------+--------------------------------+
+| srcportend | UINT16 | End of range of valid source |
+| | | ports; requires ``protocol`` |
++--------------------------------+-----------+--------------------------------+
+| dstportstart | UINT16 | Start of range of valid |
+| | | destination ports; requires |
+| | | ``protocol`` |
++--------------------------------+-----------+--------------------------------+
+| dstportend | UINT16 | End of range of valid |
+| | | destination ports; requires |
+| | | ``protocol`` |
++--------------------------------+-----------+--------------------------------+
+| type :since:`(Since 1.2.12)` | UINT8 | ICMPv6 type; requires |
+| | | ``protocol`` to be set to |
+| | | ``icmpv6`` |
++--------------------------------+-----------+--------------------------------+
+| typeend :since:`(Since | UINT8 | ICMPv6 type end of range; |
+| 1.2.12)` | | requires ``protocol`` to be |
+| | | set to ``icmpv6`` |
++--------------------------------+-----------+--------------------------------+
+| code :since:`(Since 1.2.12)` | UINT8 | ICMPv6 code; requires |
+| | | ``protocol`` to be set to |
+| | | ``icmpv6`` |
++--------------------------------+-----------+--------------------------------+
+| code :since:`(Since 1.2.12)` | UINT8 | ICMPv6 code end of range; |
+| | | requires ``protocol`` to be |
+| | | set to ``icmpv6`` |
++--------------------------------+-----------+--------------------------------+
+| comment :since:`(Since 0.8.5)` | STRING | text with max. 256 characters |
++--------------------------------+-----------+--------------------------------+
+
+Valid strings for ``protocol`` are: tcp, udp, udplite, esp, ah, icmpv6, sctp
+
+TCP/UDP/SCTP
+''''''''''''
+
+Protocol ID: ``tcp``, ``udp``, ``sctp``
+
+Note: The chain parameter is ignored for this type of traffic and should either
+be omitted or set to ``root``.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute | Datatype | Semantics |
++=========================+=========================+=========================+
+| srcmacaddr | MAC_ADDR | MAC address of sender |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr | IP_ADDR | Source IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipmask | IP_MASK | Mask applied to source |
+| | | IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr | IP_ADDR | Destination IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipmask | IP_MASK | Mask applied to |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipfrom | IP_ADDR | Start of range of |
+| | | source IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipto | IP_ADDR | End of range of source |
+| | | IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipfrom | IP_ADDR | Start of range of |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipto | IP_ADDR | End of range of |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| srcportstart | UINT16 | Start of range of valid |
+| | | source ports |
++-------------------------+-------------------------+-------------------------+
+| srcportend | UINT16 | End of range of valid |
+| | | source ports |
++-------------------------+-------------------------+-------------------------+
+| dstportstart | UINT16 | Start of range of valid |
+| | | destination ports |
++-------------------------+-------------------------+-------------------------+
+| dstportend | UINT16 | End of range of valid |
+| | | destination ports |
++-------------------------+-------------------------+-------------------------+
+| dscp | UINT8 (0x0-0x3f, 0 - | Differentiated Services |
+| | 63) | Code Point |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since | STRING | text with max. 256 |
+| 0.8.5)` | | characters |
++-------------------------+-------------------------+-------------------------+
+| state :since:`(Since | STRING | comma separated list of |
+| 0.8.5)` | | NEW,ESTA |
+| | | BLISHED,RELATED,INVALID |
+| | | or NONE |
++-------------------------+-------------------------+-------------------------+
+| flags :since:`(Since | STRING | TCP-only: format of |
+| 0.9.1)` | | mask/flags with mask |
+| | | and flags each being a |
+| | | comma separated list of |
+| | | SYN,ACK,URG,PSH,FIN,RST |
+| | | or NONE or ALL |
++-------------------------+-------------------------+-------------------------+
+| ipset :since:`(Since | STRING | The name of an IPSet |
+| 0.9.13)` | | managed outside of |
+| | | libvirt |
++-------------------------+-------------------------+-------------------------+
+| ipsetflags | IPSETFLAGS | flags for the IPSet; |
+| :since:`(Since 0.9.13)` | | requires ipset |
+| | | attribute |
++-------------------------+-------------------------+-------------------------+
+
+ICMP
+''''
+
+Protocol ID: ``icmp``
+
+Note: The chain parameter is ignored for this type of traffic and should either
+be omitted or set to ``root``.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute | Datatype | Semantics |
++=========================+=========================+=========================+
+| srcmacaddr | MAC_ADDR | MAC address of sender |
++-------------------------+-------------------------+-------------------------+
+| srcmacmask | MAC_MASK | Mask applied to MAC |
+| | | address of sender |
++-------------------------+-------------------------+-------------------------+
+| dstmacaddr | MAC_ADDR | MAC address of |
+| | | destination |
++-------------------------+-------------------------+-------------------------+
+| dstmacmask | MAC_MASK | Mask applied to MAC |
+| | | address of destination |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr | IP_ADDR | Source IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipmask | IP_MASK | Mask applied to source |
+| | | IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr | IP_ADDR | Destination IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipmask | IP_MASK | Mask applied to |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipfrom | IP_ADDR | Start of range of |
+| | | source IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipto | IP_ADDR | End of range of source |
+| | | IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipfrom | IP_ADDR | Start of range of |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipto | IP_ADDR | End of range of |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| type | UINT16 | ICMP type |
++-------------------------+-------------------------+-------------------------+
+| code | UINT16 | ICMP code |
++-------------------------+-------------------------+-------------------------+
+| dscp | UINT8 (0x0-0x3f, 0 - | Differentiated Services |
+| | 63) | Code Point |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since | STRING | text with max. 256 |
+| 0.8.5)` | | characters |
++-------------------------+-------------------------+-------------------------+
+| state :since:`(Since | STRING | comma separated list of |
+| 0.8.5)` | | NEW,ESTA |
+| | | BLISHED,RELATED,INVALID |
+| | | or NONE |
++-------------------------+-------------------------+-------------------------+
+| ipset :since:`(Since | STRING | The name of an IPSet |
+| 0.9.13)` | | managed outside of |
+| | | libvirt |
++-------------------------+-------------------------+-------------------------+
+| ipsetflags | IPSETFLAGS | flags for the IPSet; |
+| :since:`(Since 0.9.13)` | | requires ipset |
+| | | attribute |
++-------------------------+-------------------------+-------------------------+
+
+IGMP, ESP, AH, UDPLITE, 'ALL'
+'''''''''''''''''''''''''''''
+
+Protocol ID: ``igmp``, ``esp``, ``ah``, ``udplite``, ``all``
+
+Note: The chain parameter is ignored for this type of traffic and should either
+be omitted or set to ``root``.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute | Datatype | Semantics |
++=========================+=========================+=========================+
+| srcmacaddr | MAC_ADDR | MAC address of sender |
++-------------------------+-------------------------+-------------------------+
+| srcmacmask | MAC_MASK | Mask applied to MAC |
+| | | address of sender |
++-------------------------+-------------------------+-------------------------+
+| dstmacaddr | MAC_ADDR | MAC address of |
+| | | destination |
++-------------------------+-------------------------+-------------------------+
+| dstmacmask | MAC_MASK | Mask applied to MAC |
+| | | address of destination |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr | IP_ADDR | Source IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipmask | IP_MASK | Mask applied to source |
+| | | IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr | IP_ADDR | Destination IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipmask | IP_MASK | Mask applied to |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipfrom | IP_ADDR | Start of range of |
+| | | source IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipto | IP_ADDR | End of range of source |
+| | | IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipfrom | IP_ADDR | Start of range of |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipto | IP_ADDR | End of range of |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| dscp | UINT8 (0x0-0x3f, 0 - | Differentiated Services |
+| | 63) | Code Point |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since | STRING | text with max. 256 |
+| 0.8.5)` | | characters |
++-------------------------+-------------------------+-------------------------+
+| state :since:`(Since | STRING | comma separated list of |
+| 0.8.5)` | | NEW,ESTA |
+| | | BLISHED,RELATED,INVALID |
+| | | or NONE |
++-------------------------+-------------------------+-------------------------+
+| ipset :since:`(Since | STRING | The name of an IPSet |
+| 0.9.13)` | | managed outside of |
+| | | libvirt |
++-------------------------+-------------------------+-------------------------+
+| ipsetflags | IPSETFLAGS | flags for the IPSet; |
+| :since:`(Since 0.9.13)` | | requires ipset |
+| | | attribute |
++-------------------------+-------------------------+-------------------------+
+
+TCP/UDP/SCTP over IPV6
+''''''''''''''''''''''
+
+Protocol ID: ``tcp-ipv6``, ``udp-ipv6``, ``sctp-ipv6``
+
+Note: The chain parameter is ignored for this type of traffic and should either
+be omitted or set to ``root``.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute | Datatype | Semantics |
++=========================+=========================+=========================+
+| srcmacaddr | MAC_ADDR | MAC address of sender |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr | IPV6_ADDR | Source IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipmask | IPV6_MASK | Mask applied to source |
+| | | IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr | IPV6_ADDR | Destination IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipmask | IPV6_MASK | Mask applied to |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipfrom | IPV6_ADDR | Start of range of |
+| | | source IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipto | IPV6_ADDR | End of range of source |
+| | | IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipfrom | IPV6_ADDR | Start of range of |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipto | IPV6_ADDR | End of range of |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| srcportstart | UINT16 | Start of range of valid |
+| | | source ports |
++-------------------------+-------------------------+-------------------------+
+| srcportend | UINT16 | End of range of valid |
+| | | source ports |
++-------------------------+-------------------------+-------------------------+
+| dstportstart | UINT16 | Start of range of valid |
+| | | destination ports |
++-------------------------+-------------------------+-------------------------+
+| dstportend | UINT16 | End of range of valid |
+| | | destination ports |
++-------------------------+-------------------------+-------------------------+
+| dscp | UINT8 (0x0-0x3f, 0 - | Differentiated Services |
+| | 63) | Code Point |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since | STRING | text with max. 256 |
+| 0.8.5)` | | characters |
++-------------------------+-------------------------+-------------------------+
+| state :since:`(Since | STRING | comma separated list of |
+| 0.8.5)` | | NEW,ESTA |
+| | | BLISHED,RELATED,INVALID |
+| | | or NONE |
++-------------------------+-------------------------+-------------------------+
+| flags :since:`(Since | STRING | TCP-only: format of |
+| 0.9.1)` | | mask/flags with mask |
+| | | and flags each being a |
+| | | comma separated list of |
+| | | SYN,ACK,URG,PSH,FIN,RST |
+| | | or NONE or ALL |
++-------------------------+-------------------------+-------------------------+
+| ipset :since:`(Since | STRING | The name of an IPSet |
+| 0.9.13)` | | managed outside of |
+| | | libvirt |
++-------------------------+-------------------------+-------------------------+
+| ipsetflags | IPSETFLAGS | flags for the IPSet; |
+| :since:`(Since 0.9.13)` | | requires ipset |
+| | | attribute |
++-------------------------+-------------------------+-------------------------+
+
+ICMPv6
+''''''
+
+Protocol ID: ``icmpv6``
+
+Note: The chain parameter is ignored for this type of traffic and should either
+be omitted or set to ``root``.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute | Datatype | Semantics |
++=========================+=========================+=========================+
+| srcmacaddr | MAC_ADDR | MAC address of sender |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr | IPV6_ADDR | Source IPv6 address |
++-------------------------+-------------------------+-------------------------+
+| srcipmask | IPV6_MASK | Mask applied to source |
+| | | IPv6 address |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr | IPV6_ADDR | Destination IPv6 |
+| | | address |
++-------------------------+-------------------------+-------------------------+
+| dstipmask | IPV6_MASK | Mask applied to |
+| | | destination IPv6 |
+| | | address |
++-------------------------+-------------------------+-------------------------+
+| srcipfrom | IPV6_ADDR | Start of range of |
+| | | source IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipto | IPV6_ADDR | End of range of source |
+| | | IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipfrom | IPV6_ADDR | Start of range of |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipto | IPV6_ADDR | End of range of |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| type | UINT16 | ICMPv6 type |
++-------------------------+-------------------------+-------------------------+
+| code | UINT16 | ICMPv6 code |
++-------------------------+-------------------------+-------------------------+
+| dscp | UINT8 (0x0-0x3f, 0 - | Differentiated Services |
+| | 63) | Code Point |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since | STRING | text with max. 256 |
+| 0.8.5)` | | characters |
++-------------------------+-------------------------+-------------------------+
+| state :since:`(Since | STRING | comma separated list of |
+| 0.8.5)` | | NEW,ESTA |
+| | | BLISHED,RELATED,INVALID |
+| | | or NONE |
++-------------------------+-------------------------+-------------------------+
+| ipset :since:`(Since | STRING | The name of an IPSet |
+| 0.9.13)` | | managed outside of |
+| | | libvirt |
++-------------------------+-------------------------+-------------------------+
+| ipsetflags | IPSETFLAGS | flags for the IPSet; |
+| :since:`(Since 0.9.13)` | | requires ipset |
+| | | attribute |
++-------------------------+-------------------------+-------------------------+
+
+ESP, AH, UDPLITE, 'ALL' over IPv6
+'''''''''''''''''''''''''''''''''
+
+Protocol ID: ``esp-ipv6``, ``ah-ipv6``, ``udplite-ipv6``, ``all-ipv6``
+
+Note: The chain parameter is ignored for this type of traffic and should either
+be omitted or set to ``root``.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute | Datatype | Semantics |
++=========================+=========================+=========================+
+| srcmacaddr | MAC_ADDR | MAC address of sender |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr | IPV6_ADDR | Source IPv6 address |
++-------------------------+-------------------------+-------------------------+
+| srcipmask | IPV6_MASK | Mask applied to source |
+| | | IPv6 address |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr | IPV6_ADDR | Destination IPv6 |
+| | | address |
++-------------------------+-------------------------+-------------------------+
+| dstipmask | IPV6_MASK | Mask applied to |
+| | | destination IPv6 |
+| | | address |
++-------------------------+-------------------------+-------------------------+
+| srcipfrom | IPV6_ADDR | Start of range of |
+| | | source IP address |
++-------------------------+-------------------------+-------------------------+
+| srcipto | IPV6_ADDR | End of range of source |
+| | | IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipfrom | IPV6_ADDR | Start of range of |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| dstipto | IPV6_ADDR | End of range of |
+| | | destination IP address |
++-------------------------+-------------------------+-------------------------+
+| dscp | UINT8 (0x0-0x3f, 0 - | Differentiated Services |
+| | 63) | Code Point |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since | STRING | text with max. 256 |
+| 0.8.5)` | | characters |
++-------------------------+-------------------------+-------------------------+
+| state :since:`(Since | STRING | comma separated list of |
+| 0.8.5)` | | NEW,ESTA |
+| | | BLISHED,RELATED,INVALID |
+| | | or NONE |
++-------------------------+-------------------------+-------------------------+
+| ipset :since:`(Since | STRING | The name of an IPSet |
+| 0.9.13)` | | managed outside of |
+| | | libvirt |
++-------------------------+-------------------------+-------------------------+
+| ipsetflags | IPSETFLAGS | flags for the IPSet; |
+| :since:`(Since 0.9.13)` | | requires ipset |
+| | | attribute |
++-------------------------+-------------------------+-------------------------+
+
+Advanced Filter Configuration Topics
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following sections discuss advanced filter configuration topics.
+
+Connection tracking
+^^^^^^^^^^^^^^^^^^^
+
+The network filtering subsystem (on Linux) makes use of the connection tracking
+support of iptables. This helps in enforcing the directionality of network
+traffic (state match) as well as counting and limiting the number of
+simultaneous connections towards a VM. As an example, if a VM has TCP port 8080
+open as a server, clients may connect to the VM on port 8080. Connection
+tracking and enforcement of directionality then prevents the VM from initiating
+a connection from (TCP client) port 8080 to the host back to a remote host. More
+importantly, tracking helps to prevent remote attackers from establishing a
+connection back to a VM. For example, if the user inside the VM established a
+connection to port 80 on an attacker site, then the attacker will not be able to
+initiate a connection from TCP port 80 back towards the VM. By default the
+connection state match that enables connection tracking and then enforcement of
+directionality of traffic is turned on.
+
+The following shows an example XML fragment where this feature has been turned
+off for incoming connections to TCP port 12345.
+
+::
+
+ [...]
+ <rule direction='in' action='accept'
statematch='false'>
+ <tcp dstportstart='12345'/>
+ </rule>
+ [...]
+
+This now allows incoming traffic to TCP port 12345, but would also enable the
+initiation from (client) TCP port 12345 within the VM, which may or may not be
+desirable.
+
+Limiting Number of Connections
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To limit the number of connections a VM may establish, a rule must be provided
+that sets a limit of connections for a given type of traffic. If for example a
+VM is supposed to be allowed to only ping one other IP address at a time and is
+supposed to have only one active incoming ssh connection at a time, the
+following XML fragment can be used to achieve this.
+
+::
+
+ [...]
+ <rule action='drop' direction='in' priority='400'>
+ <tcp connlimit-above='1'/>
+ </rule>
+ <rule action='accept' direction='in' priority='500'>
+ <tcp dstportstart='22'/>
+ </rule>
+ <rule action='drop' direction='out' priority='400'>
+ <icmp connlimit-above='1'/>
+ </rule>
+ <rule action='accept' direction='out' priority='500'>
+ <icmp/>
+ </rule>
+ <rule action='accept' direction='out' priority='500'>
+ <udp dstportstart='53'/>
+ </rule>
+ <rule action='drop' direction='inout' priority='1000'>
+ <all/>
+ </rule>
+ [...]
+
+Note that the rule for the limit has to logically appear before the rule for
+accepting the traffic.
+
+An additional rule for letting DNS traffic to port 22 go out the VM has been
+added to avoid ssh sessions not getting established for reasons related to DNS
+lookup failures by the ssh daemon. Leaving this rule out may otherwise lead to
+fun-filled debugging joy (symptom: ssh client seems to hang while trying to
+connect).
+
+Lot of care must be taken with timeouts related to tracking of traffic. An ICMP
+ping that the user may have terminated inside the VM may have a long timeout in
+the host's connection tracking system and therefore not allow another ICMP ping
+to go through for a while. Therefore, the timeouts have to be tuned in the
+host's sysfs, i.e.,
+
+::
+
+ echo 3 > /proc/sys/net/netfilter/nf_conntrack_icmp_timeout
+
+sets the ICMP connection tracking timeout to 3 seconds. The effect of this is
+that once one ping is terminated, another one can start after 3 seconds.
+
+Further, we want to point out that a client that for whatever reason has not
+properly closed a TCP connection may cause a connection to be held open for a
+longer period of time, depending to what timeout the ``TCP established`` state
+timeout has been set to on the host. Also, idle connections may time out in the
+connection tracking system but can be reactivated once packets are exchanged.
+However, a newly initiated connection may force an idle connection into TCP
+backoff if the number of allowed connections is set to a too low limit, the new
+connection is established and hits (not exceeds) the limit of allowed
+connections and for example a key is pressed on the old ssh session, which now
+has become unresponsive due to its traffic being dropped. Therefore, the limit
+of connections should be rather high so that fluctuations in new TCP connections
+don't cause odd traffic behavior in relation to idle connections.
+
+Command line tools
+------------------
+
+The libvirt command line tool ``virsh`` has been extended with life-cycle
+support for network filters. All commands related to the network filtering
+subsystem start with the prefix ``nwfilter``. The following commands are
+available:
+
+- nwfilter-list : list UUIDs and names of all network filters
+
+- nwfilter-define : define a new network filter or update an existing one
+
+- nwfilter-undefine : delete a network filter given its name; it must not be
+ currently in use
+
+- nwfilter-dumpxml : display a network filter given its name
+
+- nwfilter-edit : edit a network filter given its name
+
+Pre-existing network filters
+----------------------------
+
+The following is a list of example network filters that are automatically
+installed with libvirt.
+
++---------------------+-------------------------------------------------------+
+| Name | Description |
++=====================+=======================================================+
+| no-arp-spoofing | Prevent a VM from spoofing ARP traffic; this filter |
+| | only allows ARP request and reply messages and |
+| | enforces that those packets contain the MAC and IP |
+| | addresses of the VM. |
++---------------------+-------------------------------------------------------+
+| allow-arp | Allow ARP traffic in both directions |
++---------------------+-------------------------------------------------------+
+| allow-ipv4 | Allow IPv4 traffic in both directions |
++---------------------+-------------------------------------------------------+
+| allow-ipv6 | Allow IPv6 traffic in both directions |
++---------------------+-------------------------------------------------------+
+| allow-incoming-ipv4 | Allow incoming IPv4 traffic |
++---------------------+-------------------------------------------------------+
+| allow-incoming-ipv6 | Allow incoming IPv6 traffic |
++---------------------+-------------------------------------------------------+
+| allow-dhcp | Allow a VM to request an IP address via DHCP (from |
+| | any DHCP server) |
++---------------------+-------------------------------------------------------+
+| allow-dhcpv6 | Similar to allow-dhcp, but for DHCPv6 |
++---------------------+-------------------------------------------------------+
+| allow-dhcp-server | Allow a VM to request an IP address from a specified |
+| | DHCP server. The dotted decimal IP address of the |
+| | DHCP server must be provided in a reference to this |
+| | filter. The name of the variable must be |
+| | *DHCPSERVER*. |
++---------------------+-------------------------------------------------------+
+| allow-dhcpv6-server | Similar to allow-dhcp-server, but for DHCPv6 |
++---------------------+-------------------------------------------------------+
+| no-ip-spoofing | Prevent a VM from sending of IPv4 packets with a |
+| | source IP address different from the one in the |
+| | packet. |
++---------------------+-------------------------------------------------------+
+| no-ipv6-spoofing | Similar to no-ip-spoofing, but for IPv6 |
++---------------------+-------------------------------------------------------+
+| no-ip-multicast | Prevent a VM from sending IP multicast packets. |
++---------------------+-------------------------------------------------------+
+| no-ipv6-multicast | Similar to no-ip-multicast, but for IPv6 |
++---------------------+-------------------------------------------------------+
+| clean-traffic | Prevent MAC, IP and ARP spoofing. This filter |
+| | references several other filters as building blocks. |
++---------------------+-------------------------------------------------------+
+
+Note that most of the above filters are only building blocks and require a
+combination with other filters to provide useful network traffic filtering. The
+most useful one in the above list is the *clean-traffic* filter. This filter
+itself can for example be combined with the *no-ip-multicast* filter to prevent
+virtual machines from sending IP multicast traffic on top of the prevention of
+packet spoofing.
+
+Writing your own filters
+------------------------
+
+Since libvirt only provides a couple of example networking filters, you may
+consider writing your own. When planning on doing so there are a couple of
+things you may need to know regarding the network filtering subsystem and how it
+works internally. Certainly you also have to know and understand the protocols
+very well that you want to be filtering on so that no further traffic than what
+you want can pass and that in fact the traffic you want to allow does pass.
+
+The network filtering subsystem is currently only available on Linux hosts and
+only works for QEMU and KVM type of virtual machines. On Linux it builds upon
+the support for ``ebtables``, ``iptables`` and ``ip6tables`` and makes use of
+their features. From the above list of supported protocols the following ones
+are implemented using ``ebtables``:
+
+- mac
+
+- stp (spanning tree protocol)
+
+- vlan (802.1Q)
+
+- arp, rarp
+
+- ipv4
+
+- ipv6
+
+All other protocols over IPv4 are supported using iptables, those over IPv6 are
+implemented using ip6tables.
+
+On a Linux host, all traffic filtering instantiated by libvirt's network filter
+subsystem first passes through the filtering support implemented by ebtables and
+only then through iptables or ip6tables filters. If a filter tree has rules with
+the protocols ``mac``, ``stp``, ``vlan`` ``arp``, ``rarp``, ``ipv4``, or
+``ipv6`` ebtables rules will automatically be instantiated.
+
+The role of the ``chain`` attribute in the network filter XML is that internally
+a new user-defined ebtables table is created that then for example receives all
+``arp`` traffic coming from or going to a virtual machine if the chain ``arp``
+has been specified. Further, a rule is generated in an interface's ``root``
+chain that directs all ipv4 traffic into the user-defined chain. Therefore, all
+ARP traffic rules should then be placed into filters specifying this chain. This
+type of branching into user-defined tables is only supported with filtering on
+the ebtables layer.
+
+:since:`Since 0.9.8` multiple chains for the same protocol can be created. For
+this the name of the chain must have a prefix of one of the previously
+enumerated protocols. To create an additional chain for handling of ARP traffic,
+a chain with name ``arp-test`` can be specified.
+
+As an example, it is possible to filter on UDP traffic by source and destination
+ports using the ``ip`` protocol filter and specifying attributes for the
+protocol, source and destination IP addresses and ports of UDP packets that are
+to be accepted. This allows early filtering of UDP traffic with ebtables.
+However, once an IP or IPv6 packet, such as a UDP packet, has passed the
+ebtables layer and there is at least one rule in a filter tree that instantiates
+iptables or ip6tables rules, a rule to let the UDP packet pass will also be
+necessary to be provided for those filtering layers. This can be achieved with a
+rule containing an appropriate ``udp`` or ``udp-ipv6`` traffic filtering node.
+
+Example custom filter
+~~~~~~~~~~~~~~~~~~~~~
+
+As an example we want to now build a filter that fulfills the following list of
+requirements:
+
+- prevents a VM's interface from MAC, IP and ARP spoofing
+
+- opens only TCP ports 22 and 80 of a VM's interface
+
+- allows the VM to send ping traffic from an interface but not let the VM be
+ pinged on the interface
+
+- allows the VM to do DNS lookups (UDP towards port 53)
+
+The requirement to prevent spoofing is fulfilled by the existing
+``clean-traffic`` network filter, thus we will reference this filter from our
+custom filter.
+
+To enable traffic for TCP ports 22 and 80 we will add 2 rules to enable this
+type of traffic. To allow the VM to send ping traffic we will add a rule for
+ICMP traffic. For simplicity reasons we allow general ICMP traffic to be
+initiated from the VM, not just ICMP echo request and response messages. To then
+disallow all other traffic to reach or be initiated by the VM we will then need
+to add a rule that drops all other traffic. Assuming our VM is called *test* and
+the interface we want to associate our filter with is called *eth0*, we name our
+filter *test-eth0*. The result of these considerations is the following network
+filter XML:
+
+::
+
+ <filter name='test-eth0'>
+ <!-- reference the clean traffic filter to prevent
+ MAC, IP and ARP spoofing. By not providing
+ and IP address parameter, libvirt will detect the
+ IP address the VM is using. -->
+ <filterref filter='clean-traffic'/>
+
+ <!-- enable TCP ports 22 (ssh) and 80 (http) to be reachable -->
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='22'/>
+ </rule>
+
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='80'/>
+ </rule>
+
+ <!-- enable general ICMP traffic to be initiated by the VM;
+ this includes ping traffic -->
+ <rule action='accept' direction='out'>
+ <icmp/>
+ </rule>
+
+ <!-- enable outgoing DNS lookups using UDP -->
+ <rule action='accept' direction='out'>
+ <udp dstportstart='53'/>
+ </rule>
+
+ <!-- drop all other traffic -->
+ <rule action='drop' direction='inout'>
+ <all/>
+ </rule>
+
+ </filter>
+
+Note that none of the rules in the above XML contain the IP address of the VM as
+either source or destination address, yet the filtering of the traffic works
+correctly. The reason is that the evaluation of the rules internally happens on
+a per-interface basis and the rules are evaluated based on the knowledge about
+which (tap) interface has sent or will receive the packet rather than what their
+source or destination IP address may be.
+
+An XML fragment for a possible network interface description inside the domain
+XML of the ``test`` VM could then look like this:
+
+::
+
+ [...]
+ <interface type='bridge'>
+ <source bridge='mybridge'/>
+ <filterref filter='test-eth0'/>
+ </interface>
+ [...]
+
+To more strictly control the ICMP traffic and enforce that only ICMP echo
+requests can be sent from the VM and only ICMP echo responses be received by the
+VM, the above ``ICMP`` rule can be replaced with the following two rules:
+
+::
+
+ <!-- enable outgoing ICMP echo requests-->
+ <rule action='accept' direction='out'>
+ <icmp type='8'/>
+ </rule>
+
+ <!-- enable incoming ICMP echo replies-->
+ <rule action='accept' direction='in'>
+ <icmp type='0'/>
+ </rule>
+
+Second example custom filter
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In this example we now want to build a similar filter as in the example above,
+but extend the list of requirements with an ftp server located inside the VM.
+Further, we will be using features that have been added in :since:`version
+0.8.5` . The requirements for this filter are:
+
+- prevents a VM's interface from MAC, IP and ARP spoofing
+
+- opens only TCP ports 22 and 80 of a VM's interface
+
+- allows the VM to send ping traffic from an interface but not let the VM be
+ pinged on the interface
+
+- allows the VM to do DNS lookups (UDP towards port 53)
+
+- enable an ftp server (in active mode) to be run inside the VM
+
+The additional requirement of allowing an ftp server to be run inside the VM
+maps into the requirement of allowing port 21 to be reachable for ftp control
+traffic as well as enabling the VM to establish an outgoing tcp connection
+originating from the VM's TCP port 20 back to the ftp client (ftp active mode).
+There are several ways of how this filter can be written and we present 2
+solutions.
+
+The 1st solution makes use of the ``state`` attribute of the TCP protocol that
+gives us a hook into the connection tracking framework of the Linux host. For
+the VM-initiated ftp data connection (ftp active mode) we use the ``RELATED``
+state that allows us to detect that the VM-initiated ftp data connection is a
+consequence of ( or 'has a relationship with' ) an existing ftp control
+connection, thus we want to allow it to let packets pass the firewall. The
+``RELATED`` state, however, is only valid for the very first packet of the
+outgoing TCP connection for the ftp data path. Afterwards, the state to compare
+against is ``ESTABLISHED``, which then applies equally to the incoming and
+outgoing direction. All this is related to the ftp data traffic originating from
+TCP port 20 of the VM. This then leads to the following solution :since:`(since
+0.8.5 (QEMU, KVM))` :
+
+::
+
+ <filter name='test-eth0'>
+ <!-- reference the clean traffic filter to prevent
+ MAC, IP and ARP spoofing. By not providing
+ and IP address parameter, libvirt will detect the
+ IP address the VM is using. -->
+ <filterref filter='clean-traffic'/>
+
+ <!-- enable TCP port 21 (ftp-control) to be reachable -->
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='21'/>
+ </rule>
+
+ <!-- enable TCP port 20 for VM-initiated ftp data connection
+ related to an existing ftp control connection -->
+ <rule action='accept' direction='out'>
+ <tcp srcportstart='20' state='RELATED,ESTABLISHED'/>
+ </rule>
+
+ <!-- accept all packets from client on the ftp data connection -->
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='20' state='ESTABLISHED'/>
+ </rule>
+
+ <!-- enable TCP ports 22 (ssh) and 80 (http) to be reachable -->
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='22'/>
+ </rule>
+
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='80'/>
+ </rule>
+
+ <!-- enable general ICMP traffic to be initiated by the VM;
+ this includes ping traffic -->
+ <rule action='accept' direction='out'>
+ <icmp/>
+ </rule>
+
+ <!-- enable outgoing DNS lookups using UDP -->
+ <rule action='accept' direction='out'>
+ <udp dstportstart='53'/>
+ </rule>
+
+ <!-- drop all other traffic -->
+ <rule action='drop' direction='inout'>
+ <all/>
+ </rule>
+
+ </filter>
+
+Before trying out a filter using the ``RELATED`` state, you have to make sure
+that the appropriate connection tracking module has been loaded into the host's
+kernel. Depending on the version of the kernel, you must run either one of the
+following two commands before the ftp connection with the VM is established.
+
+::
+
+ modprobe nf_conntrack_ftp # where available or
+
+ modprobe ip_conntrack_ftp # if above is not available
+
+If other protocols than ftp are to be used in conjunction with the ``RELATED``
+state, their corresponding module must be loaded. Modules exist at least for the
+protocols ftp, tftp, irc, sip, sctp, and amanda.
+
+The 2nd solution makes uses the state flags of connections more than the
+previous solution did. In this solution we take advantage of the fact that the
+``NEW`` state of a connection is valid when the very first packet of a traffic
+flow is seen. Subsequently, if the very first packet of a flow is accepted, the
+flow becomes a connection and enters the ``ESTABLISHED`` state. This allows us
+to write a general rule for allowing packets of ``ESTABLISHED`` connections to
+reach the VM or be sent by the VM. We write specific rules for the very first
+packets identified by the ``NEW`` state and for which ports they are acceptable.
+All packets for ports that are not explicitly accepted will be dropped and
+therefore the connection will not go into the ``ESTABLISHED`` state and any
+subsequent packets be dropped.
+
+::
+
+ <filter name='test-eth0'>
+ <!-- reference the clean traffic filter to prevent
+ MAC, IP and ARP spoofing. By not providing
+ and IP address parameter, libvirt will detect the
+ IP address the VM is using. -->
+ <filterref filter='clean-traffic'/>
+
+ <!-- let the packets of all previously accepted connections reach the VM -->
+ <rule action='accept' direction='in'>
+ <all state='ESTABLISHED'/>
+ </rule>
+
+ <!-- let the packets of all previously accepted and related connections be sent
from the VM -->
+ <rule action='accept' direction='out'>
+ <all state='ESTABLISHED,RELATED'/>
+ </rule>
+
+ <!-- enable traffic towards port 21 (ftp), 22 (ssh) and 80 (http) -->
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='21' dstportend='22'
state='NEW'/>
+ </rule>
+
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='80' state='NEW'/>
+ </rule>
+
+ <!-- enable general ICMP traffic to be initiated by the VM;
+ this includes ping traffic -->
+ <rule action='accept' direction='out'>
+ <icmp state='NEW'/>
+ </rule>
+
+ <!-- enable outgoing DNS lookups using UDP -->
+ <rule action='accept' direction='out'>
+ <udp dstportstart='53' state='NEW'/>
+ </rule>
+
+ <!-- drop all other traffic -->
+ <rule action='drop' direction='inout'>
+ <all/>
+ </rule>
+
+ </filter>
+
+Limitations
+-----------
+
+The following sections list (current) limitations of the network filtering
+subsystem.
+
+VM Migration
+~~~~~~~~~~~~
+
+VM migration is only supported if the whole filter tree that is referenced by a
+virtual machine's top level filter is also available on the target host. The
+network filter *clean-traffic* for example should be available on all libvirt
+installations of version 0.8.1 or later and thus enable migration of VMs that
+for example reference this filter. All other custom filters must be migrated
+using higher layer software. It is outside the scope of libvirt to ensure that
+referenced filters on the source system are equivalent to those on the target
+system and vice versa.
+
+Migration must occur between libvirt installations of version 0.8.1 or later in
+order not to lose the network traffic filters associated with an interface.
+
+VLAN filtering on Linux
+~~~~~~~~~~~~~~~~~~~~~~~
+
+VLAN (802.1Q) packets, if sent by a virtual machine, cannot be filtered with
+rules for protocol IDs ``arp``, ``rarp``, ``ipv4`` and ``ipv6`` but only with
+protocol IDs ``mac`` and ``vlan``. Therefore, the example filter
+``clean-traffic`` will not work as expected.
diff --git a/docs/meson.build b/docs/meson.build
index a8e360c8a4..0458eea683 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -21,7 +21,6 @@ docs_html_in_files = [
'formatcaps',
'formatnetwork',
'formatnode',
- 'formatnwfilter',
'index',
'remote',
'storage',
@@ -74,6 +73,7 @@ docs_rst_files = [
'formatdomain',
'formatdomaincaps',
'formatnetworkport',
+ 'formatnwfilter',
'formatsecret',
'formatsnapshot',
'formatstorage',
--
2.35.1