botguard

package
v1.20.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 14, 2026 License: MPL-2.0 Imports: 16 Imported by: 0

Documentation

Index

Constants

View Source
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 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

	// Logging
	LogLevel     string
	LogDecisions bool
}

Config holds all bot guard configuration.

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns production-safe defaults.

func LoadConfig

func LoadConfig(path string) (*Config, error)

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

func NewEnforcer(queue *opqueue.OpQueue, config *Config) *Enforcer

NewEnforcer creates an enforcer that writes to nft sets via OpQueue.

func (*Enforcer) Apply

func (e *Enforcer) Apply(ip netip.Addr, oldState, newState IPState, reason string) error

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

func (e *Enforcer) ApplyEmergency(ip netip.Addr, reason string) error

ApplyEmergency adds an IP directly to the emergency set (fast path).

func (*Enforcer) Remove

func (e *Enforcer) Remove(ip netip.Addr, state IPState) error

Remove removes an IP from its current set (e.g., when state expires).

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
}

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)
}

IPRecord tracks the classification state and history for one IP.

func (*IPRecord) Expired

func (r *IPRecord) Expired() bool

Expired returns true if the record has expired.

func (*IPRecord) IsIPv6

func (r *IPRecord) IsIPv6() bool

IsIPv6 returns true if this record tracks an IPv6 address.

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

func (s IPState) SetName() string

SetName returns the nftables set name for this state (IPv4). Returns empty string for states that don't map to a set.

func (IPState) SetName6

func (s IPState) SetName6() string

SetName6 returns the nftables set name for this state (IPv6).

func (IPState) String

func (s IPState) String() string

String returns the human-readable state name.

type Module

type Module struct {
	// contains filtered or unexported fields
}

Module implements the bot guard module (module.Module interface).

func New

func New() *Module

New creates a new bot guard module.

func (*Module) GetIPRecord

func (m *Module) GetIPRecord(ip netip.Addr) (*IPRecord, bool)

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) Init

func (m *Module) Init(bus *eventbus.Bus) error

Init initializes the module with the event bus.

func (*Module) InitEnforcer

func (m *Module) InitEnforcer(queue *opqueue.OpQueue)

InitEnforcer sets up the enforcer with the OpQueue. Called after daemon creates the OpQueue.

func (*Module) Name

func (m *Module) Name() string

Name returns the module identifier.

func (*Module) Start

func (m *Module) Start(ctx context.Context) error

Start begins the classification loop.

func (*Module) Status

func (m *Module) Status() module.Status

Status returns the current module status.

func (*Module) Stop

func (m *Module) Stop() error

Stop gracefully shuts down the module.

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

func (r *SuspectReader) ReadSuspects(ctx context.Context) ([]netip.Addr, error)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL