nftables通过启用interval标志的Set集合高效管理混合CIDR与单IP的恶意源黑名单,配合timeout自动过期和增量导入,实现内核级高速拦截,避免暴力展开、内存暴涨及服务中断。

直接用 nftables 的 Set(集合) 功能导入全网恶意扫描源 IP 黑名单,关键不是“一条条加”,而是把整张黑名单变成内核可高速检索的数据结构。它不依赖规则数量,只靠一次查表动作就能拦截——这才是真正能扛住数万甚至数十万 IP 的做法。
必须启用 interval 标志支持 CIDR 和单 IP 混合
恶意 IP 列表通常含 /16、/24 网段(如 185.104.0.0/16)和孤立 IP(如 203.0.113.77)混用。若忽略 interval,nftables 会把每个网段暴力展开成数百上千个独立地址,内存暴涨、加载卡死、匹配变慢。
正确创建集合命令:
nft add set inet firewall blacklist {
type ipv4_addr;
flags interval;
timeout 72h;
}-
interval:启用区间树支持,让192.168.1.0/24和10.5.3.12共存于同一集合 -
timeout 72h:自动清理过期条目,避免手动 flush 导致短暂放行
⚠️ 错误写法:
nft add set inet firewall blacklist { type ipv4_addr }→ 不支持 CIDR,严禁用于真实黑名单。
从威胁情报源一键批量导入(不中断服务)
假设你已下载好开源黑名单(如 FireHOL Level1 或 AbuseIPDB CSV),格式为每行一个 IP 或 CIDR:
198.51.100.42 203.0.113.0/24 185.104.21.177
执行导入脚本(无需停服务、不 reload 规则):
while IFS= read -r ip; do
[[ -n "$ip" ]] && nft add element inet firewall blacklist { "$ip" }
done < /path/to/malicious_ips.txt- 成功后,所有新进包在
input链中只需一次ip saddr @blacklist drop即可拦截 - 已存在的连接不受影响(conntrack 有状态),仅新连接被阻断
配套链规则必须精简且前置
确保你的 input 链策略为 drop,并只写一条引用规则,位置建议在最前(或至少在 SSH/HTTP 放行规则之前):
# 创建基础链(默认拒绝)
nft add chain inet firewall input {
type filter hook input priority 0;
policy drop;
}
# 加入唯一黑名单拦截规则(必须放在白名单规则之前!)
nft add rule inet firewall input ip saddr @blacklist drop- 这条规则生效后,内核收到包时直接哈希/区间树查
@blacklist,命中即丢弃 - 不再需要
for ip in ...; do nft add rule ...循环上万次
自动更新与防误操作要点
- ❌ 禁止使用
nft flush set inet firewall blacklist:清空瞬间所有 IP 失效,攻击者可能趁虚而入 - ✅ 推荐方式:依赖
timeout自动过期 + 定期追加新条目(如每日 cron 调用导入脚本) - ✅ 可配合
nft list set inet firewall blacklist实时查看当前有效条目数 - ✅ 若需临时禁用黑名单,改用
nft delete rule inet firewall input handle XXX删除该条规则,而非清空集合
不复杂但容易忽略。

















