[Bug] Auto approve routes broken for tags #1054

Closed
opened 2025-12-29 02:27:59 +01:00 by adam · 3 comments
Owner

Originally created by @paragor on GitHub (Jul 3, 2025).

Is this a support request?

  • This is not a support request

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

ACL for autoApprove routes currently broken (and accept policy too actually, but i have good case for approveRoute).
Right now Headscale doesn't approve routes via acl's when tags are used.
And on engine v1 all works as expected.

Expected Behavior

Headscale approve routes via ACL policy.

Steps To Reproduce

Just go to 37dc0dad35/hscontrol/policy/route_approval_test.go (L147)
text of test

		{
			name:  "multiple-routes-in-policy",
			node:  normalNode,
			route: p("172.16.10.0/24"),
			policy: `{
				"tagOwners": {
					"tag:router": ["user3@"]
				},
				"groups": {
					"group:admin": ["user1@"]
				},
				"acls": [
					{"action": "accept", "src": ["group:admin"], "dst": ["*:*"]}
				],
				"autoApprovers": {
					"routes": {
						"192.168.0.0/16": ["group:admin"],
						"172.16.0.0/12": ["group:admin"],
						"10.0.0.0/8": ["tag:router"]
					}
				}
			}`,
			canApprove: true,
		},

and change

route: p("172.16.10.0/24") 
->
route: p("10.0.0.0/8"),

test will fail, but should pass

Environment

- Headscale version: v0.26.1

Runtime environment

  • Headscale is behind a (reverse) proxy
  • Headscale runs in a container

Debug information

Originally created by @paragor on GitHub (Jul 3, 2025). ### Is this a support request? - [x] This is not a support request ### Is there an existing issue for this? - [x] I have searched the existing issues ### Current Behavior ACL for autoApprove routes currently broken (and accept policy too actually, but i have good case for approveRoute). Right now Headscale doesn't approve routes via acl's when tags are used. And on engine v1 all works as expected. ### Expected Behavior Headscale approve routes via ACL policy. ### Steps To Reproduce Just go to https://github.com/juanfont/headscale/blob/37dc0dad3532ef3310e7cf32597b763d84b512ef/hscontrol/policy/route_approval_test.go#L147 text of test ``` { name: "multiple-routes-in-policy", node: normalNode, route: p("172.16.10.0/24"), policy: `{ "tagOwners": { "tag:router": ["user3@"] }, "groups": { "group:admin": ["user1@"] }, "acls": [ {"action": "accept", "src": ["group:admin"], "dst": ["*:*"]} ], "autoApprovers": { "routes": { "192.168.0.0/16": ["group:admin"], "172.16.0.0/12": ["group:admin"], "10.0.0.0/8": ["tag:router"] } } }`, canApprove: true, }, ``` and change ``` route: p("172.16.10.0/24") -> route: p("10.0.0.0/8"), ``` test will fail, but should pass ### Environment ```markdown - Headscale version: v0.26.1 ``` ### Runtime environment - [ ] Headscale is behind a (reverse) proxy - [ ] Headscale runs in a container ### Debug information -
adam added the bug label 2025-12-29 02:27:59 +01:00
adam closed this issue 2025-12-29 02:27:59 +01:00
Author
Owner

@mathieuruellan commented on GitHub (Oct 3, 2025):

Hello, Any news about this issue? Is it confirmed? Is there a workaround?
What should be the rule for a router with multi subnet? One string with subnet with coma seperator, or multi json attributes in the "routes" object (including 0.0.0.0/0)

My current issue:
the exit node advertises with the tag exitnode and the preauthkey has also a tag exitnode set.

Acl is

"autoApprovers": {
    "routes": {
      "0.0.0.0/0": ["tag:exitnode"],
      "::/0": ["tag:exitnode"],
      "192.168.0.0/16": ["tag:exitnode"], 
      "xxx:xx:xxx:xxxx::/64": ["tag:exitnode"]
    }  
  } 

The 0.0.0.0/0 and ::/0 are not auto approved, but 192. and ipv6 - private networks are.
Here is the result on new exit node :

