之前,在学习高性能 XDP ACL 的时候,挺开心的,一下子就掌握了前沿技术。

不过在项目中落地的时候,有非常多的代码逻辑处理,才能真正将高性能 ACL 给跑起来。

四元组的 ACL 规则

项目中需要处理的 ACL 规则并不是像 iptables 规则那样的五元组规则,而是四元组:

  1. 一组对象:对象里通过标签、分组等方法获取 IP 信息。
  2. 方向:对于该组对象而言,方向是 INGRESS or EGRESS。
  3. IP 地址:由多条 CIDR 组成的远端地址。
  4. 端口:默认指的是目的端口,不分方向。
  5. 协议:TCP/UDP/ICMP 等。
  6. 动作:ACCEPT or DROP。

在指定方向后,使用四元组去匹配网络包也是可以的。

不过不过,有个隐藏的需求:

  1. 如果端口不是任意端口,则需要给反方向下发同样的规则,除了端口变为源端口。

源端口带来的复杂性

如果没处理好这个隐藏需求,会导致如下 case 出问题:

  1. 方向 BOTH,IP 地址 (“x.x.x.0/24”),端口 8080,协议 TCP,动作 DROP。

因为方向是 BOTH,所以 INGRESS 和 EGRESS 都要下发目的端口为 8080 的规则;用 iptables 规则表示:

1
2
3
4
5
INPUT:
-s x.x.x.0/24 -p tcp --dport 8080 -j DROP

OUTPUT:
-d x.x.x.0/24 -p tcp --dport 8080 -j DROP

加上隐藏需求后:

1
2
3
4
5
6
7
INPUT:
-s x.x.x.0/24 -p tcp --dport 8080 -j DROP
-s x.x.x.0/24 -p tcp --sport 8080 -j DROP

OUTPUT:
-d x.x.x.0/24 -p tcp --dport 8080 -j DROP
-d x.x.x.0/24 -p tcp --sport 8080 -j DROP

此时,如果在 XDP ACL 里处理反向源端口规则时使用 bitmap 中的同一个 bit 来表示规则,就会将所有网络包都 DROP 掉,不管有没有匹配到 8080 端口。

这也是由 XDP ACL 匹配四元组规则时引入通配源端口/目的端口时带来的隐患。

解法如下:

为源端口生成一条新的规则,即代表 bitmap 中不同位置上的 bit 了。

因此,在源端口和目的端口都匹配到通配的 bitmap 时,因为使用了不同位置上的 bit,所以最终不会匹配到这条规则。

小结

遇到隐藏需求,实在是太痛苦了;毕竟需要调整方案去满足这些需求。