创建 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] 下的 iptables、ip6tables 和 etables 类别。请注意,您仅将 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