various: implement stateful firewalling on Linux (#12025)
Updates https://github.com/tailscale/corp/issues/19623 Change-Id: I7980e1fb736e234e66fa000d488066466c96ec85 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Co-authored-by: Andrew Dunham <andrew@du.nham.ca>
This commit is contained in:
@@ -38,17 +38,18 @@ const (
|
||||
)
|
||||
|
||||
type linuxRouter struct {
|
||||
closed atomic.Bool
|
||||
logf func(fmt string, args ...any)
|
||||
tunname string
|
||||
netMon *netmon.Monitor
|
||||
unregNetMon func()
|
||||
addrs map[netip.Prefix]bool
|
||||
routes map[netip.Prefix]bool
|
||||
localRoutes map[netip.Prefix]bool
|
||||
snatSubnetRoutes bool
|
||||
netfilterMode preftype.NetfilterMode
|
||||
netfilterKind string
|
||||
closed atomic.Bool
|
||||
logf func(fmt string, args ...any)
|
||||
tunname string
|
||||
netMon *netmon.Monitor
|
||||
unregNetMon func()
|
||||
addrs map[netip.Prefix]bool
|
||||
routes map[netip.Prefix]bool
|
||||
localRoutes map[netip.Prefix]bool
|
||||
snatSubnetRoutes bool
|
||||
statefulFiltering bool
|
||||
netfilterMode preftype.NetfilterMode
|
||||
netfilterKind string
|
||||
|
||||
// ruleRestorePending is whether a timer has been started to
|
||||
// restore deleted ip rules.
|
||||
@@ -390,6 +391,7 @@ func (r *linuxRouter) Set(cfg *Config) error {
|
||||
}
|
||||
r.addrs = newAddrs
|
||||
|
||||
// Ensure that the SNAT rule is added or removed as needed.
|
||||
switch {
|
||||
case cfg.SNATSubnetRoutes == r.snatSubnetRoutes:
|
||||
// state already correct, nothing to do.
|
||||
@@ -404,6 +406,21 @@ func (r *linuxRouter) Set(cfg *Config) error {
|
||||
}
|
||||
r.snatSubnetRoutes = cfg.SNATSubnetRoutes
|
||||
|
||||
// As above, for stateful filtering
|
||||
switch {
|
||||
case cfg.StatefulFiltering == r.statefulFiltering:
|
||||
// state already correct, nothing to do.
|
||||
case cfg.StatefulFiltering:
|
||||
if err := r.addStatefulRule(); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
default:
|
||||
if err := r.delStatefulRule(); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
r.statefulFiltering = cfg.StatefulFiltering
|
||||
|
||||
// Issue 11405: enable IP forwarding on gokrazy.
|
||||
advertisingRoutes := len(cfg.SubnetRoutes) > 0
|
||||
if distro.Get() == distro.Gokrazy && advertisingRoutes {
|
||||
@@ -1327,6 +1344,26 @@ func (r *linuxRouter) delSNATRule() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// addStatefulRule adds a netfilter rule to perform stateful filtering from
|
||||
// subnets onto the tailnet.
|
||||
func (r *linuxRouter) addStatefulRule() error {
|
||||
if r.netfilterMode == netfilterOff {
|
||||
return nil
|
||||
}
|
||||
|
||||
return r.nfr.AddStatefulRule(r.tunname)
|
||||
}
|
||||
|
||||
// delStatefulRule removes the netfilter rule to perform stateful filtering
|
||||
// from subnets onto the tailnet.
|
||||
func (r *linuxRouter) delStatefulRule() error {
|
||||
if r.netfilterMode == netfilterOff {
|
||||
return nil
|
||||
}
|
||||
|
||||
return r.nfr.DelStatefulRule(r.tunname)
|
||||
}
|
||||
|
||||
// cidrDiff calls add and del as needed to make the set of prefixes in
|
||||
// old and new match. Returns a map reflecting the actual new state
|
||||
// (which may be somewhere in between old and new if some commands
|
||||
|
||||
Reference in New Issue
Block a user