|
@@ -4,12 +4,16 @@ import (
|
|
|
_ "embed"
|
|
|
"errors"
|
|
|
"github.com/RoaringBitmap/roaring"
|
|
|
+ "github.com/yl2chen/cidranger"
|
|
|
+ "log"
|
|
|
+ "net"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
)
|
|
|
|
|
|
type WhiteIp struct {
|
|
|
- Rb *roaring.Bitmap
|
|
|
+ Rb *roaring.Bitmap
|
|
|
+ Ranger cidranger.Ranger
|
|
|
}
|
|
|
|
|
|
// ip2Uint32
|
|
@@ -33,23 +37,56 @@ func ip2Uint32(rawIp string) (uint32, error) {
|
|
|
func NewRb(ip string) *WhiteIp {
|
|
|
newIp := new(WhiteIp)
|
|
|
rb := roaring.NewBitmap()
|
|
|
+ ranger := cidranger.NewPCTrieRanger()
|
|
|
for _, v := range strings.Split(ip, "\n") {
|
|
|
if len(v) < 8 {
|
|
|
continue
|
|
|
}
|
|
|
- if ipUint, err := ip2Uint32(v); err == nil {
|
|
|
- rb.Add(ipUint)
|
|
|
+ if isIP(v) { //精准ip添加
|
|
|
+ if ipUint, err := ip2Uint32(v); err == nil {
|
|
|
+ rb.Add(ipUint)
|
|
|
+ }
|
|
|
+ } else if ipNet, isIpv4 := isIPv4Segment(v); isIpv4 && ipNet != nil { //ip段添加
|
|
|
+ // 初始化 IP 段
|
|
|
+ _ = ranger.Insert(cidranger.NewBasicRangerEntry(*ipNet))
|
|
|
}
|
|
|
}
|
|
|
+ newIp.Ranger = ranger
|
|
|
newIp.Rb = rb
|
|
|
return newIp
|
|
|
}
|
|
|
|
|
|
+// 验证 IP 是否在 IP 段内
|
|
|
+func (ip *WhiteIp) isIPInRange(ips string) bool {
|
|
|
+ checkIP := net.ParseIP(ips)
|
|
|
+ contains, err := ip.Ranger.Contains(checkIP)
|
|
|
+ if err != nil {
|
|
|
+ log.Println("Failed to check IP range:", err)
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return contains
|
|
|
+}
|
|
|
+
|
|
|
+// 判断字符串是否为有效的 IP 地址
|
|
|
+func isIP(s string) bool {
|
|
|
+ ip := net.ParseIP(s)
|
|
|
+ return ip != nil
|
|
|
+}
|
|
|
+
|
|
|
+// 判断字符串是否为有效的 IPv4 段
|
|
|
+func isIPv4Segment(s string) (*net.IPNet, bool) {
|
|
|
+ _, ipNet, err := net.ParseCIDR(s)
|
|
|
+ return ipNet, err == nil
|
|
|
+}
|
|
|
+
|
|
|
// Match
|
|
|
func (ip *WhiteIp) Match(rawIp string) bool {
|
|
|
if ipUint, err := ip2Uint32(rawIp); err != nil {
|
|
|
return false
|
|
|
} else {
|
|
|
- return ip.Rb.Contains(ipUint)
|
|
|
+ if ip.Rb.Contains(ipUint) {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ return ip.isIPInRange(rawIp)
|
|
|
}
|
|
|
}
|