Files
EdgeNode/internal/waf/values/ip_range.go
2023-01-06 19:14:09 +08:00

133 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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
}