Tailscale 的 ACL 是在一个零信任网络中, 基于 “最小权限” 原则, 实现网络层访问控制的声明式策略系统 (概念回顾见 1.介绍)

它的核心思想: 在默认所有连接都被禁止的前提下, 管理员通过一份明确的规则清单, 精准宣告 “谁” 可以访问 “什么”

  • 默认拒绝: 没有对应 accept 规则的连接都会被直接丢弃
    • 注意: 新建 tailnet 的初始策略文件自带一条 **:* 的 accept, 等于全放行. 动手改 ACL 前先删掉它
  • 网络层控制: 只关心来源、端口、协议、目标, 不关心具体数据内容
  • 有向性: 配置 AB, 不代表自动允许 BA
  • 本地强制执行: 策略文件会同步给每一个设备, 设备在本地执行这些规则
  • 不影响局域网: ACL 不影响设备对本地局域网的访问

核心组成

一份典型的 ACL 策略文件包含以下几个部分:

字段说明可选值
(Source)连接发起方特定用户、一组用户、特定设备、带标签的设备组
目标 (Destination)要访问的资源特定设备 IP、一个 IP 网段、带标签的设备组
端口/协议 (Port/Protocol)可以访问目标上的具体服务
动作 (Action)对该流量的处理方式accept(唯一动作)
{
  "acls": [
    {
      "action": "accept",
      "src": [ <list-of-sources> ],
      "dst": [ <destination>:<port> ],
      "proto": "tcp", // optional
    }
  ]
}
# src 示例:
 
# 任何源: *
# 特定用户: [email protected]
# 用户组: group:<group-name>
# autogroup: autogroup:<role|property>
# 特定 IP: <tailscale ip>
# 网段: 192.168.1.0/24
# tag: tag:<tag-name>
 
 
# dst 示例
# 同上, 可以额外设置端口
# 任意端口 *
# 单个端口 22
# 多个端口 80,443
# 端口范围 8000-8010

网段 / autogroup:internet 这两类目标分别依赖 subnet router / exit node, 见 3.subnet routers 与 exit node

groups

创建用户组 (注意: free plan 仅支持创建 3 个 group)

{
	"groups": {
	  "group:engineering": [
	    "[email protected]",
	    "[email protected]",
	  ],
	  "group:sales": [
	    "[email protected]",
	    "[email protected]",
	  ],
	},
}

autogroup

一种内置的特殊分组, 自动包含具有相同属性的用户

组名支持使用的位置介绍
autogroup:internetdst经 exit node 访问公网, 给 exit node 授权用
autogroup:selfdst用户自己的设备
autogroup:ownersrcdsttagOwnersautoApproverstailnet owner
autogroup:adminsrcdsttagOwnersautoApprovers管理员角色的用户
autogroup:membersrcdsttagOwnersautoApproverstailnet 的直接成员 (包括邀请的用户), 不包括共享设备用户
autogroup:taggedsrcdsttagOwnersautoApprovers被打了 tag 的设备
autogroup:sharedsrc接受了设备共享邀请的外部用户, 不是 tailnet 成员

tag

  1. 定义标签及标签所有者 (仅标签所有者可以使用该标签)

    {
      "tagOwners": {
        "tag:server": ["[email protected]"],
        "tag:infrastructure": [], // No tag owners defined
      }
    }
    • 只有 dave 能给设备打 tag:server 这个标签
    • [] 表示没有具名 owner, 默认只有 Owner/Admin/Network Admin 能用
  2. 给设备添加标签

    • 在管理控制台配置
    • 通过 CLI 配置: tailscale up --advertise-tags=tag:server
    • 通过 API 配置

注意: tag 与 user 互斥

tag 在 Tailscale 中不是一个额外的标签, 而是指代非人设备的身份, 和 [email protected] 这种用户身份是同一层级、互相替代的东西

一台 tagged 设备对外通信时, ACL 看到的身份是它身上的那组 tag, 而不是某个具体的人

  • 给设备打 tag, 会去掉这台设备上的 user 身份
  • 通过用户身份重新登录这台设备, 会清掉它上面所有 tag

一个 trick

给一个设备打标签后, 这个设备就没有 user 身份了, 也就意味着 autogroup:member / autogroup:self 里没有这台设备了 (autogroup:tagged 反而只包含它), 可以基于此配置一下独属于用户的规则

hosts

给 IP / 网段起别名, 在 src / dst 里用名字代替裸 IP

{
	"hosts": {
		"nas": "100.101.102.103",
		"home-lan": "192.168.1.0/24",
	},
	"acls": [
		{ 
			"action": "accept", 
			"src": ["group:engineering"], 
			"dst": ["nas:22", "home-lan:*"] 
		},
	],
}
  • 值只能是单个 IP 或 CIDR, 不能指向用户 / tag, 也不做 DNS 解析
  • 别名里不能有 @

tests

tests 类似于编程语言中的断言, 在每次策略文件更改时作为检查运行. 如果断言失败, 则拒绝更新策略文件, 并提示失败的用例

确保你不会意外撤销重要权限 / 暴露关键资源

{
	"tests": [
		{
			"src": "[email protected]",
			"proto": "tcp",
			"accept": ["tag:prod:22", "tag:dev:80"],
			"deny":   ["tag:prod:443"]
		},
		{ 
			"src": "tag:prod", 
			"deny": ["tag:dev:80"] 
		}
	]
}

从 alice 用户的设备出发, 对 tcp:

  • 可以连 tag:prod 的 22
  • 可以连 tag:dev 的 80
  • 不能连 tag:prod 的 443