2a3eb3b04d
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.
96 lines
1.9 KiB
Go
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()
|
|
}
|