使用经典 ASP,我想检查给定的 IP 是否在 CIDR 中的 IP 范围内(例如 192.168.0.0/24)。
一些例子是:
192.168.0.1
属于192.168.0.0/24
? (是的)192.168.0.100
属于192.168.0.0/24
? (是的)192.168.0.130
属于192.168.0.0/25
? (不!这个是192.168.0.0-192.168.0.127
)当然,使用从
/32
到 /0
的位掩码(好吧,后者应该对所有事情说“是”)
实际用例是通过他们提供的 ipv4 端点列表来检查声称 CF-Connecting-IP 标头的 CloudFlare 代理连接是否实际上来自 CloudFlare。
我进行了广泛的搜索,基本上我在 Stackoverflow 中发现的都是关于返回 IP 范围或正则表达式验证 IP 的内容,因此它们要么对我的情况没有帮助,要么让我的代码基于起来很麻烦。
由于我没有找到任何东西可以满足我的需要,所以我按照我认为 IPv4 的工作方式自己编写了它,具体如下:
function ip4toint(ip)
ip_fields = split(ip, ".")
ip4toint = cint(ip_fields(0))*(256^3) + cint(ip_fields(1))*(256^2) + cint(ip_fields(2))*(256) + cint(ip_fields(3))
end function
function ip4netmask(ip, cidr)
cidr_fields = split(cidr, "/")
cidr_ip = cidr_fields(0)
cidr_int = ip4toint(cidr_ip)
mask_bits = cidr_fields(1)
if mask_bits = 0 then ' no need for more math. always true
ip4netmask = true
exit function
end if
ip_int = ip4toint(ip)
mask_int = cint("&hffffffff")
if mask_bits < 32 and mask_bits > 0 then
mask_int = mask_int - (2^(32 - cint(mask_bits)) - 1)
end if
ip4netmask = (cidr_int and mask_int) = (ip_int and mask_int)
end function
因此我用它来测试结果:
function testip4n(ip, range)
testip4n = "ip:" & ip & " range cidr: " & range & " ip in range: " & ip4netmask(ip, range)
end function
然后从具有各种值和预期结果的测试页面调用它:
<%=testip4n("10.3.172.198", "10.3.172.198/32")%> [expect:true]<br />
<%=testip4n("10.3.172.198", "10.3.172.199/32")%> [expect:false]<br />
<%=testip4n("10.3.172.198", "10.3.172.197/32")%> [expect:false]<br />
<%=testip4n("10.3.172.198", "10.3.172.199/31")%> [expect:true]<br />
<%=testip4n("10.3.172.198", "10.3.172.197/31")%> [expect:false]<br />
<%=testip4n("10.3.172.198", "10.3.172.100/24")%> [expect:true]<br />
<%=testip4n("10.3.172.198", "10.3.172.205/24")%> [expect:true]<br />
<%=testip4n("10.3.172.198", "10.3.174.198/24")%> [expect:false]<br />
<%=testip4n("10.3.172.198", "10.3.170.198/20")%> [expect:true]<br />
<%=testip4n("10.3.172.198", "10.3.170.198/0")%> [expect:true]<br />
<%=testip4n("10.1.172.198", "10.3.170.198/0")%> [expect:true]<br />
<%=testip4n("10.3.112.198", "10.3.170.198/0")%> [expect:true]<br />
实现中的一个特殊“好处”是,它确实将 CIDR IP 修剪为实际的网络地址,因此您不需要显式指定
192.168.0.0/24
,因为 192.168.0.15/24
将被“修剪”其实际网络地址。这有助于处理虚假值,就像我使用 Linux 工具(如 iproute2)所经历的那样。