policy/v2: write a single-address via destination bare

Via rules wrote every destination with its prefix bits; ACL and grant
rules already drop them for a single address. Both use one formatter.
This commit is contained in:
Kristoffer Dalby committed 2026-10-28 14:37:09 +00:00
1 parent 524ccc46aa
commit 6f30e2ddbe
3 files changed
+14 -15

No files matched your search

+1 -1
View File
@@ -1027,7 +1027,7 @@ func compileViaForNode(
destPorts = append(
destPorts,
tailcfg.NetPortRange{
IP: prefix.String(),
IP: filterIP(prefix),
Ports: port,
},
)
+13 -9
View File
@@ -173,16 +173,10 @@ func (pol *Policy) destinationsToNetPortRange(
for _, pref := range prefixes {
for _, port := range ports {
pr := tailcfg.NetPortRange{
IP: pref.String(),
ret = append(ret, tailcfg.NetPortRange{
IP: filterIP(pref),
Ports: port,
}
// Drop the prefix bits if its a single IP.
if pref.IsSingleIP() {
pr.IP = pref.Addr().String()
}
ret = append(ret, pr)
})
}
}
}
@@ -190,6 +184,16 @@ func (pol *Policy) destinationsToNetPortRange(
return ret
}
// filterIP writes pref as a filter destination: a single address bare,
// any other prefix with its bits, as Tailscale SaaS writes them.
func filterIP(pref netip.Prefix) string {
if pref.IsSingleIP() {
return pref.Addr().String()
}
return pref.String()
}
// compileFilterRulesForNode compiles filter rules for a specific node.
func (pol *Policy) compileFilterRulesForNode(
users types.Users,
@@ -172,9 +172,6 @@ var grantSkipReasons = map[string]string{
// Checks keyed <test_id>/<node>/filter: a listed check that matches
// fails, so a fix must delete its entry.
"via-grant-v63/blastoise/filter": viaDstAddressForm,
"via-grant-v63/squirtle/filter": viaDstAddressForm,
"grant-dxp-comma-ports/refused": grantPortList,
// Contiguous pinned addresses; TestViaGrantHACompat compares these
@@ -195,8 +192,6 @@ var grantSkipReasons = map[string]string{
const grantPortList = "GRANT_PORT_LIST: SaaS refuses a comma port list in a grant ip entry (only one port range allowed); headscale accepts it"
const viaDstAddressForm = "FILTER_ADDRESS_FORM: SaaS writes a single-address via destination as a bare address, headscale as a /32 prefix"
// TestGrantsCompat is a data-driven test that loads all GRANT-*.json
// test files captured from Tailscale SaaS and compares headscale's grants
// engine output against the real Tailscale behavior.