From f6f1ddc9528d20642e7e74cacbb07798138397b6 Mon Sep 17 00:00:00 2001 From: YouROK <8yourok8@mail.ru> Date: Wed, 28 Apr 2021 16:06:05 +0300 Subject: [PATCH] fix range block list --- server/web/blocker/blocker.go | 32 ++++--------- server/web/blocker/iplist.go | 87 +++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 22 deletions(-) create mode 100644 server/web/blocker/iplist.go diff --git a/server/web/blocker/blocker.go b/server/web/blocker/blocker.go index f32317f..3ceecca 100644 --- a/server/web/blocker/blocker.go +++ b/server/web/blocker/blocker.go @@ -13,15 +13,9 @@ import ( "server/log" "server/settings" - "github.com/anacrolix/torrent/iplist" "github.com/gin-gonic/gin" ) -type IPB struct { - Ip net.IP - Description string -} - func Blocker() gin.HandlerFunc { emptyFN := func(c *gin.Context) { c.Next() @@ -54,7 +48,7 @@ func Blocker() gin.HandlerFunc { } if blackIpList.NumRanges() > 0 { if r, ok := blackIpList.Lookup(ip); ok { - log.WebLogln("Block ip, in black list:", ip.String(), "in range", r) + log.WebLogln("Block ip, in black list:", ip.String(), "in range", r.Description, ":", r.First, "-", r.Last) c.String(http.StatusTeapot, "Banned") c.Abort() return @@ -65,17 +59,17 @@ func Blocker() gin.HandlerFunc { } } -func scanBuf(buf []byte) []IPB { +func scanBuf(buf []byte) Ranger { if len(buf) == 0 { - return nil + return New(nil) } - var ranges []IPB + var ranges []Range scanner := bufio.NewScanner(strings.NewReader(string(buf))) for scanner.Scan() { r, ok, err := parseLine(scanner.Bytes()) if err != nil { log.TLogln("Error scan ip list:", err) - return nil + return New(nil) } if ok { ranges = append(ranges, r) @@ -86,18 +80,19 @@ func scanBuf(buf []byte) []IPB { log.TLogln("Error scan ip list:", err) } if len(ranges) > 0 { - return iplist.New(ranges) + return New(ranges) } - return iplist.New(nil) + return New(nil) } -func parseLine(l []byte) (r IPB, ok bool, err error) { +func parseLine(l []byte) (r Range, ok bool, err error) { l = bytes.TrimSpace(l) if len(l) == 0 || bytes.HasPrefix(l, []byte("#")) { return } colon := bytes.LastIndexAny(l, ":") - + hyphen := bytes.IndexByte(l[colon+1:], '-') + hyphen += colon + 1 if colon >= 0 { r.Description = string(l[:colon]) } @@ -118,10 +113,3 @@ func parseLine(l []byte) (r IPB, ok bool, err error) { ok = true return } - -func minifyIP(ip *net.IP) { - v4 := ip.To4() - if v4 != nil { - *ip = append(make([]byte, 0, 4), v4...) - } -} diff --git a/server/web/blocker/iplist.go b/server/web/blocker/iplist.go new file mode 100644 index 0000000..105fb43 --- /dev/null +++ b/server/web/blocker/iplist.go @@ -0,0 +1,87 @@ +package blocker + +import ( + "bytes" + "fmt" + "net" +) + +type Ranger interface { + Lookup(net.IP) (r Range, ok bool) + NumRanges() int +} + +type IPList struct { + ranges []Range +} + +type Range struct { + First, Last net.IP + Description string +} + +func (r Range) String() string { + return fmt.Sprintf("%s-%s: %s", r.First, r.Last, r.Description) +} + +// Create a new IP list. The given ranges must already sorted by the lower +// bound IP in each range. Behaviour is undefined for lists of overlapping +// ranges. +func New(initSorted []Range) *IPList { + return &IPList{ + ranges: initSorted, + } +} + +func (ipl *IPList) NumRanges() int { + if ipl == nil { + return 0 + } + return len(ipl.ranges) +} + +// Return the range the given IP is in. ok if false if no range is found. +func (ipl *IPList) Lookup(ip net.IP) (r Range, ok bool) { + if ipl == nil { + return + } + v4 := ip.To4() + if v4 != nil { + r, ok = ipl.lookup(v4) + if ok { + return + } + } + v6 := ip.To16() + if v6 != nil { + return ipl.lookup(v6) + } + if v4 == nil && v6 == nil { + r = Range{ + Description: "bad IP", + } + ok = true + } + return +} + +// Return the range the given IP is in. Returns nil if no range is found. +func (ipl *IPList) lookup(ip net.IP) (Range, bool) { + var rng Range + var ok = false + for _, r := range ipl.ranges { + ok = bytes.Compare(r.First, ip) <= 0 && bytes.Compare(ip, r.Last) <= 0 + if ok { + rng = r + break + } + } + return rng, ok +} + +func minifyIP(ip *net.IP) { + v4 := ip.To4() + if v4 != nil { + *ip = append(make([]byte, 0, 4), v4...) + } +}