Stateful firewall in OpenFlow based SDN

2020-07-02 00:00:00 连接 模块 状态 防火墙 数据包

Stateful firewall

防火墙可以分为有状态(Stateful)和无状态(Stateless)。这里说的防火墙指的不仅是Firewall,也包括OpenStack中常使用的Security Group,它们只是不同层面的防火墙。

无状态防火墙就是基于静态数值来过滤或阻拦网络数据包。例如基于地址,端口,协议等等。无状态指的就是,防火墙本身不关心当前的网络连接状态。

有状态防火墙能区分出网络连接的状态。例如TCP连接,有状态防火墙可以知道当前是连接的哪个阶段。也就是说,有状态防火墙可以在静态数值之外,再通过连接状态来过滤或阻拦网络数据包。

这两个哪个更好?严格来说没有更好,具体要看使用场景。无状态的防火墙一般更快,在高负载网络流量下性能更好,但是只适用于简单的场景。而有状态的防火墙一般会安全的多,因为它可以定义更加严格的规则。

Connection tracker

Stateful防火墙的特点就是能知道网络连接当前的状态,并根据网络连接的状态来过滤网络流量。网络连接的状态,通常是由connection tracker来实现。可以简称为CT模块。在linux内核中,CT是由conntrack实现,开始实现是为了Netfilter 框架能了解特定网络连接的状态。其内部实际上是对各个网络连接实现了状态机,这里的状态机区别于TCP连接本身的状态机,毕竟网络连接本身不一定是有状态的,也就是说,CT模块自己有一套状态机。

CT模块可以结合iptables实现有状态防火墙,不过今天说一下如何结合OpenvSwitch和OpenFlow来实现有状态防火墙。

在OpenvSwitch实现的OpenFlow中,CT状态由ct_state提供。ct_state提供如下状态:

  • 0x01: new:这是一个连接的开始状态(NEW),这个状态只可能出现在还未commit的connection中。通常这意味着这个包是网络连接中的个数据包。
  • 0x02: est:这是一个已经存在的连接(ESTABLISHED),这个状态只可能出现在已经commit的connection中。并且当前的数据包是合法的,例如TCP连接中,client发送了SYN,server回复的SYN/ACK。
  • 0x04: rel:这是一个与已经存在的连接(est)有关联的连接(RELATED),例如ICMP "destination unreachable" messages 或者FTP 数据连接。这个状态只可能出现在已经commit的connection中。
  • 0x08: rpl:匹配回复方向的数据,意味着当前主机并没有初始化连接。这个状态只可能出现在已经commit的connection中。
  • 0x10: inv:当前数据包状态是的,意味着CT模块不能正确识别当前数据包,例如:L3/L4 protocol handler未加载或者不可用。在linux下,这通常意味着nf_conntrack 模块未加载。L3/L4 protocol handler发现packet包不合法。Packet 长度不符合协议要求。
  • 0x20: trk:表明当前数据包经过了CT模块。如果这个标志没有被设置,那么其他所有的标志位都不可能被设置。
  • 0x40: snat:数据包经过了SNAT。
  • 0x80: dnat:数据包经过了DNAT。

ct_state是从OpenvSwitch 2.5版本才有,而snat和dnat更是从2.6版本才开始有。正是这个原因,早期的OpenStack Neutron的OpenvSwitch实现方案要在虚机port和br-int中间加一个linux bridge来应用iptables以实现Security Group。这实在是个复杂低效的无奈之举,不过后期的SDN实现方案都没有采用这种网络连接方案了。

网络数据包在OpenFlow中有两种状态,untracked和tracked。当网络数据包经过了CT模块,那它就是tracked的,对应的(0x20: trk)会置位。

网络连接在OpenFlow中也有两种状态,uncommitted和committed。CT模块判断connection是否是ESTABLISHED(0x02: est),commit是一个必要条件。

看一个小例子,这个例子在后面还会提到:

table=0,priority=100,ip,ct_state=-trk,action=ct(table=1)
table=1,in_port=1,ip,ct_state=+trk+new,action=ct(commit),2table=1,in_port=1,ip,ct_state=+trk+est,action=2
table=1,in_port=2,ip,ct_state=+trk+new,action=drop
table=1,in_port=2,ip,ct_state=+trk+est,action=1

相关文章