Documentation
¶
Index ¶
- Constants
- func Descriptor() module.Descriptor
- type BatchSignal
- type BotConfig
- type Classifier
- type ClassifyResult
- type Config
- type Enforcer
- type FCrDNSVerifier
- type GuardStats
- type IPRecord
- type IPState
- type Logger
- func (l *Logger) Close() error
- func (l *Logger) LogClassification(ip string, oldState, newState IPState, reason, botName string, hitCount int64)
- func (l *Logger) LogDecision(ip string, state IPState, reason, botName string, verifyStatus VerifyStatus, ...)
- func (l *Logger) LogError(context string, err error)
- func (l *Logger) LogEvent(level, message string)
- type Module
- func (m *Module) GetIPRecord(ip netip.Addr) (*IPRecord, bool)
- func (m *Module) GetStats() GuardStats
- func (m *Module) Init(bus *eventbus.Bus) error
- func (m *Module) InitEnforcer(queue *opqueue.OpQueue)
- func (m *Module) Name() string
- func (m *Module) Start(ctx context.Context) error
- func (m *Module) Status() module.Status
- func (m *Module) Stop() error
- type SuspectReader
- type VerifyResult
- type VerifyStatus
Constants ¶
const ( ModuleName = "botguard" ModuleVersion = "1.0.0" )
Variables ¶
This section is empty.
Functions ¶
func Descriptor ¶
func Descriptor() module.Descriptor
Descriptor returns the module descriptor for registration.
Types ¶
type BatchSignal ¶
type BatchSignal struct {
IP string `json:"ip"` // IP address
Score int `json:"score"` // Behavioral score (0-100)
Reasons []string `json:"reasons"` // Why flagged (e.g., "404_flood", "wp_probe")
Action string `json:"action"` // "ban", "grey", "allow_demote", "allow_extend"
TS int64 `json:"ts"` // Unix timestamp
}
BatchSignal represents a signal from the shell botscan (Clock 3). Written as JSONL to /var/lib/nftban/botguard/batch_signals.jsonl
type BotConfig ¶ added in v1.21.0
type BotConfig struct {
Name string // e.g. "GOOGLEBOT"
Domains []string // Suffix match domains (e.g. ["googlebot.com", "google.com"])
VerifyMode string // Verification method: "fcrdns"
MaxConn int // Max concurrent connections allowed
MaxRate string // nft rate string (e.g. "80/second")
Burst int // nft burst value
}
BotConfig describes an allowed or known crawler identity. Loaded from allowed_crawlers.conf (pipe-delimited).
type Classifier ¶ added in v1.21.0
type Classifier struct {
// contains filtered or unexported fields
}
Classifier performs bot classification using FCrDNS verification and allowed/denied crawler configuration.
func NewClassifier ¶ added in v1.21.0
func NewClassifier(cfg *Config, verifier *FCrDNSVerifier) (*Classifier, error)
NewClassifier creates a classifier with loaded crawler configs.
func (*Classifier) AllowedBots ¶ added in v1.21.0
func (c *Classifier) AllowedBots() []BotConfig
AllowedBots returns a copy of the allowed bot list.
func (*Classifier) Classify ¶ added in v1.21.0
func (c *Classifier) Classify(r *IPRecord, cfg *Config) ClassifyResult
Classify determines the classification for a suspect IP record. Returns a ClassifyResult with the target state and reason.
func (*Classifier) ProcessVerification ¶ added in v1.21.0
func (c *Classifier) ProcessVerification(result VerifyResult) ClassifyResult
ProcessVerification processes a completed FCrDNS result and returns the classification decision for the verified IP.
func (*Classifier) ReloadConfigs ¶ added in v1.21.0
func (c *Classifier) ReloadConfigs() error
ReloadConfigs reloads allowed and denied crawler configs from disk.
type ClassifyResult ¶ added in v1.21.0
type ClassifyResult struct {
State IPState // Target state (allow, ban, grey, pending)
Reason string // Why this decision was made
BotName string // Identified bot name (if any)
Verify VerifyStatus // FCrDNS verification result
}
ClassifyResult is the decision returned by the Classifier.
type Config ¶
type Config struct {
// Module control
Enabled bool
// Classification loop intervals
LoopInterval time.Duration // Normal: 60s
LoopPressureInterval time.Duration // Under pressure: 40s
// Hysteresis thresholds (per IP connection count)
TripConn int // Start analyzing (default 200)
ClearConn int // Stop analyzing (default 150)
EmergencyConn int // Immediate block (default 500)
// Kernel suspect marking config (informational — actual values in nft rules)
SuspectRate string // e.g. "30/second"
SuspectBurst int // e.g. 60
SuspectTimeout time.Duration // e.g. 5m
// TTLs for classification sets
AllowTTL time.Duration // 24h initial
BanTTL time.Duration // 96h
GreyTTL time.Duration // 30m
EmergencyTTL time.Duration // 30m
PendingTTL time.Duration // 60s
// Auto-tuning
AutoTune bool
// Batch integration
BatchSignalFile string
BatchInterval time.Duration
// FCrDNS verification
VerifyWorkers int // Max concurrent DNS workers (default 8)
VerifyRateLimit int // Max new lookups per second (default 10)
VerifyTimeout time.Duration // Timeout per DNS lookup (default 3s)
VerifyCacheTTL time.Duration // Positive cache TTL (default 24h)
VerifyNegTTL time.Duration // Negative cache TTL (default 1h)
// Crawler config files
AllowedCrawlersFile string
DeniedCrawlersFile string
// Logging
LogLevel string
LogDecisions bool
}
Config holds all bot guard configuration.
func LoadConfig ¶
LoadConfig reads configuration from a shell-style config file. Supports KEY="VALUE" format (same as all NFTBan config files).
type Enforcer ¶
type Enforcer struct {
// contains filtered or unexported fields
}
Enforcer writes classification decisions to nftables enforcement sets. All writes go through the OpQueue for safe async netlink batching.
func NewEnforcer ¶
NewEnforcer creates an enforcer that writes to nft sets via OpQueue.
func (*Enforcer) Apply ¶
Apply writes a classification decision to the appropriate nft set. It removes the IP from the old set (if any) and adds it to the new set.
func (*Enforcer) ApplyEmergency ¶
ApplyEmergency adds an IP directly to the emergency set (fast path).
type FCrDNSVerifier ¶ added in v1.21.0
type FCrDNSVerifier struct {
// contains filtered or unexported fields
}
FCrDNSVerifier performs Forward-Confirmed Reverse DNS verification using a bounded worker pool with rate limiting and caching.
func NewFCrDNSVerifier ¶ added in v1.21.0
func NewFCrDNSVerifier(cfg *Config, allowedBots []BotConfig) *FCrDNSVerifier
NewFCrDNSVerifier creates a new verifier with the given config and bot list.
func (*FCrDNSVerifier) Enqueue ¶ added in v1.21.0
func (v *FCrDNSVerifier) Enqueue(ip netip.Addr)
Enqueue submits an IP for FCrDNS verification. Non-blocking: drops the request if the queue is full.
func (*FCrDNSVerifier) Results ¶ added in v1.21.0
func (v *FCrDNSVerifier) Results() <-chan VerifyResult
Results returns the channel of completed verifications.
func (*FCrDNSVerifier) Start ¶ added in v1.21.0
func (v *FCrDNSVerifier) Start(ctx context.Context)
Start launches the worker pool and rate limiter. Blocks until ctx is cancelled.
type GuardStats ¶
type GuardStats struct {
TickCount int64 // Total classification ticks
SuspectsFound int64 // Total unique IPs found in suspect set
Classified int64 // Total IPs classified
AllowCount int64 // IPs classified as allow
GreyCount int64 // IPs classified as grey
BanCount int64 // IPs classified as ban
EmergencyCount int64 // IPs classified as emergency
PendingCount int64 // IPs currently pending
TrackedIPs int64 // Currently tracked IPs in state map
LastTickDuration time.Duration // Duration of last tick
LastTickTime time.Time // When last tick completed
PressureMode bool // Whether currently in pressure mode
VerifyEnqueued int64 // IPs enqueued for FCrDNS verification
VerifyCompleted int64 // FCrDNS verifications completed
VerifyVerified int64 // IPs that passed FCrDNS
VerifyFailed int64 // IPs that failed FCrDNS
BatchSignalsProcessed int64 // Batch signals consumed from Clock 3
}
GuardStats holds runtime statistics for the bot guard module.
type IPRecord ¶
type IPRecord struct {
IP netip.Addr // Parsed IP address (IPv4 or IPv6)
State IPState // Current classification
Score int32 // Accumulated threat score
FirstSeen time.Time // When first detected as suspect
LastSeen time.Time // Last time seen in suspect set
ExpiresAt time.Time // When current state expires
HitCount int64 // Number of times seen in suspect set
Reasons []string // Why this IP was flagged (for logging)
BotName string // Identified bot name (empty if unknown)
VerifiedAt time.Time // When FCrDNS verification completed (zero if not verified)
VerifyStatus VerifyStatus // Result of FCrDNS verification
}
IPRecord tracks the classification state and history for one IP.
type IPState ¶
type IPState int
IPState represents the classification state for an IP address. State machine: UNKNOWN → PENDING → ALLOW|GREY|BAN|EMERGENCY
const ( StateUnknown IPState = iota // Not yet seen by Go classifier StatePending // Awaiting classification (light throttle) StateAllow // Verified allowed crawler (bypass throttle) StateGrey // Suspicious, throttled via penalty ladder StateBan // Denied/malicious bot (full drop) StateEmergency // Emergency pressure block (immediate drop) )
func (IPState) SetName ¶
SetName returns the nftables set name for this state (IPv4). Returns empty string for states that don't map to a set.
type Logger ¶ added in v1.21.0
type Logger struct {
// contains filtered or unexported fields
}
Logger writes structured log entries for the bot guard module. Thread-safe: all writes are mutex-protected.
func NewLogger ¶ added in v1.21.0
NewLogger creates a new file logger for botguard. Creates the log directory if it doesn't exist.
func (*Logger) LogClassification ¶ added in v1.21.0
func (l *Logger) LogClassification(ip string, oldState, newState IPState, reason, botName string, hitCount int64)
LogClassification logs a state transition to botguard.log. Format: TIMESTAMP|IP|OLD_STATE|NEW_STATE|REASON|BOT_NAME|HIT_COUNT
func (*Logger) LogDecision ¶ added in v1.21.0
func (l *Logger) LogDecision(ip string, state IPState, reason, botName string, verifyStatus VerifyStatus, hostname string)
LogDecision logs a verification-based decision to decisions.log. Format: TIMESTAMP|IP|STATE|REASON|BOT_NAME|VERIFY_STATUS|HOSTNAME
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module implements the bot guard module (module.Module interface).
func (*Module) GetIPRecord ¶
GetIPRecord returns the current record for an IP (for CLI status queries).
func (*Module) GetStats ¶
func (m *Module) GetStats() GuardStats
GetStats returns a copy of the current statistics.
func (*Module) InitEnforcer ¶
InitEnforcer sets up the enforcer with the OpQueue. Called after daemon creates the OpQueue.
type SuspectReader ¶
type SuspectReader struct {
// contains filtered or unexported fields
}
SuspectReader reads kernel-populated suspect sets.
func NewSuspectReader ¶
func NewSuspectReader() *SuspectReader
NewSuspectReader creates a reader for the kernel suspect sets.
func (*SuspectReader) ReadSuspects ¶
ReadSuspects reads both IPv4 and IPv6 suspect sets. Returns a combined list of suspect IPs (typically 20-100 entries). This operation completes in microseconds since the sets are small.
type VerifyResult ¶ added in v1.21.0
type VerifyResult struct {
IP netip.Addr // The IP that was verified
Status VerifyStatus // Verification outcome
BotName string // Matched bot name (empty if not matched)
Hostname string // Reverse DNS hostname (empty if lookup failed)
}
VerifyResult holds the outcome of an FCrDNS verification.
type VerifyStatus ¶ added in v1.21.0
type VerifyStatus int
VerifyStatus represents the result of an FCrDNS verification.
const ( VerifyNone VerifyStatus = iota // Not yet verified VerifyVerified // FCrDNS confirmed: rDNS matches allowed domain + fwd confirms VerifyFailed // FCrDNS failed: rDNS does not match or fwd mismatch VerifyTimeout // DNS lookup timed out VerifyNoRDNS // No reverse DNS record found )
func (VerifyStatus) String ¶ added in v1.21.0
func (v VerifyStatus) String() string
String returns the human-readable verify status name.