如何验证 CIDR(私有 IP 地址)范围是否在 RFC https://tools.ietf.org/html/rfc1918 中定义的任何范围内?
3. Private Address Space
The Internet Assigned Numbers Authority (IANA) has reserved the
following three blocks of the IP address space for private internets:
10.0.0.0 - 10.255.255.255 (10/8 prefix)
172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
上下文:AWS 或任何云提供商的问题在于,它们允许您使用所需的任何 CIDR 创建 VPC,它们永远不会受上述范围的约束。
例如,您甚至可以创建一个具有 CIDR:169.0.0.0.0/16
的 VPC,这很奇怪。
我们遇到了一个问题,花了几个小时来解决将一个新创建的 VPC 与思科 VPN 集成的问题。一位开发运维工程师创建了带有 CIDR:172.42.0.0/16
的 VPC。经过几个小时,我们知道如果 VPC CIDR 不属于上述 RFC 中提到的172.16.0.0/12
,VPN 将无法工作(这意味着仅支持 CIDR 范围从172.16.0.0/16
到172.31.0.0/16
)。
让我们只坚持这个 CIDR 范围:172.16.0.0/12
.第一个 IP 可以172.16.0.0
,最后一个 IP 可以172.31.255.255
。
到目前为止,我做了什么来解决这个问题?
玩了一下地形内置功能,但没有运气:
variable "cidr_block" {
type = string
validation {
condition = (
cidrhost(var.cidr_block, 0) >= "172.16.0.0" &&
cidrnetmask(var.cidr_block) <= "255.240.0.0"
)
error_message = "Must be a valid IPv4 CIDR block address. AS per RFC https://tools.ietf.org/html/rfc1918."
}
}
正则表达式:
我在这里创建了一个正则表达式:https://regex101.com/r/iYkowj/1 可以过滤范围绝对可以正常工作,但 terraform 不接受它。
所以问题是,我们如何在这里注入正则表达式或任何其他可以验证 CIDR 属于172.16.0.0/12
的函数?如果它属于此范围之外,则应显示错误。
好吧,这听起来很有趣。一、解决方案:
variable "cidr_block" {
type = string
validation {
condition = anytrue([can(regex("10(?:\.(?:[0-1]?[0-9]?[0-9])|(?:2[0-5]?[0-9])){3}\/", var.cidr_block)), can(regex("172\.(?:3?[0-1])|(?:[0-2]?[0-9])(?:\.[0-2]?[0-5]?[0-9]){2}\/(?:1[6-9]|2[0-9]|3[0-2])", var.cidr_block))])
error_message = "Must be a valid IPv4 CIDR block address."
}
}
现在解开这个。首先,我们有anytrue
函数。
如果给定集合中的任何元素为 true 或"true",则 anytrue 返回 true。如果集合为空,它还返回 false。
因此,我们需要此函数,因为我们有两个正则表达式要验证,anytrue
将验证其中一个或另一个成功。can
函数(您可能已经知道给定问题内容)如果未抛出错误,则返回true
,如果抛出错误,则返回false
。结合anytrue
,这意味着如果一个或另一个regex
函数成功找到匹配项,则至少一个true
作为列表中的元素返回,然后anytrue
返回true
并且验证成功。如果两个regex
都返回没有匹配项的错误,则两个can
返回false
,anytrue
也返回false
,然后验证失败。
至于特定的正则表达式本身,您可以查阅正则表达式文档以了解更多信息。您也可以自己使用此验证来验证它(我在开发此解决方案时也这样做,因为它有些复杂)。