在云计算中,虚拟网络中的安全需要回答以下几个基本问题。
- 如何对租户网络进行隔离?
- 如何控制用户对网络中资源的访问?
- 如何实现对网络管理的安全控制?
关于租户网络隔离,云计算中的一个重要概念是多租户的概念,即多个租户共享或者独占云中的资源。对云中的网络资源也不例外,每个租户需要有自己的网络、网段、路由和IP,这些网络构建于云的物理网络基础设施之上,在每个租户之间相互隔离。为了实现这种网络的隔离,一般采用VLAN或者基于overlay的虚拟网络进行隔离。
关于网络管理的安全控制,需要结合OpenStack的权限管理机制(Keystone)来看,保证用户对于网络管理的访问与使用是可控的。
Neutron是如何控制用户对网络中资源的访问,主要是OpneStack中两个很重要的功能,一个是安全组(Security Group)的功能,一个是防火墙即服务(FWaaS)的功能。
目录
iptables基础
在Linux系统中,对于防火墙的实现一般分为包过滤防火墙、TCP-Wrapper即程序管控、代理服务器等几种方式。其中,iptables作为一种基于包过滤方式的防火墙工具,在实际中应用非常广泛,是非常重要的安全工具。
iptables防火墙应该称为netfilter/iptables防火墙。
iptables命令定义包过滤的规则,而这些规则的读取和执行,是由内核空间中的netfilter来实现的。顾名思义,netfilter是放在内核中的网络过滤器,而它控制的位置必须是TCP/IP协议栈经过的地方。在netfilter/iptables框架中,在内核空间中一共定义了以下5个位置:
- 数据包刚刚进入网络层的位置。
- 经过路由判断,数据包从内核流入本机用户空间的位置。
- 数据包从本机用户空间进程发出的位置,后接路由判断出口的网络接口。
- 经路由判断,数据包不进入本机用户空间,只是进行转发的位置。
- 数据包将通过网络接口出去的位置。
相应的,netfilter在这5个位置定义了5个钩子函数,也叫5个规则链:
- PREROUTING 在这里处理目的地址转换。
- INPUT 在这里处理INPUT包过滤。
- OUTPUT 在这里处理OUTPUT包过滤。
- FORWARD 在这里处理FORWARD包过滤。
- POSTROUTING 在这里处理源地址转换。
任何经过本机的数据包,都会经过这5个规则链上的几个位置。一般来讲,数据包需要发给本机进程的,会通过PREROUTING –> OUTPUT –> POSTROUTING这条链;数据包只在本机进行转发的,会通过PREROUTING –> FORWARD –> POSTROUTING这条链。
iptables实际上指的是整个netfilter/iptables框架中,运行在用户空间的应用软件。它通过控制内核空间的netfilter模块,来管理网络数据包的流动与传送,其中最核心的是定义iptables策略。
iptales策略是由一组有序的规则建立的,告诉内核怎样处理数据包。而规则用于一个表的一个链,链是一个规则集。
iptables的概念从大到小是:iptables –> 表 –> 链 –> 规则。
表
首先,iptables定义了4个表来定义、区分各种不同的工作功能和处理方式。
Filter表
Filter表用于一般的数据包的过滤。其中包括3个链:
- INPUT 在此链中可添加对进入到用户空间的包的过滤。
- OUTPUT 在此链中可添加从用户空间发出去的包的过滤。
- FORWARD 在此链中可添加要转发的包的过滤。
NAT表
NAT表用于网络地址的转换,其中包括3个链:
- PREROUTING 在此链中可添加目的地址转换的规则(DNAT)。
- POSTROUTING 在此链中可添加源地址转换的规则(SNAT)。
- INPUT 在此链中可添加对进入到用户空间的包的过滤。
- OUTPUT 在此链中可添加从用户空间发出去的包的过滤。
Mangle表
Mangle表用于修改数据包的原数据,一般用于防火墙标记。Mangle表包含全部5个规则链,即PREROUTING、OUTPUT、FORWARD、INPUT和POSTROUTING。
Raw表
Raw表是用于配置免除的,包含PREROUTING和OUTPUT两个内置链。
自定义链
创建新链
1
iptables -t nat -N my_chain
添加规则
1
iptables -t filter -A my_chain -s 192.168.2.10 -j DROP
使用自定义链
1
iptables -t filter -A INPUT -j my_chain
iptables命令
1 | iptables [-t table] command [chain] [rules] [-j target] |
在iptables的一个链中定义规则时,都需要包含匹配规则和target。前者决定是否匹配该条规则,后者告诉iptables对于符合规则的数据包应该采取什么动作。
- source(-s),匹配源IP地址。
- destination(-d),匹配目的IP地址。
- protocol(-p),匹配协议。
- in-interface(-i),流入接口(如eth0)。
- out-interface(-o),流出接口。
target,即动作,它们用于在数据包匹配一条规则时触发的一个动作。
- ACCEPT,允许数据包通过。
- DROP,丢弃数据包,不响应报文。
- REJECT,丢弃数据包,响应报文。
- LOG,记录数据包信息都syslog。
- RETURN,在调用链中继续处理数据包。
Neutron中的安全组
Security Group(安全组)运行在计算节点,对进入虚拟机的流量进行控制。
- 过滤进入到计算节点上虚拟机的流量。
- 过滤从虚拟机出来的流量。
- 过滤虚拟机之间的流量。
Neutron中的自定义链
Neutron使用了自定义链,分为包装链和非包装链两类,区别在于是否对链表添加组件名重新包装(目的是为了不和系统中其他应用设置的防火墙规则混淆)。
包装链
链名需要通过组件名重新包装,如neutron-l3-agent组件定义的OUTPUT链叫neutron-l3-agent-OUTPUT,也意味着,Neutron不会用内置链OUTPUT,它必须跳转到对应的包装链(iptables -t filter OUTPUT -j neutron l3-agent-OUTPUT)非包装链
链名没有用组件名包装,例如,neutron-filter-top就是位于FORWARD和OUTPUT顶部的非包装链,用于在不同OpenStack组件共享的链。
- neutron-filter-top链的内容是:
- iptables -t filter -N neutron-filter-top
- iptables -t filter -A FORWARD -j neutron-filter-top
- iptables -t filter -A OUTPUT -j neutron-filter-top
- 添加一个包装链neutron-l3-agent-local,接管neutron-filter-top链:
- iptables -t filter -N neutron-l3-agent-local
- iptables -t filter -A neutron-filter-top -j neutron-l3-agent-local
- 对于IPv4、IPv6,Neutron为filter和nat两张表里的INPUT、FORWARD、OUTPUT三个内置链都定义了相应的包装链:
- iptables -t filter -A INPUT -j neutron-l3-agent-INPUT
- iptables -t filter -FORWARD -j neutron-l3-agent-FORWARD
- iptables -t filter -A OUTPUT -j neutron-l3-agent-OUTPUT
- 在POSTROUTING链之后还定义了一个名为neutron-postrouting-bottom的非包装类:
- iptables -t filter -N neutron-postrouting-bottom
- iptables -t filter -A POSTROUTING -j neutron-postrouting-bottom
- 在neutron-postrouting-bottom链后再定义了两个snat(neutron-l3-agent-snat)的包装类:
- iptables -t filter -N neutron-l3-agent-snat
- iptables -t filter -A neutron-postrouting-bottom -j neutron-l3-agent-snat
- iptables -t filter N neutron-l3-agent-float-snat
- iptables -t filter -A neutron-postrouting-bottom -j neutron-l3-agent-float-snat
- 最后定义sg-fallback包装链:
- iptables -t filter -N neutron-l3-agent-sg-fallback
- iptables -t filter -A neutron-l3-agent-sg-fallback -g DROP
虚拟机的链和规则
配置使用Neutron中的Security Group
/etc/neutron/neutron.conf
1
2
3
4
5
6
7
8
9
10# Rocky
service_plugins = firewall
[service_providers]
# ...
service_provider = FIREWALL:Iptables:neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver:default
[fwaas]
driver = iptables
enabled = True/etc/neutron/l3_agent.ini
1
2[AGENT]
extensions = fwaas
使用步骤。
TODO
1 | ``` |
Neutron中的防火墙
安全组由一系列的iptables rules组成,rule都是针对source/dest ip以及tcp port的,它不能像下一代的防火墙一样来表达应用特性像audited rules,也不能提供边缘防火墙的特性。所以Neutron推出了FWaaS服务。在FWaaS中,租户可以创建多个Firewall instances,而每一个virtual firewall instances和多个Firewall Policies关联,每个firewall policies由多个Firewall Rules按序组成。不能直接应用一个rule,它必须先加入到一个policy中,因为它需要先审计。
TODO
Neutron L3 agent运行在getaway host上,它通过Linux命名空间特性实例化多个neutron router,一个租户能用多个router。router中qr-xxx虚拟接口用于和租户网络相连接,qg-xxx虚拟接口用于跟外部网络相连接,防火墙服务应该是过滤出入租户网络的所有流量,所以firewall policy应该是应用在qr-xxx虚拟接口上(iptables出口规则中添加“-o qr-xxx”即可,入口规则添加“-i qr-xxx”即可),如果对所有租户网络都使用,可以运用在qg-xxx接口上(一组像上面的qr-xxx接口可以组成一个zone)。所以FWaaS不像Security Group那样运行在计算节点上,而是运行在网络节点上。
代码实现中将会有4个chains,出和如各一个,IPv4和IPv6各一个:
TODO
有状态的防火墙和基于OVS流规则的防火墙
上面讲的防火墙都是基于iptables来实现的,防火墙也可以基于OpenvSwitch流规则来实现。iptables规则无法直接应用到OVS网桥上,所以虚拟机的tap网卡并没有直接plug到OVS网桥br-int上,而是中间又创建出一个Linux网桥qbr,在OVS网桥br-int和Linux网桥qbr之间采用了qvo和qbr这对veth peers设备连接。Linux peers设备的性能比较差,基于OVS流规则的防火墙很有必要。
有状态的防火墙
例如,允许内网用户访问公网的Web服务,如果采用包过滤的无状态的防火墙技术,需要按照下面设置。
TODO
因为本地的端口是随机生成的,把1024到65535的端口都打开是非常危险的,所以有一些防火墙又根据TCP连接中的ACL为来决定数据包进出,但这容易引发拒绝服务DoS攻击,何况UDP没有ACL标志位。
有状态的防火墙,只需要上述的防火墙规则1,不需要规则2(状态防火墙之定义出站规则,不需要定义入站规则)。当用户打开浏览器访问那个Web服务时,当数据包到防火墙时,状态检测引擎会检测到这是一个发起连接的初始数据包(由SYN标志),然后它就会把这个数据包中的信息与防火墙规则作比较,如果没有相应规则允许,防火墙就会拒绝这次连接。
当然在这里它发现有一条规则允许访问外部Web服务,于是它允许数据包外出并且在状态表中新建一条会话,通常这条会话会包括此连接的源地址、源端口、目标地址、目标端口、连接时间等信息,对于TCP连接(只针对TCP,对UDP创建模拟的虚拟连接,对ICMP无效),它还会包含序列号和标志位等信息。当后续数据包到达时,如果这个数据包不包含SYN标志,也就是说这个数据包不是发起一个新的连接时,状态检测引擎就会把它的信息与状态表中的会话条目进行比较,如果信息匹配,就直接允许数据包通过,这样不再去接受规则检测,提高了效率,如果信息不匹配,数据包就会被丢弃或者连接被拒绝,并且每个会话还有一个超时值,过了这个时间,相应会话条目就会被从状态表中删除(这也就是为什么一些客户端去访问防火墙背后的服务端时,如果客户端不定时去发一条信息连一下服务器的话,服务器就无法再给客户端主动发消息了,因为状态会话已经超时,被删除了)。
就上面外部Web网站对响应包来说,由于状态检测引擎会检测到返回的数据包属于Web连接的那个会话,所以它会动态打开端口以允许返回包进入,传输完毕后有动态关闭这个端口,这样就避免了防火墙过普通包时,那种静态地开放所以高端端口的危险做法,同时由于又有会话超时的限制,它也能有效地避免外部的DoS攻击,并且外部伪造的ACK数据包也不会进入,因为它的数据包信息不回匹配状态表中的会话条目。
有状态的防火墙在iptables中的实现
iptables中的状态:
- NEW:主机向远程机器发送一个连接请求时,这个数据包的状态是NEW。
- ESTABLISHED:当连接建立之后,远程主机和本地主机通信数据状态为ESTABLISHED。
- RELATED:像ftp这样的服务,用21端口传送命令,而用20端口(port模式)或者其他端口(PASV模式)传送数据。在已有21端口上建立好连接后发送命令,用20端口传送的数据的状态时RELATED。
默认规则。对所有进入机器的数据包都丢弃。
1
iptables -P INPUT DROP
禁止其他机器主动发起对本机的连接,但是本机可以主动连接其他机器,这条可以省去由默认规则处理。
1
iptables -A INPUT -m state --state NEW -j DROP
当本机主动连接其他机器之后,再进来的数据就是ESTABLISHED状态了。
1
iptables -A INPUT -m state --state ESTABLISHED, RELATED -j ACCEPT
如果机器提供pasv模式的ftp服务(会使用动态的端口来传送数据,这对于有状态的防火墙轻易能做到)
1
2iptables -A INPUT -i ppp0 -p tcp -dport 21 -j ACCEPT
iptables -A INPUT -i ppp0 -p udp -dport 21 -j ACCEPT
两条命令解决内部用户上网收发邮件、浏览网页等需求。
1 | iptables -A FORWARD -i eth0 -p tcp -m multiport --dports 25,80,110,443,1863 -j ACCEPT |
从数据流向看iptables对TCP、UDP及ICMP报文的支持
- 第一个出去的数据包,也就是SYN报文,会标记为NEW状态。