Configuring Tailscale ACLs and network policies

Access control lists (ACLs) restrict who can access which nodes on your network.

This feature is still experimental and will later be expanded to support more advanced policy definitions. We welcome comments about how users would like this to work.

Currently, ACLs can be defined in a static configuration file on each relaynode. The default location for this file is /etc/tailscale/acl.json. Each relaynode is responsible for enforcing its own ACLs. See below for a sample ACL file.

Each section in the ACL file defines a rule that governs access by users (or groups of users, as defined by email addresses) to resources (as defined by IP addresses, hostnames, and port ranges). Each rule contains the following fields:

  • Action: (required, string). One of:

    • accept As implied, an “accept” rule will permit connections between the specified users and resources.
    • eject This rule will force Tailscale to reject connections between the specified users and resources. (Not currently supported).
  • Users: (required, array). One or more of:

    • Email addresses (eg. ["a@example.com", "b@example.com"]);
    • Roles (eg. ["role:User", "role:Admin"]);
    • Wildcards are supported (eg. ["*"]).
  • Ports: (required, array). One or more of:

    • IP addresses & ports (eg. ["10.1.2.3:465", "10.1.2.3:443"]);
    • Wildcards are supported (eg. ["*:22", "10.1.2.3:*"])
  • MachineAuth: (optional, array, not currently supported). One or more of:

    • unauthorized match devices that are unauthorized;
    • expired match devices that have had their authorization expire;
    • authorized match authorized devices (default if this rule is unspecified).

Roles

As implied above, users can be assigned one or more roles. At present, roles are defined on the coordination server by Tailscale as customers need them. In the future, Tailscale will support roles defined in Active Directory and other IAM providers.

Sample ACL File

{
  "ACLs": [
    {
        "Action": "accept",
        // Match any of several users
        "Users": ["a@example.com", "b@example.com"],
        // Match any port on 100.2.2.2, and port 22 of 10.1.2.3
        "Ports": ["100.2.2.2:*", "10.1.2.3:22"]
    },
    {
        "Action": "accept",
        // Match any user at all
        "Users": ["*"],
        // Match two specific ports
        "Ports": ["100.2.2.2:80", "10.8.8.8:53"]
    },
    {
        "Action": "accept",
        // Match all users in the "Admin" role (network administrators)
        "Users": ["role:Admin"],
        // Allow access to port 22 on all servers
        "Ports": ["*:22"]
    },
    {
        "Action": "accept",
        "Users": ["role:User"],
        // Match only windows and linux workstations (not implemented yet)
        "OS": ["windows", "linux"],
        // Only desktop machines are allowed to access this server
        "Ports": ["10.1.1.1:443"]
    },
    {
        "Action": "accept",
        "Users": ["*"],
        // Match machines which have never been authorized, or which expired.
        // (not implemented yet)
        "MachineAuth": ["unauthorized", "expired"],
        // Logged-in users on unauthorized machines can access the email server.
        // Open the TLS ports for SMTP, IMAP, and HTTP.
        "Ports": ["10.1.2.3:465", "10.1.2.3:993", "10.1.2.3:443"]
    },
    // Match absolutely everything. Comment out this section if you want
    // the above ACLs to apply.
    { "Action": "accept", "Users": ["*"], "Ports": ["*:*"] },
    // Leave this line here so that every rule can end in a comma.
    // It has no effect since it has no matching rules.
    { "Action": "accept" }
  ]
}

Last updated