|
@@ -1,6 +1,7 @@
|
|
|
package blacklist
|
|
|
|
|
|
import (
|
|
|
+ "bytes"
|
|
|
"errors"
|
|
|
"net"
|
|
|
"strconv"
|
|
@@ -41,9 +42,30 @@ func (bl *BlackList) IsBanned(ip string) bool {
|
|
|
if bl.database.KeyExists("ipblacklist", ip) {
|
|
|
return true
|
|
|
}
|
|
|
+
|
|
|
+ //The ip might be inside as a range. Do a range search.
|
|
|
+ //Need optimization, current implementation is O(N)
|
|
|
+ for _, thisIpRange := range bl.ListBannedIpRanges() {
|
|
|
+ if ipInRange(ip, thisIpRange) {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
+func (bl *BlackList) ListBannedIpRanges() []string {
|
|
|
+ entries, err := bl.database.ListTable("test")
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ results := []string{}
|
|
|
+ for _, keypairs := range entries {
|
|
|
+ thisIpRange := keypairs[0]
|
|
|
+ results = append(results, string(thisIpRange))
|
|
|
+ }
|
|
|
+ return results
|
|
|
+}
|
|
|
+
|
|
|
//Set the ban state of a ip or ip range
|
|
|
func (bl *BlackList) Ban(ipRange string) error {
|
|
|
//Check if the IP range is correct
|
|
@@ -58,16 +80,65 @@ func (bl *BlackList) Ban(ipRange string) error {
|
|
|
return bl.database.Write("ipblacklist", ipRange, true)
|
|
|
}
|
|
|
|
|
|
+//Unban an IP or IP range
|
|
|
func (bl *BlackList) UnBan(ipRange string) error {
|
|
|
//Check if the IP range is correct
|
|
|
- return nil
|
|
|
+ err := validateIpRange(ipRange)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ //Check if the ip range is banned
|
|
|
+ if !bl.database.KeyExists("ipblacklist", ipRange) {
|
|
|
+ return errors.New("invalid IP range given")
|
|
|
+ }
|
|
|
|
|
|
+ //Ip range exists, remove it from database
|
|
|
+ return bl.database.Delete("ipblacklist", ipRange)
|
|
|
+}
|
|
|
+
|
|
|
+//Break an ip range text into independent ip strings
|
|
|
+func breakdownIpRange(ipRange string) []string {
|
|
|
+ ipRange = strings.ReplaceAll(ipRange, " ", "")
|
|
|
+ err := validateIpRange(ipRange)
|
|
|
+ if err != nil {
|
|
|
+ return []string{}
|
|
|
+ }
|
|
|
+ if !strings.Contains(ipRange, "-") {
|
|
|
+ //This is not an ip range but a single ip
|
|
|
+ return []string{ipRange}
|
|
|
+ }
|
|
|
+
|
|
|
+ //Break down the IP range
|
|
|
+ results := []string{}
|
|
|
+ ips := strings.Split(ipRange, "-")
|
|
|
+
|
|
|
+ subnet := ips[0][:strings.LastIndex(ips[0], ".")]
|
|
|
+ startD := ips[0][strings.LastIndex(ips[0], ".")+1:]
|
|
|
+ if err != nil {
|
|
|
+ return []string{}
|
|
|
+ }
|
|
|
+ endD := ips[1][strings.LastIndex(ips[0], ".")+1:]
|
|
|
+ if err != nil {
|
|
|
+ return []string{}
|
|
|
+ }
|
|
|
+
|
|
|
+ startDInt, err := strconv.Atoi(startD)
|
|
|
+ endDInt, err := strconv.Atoi(endD)
|
|
|
+
|
|
|
+ currentDInt := startDInt
|
|
|
+ for currentDInt < endDInt+1 {
|
|
|
+ results = append(results, subnet+"."+strconv.Itoa(currentDInt))
|
|
|
+ currentDInt++
|
|
|
+ }
|
|
|
+
|
|
|
+ return results
|
|
|
}
|
|
|
|
|
|
//Check if an given ip in the given range
|
|
|
func ipInRange(ip string, ipRange string) bool {
|
|
|
ip = strings.TrimSpace(ip)
|
|
|
- ipRange = strings.TrimSpace(ipRange)
|
|
|
+ ipRange = strings.ReplaceAll(ipRange, " ", "")
|
|
|
if ip == ipRange {
|
|
|
//For fields that the ipRange is the ip itself
|
|
|
return true
|
|
@@ -75,27 +146,26 @@ func ipInRange(ip string, ipRange string) bool {
|
|
|
|
|
|
//Try matching range
|
|
|
if strings.Contains(ipRange, "-") {
|
|
|
- //For range, in A.B.C.D, the A.B.C part must be the same, so do prefix matching
|
|
|
+ //Parse the source IP
|
|
|
+ trial := net.ParseIP(ip)
|
|
|
+
|
|
|
+ //Parse the IP range
|
|
|
ips := strings.Split(ipRange, "-")
|
|
|
- startSubnet := ips[0][:strings.LastIndex(ips[0], ".")]
|
|
|
- targetIpSubnet := ip[:strings.LastIndex(ip, ".")]
|
|
|
- if startSubnet == targetIpSubnet {
|
|
|
- //Check the last value in range
|
|
|
- StartDval, _ := strconv.Atoi(ips[0][strings.LastIndex(ips[0], ".")+1:])
|
|
|
- EndDval, _ := strconv.Atoi(ips[1][strings.LastIndex(ips[1], ".")+1:])
|
|
|
- thisDVal, _ := strconv.Atoi(ip[strings.LastIndex(ip, ".")+1:])
|
|
|
-
|
|
|
- if thisDVal > StartDval && thisDVal < EndDval {
|
|
|
- //In range
|
|
|
- return true
|
|
|
- } else {
|
|
|
- //Not in range
|
|
|
- return false
|
|
|
- }
|
|
|
- } else {
|
|
|
- //Subnet different. Must be not in this range
|
|
|
+ ip1 := net.ParseIP(ips[0])
|
|
|
+ if ip1 == nil {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ ip2 := net.ParseIP(ips[1])
|
|
|
+ if ip2 == nil {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if trial.To4() == nil {
|
|
|
return false
|
|
|
}
|
|
|
+ if bytes.Compare(trial, ip1) >= 0 && bytes.Compare(trial, ip2) <= 0 {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ return false
|
|
|
|
|
|
}
|
|
|
return false
|