nftables 可以在 crgroupv2 上执行路由后匹配吗?

nftables 可以在 crgroupv2 上执行路由后匹配吗?

我想更改给定 cgroup(版本 2)中进程生成的每个数据包的源地址。这可能吗?

我有:

  • nftables 1.0.2,
  • linux 5.15(Ubuntu 版本)
  • /system.slice/system-my-service.slice/[email protected]组组

我尝试过:

  • 创建一个表nft add table ip myservice
  • 创建后路由 nat 链nft add chain ip myservice postrouting { type nat hook postrouting priority 100 \; }
  • 尝试创建后路由规则nft add rule ip myservice postrouting socket cgroupv2 level 1 'system.slice' snat 10.0.0.1(在实验期间,我仅使用了,因为 nft在 cgroup 名称中'system.slice'存在问题,这将是 2 级问题:-)。@

我还发现cgroup需要 int32 参数的匹配,从中我猜测它是 cgroup 版本 1(因此不适用于我),因为我没有发现将路径样式 cgroup 转换为 int 的提示的痕迹。

我怀疑该socket表达式不适用于后路由 nat 链,如nft中所示Error: Could not process rule: Operation not supported

所有的失败是否意味着这是完全错误的方法?或者我只是错过了一些明显的事情?

答案1

这是您的两个问题的答案:

  • 句法

    cgroupv2需要一个路径,它是一个字符串。字符串始终用双引号显示,如果包含特殊字符则需要双引号。这些双引号供nft命令使用,而不是供 shell 使用。对于直接命令(即:不在使用 读取的文件中nft -f),这些双引号本身应该被转义或用单引号括起来,否则 shell 会消耗它们。

    此外,该路径被记录为相对的并且不需要前导/(无论如何,它在显示回来时被接受并删除),直接从 shell 给出:

    socket cgroupv2 level 3 '"system.slice/system-my-service.slice/[email protected]"'
    

    最后,nft不关心它是否给出具有多个标记的单个参数或一次一个标记的多个参数:该行的组装和解析相同。因此,每当 shell 有一个特殊字符(此处")时,只需用单引号引用所有行,而不是尝试找出在哪里转义字符(例如\;在基本链中)。

  • 解决限制

    您可以在输出钩子中标记数据包并检查后路由钩子中的标记以进行 NAT。

    nft 'add chain ip myservice { type filter hook output priority 0; policy accept; }'
    nft 'add rule ip myservice output socket cgroupv2 level 3 "system.slice/system-my-service.slice/[email protected]" meta mark set 0xcafe'
    nft add rule ip myservice postrouting meta mark 0xcafe snat to 10.0.0.1
    

最终结果可以放在自己的文件中,在开始处使用两个glue命令幂等性。拥有自己的文件可以防止与 shell 解析的任何交互,并获得原子更新。它仍然需要"..."围绕路径参数来没有nftables解释@角色。

myservice.nft:

table ip myservice
delete table ip myservice

table ip myservice {
    chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        meta mark 0xcafe snat to 10.0.0.1
    }

    chain output {
        type filter hook output priority 0; policy accept;
        socket cgroupv2 level 3 "system.slice/system-my-service.slice/[email protected]" meta mark set 0xcafe
    }
}

nft -f myservice.nft只要 cgroup 已经存在,就可以加载它(可能意味着,在启动时必须先启动该服务nftables加载此规则)。

到底:

  • 每个传出数据包都会经过过滤器/输出

    • 如果它来自一个充分的过程组组数据包将收到标记 0xcafe
  • 新流的每个第一个数据包都将遍历 nat/postrouting 规则。

    • 如果它与标记 0xcafe 匹配(意味着它处于适当的位置)组组)这将触发流的 SNAT 规则(然后标记不再重要)

相关内容