netns,wgengine: add OpenBSD support to netns via an rtable
When an exit node has been set and a new default route is added, create a new rtable in the default rdomain and add the current default route via its physical interface. When control() is requesting a connection not go through the exit-node default route, we can use the SO_RTABLE socket option to force it through the new rtable we created. Updates #17321 Signed-off-by: joshua stein <jcs@jcs.org>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
7370c24eb4
commit
518d241700
@@ -14,6 +14,7 @@ import (
|
||||
"go4.org/netipx"
|
||||
"tailscale.com/health"
|
||||
"tailscale.com/net/netmon"
|
||||
"tailscale.com/net/netns"
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/util/eventbus"
|
||||
"tailscale.com/util/set"
|
||||
@@ -32,12 +33,13 @@ func init() {
|
||||
// https://git.zx2c4.com/wireguard-openbsd.
|
||||
|
||||
type openbsdRouter struct {
|
||||
logf logger.Logf
|
||||
netMon *netmon.Monitor
|
||||
tunname string
|
||||
local4 netip.Prefix
|
||||
local6 netip.Prefix
|
||||
routes set.Set[netip.Prefix]
|
||||
logf logger.Logf
|
||||
netMon *netmon.Monitor
|
||||
tunname string
|
||||
local4 netip.Prefix
|
||||
local6 netip.Prefix
|
||||
routes set.Set[netip.Prefix]
|
||||
areDefaultRoute bool
|
||||
}
|
||||
|
||||
func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor, health *health.Tracker, bus *eventbus.Bus) (router.Router, error) {
|
||||
@@ -76,6 +78,10 @@ func inet(p netip.Prefix) string {
|
||||
return "inet"
|
||||
}
|
||||
|
||||
func isDefaultRoute(p netip.Prefix) bool {
|
||||
return p.Bits() == 0
|
||||
}
|
||||
|
||||
func (r *openbsdRouter) Set(cfg *router.Config) error {
|
||||
if cfg == nil {
|
||||
cfg = &shutdownConfig
|
||||
@@ -219,8 +225,12 @@ func (r *openbsdRouter) Set(cfg *router.Config) error {
|
||||
dst = localAddr6.Addr().String()
|
||||
}
|
||||
routeadd := []string{"route", "-q", "-n",
|
||||
"add", "-" + inet(route), nstr,
|
||||
"-iface", dst}
|
||||
"add", "-" + inet(route), nstr}
|
||||
if isDefaultRoute(route) {
|
||||
// 1 is reserved for kernel
|
||||
routeadd = append(routeadd, "-priority", "2")
|
||||
}
|
||||
routeadd = append(routeadd, "-iface", dst)
|
||||
out, err := cmd(routeadd...).CombinedOutput()
|
||||
if err != nil {
|
||||
r.logf("addr add failed: %v: %v\n%s", routeadd, err, out)
|
||||
@@ -235,10 +245,33 @@ func (r *openbsdRouter) Set(cfg *router.Config) error {
|
||||
r.local6 = localAddr6
|
||||
r.routes = newRoutes
|
||||
|
||||
areDefault := false
|
||||
for route := range newRoutes {
|
||||
if isDefaultRoute(route) {
|
||||
areDefault = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Set up or tear down the bypass rtable as needed
|
||||
if areDefault && !r.areDefaultRoute {
|
||||
if _, err := netns.SetupBypassRtable(r.logf); err != nil {
|
||||
r.logf("router: failed to set up bypass rtable: %v", err)
|
||||
}
|
||||
r.areDefaultRoute = true
|
||||
} else if !areDefault && r.areDefaultRoute {
|
||||
netns.CleanupBypassRtable(r.logf)
|
||||
r.areDefaultRoute = false
|
||||
}
|
||||
|
||||
return errq
|
||||
}
|
||||
|
||||
func (r *openbsdRouter) Close() error {
|
||||
if r.areDefaultRoute {
|
||||
netns.CleanupBypassRtable(r.logf)
|
||||
r.areDefaultRoute = false
|
||||
}
|
||||
cleanUp(r.logf, r.tunname)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user