我有以下内容nftables.conf
:
table inet nat {
set blocked {
type ipv4_addr
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
ip daddr @blocked counter drop;
oifname "ppp0" masquerade;
iifname "br-3e4d90a574de" masquerade;
}
}
该集合blocked
是一个可以动态更新的命名集合。正是在这个集合中,我希望有一个要阻止的 IP 集合,每n分钟更新一次。为了保持原子性,我没有使用以下 ( updateblock.sh
) 来更新列表:
#!/bin/bash
sudo nft flush set inet nat blocked
sudo nft add element inet nat blocked {$nodes}
而是blockediplist.ruleset
:
#!/usr/sbin/nft -f
flush set inet nat blocked
add element inet nat blocked { <example_ip> }
我使用以下命令顺序:
nft -f /etc/nftables.conf
nft -f blockediplist.ruleset
但是,更改blockediplist.ruleset
不会立即应用。我知道规则集现在包含新 IP,因为 IP 存在于nft list ruleset
和中nft list set inet nat blocked
。即使只是这样,nft add element inet nat blocked { <IP> }
IP 也不会立即被阻止。
另一种方法是定义一个新集合并重新加载nftables.conf
整个集合,尽管我认为这将是一种糟糕且低效的做事方式。
有没有办法强制blockediplist.ruleset
立即应用更改?
更新:我刚刚发现,当我阻止一个我没有 ping 过的 IP 时,它会立即被阻止。但是,在中间 ping 将 IP 添加到阻止列表时,需要一段时间才能被阻止。当我尝试使用netdev ingress
IP 设置时,会立即被阻止。也许这种调查途径可能会揭示一些东西。
nat 钩子(与所有其他钩子一样)由 Netfilter 提供给 nftables。NAT 钩子很特殊:只有连接的第一个数据包会穿过这个钩子。conntrack 已跟踪的连接的所有其他数据包不再遍历任何 NAT 钩子,而是由conntrack直接处理以继续为此流执行配置的 NAT 操作。
这就解释了为什么你永远不应该使用这个钩子来丢弃:它不会影响已经跟踪的连接,无论是否经过 NAT。
只需将钩子类型从
type nat
更改type filter
为丢弃流量的部分。与iptables不同,表不限于一种钩子类型,实际上必须为这种情况使用多种类型,因为该集合是表的本地集合,不能在两个表之间共享。出于同样的原因,这个表在逻辑上不应该再被调用inet nat
,因为它不仅仅是在做 NAT(但我没有重命名它)。所以最后:
nftables.conf
:现在:
inet nat block
链将检查所有数据包,从而使该blocked
组立即影响流量,而不必等待下一个流量受到影响。像往常一样,只有新流的第一个数据包(暂定的 conntrack 状态 NEW)将遍历
inet nat postrouting
链。另请注意,这
iifname "br-3e4d90a574de" masquerade;
需要足够新的内核(Linux内核 >= 5.5):在路由后挂钩仅支持通过传出接口过滤之前。此外,这看起来像是一个与 Docker 相关的接口,并且添加这种规则可能会与 Docker 交互(例如:它可能会对同一网络中的两个容器之间的流量进行 NAT),因为它引用了一个桥接接口。这是因为 Docker通过加载模块使nftables(以及iptables )看到的桥接流量)。br_netfilter