Initial scaffold for tomswall

Spiritual successor to shorewall — manages nftables directly via
google/nftables. Reads a single YAML config covering zones, interfaces,
hosts, policy, rules, snat, and named portgroups. Computes differential
changes against the running nftables state and applies them atomically.
Supports detecting and purging rules added outside of tomswall.
This commit is contained in:
2026-06-28 23:43:16 +10:00
commit 2a3eb3b04d
18 changed files with 1672 additions and 0 deletions
+47
View File
@@ -0,0 +1,47 @@
package config
import "fmt"
type ZoneType string
const (
ZoneIP ZoneType = "ip"
ZoneIPSec ZoneType = "ipsec"
ZoneFirewall ZoneType = "firewall"
ZoneLoopback ZoneType = "loopback"
)
type Zone struct {
Type ZoneType `yaml:"type"`
Parent string `yaml:"parent,omitempty"`
Options []string `yaml:"options,omitempty"`
}
func (c *Config) validateZones() error {
if len(c.Zones) == 0 {
return fmt.Errorf("no zones defined")
}
firewallCount := 0
for name, z := range c.Zones {
switch z.Type {
case ZoneIP, ZoneIPSec, ZoneFirewall, ZoneLoopback:
default:
return fmt.Errorf("zone %q: unknown type %q", name, z.Type)
}
if z.Type == ZoneFirewall {
firewallCount++
}
if z.Parent != "" {
if _, ok := c.Zones[z.Parent]; !ok {
return fmt.Errorf("zone %q: parent zone %q not defined", name, z.Parent)
}
}
}
if firewallCount != 1 {
return fmt.Errorf("exactly one firewall zone required, found %d", firewallCount)
}
return nil
}