我使用 nftables,但它没有像 iptables 的字符串或 u32 匹配这样的内容,因此无法可靠地收集有效负载偏移量。如果不通过 nftables 的原始有效负载,我如何才能有效地分析 TCP 有效负载而不会出现任何用户空间瓶颈?(出于性能原因,nfqueue 不是一个答案)
是否有任何技术可以在内核级别进行此类过滤?即使标记合适的数据包对我来说也足够了 - 其余的工作可以在防火墙上轻松完成。
答案1
已经有可用的内核代码能够处理任意字符串匹配,并且在数据包路径期间仍然处于内核上下文中,为什么不重用它呢? iptables不会去任何地方。什么可能或许某天消失是遗留的内核 APIiptables,只留下iptables-nft仍然可以使用表格模块,例如细绳匹配模块。 使用iptables-旧版或者iptables-nft沿着nftables将得到以下相同的结果。
可以使用标记在数据包路径中的各个网络子系统之间传递消息,包括来自nftables到iptables然后返回iptables到nftables。
这钩内优先级表格可以帮助:
nftables 家庭 典型的钩子 nft 关键字 价值 Netfilter 内部优先级 描述 [...] inet、ip、ip6 全部 曼格尔 -150 NF_IP_PRI_MANGLE Mangle 操作 inet、ip、ip6 预路由 目的地地址 -100 NF_IP_PRI_NAT_DST 目标 NAT inet、ip、ip6、arp、netdev 全部 筛选 0 NF_IP_PRI_过滤器 过滤操作,过滤表 [...]
只需注册nftables每人两次iptables' 内置链参与:之前具有优先级iptables',一旦优先权紧随其后iptables例如,使用带有iptables优先级 0,可以使用 -5 和 5 来包围它。更多详细信息这些 二Unix/Linux SE Q/A,我在这里做出解答。
人工示例(改编自iptables-extensions(8)
)混合nftables和iptables,系统应丢弃本地发起的针对特定 DNS 地址的 DNS 请求www.netfilter.org,按钩子优先级顺序呈现(警告:仅限 UDP,由于范围固定,仅在传出数据包中不存在任何 IPv4 或 IPv6 选项/标头时才有效,但可以放宽范围以适应这种情况):
nft add table inet mytable
nft add chain inet mytable outputbefore '{ type filter hook output priority -5; policy accept; }'
nft add rule inet mytable outputbefore udp dport 53 meta mark set 1
iptables -I OUTPUT -m mark --mark 1 -m string --algo bm --from 40 --to 57 --hex-string '|03|www|09|netfilter|03|org|00|' -j MARK --set-mark 2
ip6tables -I OUTPUT -m mark --mark 1 -m string --algo bm --from 60 --to 77 --hex-string '|03|www|09|netfilter|03|org|00|' -j MARK --set-mark 2
nft add chain inet mytable outputafter '{ type filter hook output priority 5; policy accept; }'
nft add rule inet mytable outputafter meta mark 2 drop
这里的目标是iptables只处理nftables只做最少的工作:通过标记发出返回值,留下nftables负责数据包的命运:
- nftables将数据包的标记设置为 1 以“询问”iptables做某事
- iptables(或者ip6tables) 仅在“收到”标记 1 时才执行字符串匹配,以节省 CPU 使用,并且如果在这种情况下字符串匹配,则“回答”2
- nftables仅当数据包“收到”值为 2 的标记时才丢弃该数据包(从而删除iptables规则也会禁用该效果)
笔记:
警告
之间的沟通机制nftables和iptables是通过数据包标记(或者也可以通过连接跟踪connmarks)。虽然可以只写入和读取标记的几个位(通过使用标记上的可选掩码和适当的按位操作),但标记的每个用户都必须遵守标记中位所有权的某些分配约定。如果没有这一点,工具在处理标记时会相互干扰。例如防火墙使用标记来处理规则中的重定向,因此此示例可能与以下情况不兼容防火墙,即使在使用时使用自己的表nftables后端。
一些简单的情况可以使用原始载荷
上述这个具体的例子固定的抵消,可以实现nftables。当有任意偏移量来查找数据时(最好与 iptables 一起使用)细绳匹配)或一个复杂的方法来计算这种偏移量(最好与 iptables 一起使用)u32匹配)nftables無法使用。
以下是使用原始有效载荷用单个规则替换上述所有规则的等效方法。语法仅允许最大 128 位,但此处需要 19x8=152 位,因此必须将其拆分为两个原始有效载荷(128 位 + 24 位)。
printf
,xxd
并且cut
也用于一些帮助:nft add table inet mytable nft add chain inet mytable output '{ type filter hook output priority 0; policy accept; }' nft add inet mytable output udp dport 53 \ @th,160,128 0x$(printf '\3%s\11%s\3%s\0' www netfilter org | xxd -p | cut -c-32) \ @th,288,24 0x$(printf '\3%s\11%s\3%s\0' www netfilter org | xxd -p | cut -c33-) \ drop
输出为
printf '\3%s\11%s\3%s\0' www netfilter org | xxd -p
:03777777096e657466696c746572036f726700
获取两个原始有效载荷:
0x03777777096e657466696c746572036f 0x726700
可能有其他方法
iptables可以调用 eBPF 对象(无论如何,只有最近的内核允许(有限)循环来轻松尝试实现某些算法),nftables缺乏此功能。所以它再次带有标记和iptables。
这样的 eBPF 对象可能与...一起使用西地普或者碳但这可能在数据包路径中为时过早(例如:没有可用的状态 NAT),需要实际编程而不是管理。无论如何,如果必须使用以下方式处理决策,则需要通过标记进行通信:nftables。