如何在单个表达式中写入 /16 IP 地址范围?

bln*_*nks 10 ip

我想在 nginx 中禁止这个范围的中国 IP 地址:

 '223.64.0.0 - 223.117.255.255'
Run Code Online (Sandbox Code Playgroud)

我知道如何禁止每个/16范围,例如:

deny 223.64.0.0/16;
Run Code Online (Sandbox Code Playgroud)

但需要很多行才能包含整个223.64 - 223.117范围。是否有一种简写符号可以在一行中完成此操作?

Sté*_*las 26

ipcalcipcalcDebian 上的软件包)可以帮助您将一个范围分解为多个匹配的CIDR

$ ipcalc -r 223.64.0.0 - 223.117.255.255
deaggregate 223.64.0.0 - 223.117.255.255
223.64.0.0/11
223.96.0.0/12
223.112.0.0/14
223.116.0.0/15
Run Code Online (Sandbox Code Playgroud)

其他 ipcalc相同(ipcalc-ngDebian 上的包和命令名称):

$ ipcalc-ng -d '223.64.0.0 - 223.117.255.255'
[Deaggregated networks]
Network:        223.64.0.0/11
Network:        223.96.0.0/12
Network:        223.112.0.0/14
Network:        223.116.0.0/15
Run Code Online (Sandbox Code Playgroud)

该选项有更多选项来改变输出格式:

$ ipcalc-ng --no-decorate -d '223.64.0.0 - 223.117.255.255'
223.64.0.0/11
223.96.0.0/12
223.112.0.0/14
223.116.0.0/15
Run Code Online (Sandbox Code Playgroud)

包括 json,如果与以下工具结合使用,它可以提供无限的重新格式化的可能性jq

$ ipcalc-ng -j -d '223.64.0.0 - 223.117.255.255' |
    jq -r '.DEAGGREGATEDNETWORK[]|"deny " + . + ";"'
deny 223.64.0.0/11;
deny 223.96.0.0/12;
deny 223.112.0.0/14;
deny 223.116.0.0/15;
Run Code Online (Sandbox Code Playgroud)
$ ipcalc-ng -j -d '223.64.0.0 - 223.117.255.255' |
   jq -r '"deny " + (.DEAGGREGATEDNETWORK|join(" ")) + ";"'
deny 223.64.0.0/11 223.96.0.0/12 223.112.0.0/14 223.116.0.0/15;
Run Code Online (Sandbox Code Playgroud)

  • 为了完成这个答案,该技术的术语是[supernetting](https://en.wikipedia.org/wiki/Supernetwork)。感谢您提供的新工具 - 我不知道 `ipcalc` 和 `ipcalc-ng` 的存在:-) (5认同)
  • RHEL 8 有 Python 吗?使用 [ipaddress](https://docs.python.org/3/library/ipaddress.html#ipaddress.summarize_address_range) 模块,您将得到相同的结果,例如 `python3 -c "import sys, ipaddress; 首先,最后=映射(ipaddress.ip_address, sys.argv[1:3]); print(*ipaddress.summarize_address_range(first, last), sep='\n')" 223.64.0.0 223.117.255.255`. (3认同)

Jim*_* L. 7

@St\xc3\xa9phaneChazelas' 答案非常好。如果 OP 或未来的读者可能不希望汇总结果 - 例如当每个 /16 被阻止时,但以一种细粒度的方式允许将来取消阻止一个或多个单独的 /16,我经常使用jot或者seq来生成所需的 IP 范围。

\n

有时人们只知道要阻止的网络的 CIDR。假设我们想要阻止 10.24.0.0/14,但粒度为单个 /16s。

\n
# jot -w 10.%d.0.0/16 4 24\n10.24.0.0/16\n10.25.0.0/16\n10.26.0.0/16\n10.27.0.0/16\n
Run Code Online (Sandbox Code Playgroud)\n

在上面的示例中,4出现该常数是因为 /14 中有 4 个 /16,或者换句话说,2**(16-14) = 2**2 = 4。

\n

将 10.0.64.0/19 作为一系列 /24 进行阻止:

\n
# jot -w 10.0.%d.0/24 32 64\n10.0.64.0/24\n10.0.65.0/24\n10.0.66.0/24\n...\n10.0.92.0/24\n10.0.93.0/24\n10.0.94.0/24\n10.0.95.0/24\n
Run Code Online (Sandbox Code Playgroud)\n

再次使用常数 32,因为 /19 中有 32 个 /24。或者以另一种方式计算,2**(24-19) == 2**5 == 32。

\n

其他时候,CIDR 语法中未指定网络范围,要么是因为它不属于严格的 CIDR 边界,要么只是因为源文档的作者选择不使用 CIDR 表示法。 seq有时更容易适应这种情况。

\n

要阻止 10.100.0.0 到 10.109.255.255:

\n
# seq -f '10.%g.0.0/16' 100 109\n10.100.0.0/16\n10.101.0.0/16\n10.102.0.0/16\n10.103.0.0/16\n10.104.0.0/16\n10.105.0.0/16\n10.106.0.0/16\n10.107.0.0/16\n10.108.0.0/16\n10.109.0.0/16\n
Run Code Online (Sandbox Code Playgroud)\n

显然,仅将这些 IP 范围输出到 stdout 本身不会阻止任何内容。假设用户将vi它们放入配置文件中,或者将它们通过管道传输到 shell 脚本或其他将执行必要工作的系统命令。如果所需的命令语法足够简单,seq或者jot可以直接用于生成 shell 输入:

\n
# seq -f 'ipfw add 560 deny ip from 10.%g.0.0/16 to any' 100 109\nipfw add 560 deny ip from 10.100.0.0/16 to any\nipfw add 560 deny ip from 10.101.0.0/16 to any\nipfw add 560 deny ip from 10.102.0.0/16 to any\nipfw add 560 deny ip from 10.103.0.0/16 to any\nipfw add 560 deny ip from 10.104.0.0/16 to any\nipfw add 560 deny ip from 10.105.0.0/16 to any\nipfw add 560 deny ip from 10.106.0.0/16 to any\nipfw add 560 deny ip from 10.107.0.0/16 to any\nipfw add 560 deny ip from 10.108.0.0/16 to any\nipfw add 560 deny ip from 10.109.0.0/16 to any\n
Run Code Online (Sandbox Code Playgroud)\n

seq检查这些命令的准确性后,可以通过管道传送并执行的输出sh

\n

提供此解决方案只是为了表明,与许多 UNIX 任务一样,如果优先考虑(或者实际上需要)粒度而不是聚合,则有一些基本构建块可以完成此任务。

\n