在云计算中,虚拟网络中的安全需要回答以下几个基本问题。

  • 如何对租户网络进行隔离?
  • 如何控制用户对网络中资源的访问?
  • 如何实现对网络管理的安全控制?

关于租户网络隔离,云计算中的一个重要概念是多租户的概念,即多个租户共享或者独占云中的资源。对云中的网络资源也不例外,每个租户需要有自己的网络、网段、路由和IP,这些网络构建于云的物理网络基础设施之上,在每个租户之间相互隔离。为了实现这种网络的隔离,一般采用VLAN或者基于overlay的虚拟网络进行隔离。

关于网络管理的安全控制,需要结合OpenStack的权限管理机制(Keystone)来看,保证用户对于网络管理的访问与使用是可控的。

Neutron是如何控制用户对网络中资源的访问,主要是OpneStack中两个很重要的功能,一个是安全组(Security Group)的功能,一个是防火墙即服务(FWaaS)的功能。

目录

  1. iptables基础
      1. Filter表
      2. NAT表
      3. Mangle表
      4. Raw表
      5. 自定义链
    1. iptables命令
  2. Neutron中的安全组
    1. Neutron中的自定义链
    2. 虚拟机的链和规则
    3. 配置使用Neutron中的Security Group
      1. TODO
  3. Neutron中的防火墙
    1. TODO
    2. TODO
  4. 有状态的防火墙和基于OVS流规则的防火墙
    1. 有状态的防火墙
      1. TODO
    2. 有状态的防火墙在iptables中的实现
    3. 从数据流向看iptables对TCP、UDP及ICMP报文的支持

iptables基础

在Linux系统中,对于防火墙的实现一般分为包过滤防火墙、TCP-Wrapper即程序管控、代理服务器等几种方式。其中,iptables作为一种基于包过滤方式的防火墙工具,在实际中应用非常广泛,是非常重要的安全工具。

iptables防火墙应该称为netfilter/iptables防火墙。

iptables命令定义包过滤的规则,而这些规则的读取和执行,是由内核空间中的netfilter来实现的。顾名思义,netfilter是放在内核中的网络过滤器,而它控制的位置必须是TCP/IP协议栈经过的地方。在netfilter/iptables框架中,在内核空间中一共定义了以下5个位置:

  1. 数据包刚刚进入网络层的位置。
  2. 经过路由判断,数据包从内核流入本机用户空间的位置。
  3. 数据包从本机用户空间进程发出的位置,后接路由判断出口的网络接口。
  4. 经路由判断,数据包不进入本机用户空间,只是进行转发的位置。
  5. 数据包将通过网络接口出去的位置。

相应的,netfilter在这5个位置定义了5个钩子函数,也叫5个规则链:

  1. PREROUTING 在这里处理目的地址转换。
  2. INPUT 在这里处理INPUT包过滤。
  3. OUTPUT 在这里处理OUTPUT包过滤。
  4. FORWARD 在这里处理FORWARD包过滤。
  5. POSTROUTING 在这里处理源地址转换。

任何经过本机的数据包,都会经过这5个规则链上的几个位置。一般来讲,数据包需要发给本机进程的,会通过PREROUTING –> OUTPUT –> POSTROUTING这条链;数据包只在本机进行转发的,会通过PREROUTING –> FORWARD –> POSTROUTING这条链。

iptables实际上指的是整个netfilter/iptables框架中,运行在用户空间的应用软件。它通过控制内核空间的netfilter模块,来管理网络数据包的流动与传送,其中最核心的是定义iptables策略。

iptales策略是由一组有序的规则建立的,告诉内核怎样处理数据包。而规则用于一个表的一个链,链是一个规则集。
iptables的概念从大到小是:iptables –> 表 –> 链 –> 规则。

首先,iptables定义了4个表来定义、区分各种不同的工作功能和处理方式。

Filter表

