Network access controls (ACLs)
Tailscale supports network access control lists (ACLs). ACLs let you precisely define what a particular user or device is permitted to access on your Tailscale network (known as a tailnet).
You need to be an Owner, Admin, or Network admin to edit the tailnet policy file.
Introduction
When you first create your tailnet, the ACL is in its default configuration, which allows all devices within the tailnet to communicate with one another. You can edit this rule at any point to restrict communication between devices, either by using the Access Controls page of the admin console, GitOps for Tailscale ACLs, or the Tailscale API. Tailscale’s default ACL does not affect what a device can or cannot access on its own local network.
Tailscale will prevent communication between devices not explicitly defined by an allow rule in the ACL. This is why the default ACL configuration in a new tailnet allows all devices in the tailnet to reach one another. Otherwise, an immediate step in creating a new tailnet would be to configure access policies while adding your first devices.
Access rules can make use of groups to grant access to many users with few rules. Similarly, you can use tags to assign purpose-based identities to devices to further scale up your policies. Combined, groups and tags let you build powerful role-based access control (RBAC) policies. Depending on your definition, server tagging could also be considered a form of attribute-based access control (ABAC).
The access rules you define for your network get distributed to all the devices in your network, and enforcement of the rules happens on each device directly, without further involvement from Tailscale’s servers.
If you’d like to learn more about Tailscale’s approach to access control in general, we’ve written a detailed blog post that goes deep into the history of access control systems, and why we designed Tailscale’s access rules the way we did.
Tailscale policy syntax
Tailscale access control rules are expressed as a single “human JSON” tailnet policy file. HuJSON is a superset of JSON that allows comments and trailing commas. This makes a tailnet policy file easy to maintain while staying read/writable by both humans and machines.
For cases that are less complex, you can edit the tailnet policy file by hand in the Access Controls page of the admin console. You can also use GitOps for Tailscale ACLs to update the tailnet policy file. Organizations with more complex needs can use the Tailscale API to automatically update rules from software.
The tailnet policy file has several top-level sections relating to ACLs, which we explore in detail below:
acls
, the access rules themselves.groups
, collections of users, to avoid repeating yourself in access rules.hosts
, human readable shorthands for IP addresses.tests
, which let you check the behavior of ACLs and avoid accidentally breaking an important permission.tagOwners
, to define which users can assign tags to a device.autoApprovers
, to define which users can advertise routes or exit nodes without further approval.ssh
, to define which users can establish a Tailscale SSH connection on which devices, and as which SSH users.nodeAttrs
, to define which devices can use certain features.
The tailnet policy file also contains network-wide policy settings unrelated
to access control: derpMap
, disableIPv4
, and randomizeClientPort
are documented in the Network policy options section of this
article, for completeness.
An example tailnet policy file:
{
"acls": [
// dave@tailscale.com can access everything on host vega (defined below)
{
"action": "accept",
"src": ["dave@tailscale.com"],
"dst": ["vega:*"],
},
// The security group can access all HTTPS servers, and everything on
// the corp network.
{
"action": "accept",
"src": ["group:security"],
"dst": [
"*:443",
"corp-network:*"
],
},
// The employees group can access web apps over HTTP.
{
"action": "accept",
"src": ["group:employees"],
"proto": "tcp",
"dst": ["tag:webapps:80"],
},
// Only allow IP protocol 16 (CHAOS) to security
{
"action": "accept",
"src": ["group:employees"],
"proto": "16",
"dst": ["group:security:*"],
},
// Both dave@tailscale.com and the security group can access lab devices.
{
"action": "accept",
"src": ["dave@tailscale.com", "group:security"],
"dst": ["tag:lab:*"],
},
// All lab devices can talk to each other, but nothing else.
{
"action": "accept",
"src": ["tag:lab"],
"dst": ["tag:lab:*"],
},
// Devices authenticated as the same user can talk to each other on port 22.
{
"action": "accept",
"src": ["*"],
"dst": ["autogroup:self:22"],
},
],
// Readable shorthands for devices and networks.
"hosts": {
"vega": "100.3.4.5",
"corp-network": "10.0.0.0/8",
"critical-corp-server": "10.0.0.1",
},
// Role-based groups of users.
"groups": {
"group:security": [
"laura@tailscale.com",
"daniel@tailscale.com",
],
"group:employees": [
"dave@tailscale.com",
"laura@tailscale.com",
"daniel@tailscale.com",
"alice@tailscale.com",
"bob@tailscale.com",
],
},
"tests": [
// Security can always access HTTPS on vega, but not HTTP.
{
"src": "group:security",
"accept": ["vega:443"],
"deny": ["vega:80"],
},
// dave@tailscale.com can SSH into vega and the lab.
{
"src": "dave@tailscale.com",
"accept": ["vega:22", "tag:lab:22"],
},
// Lab devices can never access a critical corp service.
{
"src": "tag:lab",
"deny": ["critical-corp-server:80"],
},
],
"tagOwners": {
"tag:lab": ["dave@tailscale.com"],
"tag:security": ["group:security"],
"tag:webapps": ["dave@tailscale.com"]
},
"autoApprovers": {
// Alice can create subnet routers advertising routes in 10.0.0.0/24 that are auto-approved
"routes": {
"10.0.0.0/24": ["alice@tailscale.com"],
},
// A device tagged security can advertise exit nodes that are auto-approved
"exitNode": ["tag:security"],
},
"ssh": [
{
// All users can SSH to their own devices, as non-root
"action": "accept",
"src": ["autogroup:member"],
"dst": ["autogroup:self"],
"users": ["autogroup:nonroot"]
}
],
"derpMap": {
"regions": {
"900": {
"regionID": 900,
"hostName": "custom-derp.example.com",
},
},
},
"disableIPv4": false,
"randomizeClientPort": false,
}
Previewing changes
When editing the tailnet policy file in the Access Controls page of the admin console, you can preview the permissions granted to your users.
To do so, open the Preview rules tab and select a user from the dropdown. A list of destinations (one per line) accessible to the specified user is shown, as well the line number that defines that rule. It also includes any other users/groups that can access that destination due to that rule.

