validator

package
v1.80.1 Latest Latest
Warning

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

Go to latest
Published: Apr 13, 2026 License: MPL-2.0 Imports: 6 Imported by: 0

Documentation

Overview

============================================================================= NFTBan v1.78 - Validator CLI Helpers ============================================================================= SPDX-License-Identifier: MPL-2.0 meta:name="validator-cli" meta:type="lib" meta:owner="Antonios Voulvoulis <contact@nftban.com>" meta:created_date="2026-04-05" meta:description="CLI output helpers for the validator" meta:inventory.files="internal/validator/cli.go" meta:inventory.binaries="" meta:inventory.env_vars="" meta:inventory.config_files="" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges="none" =============================================================================

============================================================================= NFTBan v1.78 - nft JSON Output Parsing ============================================================================= SPDX-License-Identifier: MPL-2.0 meta:name="validator-nftjson" meta:type="lib" meta:owner="Antonios Voulvoulis <contact@nftban.com>" meta:created_date="2026-04-05" meta:description="Parse nft -j list ruleset JSON output" meta:inventory.files="internal/validator/nftjson.go" meta:inventory.binaries="nft" meta:inventory.env_vars="" meta:inventory.config_files="" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges="root" =============================================================================

============================================================================= NFTBan v1.78 - Kernel Truth Validator Types ============================================================================= SPDX-License-Identifier: MPL-2.0 meta:name="validator-types" meta:type="lib" meta:owner="Antonios Voulvoulis <contact@nftban.com>" meta:created_date="2026-04-05" meta:description="Type definitions for kernel state validation" meta:inventory.files="internal/validator/types.go" meta:inventory.binaries="" meta:inventory.env_vars="" meta:inventory.config_files="" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges="none" =============================================================================

============================================================================= NFTBan v1.78 - Kernel Truth Validator ============================================================================= SPDX-License-Identifier: MPL-2.0 meta:name="validator" meta:type="lib" meta:owner="Antonios Voulvoulis <contact@nftban.com>" meta:created_date="2026-04-05" meta:description="Validates live nftables kernel state against NFTBan requirements" meta:inventory.files="internal/validator/validator.go" meta:inventory.binaries="nft" meta:inventory.env_vars="" meta:inventory.config_files="" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges="root"

CRITICAL: This validator is ZERO-SIDE-EFFECT. It MUST NEVER write files, modify nft, or call mutating shell scripts. =============================================================================

Index

Constants

View Source
const (
	// Table findings
	CodeTableMissing     = "VAL-TABLE-001"
	CodeTableBothMissing = "VAL-TABLE-002"

	// Chain findings
	CodeChainMissing       = "VAL-CHAIN-001"
	CodeHelperChainMissing = "VAL-CHAIN-002"
	CodeChainCountDrop     = "VAL-CHAIN-003"
	CodeChainEmpty         = "VAL-CHAIN-004" // B80-3: chain exists but has no rules

	// Anchor findings
	CodeAnchorMissing  = "VAL-ANCHOR-001"
	CodeAnchorOrder    = "VAL-ANCHOR-002"
	CodeAnchorFinal    = "VAL-ANCHOR-003" // FINAL GUARD
	CodeAnchorTruncate = "VAL-ANCHOR-004"

	// Set findings
	CodeSetMissing = "VAL-SET-001"

	// Module findings
	CodeModuleDegraded = "VAL-MODULE-001"

	// Service findings (B80-4)
	CodeServiceDown = "VAL-SERVICE-001" // required service not active

	// System findings
	CodeNftFailed   = "VAL-SYSTEM-001"
	CodeNftNoOutput = "VAL-SYSTEM-002"
	CodeParseError  = "VAL-SYSTEM-003"
)

Finding codes (stable for automation).

Variables

View Source
var AllHelperChains = GeneratedAllHelperChains

AllHelperChains lists all known helper chains for module-truth derivation and informational reporting. Not used for base structural validation.

View Source
var GeneratedAllHelperChains = []string{
	"ddos_penalty",
	"ddos_prefix",
	"ddos_protection",
	"ddos_sanity",
	"http_bot_guard",
	"portscan_detection",
}

GeneratedAllHelperChains — all known helper chains (shell-declared + DDoS fragment sub-chains). Module-scoped: only required when their module is enabled.

