added ip blacklist checker
This commit is contained in:
parent
583eb46e84
commit
12f61545ac
|
@ -0,0 +1,9 @@
|
|||
# IP Blacklist
|
||||
|
||||
Handle a IP blacklist structure in which you receive IP Addresses in the form of:
|
||||
|
||||
1. Single IP: `10.0.0.1`
|
||||
2. IP Range: `11.0.0.1-11.0.0.255`
|
||||
3. IP CIDR: `12.0.0.0/16`
|
||||
|
||||
And then you can check if a given IP matches any of those rules.
|
|
@ -0,0 +1,101 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func netIPToUint32(ip []byte) uint32 {
|
||||
if len(ip) == 16 {
|
||||
return binary.BigEndian.Uint32(ip[12:16])
|
||||
}
|
||||
return binary.BigEndian.Uint32(ip)
|
||||
}
|
||||
|
||||
type IPRange struct {
|
||||
Start uint32
|
||||
End uint32
|
||||
}
|
||||
|
||||
type IPMatcher struct {
|
||||
ranges []IPRange
|
||||
}
|
||||
|
||||
func int2ip(nn uint32) net.IP {
|
||||
ip := make(net.IP, 4)
|
||||
binary.BigEndian.PutUint32(ip, nn)
|
||||
return ip
|
||||
}
|
||||
|
||||
func (ipm *IPMatcher) Set(rules []string) error {
|
||||
var ranges []IPRange
|
||||
|
||||
for _, rule := range rules {
|
||||
if strings.Contains(rule, "/") {
|
||||
// CIDR
|
||||
_, network, err := net.ParseCIDR(rule)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing rules for %s: %s", rule, err)
|
||||
}
|
||||
ranges = append(ranges, IPRange{
|
||||
Start: netIPToUint32(network.IP),
|
||||
End: (netIPToUint32(network.IP) & netIPToUint32(network.Mask)) | (netIPToUint32(network.Mask) ^ 0xffffffff),
|
||||
})
|
||||
} else if strings.Contains(rule, "-") {
|
||||
// Range
|
||||
parts := strings.Split(rule, "-")
|
||||
ranges = append(ranges, IPRange{
|
||||
Start: netIPToUint32(net.ParseIP(parts[0])),
|
||||
End: netIPToUint32(net.ParseIP(parts[1])),
|
||||
})
|
||||
} else {
|
||||
// Single IP
|
||||
ranges = append(ranges,
|
||||
IPRange{
|
||||
Start: netIPToUint32(net.ParseIP(rule)),
|
||||
End: netIPToUint32(net.ParseIP(rule)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Sort ranges
|
||||
// TODO: Find overlapping ranges
|
||||
ipm.ranges = ranges
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ipm *IPMatcher) Matches(ip net.IP) bool {
|
||||
incomingIp := netIPToUint32(ip)
|
||||
for _, ipRange := range ipm.ranges {
|
||||
if (ipRange.Start <= incomingIp) && (incomingIp <= ipRange.End) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func main() {
|
||||
matcher := IPMatcher{}
|
||||
matcher.Set([]string{
|
||||
"11.0.0.0/24",
|
||||
"10.0.0.1",
|
||||
"12.0.0.1-12.0.255.255",
|
||||
})
|
||||
|
||||
assert(matcher.Matches(net.ParseIP("10.0.0.2")), false, "10.0.0.2 should not match")
|
||||
assert(matcher.Matches(net.ParseIP("10.0.0.1")), true, "10.0.0.1 should match")
|
||||
assert(matcher.Matches(net.ParseIP("11.0.0.50")), true, "11.0.0.50 should match")
|
||||
assert(matcher.Matches(net.ParseIP("11.0.0.255")), true, "11.0.0.255 should match")
|
||||
assert(matcher.Matches(net.ParseIP("12.0.0.0")), false, "12.0.0.0 should not match")
|
||||
assert(matcher.Matches(net.ParseIP("12.0.50.1")), true, "12.0.50.1 should match")
|
||||
fmt.Println("done!")
|
||||
}
|
||||
|
||||
func assert(result, expected bool, description string) {
|
||||
if result != expected {
|
||||
fmt.Println(description)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue