Files
housecarl/internal/model/settings.go
T
abrown38andClaude Opus 5.5 e4efdf9c78 Confirm changes automatically from the client that made them
A change made over the network answers with a one-time confirm_token
and closes its connection (HTTP/2: a GOAWAY). The web UI and hc send the
token straight back to /confirm, which accepts it only for the newest
change, from the same user and API token, the same address, and over a
new connection: proof that the client can still reach the API through
the new ruleset (an established connection would get through anyway). A
change that cuts its client off can't be confirmed so, and rolls back by
itself. The setting manual_confirm (hc settings set --auto-confirm off)
and hc --no-confirm leave confirming to a person. Changes through the
local socket still need no confirmation. e2e: 136 checks, among them a
lockout change rolled back without anyone confirming.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 13:23:28 +01:00

96 lines
3.8 KiB
Go

package model
// Settings are the firewall-wide settings: default policies and the rules
// Housecarl adds by itself ("built-ins"), each of which can be turned off.
type Settings struct {
// Policies for packets no rule decided: accept or drop.
InputPolicy string `json:"input_policy"`
ForwardPolicy string `json:"forward_policy"`
OutputPolicy string `json:"output_policy"`
// LogPolicyDrops logs (rate-limited) what the input and forward
// policies drop.
LogPolicyDrops bool `json:"log_policy_drops,omitempty"`
Builtins Builtins `json:"builtins"`
// AntispoofV4 and AntispoofV6 are source addresses that can't come
// from the internet: dropped on external zones (Builtins.Antispoof),
// together with OwnPrefixes.
AntispoofV4 []string `json:"antispoof_v4"`
AntispoofV6 []string `json:"antispoof_v6"`
// OwnPrefixes are your own public prefixes (your delegated IPv6
// prefix, say): traffic claiming to come from them can't arrive from
// outside.
OwnPrefixes []string `json:"own_prefixes,omitempty"`
// Flowtable devices: forwarded TCP and UDP connections between them
// skip the rules once established (fast path). Empty: off. Names
// must be exact (no wildcards).
FlowtableDevices []string `json:"flowtable_devices,omitempty"`
// ProbationSeconds is how long a change made over the network has to
// be confirmed before it is rolled back (0: the default).
ProbationSeconds int `json:"probation_seconds,omitempty"`
// ManualConfirm: changes made over the network wait for a person to
// confirm them. Otherwise the client that made a change confirms it by
// itself once it reaches the API again over a new connection, from the
// same address: proof that it can still manage the firewall.
ManualConfirm bool `json:"manual_confirm,omitempty"`
}
// Builtins are rules Housecarl adds itself, shown as "added by Housecarl".
type Builtins struct {
// Loopback accepts everything on lo.
Loopback bool `json:"loopback"`
// Established accepts packets of established and related connections.
Established bool `json:"established"`
// DropInvalid drops packets conntrack finds invalid.
DropInvalid bool `json:"drop_invalid"`
// ICMPv6 accepts the ICMPv6 IPv6 needs (RFC 4890): errors, echo, and
// neighbour discovery and MLD on the local link.
ICMPv6 bool `json:"icmpv6"`
// PingInternal accepts ICMP echo to the firewall from internal zones.
PingInternal bool `json:"ping_internal"`
// DHCPv6Client accepts DHCPv6 replies on external zones (an ISP's
// prefix delegation).
DHCPv6Client bool `json:"dhcpv6_client"`
// Antispoof drops impossible source addresses arriving on external
// zones (AntispoofV4, AntispoofV6, OwnPrefixes).
Antispoof bool `json:"antispoof"`
// MSSClamp clamps TCP MSS to the route MTU on external zones (needed
// with PPPoE).
MSSClamp bool `json:"mss_clamp"`
}
// Policies.
const (
PolicyAccept = "accept"
PolicyDrop = "drop"
)
// DefaultProbation is how long a network change has to be confirmed.
const DefaultProbation = 120
// DefaultSettings are the settings of a new database: drop what isn't
// allowed in and through, allow out, every built-in on.
func DefaultSettings() Settings {
return Settings{
InputPolicy: PolicyDrop,
ForwardPolicy: PolicyDrop,
OutputPolicy: PolicyAccept,
Builtins: Builtins{Loopback: true, Established: true, DropInvalid: true, ICMPv6: true,
PingInternal: true, DHCPv6Client: true, Antispoof: true, MSSClamp: false},
AntispoofV4: []string{"0.0.0.0/8", "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12",
"192.0.2.0/24", "192.168.0.0/16", "198.51.100.0/24", "203.0.113.0/24", "224.0.0.0/4", "240.0.0.0/4"},
AntispoofV6: []string{"::1/128", "::/128", "fc00::/7", "2001:db8::/32", "ff00::/8"},
}
}
// Probation is the probation in seconds, with its default.
func (s Settings) Probation() int {
if s.ProbationSeconds > 0 {
return s.ProbationSeconds
}
return DefaultProbation
}