View Source
var GeneratedAllSetsIPv4 = []string{
	"blacklist_ipv4",
	"blacklist_manual_ipv4",
	"http_bot_allow",
	"http_bot_ban",
	"http_bot_emergency",
	"http_bot_grey",
	"http_bot_pending",
	"http_bot_suspect",
	"port_allow_tcp_ipv4",
	"port_allow_udp_ipv4",
	"tcp_ports_in",
	"tcp_ports_out",
	"udp_ports_in",
	"udp_ports_out",
	"whitelist_ipv4",
}

GeneratedAllSetsIPv4 — all known IPv4 set names from canonical schema (including optional module sets).

View Source
var GeneratedAllSetsIPv6 = []string{
	"blacklist_ipv6",
	"blacklist_manual_ipv6",
	"http_bot_allow6",
	"http_bot_ban6",
	"http_bot_emergency6",
	"http_bot_grey6",
	"http_bot_pending6",
	"http_bot_suspect6",
	"port_allow_tcp_ipv6",
	"port_allow_udp_ipv6",
	"tcp_ports_in",
	"tcp_ports_out",
	"udp_ports_in",
	"udp_ports_out",
	"whitelist_ipv6",
}

GeneratedAllSetsIPv6 — all known IPv6 set names from canonical schema (including optional module sets).

View Source
var GeneratedRequiredBaseChains = []string{
	"forward",
	"input",
	"output",
}

GeneratedRequiredBaseChains from NFTBAN_IPV4_CHAINS keys.

View Source
var GeneratedRequiredHelperChains = []string{}

GeneratedRequiredHelperChains — helper chains universally required for base PROTECTED. Currently empty: all helper chains are module-scoped.

View Source
var GeneratedRequiredSetsIPv4 = []string{
	"blacklist_ipv4",
	"blacklist_manual_ipv4",
	"tcp_ports_in",
	"udp_ports_in",
	"whitelist_ipv4",
}

GeneratedRequiredSetsIPv4 — core sets required for base protection.

View Source
var GeneratedRequiredSetsIPv6 = []string{
	"blacklist_ipv6",
	"blacklist_manual_ipv6",
	"tcp_ports_in",
	"udp_ports_in",
	"whitelist_ipv6",
}

GeneratedRequiredSetsIPv6 — core sets required for base protection.

View Source
var RequiredAnchors = []string{
	"ANCHOR_HYGIENE",
	"ANCHOR_TRUSTED",
	"ANCHOR_BAN",
	"ANCHOR_ESTABLISHED",
	"ANCHOR_DETECT",
	"ANCHOR_SERVICE",
	"ANCHOR_FINAL",
}

Required anchors in strict order. AUTHORITY NOTE (B80-5): Anchors are a validator-defined invariant, NOT derived from the shell schema. They represent the required rule-comment sequence in the input chain. The canonical authority for chains/sets is nft_schema.sh via schema_generated.go. The canonical authority for anchor ordering is this list, maintained manually in this file.

View Source
var RequiredBaseChains = GeneratedRequiredBaseChains

Required base chains per family. B80-5/6: sourced from schema_generated.go (canonical: cli/lib/nftban/lib/nft_schema.sh).

View Source
var RequiredHelperChains = GeneratedRequiredHelperChains

Required helper chains per family. Currently EMPTY — all helper chains are module-scoped (only exist when their module is enabled). Base PROTECTED does not require any helper chains. Module-level chain validation is handled by deriveModuleTruth() which checks presence per-module.

View Source
var RequiredSetsIPv4 = GeneratedRequiredSetsIPv4

Required sets for IPv4. B80-5/6: sourced from schema_generated.go (core required sets only).

View Source
var RequiredSetsIPv6 = GeneratedRequiredSetsIPv6

Required sets for IPv6. B80-5/6: sourced from schema_generated.go (core required sets only).

Functions

func CompareChainCounts

func CompareChainCounts(pre, post ChainCounts, tolerance int) (bool, string)

CompareChainCounts compares pre and post chain counts for rebuild safety. Returns (degraded bool, message string).

func SetServiceChecker added in v1.80.0

func SetServiceChecker(sc ServiceChecker)

