policy/v2: add via exit steering golden captures and tests
Add golden test data for via exit route steering and fix via exit grant compilation to match Tailscale SaaS behavior. Includes MapResponse golden tests for via grant route steering verification. Updates #2180
This commit is contained in:
parent
bca6e6334d
commit
6a55f7d731
19 changed files with 241115 additions and 89 deletions
|
|
@ -772,9 +772,12 @@ func TestGrantViaSubnetFilterRules(t *testing.T) {
|
|||
"without per-node filter compilation for via grants, these rules are missing")
|
||||
}
|
||||
|
||||
// TestGrantViaExitNodeFilterRules verifies that exit nodes with via grants
|
||||
// receive PacketFilter rules for exit traffic (0.0.0.0/0, ::/0).
|
||||
func TestGrantViaExitNodeFilterRules(t *testing.T) {
|
||||
// TestGrantViaExitNodeNoFilterRules verifies that exit nodes with via grants
|
||||
// for autogroup:internet do NOT receive PacketFilter rules for exit traffic.
|
||||
// Tailscale SaaS handles exit traffic forwarding through the client's exit
|
||||
// node selection mechanism, not through PacketFilter rules. Verified by
|
||||
// golden captures GRANT-V14 through GRANT-V36.
|
||||
func TestGrantViaExitNodeNoFilterRules(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
srv := servertest.NewServer(t)
|
||||
|
|
@ -842,51 +845,25 @@ func TestGrantViaExitNodeFilterRules(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
srv.App.Change(routeChange)
|
||||
|
||||
// Wait for clientA to see the exit routes in AllowedIPs.
|
||||
clientA.WaitForCondition(t, "clientA sees exit routes via exit-a",
|
||||
// Wait for routes to propagate.
|
||||
exitA.WaitForCondition(t, "exit-a routes approved",
|
||||
15*time.Second,
|
||||
func(nm *netmap.NetworkMap) bool {
|
||||
for _, p := range nm.Peers {
|
||||
hi := p.Hostinfo()
|
||||
if hi.Valid() && hi.Hostname() == "exit-a" {
|
||||
for i := range p.AllowedIPs().Len() {
|
||||
if p.AllowedIPs().At(i) == exitRouteV4 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return nm != nil
|
||||
})
|
||||
|
||||
// Critical: exit node's PacketFilter must contain rules for
|
||||
// exit traffic (0.0.0.0/0 or ::/0) from the via grant.
|
||||
// The exit node's PacketFilter must NOT contain rules for exit traffic.
|
||||
// The only rules should be from the peer connectivity grant (tag:exit-a
|
||||
// and tag:group-a can talk to each other at their Tailscale IPs).
|
||||
exitNM := exitA.Netmap()
|
||||
require.NotNil(t, exitNM)
|
||||
require.NotNil(t, exitNM.PacketFilter,
|
||||
"exit node PacketFilter should not be nil")
|
||||
|
||||
var foundExitDst bool
|
||||
|
||||
for _, m := range exitNM.PacketFilter {
|
||||
for _, dst := range m.Dsts {
|
||||
dstPrefix := netip.PrefixFrom(dst.Net.Addr(), dst.Net.Bits())
|
||||
if dstPrefix == exitRouteV4 || dstPrefix == exitRouteV6 {
|
||||
foundExitDst = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert.True(t, foundExitDst,
|
||||
"exit node PacketFilter should contain destination rules for exit routes (0.0.0.0/0 or ::/0); "+
|
||||
"via grant filter rules for exit traffic are missing")
|
||||
|
||||
// Log the actual PacketFilter for debugging.
|
||||
if !foundExitDst {
|
||||
for i, m := range exitNM.PacketFilter {
|
||||
t.Logf("PacketFilter[%d]: Srcs=%v, Dsts=%v, Caps=%d",
|
||||
i, m.Srcs, m.Dsts, len(m.Caps))
|
||||
assert.Falsef(t, dstPrefix == exitRouteV4 || dstPrefix == exitRouteV6,
|
||||
"exit node PacketFilter should NOT contain exit route destinations (0.0.0.0/0 or ::/0); "+
|
||||
"autogroup:internet via grants do not produce filter rules on exit nodes (verified against Tailscale SaaS)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue