Files
EdgeNode/internal/waf/values/ip_range.go

133 lines
2.8 KiB
Go
Raw Normal View History

2023-01-06 19:14:09 +08:00
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package values
import (
"bytes"
"net"
"strings"
)
type IPRangeType = string
const (
IPRangeTypeCIDR IPRangeType = "cidr" // CIDR
IPRangeTypeSingeIP IPRangeType = "singleIP" // 单个IP
IPRangeTypeRange IPRangeType = "range" // IP范围IP1-IP2
)
type IPRange struct {
Type IPRangeType
CIDR *net.IPNet
IPFrom net.IP
IPTo net.IP
}
func (this *IPRange) Contains(netIP net.IP) bool {
if netIP == nil {
return false
}
switch this.Type {
case IPRangeTypeCIDR:
if this.CIDR != nil {
return this.CIDR.Contains(netIP)
}
case IPRangeTypeSingeIP:
if this.IPFrom != nil {
return bytes.Equal(this.IPFrom, netIP)
}
case IPRangeTypeRange:
return bytes.Compare(this.IPFrom, netIP) <= 0 && bytes.Compare(this.IPTo, netIP) >= 0
}
return false
}
type IPRangeList struct {
Ranges []*IPRange
}
func NewIPRangeList() *IPRangeList {
return &IPRangeList{}
}
func ParseIPRangeList(value string) *IPRangeList {
var list = NewIPRangeList()
if len(value) == 0 {
return list
}
var lines = strings.Split(value, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if len(line) == 0 {
continue
}
if strings.Contains(line, ",") { // IPFrom,IPTo
var pieces = strings.SplitN(line, ",", 2)
if len(pieces) == 2 {
var ipFrom = net.ParseIP(strings.TrimSpace(pieces[0]))
var ipTo = net.ParseIP(strings.TrimSpace(pieces[1]))
if ipFrom != nil && ipTo != nil {
if bytes.Compare(ipFrom, ipTo) > 0 {
ipFrom, ipTo = ipTo, ipFrom
}
list.Ranges = append(list.Ranges, &IPRange{
Type: IPRangeTypeRange,
IPFrom: ipFrom,
IPTo: ipTo,
})
}
}
} else if strings.Contains(line, "-") { // IPFrom-IPTo
var pieces = strings.SplitN(line, "-", 2)
if len(pieces) == 2 {
var ipFrom = net.ParseIP(strings.TrimSpace(pieces[0]))
var ipTo = net.ParseIP(strings.TrimSpace(pieces[1]))
if ipFrom != nil && ipTo != nil {
if bytes.Compare(ipFrom, ipTo) > 0 {
ipFrom, ipTo = ipTo, ipFrom
}
list.Ranges = append(list.Ranges, &IPRange{
Type: IPRangeTypeRange,
IPFrom: ipFrom,
IPTo: ipTo,
})
}
}
} else if strings.Contains(line, "/") { // CIDR
_, cidr, _ := net.ParseCIDR(line)
if cidr != nil {
list.Ranges = append(list.Ranges, &IPRange{
Type: IPRangeTypeCIDR,
CIDR: cidr,
})
}
} else { // single ip
var netIP = net.ParseIP(line)
if netIP != nil {
list.Ranges = append(list.Ranges, &IPRange{
Type: IPRangeTypeSingeIP,
IPFrom: netIP,
})
}
}
}
return list
}
func (this *IPRangeList) Contains(ip string) bool {
var netIP = net.ParseIP(ip)
if netIP == nil {
return false
}
for _, r := range this.Ranges {
if r.Contains(netIP) {
return true
}
}
return false
}