创建 ACL 以使用 TCP 标志阻止新的 TCP 会话

问题

如何应用访问控制列表 (ACL) 以允许已建立的 TCP 会话流量,并基于 TCP 标志阻止入口端口上的新 TCP 会话?

环境

  • Cumulus Linux,所有版本

概述

此解决方案基于以下理论运行:TCP 会话通过由 SYN、SYN-ACK 和 ACK 组成的三次握手建立。只有 SYN 可能存在于新连接中。新连接中不允许 ACK、FIN 和 RST。对于现有会话,SYN 可能存在,但只能与 ACK 一起存在。

默认情况下,Cumulus Linux 在默认目录 /etc/cumulus/acl/policy.d 下的多个 *.rules 文件中对交换机的 ACL 规则进行编码。Cumulus Linux 按排序的文件顺序处理 *.rules 文件。每个 ACL 策略规则文件可能包含标记 [iptables][ip6tables][etables] 下的 iptablesip6tablesetables 类别。请注意,您仅将 etables 类别用于第 2 层,因此以下示例未引用它们。

编码规则后,使用 cl-acltool 在硬件中安装并同步它们。

以下示例解决方案在 INPUT 和 FORWARD 链上创建规则,以在设置 SYN 位且 RST、ACK 和 FIN 位重置时,丢弃入口 IPv4 和 IPv6 TCP 数据包。INPUT 和 FORWARD 链的默认设置允许所有其他数据包。cl-acltool 将 ACL 应用于端口 swp20 和 swp21。配置此 ACL 可防止创建源自入口端口 swp20 和 swp21 的新 TCP 会话。ACL 为创建源自任何其他端口的 TCP 会话执行所有操作。

配置 ACL 规则

创建 /etc/cumulus/acl/policy.d/50tcp_established.rules 并添加以下配置

INGRESS_INTF = swp20,swp21

[iptables]
-A INPUT,FORWARD --in-interface $INGRESS_INTF -p tcp --syn -j DROP
[ip6tables]
-A INPUT,FORWARD --in-interface $INGRESS_INTF -p tcp --syn -j DROP

上述规则中的 --syn 标志匹配设置了 SYN 位且清除了 ACK、RST 和 FIN 位的包。

它等效于使用 -tcp-flags SYN,RST,ACK,FIN SYN. 例如,上述规则可以重写为

-A INPUT,FORWARD --in-interface $INGRESS_INTF -p tcp --tcp-flags SYN,RST,ACK,FIN SYN -j DROP

运行 cl-acltool -i 以安装规则。如果 Cumulus Linux 未检测到错误,它将安装规则并与硬件同步。以下输出指示 cl-acltool 已成功安装规则

Reading rule file /etc/cumulus/acl/policy.d/50tcp_established.rules ...
Processing rules in file /etc/cumulus/acl/policy.d/50tcp_established.rules ...
Installing acl policy
done.

验证规则

安装规则后,使用 cl-acltool -L all 检查规则是否存在,以及数据包和字节计数器是否按预期递增。

Chain FORWARD (policy ACCEPT 41224 packets, 4653K bytes)
 pkts bytes target prot opt in out source destination 
 29 1856 DROP tcp -- swp20 any anywhere anywhere tcpflags: FIN,SYN,RST,ACK/SYN
 0 0 DROP tcp -- swp21 any anywhere anywhere tcpflags: FIN,SYN,RST,ACK/SYN