policy/v2: refactor alias resolution to use ResolvedAddresses

Introduce ResolvedAddresses type for structured IP set results. Refactor all Alias.Resolve() methods to return ResolvedAddresses instead of raw IPSets. Restrict identity-based aliases to matching address families, fix nil dereferences in partial resolution paths, and update test expectations for the new IP format (bare IPs, IP ranges instead of CIDR prefixes).

Updates #2180
This commit is contained in:
Kristoffer Dalby
2026-03-04 16:16:40 +01:00
committed by Kristoffer Dalby
parent 0fa9dcaff8
commit 9f7aa55689
9 changed files with 724 additions and 378 deletions

View File

@@ -9,7 +9,6 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/juanfont/headscale/hscontrol/policy"
"github.com/juanfont/headscale/hscontrol/policy/policyutil"
v2 "github.com/juanfont/headscale/hscontrol/policy/v2"
"github.com/juanfont/headscale/hscontrol/types"
"github.com/juanfont/headscale/hscontrol/util"
"github.com/rs/zerolog/log"
@@ -206,21 +205,14 @@ func TestReduceFilterRules(t *testing.T) {
},
},
want: []tailcfg.FilterRule{
// Merged: Both ACL rules combined (same SrcIPs and IPProto)
// Merged: Both ACL rules combined (same SrcIPs)
{
SrcIPs: []string{
"100.64.0.1/32",
"100.64.0.2/32",
"fd7a:115c:a1e0::1/128",
"fd7a:115c:a1e0::2/128",
"100.64.0.1-100.64.0.2",
},
DstPorts: []tailcfg.NetPortRange{
{
IP: "100.64.0.1/32",
Ports: tailcfg.PortRangeAny,
},
{
IP: "fd7a:115c:a1e0::1/128",
IP: "100.64.0.1",
Ports: tailcfg.PortRangeAny,
},
{
@@ -228,7 +220,6 @@ func TestReduceFilterRules(t *testing.T) {
Ports: tailcfg.PortRangeAny,
},
},
IPProto: []int{v2.ProtocolTCP, v2.ProtocolUDP, v2.ProtocolICMP, v2.ProtocolIPv6ICMP},
},
},
},
@@ -356,18 +347,13 @@ func TestReduceFilterRules(t *testing.T) {
// autogroup:internet does NOT generate packet filters - it's handled
// by exit node routing via AllowedIPs, not by packet filtering.
{
SrcIPs: []string{"100.64.0.1/32", "100.64.0.2/32", "fd7a:115c:a1e0::1/128", "fd7a:115c:a1e0::2/128"},
SrcIPs: []string{"100.64.0.1-100.64.0.2"},
DstPorts: []tailcfg.NetPortRange{
{
IP: "100.64.0.100/32",
Ports: tailcfg.PortRangeAny,
},
{
IP: "fd7a:115c:a1e0::100/128",
IP: "100.64.0.100",
Ports: tailcfg.PortRangeAny,
},
},
IPProto: []int{v2.ProtocolTCP, v2.ProtocolUDP, v2.ProtocolICMP, v2.ProtocolIPv6ICMP},
},
},
},
@@ -459,16 +445,12 @@ func TestReduceFilterRules(t *testing.T) {
},
},
want: []tailcfg.FilterRule{
// Merged: Both ACL rules combined (same SrcIPs and IPProto)
// Merged: Both ACL rules combined (same SrcIPs)
{
SrcIPs: []string{"100.64.0.1/32", "100.64.0.2/32", "fd7a:115c:a1e0::1/128", "fd7a:115c:a1e0::2/128"},
SrcIPs: []string{"100.64.0.1-100.64.0.2"},
DstPorts: []tailcfg.NetPortRange{
{
IP: "100.64.0.100/32",
Ports: tailcfg.PortRangeAny,
},
{
IP: "fd7a:115c:a1e0::100/128",
IP: "100.64.0.100",
Ports: tailcfg.PortRangeAny,
},
{IP: "0.0.0.0/5", Ports: tailcfg.PortRangeAny},
@@ -502,7 +484,6 @@ func TestReduceFilterRules(t *testing.T) {
{IP: "200.0.0.0/5", Ports: tailcfg.PortRangeAny},
{IP: "208.0.0.0/4", Ports: tailcfg.PortRangeAny},
},
IPProto: []int{v2.ProtocolTCP, v2.ProtocolUDP, v2.ProtocolICMP, v2.ProtocolIPv6ICMP},
},
},
},
@@ -566,16 +547,12 @@ func TestReduceFilterRules(t *testing.T) {
},
},
want: []tailcfg.FilterRule{
// Merged: Both ACL rules combined (same SrcIPs and IPProto)
// Merged: Both ACL rules combined (same SrcIPs)
{
SrcIPs: []string{"100.64.0.1/32", "100.64.0.2/32", "fd7a:115c:a1e0::1/128", "fd7a:115c:a1e0::2/128"},
SrcIPs: []string{"100.64.0.1-100.64.0.2"},
DstPorts: []tailcfg.NetPortRange{
{
IP: "100.64.0.100/32",
Ports: tailcfg.PortRangeAny,
},
{
IP: "fd7a:115c:a1e0::100/128",
IP: "100.64.0.100",
Ports: tailcfg.PortRangeAny,
},
{
@@ -587,7 +564,6 @@ func TestReduceFilterRules(t *testing.T) {
Ports: tailcfg.PortRangeAny,
},
},
IPProto: []int{v2.ProtocolTCP, v2.ProtocolUDP, v2.ProtocolICMP, v2.ProtocolIPv6ICMP},
},
},
},
@@ -651,16 +627,12 @@ func TestReduceFilterRules(t *testing.T) {
},
},
want: []tailcfg.FilterRule{
// Merged: Both ACL rules combined (same SrcIPs and IPProto)
// Merged: Both ACL rules combined (same SrcIPs)
{
SrcIPs: []string{"100.64.0.1/32", "100.64.0.2/32", "fd7a:115c:a1e0::1/128", "fd7a:115c:a1e0::2/128"},
SrcIPs: []string{"100.64.0.1-100.64.0.2"},
DstPorts: []tailcfg.NetPortRange{
{
IP: "100.64.0.100/32",
Ports: tailcfg.PortRangeAny,
},
{
IP: "fd7a:115c:a1e0::100/128",
IP: "100.64.0.100",
Ports: tailcfg.PortRangeAny,
},
{
@@ -672,7 +644,6 @@ func TestReduceFilterRules(t *testing.T) {
Ports: tailcfg.PortRangeAny,
},
},
IPProto: []int{v2.ProtocolTCP, v2.ProtocolUDP, v2.ProtocolICMP, v2.ProtocolIPv6ICMP},
},
},
},
@@ -725,22 +696,17 @@ func TestReduceFilterRules(t *testing.T) {
},
want: []tailcfg.FilterRule{
{
SrcIPs: []string{"100.64.0.1/32", "fd7a:115c:a1e0::1/128"},
SrcIPs: []string{"100.64.0.1"},
DstPorts: []tailcfg.NetPortRange{
{
IP: "100.64.0.100/32",
IP: "100.64.0.100",
Ports: tailcfg.PortRangeAny,
},
{
IP: "fd7a:115c:a1e0::100/128",
Ports: tailcfg.PortRangeAny,
},
{
IP: "172.16.0.21/32",
IP: "172.16.0.21",
Ports: tailcfg.PortRangeAny,
},
},
IPProto: []int{v2.ProtocolTCP, v2.ProtocolUDP, v2.ProtocolICMP, v2.ProtocolIPv6ICMP},
},
},
},