Files
tomswall/internal/config/mangle.go
T
unkinben 8d9a76c751 Add comprehensive nftables compiler with shorewall feature parity
Rewrites the compiler from ~440 to ~1700 lines covering all major shorewall
firewall features: loopback, conntrack fast-path, anti-spoof, DHCP, intra-zone,
blacklist/whitelist, conntrack notrack, tunnels (13 types), rules with sections,
DNAT/redirect, SNAT/masquerade, static NAT, policies with zone exclusions,
MSS clamping, rate limiting, connection limiting, negated addresses, ICMP type
matching, TCP RST reject, user/UID matching, mark match/set, NFQUEUE, NONAT,
and policy-level rate/conn limiting.

Adds full config types for all shorewall subsystems (mangle, accounting, maclist,
netmap, providers, tunnels, conntrack, blrules, proxyarp/ndp, routes, tc, secmarks),
shorewall migration tooling, expanded CLI commands, expression-level diff engine,
and 49 unit tests.
2026-07-01 23:56:44 +10:00

116 lines
3.2 KiB
Go

package config
import "fmt"
type MangleAction string
const (
MangleMark MangleAction = "mark"
MangleConnMark MangleAction = "connmark"
MangleClassify MangleAction = "classify"
MangleDSCP MangleAction = "dscp"
MangleTOS MangleAction = "tos"
MangleTProxy MangleAction = "tproxy"
MangleSave MangleAction = "save"
MangleRestore MangleAction = "restore"
MangleContinue MangleAction = "continue"
MangleDrop MangleAction = "drop"
MangleLog MangleAction = "log"
MangleNFLog MangleAction = "nflog"
MangleECN MangleAction = "ecn"
MangleTCPMSS MangleAction = "tcpmss"
MangleChecksum MangleAction = "checksum"
MangleInline MangleAction = "inline"
)
type MangleChain string
const (
ManglePrerouting MangleChain = "prerouting"
MangleForward MangleChain = "forward"
ManglePostrouting MangleChain = "postrouting"
MangleInput MangleChain = "input"
MangleOutput MangleChain = "output"
)
type MangleRule struct {
Action MangleAction `yaml:"action"`
Chain MangleChain `yaml:"chain"`
// MarkValue is the value to set (required for mark, connmark, classify, dscp, tos actions).
MarkValue string `yaml:"mark_value,omitempty"`
Source string `yaml:"source,omitempty"`
Dest string `yaml:"dest,omitempty"`
Proto string `yaml:"proto,omitempty"`
DPort PortSpec `yaml:"dport,omitempty"`
SPort PortSpec `yaml:"sport,omitempty"`
// User/group match (only valid for output chain).
User string `yaml:"user,omitempty"`
// Packet or connection mark test. Format: [!]value[/mask][:C]
Mark string `yaml:"mark,omitempty"`
// Packet length match.
Length string `yaml:"length,omitempty"`
// TOS field match.
TOS string `yaml:"tos,omitempty"`
// Conntrack helper match.
Helper string `yaml:"helper,omitempty"`
// Match probability (0.0 to 1.0).
Probability float64 `yaml:"probability,omitempty"`
// DSCP field match.
DSCP string `yaml:"dscp,omitempty"`
// Connection state match.
State string `yaml:"state,omitempty"`
// Time-based restrictions.
Time *TimeSpec `yaml:"time,omitempty"`
Comment string `yaml:"comment,omitempty"`
}
var validMangleActions = map[MangleAction]bool{
MangleMark: true, MangleConnMark: true, MangleClassify: true,
MangleDSCP: true, MangleTOS: true, MangleTProxy: true,
MangleSave: true, MangleRestore: true, MangleContinue: true,
MangleDrop: true, MangleLog: true, MangleNFLog: true,
MangleECN: true, MangleTCPMSS: true, MangleChecksum: true,
MangleInline: true,
}
var validMangleChains = map[MangleChain]bool{
ManglePrerouting: true, MangleForward: true,
ManglePostrouting: true, MangleInput: true,
MangleOutput: true,
}
// markValueRequiredActions lists actions that require a mark_value.
var markValueRequiredActions = map[MangleAction]bool{
MangleMark: true, MangleConnMark: true, MangleClassify: true,
MangleDSCP: true, MangleTOS: true,
}
func (c *Config) validateMangle() error {
for i, m := range c.Mangle {
if !validMangleActions[m.Action] {
return fmt.Errorf("mangle[%d]: unknown action %q", i, m.Action)
}
if !validMangleChains[m.Chain] {
return fmt.Errorf("mangle[%d]: unknown chain %q", i, m.Chain)
}
if markValueRequiredActions[m.Action] && m.MarkValue == "" {
return fmt.Errorf("mangle[%d]: mark_value required for %s action", i, m.Action)
}
}
return nil
}