我使用 nftables 作为我的规则。
我的问题:如何记录 tcp 标志?
这是我的规则:
nft add rule filter input tcp dport 22 ct state new tcp flags \& \(fin\|syn\) ==\( fin \| syn\) accept
我总是得到的结果:
Dec 6 13:40:19 my_host my_FIN IN=eth0 OUT=eth1 MAC= SRC=x.1.1.1 DST=x.2.2.2 LEN=40 TOS=00 PREC=0x00 TTL=127 ID=17695 DF PROTO=TCP SPT=54049 DPT=422SEQ=2558094232 ACK=0 WINDOW=8192 SYN URGP=0 MARK=0
编辑 我的规则:
chain FORWARD {
ip saddr 1.1.1.1 ip daddr . tcp dport @myset tcp flags & (fin | syn) == fin | syn counter packets 0 bytes 0 log prefix " myprefix " group 1 accept
}
答案1
对于 TCP 情况,Netfilter 的 conntrack 在其内部状态和等效 TCP 状态之间进行了额外的一致性检查。这网络开发 2.1 PDF文档(抱歉我找不到它的 netdev url,这是来自作者的网站)讲述了它:
L4 跟踪器尝试保持状态,例如 tcp:跟踪状态,检查序列号。例子:
- 新的TCP数据包?同步位设置?
- 预期窗口中的 TCP 序列号?
- 未确认的数据? → 调整超时时间
- 首先?鳍? → 删除连接和/或调整超时
连线新的状态与 TCP 匹配SYN_SENT或 TCPSYN_已接收状态。如果您选择新的规则中的状态条件,使用ct state new
,它永远不会匹配任何鳍数据包,因为从来没有鳍数据包参与建立新的 TCP 连接。
删除后重试ct state new
。
更新:还有第二个问题我最初没有看到。这个表达式:
tcp flags & (fin | syn) == fin | syn
永远不会与 FIN 标志匹配,因为永远不会同时找到 FIN+SYN(除了一些随机的无效尝试)。正确的表达应该是:
tcp flags & (fin | syn) != 0
每当 FIN 时都会匹配或者SYN 已设置。实际上nftables简化了它,只显示或需要这个:
tcp flags fin,syn
因此,考虑到这两项调整(ct state new
仍必须删除),规则变为:
nft add rule filter FORWARD 'tcp dport 22 tcp flags fin,syn log prefix " my_FIN " group 1 accept
或在完整的链集中:
chain FORWARD {
type filter hook forward priority 0; policy accept;
ip saddr 1.1.1.1 ip daddr . tcp dport @myset tcp flags fin,syn counter log prefix " myprefix " group 1 accept
}
一旦您可以使用上述规则实际检测到 FIN 数据包,如果您的目的是过滤某些 TCP 攻击(您真的需要吗?),请注意,netfilter 可能会考虑首先在 TCP 连接的第一个数据包中看到 TCP FIN,如下所示无效的状态:您可能有兴趣记录这些状态 ( ct state invalid
)。有 netfilter sysctl 开关可以改变结果无效的状态:启用nf_conntrack_tcp_be_liberal 这不会将其归类为无效,并且禁用nf_conntrack_tcp_loose这将停止恢复已建立的 TCP 连接,即停止处于没有 SYN 的 NEW 状态。这种恢复应该仅在丢失连接跟踪后发生:在防火墙路由器重新启动后或使用 刷新 conntrack 状态后conntrack -F
,但谁知道呢,这里可能会选择偏执。