SetServiceChecker replaces the service checker (for testing only).

Types

type AnchorCheck

type AnchorCheck struct {
	RequiredCount int      `json:"required_count"`
	FoundCount    int      `json:"found_count"`
	Ordered       bool     `json:"ordered"`
	AnchorsFound  []string `json:"anchors_found"`
	Missing       []string `json:"missing"`
	OrderExpected []string `json:"order_expected"`
	OrderActual   []string `json:"order_actual"`
	FinalPresent  bool     `json:"final_present"` // FINAL GUARD invariant
}

AnchorCheck holds anchor validation results.

type ChainCheck

type ChainCheck struct {
	Required []string `json:"required"`
	Found    []string `json:"found"`
	Missing  []string `json:"missing"`
	AllFound bool     `json:"all_found"`
}

ChainCheck holds chain validation results.

type ChainCounts

type ChainCounts struct {
	IPv4Total   int `json:"ipv4_total"`
	IPv4Base    int `json:"ipv4_base"`
	IPv4Helper  int `json:"ipv4_helper"`
	IPv6Total   int `json:"ipv6_total"`
	IPv6Base    int `json:"ipv6_base"`
	IPv6Helper  int `json:"ipv6_helper"`
	TotalChains int `json:"total_chains"`
}

ChainCounts for relative comparison (rebuild safety).

type FamilyResult

type FamilyResult struct {
	Family       string      `json:"family"` // "ip" or "ip6"
	Status       Status      `json:"status"`
	TablePresent bool        `json:"table_present"`
	ChainCount   int         `json:"chain_count"`
	SetCount     int         `json:"set_count"`
	BaseChains   ChainCheck  `json:"base_chains"`
	HelperChains ChainCheck  `json:"helper_chains"`
	Anchors      AnchorCheck `json:"anchors"`
	Sets         SetCheck    `json:"sets"`
}

FamilyResult holds validation results for a single address family (ip/ip6).

type Finding

type Finding struct {
	Code        string   `json:"code"`
	Severity    Severity `json:"severity"`
	Component   string   `json:"component"`
	Family      string   `json:"family,omitempty"`
	Message     string   `json:"message"`
	Remediation string   `json:"remediation,omitempty"`
}

Finding represents a single validation finding.

type ModuleInfo

type ModuleInfo struct {
	Enabled       bool   `json:"enabled"`
	KernelPresent bool   `json:"kernel_present"`
	Details       string `json:"details,omitempty"`
}

ModuleInfo holds information about a single module.

type ModuleStatus

type ModuleStatus struct {
	DDoS             ModuleInfo `json:"ddos"`
	Portscan         ModuleInfo `json:"portscan"`
	Blacklist        ModuleInfo `json:"blacklist"`
	Whitelist        ModuleInfo `json:"whitelist"`
	ServiceAdmission ModuleInfo `json:"service_admission"`
}

ModuleStatus holds runtime truth about protection modules.

type NftChain

type NftChain struct {
	Family   string `json:"family"`
	Table    string `json:"table"`
	Name     string `json:"name"`
	Type     string `json:"type,omitempty"`
	Hook     string `json:"hook,omitempty"`
	Priority int    `json:"prio,omitempty"`
	Policy   string `json:"policy,omitempty"`
	Handle   int    `json:"handle,omitempty"`
}

NftChain represents an nftables chain.

type NftCounter

type NftCounter struct {
	Family  string `json:"family"`
	Table   string `json:"table"`
	Name    string `json:"name"`
	Handle  int    `json:"handle,omitempty"`
	Packets int64  `json:"packets,omitempty"`
	Bytes   int64  `json:"bytes,omitempty"`
}

NftCounter represents a named counter.

type NftMetainfo

type NftMetainfo struct {
	Version           string `json:"version"`
	ReleaseName       string `json:"release_name"`
	JsonSchemaVersion int    `json:"json_schema_version"`
}

NftMetainfo holds nft version info.

type NftObject

type NftObject struct {
	Metainfo *NftMetainfo `json:"metainfo,omitempty"`
	Table    *NftTable    `json:"table,omitempty"`
	Chain    *NftChain    `json:"chain,omitempty"`
	Set      *NftSet      `json:"set,omitempty"`
	Rule     *NftRule     `json:"rule,omitempty"`
	Counter  *NftCounter  `json:"counter,omitempty"`
}

