Skip to content

Commit d810597

Browse files
authored
policy/matcher: fix bug using contains instead of overlap (#2556)
* policy/matcher: slices.ContainsFunc Signed-off-by: Kristoffer Dalby <[email protected]> * policy/matcher: slices.ContainsFunc, correct contains vs overlap Signed-off-by: Kristoffer Dalby <[email protected]> * policy: add tests to validate fix for 2181 Fixes #2181 Signed-off-by: Kristoffer Dalby <[email protected]> --------- Signed-off-by: Kristoffer Dalby <[email protected]>
1 parent 93afb03 commit d810597

File tree

2 files changed

+110
-30
lines changed

2 files changed

+110
-30
lines changed

hscontrol/policy/matcher/matcher.go

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package matcher
33
import (
44
"net/netip"
55

6+
"slices"
7+
68
"github.com/juanfont/headscale/hscontrol/util"
79
"go4.org/netipx"
810
"tailscale.com/tailcfg"
@@ -58,41 +60,17 @@ func MatchFromStrings(sources, destinations []string) Match {
5860
}
5961

6062
func (m *Match) SrcsContainsIPs(ips ...netip.Addr) bool {
61-
for _, ip := range ips {
62-
if m.srcs.Contains(ip) {
63-
return true
64-
}
65-
}
66-
67-
return false
63+
return slices.ContainsFunc(ips, m.srcs.Contains)
6864
}
6965

7066
func (m *Match) DestsContainsIP(ips ...netip.Addr) bool {
71-
for _, ip := range ips {
72-
if m.dests.Contains(ip) {
73-
return true
74-
}
75-
}
76-
77-
return false
67+
return slices.ContainsFunc(ips, m.dests.Contains)
7868
}
7969

8070
func (m *Match) SrcsOverlapsPrefixes(prefixes ...netip.Prefix) bool {
81-
for _, prefix := range prefixes {
82-
if m.srcs.ContainsPrefix(prefix) {
83-
return true
84-
}
85-
}
86-
87-
return false
71+
return slices.ContainsFunc(prefixes, m.srcs.OverlapsPrefix)
8872
}
8973

9074
func (m *Match) DestsOverlapsPrefixes(prefixes ...netip.Prefix) bool {
91-
for _, prefix := range prefixes {
92-
if m.dests.ContainsPrefix(prefix) {
93-
return true
94-
}
95-
}
96-
97-
return false
75+
return slices.ContainsFunc(prefixes, m.dests.OverlapsPrefix)
9876
}

hscontrol/policy/policy_test.go

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ package policy
22

33
import (
44
"fmt"
5-
"github.com/juanfont/headscale/hscontrol/policy/matcher"
65
"net/netip"
76
"testing"
87

8+
"github.com/juanfont/headscale/hscontrol/policy/matcher"
9+
910
"github.com/google/go-cmp/cmp"
1011
"github.com/juanfont/headscale/hscontrol/types"
1112
"github.com/juanfont/headscale/hscontrol/util"
@@ -1370,7 +1371,6 @@ func TestFilterNodesByACL(t *testing.T) {
13701371
},
13711372
},
13721373
},
1373-
13741374
{
13751375
name: "subnet-router-with-only-route",
13761376
args: args{
@@ -1422,6 +1422,108 @@ func TestFilterNodesByACL(t *testing.T) {
14221422
},
14231423
},
14241424
},
1425+
{
1426+
name: "subnet-router-with-only-route-smaller-mask-2181",
1427+
args: args{
1428+
nodes: []*types.Node{
1429+
{
1430+
ID: 1,
1431+
IPv4: ap("100.64.0.1"),
1432+
Hostname: "router",
1433+
User: types.User{Name: "router"},
1434+
Hostinfo: &tailcfg.Hostinfo{
1435+
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")},
1436+
},
1437+
ApprovedRoutes: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")},
1438+
},
1439+
{
1440+
ID: 2,
1441+
IPv4: ap("100.64.0.2"),
1442+
Hostname: "node",
1443+
User: types.User{Name: "node"},
1444+
},
1445+
},
1446+
rules: []tailcfg.FilterRule{
1447+
{
1448+
SrcIPs: []string{
1449+
"100.64.0.2/32",
1450+
},
1451+
DstPorts: []tailcfg.NetPortRange{
1452+
{IP: "10.99.0.2/32", Ports: tailcfg.PortRangeAny},
1453+
},
1454+
},
1455+
},
1456+
node: &types.Node{
1457+
ID: 1,
1458+
IPv4: ap("100.64.0.1"),
1459+
Hostname: "router",
1460+
User: types.User{Name: "router"},
1461+
Hostinfo: &tailcfg.Hostinfo{
1462+
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")},
1463+
},
1464+
ApprovedRoutes: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")},
1465+
},
1466+
},
1467+
want: []*types.Node{
1468+
{
1469+
ID: 2,
1470+
IPv4: ap("100.64.0.2"),
1471+
Hostname: "node",
1472+
User: types.User{Name: "node"},
1473+
},
1474+
},
1475+
},
1476+
{
1477+
name: "node-to-subnet-router-with-only-route-smaller-mask-2181",
1478+
args: args{
1479+
nodes: []*types.Node{
1480+
{
1481+
ID: 1,
1482+
IPv4: ap("100.64.0.1"),
1483+
Hostname: "router",
1484+
User: types.User{Name: "router"},
1485+
Hostinfo: &tailcfg.Hostinfo{
1486+
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")},
1487+
},
1488+
ApprovedRoutes: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")},
1489+
},
1490+
{
1491+
ID: 2,
1492+
IPv4: ap("100.64.0.2"),
1493+
Hostname: "node",
1494+
User: types.User{Name: "node"},
1495+
},
1496+
},
1497+
rules: []tailcfg.FilterRule{
1498+
{
1499+
SrcIPs: []string{
1500+
"100.64.0.2/32",
1501+
},
1502+
DstPorts: []tailcfg.NetPortRange{
1503+
{IP: "10.99.0.2/32", Ports: tailcfg.PortRangeAny},
1504+
},
1505+
},
1506+
},
1507+
node: &types.Node{
1508+
ID: 2,
1509+
IPv4: ap("100.64.0.2"),
1510+
Hostname: "node",
1511+
User: types.User{Name: "node"},
1512+
},
1513+
},
1514+
want: []*types.Node{
1515+
{
1516+
ID: 1,
1517+
IPv4: ap("100.64.0.1"),
1518+
Hostname: "router",
1519+
User: types.User{Name: "router"},
1520+
Hostinfo: &tailcfg.Hostinfo{
1521+
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")},
1522+
},
1523+
ApprovedRoutes: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")},
1524+
},
1525+
},
1526+
},
14251527
}
14261528

14271529
for _, tt := range tests {

0 commit comments

Comments
 (0)