Hi,
I'm trying to configure nwfilter for KVM, but so far I haven't managed
to figure out a working configuration.
Network setup: The dom0 (Debian 7.1, kernel 3.2.46-1, libvirt 0.9.12) is
connected via eth0, part of the external subnet 192.168.17.0/24, and has
an additional subnet 192.168.128.160/28 routed to its main address
192.168.17.125.
The host's subnet is configured as bridge in virsh:
> <network>
> <name>foo</name>
> <forward dev='eth0' mode='route'>
> <interface dev='eth0'/>
> </forward>
> <bridge name='foo-br0' stp='off' delay='0' />
> <ip address='192.168.128.161' netmask='255.255.255.240'>
> </ip>
> </network>
The domU is configured to use this bridge (static IP configured in DomU):
> <interface type='network'>
> <source network='foo'/>
> <target dev='vnet0'/>
> <model type='virtio'/>
> <filterref filter='test-eth0'>
> <parameter name='CTRL_IP_LEARNING' value='none'/>
> <parameter name='IP' value='192.168.128.162'/>
> </filterref>
> <alias name='net0'/>
> <address type='pci' domain='0x0000' bus='0x00'
slot='0x03' function='0x0'/>
> </interface>
With an empty filter, connectivity is working fine. Now, if I add the
example ruleset suggested in the documentation (
http://libvirt.org/formatnwfilter.html#nwfwriteexample ), *incoming*
ICMP works (but not outgoing), and inbound SSH traffic is blocked,
together with outbound DNS.
The linked rules produce the following iptables chains:
> Chain INPUT (policy ACCEPT)
> target prot opt source destination
> libvirt-host-in all -- 0.0.0.0/0 0.0.0.0/0
> ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:53
> ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:53
> ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:67
> ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:67
>
> Chain FORWARD (policy ACCEPT)
> target prot opt source destination
> libvirt-in all -- 0.0.0.0/0 0.0.0.0/0
> libvirt-out all -- 0.0.0.0/0 0.0.0.0/0
> libvirt-in-post all -- 0.0.0.0/0 0.0.0.0/0
> ACCEPT all -- 0.0.0.0/0 192.168.128.160/28
> ACCEPT all -- 192.168.128.160/28 0.0.0.0/0
> ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
> REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with
icmp-port-unreachable
> REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with
icmp-port-unreachable
>
> Chain OUTPUT (policy ACCEPT)
> target prot opt source destination
>
> Chain FI-vnet0 (1 references)
> target prot opt source destination
> RETURN tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:22 state
ESTABLISHED ctdir ORIGINAL
> RETURN tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:80 state
ESTABLISHED ctdir ORIGINAL
> RETURN icmp -- 0.0.0.0/0 0.0.0.0/0 state NEW,ESTABLISHED
ctdir REPLY
> RETURN udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:53 state
NEW,ESTABLISHED ctdir REPLY
> DROP all -- 0.0.0.0/0 0.0.0.0/0
>
> Chain FO-vnet0 (1 references)
> target prot opt source destination
> ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state
NEW,ESTABLISHED ctdir REPLY
> ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 state
NEW,ESTABLISHED ctdir REPLY
> ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED ctdir
ORIGINAL
> ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp spt:53 state
ESTABLISHED ctdir ORIGINAL
> DROP all -- 0.0.0.0/0 0.0.0.0/0
>
> Chain HI-vnet0 (1 references)
> target prot opt source destination
> RETURN tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:22 state
ESTABLISHED ctdir ORIGINAL
> RETURN tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:80 state
ESTABLISHED ctdir ORIGINAL
> RETURN icmp -- 0.0.0.0/0 0.0.0.0/0 state NEW,ESTABLISHED
ctdir REPLY
> RETURN udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:53 state
NEW,ESTABLISHED ctdir REPLY
> DROP all -- 0.0.0.0/0 0.0.0.0/0
>
> Chain libvirt-host-in (1 references)
> target prot opt source destination
> HI-vnet0 all -- 0.0.0.0/0 0.0.0.0/0 [goto] PHYSDEV match
--physdev-in vnet0
>
> Chain libvirt-in (1 references)
> target prot opt source destination
> FI-vnet0 all -- 0.0.0.0/0 0.0.0.0/0 [goto] PHYSDEV match
--physdev-in vnet0
>
> Chain libvirt-in-post (1 references)
> target prot opt source destination
> ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 PHYSDEV match
--physdev-in vnet0
>
> Chain libvirt-out (1 references)
> target prot opt source destination
> FO-vnet0 all -- 0.0.0.0/0 0.0.0.0/0 [goto] PHYSDEV match
--physdev-out vnet0
I've tried fidgeting with the configuration (direction inout instead of
in/out, etc.), but I didn't find a setup that works as intended. What am
I missing?
Depending on the settings of your Linux distribution you may need to
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
to enable iptables filtering for traffic traversing the bridge. Does
this get it to work?
Stefan