NftObject is a wrapper for any nft object (table, chain, set, rule, etc.). Only one field will be populated per object.

type NftRule

type NftRule struct {
	Family  string        `json:"family"`
	Table   string        `json:"table"`
	Chain   string        `json:"chain"`
	Handle  int           `json:"handle,omitempty"`
	Comment string        `json:"comment,omitempty"`
	Expr    []interface{} `json:"expr,omitempty"`
}

NftRule represents an nftables rule.

type NftRuleset

type NftRuleset struct {
	Nftables []NftObject `json:"nftables"`
}

NftRuleset represents the top-level nft -j list ruleset output. The JSON structure is: { "nftables": [ {...}, {...}, ... ] }

func LoadRulesetJSON

func LoadRulesetJSON(ctx context.Context) (*NftRuleset, error)

LoadRulesetJSON executes nft -j list ruleset and parses the output. This is a PURE function - it only reads kernel state, never modifies.

type NftSet

type NftSet struct {
	Family  string     `json:"family"`
	Table   string     `json:"table"`
	Name    string     `json:"name"`
	Type    NftSetType `json:"type,omitempty"`
	Flags   []string   `json:"flags,omitempty"`
	Timeout int        `json:"timeout,omitempty"`
	Handle  int        `json:"handle,omitempty"`
}

NftSet represents an nftables set.

type NftSetType

type NftSetType struct {
	Types []string
}

NftSetType handles nft set type which can be string or []string (for concatenations).

func (*NftSetType) UnmarshalJSON

func (t *NftSetType) UnmarshalJSON(data []byte) error

UnmarshalJSON handles both string and []string for nft set type field.

type NftTable

type NftTable struct {
	Family string `json:"family"`
	Name   string `json:"name"`
	Handle int    `json:"handle,omitempty"`
}

NftTable represents an nftables table.

type RulesetDocument

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

RulesetDocument provides structured access to the parsed ruleset.

func ParseRuleset

func ParseRuleset(raw *NftRuleset) *RulesetDocument

ParseRuleset converts raw NftRuleset into a structured document.

func (*RulesetDocument) ChainExists

func (d *RulesetDocument) ChainExists(family, table, chain string) bool

ChainExists checks if a chain exists.

func (*RulesetDocument) CountChains

func (d *RulesetDocument) CountChains(family string) int

CountChains returns total chain count for a family's nftban table.

func (*RulesetDocument) CountRulesInChain added in v1.80.0

func (d *RulesetDocument) CountRulesInChain(family, table, chain string) int

CountRulesInChain returns the number of rules in a specific chain. Returns 0 if the chain has no rules or does not exist.

func (*RulesetDocument) CountSets

func (d *RulesetDocument) CountSets(family string) int

CountSets returns total set count for a family's nftban table.

func (*RulesetDocument) ExtractAnchorsFromChain

func (d *RulesetDocument) ExtractAnchorsFromChain(family, table, chain string) []string

ExtractAnchorsFromChain extracts anchor names from rule comments in a chain. Anchors are identified by comments containing "NFTBAN_ANCHOR:ANCHOR_*".

func (*RulesetDocument) GetChains

func (d *RulesetDocument) GetChains(family, table string) []string

GetChains returns all chain names for a table.

func (*RulesetDocument) GetRules

func (d *RulesetDocument) GetRules(family, table, chain string) []*NftRule

GetRules returns all rules for a chain.

func (*RulesetDocument) GetSets

func (d *RulesetDocument) GetSets(family, table string) []string

GetSets returns all set names for a table.

func (*RulesetDocument) SetExists

func (d *RulesetDocument) SetExists(family, table, set string) bool

SetExists checks if a set exists.

func (*RulesetDocument) TableExists

func (d *RulesetDocument) TableExists(family, name string) bool

TableExists checks if a table exists.

type RuntimeState added in v1.80.0

type RuntimeState string

RuntimeState represents a three-state service status. Aligns with the v1.82 health model direction (RUNNING / STOPPED / ERROR).

const (
	RuntimeRunning RuntimeState = "RUNNING"
	RuntimeStopped RuntimeState = "STOPPED"
	RuntimeError   RuntimeState = "ERROR" // systemctl query itself failed
)

