You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
4.6 KiB
134 lines
4.6 KiB
package ipcheck
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"gitea.drugeyes.vip/pharnexbase/ipcheck/utils"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// SingleIpInRange 单个ip地址(范围)判断是否在配置ip范围内
|
|
func SingleIpInRange(ip, ipConfigStr string) (bool, error) {
|
|
singleIp := utils.NewIpRange(ip)
|
|
if singleIp == nil {
|
|
return false, errors.New("ip格式错误!")
|
|
}
|
|
|
|
//判断ip范围是否满足从小到大的规则
|
|
if err := singleIp.CheckIpRange(); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
ipConfigArr := strings.Split(strings.ReplaceAll(ipConfigStr, "\r\n", "\n"), "\n")
|
|
for _, ipConfig := range ipConfigArr {
|
|
containIp := utils.NewIpRange(ipConfig)
|
|
if containIp != nil && singleIp.Type() == containIp.Type() { //只有ip类型相同才判断范围
|
|
if containIp.IsContain(singleIp) {
|
|
return true, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
// MultipleIpInRange 多个ip地址判断是否在配置ip范围内(该方法在ips很多,且配置ip很多的时候会有速度提升,单个ip的时候不建议使用该方法)
|
|
func MultipleIpInRange(ips, ipConfigStr []string) (bool, string, error) {
|
|
ownerIpv4s, ownerIpv6s, errIp, err := FilterIpAndSort(ips)
|
|
if err != nil {
|
|
return false, errIp, err
|
|
}
|
|
|
|
containIpv4s, containIpv6s, errIp, err := FilterIpAndSort(strings.Split(strings.ReplaceAll(strings.Join(ipConfigStr, "\n"), "\r\n", "\n"), "\n"))
|
|
if err != nil {
|
|
return false, errIp, err
|
|
}
|
|
|
|
//优化步骤
|
|
var ipv4Start uint32 = 0 //自己ip段重复也需要提示
|
|
//处理判断ipv4(双指针)
|
|
for i, j := 0, 0; i < len(ownerIpv4s) && j < len(containIpv4s); {
|
|
ownerLeft := utils.Ipv4ToUint32(ownerIpv4s[i][0])
|
|
ownerRight := utils.Ipv4ToUint32(ownerIpv4s[i][1])
|
|
if ownerLeft > utils.Ipv4ToUint32(containIpv4s[j][1]) { //如果范围ip右边值都比目标ip的左边值小则增加范围ip的指针
|
|
j++
|
|
continue
|
|
}
|
|
|
|
if containIpv4s[j].IsContain(ownerIpv4s[i]) || ownerIpv4s[i].IsContain(containIpv4s[j]) {
|
|
return true, fmt.Sprintf("%s<-->%s", ownerIpv4s[i].IpString(), containIpv4s[j].IpString()), errors.New("输入ip与已存在ip配置范围重叠!")
|
|
}
|
|
|
|
if ipv4Start >= ownerLeft { //判断自己ip段是否重复,重复就返回重复的ip
|
|
if i > 0 {
|
|
return false, fmt.Sprintf("%s<-->%s", ownerIpv4s[i-1].IpString(), ownerIpv4s[i].IpString()), errors.New("输入ip范围重叠!")
|
|
}
|
|
return false, ownerIpv4s[i].IpString(), errors.New("请勿填写0.0.0.0和0:0:0:0:0:0:0:0等无效ip!")
|
|
}
|
|
ipv4Start = ownerRight
|
|
i++
|
|
}
|
|
|
|
var ipv6Start = utils.Uint128{H: 0, L: 0} //自己ip段重复也需要提示
|
|
//处理判断ipv6(双指针)
|
|
for i, j := 0, 0; i < len(ownerIpv6s) && j < len(containIpv6s); {
|
|
ownerLeft := utils.Ipv6ToUint128(ownerIpv6s[i][0])
|
|
ownerRight := utils.Ipv6ToUint128(ownerIpv6s[i][1])
|
|
containRight := utils.Ipv6ToUint128(containIpv6s[j][1])
|
|
if (ownerLeft.H > containRight.H) || (ownerLeft.H == containRight.H && ownerLeft.L > containRight.L) {
|
|
j++
|
|
continue
|
|
}
|
|
|
|
if containIpv6s[j].IsContain(ownerIpv6s[i]) || ownerIpv6s[i].IsContain(containIpv6s[j]) {
|
|
return true, fmt.Sprintf("%s<-->%s", ownerIpv6s[i].IpString(), containIpv6s[j].IpString()), errors.New("输入ip与已存在ip配置范围重叠!")
|
|
}
|
|
|
|
if (ipv6Start.H > ownerLeft.H) || (ipv6Start.H == ownerLeft.H && ipv6Start.L >= ownerLeft.L) { //判断自己ip段是否重复,重复就返回重复的ip
|
|
if i > 0 {
|
|
return false, fmt.Sprintf("%s<-->%s", ownerIpv6s[i-1].IpString(), ownerIpv6s[i].IpString()), errors.New("输入ip范围重叠!")
|
|
}
|
|
return false, ownerIpv6s[i].IpString(), errors.New("请勿填写0.0.0.0和0:0:0:0:0:0:0:0等无效ip!")
|
|
}
|
|
ipv6Start = ownerRight
|
|
i++
|
|
}
|
|
|
|
return false, "", nil
|
|
}
|
|
|
|
// FilterIpAndSort 筛选出ipv4和ipv6并排序
|
|
func FilterIpAndSort(ips []string) (ipv4s []utils.Ipv4, ipv6s []utils.Ipv6, errIp string, err error) {
|
|
for _, ip := range ips {
|
|
ownerIp := utils.NewIpRange(ip)
|
|
if ownerIp == nil {
|
|
return ipv4s, ipv6s, ip, errors.New("ip格式错误!")
|
|
}
|
|
|
|
//判断ip范围是否满足从小到大的规则
|
|
if err := ownerIp.CheckIpRange(); err != nil {
|
|
return ipv4s, ipv6s, ip, err
|
|
}
|
|
|
|
if ownerIp.Type() == utils.Ipv4Type {
|
|
ipv4s = append(ipv4s, ownerIp.(utils.Ipv4))
|
|
} else {
|
|
ipv6s = append(ipv6s, ownerIp.(utils.Ipv6))
|
|
}
|
|
}
|
|
|
|
//处理排序
|
|
sort.Slice(ipv4s, func(i, j int) bool {
|
|
return utils.Ipv4ToUint32(ipv4s[i][0]) < utils.Ipv4ToUint32(ipv4s[j][0])
|
|
})
|
|
|
|
sort.Slice(ipv6s, func(i, j int) bool {
|
|
if utils.Ipv6ToUint128(ipv6s[i][0]).H < utils.Ipv6ToUint128(ipv6s[j][0]).H {
|
|
return true
|
|
}
|
|
return utils.Ipv6ToUint128(ipv6s[i][0]).H == utils.Ipv6ToUint128(ipv6s[j][0]).H && utils.Ipv6ToUint128(ipv6s[i][0]).L < utils.Ipv6ToUint128(ipv6s[j][0]).L
|
|
})
|
|
|
|
return
|
|
}
|
|
|