使用Python libnftables为nftables自定义链添加drop策略失败
问题
我尝试用Python结合libnftables的JSON接口,为nftables创建自定义表、链和白名单规则集,需求如下:
- 创建默认策略为
drop的链,丢弃所有不匹配白名单的出站数据包 - 使用自定义表实现,确保与fail2ban等工具的现有规则共存
目前表、链、规则都能成功创建,但链的默认策略drop未生效,规则集输出中看不到该策略(推测默认是accept)。JSON配置通过了libnftables的验证,但策略就是不生效。
配置与输出信息
设置的JSON配置:
{'nftables': [{'add': {'table': {'family': 'ip', 'name': 'O365'}}}, {'add': {'chain': {'family': 'ip', 'table': 'O365', 'name': 'O365WhiteList', 'policy': 'drop'}}}, {'add': {'rule': {'family': 'ip', 'table': 'O365', 'chain': 'O365WhiteList', 'expr': [{'match': {'op': '==', 'left': {'payload': {'protocol': 'tcp', 'field': 'dport'}}, 'right': 22}}, {'accept': None} ] }}}]}
规则集输出:
# Warning: table ip filter is managed by iptables-nft, do not touch! table ip filter { chain f2b-sshd { counter packets 92105 bytes 13096562 return } chain INPUT { type filter hook input priority filter; policy accept; meta l4proto tcp tcp dport 22 counter packets 132201 bytes 15881220 jump f2b-sshd } } # Warning: table ip nat is managed by iptables-nft, do not touch! table ip nat { chain POSTROUTING { type nat hook postrouting priority srcnat; policy accept; oifname "ens19" counter packets 983 bytes 70843 masquerade } } table ip O365 { chain O365WhiteList { tcp dport 22 accept } }
完整代码
import json import nftables #some objects to be turned into json for nftables to apply as commands delTable = {"nftables": [{ "delete": { "table": { "family": "ip", "name": "O365" }}}]} setupTablesCmds= """ { "nftables": [ { "add": { "table": { "family": "ip", "name": "O365" }}}, { "add": { "chain": { "family": "ip", "table": "O365", "name": "O365WhiteList", "policy": "drop" }}}, { "add": { "rule": { "family": "ip", "table": "O365", "chain": "O365WhiteList", "expr": [ { "match": { "op": "==", "left": { "payload": { "protocol": "tcp", "field": "dport" }}, "right": 22 }}, { "accept": null } ] }}} ]} """ nft = nftables.Nftables() try: nft.json_validate(json.loads(setupTablesCmds)) except Exception as e: print(f"ERROR: failed validating initial setup json schema: {e}") exit(1) print(" base config data passed validation, yay! " ) print() print("Removing old O365 table") rc, output, error = nft.json_cmd(delTable) if rc != 0: # error here is probably because table doesn't exist, which is fine, so no exit on error for now print(f"ERROR: running json cmd: {error}") print(" setting up new O365 table " ) print( "json commands = :", json.loads(setupTablesCmds)) rc, output, error = nft.json_cmd(json.loads(setupTablesCmds)) if rc != 0: print(f"ERROR: running json cmd: {error}") exit(1) if len(output) != 0: print(f"WARNING: output: {output}") print(" Base config applied ok, O365 table created" )
原因与解决办法
核心原因
nftables中,只有"基础链"(Base Chain,即挂载到钩子点的链)才支持设置默认策略。你创建的O365WhiteList是一条"常规链"(Regular Chain),这类链没有默认策略,数据包匹配完所有规则后默认会return,而非遵循你设置的policy参数。
解决步骤
修改链为基础链
要实现出站过滤,需把链设置为基础链,挂载到output钩子点,同时指定链类型为filter。修改链的JSON配置,添加type、hook、priority字段:{ "add": { "chain": { "family": "ip", "table": "O365", "name": "O365WhiteList", "type": "filter", "hook": "output", "priority": 0, "policy": "drop" }}}各字段说明:
type: 链的类型,过滤规则用filterhook: 指定挂载的钩子点,出站流量用outputpriority: 钩子执行优先级,0为默认值,可根据需求调整
验证修改效果
重新运行代码后,查看规则集,会看到链的定义中包含policy drop:table ip O365 { chain O365WhiteList { type filter hook output priority filter; policy drop; tcp dport 22 accept } }可选:规则复用方案
若想把白名单规则放在常规链中,再由基础链跳转,可以:- 创建带
policy drop的基础链 - 创建常规链存放白名单规则
- 在基础链中添加跳转规则到常规链
这样既实现默认丢弃,又能灵活复用规则。
- 创建带
内容的提问来源于stack exchange,提问作者user2512377
相关产品推荐
相关产品推荐