Another way to increase confidence in your changes is to define some ACL tests, to check that your changes don’t accidentally remove access to an important system, or accidentally open up access wider than you intended.
ACL rules
The acls
section of the tailnet policy file is a list of access rules for
your network. Each rule is a HuJSON object that grants
access from a set of sources to a set of destinations.
All rules eventually boil down to allowing traffic from a particular source IP address to a destination IP address and port. While you can write rules that reference IP addresses directly, it’s more common to use higher-level specifiers like usernames and groups, which Tailscale automatically translates to the right low-level rules.
Each access rule looks like this:
{
"action": "accept",
"src": [ list-of-sources... ],
"proto": "protocol", // optional
"dst": [ list-of-destinations... ],
}
users
and ports
, instead of src
and dst
, respectively. While both sets of
terms are currently supported, we are using src
and dst
going forward.Tailscale access rules are “default deny”, so the only possible
action
is accept
, to allow traffic that would otherwise be denied.
The src
field specifies a list of sources to which the rule
applies. Each element in the list can be one of the following:
Type | Example | Meaning |
---|---|---|
Any | * | No restriction on the source |
User | shreya@example.com | All devices currently signed in as the given user |
Group (ref) | group:example | Same as listing every user in the group explicitly |
Tailscale IP | 100.101.102.103 | Only the device that owns the given Tailscale IP. IPv6 addresses must follow the format [1:2:3::4]:80 . |
Subnet CIDR Range (ref) | 192.168.1.0/24 | Any IP within the given subnet |
Hosts (ref) | my-host | Looks up the Tailscale IP or CIDR in the hosts section |
Tags (ref) | tag:production | All devices currently tagged with the given tag |
Autogroups (ref) | autogroup:member | Devices of users, destinations, or usernames with the same properties or roles |
The proto
field is optional, and specifies the protocol to which the rule applies. (If no protocol is specified, then the ACL rule applies to all TCP and UDP traffic.)
A proto
field can only be included in an ACL rule for Tailscale version v1.18.2 or later. Older clients will fail closed, blocking traffic for ACL rules with protocols, unless it is otherwise allowed.
If traffic is allowed for a given pair of IPs, then ICMP will also be allowed.
proto
can be specified as either an IANA IP protocol number 1-255 (e.g., "16"
) or one of the following named aliases (e.g., "sctp"
):
Protocol | proto |
IANA protocol number |
---|---|---|
Internet Group Management (IGMP) | igmp |
2 |
IPv4 encapsulation | ipv4 , ip-in-ip |
4 |
Transmission Control (TCP) | tcp |
6 |
Exterior Gateway Protocol (EGP) | egp |
8 |
Any private interior gateway | igp |
9 |
User Datagram (UDP) | udp |
17 |
Generic Routing Encapsulation (GRE) | gre |
47 |
Encap Security Payload (ESP) | esp |
50 |
Authentication Header (AH) | ah |
51 |
Stream Control Transmission Protocol (SCTP) | sctp |
132 |
Only TCP, UDP, and SCTP traffic support specifying ports. For all other protocols, the port specified needs to be *
.
The dst
field specifies a list of destination devices and ports to
which the rule applies. Each element in the list is of the form
host:ports
. host
is one of the following:
Type | Example | Meaning |
---|---|---|
Any | * | No restriction on the destination |
User | shreya@example.com | Any device currently signed in as the given user |
Group (ref) | group:example | Same as listing every user in the group explicitly |
Tailscale IP | 100.101.102.103 | Only the device that owns the given Tailscale IP |
Hosts (ref) | my-host | Looks up the Tailscale IP in the hosts section |
Subnet CIDR Range (ref) | 192.168.1.0/24 | Any IP within the given subnet |
Tags (ref) | tag:production | Any device currently tagged with the given tag |
Internet access (ref) | autogroup:internet | Access to the internet through exit nodes |
Own devices | autogroup:self | Access to devices where the same user is authenticated on both the src and the dst . This does not include devices the user has ACL tags. |
Tailnet devices | autogroup:member | Access to devices on the tailnet where the user is a direct member (not a shared user) of the tailnet |
Admin devices | autogroup:admin | Access to devices where the user is an Admin |
Network admin devices | autogroup:network-admin | Access to devices where the user is a Network admin |
IT admin devices | autogroup:it-admin | Access to devices where the user is an IT admin |
Billing admin devices | autogroup:billing-admin | Access to devices where the user is a Billing admin |
Auditor devices | autogroup:auditor | Access to devices where the user is an Auditor |
Owner devices | autogroup:owner | Access to devices where the user is the tailnet Owner |
ports
is one of the following:
Type | Example |
---|---|
Any | * |
Single | 22 |
Multiple | 80,443 |
Range | 1000-2000 |
Users
Users can be specified in both the source (src
) and destination
(dst
) fields of an access rule. Users must be referenced using the
full email address they use to sign into Tailscale.
username@github
. For example, the GitHub user alice
should be
written as alice@github
.Referencing an external user in an access rule does not implicitly grant them access to your Tailscale network. However, if you’ve shared a device with someone outside your Tailscale network, you can use their Tailscale login email in ACLs to further restrict what they can access on the shared device.
Groups
The groups
section lets you define a shorthand for a group of users,
which you can then use in ACL rules instead of listing users out
explicitly. Any change you make to the membership of a group is
automatically propagated to all the rules that reference that group.
A groups
definition looks like this:
"groups": {
"group:engineering": [
"dave@example.com",
"laura@example.com",
],
"group:sales": [
"brad@example.com",
"alice@example.com",
],
},
Every group name must start with the prefix group:
. Each member of a
group is specified by their full email address, as explained in the
users section above. To avoid the risk of obfuscating group
membership, groups cannot contain other groups.
You can edit only groups that are defined in ACLs. That is, while you can use groups that are synced from a System for Cross-domain Identity Management (SCIM) integration or tailnet autogroups, you cannot edit them.
You can add or remove a user’s group membership by editing the tailnet policy file, as
shown in the example groups
definition above, and directly from the Users page of the admin console.
Editing a user’s group membership from the Users page
You need to be an Owner, Admin, or Network admin to edit a user’s group membership from the Users page, same as for editing ACLs in general.
- Open the Users page in the admin console.
- Find the user by name.
- Click the
menu and then click Edit group membership.
- In the Edit group membership dialog:
- To add a group, click Add to a group and select the group to add.
- To remove a group, click the X next to the group to delete.
- When you are done editing the groups for the user, click Save.
Autogroups
An autogroup is a special group that automatically includes users, destinations, or usernames with the same properties, which you can then use in access rules.
Where allowed | Autogroup | Meaning | Availability by plan |
---|---|---|---|
As a dst |
autogroup:internet | Used to allow access for any user through any exit node in your tailnet. You cannot restrict access to only some exit nodes. | Available on all plans |
autogroup:self | Used to allow access for any user that is authenticated as the same user as the source. Does not apply to tags. | ||
As a src or dst , tagOwner , or autoApprover |
autogroup:owner | Used to allow access for the tailnet Owner. | Available on all plans |
autogroup:admin | Used to allow access for any user who has the role of Admin. | ||
autogroup:member | Used to allow access for any user who is a direct member (including all invited users) of the tailnet. Users from shared nodes are not included. | ||
autogroup:tagged | Used to allow access for any node which is tagged. | ||
autogroup:auditor | Used to allow access for any user who has the role of Auditor. | Available on the Free, Premium, and Enterprise plans | |
autogroup:billing-admin | Used to allow access for any user who has the role of Billing admin. | ||
autogroup:it-admin | Used to allow access for any user who has the role of IT admin. | ||
autogroup:network-admin | Used to allow access for any user who has the role of Network admin. | ||
As a src |
autogroup:shared | Used to allow access for any user who accepted a sharing invitation to your network. This lets you write rules without knowing sharee email addresses in advance. | Available on all plans |
As an SSH user | autogroup:nonroot | Used to allow Tailscale SSH access to any user that is not root . |
Available on the Free, Premium, and Enterprise plans |
autogroup:self
only applies to user-owned nodes, not also tagged nodes. You cannot use autogroup:self
with autogroup:tagged
.autogroup:members
instead of autogroup:member
. While both are currently supported, we are using autogroup:member
going forward. You cannot use both autogroup:member
and autogroup:members
in the same tailnet policy file.Here’s an example ssh
rule that allows all users to have Tailscale SSH access to their own devices, as non-root:
"ssh": [
{
// All users can SSH to their own devices, as non-root
"action": "accept",
"src": ["autogroup:member"],
"dst": ["autogroup:self"],
"users": ["autogroup:nonroot"]
}
Important note about autogroup:nonroot
In the default ACL, the ssh
rule uses autogroup:self
for the dst
field and
autogroup:nonroot
in the users
field. If you change the dst
field from
autogroup:self
to some other destination, such as an ACL tag,
also consider replacing autogroup:nonroot
in the users
field. If you don't remove
autogroup:nonroot
from the users
field, then anyone permitted by the src
setting
will be able to SSH in as any nonroot user on the dst
device.
Hosts
The hosts
section lets you define a human-friendly name for an IP
address or CIDR range, to make access rules more readable.
A hosts
definition looks like this:
"hosts": {
"example-host-1": "100.100.100.100",
"example-network-1": "100.100.101.100/24",
},
The human-friendly name cannot include the character @
.
Tests
The tests
section lets you write assertions about your access rules,
which are checked whenever the tailnet policy file is changed. Failing
assertions cause the new tailnet policy file to be rejected, with an error
detailing which test assertion wasn’t met.
Just like writing tests for software, ACL tests let you ensure that an important permission isn’t accidentally revoked later on, or that a critical system in your network isn’t exposed more than expected.
A tests
definition looks like this:
"tests": [
{
"src": "dave@example.com",
"accept": ["example-host-1:22", "vega:80"],
"deny": ["1.2.3.4:443"],
},
],
The src
field specifies the user identity being tested, which can be a
user’s email address, a group, an ACL tag, or a host that maps to an IP address.
The test case will be run from the perspective of a device signed in as that user, with that group membership,
with that tag, or as that host, respectively.
The accept
and deny
fields specify destinations that the ACL rules
should accept or deny, respectively.
allow
, instead of accept
, in ACL tests. While both terms are currently
supported, we are using accept
going forward.Each destination in the list is of the form host:port
, where port
is a single numeric port and
host
is one of the following:
Type | Example | Meaning |
---|---|---|
Tailscale IP | 100.101.102.103 | The Tailscale IP of the device. IPv6 addresses must follow the format [1:2:3::4]:80 . |
Hosts (ref) | my-host | Looks up the Tailscale IP in the hosts section |
User | shreya@example.com | The Tailscale IP of a device currently signed in as the given user |
Group | group:security@example.com | The Tailscale IP of a device currently signed in as a representative member of the given group |
Tags (ref) | tag:production | The Tailscale IP of a device currently tagged with the given tag |
Protocols cannot yet be included in ACL tests.
Sources in src
and destinations in accept
and deny
must refer to specific
entities and do not support *
wildcards. For example, an accept
destination cannot be tags:*
.
Tag Owners
The tagOwners
section of the tailnet policy file defines the tags that can
be applied to devices, and the list of users who are allowed to assign
each tag.
Tags are a substitute for a human identity on a device. That is, rather than a device being authenticated as a particular user, the device’s identity on the Tailscale network is the set of tags assigned to it. You can learn more in our article on server role accounts with ACL tags.
A tagOwners
definition looks like this:
"tagOwners": {
"tag:webserver": [
"group:engineering",
],
"tag:secure-server": [
"group:security-admins",
"president@example.com",
],
"tag:corp": [
"autogroup:member",
],
}
Every tag name must start with the prefix tag:
. A tag owner
can be a user’s full login email address (as defined in the users
section above), a group name, or an autogroup.
A shorthand notation, []
, is available for autogroup:admin
. That is, the following are equivalent:
"tag:monitoring": [
"autogroup:admin",
],
"tag:monitoring": [
"[]",
],
autogroup:admin
and autogroup:network-admin
can assign any tags, so []
implicitly means that
only autogroup:admin
and autogroup:network-admin
are allowed.
Auto Approvers for routes and exit nodes
The autoApprovers
section of the tailnet policy file defines the list of
users who can perform certain actions without requiring further approval from the admin console. This includes advertising a specified set of routes as a subnet router or advertising an exit node. For routes, this also permits the auto approvers to advertise a subnet of the specified routes.
An Owner, Admin, or Network admin can still disable the route or exit node from the admin console. To avoid the same route being advertised and auto-approved again, consider modifying autoApprovers
.
If the device is re-authenticated by a different user who cannot advertise the route or exit node, or the user who advertised it is suspended or deleted, the route or exit node is no longer advertised. To avoid this, consider making an ACL tag an auto approver.
An autoApprovers
definition looks like this:
"autoApprovers": {
"routes": {
"10.0.0.0/24": ["group:engineering", "alice@example.com", "tag:foo"],
},
"exitNode": ["tag:bar"],
}
The auto approver of a route or exit node can be a user’s full login email address (as defined in the users section above), a group name, an autogroup or a tag.
Tailscale SSH
The ssh
section of the tailnet policy file defines the lists of users and devices that can use Tailscale SSH,
and as which SSH users. For a connection to be permitted, the tailnet policy file must contain rules permitting both network
access and SSH access:
- An access rule to allow connections from the source to the destination on port 22.
- An SSH access rule to allow connections from the source to the destination and the given SSH users. This is used for Tailscale SSH, to distribute keys for authenticating SSH connections.
An ssh
definition looks like this:
{
"action": "check", // "accept" or "check"
"src": [ list-of-sources... ],
"dst": [ list-of-destinations... ],
"users": [ list-of-ssh-users... ],
"checkPeriod": "20h", // optional, only for check actions. default 12h
},
The action
field specifies whether to accept the connection or to perform additional checks on it.
The src
field is the source where a connection originates from. This can be a user, group, autogroup:member
, or autogroup:tagged
.
The dst
field is the destination where the connection goes. This can be a user, tag, or autogroup. Note that unlike ACLs, a port cannot be specified. Only port 22
is allowed, and does not need to be specified as it is used by default.
The users
field is the set of allowed usernames on the host. An SSH rule can also specify autogroup:nonroot
to allow any user that is not root
. If no user
is specified, Tailscale will use the local host’s user. That is, if you are logged in as alice
locally, then SSH to
another device, Tailscale SSH will try to log in as user alice
. Like other SSH clients, Tailscale will only use user accounts that already exist on the host, not create new accounts.
Optionally, for check mode only, the checkPeriod
field is the time period for which to allow a connection before requiring a check. This can be specified in
minutes or hours, with a minimum of one minute and a maximum of 168 hours (one week). If not specified, this is 12 hours. You may also specify "always"
to require check mode on every connection. Choosing to always require check mode may cause unexpected behavior from automation tools that open many SSH connections in a short time span, like Ansible.
SSH access rules are evaluated considering the most restrictive policies first:
- Check policies
- Accept policies
For example, if you have an access rule allowing the user alice@example.com to access a resource with an accept
rule, and a rule allowing group:devops
which
alice@example.com belongs to, to access a resource with a check
rule, then the check
rule applies.
The only kinds of connections that are allowed are:
- From a user to their own devices, as any user including
root
. - From a user to a tagged device, as any user including
root
. - From a tagged device to another tagged device, for any tags. Note that an SSH access rule from a tagged device cannot be in check mode.
- From a user to a device that has been shared with them, as long as the destination host has Tailscale configured with SSH and the destination’s ACL allows the user to connect over SSH.
That is, the broadest policy allowed would be:
{
"acls": [
{
"action": "accept",
"src": ["*"],
"dst": ["*:*"]
}
],
"ssh": [
{
"action": "accept",
"src": ["autogroup:member"],
"dst": ["autogroup:self"],
"users": ["root", "autogroup:nonroot"]
},
{
"action": "accept",
"src": ["autogroup:member"],
"dst": ["tag:prod"],
"users": ["root", "autogroup:nonroot"]
},
{
"action": "accept",
"src": ["tag:logging"],
"dst": ["tag:prod"],
"users": ["root", "autogroup:nonroot"]
},
]
}
To allow a user to only SSH to their own devices, as non-root
:
{
"acls": [
{
"action": "accept",
"src": ["*"],
"dst": ["*:*"]
}
],
"ssh": [
{
"action": "accept",
"src": ["autogroup:member"],
"dst": ["autogroup:self"],
"users": ["autogroup:nonroot"]
}
]
}
To allow group:sre
to access devices in the production environment tagged tag:prod
:
{
"groups": {
"group:sre": ["alice@example.com", "bob@example.com"]
},
"acls": [
{
"action": "accept",
"src": ["group:sre"],
"dst": ["tag:prod:*"]
},
],
"ssh": [
{
"action": "accept",
"src": ["group:sre"],
"dst": ["tag:prod"],
"users": ["ubuntu", "root"],
},
]
"tagOwners": {
// users in group:sre can apply the tag tag:prod
"tag:prod": ["group:sre"]
}
}
Node attributes
The nodeAttrs
section of the tailnet policy file defines additional attributes that apply to certain devices in your tailnet. You can use this to set different NextDNS configurations for different devices in your tailnet.
A nodeAttrs
definition looks like this:
"nodeAttrs": [
{
"target": ["my-kid@my-home.com", "tag:server"],
"attr": [
"nextdns:abc123",
"nextdns:no-device-info",
],
},
],
The target
field specifies which nodes the attributes apply to. This can be a tag (tag:server
), user (alice@example.com
), group (group:kids
), or *
.
The attr
field specifies which attributes apply to those nodes. For this example, the attributes are:
nextdns:abc123
, for a NextDNS configurationabc123
. If this is used, the attribute overrides the global NextDNS configuration.nextdns:no-device-info
, to disable sending device metadata to NextDNS.
This example allows members of the tailnet to use Tailscale Funnel on their nodes:
"nodeAttrs": [
{
"target": ["autogroup:members"],
"attr": ["funnel"],
},
],
Network policy options
In addition to access rules, the tailnet policy file includes a few network-wide policy settings for specialized purposes. Most networks should never need to specify these.
The derpMap
section lets you add custom DERP
servers to your network, which your
devices will use as needed to relay traffic. You can also use this
section to disable the use of Tailscale-provided DERP servers, for
example to meet corporate compliance requirements. The derpMap
section is detailed in the article on running custom DERP
servers.
The disableIPv4
field, if set to true
, stops assigning Tailscale
IPv4 addresses to your devices. All devices in your network will
receive exclusively IPv6 Tailscale addresses, and devices that do not
support IPv6 (e.g. systems that have IPv6 disabled in the operating
system) will be unreachable. This option is intended for users who
have a pre-existing conflicting use of the 100.64.0.0/10
carrier-grade NAT address range.
The OneCGNATRoute
field controls the routes that Tailscale clients will generate.
Tailscale clients can have either:
- One large
100.64/10
route to avoid churn in the routing table as nodes go online and offline. (The churn is disruptive to Chromium-based browsers on macOS.) - Fine-grained /32 routes.
The possible values for OneCGNATRoute
are:
- An empty string or not provided: Use default heuristics for each platform.
- On macOS (for Tailscale v1.28 or later), Tailscale will prefer to add one large
100.64/10
route. Tailscale will not do this if there are other interfaces that also route IP addresses in that range. - On other platforms, Tailscale will add fine-grained /32 routes for each node.
- On macOS (for Tailscale v1.28 or later), Tailscale will prefer to add one large
"mac-always"
: macOS clients will always add one100.64/10
route."mac-never"
: macOS clients will always add fine-grained /32 routes.
The randomizeClientPort
field, if set to true
, makes devices
prefer a random port for WireGuard traffic over the default static
port 41641. This option is intended as a workaround for some buggy
firewall devices, and should only be enabled after consulting with
Tailscale (contact support).
Subnet routers and exit nodes
ACLs can only allow connections, not reject them. ACLs don’t limit discovery of routes. So, you can restrict access to a node separately from access to a subnet that node routes to, if it’s a subnet router; or public IP, if it’s an exit node.
To restrict access to a subnet, ensure that no ACL allows access to those routes. You can enforce this with a test, which will fail if any rule accidentally allows access, like so:
"tests": [
{
"src": "not-allowed@example.com",
"accept": ["100.101.102.103:22"], // allow access to the tailscale IP
"deny": ["192.168.0.7:22"], // does not allow access to the subnet
}
],
To restrict access to all exit nodes, only grant access to autogroup:internet
to those who you wish to use exit nodes. You can enforce this with a test, which will fail if any rule accidentally allows access to a public IP, like so:
"tests": [
{
"src": "not-allowed@example.com",
"accept": ["100.101.102.103:22"], // allow access to the tailscale IP
"deny": ["8.8.8.8:22"], // does not allow access to a public IP
}
],
Right now, there is no way to restrict use of specific exit nodes using ACLs. Subscribe to this GitHub issue for updates.
Taildrop precedence
Taildrop permits you to share files between devices that you are logged in to, even if ACLs are used to restrict access to the devices.
Debugging ACLs
To debug whether ACLs block communication between nodes, use tailscale ping
.
There are two types of ping checks that tailscale ping
can do: TSMP and ICMP.
TSMP pings check whether two nodes can establish a network connection, but
stops before the ACL check. Use tailscale ping --tsmp
to send a TSMP ping.
ICMP pings check the end-to-end connectivity between nodes, including ACLs.
Use tailscale ping --icmp
or regular ping
to send an ICMP ping.
If TSMP ping succeeds but ICMP ping fails, connections between nodes are likely blocked by ACLs. If TSMP ping fails, nodes cannot establish a network connection, even though ACLs may allow connections. If both TSMP and ICMP pings succeed but connections still fail, check the port numbers in your ACLs and services you are trying to connect to.
In addition to manual testing, built-in ACL tests ensure that specific connections are allowed and prevent ACL changes from accidentally breaking these connections.
Reverting ACLs
You can revert your tailnet policy file from a previous date and time, in the Configuration logs page of the admin console. For instruction, see Reverting ACLs from audit logs.
ACL availability by plan
Restrictions | Restricted use of ACLs | Full use of ACLs |
---|---|---|
Availability | Available on all plans | Available on the Free, Premium, and Enterprise plans |
Access rules for... |
|
|
Access rules specifying... |
|
|
ACL sections for... |
|
|