使用来自 python 的 libnftables-json API 添加 nftables 映射元素

Add nftables map element using libnftables-json API from python

我正在尝试使用来自 python 的 nftables JSON API 动态添加地图元素。在我的防火墙中,我在 ip 系列的 router table 中有以下映射:

map port_forwards {
    type inet_service: ipv4_addr . inet_service;
}

这是我正在尝试做的一个最小示例:

import nftables

nft_cmd = {"nftables": [
    { "add": { "element":{
        "family": "ip",
        "table": "router",
        "name": "port_forwards",
        "elem": { "map": {
            "key": "80",
            "data": "172.16.0.1 . 80"
        }}
    }}}
]}

nft = nftables.Nftables()
nft.json_validate(nft_cmd)
rc, _output, error = nft.json_cmd(nft_cmd)
if rc != 0:
    raise RuntimeError(f"Error running nftables command: {error}")

这会导致以下错误:

RuntimeError: Error running nftables command: internal:0:0-0: Error: Unexpected JSON type object for immediate value.

internal:0:0-0: Error: Invalid set.

internal:0:0-0: Error: Parsing command array at index 0 failed.

我假设我对规范有某种误解 (https://manpages.debian.org/unstable/libnftables1/libnftables-json.5.en.html),但我想不出正确的用法。

更新:我发现 nft 可以用 json 格式回显您的命令。这是命令:

sudo nft -e -j add element ip router port_forwards '{80 : 172.16.0.1 . 8080 }'

并且回复漂亮:

{"nftables": [
    {"add": {"element": {
        "family": "ip",
        "table": "router",
        "name": "port_forwards",
        "elem": {"set": [[
            80,
            {"concat": ["172.16.0.1", 8080]}
        ]]}
    }}}
]}

不幸的是,将其复制到上面的 python 代码中仍然会导致相同的错误

事实证明,"elem" 属性 直接获取数组,而不是包裹在 "set" 对象中。错误暗示了这一点:

Unexpected JSON type object for immediate value.

工作代码如下所示:

import nftables

nft_cmd = {"nftables": [
    { "add": { "element":{
        "family": "ip",
        "table": "router",
        "name": "port_forwards",
        "elem": [[
            80,
            {"concat": ["172.16.0.1", 8080]}
        ]]
    }}}
]}


nft = nftables.Nftables()
nft.json_validate(nft_cmd)
rc, _output, error = nft.json_cmd(nft_cmd)
if rc != 0:
    raise RuntimeError(f"Error running nftables command: {error}")