Documentation
¶
Overview ¶
Package nftenforce answers one question: is a named nftables set actually ENFORCING, or does it merely exist?
WHY THIS EXISTS ¶
`nft get element` proves an address is a member of a set. It proves nothing about whether packets are filtered. A set can be populated and completely inert: unreferenced by any rule, referenced only from a chain nothing jumps to, referenced with a counter but no verdict, or shadowed by an earlier unconditional accept.
That gap produced a P0: `nftban ban` verified set membership and then told the operator "the IP is now blocked by the firewall". On a host whose filter chains never loaded, both statements were issued together — the first true, the second false.
Membership is not enforcement. This package evaluates the rest of the chain:
member in target set → a rule references that EXACT set → the rule's chain is reachable from a base chain with an active hook → the rule's verdict actually enforces (drop/reject)
PARSER AUTHORITY ¶
The nft JSON decode types come from internal/validator, which has carried a complete typed model (NftRuleset / NftObject / NftChain including Hook / NftRule) since v1.109. This package deliberately adds NO decode types of its own — only reachability semantics, which did not exist anywhere.
The tree still holds several other ad-hoc `json:"nftables"` decodes (two in internal/metrics, two more in internal/validator/module_health.go). Those predate this package and consolidating them is a separate failure domain; this package simply does not add to the count.
FAIL CLOSED. Anything this package cannot model — an unknown verdict on a referencing rule, a jump to a chain that does not exist, a malformed ruleset — is reported as ambiguity, never as enforcement. It is better to tell an operator "could not verify" than to tell them "protected" and be wrong.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNoRuleset = errors.New("nft json: input contains no nftables ruleset")
ErrNoRuleset is returned when the input contains no nftables array at all.
Functions ¶
This section is empty.
Types ¶
type Outcome ¶
type Outcome string
Outcome is the result of an enforcement evaluation.
const ( // ReachableEnforcingPath is the ONLY outcome that means "enforced". ReachableEnforcingPath Outcome = "REACHABLE_ENFORCING_PATH" // NoSetReference means no rule anywhere references the set. NoSetReference Outcome = "NO_SET_REFERENCE" // SetReferenceUnreachable means a rule references the set, but its chain is // not reachable from any base chain with a hook. SetReferenceUnreachable Outcome = "SET_REFERENCE_UNREACHABLE" // ReachableNonEnforcingPath means the reference is reachable but does not // enforce: counter-only, accept, or shadowed by an earlier unconditional accept. ReachableNonEnforcingPath Outcome = "REACHABLE_NON_ENFORCING_PATH" // AmbiguousRuleset means the ruleset contains something this evaluator does // not model well enough to make a safe claim. AmbiguousRuleset Outcome = "AMBIGUOUS_RULESET" // ParserFailure means the input could not be decoded at all. ParserFailure Outcome = "PARSER_FAILURE" )
type Result ¶
type Result struct {
Outcome Outcome
// Detail is a short human-readable explanation, safe to print.
Detail string
// Chain is the chain holding the set reference, when one was found.
Chain string
// BaseChain is the hooked chain the reference was reached from, when reachable.
BaseChain string
}
Result carries the outcome plus enough detail to explain it to an operator.