diff --git a/hscontrol/policy/v2/tailscale_grants_compat_test.go b/hscontrol/policy/v2/tailscale_grants_compat_test.go index 6930f660..7bd4e7d9 100644 --- a/hscontrol/policy/v2/tailscale_grants_compat_test.go +++ b/hscontrol/policy/v2/tailscale_grants_compat_test.go @@ -239,23 +239,16 @@ var grantSkipReasons = map[string]string{ // ======================================================================== // K-series: Various IP grant patterns - "GRANT-K1": "SRCIPS_FORMAT", - "GRANT-K2": "SRCIPS_FORMAT", - "GRANT-K4": "SRCIPS_FORMAT", "GRANT-K14": "SRCIPS_FORMAT", "GRANT-K15": "SRCIPS_FORMAT", - "GRANT-K16": "SRCIPS_FORMAT", - "GRANT-K17": "SRCIPS_FORMAT", "GRANT-K20": "SRCIPS_FORMAT", "GRANT-K21": "SRCIPS_FORMAT", - "GRANT-K22": "SRCIPS_FORMAT", - "GRANT-K26": "SRCIPS_FORMAT", // P01-series: Wildcard and basic IP grants - "GRANT-P01_1": "SRCIPS_FORMAT", - "GRANT-P01_2": "SRCIPS_FORMAT", - "GRANT-P01_3": "SRCIPS_FORMAT", - "GRANT-P01_4": "SRCIPS_FORMAT", + // "GRANT-P01_1": "SRCIPS_FORMAT", + // "GRANT-P01_2": "SRCIPS_FORMAT", + // "GRANT-P01_3": "SRCIPS_FORMAT", + // "GRANT-P01_4": "SRCIPS_FORMAT", // P05-series: Tag-to-tag grants "GRANT-P05_1": "SRCIPS_FORMAT", diff --git a/hscontrol/policy/v2/types.go b/hscontrol/policy/v2/types.go index 9375785f..cb20389f 100644 --- a/hscontrol/policy/v2/types.go +++ b/hscontrol/policy/v2/types.go @@ -135,6 +135,7 @@ func newResolved(ipb *netipx.IPSetBuilder) (resolved, error) { if err != nil { return resolved{}, err } + return resolved{ips: *ips}, nil } @@ -142,9 +143,11 @@ func newResolvedAddresses(ips *netipx.IPSet, err error) (ResolvedAddresses, erro if err != nil { return nil, err } + if ips == nil { return nil, nil } + return resolved{ips: *ips}, nil } @@ -301,6 +304,7 @@ func (a Asterix) resolve(p *Policy, _ types.Users, _ views.Slice[types.NodeView] if pfxs := p.AutoApprovers.prefixes(); len(pfxs) > 0 { var ipb netipx.IPSetBuilder ipb.AddSet(asterixResolved()) + for _, pfx := range p.AutoApprovers.prefixes() { ipb.AddPrefix(pfx) } @@ -1518,6 +1522,7 @@ func (ap AutoApproverPolicy) prefixes() []netip.Prefix { if tsaddr.IsExitRoute(prefix) { continue } + prefixes = append(prefixes, prefix) } @@ -1722,9 +1727,8 @@ func (p *Protocol) Description() string { func (p *Protocol) toIANAProtocolNumbers() []int { switch *p { case "": - // Empty protocol applies to TCP, UDP, ICMP, and ICMPv6 traffic - // This matches Tailscale's behavior for protocol defaults - return []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP} + // Empty means the same as wildcard-ish, the client will add the default protocols (TCP, UDP, ICMP) if empty. + return nil case ProtocolNameWildcard: // Wildcard protocol - defensive handling (should not reach here due to validation) return nil diff --git a/hscontrol/types/node.go b/hscontrol/types/node.go index 91feb7d4..d16e0dd5 100644 --- a/hscontrol/types/node.go +++ b/hscontrol/types/node.go @@ -300,9 +300,22 @@ func (node *Node) InIPSet(set *netipx.IPSet) bool { // AppendToIPSet adds the individual ips in NodeAddresses to a // given netipx.IPSetBuilder. func (node *Node) AppendToIPSet(build *netipx.IPSetBuilder) { - for _, ip := range node.IPs() { - build.Add(ip) + if node.IPv4 != nil { + build.Add(*node.IPv4) + return } + + if node.IPv6 != nil { + build.Add(*node.IPv6) + } + + // TODO(kradalby): Evaluate what we want to do here: + // Tailscale only adds the IPv4 addresses to any packet filter rule that is resolved to a given node. + // Presumably, it will add the IPv4 if a node does not have an IPv4. + // Until this change, we always added both, and that might be something people are dependent on, and we might want to keep it. + // for _, ip := range node.IPs() { + // build.Add(ip) + // } } func (node *Node) CanAccess(matchers []matcher.Match, node2 *Node) bool {