Files
tomswall/internal/nftables/cleanup.go
T
unkinben 2a3eb3b04d 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.
2026-06-28 23:43:16 +10:00

96 lines
1.9 KiB
Go

package nftables
import (
"fmt"
"github.com/google/nftables"
)
type ForeignRule struct {
Table string
Chain string
Handle uint64
Family nftables.TableFamily
table *nftables.Table
chain *nftables.Chain
}
func (f ForeignRule) String() string {
return fmt.Sprintf("table=%s chain=%s handle=%d", f.Table, f.Chain, f.Handle)
}
func (e *Engine) FindForeignRules() ([]ForeignRule, error) {
tables, err := e.conn.ListTables()
if err != nil {
return nil, fmt.Errorf("listing tables: %w", err)
}
var ourTable *nftables.Table
for _, t := range tables {
if t.Name == e.cfg.Settings.TableName && t.Family == nftables.TableFamilyINet {
ourTable = t
break
}
}
if ourTable == nil {
return nil, nil
}
compiler := NewCompiler(e.cfg)
desired, err := compiler.Compile()
if err != nil {
return nil, fmt.Errorf("compiling config: %w", err)
}
desiredTags := make(map[string]bool)
for _, rules := range desired.Rules {
for _, r := range rules {
desiredTags[r.Tag] = true
}
}
var foreign []ForeignRule
chains, err := e.conn.ListChainsOfTableFamily(nftables.TableFamilyINet)
if err != nil {
return nil, fmt.Errorf("listing chains: %w", err)
}
for _, chain := range chains {
if chain.Table.Name != e.cfg.Settings.TableName {
continue
}
rules, err := e.conn.GetRules(ourTable, chain)
if err != nil {
continue
}
for _, rule := range rules {
tag := string(rule.UserData)
if tag == "" || !desiredTags[tag] {
foreign = append(foreign, ForeignRule{
Table: ourTable.Name,
Chain: chain.Name,
Handle: rule.Handle,
Family: ourTable.Family,
table: ourTable,
chain: chain,
})
}
}
}
return foreign, nil
}
func (e *Engine) PurgeForeignRules(foreign []ForeignRule) error {
for _, f := range foreign {
e.conn.DelRule(&nftables.Rule{
Table: f.table,
Chain: f.chain,
Handle: f.Handle,
})
}
return e.conn.Flush()
}