Hello,
I am currently investigating the possibility to implement MAC address
based filtering in libvirt and was wondering if there is any related
effort going on and what people in general would think about that.
Here is a description of my current prototype implementation:
I have a small setup of two guests and a network:
Guest1:
root@stenzel-desktop:/etc/libvirt/qemu# cat build1.xml
<domain type='kvm'>
<name>build1</name>
...
<interface type='network'>
<mac address='D0:0F:D0:0F:02:01'/>
<source network='mynet'/>
<model type='virtio' />
</interface>
...
</domain>
Guest2:
root@stenzel-desktop:/etc/libvirt/qemu# cat build2.xml
<domain type='kvm'>
<name>build2</name>
...
<interface type='network'>
<mac address='D0:0F:D0:0F:02:02'/>
<source network='mynet'/>
<model type='virtio' />
</interface>
...
</domain>
and the network to which I added a new XML element "filter" with
attribute "mac", which switches on the MAC address filtering:
root@stenzel-desktop:/etc/libvirt/qemu# cat networks/mynet.xml
<network>
<name>mynet</name>
<uuid>920debe0-c3ef-4395-8241-ee82d4b49c2d</uuid>
<bridge name="br%d" stp="off"/>
<filter mac="on"/>
</network>
the "filter" element is evaluated at startup of libvirtd and a generic
ebtables rules is generated (all frames are dropped):
stenzel@stenzel-desktop:~/projects/vsn/libvirt$ sudo ebtables -L
Bridge table: filter
...
Bridge chain: FORWARD, entries: 0, policy: DROP
...
When starting up guest1, ...
stenzel@stenzel-desktop:~/projects/vsn/libvirt$ sudo virsh start build1
Domain build1 started
... an ebtables rule is generated to allow its mac address on the its
interface:
stenzel@stenzel-desktop:~/projects/vsn/libvirt$ sudo ebtables -L
...
Bridge chain: FORWARD, entries: 1, policy: DROP
-s d0:f:d0:f:2:1 -i vnet0 -j ACCEPT
...
the same happens when starting up the second guest:
stenzel@stenzel-desktop:~/projects/vsn/libvirt$ sudo virsh start build2
Domain build2 started
stenzel@stenzel-desktop:~/projects/vsn/libvirt$ sudo ebtables -L
...
Bridge chain: FORWARD, entries: 2, policy: DROP
-s d0:f:d0:f:2:2 -i vnet1 -j ACCEPT
-s d0:f:d0:f:2:1 -i vnet0 -j ACCEPT
...
so the two guests are allowed to communicate.
After destroying the two guests, the corresponding ebtables rules are
removed:
stenzel@stenzel-desktop:~/projects/vsn/libvirt$ sudo virsh destroy
build2
Domain build2 destroyed
stenzel@stenzel-desktop:~/projects/vsn/libvirt$ sudo ebtables -L
...
Bridge chain: FORWARD, entries: 1, policy: DROP
-s d0:f:d0:f:2:1 -i vnet0 -j ACCEPT
...
stenzel@stenzel-desktop:~/projects/vsn/libvirt$ sudo virsh destroy
build1
Domain build1 destroyed
stenzel@stenzel-desktop:~/projects/vsn/libvirt$ sudo ebtables -L
...
Bridge chain: FORWARD, entries: 0, policy: DROP
...
The current prototype implementation is based on the existing iptables
wrapper in libvirt. I basically cloned the iptables wrapper to an
ebtables wrapper and did some ebtables specific adjustments. There are
currenlty four occasions when the ebtables wrapper is called:
- when creating the network
- when adding a guest to the network
- when removing a guest from the network
- when destroying the network (currently not implemented)
These calls can be augmented to also do for example tagged vlan and
protocol filtering.
Configuring the filter rules via virsh is also an option.
Comments are appreciated.
--
Best regards,
Gerhard Stenzel,
-----------------------------------------------------------------------------------------------------------------------------------
IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Martin Jetter
Geschäftsführung: Erich Baier
Sitz der Gesellschaft: Böblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294