我使用 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
的组合,如下所示:grep
wc -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 awk
。ENDFILE
是 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