mirror of
https://github.com/juanfont/headscale.git
synced 2025-11-20 17:56:02 -05:00
Filter exit routes through ACL policy to fix issue #2788
Exit nodes are now only visible to nodes that have permission to use them according to ACL policy. Previously, exit routes (0.0.0.0/0 and ::/0) were unconditionally added to the AllowedIPs field in the network map, making exit nodes visible to all peers regardless of policy. Changes: - Modified buildTailPeers and WithSelfNode in builder.go to filter exit routes through policy.ReduceRoutes, same as primary routes - Removed unconditional addition of exit routes in tail.go tailNode function - Updated tail_test.go to reflect new behavior where exit routes are filtered The fix ensures that exit nodes are only visible when a node has autogroup:internet in their ACL destination rules. Co-authored-by: kradalby <98431+kradalby@users.noreply.github.com>
This commit is contained in:
@@ -79,7 +79,23 @@ func (b *MapResponseBuilder) WithSelfNode() *MapResponseBuilder {
|
|||||||
tailnode, err := tailNode(
|
tailnode, err := tailNode(
|
||||||
nv, b.capVer, b.mapper.state,
|
nv, b.capVer, b.mapper.state,
|
||||||
func(id types.NodeID) []netip.Prefix {
|
func(id types.NodeID) []netip.Prefix {
|
||||||
return policy.ReduceRoutes(nv, b.mapper.state.GetNodePrimaryRoutes(id), matchers)
|
// Get the peer node to check for exit routes
|
||||||
|
peer, ok := b.mapper.state.GetNodeByID(id)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start with primary routes (subnet routes, but not exit routes)
|
||||||
|
routes := policy.ReduceRoutes(nv, b.mapper.state.GetNodePrimaryRoutes(id), matchers)
|
||||||
|
|
||||||
|
// Also filter exit routes through policy
|
||||||
|
// Only add exit routes if the viewing node (self in this case) has permission to use them
|
||||||
|
if exitRoutes := peer.ExitRoutes(); len(exitRoutes) > 0 {
|
||||||
|
filteredExitRoutes := policy.ReduceRoutes(nv, exitRoutes, matchers)
|
||||||
|
routes = append(routes, filteredExitRoutes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return routes
|
||||||
},
|
},
|
||||||
b.mapper.cfg)
|
b.mapper.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -254,7 +270,23 @@ func (b *MapResponseBuilder) buildTailPeers(peers views.Slice[types.NodeView]) (
|
|||||||
tailPeers, err := tailNodes(
|
tailPeers, err := tailNodes(
|
||||||
changedViews, b.capVer, b.mapper.state,
|
changedViews, b.capVer, b.mapper.state,
|
||||||
func(id types.NodeID) []netip.Prefix {
|
func(id types.NodeID) []netip.Prefix {
|
||||||
return policy.ReduceRoutes(node, b.mapper.state.GetNodePrimaryRoutes(id), matchers)
|
// Get the peer node to check for exit routes
|
||||||
|
peer, ok := b.mapper.state.GetNodeByID(id)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start with primary routes (subnet routes, but not exit routes)
|
||||||
|
routes := policy.ReduceRoutes(node, b.mapper.state.GetNodePrimaryRoutes(id), matchers)
|
||||||
|
|
||||||
|
// Also filter exit routes through policy
|
||||||
|
// Only add exit routes if the viewing node has permission to use them
|
||||||
|
if exitRoutes := peer.ExitRoutes(); len(exitRoutes) > 0 {
|
||||||
|
filteredExitRoutes := policy.ReduceRoutes(node, exitRoutes, matchers)
|
||||||
|
routes = append(routes, filteredExitRoutes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return routes
|
||||||
},
|
},
|
||||||
b.mapper.cfg)
|
b.mapper.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -88,9 +88,9 @@ func tailNode(
|
|||||||
}
|
}
|
||||||
tags = lo.Uniq(tags)
|
tags = lo.Uniq(tags)
|
||||||
|
|
||||||
|
// Get filtered routes (includes both primary routes and exit routes if allowed by policy)
|
||||||
routes := primaryRouteFunc(node.ID())
|
routes := primaryRouteFunc(node.ID())
|
||||||
allowed := append(addrs, routes...)
|
allowed := append(addrs, routes...)
|
||||||
allowed = append(allowed, node.ExitRoutes()...)
|
|
||||||
tsaddr.SortPrefixes(allowed)
|
tsaddr.SortPrefixes(allowed)
|
||||||
|
|
||||||
tNode := tailcfg.Node{
|
tNode := tailcfg.Node{
|
||||||
|
|||||||
@@ -137,10 +137,8 @@ func TestTailNode(t *testing.T) {
|
|||||||
),
|
),
|
||||||
Addresses: []netip.Prefix{netip.MustParsePrefix("100.64.0.1/32")},
|
Addresses: []netip.Prefix{netip.MustParsePrefix("100.64.0.1/32")},
|
||||||
AllowedIPs: []netip.Prefix{
|
AllowedIPs: []netip.Prefix{
|
||||||
tsaddr.AllIPv4(),
|
|
||||||
netip.MustParsePrefix("192.168.0.0/24"),
|
netip.MustParsePrefix("192.168.0.0/24"),
|
||||||
netip.MustParsePrefix("100.64.0.1/32"),
|
netip.MustParsePrefix("100.64.0.1/32"),
|
||||||
tsaddr.AllIPv6(),
|
|
||||||
},
|
},
|
||||||
PrimaryRoutes: []netip.Prefix{
|
PrimaryRoutes: []netip.Prefix{
|
||||||
netip.MustParsePrefix("192.168.0.0/24"),
|
netip.MustParsePrefix("192.168.0.0/24"),
|
||||||
|
|||||||
Reference in New Issue
Block a user