type ServiceChecker added in v1.80.0

type ServiceChecker interface {
	// CheckUnit returns (RuntimeState, detail string).
	// RuntimeState: RUNNING / STOPPED / ERROR.
	// detail: the raw systemctl output (e.g. "active", "inactive", "failed").
	CheckUnit(unit string) (RuntimeState, string)
}

ServiceChecker abstracts service-state queries so unit tests can mock systemd without requiring a real init system. The default implementation calls `systemctl is-active <unit>`.

type ServiceState added in v1.80.0

type ServiceState struct {
	Nftband       RuntimeState `json:"nftband"`
	NftbandDetail string       `json:"nftband_detail,omitempty"`
}

ServiceState holds the live status of required system services. B80-4: the validator MUST check these before declaring PROTECTED. A system with correct kernel structure but a dead daemon is not protected.

type SetCheck

type SetCheck struct {
	Required []string `json:"required"`
	Found    []string `json:"found"`
	Missing  []string `json:"missing"`
	AllFound bool     `json:"all_found"`
}

SetCheck holds set validation results.

type Severity

type Severity string

Severity for findings.

const (
	SeverityInfo     Severity = "info"
	SeverityWarn     Severity = "warn"
	SeverityError    Severity = "error"
	SeverityCritical Severity = "critical"
)

type Status

type Status string

Status represents the overall protection state.

const (
	// StatusProtected means all validation checks passed.
	StatusProtected Status = "protected"
	// StatusDegraded means partial protection - some checks failed.
	StatusDegraded Status = "degraded"
	// StatusDown means no viable nftban protection detected.
	StatusDown Status = "down"
)

type SummaryCounts

type SummaryCounts struct {
	TotalFindings    int `json:"total_findings"`
	CriticalFindings int `json:"critical_findings"`
	ErrorFindings    int `json:"error_findings"`
	WarnFindings     int `json:"warn_findings"`
	CheckedFamilies  int `json:"checked_families"`
	ProtectedFams    int `json:"protected_families"`
	DegradedFams     int `json:"degraded_families"`
}

SummaryCounts provides quick stats.

type SystemdChecker added in v1.80.0

type SystemdChecker struct{}

SystemdChecker is the default production ServiceChecker.

func (SystemdChecker) CheckUnit added in v1.80.0

func (SystemdChecker) CheckUnit(unit string) (RuntimeState, string)

CheckUnit queries systemd for the unit's active state. This is a read-only query — zero side effects.

type ValidationResult

type ValidationResult struct {
	Status       Status         `json:"status"`
	Timestamp    time.Time      `json:"timestamp"`
	Families     []FamilyResult `json:"families"`
	Findings     []Finding      `json:"findings"`
	Summary      SummaryCounts  `json:"summary"`
	ModuleTruth  ModuleStatus   `json:"module_truth"`
	ChainCount   ChainCounts    `json:"chain_counts"`
	ServiceState ServiceState   `json:"service_state"` // B80-4
}

ValidationResult is the complete output of kernel validation.

func RunValidation

func RunValidation(ctx context.Context) (*ValidationResult, error)

RunValidation is a convenience function that runs validation and returns the result. Returns (result, nil) even if status is DOWN - that's a valid result.

func ValidateKernel

func ValidateKernel(ctx context.Context) (*ValidationResult, error)

ValidateKernel performs complete kernel state validation. This is the main entrypoint for the validator.

CRITICAL: This function is PURE - it only reads, never modifies.

func (*ValidationResult) ExitCode

func (r *ValidationResult) ExitCode() int

ExitCode returns the appropriate exit code for the status. 0 = PROTECTED, 1 = DEGRADED, 2 = DOWN

func (*ValidationResult) PrintSummary

func (r *ValidationResult) PrintSummary()

PrintSummary prints a human-readable summary to stdout.

func (*ValidationResult) StatusString

func (r *ValidationResult) StatusString() string

StatusString returns a human-readable status with emoji.

func (*ValidationResult) ToJSON

func (r *ValidationResult) ToJSON() ([]byte, error)

ToJSON converts the validation result to JSON.

Jump to

Keyboard shortcuts

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