ipn/ipnlocal: route extra WireGuard AllowedIPs through the route manager
The conn25 extension's ExtraWireGuardAllowedIPs hook (Transit IPs) was only appended to wgcfg.Config.Peers in authReconfig. Now that outbound peer selection comes from the route manager's outbound table via the engine's PeerByIPPacketFunc (which, when installed, replaces wireguard-go's AllowedIPs trie lookup entirely) and lazily created peers get their allowed IPs from the route manager via the engine's peer config func, those extras never reached either path: outbound packets to Transit IPs matched no peer, and lazily created peers didn't accept inbound Transit IP sources. Teach the route manager a per-peer set of extra allowed IPs, staged by Mutation.SetExtraAllowedIPs. They appear in the outbound table and in PeerAllowedIPs (so both outbound routing and per-peer allowed source prefixes see them) but are excluded from the OS route set, preserving the hook's contract that the extras reach WireGuard but not the OS routing table. authReconfig now feeds the hook's results into the route manager and incrementally syncs any changed peers to the WireGuard device; the append to cfg.Peers remains only so Reconfig's full per-peer device sync doesn't strip the extras from active peers, and goes away with Config.Peers. Updates #12542 Change-Id: I06c8fa30929fbf8fe171a2d34c47c6fcc3abfa16 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
aff605d163
commit
6a635c4e55
@@ -17,6 +17,7 @@ import (
|
||||
"tailscale.com/tstest"
|
||||
"tailscale.com/types/key"
|
||||
"tailscale.com/types/netmap"
|
||||
"tailscale.com/types/views"
|
||||
"tailscale.com/util/eventbus"
|
||||
"tailscale.com/util/mak"
|
||||
"tailscale.com/util/set"
|
||||
@@ -505,3 +506,56 @@ func TestNodeBackendDiscoChangedDelta(t *testing.T) {
|
||||
t.Errorf("upsert(after TSMP entry GC) discoChanged = %v; want %v", got, nk2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodeBackendRouteManagerExtras(t *testing.T) {
|
||||
nb := newNodeBackend(t.Context(), tstest.WhileTestRunningLogger(t), eventbus.New())
|
||||
|
||||
n := &tailcfg.Node{
|
||||
ID: 1,
|
||||
Key: key.NewNode().Public(),
|
||||
HomeDERP: 1,
|
||||
Addresses: []netip.Prefix{
|
||||
netip.MustParsePrefix("100.64.0.1/32"),
|
||||
},
|
||||
}
|
||||
n.AllowedIPs = n.Addresses
|
||||
p1 := n.View()
|
||||
nb.SetNetMap(&netmap.NetworkMap{Peers: []tailcfg.NodeView{p1}})
|
||||
|
||||
transit := netip.MustParsePrefix("fe80::1234/128")
|
||||
extrasFor := func(k key.NodePublic) views.Slice[netip.Prefix] {
|
||||
if k == p1.Key() {
|
||||
return views.SliceOf([]netip.Prefix{transit})
|
||||
}
|
||||
return views.Slice[netip.Prefix]{}
|
||||
}
|
||||
|
||||
// Installing extras reports the peer's allowed prefixes as
|
||||
// changed and adds the transit IP to the outbound table.
|
||||
changed := nb.updateRouteManagerExtras(extrasFor)
|
||||
if len(changed) != 1 || !slices.Contains(changed[p1.Key()], transit) {
|
||||
t.Errorf("updateRouteManagerExtras changed = %v; want %v including %v", changed, p1.Key(), transit)
|
||||
}
|
||||
if pr, ok := nb.routeMgr.Outbound().Lookup(transit.Addr()); !ok || pr.Key != p1.Key() {
|
||||
t.Errorf("Outbound lookup %v = %v, %v; want %v", transit.Addr(), pr, ok, p1.Key())
|
||||
}
|
||||
if nb.routeMgr.OSRoutes().Get(transit) {
|
||||
t.Errorf("OSRoutes contains %v; extras must not reach the OS route set", transit)
|
||||
}
|
||||
|
||||
// An unchanged hook result is a no-op.
|
||||
if changed := nb.updateRouteManagerExtras(extrasFor); changed != nil {
|
||||
t.Errorf("unchanged extras reported changes: %v", changed)
|
||||
}
|
||||
|
||||
// A hook that no longer returns extras removes them.
|
||||
changed = nb.updateRouteManagerExtras(func(key.NodePublic) views.Slice[netip.Prefix] {
|
||||
return views.Slice[netip.Prefix]{}
|
||||
})
|
||||
if len(changed) != 1 {
|
||||
t.Errorf("clearing extras changed = %v; want just %v", changed, p1.Key())
|
||||
}
|
||||
if _, ok := nb.routeMgr.Outbound().Lookup(transit.Addr()); ok {
|
||||
t.Errorf("Outbound still routes %v after extras cleared", transit.Addr())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user