Tailnet lock
Tailnet lock lets you verify that no node is added to your tailnet without being signed by trusted nodes in your tailnet. When tailnet lock is enabled, even if Tailscale infrastructure is malicious or hacked, attackers can’t send or receive traffic in your tailnet.
What is tailnet lock?
Tailnet lock lets you control which nodes are signed and verified by trusted nodes in your tailnet, meaning you don't need to trust the Tailscale coordination server for distributing public node keys to peer nodes in your tailnet. You can control which nodes are trusted to sign another node's public key.
How it works
To help understand the types of keys being discussed, each node has a node key, and a tailnet lock key.
-
The node key is a public/private key pair generated on a node by a Tailscale client. The coordination server ties the node key to a specific identity. The private key remains private on the node. The public key is transmitted to the coordination server.
-
The tailnet lock key, also a public/private key pair, is introduced by the tailnet lock feature. Every node generates a tailnet lock key, even if tailnet lock is not enabled. The private component of the tailnet lock key remains private on the node. The private key remains on the node.
Without tailnet lock, when a new node is added to the tailnet, its public node key is distributed to peer nodes by the Tailscale coordination server. If Tailscale were malicious, and stealthily inserted new nodes into your network, then Tailscale could send or receive traffic to your existing nodes in plaintext.
With tailnet lock, when a new node is added to the tailnet, its public node key requires a signature from a tailnet lock key. The coordination server distributes the signed public node key to peer nodes in the tailnet. Peer nodes can then verify the signature before allowing connections. In this manner, you control which nodes are trusted to be in your tailnet, as well as which nodes are trusted to sign other nodes.
Disablement secrets
When you enable tailnet lock, you create disablement secrets. A disablement secret is required if you want to disable tailnet lock.
Disabling tailnet lock is a security-relevant operation—if the disablement procedure lacked authorization checks, a compromised coordination server could trivially disable tailnet lock (and all its protections) to attack a tailnet as if tailnet lock wasn't running. To avoid this, use of a disablement secret is required to globally disable tailnet lock.
If you generate a disablement secret for Tailscale support, then Tailscale can disable tailnet lock if needed, but not without being detected.
The disablement secrets are displayed only when you initialize tailnet lock. Ensure that you securely store them. Some options include using your organization's secure storage like a password manager, or printing them and storing them in a secure safe.
Tailnet key authority
To determine which tailnet lock keys to trust, nodes implement a new subsystem, the tailnet key authority, to track and update the set of tailnet lock keys that can be used to sign node keys. You specify the initial set of trusted lock keys when you enable tailnet lock. You can add or remove keys to change the set of trusted tailnet lock keys. The coordination server publishes the set of trusted tailnet lock keys across your tailnet.
Enable tailnet lock
You need to be an Owner, Admin, or IT admin of a tailnet in order to enable tailnet lock.
Tailnet lock is not enabled by default. When tailnet lock is enabled, all existing nodes in the tailnet are signed.
Ensure the nodes that you want to lock with tailnet lock are running Tailscale v1.46.1 or later.
Enabling tailnet lock requires using the tailscale lock init
command. Use the Tailscale admin console to make it easier to create the tailscale lock init
command values.
- Open the Device management page of the admin console.
- Select Enable tailnet lock.
- In the Add signing nodes section, select Add signing node.
- Select the nodes whose tailnet lock keys you want to trust. You must select at least two signing nodes.
- In the Configure disablement options section, specify whether to send a disablement secret to Tailscale support. By default, Send disablement secret to Tailscale support is enabled, and we recommend you keep this option enabled. This option will create an extra disablement secret that is automatically transmitted to Tailscale support. This way, Tailscale support could disable tailnet lock in case of an issue with how we’ve implemented tailnet lock.
- In the Run command from signing node section, copy the
tailscale lock init
command. - Open a terminal window on one of the signing nodes you selected.
- Paste in the
tailscale lock init
command that you copied from the admin console and press Enter.
When you run the tailscale lock init
command that was provided by the admin console, 10 disablement secrets are displayed. Only a single disablement is needed to disable tailnet lock, not all 10, although 10 are generated. Make note of the disablement secrets that are displayed in the output. The disablement secrets are long passwords needed to disable your tailnet lock. For more information about disablement secrets, see tailscale lock disable
.
The disablement secrets are displayed only when you initialize tailnet lock. Ensure that you securely store them. Some options include using your organization's secure storage like a password manager, or printing them and storing them in a secure safe.
After tailscale lock init
completes successfully:
- All existing nodes in the tailnet are signed by the trusted tailnet lock keys.
- The set of trusted tailnet lock keys is distributed to the existing nodes.
- Nodes verify the signature of a peer's node key before allowing a connection.
- All new node keys must be signed by an existing tailnet lock key.
Disable tailnet lock
You need to be an Owner, Admin, or IT admin of a tailnet in order to disable tailnet lock.
Run the tailscale lock disable
command, specifying a disablement secret that you stored securely when you enabled tailnet lock.
tailscale lock disable <disablement-secret>
Once the specified disablement secret is used, it has been distributed to all nodes in the tailnet and should be considered public.
If tailnet lock is re-enabled, for example, by running the tailscale lock init
command again, new disablement secrets will be generated.
If you encounter a significant issue with tailnet lock for your entire tailnet and can’t disable it via the Device management page (for example, if you can’t locate your disablement secret), you could run the tailscale lock local-disable
command on each of your nodes to make your tailnet in effect ignore tailnet lock. For details, see tailscale lock local-disable
.
Add a node to a locked tailnet
If you have already enabled tailnet lock and want to add an additional node, you need to sign the node key for the node to be added.
You have two options to add a node:
- Use a Tailscale client app signing link. This is possible only for macOS, Windows, and iOS. We are working on Android.
- Use the
tailscale lock sign
command, which is part of the Tailscale CLI. This is possible only for Linux, macOS, and Windows.
Both options require access to the Tailscale admin console, because retrieving information for the node key to add is possible only through the Machines page of the admin console.
Use a client app to add a node
- Open the Machines page of the admin console.
- Select the node that needs to be signed. Look for the Locked out badge in the machines list, or use the
property:locked-out
filter to see all devices that are locked out. - Select Sign node.
- In the Sign node dialog, you have 3 tabs to choose from, to add the node.
-
In the Desktop tab, if you are on a macOS or Windows device that is a signing node, select Sign this node. Otherwise, select Copy signing URL, send the URL to a signing node, and open the URL on the signing node. Either process opens the Tailscale client and lets you add the node.
-
In the Mobile tab, if you are on a iOS device that is a signing node, scan the QR code to open the Tailscale client, then add the node. Alternatively, select Copy signing URL, send the URL to a signing node, and open the URL on the signing node. Either process opens the Tailscale client and lets you add the node.
Using a QR code to add a node is currently supported only on iOS devices.
-
In the CLI tab, select the Copy icon to copy the
tailscale lock sign
command. Run the command on a signing node to add the node.
-
Use the CLI to add a node
Use the tailscale lock sign
command to add a node:
tailscale lock sign nodekey:1abddef1 tlpub:abcdef12
nodekey:1abddef1
is the node key for the node to be added. tlpub:abcdef12
is an optional tailnet lock key for a trusted signing node, to use for key rotation.
You can determine the tailscale lock sign
command either using the admin console or using the Tailscale CLI.
To determine the tailscale lock sign
command using the admin console:
- Open the Machines page of the admin console.
- Select the node that needs to be signed. Look for the Locked out badge in the machines list, or use the
property:locked-out
filter to see all devices that are locked out. - Select Sign node.
- Select CLI.
- Copy the
tailscale lock sign
command needed to sign the node. - Run the command on a signing node to add the node.
Alternatively, to determine the tailscale lock sign
command using the Tailscale CLI:
-
On the node that you want to add to your tailnet, run:
tailscale lock status
-
In the output of
tailnet lock status
, copy thetailscale lock sign
command needed to sign the node.
Then, on a node with a trusted tailnet lock key, run the command you copied in the previous step:
tailscale lock sign nodekey:<your-node-key> tlpub:<your-tailnet-lock-key>
When a signed node key expires, the new node key will not need to be re-signed. When the user re-authenticates, the node's signature will be automatically rotated, by signing the new node key with the node's tailnet lock key.
Add a node using a pre-signed auth key
Signing an auth key lets you add devices to your locked tailnet using pre-signed auth keys, so that you don't need to add the node and then sign its node key.
-
Generate a pre-approved auth key.
-
On a node with a trusted tailnet lock key, set an environment variable,
AUTH_KEY
, to the value of the auth key:export AUTH_KEY="tskey-auth-XXXXCTRL-NNNNNN"
-
Sign the auth key by running the
tailscale lock sign
command:tailscale lock sign $AUTH_KEY
-
Use the new key that is generated by the
tailscale lock sign
command to pre-approve devices in your tailnet.
Determine a node's tailnet lock public key
For some tailnet lock operations, you need to know a node's tailnet lock public key. This is not the same as a node's Tailscale public key, which is of the form nodekey:abcdef12
. A node's tailnet lock public key is of the form tlpub:abcdef12.
Determining the tailnet lock public key by using the CLI
To determine a node's tailnet lock public key using the Tailscale CLI, which is possible only for Linux, macOS, and Windows:
- Run
tailscale lock status
. The command displays the tailnet lock public key for the node.
Determining the tailnet lock public key by using the admin console
To determine a node's tailnet lock public key using the admin console:
-
Open the Machines page.
-
Select the node whose tailnet lock public key you want to determine.
-
In the Machine Details section, look for Tailnet lock key. If you do not see Tailnet lock key within the UI, then tailnet lock is not enabled for the tailnet.
-
Select Copy to copy the key to your clipboard.
Determining the tailnet lock public key by using the client
Add a signing node
-
Determine the tailnet lock public key for the node you want to add as a signing node.
-
On a node with a trusted tailnet lock key, run the
tailscale lock add
command, passing in the tailnet lock keys that you determined in the previous step.This examples adds two signing nodes:
tailscale lock add tlpub:trusted-key1, tlpub:trusted-key2
Remove a signing node
This command needs to be run from a node with a trusted tailnet lock key.
-
If you don't already have the tailnet lock public key for each node you want to remove as a signing node, determine the tailnet lock public key.
-
On a node with a trusted tailnet lock key, run the
tailscale lock remove
command, passing in the tailnet lock keys that you determined in the previous step.This example removes two signing nodes:
tailscale lock remove tlpub:trusted-key7 tlpub:trusted-key8
When you remove a signing node Node-B by running tailscale lock remove
on node Node-A, by default all nodes previously signed by Node-B are re-signed with Node-A's key. You can disable this by passing in --re-sign=false
to the tailscale lock remove
command.
Revoke a compromised signing node
If a signing node is compromised, revoke the compromised key by running the tailscale lock revoke-keys
command. Revoked keys are prevented from being used in the future. Any nodes that were previously signed by a revoked key lose their authorization and must be signed again.
If you want to remove a key that has not been compromised, use the tailscale lock remove
command instead.
Revocation is a multi-step process that requires several signing nodes to co-sign the revocation. Each step uses the tailscale lock revoke-keys
command.
-
Open a terminal on a signing node that does not have a compromised key.
-
Run the following command, where
tlpub:compromised-key1 tlpub:compromised-key2
is a space-separated list of the keys that you want to revoke:tailscale lock revoke-keys tlpub:compromised-key1 tlpub:compromised-key2
The output of this command contains a
tailscale lock revoke-keys --cosign
command, which you will use in the next step. -
On another trusted signing node, run the
tailscale lock revoke-keys --cosign
command. The output of this command contains a newtailscale lock revoke-keys --cosign
command. Repeat this process, always using the new output from each--cosign
command, until the number of times you used--cosign
exceeds the number of revoked keys. For example, if you revoked 3 keys, you need to run thetailscale lock revoke-keys --cosign
command 4 times. -
Finish the process by running the command that was output from the last use of
--cosign
except replace--cosign
with--finish
:tailscale lock revoke-keys --finish <hex-data>
By default, Tailscale will determine the appropriate point in the tailnet lock log to fork. If more signing nodes agree that a key should be revoked than not, then the keys in the fork that Tailscale determined to still be trusted are then used instead of the revoked keys.
If the majority of signing nodes are compromised, you can disable and then re-enable tailnet lock itself.
How tailnet lock works with other Tailscale features
Take the following into consideration for how tailnet lock works with other Tailscale features.
Sharing
To use tailnet lock with the sharing feature, a node shared into a tailnet with tailnet lock will need to also be signed to be accessible.
Tailscale SSH Console
You can use Tailscale SSH Console to establish an SSH session for a signed node in your tailnet, provided:
- your tailnet policy file permits network access.
- a Tailscale SSH rule permits SSH access.
Configuration audit logging
Enabling, disabling, or modifying tailnet lock configuration creates events that will appear in the configuration audit logs.
Independent of configuration audit logging, you can run the tailscale lock log
command on a node to see recent changes to your tailnet lock.
Limitations
- You need to securely store the disablement secrets yourself. If you lose disablement secrets, and you did not provide one to Tailscale support, the tailnet cannot be recovered.
- You cannot enable both tailnet lock and device approval—they are mutually exclusive features.
- Tailnet lock keys are stored on the device. If the device is compromised, the key can be obtained.
- You cannot use an Android device as a signing node, because it cannot be used for signing operations. This is being worked on.