有没有什么方法可以快速有效地获取 Bash 中数千个 CIDR/网络掩码范围中的 IP 主机地址数量?

有没有什么方法可以快速有效地获取 Bash 中数千个 CIDR/网络掩码范围中的 IP 主机地址数量?

我使用 IPSet 管理数万个 IPv4 CIDR/网络掩码范围,然后将其链接到 IPTables 规则。此设置运行良好,但我希望获得 IPSet 作用的 IP 主机地址的良好、高级概览计数,以便用于客户端报告目的。

IPSet 条目格式始终如下:

123.456.0.0/16 timeout 86400

timeout因此,我可以在必须获取值以对条目包含的 CIDR/网络掩码范围起作用的行上进行 grep 。

例如,如果我将 IPSet 输出(通过ipset -L -n > ipset-20181228.txt)保存到名为的文本文件,然后运行和ipset-20181228.txt的组合,如下所示:grepwc -l

grep  "timeout" ipset-20181228.txt  | wc -l

我得到了 39,000 多个项目的计数,相当于 39,000 多个 CIDR/网络掩码范围。但这(当然)仅计算了 CIDR/网络掩码范围,而不是该范围内 IP 主机地址的完整计数。

我尝试使用prips(在 Bash 中将 CIDR/网络掩码值扩展为实际 IP 地址)使用 grep 仅剔除具有 CIDR/网络掩码范围的项目,如下所示:

grep -oE '(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([0-9]{1,2})' ipset-20181228.txt | awk 'NF { system( "prips " $0)  }' | wc -l

在我的 2018 款 MacBook Air 上(风扇运转)运行了整整 20 到 30 分钟(!!!)后,我得到的计数是 736,000,000+,这正是我想要的……但 20 到 30 分钟太长了。我希望它尽可能地可编写脚本且不具侵入性,并且不能相信这样的命令可以在生产服务器上运行而不会消耗资源;我的意思是看看它在我的本地 2018 款 MacBook Air 开发设置上的表现。

有没有办法仅根据 CIDR/网络掩码值来计算 CIDR/网络掩码范围计数?我希望有一些我不知道的命令行工具(或我正在使用的现有工具中的选项)可以提供帮助。

答案1

如果您的grep命令输出类似这样的行123.456.0.0/16,那么您需要将它们传输到

awk -F / '{ count[$2]++ } END { for (mask in count) total+=count[mask]*2^(32-mask); print total }'

该命令仅提取掩码(即 之后的内容/)并计算每个掩码的出现次数。最后计算每个遇到的掩码的主机数(2^(32-mask)),乘以出现次数并求和。

笔记:

  • 不执行健全性检查。例如,1.2.3.4/40将接受类似输入,计算非整数输出。grep如果需要,请改进您的初步过滤器。
  • 每个范围独立地对总数做出贡献。如果您的范围重叠,那么您将得到一个夸大的结果(我认为您的尝试prips在这方面并没有更好)。

答案2

我认为这样的事情会起作用,因为原始海报正在运行 grep 从以下行中获取 CIDR timeout

awk -F'[ /]' '/timeout/ {hosts+=2^(32-$2)};ENDFILE{print "Hosts number in "FILENAME": "hosts;total+=hosts;hosts=0};END {print "Total: "total}' ipset*.txt

编辑-awk上述程序只有在使用 时才能正常运行GNU awkENDFILE是 GNU 扩展。

如果它是主程序部分的一部分,我想BSD awk它会忽略并运行该部分。ENDFILE

这与 GNU 和 BSD awk 兼容。

awk -F'[ /]' '{if (filename != FILENAME) hosts=0};/timeout/ {hosts+=2^(32-$2)};{filename=FILENAME;file_total[filename]=hosts};END{for (i in file_total) {print "Hosts number in "i": "file_total[i];total+=file_total[i]};{print "Total: "total};}' ipset*.txt

相关内容