From fae6cfd5bf2fab4380551e4d51fe6c5b7e283574 Mon Sep 17 00:00:00 2001 From: YouROK <8yourok8@mail.ru> Date: Fri, 23 Apr 2021 10:17:45 +0300 Subject: [PATCH] add white/black ip list --- server/web/blocker/blocker.go | 129 ++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 server/web/blocker/blocker.go diff --git a/server/web/blocker/blocker.go b/server/web/blocker/blocker.go new file mode 100644 index 0000000..9409a2d --- /dev/null +++ b/server/web/blocker/blocker.go @@ -0,0 +1,129 @@ +package blocker + +import ( + "bufio" + "bytes" + "errors" + "io/ioutil" + "net" + "net/http" + "path/filepath" + "strings" + + "server/log" + "server/settings" + + "github.com/anacrolix/torrent/iplist" + "github.com/gin-gonic/gin" +) + +func Blocker() gin.HandlerFunc { + emptyFN := func(c *gin.Context) { + c.Next() + } + + name := filepath.Join(settings.Path, "bip.txt") + buf, err := ioutil.ReadFile(name) + if err != nil { + return emptyFN + } + blackIpList := scanBuf(buf) + + name = filepath.Join(settings.Path, "wip.txt") + buf, err = ioutil.ReadFile(name) + if err != nil { + return emptyFN + } + whiteIpList := scanBuf(buf) + if blackIpList.NumRanges() == 0 { + return emptyFN + } + + if blackIpList.NumRanges() == 0 && whiteIpList.NumRanges() == 0 { + return emptyFN + } + + return func(c *gin.Context) { + arr := strings.Split(c.Request.RemoteAddr, ":") + if len(arr) > 0 { + ip := net.ParseIP(arr[0]) + minifyIP(&ip) + if whiteIpList.NumRanges() > 0 { + if _, ok := whiteIpList.Lookup(ip); !ok { + log.TLogln("Block ip, not in white list", ip.String()) + c.String(http.StatusTeapot, "Banned") + c.Abort() + return + } + } + if blackIpList.NumRanges() > 0 { + if r, ok := blackIpList.Lookup(ip); ok { + log.TLogln("Block ip, in black list:", ip.String(), "in range", r.Description, ":", r.First, "-", r.Last) + c.String(http.StatusTeapot, "Banned") + c.Abort() + return + } + } + } + c.Next() + } +} + +func scanBuf(buf []byte) iplist.Ranger { + scanner := bufio.NewScanner(strings.NewReader(string(buf))) + var ranges []iplist.Range + for scanner.Scan() { + r, ok, err := parseLine(scanner.Bytes()) + if err != nil { + log.TLogln("Error scan ip list:", err) + return iplist.New(nil) + } + if ok { + ranges = append(ranges, r) + } + } + err := scanner.Err() + if err != nil { + log.TLogln("Error scan ip list:", err) + } + if len(ranges) > 0 { + return iplist.New(ranges) + } + return iplist.New(nil) +} + +func parseLine(l []byte) (r iplist.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]) + } + if hyphen-(colon+1) >= 0 { + r.First = net.ParseIP(string(l[colon+1 : hyphen])) + minifyIP(&r.First) + r.Last = net.ParseIP(string(l[hyphen+1:])) + minifyIP(&r.Last) + } else { + r.First = net.ParseIP(string(l[colon+1:])) + minifyIP(&r.First) + r.Last = r.First + } + if r.First == nil || r.Last == nil || len(r.First) != len(r.Last) { + err = errors.New("bad IP range") + return + } + ok = true + return +} + +func minifyIP(ip *net.IP) { + v4 := ip.To4() + if v4 != nil { + *ip = append(make([]byte, 0, 4), v4...) + } +}