Files
tomswall/internal/config/blrules.go
T
unkin-agent 8efed72c96
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Match exact all/any zone tokens, skip only interface-less ip zones, keep DNAT free of rule extras, reject '!' inside address lists
2026-10-03 20:50:36 +10:00

84 lines
2.3 KiB
Go

package config
import "fmt"
type BlruleAction string
const (
BlruleAccept BlruleAction = "accept"
BlruleWhitelist BlruleAction = "whitelist"
BlruleDrop BlruleAction = "drop"
BlruleReject BlruleAction = "reject"
BlruleLog BlruleAction = "log"
BlruleContinue BlruleAction = "continue"
BlruleNFQueue BlruleAction = "nfqueue"
)
// BlruleRule defines a blacklist/whitelist rule.
// Processed before normal rules; ACCEPT/WHITELIST/CONTINUE exempt matching
// traffic from remaining blacklist rules.
type BlruleRule struct {
Action BlruleAction `yaml:"action"`
Source string `yaml:"source"`
Dest string `yaml:"dest"`
Proto string `yaml:"proto,omitempty"`
DPort PortSpec `yaml:"dport,omitempty"`
SPort PortSpec `yaml:"sport,omitempty"`
Log string `yaml:"log,omitempty"`
// NFQUEUE number (only for nfqueue action).
NFQueue int `yaml:"nfqueue,omitempty"`
Comment string `yaml:"comment,omitempty"`
}
var validBlruleActions = map[BlruleAction]bool{
BlruleAccept: true, BlruleWhitelist: true,
BlruleDrop: true, BlruleReject: true,
BlruleLog: true, BlruleContinue: true,
BlruleNFQueue: true,
}
func (c *Config) validateBlrules() error {
for i, r := range c.Blrules {
if !validBlruleActions[r.Action] {
return fmt.Errorf("blrules[%d]: unknown action %q", i, r.Action)
}
if r.Source == "" {
return fmt.Errorf("blrules[%d]: source required", i)
}
if r.Dest == "" {
return fmt.Errorf("blrules[%d]: dest required", i)
}
if r.Source != "all" && r.Source != "any" && r.Source != "none" &&
!hasPrefix(r.Source, "all!") && !hasPrefix(r.Source, "any!") {
for _, zs := range SplitZoneList(r.Source) {
if _, ok := c.Zones[zs.Zone]; !ok {
return fmt.Errorf("blrules[%d]: source zone %q not defined", i, zs.Zone)
}
if !validAddrList(zs.Addr) {
return fmt.Errorf("blrules[%d]: source %q: '!' may only prefix the whole address list", i, zs.Addr)
}
}
}
if r.Dest != "all" && r.Dest != "any" && r.Dest != "none" &&
!hasPrefix(r.Dest, "all!") && !hasPrefix(r.Dest, "any!") {
for _, zs := range SplitZoneList(r.Dest) {
if _, ok := c.Zones[zs.Zone]; !ok {
return fmt.Errorf("blrules[%d]: dest zone %q not defined", i, zs.Zone)
}
if !validAddrList(zs.Addr) {
return fmt.Errorf("blrules[%d]: dest %q: '!' may only prefix the whole address list", i, zs.Addr)
}
}
}
}
return nil
}