Device approval #634

Closed
opened 2025-12-29 02:21:26 +01:00 by adam · 9 comments
Owner

Originally created by @SinghNanak on GitHub (Feb 15, 2024).

Why

I don't want unauthorized devices connecting to my network.

Description

https://tailscale.com/kb/1099/device-approval

Originally created by @SinghNanak on GitHub (Feb 15, 2024). <!-- We typically have a clear roadmap for what we want to improve and reserve the right to close feature requests that does not fit in the roadmap, or fit with the scope of the project, or we actually want to implement ourselves. Headscale is a multinational community across the globe. Our language is English. All bug reports needs to be in English. --> ## Why <!-- Include the reason, why you would need the feature. E.g. what problem does it solve? Or which workflow is currently frustrating and will be improved by this? --> I don't want unauthorized devices connecting to my network. ## Description <!-- A clear and precise description of what new or changed feature you want. --> https://tailscale.com/kb/1099/device-approval
adam added the enhancementstale labels 2025-12-29 02:21:26 +01:00
adam closed this issue 2025-12-29 02:21:26 +01:00
Author
Owner

@lennartbrandin commented on GitHub (Feb 16, 2024):

What is the usecase instead of just keeping default login (your keys / node registration) secure?

@lennartbrandin commented on GitHub (Feb 16, 2024): What is the usecase instead of just keeping default login (your keys / node registration) secure?
Author
Owner

@SinghNanak commented on GitHub (Feb 16, 2024):

It helps when there are multiple users and devices.

@SinghNanak commented on GitHub (Feb 16, 2024): It helps when there are multiple users and devices.
Author
Owner

@adriangoransson commented on GitHub (Mar 8, 2024):

I agree that this would be helpful to enable OIDC for user management but still approve every new device key manually. For example if the connected oidc account were to be compromised.

@adriangoransson commented on GitHub (Mar 8, 2024): I agree that this would be helpful to enable OIDC for user management but still approve every new device key manually. For example if the connected oidc account were to be compromised.
Author
Owner

@adriangoransson commented on GitHub (Mar 8, 2024):

I forgot that ACLs and tags are kind of powerful, so it is possible to work around this limitation.

# Allow all traffic from all nodes tagged with "tag:device-approved".
acls:
  - action: accept
    src:
      - tag:device-approved
    dst:
      - "*:*"

# Tags must be owned. An autogroup seemed appropriate.
https://tailscale.com/kb/1337/acl-syntax#autogroups
tagOwners:
  tag:device-approved:
    - autogroup:owner

Approve a new device with

headscale nodes tag -i <ID> -t tag:device-approved

Where you get <ID> from headscale nodes ls [-u <user>].

@adriangoransson commented on GitHub (Mar 8, 2024): I forgot that ACLs and tags are kind of powerful, so it is possible to work around this limitation. ```yaml # Allow all traffic from all nodes tagged with "tag:device-approved". acls: - action: accept src: - tag:device-approved dst: - "*:*" # Tags must be owned. An autogroup seemed appropriate. https://tailscale.com/kb/1337/acl-syntax#autogroups tagOwners: tag:device-approved: - autogroup:owner ``` Approve a new device with ```sh headscale nodes tag -i <ID> -t tag:device-approved ``` Where you get `<ID>` from `headscale nodes ls [-u <user>]`.
Author
Owner

@dmitryroshchin commented on GitHub (Mar 20, 2024):

That work fine, but if we have the following acl:

{
      "action": "accept",
      "src": [
        "group:boss"
      ],
      "dst": [
        "ec2-router-test.internal:80"
      ]
    }

how could we combine it with tag:device-approved?

I've managed to achieve it by using additional acl, which allows access to my subnet routers:

 {
      "action": "accept",
      "src": [
        "tag:device-approved"
      ],
      "dst": [
        "100.64.0.0/24:0"
      ]
    }

But are there any other options to make acl src based on group and tag simultaneously?

@dmitryroshchin commented on GitHub (Mar 20, 2024): That work fine, but if we have the following acl: ``` { "action": "accept", "src": [ "group:boss" ], "dst": [ "ec2-router-test.internal:80" ] } ``` how could we combine it with **tag:device-approved**? I've managed to achieve it by using additional acl, which allows access to my subnet routers: ``` { "action": "accept", "src": [ "tag:device-approved" ], "dst": [ "100.64.0.0/24:0" ] } ``` But are there any other options to make acl src based on group and tag simultaneously?
Author
Owner

@adriangoransson commented on GitHub (Mar 21, 2024):

