Add DNSBL querying in conditions

This commit is contained in:
WeebDataHoarder
2025-04-08 22:11:58 +02:00
parent 285090c9c1
commit ce111f6ae9
8 changed files with 254 additions and 11 deletions

73
utils/decaymap.go Normal file
View File

@@ -0,0 +1,73 @@
package utils
import (
"sync"
"time"
)
func zilch[T any]() T {
var zero T
return zero
}
type DecayMap[K, V comparable] struct {
data map[K]DecayMapEntry[V]
lock sync.RWMutex
}
type DecayMapEntry[V comparable] struct {
Value V
expiry time.Time
}
func NewDecayMap[K, V comparable]() *DecayMap[K, V] {
return &DecayMap[K, V]{
data: make(map[K]DecayMapEntry[V]),
}
}
func (m *DecayMap[K, V]) Get(key K) (V, bool) {
m.lock.RLock()
value, ok := m.data[key]
m.lock.RUnlock()
if !ok {
return zilch[V](), false
}
if time.Now().After(value.expiry) {
m.lock.Lock()
// Since previously reading m.data[key], the value may have been updated.
// Delete the entry only if the expiry time is still the same.
if m.data[key].expiry == value.expiry {
delete(m.data, key)
}
m.lock.Unlock()
return zilch[V](), false
}
return value.Value, true
}
func (m *DecayMap[K, V]) Set(key K, value V, ttl time.Duration) {
m.lock.Lock()
defer m.lock.Unlock()
m.data[key] = DecayMapEntry[V]{
Value: value,
expiry: time.Now().Add(ttl),
}
}
func (m *DecayMap[K, V]) Decay() {
m.lock.Lock()
defer m.lock.Unlock()
now := time.Now()
for key, entry := range m.data {
if now.After(entry.expiry) {
delete(m.data, key)
}
}
}

75
utils/dnsbl.go Normal file
View File

@@ -0,0 +1,75 @@
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
}