2026-01-23 20:58:38 +00:00
|
|
|
|
// This file is "generated" by Claude.
|
|
|
|
|
|
// It contains a large set of input ACL/Policy JSON configurations that
|
|
|
|
|
|
// the AI agent has systematically applied to a Tailnet on Tailscale SaaS
|
|
|
|
|
|
// and then observed the individual clients connected to the Tailnet
|
|
|
|
|
|
// with a given policy and recorded the resulting Packet filter rules sent
|
|
|
|
|
|
// to the clients.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
//
|
2026-01-23 20:58:38 +00:00
|
|
|
|
// There is likely a lot of duplicate or overlapping tests, however, the main
|
|
|
|
|
|
// exercise of this work was to create a comperehensive test set for comparing
|
|
|
|
|
|
// the behaviour of our policy engine and the upstream one.
|
|
|
|
|
|
//
|
|
|
|
|
|
// We aim to keep these tests to make sure we do not regress as we evolve
|
|
|
|
|
|
// and improve our policy implementation.
|
|
|
|
|
|
// This file is NOT intended for developer/humans to change and should be
|
|
|
|
|
|
// consider a "black box" test suite.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
package v2
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"net/netip"
|
|
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
|
|
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
|
|
|
|
|
"github.com/juanfont/headscale/hscontrol/policy/policyutil"
|
|
|
|
|
|
"github.com/juanfont/headscale/hscontrol/types"
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
"gorm.io/gorm"
|
|
|
|
|
|
"tailscale.com/tailcfg"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// ptrAddr is a helper to create a pointer to a netip.Addr.
|
|
|
|
|
|
func ptrAddr(s string) *netip.Addr {
|
|
|
|
|
|
addr := netip.MustParseAddr(s)
|
|
|
|
|
|
return &addr
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// setupTailscaleCompatUsers returns the test users for compatibility tests.
|
|
|
|
|
|
func setupTailscaleCompatUsers() types.Users {
|
|
|
|
|
|
return types.Users{
|
|
|
|
|
|
{Model: gorm.Model{ID: 1}, Name: "kratail2tid"},
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// setupTailscaleCompatNodes returns the test nodes for compatibility tests.
|
|
|
|
|
|
// The node configuration matches the Tailscale test environment:
|
|
|
|
|
|
// - 1 user-owned node (user1)
|
|
|
|
|
|
// - 4 tagged nodes (tagged-server, tagged-client, tagged-db, tagged-web).
|
|
|
|
|
|
func setupTailscaleCompatNodes(users types.Users) types.Nodes {
|
|
|
|
|
|
// Node: user1 - User-owned by kratail2tid
|
|
|
|
|
|
nodeUser1 := &types.Node{
|
|
|
|
|
|
ID: 1,
|
|
|
|
|
|
GivenName: "user1",
|
|
|
|
|
|
User: &users[0],
|
|
|
|
|
|
UserID: &users[0].ID,
|
|
|
|
|
|
IPv4: ptrAddr("100.90.199.68"),
|
|
|
|
|
|
IPv6: ptrAddr("fd7a:115c:a1e0::2d01:c747"),
|
|
|
|
|
|
Hostinfo: &tailcfg.Hostinfo{},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Node: tagged-server - Has tag:server
|
|
|
|
|
|
nodeTaggedServer := &types.Node{
|
|
|
|
|
|
ID: 2,
|
|
|
|
|
|
GivenName: "tagged-server",
|
|
|
|
|
|
IPv4: ptrAddr("100.108.74.26"),
|
|
|
|
|
|
IPv6: ptrAddr("fd7a:115c:a1e0::b901:4a87"),
|
|
|
|
|
|
Tags: []string{"tag:server"},
|
|
|
|
|
|
Hostinfo: &tailcfg.Hostinfo{},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Node: tagged-client - Has tag:client
|
|
|
|
|
|
nodeTaggedClient := &types.Node{
|
|
|
|
|
|
ID: 3,
|
|
|
|
|
|
GivenName: "tagged-client",
|
|
|
|
|
|
IPv4: ptrAddr("100.80.238.75"),
|
|
|
|
|
|
IPv6: ptrAddr("fd7a:115c:a1e0::7901:ee86"),
|
|
|
|
|
|
Tags: []string{"tag:client"},
|
|
|
|
|
|
Hostinfo: &tailcfg.Hostinfo{},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Node: tagged-db - Has tag:database
|
|
|
|
|
|
nodeTaggedDB := &types.Node{
|
|
|
|
|
|
ID: 4,
|
|
|
|
|
|
GivenName: "tagged-db",
|
|
|
|
|
|
IPv4: ptrAddr("100.74.60.128"),
|
|
|
|
|
|
IPv6: ptrAddr("fd7a:115c:a1e0::2f01:3c9c"),
|
|
|
|
|
|
Tags: []string{"tag:database"},
|
|
|
|
|
|
Hostinfo: &tailcfg.Hostinfo{},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Node: tagged-web - Has tag:web
|
|
|
|
|
|
nodeTaggedWeb := &types.Node{
|
|
|
|
|
|
ID: 5,
|
|
|
|
|
|
GivenName: "tagged-web",
|
|
|
|
|
|
IPv4: ptrAddr("100.94.92.91"),
|
|
|
|
|
|
IPv6: ptrAddr("fd7a:115c:a1e0::ef01:5c81"),
|
|
|
|
|
|
Tags: []string{"tag:web"},
|
|
|
|
|
|
Hostinfo: &tailcfg.Hostinfo{},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return types.Nodes{
|
|
|
|
|
|
nodeUser1,
|
|
|
|
|
|
nodeTaggedServer,
|
|
|
|
|
|
nodeTaggedClient,
|
|
|
|
|
|
nodeTaggedDB,
|
|
|
|
|
|
nodeTaggedWeb,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// findNodeByGivenName finds a node by its GivenName field.
|
|
|
|
|
|
func findNodeByGivenName(nodes types.Nodes, name string) *types.Node {
|
|
|
|
|
|
for _, n := range nodes {
|
|
|
|
|
|
if n.GivenName == name {
|
|
|
|
|
|
return n
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// tailscaleCompatTest defines a test case for Tailscale compatibility testing.
|
|
|
|
|
|
type tailscaleCompatTest struct {
|
|
|
|
|
|
name string // Test name
|
|
|
|
|
|
policy string // HuJSON policy as multiline raw string
|
|
|
|
|
|
wantFilters map[string][]tailcfg.FilterRule // node GivenName -> expected filters
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// basePolicyTemplate provides the standard groups, tagOwners, and hosts
|
|
|
|
|
|
// that are used in all Tailscale compatibility tests.
|
|
|
|
|
|
const basePolicyPrefix = `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [`
|
|
|
|
|
|
|
|
|
|
|
|
const basePolicySuffix = `
|
|
|
|
|
|
]
|
|
|
|
|
|
}`
|
|
|
|
|
|
|
|
|
|
|
|
// makePolicy creates a full policy from just the ACL rules portion.
|
|
|
|
|
|
func makePolicy(aclRules string) string {
|
|
|
|
|
|
return basePolicyPrefix + aclRules + basePolicySuffix
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// cmpOptions returns comparison options for FilterRule slices.
|
|
|
|
|
|
// It sorts SrcIPs and DstPorts to handle ordering differences.
|
|
|
|
|
|
func cmpOptions() []cmp.Option {
|
|
|
|
|
|
return []cmp.Option{
|
|
|
|
|
|
cmpopts.SortSlices(func(a, b string) bool { return a < b }),
|
|
|
|
|
|
cmpopts.SortSlices(func(a, b tailcfg.NetPortRange) bool {
|
|
|
|
|
|
if a.IP != b.IP {
|
|
|
|
|
|
return a.IP < b.IP
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if a.Ports.First != b.Ports.First {
|
|
|
|
|
|
return a.Ports.First < b.Ports.First
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return a.Ports.Last < b.Ports.Last
|
|
|
|
|
|
}),
|
|
|
|
|
|
cmpopts.SortSlices(func(a, b int) bool { return a < b }),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// Tailscale uses partitioned CGNAT CIDR ranges for wildcard source expansion
|
|
|
|
|
|
// (excluding the ChromeOS VM range 100.115.92.0/23). Headscale uses the simpler
|
|
|
|
|
|
// full CGNAT range (100.64.0.0/10) and Tailscale ULA range (fd7a:115c:a1e0::/48).
|
|
|
|
|
|
// This is functionally equivalent for access control purposes.
|
|
|
|
|
|
//
|
|
|
|
|
|
// For reference, Tailscale's partitioned ranges are:
|
2026-01-23 19:36:17 +00:00
|
|
|
|
// var tailscaleCGNATCIDRs = []string{
|
|
|
|
|
|
// "100.64.0.0/11",
|
|
|
|
|
|
// "100.96.0.0/12",
|
|
|
|
|
|
// "100.112.0.0/15",
|
|
|
|
|
|
// "100.114.0.0/16",
|
|
|
|
|
|
// "100.115.0.0/18",
|
|
|
|
|
|
// "100.115.64.0/20",
|
|
|
|
|
|
// "100.115.80.0/21",
|
|
|
|
|
|
// "100.115.88.0/22",
|
|
|
|
|
|
// "100.115.94.0/23",
|
|
|
|
|
|
// "100.115.96.0/19",
|
|
|
|
|
|
// "100.115.128.0/17",
|
|
|
|
|
|
// "100.116.0.0/14",
|
|
|
|
|
|
// "100.120.0.0/13",
|
|
|
|
|
|
// "fd7a:115c:a1e0::/48",
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// TestTailscaleCompatWildcardACLs tests wildcard ACL rules (* source and destination).
|
|
|
|
|
|
// These are the most fundamental tests for basic allow-all and IP-based rules.
|
|
|
|
|
|
func TestTailscaleCompatWildcardACLs(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
users := setupTailscaleCompatUsers()
|
|
|
|
|
|
nodes := setupTailscaleCompatNodes(users)
|
|
|
|
|
|
|
|
|
|
|
|
tests := []tailscaleCompatTest{
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "allow_all_wildcard",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["*:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// All nodes receive the same filter for allow-all rule.
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale expands `*` source to partitioned CGNAT CIDR ranges:
|
2026-01-23 19:36:17 +00:00
|
|
|
|
// 100.64.0.0/11, 100.96.0.0/12, 100.112.0.0/15, etc. plus fd7a:115c:a1e0::/48
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// Headscale uses the full 100.64.0.0/10 and fd7a:115c:a1e0::/48 ranges.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full range.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "single_ip_as_source",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["100.90.199.68"], "dst": ["*:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Single IP source: Headscale resolves the IP to a node and includes ALL of the
|
|
|
|
|
|
// node's IPs (both IPv4 and IPv6). Tailscale uses only the literal IP specified.
|
|
|
|
|
|
// TODO: Tailscale only includes the literal IP "100.90.199.68/32" without IPv6.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// TODO: Tailscale only includes the literal IP:
|
|
|
|
|
|
// SrcIPs: []string{"100.90.199.68/32"},
|
|
|
|
|
|
// Headscale: Resolves IP to node and includes ALL node IPs (IPv4+IPv6)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "cidr_as_source",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["100.64.0.0/16"], "dst": ["*:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// CIDR source is passed through unchanged to the filter.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{"100.64.0.0/16"},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{"100.64.0.0/16"},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{"100.64.0.0/16"},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{"100.64.0.0/16"},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{"100.64.0.0/16"},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "single_ip_as_destination",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["100.108.74.26:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Single IP destination: ONLY that node receives the filter.
|
|
|
|
|
|
// KEY INSIGHT: Destination filters are only sent to nodes that ARE the destination.
|
|
|
|
|
|
// NOTE: This IP (100.108.74.26) is tagged-server.
|
|
|
|
|
|
// NOTE: Headscale resolves the IP to a node and includes ALL of the node's IPs.
|
|
|
|
|
|
// TODO: Tailscale only includes the literal destination IP without IPv6.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10
|
2026-01-23 19:36:17 +00:00
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// TODO: Tailscale only includes the literal destination IP:
|
|
|
|
|
|
// DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// {IP: "100.108.74.26/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
// },
|
|
|
|
|
|
// Headscale: Resolves IP to node and includes ALL node IPs (IPv4+IPv6)
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "cidr_as_destination",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["100.64.0.0/12:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// CIDR destination: only nodes with IPs in the CIDR range receive the filter.
|
|
|
|
|
|
// 100.64.0.0/12 covers 100.64.0.0 - 100.79.255.255
|
|
|
|
|
|
// Of our test nodes, only tagged-db (100.74.60.128) falls in this range.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil, // 100.90.199.68 is NOT in 100.64.0.0/12
|
|
|
|
|
|
"tagged-server": nil, // 100.108.74.26 is NOT in 100.64.0.0/12
|
|
|
|
|
|
"tagged-client": nil, // 100.80.238.75 is NOT in 100.64.0.0/12
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10
|
2026-01-23 19:36:17 +00:00
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.64.0.0/12", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": nil, // 100.94.92.91 is NOT in 100.64.0.0/12
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
pol, err := unmarshalPolicy([]byte(tt.policy))
|
|
|
|
|
|
require.NoError(t, err, "failed to parse policy")
|
|
|
|
|
|
|
|
|
|
|
|
err = pol.validate()
|
|
|
|
|
|
require.NoError(t, err, "policy validation failed")
|
|
|
|
|
|
|
|
|
|
|
|
for nodeName, wantFilters := range tt.wantFilters {
|
|
|
|
|
|
node := findNodeByGivenName(nodes, nodeName)
|
|
|
|
|
|
require.NotNil(t, node, "node %s not found", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice())
|
|
|
|
|
|
require.NoError(t, err, "failed to compile filters for node %s", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters)
|
|
|
|
|
|
|
|
|
|
|
|
if len(wantFilters) == 0 && len(gotFilters) == 0 {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" {
|
|
|
|
|
|
t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TestTailscaleCompatBasicTags tests basic tag-to-tag ACL rules.
|
|
|
|
|
|
// These tests verify that tags are correctly expanded to node IPs
|
|
|
|
|
|
// and that filters are distributed to the correct destination nodes.
|
|
|
|
|
|
func TestTailscaleCompatBasicTags(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
users := setupTailscaleCompatUsers()
|
|
|
|
|
|
nodes := setupTailscaleCompatNodes(users)
|
|
|
|
|
|
|
|
|
|
|
|
tests := []tailscaleCompatTest{
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tag_client_to_tag_server_port_22",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tag_as_source_wildcard_dest",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["*:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// When dst is *, all nodes should receive the filter
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "multiple_source_tags",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client", "tag:web"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tag_as_destination_only",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// When using wildcard source and tag destination, ONLY the tagged node receives the filter.
|
|
|
|
|
|
// This is different from tag_as_source_wildcard_dest where all nodes receive the filter.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10
|
2026-01-23 19:36:17 +00:00
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "multiple_destination_tags",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:5432", "tag:web:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Multiple destination tags in a single rule.
|
|
|
|
|
|
// Each tagged node receives ONLY its own destination portion.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "all_tagged_nodes_as_source_to_specific_destination",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:tagged"], "dst": ["tag:database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// All tagged nodes as source (including the destination node itself).
|
|
|
|
|
|
// Only the destination node receives the filter.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
pol, err := unmarshalPolicy([]byte(tt.policy))
|
|
|
|
|
|
require.NoError(t, err, "failed to parse policy")
|
|
|
|
|
|
|
|
|
|
|
|
err = pol.validate()
|
|
|
|
|
|
require.NoError(t, err, "policy validation failed")
|
|
|
|
|
|
|
|
|
|
|
|
for nodeName, wantFilters := range tt.wantFilters {
|
|
|
|
|
|
node := findNodeByGivenName(nodes, nodeName)
|
|
|
|
|
|
require.NotNil(t, node, "node %s not found", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Get compiled filters for this specific node
|
|
|
|
|
|
compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice())
|
|
|
|
|
|
require.NoError(t, err, "failed to compile filters for node %s", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Reduce to only rules where this node is a destination
|
|
|
|
|
|
gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters)
|
|
|
|
|
|
|
|
|
|
|
|
// Handle nil vs empty slice comparison
|
|
|
|
|
|
if len(wantFilters) == 0 && len(gotFilters) == 0 {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" {
|
|
|
|
|
|
t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TestTailscaleCompatUsersGroups tests user and group ACL rules.
|
|
|
|
|
|
func TestTailscaleCompatUsersGroups(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
users := setupTailscaleCompatUsers()
|
|
|
|
|
|
nodes := setupTailscaleCompatNodes(users)
|
|
|
|
|
|
|
|
|
|
|
|
tests := []tailscaleCompatTest{
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "user_as_source",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["kratail2tid@"], "dst": ["*:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// User as source expands to IPs of nodes owned by that user
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "user_as_destination",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["kratail2tid@:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// User as destination - only user-owned nodes receive the filter
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "group_as_source",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["*:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Group as source expands to IPs of nodes owned by group members
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "group_as_destination",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["group:admins:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Group as destination - only nodes owned by group members receive the filter
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "multiple_destinations_different_ports",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Each destination node receives ONLY its own destination portion
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
pol, err := unmarshalPolicy([]byte(tt.policy))
|
|
|
|
|
|
require.NoError(t, err, "failed to parse policy")
|
|
|
|
|
|
|
|
|
|
|
|
err = pol.validate()
|
|
|
|
|
|
require.NoError(t, err, "policy validation failed")
|
|
|
|
|
|
|
|
|
|
|
|
for nodeName, wantFilters := range tt.wantFilters {
|
|
|
|
|
|
node := findNodeByGivenName(nodes, nodeName)
|
|
|
|
|
|
require.NotNil(t, node, "node %s not found", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Get compiled filters for this specific node
|
|
|
|
|
|
compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice())
|
|
|
|
|
|
require.NoError(t, err, "failed to compile filters for node %s", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Reduce to only rules where this node is a destination
|
|
|
|
|
|
gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters)
|
|
|
|
|
|
|
|
|
|
|
|
if len(wantFilters) == 0 && len(gotFilters) == 0 {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" {
|
|
|
|
|
|
t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TestTailscaleCompatAutogroups tests autogroup ACL rules.
|
|
|
|
|
|
func TestTailscaleCompatAutogroups(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
users := setupTailscaleCompatUsers()
|
|
|
|
|
|
nodes := setupTailscaleCompatNodes(users)
|
|
|
|
|
|
|
|
|
|
|
|
tests := []tailscaleCompatTest{
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_member_as_source",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["*:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// autogroup:member expands to IPs of user-owned nodes only
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_tagged_as_source",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:tagged"], "dst": ["*:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// autogroup:tagged expands to IPs of all tagged nodes
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_member_plus_tag_client",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Sources are merged into one Srcs array
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_self_as_destination",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// autogroup:self allows a node to access ITSELF.
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// The source wildcard `*` is narrowed to the node's own IP for autogroup:self.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
// KEY INSIGHT: Tagged nodes do NOT receive autogroup:self filters.
|
|
|
|
|
|
// Only user-owned nodes can use autogroup:self.
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: For autogroup:self destinations, both Tailscale and Headscale narrow
|
|
|
|
|
|
// the wildcard source to only the same-user untagged nodes.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// Source is narrowed to the node's own IPs for autogroup:self.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// Tailscale uses CIDR format: "100.90.199.68/32" and "fd7a:115c:a1e0::2d01:c747/128"
|
2026-01-23 19:36:17 +00:00
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil, // Tagged nodes do NOT receive autogroup:self filters
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_internet_as_destination",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:internet:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// autogroup:internet produces NO PacketFilter entries.
|
|
|
|
|
|
// This autogroup relates to exit node routing, not direct node-to-node filters.
|
|
|
|
|
|
// It controls what traffic can be routed through exit nodes to the internet.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_member_as_destination",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:member:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// autogroup:member as destination - only user-owned nodes receive the filter.
|
|
|
|
|
|
// Tagged nodes do NOT receive this filter.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10
|
2026-01-23 19:36:17 +00:00
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_self_mixed_with_tag",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self:*", "tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// KEY FINDING: Mixed destinations create SEPARATE filter entries with different Srcs!
|
|
|
|
|
|
// - autogroup:self narrows Srcs to the user's own IPs
|
|
|
|
|
|
// - tag:server keeps Srcs as full wildcard
|
|
|
|
|
|
// user1 gets ONLY the self filter (narrowed Srcs to user1's IPs)
|
|
|
|
|
|
// tagged-server gets ONLY the tag filter (full wildcard Srcs)
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// autogroup:self narrows Srcs to user's own IPs
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// tag:server keeps full wildcard Srcs
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10
|
2026-01-23 19:36:17 +00:00
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil, // Not in destination
|
|
|
|
|
|
"tagged-db": nil, // Not in destination
|
|
|
|
|
|
"tagged-web": nil, // Not in destination
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_tagged_as_destination",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:tagged:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// autogroup:tagged as destination - all tagged nodes receive the filter.
|
|
|
|
|
|
// User-owned nodes do NOT receive this filter.
|
|
|
|
|
|
// KEY INSIGHT: ReduceFilterRules filters DstPorts to only the current node's IPs.
|
|
|
|
|
|
// So each tagged node only sees its OWN IPs in DstPorts after reduction.
|
|
|
|
|
|
// TODO: Tailscale includes ALL tagged nodes' IPs in DstPorts for each node.
|
|
|
|
|
|
// Headscale only includes the current node's IPs after ReduceFilterRules.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10
|
2026-01-23 19:36:17 +00:00
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// TODO: Tailscale includes ALL tagged nodes' IPs:
|
|
|
|
|
|
// DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// {IP: "100.108.74.26/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
// {IP: "100.74.60.128/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
// {IP: "100.80.238.75/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
// {IP: "100.94.92.91/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
// {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
// {IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
// {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
// {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
// },
|
|
|
|
|
|
// Headscale: After ReduceFilterRules, only this node's IPs are in DstPorts
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// TODO: Tailscale includes ALL tagged nodes' IPs (see tagged-server comment)
|
|
|
|
|
|
// Headscale: Only this node's IPs after ReduceFilterRules
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.80.238.75/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// TODO: Tailscale includes ALL tagged nodes' IPs (see tagged-server comment)
|
|
|
|
|
|
// Headscale: Only this node's IPs after ReduceFilterRules
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// TODO: Tailscale includes ALL tagged nodes' IPs (see tagged-server comment)
|
|
|
|
|
|
// Headscale: Only this node's IPs after ReduceFilterRules
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
pol, err := unmarshalPolicy([]byte(tt.policy))
|
|
|
|
|
|
require.NoError(t, err, "failed to parse policy")
|
|
|
|
|
|
|
|
|
|
|
|
err = pol.validate()
|
|
|
|
|
|
require.NoError(t, err, "policy validation failed")
|
|
|
|
|
|
|
|
|
|
|
|
for nodeName, wantFilters := range tt.wantFilters {
|
|
|
|
|
|
node := findNodeByGivenName(nodes, nodeName)
|
|
|
|
|
|
require.NotNil(t, node, "node %s not found", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Get compiled filters for this specific node
|
|
|
|
|
|
compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice())
|
|
|
|
|
|
require.NoError(t, err, "failed to compile filters for node %s", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Reduce to only rules where this node is a destination
|
|
|
|
|
|
gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters)
|
|
|
|
|
|
|
|
|
|
|
|
if len(wantFilters) == 0 && len(gotFilters) == 0 {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" {
|
|
|
|
|
|
t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TestTailscaleCompatHosts tests host alias ACL rules.
|
|
|
|
|
|
func TestTailscaleCompatHosts(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
users := setupTailscaleCompatUsers()
|
|
|
|
|
|
nodes := setupTailscaleCompatNodes(users)
|
|
|
|
|
|
|
|
|
|
|
|
tests := []tailscaleCompatTest{
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "host_as_destination",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["webserver:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Host reference webserver = 100.108.74.26 = tagged-server
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10
|
2026-01-23 19:36:17 +00:00
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// TODO: Tailscale only includes the literal IPv4 for host aliases:
|
|
|
|
|
|
// DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
// },
|
|
|
|
|
|
// Headscale: Resolves host alias to node and includes ALL node IPs (IPv4+IPv6)
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "host_as_source",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["webserver"], "dst": ["*:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Host as source resolves to the defined IP
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// TODO: Tailscale only includes the literal IPv4 for host aliases:
|
|
|
|
|
|
// SrcIPs: []string{"100.108.74.26/32"},
|
|
|
|
|
|
// Headscale: Resolves host alias to node and includes ALL node IPs (IPv4+IPv6)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// TODO: Tailscale only includes the literal IPv4 for host aliases (see user1 comment)
|
|
|
|
|
|
// Headscale: Resolves host alias to node and includes ALL node IPs (IPv4+IPv6)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// TODO: Tailscale only includes the literal IPv4 for host aliases (see user1 comment)
|
|
|
|
|
|
// Headscale: Resolves host alias to node and includes ALL node IPs (IPv4+IPv6)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// TODO: Tailscale only includes the literal IPv4 for host aliases (see user1 comment)
|
|
|
|
|
|
// Headscale: Resolves host alias to node and includes ALL node IPs (IPv4+IPv6)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// TODO: Tailscale only includes the literal IPv4 for host aliases (see user1 comment)
|
|
|
|
|
|
// Headscale: Resolves host alias to node and includes ALL node IPs (IPv4+IPv6)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "cidr_host_as_source",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["internal"], "dst": ["*:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// CIDR host definition (10.0.0.0/8) is passed through unchanged
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{"10.0.0.0/8"},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{"10.0.0.0/8"},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{"10.0.0.0/8"},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{"10.0.0.0/8"},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{"10.0.0.0/8"},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
pol, err := unmarshalPolicy([]byte(tt.policy))
|
|
|
|
|
|
require.NoError(t, err, "failed to parse policy")
|
|
|
|
|
|
|
|
|
|
|
|
err = pol.validate()
|
|
|
|
|
|
require.NoError(t, err, "policy validation failed")
|
|
|
|
|
|
|
|
|
|
|
|
for nodeName, wantFilters := range tt.wantFilters {
|
|
|
|
|
|
node := findNodeByGivenName(nodes, nodeName)
|
|
|
|
|
|
require.NotNil(t, node, "node %s not found", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Get compiled filters for this specific node
|
|
|
|
|
|
compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice())
|
|
|
|
|
|
require.NoError(t, err, "failed to compile filters for node %s", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Reduce to only rules where this node is a destination
|
|
|
|
|
|
gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters)
|
|
|
|
|
|
|
|
|
|
|
|
if len(wantFilters) == 0 && len(gotFilters) == 0 {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" {
|
|
|
|
|
|
t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TestTailscaleCompatProtocolsPorts tests protocol and port ACL rules.
|
|
|
|
|
|
func TestTailscaleCompatProtocolsPorts(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
users := setupTailscaleCompatUsers()
|
|
|
|
|
|
nodes := setupTailscaleCompatNodes(users)
|
|
|
|
|
|
|
|
|
|
|
|
tests := []tailscaleCompatTest{
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tcp_only_protocol",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "proto": "tcp", "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "udp_only_protocol",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "proto": "udp", "dst": ["tag:server:53"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 53, Last: 53}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 53, Last: 53}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolUDP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "icmp_numeric_protocol",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "proto": "1", "dst": ["tag:server:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Numeric protocol values work (e.g., "1" for ICMP)
|
|
|
|
|
|
// Even for ICMP (which doesn't use ports), the ports field is 0-65535
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10
|
2026-01-23 19:36:17 +00:00
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "port_range",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["tag:server:80-443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "multiple_comma_separated_ports",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["tag:server:22,80,443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Comma-separated ports expand into separate DstPorts entries
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_port",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["tag:server:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRangeAny},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
pol, err := unmarshalPolicy([]byte(tt.policy))
|
|
|
|
|
|
require.NoError(t, err, "failed to parse policy")
|
|
|
|
|
|
|
|
|
|
|
|
err = pol.validate()
|
|
|
|
|
|
require.NoError(t, err, "policy validation failed")
|
|
|
|
|
|
|
|
|
|
|
|
for nodeName, wantFilters := range tt.wantFilters {
|
|
|
|
|
|
node := findNodeByGivenName(nodes, nodeName)
|
|
|
|
|
|
require.NotNil(t, node, "node %s not found", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Get compiled filters for this specific node
|
|
|
|
|
|
compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice())
|
|
|
|
|
|
require.NoError(t, err, "failed to compile filters for node %s", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Reduce to only rules where this node is a destination
|
|
|
|
|
|
gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters)
|
|
|
|
|
|
|
|
|
|
|
|
if len(wantFilters) == 0 && len(gotFilters) == 0 {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" {
|
|
|
|
|
|
t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TestTailscaleCompatMixedSources tests mixing different source types in a single rule.
|
|
|
|
|
|
// From findings/09-mixed-scenarios.md - Category 1: Mixed Sources (Single Rule).
|
|
|
|
|
|
func TestTailscaleCompatMixedSources(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
users := setupTailscaleCompatUsers()
|
|
|
|
|
|
nodes := setupTailscaleCompatNodes(users)
|
|
|
|
|
|
|
|
|
|
|
|
tests := []tailscaleCompatTest{
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_tagged_plus_autogroup_member_full_tailnet",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:tagged", "autogroup:member"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Full tailnet coverage: autogroup:tagged (all 4 tagged) + autogroup:member (user1)
|
|
|
|
|
|
// All 5 nodes' IPv4 and IPv6 addresses should be in Srcs (10 total entries)
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "group_plus_tag",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// group:admins → user1's IPs + tag:client → tagged-client's IPs
|
|
|
|
|
|
// Both merged into single Srcs array (4 IPs total)
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "explicit_user_plus_tag",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["kratail2tid@", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Explicit user kratail2tid@ → user1's IPs + tag:client → tagged-client's IPs
|
|
|
|
|
|
// Both merged into single Srcs array (4 IPs total)
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "cidr_plus_tag",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["10.0.0.0/8", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// CIDR 10.0.0.0/8 + tag:client IPs merged into single Srcs array
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"10.0.0.0/8",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "host_plus_tag",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["internal", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Host alias "internal" (10.0.0.0/8) + tag:client IPs merged into single Srcs array
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"10.0.0.0/8",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "webserver_host_plus_tag",
|
|
|
|
|
|
// Test 1.5: webserver (host) + tag:client
|
|
|
|
|
|
// Host aliases are IPv4 only; tags include IPv6.
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["webserver", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// TODO: Tailscale: webserver host = 100.108.74.26/32 (IPv4 only)
|
|
|
|
|
|
// Tailscale Srcs: ["100.108.74.26/32", "100.80.238.75/32", "fd7a:115c:a1e0::7901:ee86/128"]
|
|
|
|
|
|
// Headscale: Host resolves to node and includes ALL node IPs
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "raw_ip_plus_tag",
|
|
|
|
|
|
// Test 1.6: 100.90.199.68 (raw IP) + tag:client
|
|
|
|
|
|
// Raw IPs are treated as literal CIDRs
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["100.90.199.68", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Raw IP 100.90.199.68 resolves to user1 node - Headscale includes all node IPs
|
|
|
|
|
|
// tag:client expands to tagged-client's IPs
|
|
|
|
|
|
// TODO: Tailscale may treat raw IP as literal /32 only without IPv6
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128", // user1 IPv6 added by Headscale
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_user_three_ways",
|
|
|
|
|
|
// Test 1.7: autogroup:member + group:admins + kratail2tid@ (same user 3 ways)
|
|
|
|
|
|
// All three resolve to user1, should deduplicate to just user1's IPs
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "group:admins", "kratail2tid@"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// All three sources resolve to user1 - should be deduplicated
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_ip_two_ways_as_source",
|
|
|
|
|
|
// Test 1.8: tag:server + webserver (same IP via tag and host)
|
|
|
|
|
|
// Both reference tagged-server's IP - should deduplicate
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:server", "webserver"], "dst": ["tag:database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// TODO: Tailscale: webserver host only adds IPv4
|
|
|
|
|
|
// Tailscale Srcs: ["100.108.74.26/32", "fd7a:115c:a1e0::b901:4a87/128"]
|
|
|
|
|
|
// Headscale: Both tag:server and webserver resolve to all node IPs
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
pol, err := unmarshalPolicy([]byte(tt.policy))
|
|
|
|
|
|
require.NoError(t, err, "failed to parse policy")
|
|
|
|
|
|
|
|
|
|
|
|
err = pol.validate()
|
|
|
|
|
|
require.NoError(t, err, "policy validation failed")
|
|
|
|
|
|
|
|
|
|
|
|
for nodeName, wantFilters := range tt.wantFilters {
|
|
|
|
|
|
node := findNodeByGivenName(nodes, nodeName)
|
|
|
|
|
|
require.NotNil(t, node, "node %s not found", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Get compiled filters for this specific node
|
|
|
|
|
|
compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice())
|
|
|
|
|
|
require.NoError(t, err, "failed to compile filters for node %s", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Reduce to only rules where this node is a destination
|
|
|
|
|
|
gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters)
|
|
|
|
|
|
|
|
|
|
|
|
if len(wantFilters) == 0 && len(gotFilters) == 0 {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" {
|
|
|
|
|
|
t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TestTailscaleCompatComplexScenarios tests complex ACL rule combinations.
|
|
|
|
|
|
func TestTailscaleCompatComplexScenarios(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
users := setupTailscaleCompatUsers()
|
|
|
|
|
|
nodes := setupTailscaleCompatNodes(users)
|
|
|
|
|
|
|
|
|
|
|
|
tests := []tailscaleCompatTest{
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "empty_group_produces_no_filter",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["group:empty"], "dst": ["*:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Empty groups produce no filter entries
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "multiple_rules_same_source_merged",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80,443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// KEY INSIGHT: In Tailscale, multiple rules with the SAME source are MERGED into a
|
|
|
|
|
|
// single filter entry with all destination ports combined.
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Headscale now merges rules with identical SrcIPs and IPProto.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: Both ACL rules combined into single filter entry
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "different_sources_same_destination_separate",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:web"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:database"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// KEY INSIGHT: Different sources are NEVER merged - always separate filter entries.
|
|
|
|
|
|
// Each source gets its own filter entry even with identical destinations.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "mixed_overlapping_rules",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:web"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:web"], "dst": ["tag:server:443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// In Tailscale: 4 rules → 2 filter entries (merged per-source)
|
|
|
|
|
|
// - tag:client rules merged (ports 22, 80)
|
|
|
|
|
|
// - tag:web rules merged (ports 22, 443)
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Headscale now merges rules with identical SrcIPs and IPProto.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: tag:client rules (ports 22, 80)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: tag:web rules (ports 22, 443)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "multiple_tag_destinations_distributed",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Multiple tag destinations are distributed to their respective nodes.
|
|
|
|
|
|
// tagged-server gets port 22, tagged-db gets port 5432.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_node_different_ports_via_tag_and_host",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "webserver:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// KEY FINDING: Same IP can appear multiple times in Dsts with different ports
|
|
|
|
|
|
// when referenced via different aliases (tag vs host).
|
|
|
|
|
|
// - tag:server adds both IPv4 and IPv6 (port 22)
|
|
|
|
|
|
// - webserver host adds only IPv4 (port 80)
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// TODO: Tailscale includes webserver:80 BEFORE tag:server:22 in Dsts:
|
|
|
|
|
|
// DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
// {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// },
|
|
|
|
|
|
// Headscale: tag destinations come first, then host destinations
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// Host alias "webserver" expands to node's IPs (IPv4 + IPv6)
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "group_and_tag_destinations_distributed",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["group:admins:22", "tag:server:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Group:admins → user1, tag:server → tagged-server
|
|
|
|
|
|
// Each destination type distributed to its respective nodes.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_mixed_with_specific_source",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["tag:server:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Wildcard `*` is NOT merged with specific sources.
|
|
|
|
|
|
// Each remains a separate filter entry.
|
|
|
|
|
|
// Wildcard expands to CIDR ranges, specific tag expands to node IP.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10
|
2026-01-23 19:36:17 +00:00
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_src_different_dest_ports_merged",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]}
|
|
|
|
|
|
`),
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// KEY FINDING: Same source, same dest node, different ports = MERGED
|
|
|
|
|
|
// 2 rules → 1 filter entry with all ports combined (4 Dsts: 2 ports × 2 IPs)
|
|
|
|
|
|
// Headscale now merges rules with identical SrcIPs and IPProto.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: Both rules combined
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_src_different_dest_nodes_separate",
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
// Same source, different destination nodes = separate filter entries per node.
|
|
|
|
|
|
// Each destination node only receives its relevant filter.
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 2: Mixed Destinations - Additional tests
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tag_plus_raw_ip_same_node_different_ports",
|
|
|
|
|
|
// Test 2.3: tag:server:22 + 100.108.74.26:80 (tag + raw IP, same node)
|
|
|
|
|
|
// Same behavior as Test 2.2 - same IP can appear multiple times with different ports
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "100.108.74.26:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// tag:server adds both IPv4+IPv6 for port 22
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// Headscale resolves raw IP to node and includes all IPs (IPv4+IPv6)
|
|
|
|
|
|
// TODO: Tailscale adds only IPv4 for raw IP destinations
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "user_via_email_and_group_different_ports",
|
|
|
|
|
|
// Test 2.6: kratail2tid@:22 + group:admins:80 (same user via email + group)
|
|
|
|
|
|
// Same user referenced via email and group creates separate Dst entries per port
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["kratail2tid@:22", "group:admins:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// Same user via email and group with different ports - 4 Dst entries total
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "multiple_host_destinations",
|
|
|
|
|
|
// Test 2.7: webserver:22 + database:5432 (multiple hosts)
|
|
|
|
|
|
// Host destinations are properly distributed to matching nodes
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["webserver:22", "database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// Headscale resolves host alias to node and includes all IPs (IPv4+IPv6)
|
|
|
|
|
|
// TODO: Tailscale host alias is IPv4-only
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// Headscale resolves host alias to node and includes all IPs (IPv4+IPv6)
|
|
|
|
|
|
// TODO: Tailscale host alias is IPv4-only
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 3: Overlapping References - Same entity via different names
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_ip_via_tag_and_host_source",
|
|
|
|
|
|
// Test 3.1: src: [tag:server, webserver] - same IP via tag and host
|
|
|
|
|
|
// Duplicate IPs should be deduplicated in Srcs
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:server", "webserver"], "dst": ["tag:client:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// tag:server gives IPv4+IPv6, webserver adds IPv4 again (but deduplicated)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_ip_port_via_tag_and_host_dest",
|
|
|
|
|
|
// Test 3.3: dst: [tag:server:22, webserver:22] - same IP:port via tag and host
|
|
|
|
|
|
// Destinations are NOT deduplicated - same IP:port can appear multiple times
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "webserver:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// Destinations NOT deduplicated - same IP can appear twice
|
|
|
|
|
|
// tag:server adds IPv4:22 + IPv6:22
|
|
|
|
|
|
// webserver adds IPv4:22 again + Headscale adds IPv6 too
|
|
|
|
|
|
// TODO: Tailscale: webserver adds IPv4:22 only (duplicated with tag:server)
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_ip_port_via_tag_and_raw_ip_dest",
|
|
|
|
|
|
// Test 3.4: dst: [tag:server:22, 100.108.74.26:22] - tag + raw IP (identical)
|
|
|
|
|
|
// Same behavior as Test 3.3 - Dsts not deduplicated
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "100.108.74.26:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// Destinations NOT deduplicated
|
|
|
|
|
|
// tag:server adds IPv4:22 + IPv6:22
|
|
|
|
|
|
// Raw IP adds IPv4:22 again + Headscale adds IPv6 too
|
|
|
|
|
|
// TODO: Tailscale: raw IP adds IPv4:22 only (duplicated)
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tag_database_plus_host_database_source",
|
|
|
|
|
|
// Test 3.5: src: [tag:database, database] - tag:database + host database (same node)
|
|
|
|
|
|
// Sources ARE deduplicated
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:database", "database"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Sources deduplicated: tag:database (IPv4+IPv6) + database host (IPv4)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 4: Cross-Type Source→Destination Combinations
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_tagged_to_user",
|
|
|
|
|
|
// Test 4.2: autogroup:tagged → kratail2tid@:22
|
|
|
|
|
|
// Tagged nodes → user-owned nodes
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:tagged"], "dst": ["kratail2tid@:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// All 4 tagged nodes (8 IPs) can access user1:22
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "group_to_host_alias",
|
|
|
|
|
|
// Test 4.3: group:admins → webserver:22
|
|
|
|
|
|
// Group → host alias
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["webserver:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// Headscale resolves host alias to node and adds IPv6 too
|
|
|
|
|
|
// TODO: Tailscale host alias is IPv4-only
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 5: Order Effects - Order does NOT affect output
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "source_order_independence",
|
|
|
|
|
|
// Test 5.1: Order of sources doesn't affect output - they are sorted
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:web", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Sources are sorted: IPv4 first (ascending), then IPv6 (ascending)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 6: Edge Cases
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "cidr_host_as_source",
|
|
|
|
|
|
// Test 6.5: internal (10.0.0.0/8) → tag:server:22
|
|
|
|
|
|
// CIDR host definitions work as sources
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["internal"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// CIDR host goes directly into SrcIPs
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"10.0.0.0/8",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "cidr_host_as_destination_no_matching_nodes",
|
|
|
|
|
|
// Test 6.6: tag:client → internal:22 (CIDR host as destination)
|
|
|
|
|
|
// No nodes in 10.0.0.0/8 range, so no filters generated for any tailnet nodes
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["internal:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 7: Maximum Combinations
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "multiple_tags_as_sources",
|
|
|
|
|
|
// Test 7.x: Multiple tags as sources
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client", "tag:web", "tag:database"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// All 3 tags' IPs
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tag_to_multiple_destinations_ports",
|
|
|
|
|
|
// Test 7.x: tag:client → multiple destinations with different ports
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:5432", "tag:web:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 8: Redundancy Stress Tests
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "user1_referenced_multiple_ways_as_source",
|
|
|
|
|
|
// Test 8.1: user1 referenced 5 ways - all deduplicated
|
|
|
|
|
|
// autogroup:member, kratail2tid@, group:admins, group:developers, 100.90.199.68
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "kratail2tid@", "group:admins", "group:developers", "100.90.199.68"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// All 5 references resolve to user1 - deduplicated
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 9: All Tags + All Autogroups
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "all_four_tags_as_sources",
|
|
|
|
|
|
// Test 9.1: All 4 tags as sources
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:server", "tag:client", "tag:database", "tag:web"], "dst": ["kratail2tid@:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// All 4 tagged nodes (8 IPs total)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "all_four_tags_as_destinations",
|
|
|
|
|
|
// Test 9.2: All 4 tags as destinations
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["kratail2tid@"], "dst": ["tag:server:22", "tag:client:22", "tag:database:22", "tag:web:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "both_autogroups_as_sources",
|
|
|
|
|
|
// Test 9.3: autogroup:member + autogroup:tagged as sources (full tailnet)
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "autogroup:tagged"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// All 5 nodes (10 IPs)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 10: Multiple Rules with Mixed Types
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "cross_type_separate_rules",
|
|
|
|
|
|
// Test 10.1: Different source types in separate rules
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 11: Port Variations with Mixed Types
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "mixed_sources_with_port_range",
|
|
|
|
|
|
// Test 11.2: Mixed sources with port range
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["tag:server:80-443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 14: Multi-Rule Compounding
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_src_different_dests_two_rules",
|
|
|
|
|
|
// Test 14.1: Same src, different dests (2 rules)
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "different_srcs_same_dest_two_rules",
|
|
|
|
|
|
// Test 14.6: Different srcs, same dest (2 rules)
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
// Two separate filter rules for each ACL rule
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 12: CIDR Host Combinations
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "cidr_host_plus_tag_as_sources",
|
|
|
|
|
|
// Test 12.1: CIDR host + tag as sources
|
|
|
|
|
|
// internal (10.0.0.0/8) + tag:client
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["internal", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// CIDR host appears as-is in Srcs + tag:client IPs
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"10.0.0.0/8",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "multiple_cidr_hosts_as_sources",
|
|
|
|
|
|
// Test 12.2: Multiple CIDR hosts as sources
|
|
|
|
|
|
// internal (10.0.0.0/8) + subnet24 (192.168.1.0/24)
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["internal", "subnet24"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Both CIDR hosts appear in Srcs
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"10.0.0.0/8",
|
|
|
|
|
|
"192.168.1.0/24",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_cidr_via_host_and_raw",
|
|
|
|
|
|
// Test 12.4: Same CIDR referenced via host alias and raw CIDR
|
|
|
|
|
|
// internal (10.0.0.0/8) + 10.0.0.0/8 - should deduplicate
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["internal", "10.0.0.0/8"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Same CIDR referenced 2 ways should deduplicate
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"10.0.0.0/8",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 13: autogroup:self Deep Dive - Tests where autogroup:self works
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_autogroup_self",
|
|
|
|
|
|
// Test 13.1: * → autogroup:self:*
|
|
|
|
|
|
// CRITICAL: autogroup:self NARROWS Srcs even when source is wildcard
|
|
|
|
|
|
// Only user-owned nodes receive filters; tagged nodes get empty
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Srcs narrowed to user1's own IPs (NOT wildcard CIDRs)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// Dsts = user1's own IPs with all ports (no CIDR notation for autogroup:self)
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Tagged nodes receive NO filters for autogroup:self
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_autogroup_self_specific_port",
|
|
|
|
|
|
// Test 13.2: * → autogroup:self:22
|
|
|
|
|
|
// Specific port with autogroup:self
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_member_to_self",
|
|
|
|
|
|
// Test 13.5: autogroup:member → autogroup:self:*
|
|
|
|
|
|
// autogroup:member is a valid source for autogroup:self
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["autogroup:self:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "specific_user_to_self",
|
|
|
|
|
|
// Test 13.8: kratail2tid@ → autogroup:self:*
|
|
|
|
|
|
// Specific user email is a valid source for autogroup:self
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["kratail2tid@"], "dst": ["autogroup:self:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "group_to_self",
|
|
|
|
|
|
// Test 13.9: group:admins → autogroup:self:*
|
|
|
|
|
|
// Groups are valid sources for autogroup:self
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["autogroup:self:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_self_plus_tag",
|
|
|
|
|
|
// Test 13.16: * → [autogroup:self:*, tag:server:22]
|
|
|
|
|
|
// Mixed destinations with autogroup:self - different Srcs for each
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self:*", "tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Self filter gets narrowed Srcs (user1's IPs only)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// autogroup:self destinations use plain IPs (no CIDR notation)
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Tag filter gets full wildcard Srcs
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10
|
2026-01-23 19:36:17 +00:00
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Tag destinations use CIDR notation
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 14: More Multi-Rule Compounding
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_src_same_dest_different_ports_two_rules",
|
|
|
|
|
|
// Test 14.2: Same src, same dest, different ports (2 rules)
|
|
|
|
|
|
// In Tailscale: MERGED into single filter entry with combined Dsts
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Headscale now merges rules with identical SrcIPs and IPProto.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: Both rules combined
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "three_different_srcs_same_dest_different_ports",
|
|
|
|
|
|
// Test 14.21: 3 different sources → same dest, different ports
|
|
|
|
|
|
// Each rule becomes a separate filter entry
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:web"], "dst": ["tag:server:80"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:database"], "dst": ["tag:server:443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "overlapping_dests_same_src_different_rules",
|
|
|
|
|
|
// Test 10.2: Overlapping destinations, different sources (2 rules)
|
|
|
|
|
|
// Each rule creates its own filter entry on destination nodes
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["tag:server:*"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:tagged"], "dst": ["tag:server:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Rule 1: group:admins → tag:server:*
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
// Rule 2: autogroup:tagged → tag:server:*
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "mixed_sources_comma_ports",
|
|
|
|
|
|
// Test 11.1: Mixed sources with comma-separated ports
|
|
|
|
|
|
// Each port becomes a separate Dst entry
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["tag:server:22,80,443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// Each port is a separate Dst entry (6 total: 3 ports × 2 IPs)
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "full_autogroups_with_wildcard_and_specific_port",
|
|
|
|
|
|
// Test 11.4: Both autogroups with wildcard and specific port destinations
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:tagged", "autogroup:member"], "dst": ["tag:server:*", "tag:database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// All 5 nodes (10 IPs) as sources
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// Wildcard port → 0-65535
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 13: More autogroup:self tests
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_self_comma_ports",
|
|
|
|
|
|
// Test 13.3: * → autogroup:self:22,80,443
|
|
|
|
|
|
// Comma-separated ports create separate Dsts entries
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self:22,80,443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// 6 Dsts: 3 ports × 2 IPs (autogroup:self uses plain IPs)
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_self_port_range",
|
|
|
|
|
|
// Test 13.4: * → autogroup:self:80-443
|
|
|
|
|
|
// Port range preserved as First/Last
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self:80-443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// Port range preserved (autogroup:self uses plain IPs)
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "self_twice_separate_rules_merged",
|
|
|
|
|
|
// Test 13.36: Self twice in separate rules (merged)
|
|
|
|
|
|
// * → autogroup:self:22
|
|
|
|
|
|
// * → autogroup:self:80
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Tailscale MERGES these into a single filter entry with 4 Dsts
|
2026-01-23 19:36:17 +00:00
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: Both rules combined into 1 filter entry with 4 Dsts
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 14: More Multi-Rule Compounding
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_src_different_dests_two_rules_distributed",
|
|
|
|
|
|
// Test 14.1: Same src, different dests (2 rules)
|
|
|
|
|
|
// Rules distributed to different destination nodes
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "different_srcs_same_dest_two_rules",
|
|
|
|
|
|
// Test 14.6: Different srcs, same dest (2 rules)
|
|
|
|
|
|
// Creates 2 SEPARATE filter entries (not merged)
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:web"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "group_and_user_same_person_same_dest",
|
|
|
|
|
|
// Test 14.8: Group + user (same person) → same dest (2 rules)
|
|
|
|
|
|
// Srcs DEDUPLICATED but Dsts NOT deduplicated
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["kratail2tid@"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: 1 filter entry with Srcs deduplicated and 4 Dsts (duplicated)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_self_plus_group",
|
|
|
|
|
|
// Test 13.20: * → [autogroup:self:*, group:admins:22]
|
|
|
|
|
|
// user1 gets TWO filter entries (different Srcs)
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self:*", "group:admins:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
// Entry 1: autogroup:self with narrowed Srcs
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 2: group:admins with full wildcard Srcs
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_src_same_dest_different_ports_two_rules_merged",
|
|
|
|
|
|
// Test 14.2: Same src, same dest, different ports (2 rules)
|
|
|
|
|
|
// MERGED into single filter entry with 4 Dsts
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: Both rules combined
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "three_different_srcs_same_dest_different_ports",
|
|
|
|
|
|
// Test 14.21: 3 different srcs → same dest, different ports (3 rules)
|
|
|
|
|
|
// Creates 3 SEPARATE filter entries
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:web"], "dst": ["tag:server:80"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:database"], "dst": ["tag:server:443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "three_refs_same_user_same_dest_port",
|
|
|
|
|
|
// Test 14.22: 3 refs to same user → same dest:port (3 rules)
|
|
|
|
|
|
// Srcs DEDUPLICATED, Dsts NOT deduplicated (6 entries)
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["kratail2tid@"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: 1 filter entry with Srcs deduplicated and 6 Dsts (not deduplicated)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_src_three_different_dests",
|
|
|
|
|
|
// Test 14.23: Same src → 3 different dests (3 rules)
|
|
|
|
|
|
// Each destination node receives its own filter entry
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:web:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "full_wildcard_plus_specific_rule",
|
|
|
|
|
|
// Test 14.36: Full wildcard + specific rule
|
|
|
|
|
|
// BOTH rules create filter entries (wildcard does NOT subsume specific)
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["*:*"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
// Wildcard rule only
|
|
|
|
|
|
{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs and IPProto [0] (any).
|
|
|
|
|
|
// Headscale uses full 100.64.0.0/10 and explicit IPProto list.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
// TODO: Tailscale produces 2 entries: wildcard (IPProto [0]) + specific (IPProto [6,17,1,58])
|
|
|
|
|
|
// Headscale produces 2 entries but with same IPProto
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "both_autogroups_to_wildcard",
|
|
|
|
|
|
// Test 14.42: Both autogroups → wildcard (full network)
|
|
|
|
|
|
// Different Srcs = separate entries, even with identical Dsts
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:tagged"], "dst": ["*:*"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["*:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
// Entry 1: autogroup:tagged Srcs
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 2: autogroup:member Srcs
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "triple_src_ref_each_rule",
|
|
|
|
|
|
// Test 14.45: Triple src ref each rule
|
|
|
|
|
|
// Sources deduplicated within each rule
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "group:admins", "kratail2tid@"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:server", "webserver", "100.108.74.26"], "dst": ["group:admins:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
// Rule 2: tag:server + webserver + raw IP → group:admins (user1)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Srcs deduplicated to 1 IP + IPv6 (all resolve to same tagged-server)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
// Rule 1: autogroup:member + group:admins + user → tag:server
|
|
|
|
|
|
{
|
|
|
|
|
|
// Srcs deduplicated to user1's IPs (all 3 resolve to same user)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_src_four_dests",
|
|
|
|
|
|
// Test 14.47: Same src → 4 dests
|
|
|
|
|
|
// Same Srcs across 4 rules = merged into single filter entry per destination node
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:database:5432"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:web:80"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["webserver:443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
2026-01-24 07:49:39 +00:00
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "overlapping_destinations_different_sources",
|
|
|
|
|
|
// Test 10.2: Overlapping destinations, different sources
|
|
|
|
|
|
// Rules with same destination create SEPARATE filter entries, NOT merged
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["*:*"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:tagged"], "dst": ["*:*"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
// Entry 1: group:admins → *:*
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 2: autogroup:tagged → *:*
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_dest_node_via_tag_vs_host_source",
|
|
|
|
|
|
// Test 10.3: Same dest node via tag vs host source
|
|
|
|
|
|
// Same destination with different sources = separate entries
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["webserver"], "dst": ["tag:server:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
// Entry 1: tag:client → :22
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 2: webserver → :80 (host source expands to node IPs)
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "three_rules_same_dest_different_sources",
|
|
|
|
|
|
// Test 10.4: 3 rules, same dest, different sources
|
|
|
|
|
|
// 3 separate filter entries on the same destination node
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
// Entry 1: * → :22
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 2: tag:client → :80
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 3: autogroup:member → :443
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "mixed_sources_in_multiple_rules",
|
|
|
|
|
|
// Test 10.5: Mixed sources in multiple rules
|
|
|
|
|
|
// Sources within a rule are deduplicated
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client", "tag:web"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "group:admins"], "dst": ["tag:database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
// Rule 1: [tag:client, tag:web] → tag:server:22
|
|
|
|
|
|
// Sources merged and deduplicated
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
// Rule 2: [autogroup:member, group:admins] → tag:database:5432
|
|
|
|
|
|
// Both resolve to user1, deduplicated
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "mixed_sources_with_port_range_11_2",
|
|
|
|
|
|
// Test 11.2: Mixed sources with port range
|
|
|
|
|
|
// Port range preserved as First/Last
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins", "webserver"], "dst": ["tag:server:80-443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// group:admins (IPv4+IPv6) + webserver (node IPs) = 4 Srcs
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_dest_node_different_ports_via_different_refs_2_2",
|
|
|
|
|
|
// Test 2.2: Same node referenced via tag and host with different ports
|
|
|
|
|
|
// Same IP can appear multiple times in Dsts with different ports
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "webserver:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// tag:server:22 adds IPv4 and IPv6
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// webserver:80 expands to node IPs (both IPv4 and IPv6)
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_user_different_ports_via_email_and_group_2_6",
|
|
|
|
|
|
// Test 2.6: Same user referenced via email and group with different ports
|
|
|
|
|
|
// Destinations are NOT deduplicated when ports differ
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["kratail2tid@:22", "group:admins:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// 4 entries: user1's IPv4 and IPv6 for EACH port (22 and 80)
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "diff_srcs_same_dest_14_6",
|
|
|
|
|
|
// Test 14.6: Different srcs, same dest (2 rules)
|
|
|
|
|
|
// Different sources, same destination = 2 SEPARATE filter entries
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:web"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
// Entry 1: tag:client → :22
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 2: tag:web → :22
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "group_plus_user_same_person_same_dest_14_8",
|
|
|
|
|
|
// Test 14.8: Group + user (same person) → same dest (2 rules)
|
|
|
|
|
|
// Same person via group + user email = 1 filter entry, Srcs MERGED, Dsts NOT merged
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["kratail2tid@"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: 1 filter entry with 4 Dsts (duplicated)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "self_overlap_with_explicit_user_13_86",
|
|
|
|
|
|
// Test 13.86: self:22 + user:22 (overlap on same node)
|
|
|
|
|
|
// Different Srcs for self vs explicit user = separate entries
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale produces 2 entries, one with wildcard CGNAT Srcs, one with user1's IPs.
|
|
|
|
|
|
// Headscale produces similar with full CGNAT range (100.64.0.0/10).
|
|
|
|
|
|
// In Headscale, autogroup:self entry comes FIRST, explicit user SECOND.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self:22", "kratail2tid@:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
// Entry 1: * → autogroup:self:22 (Srcs narrowed to user1's IPs, no CIDR in DstPorts)
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 2: * → kratail2tid@:22 (wildcard Srcs, CIDR in DstPorts)
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "self_twice_different_ports_13_36",
|
|
|
|
|
|
// Test 13.36: Self twice in separate rules (merged)
|
|
|
|
|
|
// Multiple self rules with same source = MERGED into single filter entry
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: 1 filter entry with 4 Dsts
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "six_rules_mixing_all_patterns",
|
|
|
|
|
|
// Test 14.50: 6 rules mixing all patterns
|
|
|
|
|
|
// Self-referential rules work, different Srcs create separate entries
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:server"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:client:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:database"], "dst": ["tag:database:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:web"], "dst": ["tag:web:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["*:80"]},
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:member:443"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
// Entry 1: autogroup:member → *:80
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 2: * → autogroup:member:443 (user1 is in autogroup:member)
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
// Entry 1: tag:server → tag:server:22 (self-reference)
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 2: autogroup:member → *:80
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
// Entry 1: tag:client → tag:client:22 (self-reference)
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 2: autogroup:member → *:80
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
// Entry 1: tag:database → tag:database:22 (self-reference)
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 2: autogroup:member → *:80
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
// Entry 1: tag:web → tag:web:22 (self-reference)
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 2: autogroup:member → *:80
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 1: Mixed Sources
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_member_plus_tag_client_1_1",
|
|
|
|
|
|
// Test 1.1: autogroup:member + tag:client
|
|
|
|
|
|
// Sources are merged into single Srcs array
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// autogroup:member (user1) + tag:client = merged
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "group_admins_plus_tag_client_1_3",
|
|
|
|
|
|
// Test 1.3: group:admins + tag:client
|
|
|
|
|
|
// Sources are merged into single Srcs array
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// group:admins (user1) + tag:client = merged
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "user_email_plus_tag_client_1_4",
|
|
|
|
|
|
// Test 1.4: kratail2tid@ + tag:client
|
|
|
|
|
|
// User email expanded to IPs + tag = merged
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["kratail2tid@", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "host_plus_tag_client_1_5",
|
|
|
|
|
|
// Test 1.5: webserver (host) + tag:client
|
|
|
|
|
|
// Host expands to node IPs + tag = merged
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["webserver", "tag:client"], "dst": ["tag:database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// webserver (tagged-server IPs) + tag:client = merged
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "raw_ip_plus_tag_client_1_6",
|
|
|
|
|
|
// Test 1.6: 100.90.199.68 (raw IP) + tag:client
|
|
|
|
|
|
// Raw IP expands to node's both IPs + tag = merged
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["100.90.199.68", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Raw IP expands to user1's IPs + tag:client = merged (4 IPs)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "user1_three_ways_1_7",
|
|
|
|
|
|
// Test 1.7: autogroup:member + group:admins + kratail2tid@
|
|
|
|
|
|
// Same user referenced 3 ways = deduplicated to 2 IPs
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "group:admins", "kratail2tid@"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// All 3 references resolve to user1's IPs, deduplicated
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 2: Mixed Destinations
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tag_server_22_plus_tag_database_5432_2_1",
|
|
|
|
|
|
// Test 2.1: tag:server:22 + tag:database:5432
|
|
|
|
|
|
// Multiple destinations in same rule, distributed to each node
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tag_server_22_plus_raw_ip_80_2_3",
|
|
|
|
|
|
// Test 2.3: tag:server:22 + 100.108.74.26:80 (tag + raw IP, same node)
|
|
|
|
|
|
// Same node via tag and raw IP, different ports = NOT deduplicated in Dsts
|
|
|
|
|
|
// Raw IP destination expands to include node's IPv6
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "100.108.74.26:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// tag:server:22 adds IPv4 and IPv6
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// raw IP:80 expands to both IPs
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "group_admins_22_plus_tag_server_80_2_4",
|
|
|
|
|
|
// Test 2.4: group:admins:22 + tag:server:80
|
|
|
|
|
|
// User destination on port 22, tag destination on port 80
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["group:admins:22", "tag:server:80"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "webserver_22_plus_database_5432_2_7",
|
|
|
|
|
|
// Test 2.7: webserver:22 + database:5432 (multiple hosts)
|
|
|
|
|
|
// Multiple host destinations
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["webserver:22", "database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// webserver host expands to tagged-server's IPs
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// database host expands to tagged-db's IPs
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 3: Overlapping References
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "user1_three_ways_source_3_2",
|
|
|
|
|
|
// Test 3.2: user1 referenced 3 ways as source
|
|
|
|
|
|
// All resolve to same IPs, deduplicated
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "kratail2tid@", "group:admins"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// All 3 references resolve to user1, deduplicated to 2 IPs
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_ip_port_tag_and_host_dest_3_3",
|
|
|
|
|
|
// Test 3.3: Same IP:port via tag and host as dest
|
|
|
|
|
|
// Same IP:port referenced two ways = NOT deduplicated
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "webserver:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// tag:server:22 adds IPv4 and IPv6
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// webserver:22 also expands to same IPs - NOT deduplicated
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_ip_port_tag_and_raw_ip_dest_3_4",
|
|
|
|
|
|
// Test 3.4: Same IP:port via tag and raw IP
|
|
|
|
|
|
// Raw IP also expands to both IPs when matching a node
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "100.108.74.26:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// tag:server:22 adds IPv4 and IPv6
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// raw IP also expands to both IPs (NOT deduplicated)
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 4: Cross-Type Source→Destination Combinations
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "raw_ip_to_tag_server_4_7",
|
|
|
|
|
|
// Test 4.7: 100.90.199.68 → tag:server:22
|
|
|
|
|
|
// Raw IP as source, tag as destination
|
|
|
|
|
|
// In Headscale, raw IP that matches a node expands to include IPv6
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["100.90.199.68"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tag_client_to_raw_ip_4_8",
|
|
|
|
|
|
// Test 4.8: tag:client → 100.108.74.26:22
|
|
|
|
|
|
// Tag as source, raw IP as destination
|
|
|
|
|
|
// In Headscale, raw IP destination that matches a node expands to include IPv6
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["100.108.74.26:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 7: Maximum Combinations ("Kitchen Sink")
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "all_source_types_to_tag_server_7_1",
|
|
|
|
|
|
// Test 7.1: ALL source types → tag:server:22
|
|
|
|
|
|
// Mix of all source types in one rule
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "autogroup:tagged", "group:admins", "tag:client", "webserver", "100.74.60.128"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// All sources merged: user1, all tagged, webserver, database IP
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 8: Redundancy Stress Tests
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "user1_referenced_5_ways_8_1",
|
|
|
|
|
|
// Test 8.1: user1 referenced 5 ways
|
|
|
|
|
|
// All references deduplicated to user1's 2 IPs
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "group:admins", "group:developers", "kratail2tid@", "100.90.199.68"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// 5 references → deduplicated to user1's IPs + raw IP
|
|
|
|
|
|
// Note: raw IP only adds IPv4, others add both
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tagged_server_3_ways_source_8_2",
|
|
|
|
|
|
// Test 8.2: tagged-server referenced 3 ways as source
|
|
|
|
|
|
// tag:server + webserver + raw IP = deduplicated
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:server", "webserver", "100.108.74.26"], "dst": ["tag:database:5432"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// All 3 references resolve to tagged-server's IPs, deduplicated
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_ip_port_3_ways_dest_8_5",
|
|
|
|
|
|
// Test 8.5: Same IP:port referenced 3 ways as destination
|
|
|
|
|
|
// tag:server:22 + webserver:22 + 100.108.74.26:22
|
|
|
|
|
|
// Destinations are NOT deduplicated, raw IP also expands
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "webserver:22", "100.108.74.26:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// tag:server:22 adds both IPs
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// webserver:22 also adds both IPs (NOT deduplicated)
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// raw IP also adds both IPs (NOT deduplicated)
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Category 12: CIDR Host Combinations
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "cidr_subnet_plus_tag_as_sources_12_3",
|
|
|
|
|
|
// Test 12.3: internal (CIDR host) + tag as sources
|
|
|
|
|
|
// External CIDR doesn't match nodes, tag does
|
|
|
|
|
|
policy: makePolicy(`
|
|
|
|
|
|
{"action": "accept", "src": ["internal", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// internal (10.0.0.0/8) + tag:client IPs
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"10.0.0.0/8",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Category 5: Order Effects
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Test 5.1a: Source Order - [tag:client, tag:web]
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "source_order_client_web_5_1a",
|
|
|
|
|
|
// Test that order of sources doesn't affect output
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["tag:client", "tag:web"], "dst": ["tag:server:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Sources merged and sorted: IPv4 first (sorted), then IPv6 (sorted)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 5.1b: Source Order Reversed - [tag:web, tag:client]
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "source_order_web_client_5_1b",
|
|
|
|
|
|
// Same as 5.1a but reversed order - should produce identical output
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["tag:web", "tag:client"], "dst": ["tag:server:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Should be identical to 5.1a - order doesn't matter
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 5.2a: Destination Order - [tag:server:22, tag:database:80]
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "dest_order_server_db_5_2a",
|
|
|
|
|
|
// Test destination order - each node should get only its portion
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:80"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 5.2b: Destination Order Reversed - [tag:database:80, tag:server:22]
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "dest_order_db_server_5_2b",
|
|
|
|
|
|
// Same as 5.2a but reversed - should produce identical per-node filters
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["tag:client"], "dst": ["tag:database:80", "tag:server:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 5.3a: Mixed Source Types Order - [autogroup:member, tag:client]
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "mixed_source_order_member_client_5_3a",
|
|
|
|
|
|
// Test mixed source types order
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["tag:server:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Sources sorted: IPv4 first, then IPv6
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 5.3b: Mixed Source Types Order Reversed - [tag:client, autogroup:member]
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "mixed_source_order_client_member_5_3b",
|
|
|
|
|
|
// Same as 5.3a but reversed - should produce identical output
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["tag:client", "autogroup:member"], "dst": ["tag:server:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Should be identical to 5.3a
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Category 6: Edge Cases
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Test 6.3: Empty group as source - no filters expected
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "empty_group_source_6_3",
|
|
|
|
|
|
// group:empty has no members, so no filters should be generated
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["group:empty"], "dst": ["tag:server:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": nil, // No filter because source group is empty
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 6.5: CIDR host (internal = 10.0.0.0/8) as source
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "cidr_host_source_6_5",
|
|
|
|
|
|
// Host "internal" defined as 10.0.0.0/8 - CIDR goes directly into Srcs
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["internal"], "dst": ["tag:server:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{"10.0.0.0/8"},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 6.6: CIDR host as destination - no tailnet nodes match
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "cidr_host_dest_6_6",
|
|
|
|
|
|
// internal (10.0.0.0/8) as destination - no tailnet nodes in this range
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["tag:client"], "dst": ["internal:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// No nodes match 10.0.0.0/8, so no filters generated
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Category 9: All Tags + All Autogroups
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Test 9.1: All 4 tags as sources
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "all_four_tags_sources_9_1",
|
|
|
|
|
|
// All 4 tags combined as sources
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["tag:server", "tag:client", "tag:database", "tag:web"], "dst": ["tag:server:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// 4 tags = 8 IPs (4 IPv4 + 4 IPv6, deduplicated)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 9.2: All 4 tags as destinations
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "all_four_tags_dests_9_2",
|
|
|
|
|
|
// All 4 tags as destinations - each node gets only its own IP:port
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22", "tag:client:22", "tag:database:22", "tag:web:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil, // Not a destination
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 9.3: Both autogroups as sources
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "both_autogroups_sources_9_3",
|
|
|
|
|
|
// autogroup:member + autogroup:tagged = full tailnet coverage
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["autogroup:member", "autogroup:tagged"], "dst": ["tag:server:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Full tailnet: 5 nodes = 10 IPs (5 IPv4 + 5 IPv6)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Category 10: Multiple Rules with Mixed Types
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Test 10.1: Cross-type in separate rules
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "cross_type_separate_rules_10_1",
|
|
|
|
|
|
// Rule 1: autogroup:member → tag:server:22
|
|
|
|
|
|
// Rule 2: tag:client → group:admins:80
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["group:admins:80"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// user1 gets filter from Rule 2 (tag:client → group:admins:80)
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-server gets filter from Rule 1 (autogroup:member → tag:server:22)
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 10.2: Overlapping destinations, different sources
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "overlapping_dests_diff_sources_10_2",
|
|
|
|
|
|
// Rule 1: group:admins → tag:server:22
|
|
|
|
|
|
// Rule 2: autogroup:tagged → tag:server:22
|
|
|
|
|
|
// Same destination, different sources - creates separate filter entries
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:tagged"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// tagged-server gets TWO separate filter entries (one per rule)
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
// Rule 1: group:admins
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Rule 2: autogroup:tagged
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 10.3: Three rules to same destination
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "three_rules_same_dest_10_3",
|
|
|
|
|
|
// Rule 1: autogroup:member → tag:server:22
|
|
|
|
|
|
// Rule 2: tag:client → tag:server:22
|
|
|
|
|
|
// Rule 3: group:admins → tag:server:22
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// tagged-server gets TWO filter entries (Rules 1+3 merged, Rule 2 separate)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
"tagged-server": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Rules 1+3: autogroup:member and group:admins (same SrcIPs) merged
|
|
|
|
|
|
// DstPorts combined from both rules (duplicates included)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-24 07:49:39 +00:00
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
2026-01-24 07:49:39 +00:00
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Rule 2: tag:client (different SrcIPs, not merged)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Category 11: Port Variations with Mixed Types
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Test 11.1: Mixed sources with comma ports
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "mixed_sources_comma_ports_11_1",
|
|
|
|
|
|
// Comma-separated ports create separate Dsts entries
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["tag:server:22,80,443"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
// 3 ports × 2 IPs = 6 Dsts entries
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 11.2: Mixed sources with port range
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "mixed_sources_port_range_11_2",
|
|
|
|
|
|
// Port ranges preserved as First/Last in Dsts
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["group:admins", "webserver"], "dst": ["tag:server:80-443"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// group:admins (IPv4+IPv6) + webserver (IPv4+IPv6 since it matches tagged-server node)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 11.4: Full autogroups with wildcard port
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroups_wildcard_port_11_4",
|
|
|
|
|
|
// Wildcard port (*) expands to 0-65535
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["autogroup:tagged", "autogroup:member"], "dst": ["tag:server:*"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Full tailnet: 5 nodes = 10 IPs
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Category 13: autogroup:self Deep Dive
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Test 13.1: Wildcard → self:*
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_self_all_ports_13_1",
|
|
|
|
|
|
// autogroup:self NARROWS Srcs even when source is wildcard
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["autogroup:self:*"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
// Only user1 (user-owned) receives filter
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
// Srcs NARROWED to user1's IPs only (not wildcard CIDRs!)
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Tagged nodes receive NO filters
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 13.2: Wildcard → self:22
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_self_port_22_13_2",
|
|
|
|
|
|
// Specific port with self
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["autogroup:self:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 13.5: autogroup:member → self:*
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "member_to_self_13_5",
|
|
|
|
|
|
// autogroup:member works with autogroup:self
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["autogroup:member"], "dst": ["autogroup:self:*"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 13.8: Specific user → self:*
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "specific_user_to_self_13_8",
|
|
|
|
|
|
// Specific user email works with autogroup:self
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["kratail2tid@"], "dst": ["autogroup:self:*"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 13.9: group:admins → self:*
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "group_to_self_13_9",
|
|
|
|
|
|
// Groups work with autogroup:self
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["group:admins"], "dst": ["autogroup:self:*"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Category 14: Multi-Rule Compounding
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Test 14.1: Same src, different dests (2 rules)
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_src_diff_dests_14_1",
|
|
|
|
|
|
// Same source, different destinations = separate filter entries per dest node
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.2: Same src, same dest, different ports (2 rules)
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_src_same_dest_diff_ports_merged_14_2",
|
|
|
|
|
|
// Same source + dest node + different ports
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// MERGED into 1 filter entry with 4 Dsts
|
2026-01-23 19:36:17 +00:00
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: 1 entry with 4 DstPorts
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.6: Different srcs, same dest (2 rules)
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "diff_srcs_same_dest_14_6",
|
|
|
|
|
|
// Different sources, same dest = 2 SEPARATE filter entries
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:web"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// TWO separate filter entries
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
// Entry 1: tag:client
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
// Entry 2: tag:web
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.8: Group + user (same person) → same dest (2 rules)
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "group_user_same_person_same_dest_14_8",
|
|
|
|
|
|
// Group + user (same person)
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// MERGED into 1 filter entry (Srcs deduplicated, Dsts NOT)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["kratail2tid@"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: 1 entry with deduplicated Srcs but duplicated Dsts
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Category 7: Kitchen Sink Tests
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Test 7.2: tag:client → ALL destination types
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "all_dest_types_7_2",
|
|
|
|
|
|
// Test ALL destination types from one source
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:5432", "webserver:80", "database:443", "group:admins:8080", "kratail2tid@:3000", "100.108.74.26:9000"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// user1 gets entries for user:3000 and group:8080
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 8080, Last: 8080}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 8080, Last: 8080}},
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 3000, Last: 3000}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 3000, Last: 3000}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-server gets tag:server:22, webserver:80, raw IP:9000
|
|
|
|
|
|
// Note: Host aliases that match node IPs get expanded to include IPv6
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 9000, Last: 9000}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 9000, Last: 9000}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-db gets tag:database:5432 and database:443
|
|
|
|
|
|
// Note: Host aliases that match node IPs get expanded to include IPv6
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 7.3: 10 different sources → *:*
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "ten_sources_to_wildcard_7_3",
|
|
|
|
|
|
// 10 different source types all deduplicated
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "autogroup:tagged", "group:admins", "group:developers", "kratail2tid@", "tag:client", "tag:web", "tag:database", "webserver", "database"], "dst": ["*:*"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
// All nodes receive the deduplicated sources (including tagged-client since it's in *:*)
|
|
|
|
|
|
// The sources are: autogroup:member, autogroup:tagged, group:admins, group:developers,
|
|
|
|
|
|
// kratail2tid@, tag:client, tag:web, tag:database, webserver, database
|
|
|
|
|
|
// autogroup:tagged includes ALL tagged nodes: tagged-server, tagged-client, tagged-db, tagged-web
|
|
|
|
|
|
// All 5 nodes' IPs are included in the sources
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Category 12: CIDR Host Combinations
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Test 12.1: CIDR host + tag as sources
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "cidr_host_plus_tag_sources_12_1",
|
|
|
|
|
|
// CIDR host (10.0.0.0/8) combined with tag as sources
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["internal", "tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"10.0.0.0/8",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 12.2: Multiple CIDR hosts as sources
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "multiple_cidr_hosts_sources_12_2",
|
|
|
|
|
|
// Multiple CIDR hosts (10.0.0.0/8 + 192.168.1.0/24)
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["internal", "subnet24"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"10.0.0.0/8",
|
|
|
|
|
|
"192.168.1.0/24",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 12.4: Host CIDR + raw CIDR (same value) as sources
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "host_cidr_plus_raw_cidr_same_12_4",
|
|
|
|
|
|
// Same CIDR via host alias and raw value - should deduplicate
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["internal", "10.0.0.0/8"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// Deduplicated - only one 10.0.0.0/8 entry
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"10.0.0.0/8",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Additional Missing Tests from 09-mixed-scenarios.md
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Test 6.2: * → [webserver:22, database:5432]
|
|
|
|
|
|
// Wildcard source + multiple host destinations
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_multiple_hosts_6_2",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["webserver:22", "database:5432"]}`),
|
|
|
|
|
|
// Wildcard `*` expands to all nodes (Headscale uses 0.0.0.0/0 and ::/0)
|
|
|
|
|
|
// Host destinations are properly distributed to matching nodes
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// tagged-server gets webserver:22 (since webserver = 100.108.74.26 = tagged-server)
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
// NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10:
|
2026-01-23 19:36:17 +00:00
|
|
|
|
// "100.115.94.0/23", "100.115.96.0/19", ..., "fd7a:115c:a1e0::/48"
|
|
|
|
|
|
// TODO: Host destination is IPv4-only in Tailscale, but Headscale
|
|
|
|
|
|
// resolves host aliases to node IPs and includes both IPv4+IPv6
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-db gets database:5432 (since database = 100.74.60.128 = tagged-db)
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// TODO: Host destination is IPv4-only in Tailscale
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 7.4: * → 9 destinations (multiple per node)
|
|
|
|
|
|
// Destinations: tag:server:22, tag:server:80, tag:server:443, tag:database:5432,
|
|
|
|
|
|
// tag:database:3306, tag:web:80, tag:web:443, webserver:8080, database:8080
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_9_destinations_7_4",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["tag:server:22", "tag:server:80", "tag:server:443", "tag:database:5432", "tag:database:3306", "tag:web:80", "tag:web:443", "webserver:8080", "database:8080"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
// tagged-server gets: tag:server:22/80/443 + webserver:8080
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// webserver:8080 (host alias - Headscale includes IPv4+IPv6)
|
|
|
|
|
|
// TODO: Tailscale host destinations are IPv4-only
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 8080, Last: 8080}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 8080, Last: 8080}},
|
|
|
|
|
|
// tag:server:22 (IPv4)
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// tag:server:80 (IPv4)
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
// tag:server:443 (IPv4)
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
// tag:server:22 (IPv6)
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// tag:server:80 (IPv6)
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
// tag:server:443 (IPv6)
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-db gets: tag:database:5432/3306 + database:8080
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// database:8080 (host alias - Headscale includes IPv4+IPv6)
|
|
|
|
|
|
// TODO: Tailscale host destinations are IPv4-only
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 8080, Last: 8080}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 8080, Last: 8080}},
|
|
|
|
|
|
// tag:database:5432 (IPv4)
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
// tag:database:3306 (IPv4)
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 3306, Last: 3306}},
|
|
|
|
|
|
// tag:database:5432 (IPv6)
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
// tag:database:3306 (IPv6)
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 3306, Last: 3306}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-web gets: tag:web:80/443
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// tag:web:80 (IPv4)
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
// tag:web:443 (IPv4)
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
// tag:web:80 (IPv6)
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
// tag:web:443 (IPv6)
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 7.5: MANY sources → MANY destinations
|
|
|
|
|
|
// Sources: autogroup:member, group:admins, kratail2tid@, tag:client, tag:web, 100.80.238.75, 100.94.92.91
|
|
|
|
|
|
// Destinations: tag:server:22, webserver:80, 100.108.74.26:443, group:admins:8080, kratail2tid@:9000
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "many_sources_many_destinations_7_5",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["autogroup:member", "group:admins", "kratail2tid@", "tag:client", "tag:web", "100.80.238.75", "100.94.92.91"], "dst": ["tag:server:22", "webserver:80", "100.108.74.26:443", "group:admins:8080", "kratail2tid@:9000"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// user1 gets: group:admins:8080 + kratail2tid@:9000
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// kratail2tid@:9000
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 9000, Last: 9000}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 9000, Last: 9000}},
|
|
|
|
|
|
// group:admins:8080
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 8080, Last: 8080}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 8080, Last: 8080}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-server gets: tag:server:22 + webserver:80 + 100.108.74.26:443
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// webserver:80 (host alias matches tagged-server, includes IPv6)
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
// tag:server:22
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// 100.108.74.26:443 (raw IP matches node, so Headscale includes IPv6)
|
|
|
|
|
|
// TODO: Tailscale raw IP destinations are IPv4-only
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 8.3: tagged-db referenced 3 ways as source
|
|
|
|
|
|
// Sources: tag:database, database (host alias), 100.74.60.128 (raw IP)
|
|
|
|
|
|
// All 3 resolve to tagged-db - should be deduplicated in Srcs
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tagged_db_3_ways_source_8_3",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["tag:database", "database", "100.74.60.128"], "dst": ["tag:server:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// tagged-server receives filter
|
|
|
|
|
|
// Srcs should be deduplicated: tag adds IPv6, host/raw IP are IPv4-only
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 8.4: autogroup:tagged + all 4 tags as sources
|
|
|
|
|
|
// Sources: autogroup:tagged, tag:server, tag:client, tag:database, tag:web
|
|
|
|
|
|
// autogroup:tagged covers all 4 tags, so individual tags are redundant
|
|
|
|
|
|
// Should deduplicate to just 8 IPs (4 nodes × 2 IPs each)
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_tagged_plus_all_4_tags_8_4",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["autogroup:tagged", "tag:server", "tag:client", "tag:database", "tag:web"], "dst": ["autogroup:member:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// user1 (autogroup:member) receives the filter
|
|
|
|
|
|
// Srcs = all 4 tagged nodes deduplicated = 8 IPs
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Additional Missing Tests - Batch 2
|
|
|
|
|
|
// ===========================================
|
|
|
|
|
|
// Test 1.8: tag:server + webserver (same IP two ways as sources)
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tag_server_plus_webserver_same_ip_1_8",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["tag:server", "webserver"], "dst": ["tag:client:22"]}`),
|
|
|
|
|
|
// tag:server and webserver both resolve to tagged-server (100.108.74.26)
|
|
|
|
|
|
// Sources should be deduplicated
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// tagged-client receives the filter
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
// Deduplicated: tag:server adds IPv4+IPv6, webserver adds IPv4 only
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 4.3: group:admins → webserver:22
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "group_admins_to_webserver_4_3",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["group:admins"], "dst": ["webserver:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// tagged-server (webserver) receives the filter
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// TODO: Tailscale only includes IPv4 for host alias
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 4.4: webserver → group:admins:22
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "webserver_to_group_admins_4_4",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["webserver"], "dst": ["group:admins:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// user1 (group:admins member) receives the filter
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
// TODO: Tailscale only includes IPv4 for host source
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 8.6: user1:22 referenced 4 ways as destination
|
|
|
|
|
|
// Destinations: group:admins:22, group:developers:22, kratail2tid@:22, 100.90.199.68:22
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "user1_4_ways_dest_8_6",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["tag:client"], "dst": ["group:admins:22", "group:developers:22", "kratail2tid@:22", "100.90.199.68:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// user1 receives the filter - Dsts NOT deduplicated
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// kratail2tid@:22
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// group:admins:22
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// group:developers:22
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// 100.90.199.68:22 (raw IP matches node, includes IPv6)
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 8.7: Same node, 5 ports via different references
|
|
|
|
|
|
// Destinations: tag:server:22, tag:server:80, tag:server:443, webserver:8080, 100.108.74.26:9000
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_node_5_ports_different_refs_8_7",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:server:80", "tag:server:443", "webserver:8080", "100.108.74.26:9000"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// tagged-server receives the filter
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// webserver:8080 (host alias - includes IPv6)
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 8080, Last: 8080}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 8080, Last: 8080}},
|
|
|
|
|
|
// 100.108.74.26:9000 (raw IP - includes IPv6)
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 9000, Last: 9000}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 9000, Last: 9000}},
|
|
|
|
|
|
// tag:server:22
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// tag:server:80
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
// tag:server:443
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 9.4: Wildcard to autogroup:self
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_autogroup_self_9_4",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["autogroup:self:*"]}`),
|
|
|
|
|
|
// Only user1 (user-owned) receives filter; tagged nodes don't support autogroup:self
|
|
|
|
|
|
// Sources narrowed to user1's own IPs (not full wildcard)
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// Note: autogroup:self destinations use raw IP format (no /32 suffix)
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 10.4: 3 rules, same dest, different sources
|
|
|
|
|
|
// Rule 1: * → tag:server:22
|
|
|
|
|
|
// Rule 2: tag:client → tag:server:80
|
|
|
|
|
|
// Rule 3: autogroup:member → tag:server:443
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "three_rules_same_dest_different_sources_10_4",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:443"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// tagged-server receives 3 filter entries
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 10.5: Mixed sources in multiple rules
|
|
|
|
|
|
// Rule 1: [tag:client, tag:web] → tag:server:22
|
|
|
|
|
|
// Rule 2: [autogroup:member, group:admins] → tag:database:5432
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "mixed_sources_multiple_rules_10_5",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"],
|
|
|
|
|
|
"group:developers": ["kratail2tid@"],
|
|
|
|
|
|
"group:empty": []
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26",
|
|
|
|
|
|
"database": "100.74.60.128",
|
|
|
|
|
|
"internal": "10.0.0.0/8",
|
|
|
|
|
|
"subnet24": "192.168.1.0/24"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client", "tag:web"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "group:admins"], "dst": ["tag:database:5432"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// tagged-server receives filter from rule 1
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-db receives filter from rule 2
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 11.3: Mixed sources with mixed port formats
|
|
|
|
|
|
// Destinations: tag:server:22, tag:server:80-443, tag:database:5432,3306
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "mixed_sources_mixed_port_formats_11_3",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["tag:client", "tag:web"], "dst": ["tag:server:22", "tag:server:80-443", "tag:database:5432,3306"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// tagged-server receives :22 and :80-443
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// :22
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
// :80-443
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-db receives :5432,3306
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// :5432
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
// :3306
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 3306, Last: 3306}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 3306, Last: 3306}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 12.5: Multiple CIDR + tag destinations
|
|
|
|
|
|
// Destinations: internal:22, subnet24:80, tag:server:443
|
|
|
|
|
|
// CIDR destinations don't match tailnet nodes
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "multiple_cidr_plus_tag_destinations_12_5",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["internal:22", "subnet24:80", "tag:server:443"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// Only tag:server:443 is delivered (CIDRs don't match tailnet nodes)
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 13.4: Wildcard → self:80-443 (port range)
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_self_port_range_13_4",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["autogroup:self:80-443"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// Note: autogroup:self destinations use raw IP format (no /32 suffix)
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 443}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 13.16: Wildcard → self + tag:server:22 (mixed destinations)
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_self_plus_tag_server_13_16",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["autogroup:self:*", "tag:server:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// user1: receives narrowed Srcs for autogroup:self
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// Note: autogroup:self destinations use raw IP format (no /32 suffix)
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-server: receives full wildcard Srcs for tag:server:22
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 13.20: Wildcard → self + group:admins:22 (same dest node)
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_self_plus_group_admins_13_20",
|
|
|
|
|
|
policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["autogroup:self:*", "group:admins:22"]}`),
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// user1 gets 2 filter entries:
|
|
|
|
|
|
// Entry 1: autogroup:self:* with narrowed Srcs (processed first due to autogroup:self splitting)
|
|
|
|
|
|
// Entry 2: group:admins:22 with full wildcard
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
// Note: autogroup:self destinations use raw IP format (no /32 suffix)
|
2026-01-23 21:05:00 +00:00
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// ===== Category 14: Multi-Rule Tests =====
|
|
|
|
|
|
|
|
|
|
|
|
// Test 14.21: 3 different srcs → same dest, different ports (3 rules)
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "three_diff_srcs_same_dest_diff_ports_14_21",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:web"], "dst": ["tag:server:80"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:database"], "dst": ["tag:server:443"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// tagged-server: receives 3 separate filter entries (different Srcs = separate)
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.22: 3 refs to same user → same dest:port (3 rules)
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// MERGED into 1 entry with 6 Dsts (not deduplicated)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "three_refs_same_user_same_dest_14_22",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["kratail2tid@"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"tagged-server": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: 1 entry with 6 Dsts (not deduplicated)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.23: Same src → 3 different dests (3 rules)
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_src_three_diff_dests_14_23",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:web:80"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
// Each destination node receives its own filter (same Srcs per node)
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.26: Same entity as both src and dst in 2 rules
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// MERGED into 1 entry with 4 Dsts (not deduplicated)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "same_entity_src_and_dst_14_26",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["autogroup:member:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["group:admins:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"user1": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: 1 entry with 4 Dsts (not deduplicated)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.27: User→user:22, group→user:80 (same Srcs, different ports)
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// MERGED into 1 entry with 4 Dsts
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "user_to_user_22_group_to_user_80_14_27",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["kratail2tid@"], "dst": ["kratail2tid@:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["group:admins"], "dst": ["kratail2tid@:80"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"user1": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: 1 entry with 4 Dsts
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.29: tagged→tagged:22, specific tags→tagged:80
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "tagged_to_tagged_specific_tags_14_29",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:tagged"], "dst": ["autogroup:tagged:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client", "tag:web"], "dst": ["autogroup:tagged:80"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
// Each tagged node receives 2 filter entries (different Srcs = separate)
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.42: Both autogroups → wildcard (full network)
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "both_autogroups_to_wildcard_14_42",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:tagged"], "dst": ["*:*"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["*:*"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
// All nodes receive 2 filter entries (different Srcs = separate entries)
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.45: Triple src ref each rule
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "triple_src_ref_each_rule_14_45",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "group:admins", "kratail2tid@"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:server", "webserver", "100.108.74.26"], "dst": ["group:admins:80"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
// tagged-server: receives filter from rule 1 (triple user ref deduplicated to 1 IP)
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// user1: receives filter from rule 2 (triple ref deduplicated to tag:server IP)
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.47: Same src → 4 dests (4 rules)
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_src_four_dests_14_47",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:database:5432"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:web:80"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["webserver:443"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// tagged-server: merged entry for :22 and :443 (same SrcIPs)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
2026-01-24 07:49:39 +00:00
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.50: 6 rules mixing all patterns
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "six_rules_mixed_patterns_14_50",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:server"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:client:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:database"], "dst": ["tag:database:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:web"], "dst": ["tag:web:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member"], "dst": ["*:80"]},
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:member:443"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
// user1: receives 2 entries: member→*:80 and *→user1:443
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-server: receives self-ref + member→*:80
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-client: receives self-ref + member→*:80
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-db: receives self-ref + member→*:80
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-web: receives self-ref + member→*:80
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.17: Wildcard → group and user (same person):22
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Test 14.17: * → group:admins:22 and * → kratail2tid@:22
|
|
|
|
|
|
// MERGED into 1 entry with 4 Dsts (duplicated)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_to_group_and_user_same_14_17",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["group:admins:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["kratail2tid@:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"user1": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: 1 entry with 4 Dsts (duplicated)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.18: Tag → member and group (same):22
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// MERGED into 1 entry with 4 Dsts (duplicated)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "tag_to_member_and_group_same_14_18",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["autogroup:member:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["group:admins:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-server": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
"tagged-db": nil,
|
|
|
|
|
|
"tagged-web": nil,
|
|
|
|
|
|
"user1": {
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Merged: 1 entry with 4 Dsts (duplicated)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.20: Two rules with multi-dest, partial dest overlap
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "two_rules_multi_dest_partial_overlap_14_20",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["tag:server:22", "tag:database:5432"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80", "tag:web:443"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
// tagged-server: receives both wildcard:22 and tag:client:80
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-db: receives wildcard:5432
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-web: receives tag:client:443
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.30: All→all subset, wildcard→wildcard
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "all_to_all_subset_wildcard_wildcard_14_30",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "autogroup:tagged"], "dst": ["autogroup:member:22", "autogroup:tagged:80"]},
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["*:443"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
// user1: receives member:22 (first rule dst) + *:443 (second rule)
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-web: receives tagged:80 (first rule dst) + *:443 (second rule)
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Other tagged nodes: same pattern - tagged:80 + *:443
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.108.74.26/32",
|
|
|
|
|
|
"100.74.60.128/32",
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"100.90.199.68/32",
|
|
|
|
|
|
"100.94.92.91/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::2d01:c747/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::2f01:3c9c/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::b901:4a87/128",
|
|
|
|
|
|
"fd7a:115c:a1e0::ef01:5c81/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.37: Multiple wildcard src rules
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// Rules with same SrcIPs going to the same node are MERGED
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "multiple_wildcard_src_rules_14_37",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["tag:database:5432"]},
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["*:80"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// tagged-server: receives rule 1 (:22) and rule 3 (:80) - MERGED
|
2026-01-23 19:36:17 +00:00
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
2026-01-24 07:49:39 +00:00
|
|
|
|
// tagged-db: receives rule 2 (:5432) and rule 3 (:80) - MERGED
|
2026-01-23 19:36:17 +00:00
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.38: Wildcard dest + specific dest
|
|
|
|
|
|
// TODO: Tailscale subsumes specific into wildcard (1 entry), Headscale creates 2 separate entries
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_dest_plus_specific_dest_14_38",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["*:*"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
// tagged-client: receives only wildcard (tag:server:22 doesn't apply to tagged-client)
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-server: receives both wildcard and specific (specific is subset)
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRangeAny},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.40: Wildcard in different positions
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "wildcard_in_different_positions_14_40",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["tag:server:22", "tag:database:5432"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80", "*:443"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
// user1: receives only *:443 from rule 2
|
|
|
|
|
|
"user1": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-server: receives wildcard:22 and tag:client:80 and tag:client:443
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}},
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-db: receives wildcard:5432 and tag:client:443
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
2026-01-23 20:52:35 +00:00
|
|
|
|
"100.64.0.0/10",
|
|
|
|
|
|
"fd7a:115c:a1e0::/48",
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-web: receives only tag:client:443
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-client: receives only tag:client:443
|
|
|
|
|
|
"tagged-client": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
2026-01-28 12:05:08 +00:00
|
|
|
|
{IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// Test 14.49: Same src → 5 dests (some overlap)
|
|
|
|
|
|
// TODO: Tailscale merges, Headscale creates separate entries but may deduplicate destinations
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "same_src_five_dests_overlap_14_49",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {"group:admins": ["kratail2tid@"]},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"],
|
|
|
|
|
|
"tag:database": ["kratail2tid@"],
|
|
|
|
|
|
"tag:web": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:database:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["tag:web:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["webserver:22"]},
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["database:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantFilters: map[string][]tailcfg.FilterRule{
|
|
|
|
|
|
"user1": nil,
|
|
|
|
|
|
"tagged-client": nil,
|
|
|
|
|
|
// tagged-server: receives rules 1 and 4 (tag:server:22 and webserver:22 resolve to same node)
|
|
|
|
|
|
// Note: Host alias (webserver) also resolves to both IPv4 and IPv6 when it matches a node
|
|
|
|
|
|
"tagged-server": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-db: receives rules 2 and 5 (tag:database:22 and database:22 resolve to same node)
|
|
|
|
|
|
"tagged-db": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// tagged-web: receives rule 3 only
|
|
|
|
|
|
"tagged-web": {
|
|
|
|
|
|
{
|
|
|
|
|
|
SrcIPs: []string{
|
|
|
|
|
|
"100.80.238.75/32",
|
|
|
|
|
|
"fd7a:115c:a1e0::7901:ee86/128",
|
|
|
|
|
|
},
|
|
|
|
|
|
DstPorts: []tailcfg.NetPortRange{
|
|
|
|
|
|
{IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
{IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
|
|
|
|
|
},
|
policy: add ICMP protocols to default and export constants
When ACL rules don't specify a protocol, Headscale now defaults to
[TCP, UDP, ICMP, ICMPv6] instead of just [TCP, UDP], matching
Tailscale's behavior.
Also export protocol number constants (ProtocolTCP, ProtocolUDP, etc.)
for use in external test packages, renaming the string protocol
constants to ProtoNameTCP, ProtoNameUDP, etc. to avoid conflicts.
This resolves 78 ICMP-related TODOs in the Tailscale compatibility
tests, reducing the total from 165 to 87.
Updates #3036
2026-01-23 20:16:02 +00:00
|
|
|
|
IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP},
|
2026-01-23 19:36:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
pol, err := unmarshalPolicy([]byte(tt.policy))
|
|
|
|
|
|
require.NoError(t, err, "failed to parse policy")
|
|
|
|
|
|
|
|
|
|
|
|
err = pol.validate()
|
|
|
|
|
|
require.NoError(t, err, "policy validation failed")
|
|
|
|
|
|
|
|
|
|
|
|
for nodeName, wantFilters := range tt.wantFilters {
|
|
|
|
|
|
node := findNodeByGivenName(nodes, nodeName)
|
|
|
|
|
|
require.NotNil(t, node, "node %s not found", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Get compiled filters for this specific node
|
|
|
|
|
|
compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice())
|
|
|
|
|
|
require.NoError(t, err, "failed to compile filters for node %s", nodeName)
|
|
|
|
|
|
|
|
|
|
|
|
// Reduce to only rules where this node is a destination
|
|
|
|
|
|
gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters)
|
|
|
|
|
|
|
|
|
|
|
|
if len(wantFilters) == 0 && len(gotFilters) == 0 {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" {
|
|
|
|
|
|
t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TestTailscaleCompatErrorCases tests ACL configurations that should produce validation errors.
|
|
|
|
|
|
// These tests verify that Headscale correctly rejects invalid policies, matching Tailscale's behavior
|
|
|
|
|
|
// where the coordination server rejects the policy at update time (400 Bad Request).
|
|
|
|
|
|
//
|
|
|
|
|
|
// Reference: /home/kradalby/acl-explore/findings/09-mixed-scenarios.md.
|
|
|
|
|
|
func TestTailscaleCompatErrorCases(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
|
name string
|
|
|
|
|
|
policy string
|
|
|
|
|
|
wantErr string
|
|
|
|
|
|
reference string // Test case reference from findings
|
|
|
|
|
|
}{
|
|
|
|
|
|
// Test 6.4: tag:nonexistent → tag:server:22 (ERROR)
|
|
|
|
|
|
// Tailscale error: "src=tag not found: \"tag:nonexistent\" (400)"
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "undefined_tag_source_6_4",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:nonexistent"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
2026-02-06 21:45:32 +01:00
|
|
|
|
wantErr: `tag not defined in policy: "tag:nonexistent"`,
|
2026-01-23 19:36:17 +00:00
|
|
|
|
reference: "Test 6.4: tag:nonexistent → tag:server:22",
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Test 13.41: autogroup:self as SOURCE (ERROR)
|
|
|
|
|
|
// Tailscale error: "\"autogroup:self\" not valid on the src side of a rule (400)"
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "self_as_source_13_41",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:self"], "dst": ["tag:server:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
2026-02-06 21:45:32 +01:00
|
|
|
|
wantErr: `autogroup:self can only be used in ACL destinations`,
|
2026-01-23 19:36:17 +00:00
|
|
|
|
reference: "Test 13.41: autogroup:self as SOURCE",
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Test 13.43: autogroup:self without port (ERROR)
|
|
|
|
|
|
// Tailscale error: "dst=\"autogroup:self\": port range \"self\": invalid first integer (400)"
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "self_without_port_13_43",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["*"], "dst": ["autogroup:self"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
wantErr: `invalid port number`,
|
|
|
|
|
|
reference: "Test 13.43: autogroup:self without port",
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
|
|
pol, err := unmarshalPolicy([]byte(tt.policy))
|
|
|
|
|
|
// Check for parsing errors (some errors occur at parse time)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
require.ErrorContains(t, err, tt.wantErr,
|
|
|
|
|
|
"test %s (%s): expected parse error containing %q, got %q",
|
|
|
|
|
|
tt.name, tt.reference, tt.wantErr, err.Error())
|
|
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check for validation errors
|
|
|
|
|
|
err = pol.validate()
|
|
|
|
|
|
require.Error(t, err, "test %s (%s): expected validation error, got none", tt.name, tt.reference)
|
|
|
|
|
|
require.ErrorContains(t, err, tt.wantErr,
|
|
|
|
|
|
"test %s (%s): expected error containing %q, got %q",
|
|
|
|
|
|
tt.name, tt.reference, tt.wantErr, err.Error())
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// TestTailscaleCompatErrorCasesHeadscaleDiffers validates that Headscale correctly rejects
|
|
|
|
|
|
// policies that Tailscale also rejects. These tests verify that autogroup:self destination
|
|
|
|
|
|
// validation for ACL rules matches Tailscale's behavior.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
//
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// Tailscale validates that autogroup:self can only be used when ALL sources are
|
|
|
|
|
|
// users, groups, or autogroup:member. Headscale now performs this same validation.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
//
|
|
|
|
|
|
// Reference: /home/kradalby/acl-explore/findings/09-mixed-scenarios.md.
|
|
|
|
|
|
func TestTailscaleCompatErrorCasesHeadscaleDiffers(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// These tests verify that Headscale rejects policies the same way Tailscale does.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
// Tailscale rejects these policies at validation time (400 Bad Request),
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// and Headscale now does the same.
|
2026-01-23 19:36:17 +00:00
|
|
|
|
tests := []struct {
|
|
|
|
|
|
name string
|
|
|
|
|
|
policy string
|
2026-01-23 20:37:27 +00:00
|
|
|
|
tailscaleError string // What Tailscale returns (and Headscale should match)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
reference string
|
|
|
|
|
|
}{
|
|
|
|
|
|
// Test 2.5: tag:client → autogroup:self:* + tag:server:22
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// Tailscale REJECTS this - autogroup:self requires user/group sources
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "tag_source_with_self_dest_2_5",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"],
|
|
|
|
|
|
"tag:client": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["autogroup:self:*", "tag:server:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)",
|
|
|
|
|
|
reference: "Test 2.5: tag:client → autogroup:self:* + tag:server:22",
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Test 4.5: tag:client → autogroup:self:*
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// Tailscale REJECTS this - autogroup:self requires user/group sources
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "tag_source_to_self_dest_only_4_5",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:client": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["autogroup:self:*"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)",
|
|
|
|
|
|
reference: "Test 4.5: tag:client → autogroup:self:*",
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Test 6.1: autogroup:tagged → autogroup:self:*
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// Tailscale REJECTS this - autogroup:tagged is NOT a valid source for autogroup:self
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_tagged_to_self_6_1",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:tagged"], "dst": ["autogroup:self:*"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)",
|
|
|
|
|
|
reference: "Test 6.1: autogroup:tagged → autogroup:self:*",
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Test 9.5: [autogroup:member, autogroup:tagged] → [autogroup:self:*, tag:server:22]
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// Tailscale REJECTS this - ANY invalid source (autogroup:tagged) invalidates the rule
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "both_autogroups_to_self_plus_tag_9_5",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "autogroup:tagged"], "dst": ["autogroup:self:*", "tag:server:22"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)",
|
|
|
|
|
|
reference: "Test 9.5: [autogroup:member, autogroup:tagged] → [autogroup:self:*, tag:server:22]",
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Test 13.6: autogroup:tagged → self:*
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// Tailscale REJECTS this - same as 6.1
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "autogroup_tagged_to_self_13_6",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:tagged"], "dst": ["autogroup:self:*"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)",
|
|
|
|
|
|
reference: "Test 13.6: autogroup:tagged → self:*",
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Test 13.10: tag:client → self:*
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// Tailscale REJECTS this - tags are not valid sources for autogroup:self
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "tag_to_self_13_10",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:client": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["tag:client"], "dst": ["autogroup:self:*"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)",
|
|
|
|
|
|
reference: "Test 13.10: tag:client → self:*",
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Test 13.13: Host → self:*
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// Tailscale REJECTS this - hosts are not valid sources for autogroup:self
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "host_to_self_13_13",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"hosts": {
|
|
|
|
|
|
"webserver": "100.108.74.26"
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["webserver"], "dst": ["autogroup:self:*"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)",
|
|
|
|
|
|
reference: "Test 13.13: Host → self:*",
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Test 13.14: Raw IP → self:*
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// Tailscale REJECTS this - raw IPs are not valid sources for autogroup:self
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "raw_ip_to_self_13_14",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:server": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["100.90.199.68"], "dst": ["autogroup:self:*"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)",
|
|
|
|
|
|
reference: "Test 13.14: Raw IP (user1) → self:*",
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Test 13.25: [autogroup:member, tag:client] → self:*
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// Tailscale REJECTS this - ANY invalid source (tag:client) invalidates the rule
|
2026-01-23 19:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "mixed_valid_invalid_sources_to_self_13_25",
|
|
|
|
|
|
policy: `{
|
|
|
|
|
|
"groups": {
|
|
|
|
|
|
"group:admins": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"tagOwners": {
|
|
|
|
|
|
"tag:client": ["kratail2tid@"]
|
|
|
|
|
|
},
|
|
|
|
|
|
"acls": [
|
|
|
|
|
|
{"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["autogroup:self:*"]}
|
|
|
|
|
|
]
|
|
|
|
|
|
}`,
|
|
|
|
|
|
tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)",
|
|
|
|
|
|
reference: "Test 13.25: [autogroup:member, tag:client] → self:*",
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
2026-01-23 20:37:27 +00:00
|
|
|
|
// unmarshalPolicy calls validate() internally, so we expect it to fail
|
|
|
|
|
|
// with our validation error
|
|
|
|
|
|
_, err := unmarshalPolicy([]byte(tt.policy))
|
|
|
|
|
|
require.Error(t, err,
|
|
|
|
|
|
"test %s (%s): should reject policy like Tailscale",
|
|
|
|
|
|
tt.name, tt.reference)
|
|
|
|
|
|
require.ErrorIs(t, err, ErrACLAutogroupSelfInvalidSource,
|
|
|
|
|
|
"test %s (%s): expected autogroup:self validation error",
|
|
|
|
|
|
tt.name, tt.reference)
|
2026-01-23 19:36:17 +00:00
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|