IP范围支持多行

This commit is contained in:
刘祥超
2023-01-06 19:14:09 +08:00
parent c567404b7a
commit 8a8881ac47
9 changed files with 382 additions and 68 deletions

View File

@@ -12,6 +12,7 @@ import (
"github.com/TeaOSLab/EdgeNode/internal/waf/checkpoints"
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
"github.com/TeaOSLab/EdgeNode/internal/waf/utils"
"github.com/TeaOSLab/EdgeNode/internal/waf/values"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
@@ -47,6 +48,10 @@ type Rule struct {
isIP bool
ipValue net.IP
ipRangeListValue *values.IPRangeList
numberListValue *values.NumberList
stringListValue *values.StringList
floatValue float64
reg *re.Regexp
}
@@ -104,32 +109,7 @@ func (this *Rule) Init() error {
return errors.New("value should be a valid ip")
}
case RuleOperatorIPRange, RuleOperatorNotIPRange:
if strings.Contains(this.Value, ",") {
ipList := strings.SplitN(this.Value, ",", 2)
ipString1 := strings.TrimSpace(ipList[0])
ipString2 := strings.TrimSpace(ipList[1])
if len(ipString1) > 0 {
ip1 := net.ParseIP(ipString1)
if ip1 == nil {
return errors.New("start ip is invalid")
}
}
if len(ipString2) > 0 {
ip2 := net.ParseIP(ipString2)
if ip2 == nil {
return errors.New("end ip is invalid")
}
}
} else if strings.Contains(this.Value, "/") {
_, _, err := net.ParseCIDR(this.Value)
if err != nil {
return err
}
} else {
return errors.New("invalid ip range")
}
this.ipRangeListValue = values.ParseIPRangeList(this.Value)
}
if singleParamRegexp.MatchString(this.Param) {
@@ -643,50 +623,11 @@ func (this *Rule) unescape(v string) string {
return v
}
func (this *Rule) containsIP(value interface{}) bool {
ip := net.ParseIP(types.String(value))
if ip == nil {
return false
}
// 检查IP范围格式
if strings.Contains(this.Value, ",") {
ipList := strings.SplitN(this.Value, ",", 2)
ipString1 := strings.TrimSpace(ipList[0])
ipString2 := strings.TrimSpace(ipList[1])
if len(ipString1) > 0 {
ip1 := net.ParseIP(ipString1)
if ip1 == nil {
return false
}
if bytes.Compare(ip, ip1) < 0 {
return false
}
}
if len(ipString2) > 0 {
ip2 := net.ParseIP(ipString2)
if ip2 == nil {
return false
}
if bytes.Compare(ip, ip2) > 0 {
return false
}
}
return true
} else if strings.Contains(this.Value, "/") {
_, ipNet, err := net.ParseCIDR(this.Value)
if err != nil {
return false
}
return ipNet.Contains(ip)
} else {
func (this *Rule) containsIP(value any) bool {
if this.ipRangeListValue == nil {
return false
}
return this.ipRangeListValue.Contains(types.String(value))
}
func (this *Rule) ipToInt64(ip net.IP) int64 {

View File

@@ -0,0 +1,7 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package values
func ParseIPList(v string) *StringList {
return ParseStringList(v)
}

View File

@@ -0,0 +1,26 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package values_test
import (
"github.com/TeaOSLab/EdgeNode/internal/waf/values"
"github.com/iwind/TeaGo/assert"
"testing"
)
func TestParseIPList(t *testing.T) {
var a = assert.NewAssertion(t)
{
var list = values.ParseIPList("")
a.IsFalse(list.Contains("192.168.1.100"))
}
{
var list = values.ParseIPList(`
192.168.1.1
192.168.1.101`)
a.IsFalse(list.Contains("192.168.1.100"))
a.IsTrue(list.Contains("192.168.1.101"))
}
}

View File

@@ -0,0 +1,132 @@
// 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
}

View File

@@ -0,0 +1,54 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package values_test
import (
"github.com/TeaOSLab/EdgeNode/internal/waf/values"
"github.com/iwind/TeaGo/assert"
"github.com/iwind/TeaGo/logs"
"testing"
)
func TestIPRange_ParseIPRangeList(t *testing.T) {
{
var r = values.ParseIPRangeList("")
logs.PrintAsJSON(r, t)
}
{
var r = values.ParseIPRangeList("192.168.2.1")
logs.PrintAsJSON(r, t)
}
{
var r = values.ParseIPRangeList(`192.168.2.1
192.168.1.100/24
192.168.1.1-192.168.2.100
192.168.1.2,192.168.2.200
192.168.2.200 - 192.168.2.100
# 以下是错误的
192.168
192.168.100.1-1`)
logs.PrintAsJSON(r, t)
}
}
func TestIPRange_Contains(t *testing.T) {
{
var a = assert.NewAssertion(t)
var r = values.ParseIPRangeList(`192.168.2.1
192.168.1.100/24
192.168.1.1-192.168.2.100
192.168.2.2,192.168.2.200
192.168.3.200 - 192.168.3.100
192.168.4.100
192.168.5.1/26`)
a.IsTrue(r.Contains("192.168.1.102"))
a.IsTrue(r.Contains("192.168.2.101"))
a.IsTrue(r.Contains("192.168.1.1"))
a.IsTrue(r.Contains("192.168.2.100"))
a.IsFalse(r.Contains("192.168.2.201"))
a.IsTrue(r.Contains("192.168.3.101"))
a.IsTrue(r.Contains("192.168.4.100"))
a.IsTrue(r.Contains("192.168.5.63"))
a.IsFalse(r.Contains("192.168.5.128"))
}
}

View File

@@ -0,0 +1,48 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package values
import (
"github.com/TeaOSLab/EdgeNode/internal/zero"
"github.com/iwind/TeaGo/types"
"strings"
)
type NumberList struct {
ValueMap map[float64]zero.Zero
}
func NewNumberList() *NumberList {
return &NumberList{
ValueMap: map[float64]zero.Zero{},
}
}
func ParseNumberList(v string) *NumberList {
var list = NewNumberList()
if len(v) == 0 {
return list
}
var lines = strings.Split(v, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if len(line) == 0 {
continue
}
var values = strings.Split(line, ",")
for _, value := range values {
value = strings.TrimSpace(value)
if len(value) > 0 {
list.ValueMap[types.Float64(value)] = zero.Zero{}
}
}
}
return list
}
func (this *NumberList) Contains(f float64) bool {
_, ok := this.ValueMap[f]
return ok
}

View File

@@ -0,0 +1,29 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package values_test
import (
"github.com/TeaOSLab/EdgeNode/internal/waf/values"
"github.com/iwind/TeaGo/assert"
"testing"
)
func TestParseNumberList(t *testing.T) {
var a = assert.NewAssertion(t)
{
var list = values.ParseNumberList("")
a.IsFalse(list.Contains(123))
}
{
var list = values.ParseNumberList(`123
456
789.1234`)
a.IsTrue(list.Contains(123))
a.IsFalse(list.Contains(0))
a.IsFalse(list.Contains(789.123))
a.IsTrue(list.Contains(789.1234))
}
}

View File

@@ -0,0 +1,47 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package values
import (
"github.com/TeaOSLab/EdgeNode/internal/zero"
"strings"
)
type StringList struct {
ValueMap map[string]zero.Zero
}
func NewStringList() *StringList {
return &StringList{
ValueMap: map[string]zero.Zero{},
}
}
func ParseStringList(v string) *StringList {
var list = NewStringList()
if len(v) == 0 {
return list
}
var lines = strings.Split(v, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if len(line) == 0 {
continue
}
var values = strings.Split(line, ",")
for _, value := range values {
value = strings.TrimSpace(value)
if len(value) > 0 {
list.ValueMap[value] = zero.Zero{}
}
}
}
return list
}
func (this *StringList) Contains(f string) bool {
_, ok := this.ValueMap[f]
return ok
}

View File

@@ -0,0 +1,30 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package values_test
import (
"github.com/TeaOSLab/EdgeNode/internal/waf/values"
"github.com/iwind/TeaGo/assert"
"testing"
)
func TestParseStringList(t *testing.T) {
var a = assert.NewAssertion(t)
{
var list = values.ParseStringList("")
a.IsFalse(list.Contains("hello"))
}
{
var list = values.ParseStringList(`hello
world
hi
people`)
a.IsTrue(list.Contains("hello"))
a.IsFalse(list.Contains("hello1"))
a.IsTrue(list.Contains("hi"))
}
}