防火墙
防火墙是避免网络信息基础设施免受复杂网络环境中安全攻击的必要设施。高效的防火墙则更需要实时跟踪来往于不同网络设备间的各类网络连接,即“有状态防火墙”。对于实际的硬件物理网络基础设施需要防火墙,对于虚拟网络设备,openstack在这样的云平台亦需要同样的防火墙进行网络保护。
在Openstack中,防火墙由“Security Group”和“FWaas”两大服务组成。其中Security Group在port级别提供对VM网络通信的访问控制。而Fwaas则运行在vrouter上在subnet的边界控制子网间的L3和L4流量。简而言之,“Security Group”保护port,“FWaas”保护subnet。
Openstack下的“Security Group”不仅保护租户VM,使其避免受到无价值数据流的影响,同时还限制租户VM,避免其主动发起ARP spoofing,DHCP spoofing等不安全网络行为。实际定位到底层,“Security Group”可以通过iptables和ovs 流表两种方式实现。本文将重点讲述基于OVS 流表实现的安全组(Security Group)。
以下内容基于Pike版Openstack
OVS Conntrack 概述
无状态的防火墙只能通过静态的网络元组来过滤,阻拦,放行数据报文。这里的静态网络元组包括IP地址,端口,网络协议。无状态防火墙并不关心当前网络连接处于何种状态。相较于无状态防火墙,有状态防火墙增加了对当前网络连接状态的识别,同步使用静态的网络元祖对数据报文进行过滤,阻拦,放行。增加的识别标志在一定程度上消耗系统资源,但更加严格的规则却更能保障网络更加安全。
网络连接状态的识别通常是由CT模块(connection tracker)实现的。在linux内核中,CT是由conntrack实现。从OVS 2.5起,开始支持conntrack,并在openflow中体现相关CT状态的识别与处理。Openstack则从M版开始,使用OVS的新特性,来实现“有状态防火墙”中的“Security Group”功能。
从OVS提供的CT功能简图2来看,相对于原有流表处理,无非增加了提交连接数据包进入CT模块,标记连接状态,用于后续流表查询连接状态,匹配数据报文进行指定处理的过程。
图3列举了OVS实现的openflow 中新增的CT相关字段。(有删减,仅列举了后续流表分析时用到的字段)
这里需要重点解释下rel,inv,zone=value(ct_zone)这三条项目。
rel,即related。这里举个典型的例子描述下related数据包。当VM A ping 某外网IP地址B,发出一个ICMP Echo Request报文,当该Request报文到达路由器时,路由器判定外网IP地址不可达,回送一个ICMP Network Unreachable报文。那么这个ICMP Network Unreachable报文与先前发出的ICMP Echo Request报文就是存在related关系。因为对于ICMP Echo Request报文而言,只有ICMP Echo Reply报文是与它存在reply(rpl)关系的。
inv,即invalid。如果存在下述几种情况:linux内核中L3/L4协议处理程序不可用或者未加载;nf_conntrack_ipv4或nf_conntrack_ipv6模块没有加载;L3/L4协议判定数据包非法;数据包本身报文长度与协议本身不匹配,那么该数据包将被置位inv。例:UDP奇数字节报文,被某型网卡驱动末位padding 0,但未增加IP头部内长度信息,也未增加UDP头部内长度信息,导致该报文在OVS CT中判定inv,最终drop导致通信与预期不符。
通过查询系统连接跟踪条目,如图4所示,可知协议类型,源IP,目的IP,源端口,目的端口这5项元组共同构成了识别一条连接跟踪的索引。在openstack环境中,会有一定概率存在不同项目下的VM,使用相同网段的子网IP,且恰好被调度到同一台宿主机。在极其偶然的情况下这两台VM恰好使用同样的协议,同样的源端口去访问同一个目的IP的同一个目的端口。如果不加任何隔离处理必将导致连接跟踪条目的重叠冲突。
zone=value(ct_zone),很好的处理了这种冲突。zone可以称之为隔离连接跟踪条目的namespace。不同zone中的连接跟踪条目即使协议类型,源IP,目的IP,源端口,目的端口完全一致,也不会存在冲突。在Security Group的OVS驱动中,每条连接在提交至CT模块时,zone均被指定为该网络连接所处network在本节点上local vlan tag。(此处network为neutron下的network模型)
安全组相关特性
当一个port不添加任何安全组信息时,只有匹配该port的ARP报文,DHCP报文,和已建立的连接才会被初始化时下发的流表规则放行。当然,关闭port的port_security_enabled属性可以屏蔽anti ARP spoofing和anti DHCP spoofing流表规则的下发。Neutron中的一些特殊类型port,例如DHCP port,gateway port等被认为是security port,自然也是关闭port_security_enabled属性。如果需要在port上允许其他自定义的IP,MAC网络包的流通,也可以通过port的allowed_address_pairs添加相应信息。被添加的IP,MAC会在下发安全组规则时作为可信任的地址信息被填入流表。
当安全组A的一条ingress规则通过remote group id指向了安全组B,那么代表着所有通过安全组B的流量才能匹配这条ingress规则。也即意味着只有绑定了绑定了安全组B的port发出的流量才能匹配这条ingress规则。
OVS安全组流表分析
以“目的IP192.168.0.0/24目标端口22协议TCP出向放行”,“任意IP目标端口80协议TCP入向放行”两条安全组规则为例,分析流量具体经过的流表,如下图5所示。
OVS与iptables对比
不使用OVS情况下,Linux内核的连接跟踪模块仅限于IP协议层(L3)的Linux内核防火墙(iptables)使用。而实际VM流量从tap口流出时已经是L2层报文。因此额外添加了一层Linux bridge,配合ebtables,处理原有L2层报文后上送至iptables,从而在iptables中执行连接跟踪,所有Security Group规则也被转换成具体的iptables规则,配合连接状态,实现状态防火墙的功能。经过筛选处理后的报文再通过veth从Linux bridge流向br-int,执行外部交换与路由。
对比OVS与iptables实现的状态防火墙,多一层虚拟网络设备就多一次处理,这里必然导致多一重性能损耗。如图7所示,在Security Group 规则数量庞大的情况下,性能消耗则更加明显。
参考链接
1.http://www.openvswitch.org/support/dist-docs/ovs-ofctl.8.txt
2.http://www.openvswitch.org//support/dist-docs/ovs-fields.7.txt
3.http://docs.openvswitch.org/en/latest/tutorials/ovs-conntrack/
4.https://redhatstackblog.redhat.com/2016/07/22/how-connection-tracking-in-open-vswitch-helps-openstack-performance/
5.http://www.openvswitch.org/support/ovscon2014/17/1030-conntrack_nat.pdf
6. https://docs.openstack.org/neutron/pike/contributor/internals/openvswitch_firewall.html
7. https://zhuanlan.zhihu.com/p/25089778