Filter表用于一般的数据包的过滤。其中包括3个链:

  1. INPUT 在此链中可添加对进入到用户空间的包的过滤。
  2. OUTPUT 在此链中可添加从用户空间发出去的包的过滤。
  3. FORWARD 在此链中可添加要转发的包的过滤。

NAT表

NAT表用于网络地址的转换,其中包括3个链:

  1. PREROUTING 在此链中可添加目的地址转换的规则(DNAT)。
  2. POSTROUTING 在此链中可添加源地址转换的规则(SNAT)。
  3. INPUT 在此链中可添加对进入到用户空间的包的过滤。
  4. OUTPUT 在此链中可添加从用户空间发出去的包的过滤。

Mangle表

Mangle表用于修改数据包的原数据,一般用于防火墙标记。Mangle表包含全部5个规则链,即PREROUTING、OUTPUT、FORWARD、INPUT和POSTROUTING。

Raw表

Raw表是用于配置免除的,包含PREROUTING和OUTPUT两个内置链。

自定义链

链中规则的执行优先级:
raw表 > mangle表 > nat表 > filter表

  1. 创建新链

    1
    iptables -t nat -N my_chain


  2. 添加规则

    1
    iptables -t filter -A my_chain -s 192.168.2.10 -j DROP


  3. 使用自定义链

    1
    iptables -t filter -A INPUT -j my_chain

iptables命令

1
iptables [-t table] command [chain] [rules] [-j target]
  • table 指定表的名字,默认是filter。
  • command 对链的操作命令。
  • chain 链名。
  • rules 规则。
  • 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(安全组)运行在计算节点,对进入虚拟机的流量进行控制。

  1. 过滤进入到计算节点上虚拟机的流量。
  2. 过滤从虚拟机出来的流量。
  3. 过滤虚拟机之间的流量。

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组件共享的链。

  1. 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
  1. 添加一个包装链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
  1. 对于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
  1. 在POSTROUTING链之后还定义了一个名为neutron-postrouting-bottom的非包装类:
  • iptables -t filter -N neutron-postrouting-bottom
  • iptables -t filter -A POSTROUTING -j neutron-postrouting-bottom
  1. 在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
  1. 最后定义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

  1. /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
  2. /etc/neutron/l3_agent.ini

    1
    2
    [AGENT]
    extensions = fwaas

使用步骤。

TODO

1
2
3
4
5
6
7
```

## Allowed Address Pairs扩展
安全组有一条默认的防欺骗规则,只允许匹配的IP -> MAC的流量访问虚拟机。通过Allowed Address Pairs扩展可以设置任意的源IP来访问外部网络。

```bash
neutron port-update <port-id> --allowed-address-pairs type=dict list=true ip_address=192.168.99.122

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. 默认规则。对所有进入机器的数据包都丢弃。

    1
    iptables -P INPUT DROP
  2. 禁止其他机器主动发起对本机的连接,但是本机可以主动连接其他机器,这条可以省去由默认规则处理。

    1
    iptables -A INPUT -m state --state NEW -j DROP
  3. 当本机主动连接其他机器之后,再进来的数据就是ESTABLISHED状态了。

    1
    iptables -A INPUT -m state --state ESTABLISHED, RELATED -j ACCEPT
  4. 如果机器提供pasv模式的ftp服务(会使用动态的端口来传送数据,这对于有状态的防火墙轻易能做到)

    1
    2
    iptables -A INPUT -i ppp0 -p tcp -dport 21 -j ACCEPT
    iptables -A INPUT -i ppp0 -p udp -dport 21 -j ACCEPT

两条命令解决内部用户上网收发邮件、浏览网页等需求。

1
2
iptables -A FORWARD -i eth0 -p tcp -m multiport --dports 25,80,110,443,1863 -j ACCEPT
iptables -A FORWARD -i eth0 -p udp --dport 53 -j ACCEPT

从数据流向看iptables对TCP、UDP及ICMP报文的支持

  1. 第一个出去的数据包,也就是SYN报文,会标记为NEW状态。