@dmitryroshchin I don't think you can combine multiple conditions, but I would be happy to be proved wrong!

I've solved it similarly to how you have done it, by limiting access to subnet routers using tag:device-approved, and then by having further restrictions on the exposed subnets with tags and groups. So it's not a complete workaround, but it works for this specific case. :)

@adriangoransson commented on GitHub (Mar 21, 2024): @dmitryroshchin I don't think you can combine multiple conditions, but I would be happy to be proved wrong! I've solved it similarly to how you have done it, by limiting access to subnet routers using `tag:device-approved`, and then by having further restrictions on the exposed subnets with tags and groups. So it's not a complete workaround, but it works for this specific case. :)
Author
Owner

@adriangoransson commented on GitHub (May 29, 2024):

FYI: If I understand correctly, my method of doing this mentioned above has the caveat that node keys will never expire.

Key expiry for a tagged device is disabled by default. If you change the tags on the device via the admin console, Tailscale CLI, or Tailscale API, the device’s key expiry will not change unless you are asked to re-authenticate. That is, if it is enabled, it stays enabled; and if it is disabled, it stays disabled. Once you re-authenticate, the device’s key expiry will be disabled.

From https://tailscale.com/kb/1085/auth-keys?q=pre#key-expiry

I might be wrong, but it is an important security aspect to consider! ⚠️


edit: I might be wrong actually. It looks like the expiration field is set correctly for my manually tagged nodes.

$ headscale nodes list
ID | Hostname                   | Name                       | [...] | User              | [...] | Ephemeral | Last seen           | Expiration          | Online  | Expired
14 | tailscale-578ff55bb4-zj4zw | tailscale-578ff55bb4-zj4zw | [...] | pod-node          | [...] | true      | 2024-05-30 07:38:13 | 0001-01-01 00:00:00 | online  | no
15 | tailscale-578ff55bb4-hml8p | tailscale-578ff55bb4-hml8p | [...] | pod-node          | [...] | true      | 2024-05-30 07:38:22 | 0001-01-01 00:00:00 | online  | no
16 | localhost                  | <redacted>                 | [...] | <redacted>        | [...] | false     | 2024-05-17 15:14:38 | 2024-11-11 14:39:32 | offline | no
@adriangoransson commented on GitHub (May 29, 2024): FYI: If I understand correctly, my method of doing this mentioned above has the caveat that node keys will never expire. > Key expiry for a [tagged](https://tailscale.com/kb/1068/acl-tags#generate-an-auth-key-with-an-acl-tag) device is disabled by default. If you change the tags on the device via the admin console, [Tailscale CLI](https://tailscale.com/kb/1080/cli), or [Tailscale API](https://tailscale.com/kb/1101/api), the device’s key expiry will not change unless you are asked to re-authenticate. That is, if it is enabled, it stays enabled; and if it is disabled, it stays disabled. Once you re-authenticate, the device’s key expiry will be disabled. From https://tailscale.com/kb/1085/auth-keys?q=pre#key-expiry I might be wrong, but it is an important security aspect to consider! ⚠️ --- edit: I might be wrong actually. It looks like the expiration field is set correctly for my manually tagged nodes. ```sh $ headscale nodes list ID | Hostname | Name | [...] | User | [...] | Ephemeral | Last seen | Expiration | Online | Expired 14 | tailscale-578ff55bb4-zj4zw | tailscale-578ff55bb4-zj4zw | [...] | pod-node | [...] | true | 2024-05-30 07:38:13 | 0001-01-01 00:00:00 | online | no 15 | tailscale-578ff55bb4-hml8p | tailscale-578ff55bb4-hml8p | [...] | pod-node | [...] | true | 2024-05-30 07:38:22 | 0001-01-01 00:00:00 | online | no 16 | localhost | <redacted> | [...] | <redacted> | [...] | false | 2024-05-17 15:14:38 | 2024-11-11 14:39:32 | offline | no ```
Author
Owner

@github-actions[bot] commented on GitHub (Aug 29, 2024):

This issue is stale because it has been open for 90 days with no activity.

@github-actions[bot] commented on GitHub (Aug 29, 2024): This issue is stale because it has been open for 90 days with no activity.
Author
Owner

@github-actions[bot] commented on GitHub (Sep 5, 2024):

This issue was closed because it has been inactive for 14 days since being marked as stale.

@github-actions[bot] commented on GitHub (Sep 5, 2024): This issue was closed because it has been inactive for 14 days since being marked as stale.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/headscale#634