判断两个CIDR是否有IP冲突

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了判断两个CIDR是否有IP冲突相关的知识,希望对你有一定的参考价值。

1.校验网段是否合法

1.1函数

import (
"fmt"
"net"
)
func IsNetWorkOk(network string ) bool
_, _, err := net.ParseCIDR(network)
if err != nil
return false

return true

判断两个CIDR是否有IP冲突_最小值

1.2分析

第一步就是先split变成ip跟子网掩码

主要原理就是变成二进制以后再进行判断

ipv4跟ipv6都可以校验,如果只想校验ipv4可以调用parseIPv4方法


1.3主函数运行测试

func main() 
ip := "100.4.11.3/24"
result := IsNetWorkOk(ip)
fmt.Println(result)

2.校验ip是否合法

2.1函数

func IsIpOk(ip string ) bool
address := net.ParseIP(ip)
if address == nil
return false

return true

2.2分析

判断两个CIDR是否有IP冲突_运行测试_02

点分十进制换成2进制,判断是否合法

判断两个CIDR是否有IP冲突_运行测试_03

2.3主函数运行测试

func main() 
ip := "100.4.11.34"
result := IsIpOk(ip)
fmt.Println(result)

3.判断两个网段,一个是否是另一个的子网

3.1函数

func ContainsCIDR(a, b *net.IPNet) bool 
ones1, _ := a.Mask.Size()
ones2, _ := b.Mask.Size()
return ones1 <= ones2 && a.Contains(b.IP)


//最好提前做好网段是否合法校验
func ContainsCIDRString(a,b string)(bool,error)
_, net1, err := net.ParseCIDR(a)
if err != nil
return false,err

_, net2, err := net.ParseCIDR(b)
if err != nil
return false,err

result := ContainsCIDR(net1,net2)
return result,err

3.2分析

判断两个CIDR是否有IP冲突_主函数_04

调用了ip包含的方法

3.3运行测试

func main() 
net1 := "100.64.0.0/16"
net2 := "100.64.0.0/20"
_, a, err := net.ParseCIDR(net1)
_, b, err := net.ParseCIDR(net2)
if err != nil
return

result := ContainsCIDR(a,b)
fmt.Println(result)

4.判断两个网段是否冲突

4.1函数

package main

import (
"fmt"
"strconv"
"strings"
)

func main()
s1:="192.168.0.0/24"
s2:="192.168.15.0/20"
b:=IsCIDROverlay(s1,s2)
fmt.Println(b)

//判断CIDR是否相交
//true代表相交
func IsCIDROverlay(s1, s2 string) bool
minIp1, maxIp1 := getCidrIpRange(s1)
minIp2, maxIp2 := getCidrIpRange(s2)
if compareIp(maxIp1, minIp2) == -1 ||
compareIp(minIp1, maxIp2) == 1
return false

return true


//返回1代表大于s1>s2,
//返回-1代表大于s1<s2,
//返回0代表大于s1=s2,
func compareIp(s1, s2 string) int
ip1 := strings.Split(s1, ".")
ip2 := strings.Split(s2, ".")
for i := 0; i < 4; i++
ipInt1, _ := strconv.Atoi(ip1[i])
ipInt2, _ := strconv.Atoi(ip2[i])
if ipInt1 < ipInt2
return -1
else if ipInt1 > ipInt2
return 1


return 0


func getCidrIpRange(cidr string) (string, string)
ip := strings.Split(cidr, "/")[0]
ipSegs := strings.Split(ip, ".")
maskLen, _ := strconv.Atoi(strings.Split(cidr, "/")[1])
seg1MinIp, seg1MaxIp := getIpSeg1Range(ipSegs, maskLen)
seg2MinIp, seg2MaxIp := getIpSeg2Range(ipSegs, maskLen)
seg3MinIp, seg3MaxIp := getIpSeg3Range(ipSegs, maskLen)
seg4MinIp, seg4MaxIp := getIpSeg4Range(ipSegs, maskLen)
return strconv.Itoa(seg1MinIp) + "." + strconv.Itoa(seg2MinIp)+ "." + strconv.Itoa(seg3MinIp) + "." + strconv.Itoa(seg4MinIp),
strconv.Itoa(seg1MaxIp) + "." + strconv.Itoa(seg2MaxIp)+ "." + strconv.Itoa(seg3MaxIp) + "." + strconv.Itoa(seg4MaxIp)


