一般来说,使用KVM创建虚拟机,都会有虚拟机之间通信的需求,KVM的四种网络模式也都默认允许同一网段的虚拟机之间互通。如果有特殊需求,需要禁止虚拟机之间的通信,该如何配置?
KVM四种网络模式
首先隔离模式,相当于Vmware/Vbox 仅主机模式,VM之间可通信,VM与宿主可通信,VM与外部不可通信
NAT模式,VM之间可通信,VM与宿主可通信,VM可访问外部,外部访问VM需要做端口转发
桥接模式,VM之间可通信,VM与宿主可通信,VM可访问外部,外部可访问VM。一般桥接模式下VM网段与宿主机同段。
路由模式,VM之间可通信,VM与宿主可通信,VM可访问外部,外部可访问VM。路由模式下VM网段可以与宿主机不同端,外部需要配置路由才能访问VM
iptables解决方案
搜了资料,有人说可以用iptables实现,原理如下
NAT模式下,宿主机有一块网卡virbr0。针对virbr0,在iptables中FORWARD链限制同网段互访
1 | -A FORWARD -i virbr0 -s 192.168.1.0/24 -d 192.168.1.0/24 -j DROP |
我尝试了下,不知为何不生效,也许因为虚拟机互访实际流量并不经过virbr0?尝试将FORWARD链改为INPUT链也是不生效。后来放弃iptables,改用nwfilter。
nwfilter解决方案
nwfilter是kvm自带的网络流量工具,可以精确控制每一块vm网卡。上面iptables的方案是在宿主机上做策略,而nwfilter是对每一个vm做策略,nwfilter的策略可以应用在多个vm上。
总的来说nwfilter的用法就是,定义nwfilter策略,生效策略,应用策略。下面以NAT模式下禁止虚拟机之间互通为例介绍nwfilter解决方案
定义策略
在/etc/libvirt/nwfilter下建立xml文件
1 | vi /etc/libvir/nwfilter/deny-inter.xml |
写入规则
1 | <filter name='deny-inter' chain='ipv4' priority='-700'> |
其中,
这里只采用了ipv4的链,只需要对ip包进行过滤
注意uuid不要与现有的相同
每条规则后的优先级越小越优,如果优先级相同优先匹配前面的规则
这里的规则将来是应用在虚拟机上,所以in/out是针对虚拟机网卡的
第一条规则是为了保证dhcp正常工作,这里用in方向策略会方便一点,因为dhcp discover包发出去是广播,dhcp offer包回来是单播,in方向只需要允许宿主机的单播包就可以了
更多nwfilter的详细用法可以参考VirtualNetworking - Libvirt Wiki
生效策略
1 | virsh nwfilter-define deny-inter.xml #生效策略 |
应用策略
编辑虚拟机配置文件
1 | virsh edit vm01 |
找到
1 | <interface type='network'> |
最后重启虚拟机,VM之间无法ping通,VM与宿主机可通,VM ping 外面可通。