Files
tomswall/internal/config/tunnels.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

90 lines
2.7 KiB
Go

package config
import "fmt"
type TunnelType string
const (
TunnelIPSec TunnelType = "ipsec"
TunnelIPSecNAT TunnelType = "ipsecnat"
TunnelIPIP TunnelType = "ipip"
TunnelGRE TunnelType = "gre"
TunnelL2TP TunnelType = "l2tp"
TunnelPPTPClient TunnelType = "pptpclient"
TunnelPPTPServer TunnelType = "pptpserver"
TunnelOpenVPN TunnelType = "openvpn"
TunnelOpenVPNClient TunnelType = "openvpnclient"
TunnelOpenVPNServer TunnelType = "openvpnserver"
TunnelTinc TunnelType = "tinc"
Tunnel6to4 TunnelType = "6to4"
TunnelGeneric TunnelType = "generic"
)
// Tunnel defines VPN tunnel rules that allow encapsulated traffic to pass
// between the firewall and remote gateways. The actual traffic flowing
// through the tunnel is handled by normal zone/policy/rules.
type Tunnel struct {
// Tunnel type. For ipsec, append ":ah" to use Authentication Headers (default: no AH).
// For openvpn variants, append ":tcp" or ":udp" (default: udp).
// For generic, append ":protocol" or ":protocol:port".
Type string `yaml:"type"`
// Zone of the physical interface through which tunnel traffic passes.
Zone string `yaml:"zone"`
// Remote tunnel gateway address(es). Use 0.0.0.0/0 or ::/0 for road warriors.
Gateways []string `yaml:"gateways"`
// Zones that the remote gateway host belongs to (for IPSEC ISAKMP traffic).
GatewayZones []string `yaml:"gateway_zones,omitempty"`
// Port override for openvpn/generic types (default: type-specific).
Port int `yaml:"port,omitempty"`
Comment string `yaml:"comment,omitempty"`
}
var validTunnelTypes = map[TunnelType]bool{
TunnelIPSec: true, TunnelIPSecNAT: true,
TunnelIPIP: true, TunnelGRE: true, TunnelL2TP: true,
TunnelPPTPClient: true, TunnelPPTPServer: true,
TunnelOpenVPN: true, TunnelOpenVPNClient: true, TunnelOpenVPNServer: true,
TunnelTinc: true, Tunnel6to4: true, TunnelGeneric: true,
}
func ParseTunnelType(s string) (TunnelType, string, bool) {
for i, c := range s {
if c == ':' {
return TunnelType(s[:i]), s[i+1:], true
}
}
return TunnelType(s), "", false
}
func (c *Config) validateTunnels() error {
for i, t := range c.Tunnels {
baseType, _, _ := ParseTunnelType(t.Type)
if !validTunnelTypes[baseType] {
return fmt.Errorf("tunnels[%d]: unknown tunnel type %q", i, baseType)
}
if t.Zone == "" {
return fmt.Errorf("tunnels[%d]: zone required", i)
}
if _, ok := c.Zones[t.Zone]; !ok {
return fmt.Errorf("tunnels[%d]: zone %q not defined", i, t.Zone)
}
if len(t.Gateways) == 0 {
return fmt.Errorf("tunnels[%d]: at least one gateway required", i)
}
for _, gz := range t.GatewayZones {
if _, ok := c.Zones[gz]; !ok {
return fmt.Errorf("tunnels[%d]: gateway zone %q not defined", i, gz)
}
}
}
return nil
}