76 lines
1.4 KiB
Go
76 lines
1.4 KiB
Go
package utils
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"strconv"
|
|
)
|
|
|
|
type DNSBL struct {
|
|
target string
|
|
resolver *net.Resolver
|
|
}
|
|
|
|
func NewDNSBL(target string, resolver *net.Resolver) *DNSBL {
|
|
if resolver == nil {
|
|
resolver = net.DefaultResolver
|
|
}
|
|
return &DNSBL{
|
|
target: target,
|
|
resolver: resolver,
|
|
}
|
|
}
|
|
|
|
var nibbleTable = [16]byte{
|
|
'0', '1', '2', '3',
|
|
'4', '5', '6', '7',
|
|
'8', '9', 'a', 'b',
|
|
'c', 'd', 'e', 'f',
|
|
}
|
|
|
|
type DNSBLResponse uint8
|
|
|
|
func (r DNSBLResponse) Bad() bool {
|
|
return r != ResponseGood && r != ResponseUnknown
|
|
}
|
|
|
|
const (
|
|
ResponseGood = DNSBLResponse(0)
|
|
ResponseUnknown = DNSBLResponse(255)
|
|
)
|
|
|
|
func (bl DNSBL) Lookup(ctx context.Context, ip net.IP) (DNSBLResponse, error) {
|
|
var target []byte
|
|
if ip4 := ip.To4(); ip4 != nil {
|
|
// max length preallocate
|
|
target = make([]byte, 0, len(bl.target)+1+len(ip4)*4)
|
|
|
|
for i := len(ip4) - 1; i >= 0; i-- {
|
|
target = strconv.AppendUint(target, uint64(ip4[i]), 10)
|
|
target = append(target, '.')
|
|
}
|
|
} else {
|
|
// IPv6
|
|
// max length preallocate
|
|
target = make([]byte, 0, len(bl.target)+1+len(ip)*4)
|
|
|
|
for i := len(ip) - 1; i >= 0; i-- {
|
|
target = append(target, nibbleTable[ip[i]&0xf], '.', ip[i]>>4, '.')
|
|
}
|
|
}
|
|
|
|
target = append(target, bl.target...)
|
|
|
|
ips, err := bl.resolver.LookupIP(ctx, "ip4", string(target))
|
|
if err != nil {
|
|
return ResponseUnknown, err
|
|
}
|
|
|
|
for _, ip := range ips {
|
|
ip4 := ip.To4()
|
|
return DNSBLResponse(ip4[len(ip4)-1]), nil
|
|
}
|
|
|
|
return ResponseUnknown, nil
|
|
}
|