之前的文章<<VMware vSphere虚拟网络防护>>介绍了VMware vSphere的网络基础知识和南北向网络安全防护的思路。南北向网络防护是在网络边界进行安全隔离和流量过滤。那么怎样对网络内部的东西向流量如何进行安全防护呢?VMware NSX提供了东西向安全防护的能力。不过NSX的License价格很贵,很多企业并没有购买意愿。本文介绍在非NSX环境中只依赖vSphere提供的能力将流量引至虚拟安全设备实现东西向网络安全防护的思路。
我们当前一台ESXi上的环境如图:
我们在10.187.160.40
上使用PING访问10.187.160.41
。由于两IP为同一子网,首先通过ARP广播确定10.187.160.41
对应的MAC地址,然后由虚拟交换机vswitch0
将ICMP数据包转发给10.187.160.41
。为了进行东西向安全防护,我们可以将流量引至虚拟安全设备,由虚拟安全设备执行安全策略。对于虚拟交换机OpenvSwitch, 我们可以使用OpenFlow协议实现引流,但是vSphere的虚拟交换机不具备这种能力,因而不能使用这种方案。<<VMware vSphere虚拟网络防护>>中我们介绍了vSphere虚拟交换机的基础知识。它支持端口组粒度的VLAN设置,我们可以基于不同VLAN之间网络的二层网络隔离性来实现引流。
下面来看具体实现。我们在ESXi主机上新建虚拟交换机vss_internal
, 在vss_internal
上创建VLAN TAG分别为100
和200
的端口组vlan100
和vlan200
。10.187.160.40
的网卡接入vlan100
, 10.187.160.41
的网卡接入vlan200
。我们在新建的虚拟交换机vss_internal
和原有的虚拟交换机vswitch0上
各创建一个TAG为4095
的TRUNK端口组,并开启其混杂模式
, MAC地址更改
, 伪传输
等三个安全选项。我们的虚拟安全设备的两个网络接口分别接入其中。在接入vss_internal
的网络接口上创建两个TAG分别为100
和200
的VLAN子接口。在虚拟安全设备上创建一个OVS bridge,并将两个VLAN子接口和接入vswitch0
的网络接口接入OVS bridge。整体结构如下:
我们来分析10.187.160.40
访问10.187.160.41
的流程。首先10.187.160.40
的接口发送ARP广播查询10.187.10.41
的MAC地址。因为两个接口分属不同VLAN,虚拟交换机vss_internal
不会将ARP数据包转发至10.187.160.41
的端口。由于虚拟安全设备的ens192
接口的端口组为trunk, 因而它会收到上述ARP数据包。子接口vlan100
将VLAN TAG剥去,并发送到ovs_bridge
,ovs_bridge
按正常广播逻辑将数据包发送到vlan200
子接口。vlan200
子接口给数据包添加VLAN TAG将数据包由ens192
发出,再次回到虚拟交换机vss_internal
。此时数据包的VLAN TAG为200
,因而vss_internal
将数据包转发至10.187.160.41
所在接口。10.187.160.41
发送ARP响应,此时数据包的目的MAC地址为10.187.160.40
的MAC地址。数据包到达vss_internal
之后,由于VLAN不同,vss_internal
并不会将数据包转发至10.187.160.40
。但是由于ens192
所在的端口组开启了混杂模式且为trunk模式,ens192
会收到该数据包。子接口vlan200
剥去VLAN后,将数据包发送至ovs_bridge
。ovs_bridge
会学习到MAC与PORT的对应关系,因而会将数据包发送至vlan100
。子接口vlan100
添加VLAN TAG将数据包发送回vss_internal
。vss_internal
再将数据包转发至10.187.160.40
。ARP请求与响应的流程结束。ICMP的请求与回应的流程与ARP响应流程相似。
ICMP请求包路径如图:
下面看一下10.187.160.40
访问ESXi主机外的IP(如网关IP:10.187.160.1)的情形。ARP广播数据包到达ovs_bridge
后,也会从ens160
接口发出,vswitch0
会将广播包由uplink发送至物理交换机。10.187.160.1
的接口返回ARP响应后,再次从uplink进入vswitch0
, vswitch0
将数据包发送至ens160
。ens160
将数据包发送到ovs_bridge
。ovs_bridge
根据学习到MAC与PORT的对应关系,将数据包发送至vlan100
。后续流程与上述流程一致。接下来的ICMP请求包流程如下图所示:
下面来看虚拟安全设备上的具体操作实现。
首先创建两个VLAN子接口:
1 | ip link add link ens192 name ens192.100 type vlan id 100 |
创建OVS bridge, 并连接相应接口:
1 | ovs-vsctl add-br ovsbr1 |
如果我们需要完成10.187.160.40
和10.187.160.41
之间的访问控制,如何实现呢?可以有两种方式:
- 因为所有流量都要经过OVS bridge, 我们可以直接通过OpenFlow流表来添加ACL规则。
- 参考OpenStack安全组实现,在OVS bridge和子接间添加一个Linux Bridge,然后由iptables实现访问控制。
首先介绍直接通过OpenFlow流表实现。
默认流表如下:
1 | [root@localhost ~]# ovs-ofctl dump-flows ovsbr1 |
我们添加一条流将从10.187.160.40访问10.187.160.41的ICMP数据包丢弃:
1 | ovs-ofctl add-flow ovsbr1 "table=0, priority=10, dl_type=0x0800, nw_proto=0x01, nw_src=10.187.160.40, nw_dst=10.187.160.41, actions=drop” |
添加后的流表结果如下:
1 | [root@localhost ~]# ovs-ofctl dump-flows ovsbr1 |
随后再删除该流:
1 | ovs-ofctl del-flows ovsbr1 “icmp" |
我们查看10.187.160.40
上的测试结果, 添加流时数据包被丢弃了,删除流后,访问再次正常。
下面介绍基于iptables实现。
首先开启Linux bridge上的iptables:
1 | echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables |
接下来调整网络结构,在OVS bridge与VLAN子接口之间添加Linux Bridge。
1 | ovs-vsctl del-port ovsbr1 ens192.100 |
查看OVS bridge结构:
1 | [root@localhost ~]# ovs-vsctl show |
查看Linux Bridge结构:
1 | [root@localhost ~]# brctl show |
调整后结构如图:
添加访问控制规则, 并查看:
1 | [root@localhost ~]# iptables -A FORWARD -p icmp -m physdev --physdev-is-bridged --physdev-out ens192.200 -s 10.187.160.40/32 -d 10.187.160.41/32 -j DROP |
接着再清空规则:
1 | iptables -F |
从结果上可以看到, 添加规则时数据包被丢弃了,清空规则后访问恢复:
上述方案基于原来vSphere环境上没有配置VLAN,若是原来ESXi主机上就有多个VLAN,则需要创建多个OVS bridge和在ens160接口上创建子接口来完成VLAN区分,架构如图所示:
原属于同一个VLAN但分布在不同ESXi的网络接口在这种结构的内部虚拟交换机上可以具备不同的VLAN TAG,只需要虚拟安全设备接入vswitch0的接口上的子接口VLAN一致。此时网络结构与数据包路径如图:
除了使用VLAN区分不同的网络,还可以使用VXLAN、GRE等overlay机制构建隔离的逻辑网络。可以参考OpenStack的Neutron实现中的br-int
与br-tun
实现。本文不再详细说明。
VMware vSphere提供了相应API来操作端口组,修改虚拟机的网络接口所属端口组等,可以利用这些API自动化完成本文上述的网络结构改动与构建。