nftables 的 meta iifname/oifname 是内核软件层过滤,非硬件加速;通过 FORWARD 链联合匹配 iifname 与 oifname 可实现 eth0↔eth1 双向流控制,推荐用接口索引(iif/oif)提升性能并增强稳定性。

nftables 的 meta iifname 并非“硬件级”过滤机制,它属于内核网络栈中 netfilter 框架的软件钩子层(位于 PREROUTING 链),运行在协议栈早期但仍在 CPU 上执行,不涉及网卡 DMA、TCAM 或 ASIC 硬件加速。所谓“原生引擎”实为 nft 表达式系统对 skb 元数据(如入接口名)的高效提取与匹配,其低开销源于:
- 避免解析 IP/TCP 头部(
iifname在sk_buff初始化时已由驱动填充) - 无状态匹配,无需连接跟踪模块(
ct state)参与 - 规则编译后由
nft虚拟机(nft_expr_eval)直接查表,无系统调用上下文切换
要实现跨物理网卡双向流的高效过滤(例如:只允许 eth0 ↔ eth1 流量,拒绝 eth0 ↔ eth0 或 eth1 ↔ eth1),关键在于理解流量方向与 iifname/oifname 的语义边界,并结合钩子点精准部署。
明确 iifname 和 oifname 的作用时机
iifname(入接口名)仅在 PREROUTING 和 INPUT 链可用,表示数据包**到达本机时进入的物理/虚拟接口**;
oifname(出接口名)仅在 FORWARD 和 OUTPUT 链可用,表示数据包**离开本机时使用的出口接口**。
对跨网卡转发流(如 `eth0 → eth1`):
- 从 `eth0` 进来的包:`iifname "eth0"` 在
PREROUTING或FORWARD链命中 - 将发往 `eth1` 的包:`oifname "eth1"` 在
FORWARD链命中 - 二者需在同一链(推荐
FORWARD)联合判断,才能完整约束双向路径
构建跨网卡双向流规则(FORWARD 链)
假设目标是:仅允许 `eth0 ↔ eth1` 之间的转发,禁止同网卡环回或其它组合。在 inet 表中定义:
nft add table inet filter
nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; }
nft add rule inet filter forward iifname "eth0" oifname "eth1" accept
nft add rule inet filter forward iifname "eth1" oifname "eth0" accept
说明:
- 使用
inet地址族自动覆盖 IPv4/IPv6,避免重复配置 -
policy drop设为默认拒绝,安全基线更清晰 - 两条规则分别覆盖正向与反向路径,合起来即双向流策略
- 不依赖 `ct state`,无连接跟踪开销,每包仅做两次字符串比较(内核中为指针比对,极快)
进一步降低开销:用接口索引替代名称匹配
接口名字符串匹配虽快,但仍涉及内存比对。若追求极致性能(如万兆线速下微秒级延迟),可改用内核分配的稳定接口索引(`iif` / `oif`):
# 查看接口索引
ip link show | awk '/^[0-9]+:/ {print $2, $1}'
# 示例输出:eth0: 2, eth1: 3
<h1>替换为索引匹配(更轻量)</h1><p>nft add rule inet filter forward iif 2 oif 3 accept
nft add rule inet filter forward iif 3 oif 2 accept
优势:
- `iif`/`oif` 是 32 位整数,比对为单条 CPU 指令
- 不受接口重命名(如 systemd-renamed `enp0s3`)影响,稳定性更高
- 适用于高吞吐场景(如 NFV、边缘网关)
验证与观测(避免误阻断)
启用计数器并实时查看匹配情况:
nft add rule inet filter forward iif 2 oif 3 counter accept nft add rule inet filter forward iif 3 oif 2 counter accept # 实时观察计数 nft list chain inet filter forward -a
注意:
- 确保 `net.ipv4.ip_forward=1` 已启用(`sysctl -w net.ipv4.ip_forward=1`)
- 确认物理连接与路由表正确(`ip route get 192.168.2.100 from 192.168.1.100 dev eth0`)
- 若使用 NetworkManager 或 cloud-init,检查其是否覆盖 `nft` 规则(建议禁用 firewalld)
不复杂但容易忽略


















