![如何在单个表达式中写入 /16 IP 地址范围?](https://linux22.com/image/196564/%E5%A6%82%E4%BD%95%E5%9C%A8%E5%8D%95%E4%B8%AA%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%B8%AD%E5%86%99%E5%85%A5%20%2F16%20IP%20%E5%9C%B0%E5%9D%80%E8%8C%83%E5%9B%B4%EF%BC%9F.png)
我想在 nginx 中禁止这个范围的中国 IP 地址:
'223.64.0.0 - 223.117.255.255'
我知道如何禁止每个/16
范围,例如:
deny 223.64.0.0/16;
但需要很多行才能包含整个223.64 - 223.117
范围。是否有一种简写符号可以在一行中完成此操作?
答案1
伊普计算(ipcalc
Debian 上的软件包)可以帮助你解聚将一个范围分解为多个匹配项CIDRs:
$ 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
与相同另一个 ipcalc(ipcalc-ng
Debian 上的包和命令名称):
$ 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
该选项有更多选项来改变输出格式:
$ 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
包括 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;
$ 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;
答案2
@StéphaneChazelas
' 答案非常好。如果OP或未来的读者可能更喜欢不是将结果汇总起来——例如,当每个 /16 被阻止时,但以一种细粒度的方式,允许将来取消阻止一个或多个单独的 /16,我经常使用 或jot
来seq
生成必要的 IP 范围。
有时人们只知道要阻止的网络的 CIDR。假设我们想要阻止 10.24.0.0/14,但粒度为单个 /16s。
# jot -w 10.%d.0.0/16 4 24
10.24.0.0/16
10.25.0.0/16
10.26.0.0/16
10.27.0.0/16
在上面的示例中,4
出现该常数是因为 /14 中有 4 个 /16,或者换句话说,2**(16-14) = 2**2 = 4。
将 10.0.64.0/19 作为一系列 /24 进行阻止:
# jot -w 10.0.%d.0/24 32 64
10.0.64.0/24
10.0.65.0/24
10.0.66.0/24
...
10.0.92.0/24
10.0.93.0/24
10.0.94.0/24
10.0.95.0/24
再次使用常数 32,因为 /19 中有 32 个 /24。或者以另一种方式计算,2**(24-19) == 2**5 == 32。
其他时候,CIDR 语法中未指定网络范围,要么是因为它不属于严格的 CIDR 边界,要么只是因为源文档的作者选择不使用 CIDR 表示法。 seq
有时更容易适应这种情况。
要阻止 10.100.0.0 到 10.109.255.255:
# seq -f '10.%g.0.0/16' 100 109
10.100.0.0/16
10.101.0.0/16
10.102.0.0/16
10.103.0.0/16
10.104.0.0/16
10.105.0.0/16
10.106.0.0/16
10.107.0.0/16
10.108.0.0/16
10.109.0.0/16
显然,仅将这些 IP 范围输出到 stdout 本身不会阻止任何内容。假设用户将vi
它们放入配置文件中,或者将它们通过管道传输到 shell 脚本或其他将执行必要工作的系统命令。如果所需的命令语法足够简单,seq
或者jot
可以直接用于生成 shell 输入:
# seq -f 'ipfw add 560 deny ip from 10.%g.0.0/16 to any' 100 109
ipfw add 560 deny ip from 10.100.0.0/16 to any
ipfw add 560 deny ip from 10.101.0.0/16 to any
ipfw add 560 deny ip from 10.102.0.0/16 to any
ipfw add 560 deny ip from 10.103.0.0/16 to any
ipfw add 560 deny ip from 10.104.0.0/16 to any
ipfw add 560 deny ip from 10.105.0.0/16 to any
ipfw add 560 deny ip from 10.106.0.0/16 to any
ipfw add 560 deny ip from 10.107.0.0/16 to any
ipfw add 560 deny ip from 10.108.0.0/16 to any
ipfw add 560 deny ip from 10.109.0.0/16 to any
seq
检查这些命令的准确性后,可以通过管道传送sh
并执行 的输出。
提供此解决方案只是为了表明,与许多 UNIX 任务一样,如果优先考虑(或者实际上需要)粒度而不是聚合,则有一些基本构建块可以完成此任务。