policy/v2: use approved node routes in wildcard SrcIPs

Per Tailscale documentation, the wildcard (*) source includes "any
approved subnets" — the actually-advertised-and-approved routes from
nodes, not the autoApprover policy prefixes.

Change Asterix.resolve() to return just the base CGNAT+ULA set, and
add approved subnet routes as separate SrcIPs entries in the filter
compilation path. This preserves individual route prefixes that would
otherwise be merged by IPSet (e.g., 10.0.0.0/8 absorbing 10.33.0.0/16).

Also swap rule ordering in compileGrantWithAutogroupSelf() to emit
non-self destination rules before autogroup:self rules, matching the
Tailscale FilterRule wire format ordering.

Remove the unused AutoApproverPolicy.prefixes() method.

Updates #2180
This commit is contained in:
Kristoffer Dalby 2026-03-18 13:40:36 +00:00
parent 995ed0187c
commit e05f45cfb1
4 changed files with 103 additions and 61 deletions

View file

@ -89,7 +89,11 @@ func setupACLCompatNodes(users types.Users) types.Nodes {
{
ID: 7, GivenName: "subnet-router",
IPv4: ptrAddr("100.92.142.61"), IPv6: ptrAddr("fd7a:115c:a1e0::3e37:8e3d"),
Tags: []string{"tag:router"}, Hostinfo: &tailcfg.Hostinfo{},
Tags: []string{"tag:router"},
Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.33.0.0/16")},
},
ApprovedRoutes: []netip.Prefix{netip.MustParsePrefix("10.33.0.0/16")},
},
{
ID: 8, GivenName: "exit-node",
@ -146,11 +150,13 @@ type aclTestFile struct {
} `json:"input"`
Topology struct {
Nodes map[string]struct {
Hostname string `json:"hostname"`
Tags []string `json:"tags"`
IPv4 string `json:"ipv4"`
IPv6 string `json:"ipv6"`
User string `json:"user"`
Hostname string `json:"hostname"`
Tags []string `json:"tags"`
IPv4 string `json:"ipv4"`
IPv6 string `json:"ipv6"`
User string `json:"user"`
RoutableIPs []string `json:"routable_ips"`
ApprovedRoutes []string `json:"approved_routes"`
} `json:"nodes"`
} `json:"topology"`
Captures map[string]struct {