package blacklist import ( "errors" "net" "strconv" "strings" db "imuslab.com/arozos/mod/database" ) /* ArozOS Blacklist Module Author: tobychui This module record the IP blacklist of users trying to enter the system without permission */ type BlackList struct { Enabled bool database *db.Database } func NewBlacklistManager(sysdb *db.Database) *BlackList { sysdb.NewTable("ipblacklist") return &BlackList{ Enabled: true, database: sysdb, } } func (bl *BlackList) IsBanned(ip string) bool { if bl.database.KeyExists("ipblacklist", ip) { return true } return false } func (bl *BlackList) SetBan(ipRange string) error { //Check if the IP range is correct err := validateIpRange(ipRange) if err != nil { return err } return nil } func ipInRange(ip string, ipRange string) bool { ip = strings.TrimSpace(ip) ipRange = strings.TrimSpace(ipRange) if ip == ipRange { //For fields that the ipRange is the ip itself return true } //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 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 return false } } return false } //Check if the given IP Range string is actually an IP range func validateIpRange(ipRange string) error { ipRange = strings.TrimSpace(ipRange) ipRange = strings.ReplaceAll(ipRange, " ", "") if strings.Contains(ipRange, "-") { //This is a range if strings.Count(ipRange, "-") != 1 { //Invalid range defination return errors.New("Invalid ip range defination") } ips := strings.Split(ipRange, "-") //Check if the starting IP and ending IP are both valid if net.ParseIP(ips[0]) == nil { return errors.New("Starting ip is invalid") } if net.ParseIP(ips[1]) == nil { return errors.New("Ending ip is invalid") } //Check if the ending IP is larger than the starting IP startingIpInt, _ := strconv.Atoi(strings.ReplaceAll(ips[0], ".", "")) endingIpInt, _ := strconv.Atoi(strings.ReplaceAll(ips[1], ".", "")) if startingIpInt >= endingIpInt { return errors.New("Invalid ip range: Starting IP is larger or equal to ending ip") } //Check if they are in the same subnet startSubnet := ips[0][:strings.LastIndex(ips[0], ".")] endSubnet := ips[1][:strings.LastIndex(ips[1], ".")] if startSubnet != endSubnet { //They are not in the same subnet return errors.New("IP range subnet mismatch") } } else { //This is a single IP instead of range. Check if it is a valid IP addr if net.ParseIP(ipRange) != nil { //Ok return nil } else { return errors.New("Invalid ip given") } } return nil }