ID | Hostname     | Approved                                             | Available                                            | Serving (Primary)                                       
32 | exit-node-sg | 192.168.0.0/16, xx:xx:xxx:xxxx::/64                  | 0.0.0.0/0, 192.168.0.0/16, ::/0, xx:xx:xxx:xxxx::/64 | 
@mathieuruellan commented on GitHub (Oct 3, 2025): Hello, Any news about this issue? Is it confirmed? Is there a workaround? What should be the rule for a router with multi subnet? One string with subnet with coma seperator, or multi json attributes in the "routes" object (including 0.0.0.0/0) My current issue: the exit node advertises with the tag exitnode and the preauthkey has also a tag exitnode set. Acl is ``` "autoApprovers": { "routes": { "0.0.0.0/0": ["tag:exitnode"], "::/0": ["tag:exitnode"], "192.168.0.0/16": ["tag:exitnode"], "xxx:xx:xxx:xxxx::/64": ["tag:exitnode"] } } ``` The 0.0.0.0/0 and ::/0 are not auto approved, but 192. and ipv6 - private networks are. Here is the result on new exit node : ``` ID | Hostname | Approved | Available | Serving (Primary) 32 | exit-node-sg | 192.168.0.0/16, xx:xx:xxx:xxxx::/64 | 0.0.0.0/0, 192.168.0.0/16, ::/0, xx:xx:xxx:xxxx::/64 | ```
Author
Owner

@nblock commented on GitHub (Oct 9, 2025):

Any news about this issue?

I cannot reproduce this on 0.26.1. The following works in my tests (tested with the linked docs):

Also the combination of both worked with this policy:

{
  "tagOwners": {
    "tag:exit": [
      "alice@"
    ],
    "tag:router": [
      "alice@"
    ]
  },
  "autoApprovers": {
    "exitNode": [
      "tag:exit"
    ],
    "routes": {
      "192.168.0.0/24": [
        "tag:router"
      ]
    }
  },
  "acls": [
    {
      "action": "accept",
      "src": [
        "*"
      ],
      "dst": [
        "*:*"
      ]
    }
  ]
}

Client: tailscale up --login-server https://headscale.example.com --advertise-tags tag:exit,tag:router --advertise-exit-node --advertise-routes 192.168.0.0/24

Headscale:

$ headscale node list-routes
ID | Hostname | Approved                        | Available                       | Serving (Primary)              
1  | n1       | 0.0.0.0/0, 192.168.0.0/24, ::/0 | 0.0.0.0/0, 192.168.0.0/24, ::/0 | 192.168.0.0/24, 0.0.0.0/0, ::/0
@nblock commented on GitHub (Oct 9, 2025): > Any news about this issue? I cannot reproduce this on 0.26.1. The following works in my tests (tested with the linked docs): - [Automatically approve routes of a subnet router](https://headscale.net/0.26.1/ref/routes/#automatically-approve-routes-of-a-subnet-router) - [Automatically approve an exit node with auto approvers](https://headscale.net/0.26.1/ref/routes/#automatically-approve-an-exit-node-with-auto-approvers) Also the combination of both worked with this policy: ```json { "tagOwners": { "tag:exit": [ "alice@" ], "tag:router": [ "alice@" ] }, "autoApprovers": { "exitNode": [ "tag:exit" ], "routes": { "192.168.0.0/24": [ "tag:router" ] } }, "acls": [ { "action": "accept", "src": [ "*" ], "dst": [ "*:*" ] } ] } ``` Client: `tailscale up --login-server https://headscale.example.com --advertise-tags tag:exit,tag:router --advertise-exit-node --advertise-routes 192.168.0.0/24` Headscale: ```console $ headscale node list-routes ID | Hostname | Approved | Available | Serving (Primary) 1 | n1 | 0.0.0.0/0, 192.168.0.0/24, ::/0 | 0.0.0.0/0, 192.168.0.0/24, ::/0 | 192.168.0.0/24, 0.0.0.0/0, ::/0 ```
Author
Owner

@mathieuruellan commented on GitHub (Oct 11, 2025):

@nblock I succeed to make it work! Just a typo in my advertise tags. Thanks a lot!

@mathieuruellan commented on GitHub (Oct 11, 2025): @nblock I succeed to make it work! Just a typo in my advertise tags. Thanks a lot!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/headscale#1054