我正在尝试为 KVM 配置 nwfilter,但到目前为止我还没有找到可行的配置。
网络设置:dom0(Debian 7.1,内核 3.2.46-1,libvirt 0.9.12)通过 eth0 连接,属于外部子网 192.168.17.0/24 的一部分,并且有一个附加子网 192.168.128.160/28 路由到其主地址 192.168.17.125。
主机的子网在 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>
domU 配置为使用此桥(在 DomU 中配置静态 IP):
<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>
使用空过滤器时,连接工作正常。现在,如果我添加文档中建议的示例规则集( http://libvirt.org/formatnwfilter.html#nwfwriteexample),传入 ICMP 可以工作(但不能传出),并且入站 SSH 流量和出站 DNS 都被阻止。
链接的规则产生以下 iptables 链:
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
如果我尝试文档中第二个示例中的第二个过滤器集( http://libvirt.org/formatnwfilter.html#nwfwriteexample2nd ),由此产生的防火墙规则就更加没有意义了。
引用它应该做的事情:
- 仅打开虚拟机接口的 TCP 端口 22 和 80
- 允许虚拟机从接口发送 ping 流量,但不允许虚拟机在该接口上被 ping
- 允许虚拟机进行 DNS 查找(UDP 端口 53)
- 启用 ftp 服务器(主动模式)在虚拟机内运行
它能做什么:
- 打开所有传入端口
- 允许对虚拟机进行 ping
- 阻止所有传出流量(ICMP 除外,但我怀疑这只是因为 ICMP 过滤根本不起作用,见上文)
- 防止 ftp 服务器以主动模式运行
我没有修改任何包含的 nwfilter 规则集或网络堆栈的任何其他部分。如何让 nwfilter 正常运行?