如何以最佳方式从文件中添加 CIDR 以进行设置?

如何以最佳方式从文件中添加 CIDR 以进行设置?

所以我有几个包含CIDR条目的文件(例如1.1.1.0/24)。任务是NFTables使用 bash 脚本将这些文件中的条目添加到一组。在这样做时,我仅限于OpenWRT公用事业。

问题是这些文件中可能有很多条目,并且它们可能会耗尽条目的限制每个命令 4096 个字符。而且这些文件会自动更新cron,因此也需要定期删除和重新填充一组文件。

在我看来,有一种比我已经做到的更简单的方法。我还想减少这个混乱的执行时间。这是我的尝试。

nft add element $TARGET_SET { $(awk '{print $1 ", "}' "$CUSTOM_CIDRS_FILE") }

这里还有一个问题,如果我的文件有大量条目,我会克服每个命令 4096 个字符的限制吗?最后一个问题,如果我在循环中一次添加一个条目,形成一组是否需要很长时间?

我主要等待经过良好实践的答案。

答案1

awk可以构建一个要执行的字符串,该字符串可以保持在特定长度以下;这无疑比 xargs必须分叉echo ... | tr管道更有效。

#!/usr/bin/env awk
{
    len = length()
    if (len > limit) {
        if (length(outbuf)) {
            system("echo " ENVIRON["TARGET_SET"] outbuf)
        }
        outbuf = $0
        # the limit will be 4096 minus the length of the rest of
        # the command and if the 4096 is kern.argmax then you
        # may need to subtract even more to account for the
        # length of the environment variables!
        limit = 6
    } else {
        # join another field to output buffer
        outbuf = outbuf "," $0
    }
    # the plus is for the length of the field joiner
    limit -= len + 1
}
END {
    if (length(outbuf)) {
        system("echo " ENVIRON["TARGET_SET"] outbuf)
    }
}

该脚本中的内容"echo "用于测试,可能会运行合适的nft ...命令。TARGET_SET必须导出以便awk可以从环境中读取它。

答案2

您在哪里读到过 nftables 命令中 4096 个字符的限制?如果我有 4000 个 CIDR 范围的列表(几乎 64,000 个字符),我可以运行您的命令而不会出现错误:

# wc -l ranges.txt
400.0 ranges.txt
# export TARGET_SET=example_set
# export CUSTOM_CIDRS_FILE=ranges.txt
# nft add set ip filter $TARGET_SET { type ipv4_addr\; flags interval\; }
# nft add element $TARGET_SET { $(awk '{print $1 ", "}' "$CUSTOM_CIDRS_FILE") }

这些nft add命令运行大约 0.003 秒,包含 4000 个元素。

似乎在某些时候我们可能会遇到 Linux 命令行长度限制,在这种情况下我们可以批量处理。这将以 1000 个为批次添加元素:

xargs -n1000 sh -c '
  nft add element ip filter $TARGET_SET { $(
    echo "$@" | tr " " ","
  ) }' -- < $CUSTOM_CIDRS_FILE

(请注意,上面假设TARGET_SET是环境变量,而不是 shell 变量。)

对于相同的 4000 个元素,运行时间约为 0.1 秒。

相关内容