//计算得到CIDR地址范围内可拥有的主机数量
func getCidrHostNum(maskLen int) uint
cidrIpNum := uint(0)
var i uint = uint(32 - maskLen - 1)
for ; i >= 1; i--
cidrIpNum += 1 << i

return cidrIpNum


//获取Cidr的掩码
func getCidrIpMask(maskLen int) string
// ^uint32(0)二进制为32个比特1,通过向左位移,得到CIDR掩码的二进制
cidrMask := ^uint32(0) << uint(32-maskLen)
fmt.Println(fmt.Sprintf("%b \\n", cidrMask))
//计算CIDR掩码的四个片段,将想要得到的片段移动到内存最低8位后,将其强转为8位整型,从而得到
cidrMaskSeg1 := uint8(cidrMask >> 24)
cidrMaskSeg2 := uint8(cidrMask >> 16)
cidrMaskSeg3 := uint8(cidrMask >> 8)
cidrMaskSeg4 := uint8(cidrMask & uint32(255))

return fmt.Sprint(cidrMaskSeg1) + "." + fmt.Sprint(cidrMaskSeg2) + "." + fmt.Sprint(cidrMaskSeg3) + "." + fmt.Sprint(cidrMaskSeg4)




func getIpSeg1Range(ipSegs []string, maskLen int) (int, int)
if maskLen > 8
segIp, _ := strconv.Atoi(ipSegs[0])
return segIp, segIp

ipSeg, _ := strconv.Atoi(ipSegs[0])
return getIpSegRange(uint8(ipSeg), uint8(8-maskLen))


func getIpSeg2Range(ipSegs []string, maskLen int) (int, int)
if maskLen > 16
segIp, _ := strconv.Atoi(ipSegs[1])
return segIp, segIp

ipSeg, _ := strconv.Atoi(ipSegs[1])
return getIpSegRange(uint8(ipSeg), uint8(16-maskLen))



//得到第三段IP的区间(第一片段.第二片段.第三片段.第四片段)
func getIpSeg3Range(ipSegs []string, maskLen int) (int, int)
if maskLen > 24
segIp, _ := strconv.Atoi(ipSegs[2])
return segIp, segIp

ipSeg, _ := strconv.Atoi(ipSegs[2])
return getIpSegRange(uint8(ipSeg), uint8(24-maskLen))


//得到第四段IP的区间(第一片段.第二片段.第三片段.第四片段)
func getIpSeg4Range(ipSegs []string, maskLen int) (int, int)
ipSeg, _ := strconv.Atoi(ipSegs[3])
segMinIp, segMaxIp := getIpSegRange(uint8(ipSeg), uint8(32-maskLen))
return segMinIp + 1, segMaxIp

//根据用户输入的基础IP地址和CIDR掩码计算一个IP片段的区间
//或是加法 ^是异或
func getIpSegRange(userSegIp, offset uint8) (int, int)
var ipSegMax uint8 = 255
netSegIp := ipSegMax << offset
segMinIp := netSegIp & userSegIp
segMaxIp := segMinIp | ^(ipSegMax << offset)
return int(segMinIp), int(segMaxIp)

4.2分析

判断两个CIDR是否有IP冲突_主函数_05

判断两个CIDR是否有IP冲突_主函数_06

A网段最小值大于B网段最大值,或者A网段最大值小于B网段最小值代表两个网段没有重叠部分

4.3运行测试

​在线网络地址计算器​

func main() 
s1:="192.168.14.0/20"
s2:="192.168.15.0/20"
b:=IsCIDROverlay(s1,s2)
fmt.Println(b)

判断两个CIDR是否有IP冲突_最小值_07


以上是关于判断两个CIDR是否有IP冲突的主要内容,如果未能解决你的问题,请参考以下文章

IP 地址重叠/在 CIDR 范围内

如何从 PostgreSQL 中的两个 IP 获取 CIDR?

Nginx的访问控制

Python中的IP地址列表到CIDR列表

计算公式

无分类编址(CIDR)构成超网