Tailscale 的 ACL 是在一个零信任网络中, 基于 “最小权限” 原则, 实现网络层访问控制的声明式策略系统 (概念回顾见 1.介绍)
它的核心思想: 在默认所有连接都被禁止的前提下, 管理员通过一份明确的规则清单, 精准宣告 “谁” 可以访问 “什么”
- 默认拒绝: 没有对应 accept 规则的连接都会被直接丢弃
- 注意: 新建 tailnet 的初始策略文件自带一条
*→*:*的 accept, 等于全放行. 动手改 ACL 前先删掉它
- 注意: 新建 tailnet 的初始策略文件自带一条
- 网络层控制: 只关心来源、端口、协议、目标, 不关心具体数据内容
- 有向性: 配置 A→B, 不代表自动允许 B→A
- 本地强制执行: 策略文件会同步给每一个设备, 设备在本地执行这些规则
- 不影响局域网: 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:internet | dst | 经 exit node 访问公网, 给 exit node 授权用 |
autogroup:self | dst | 用户自己的设备 |
autogroup:owner | src、dst、tagOwners、autoApprovers | tailnet owner |
autogroup:admin | src、dst、tagOwners、autoApprovers | 管理员角色的用户 |
autogroup:member | src、dst、tagOwners、autoApprovers | tailnet 的直接成员 (包括邀请的用户), 不包括共享设备用户 |
autogroup:tagged | src、dst、tagOwners、autoApprovers | 被打了 tag 的设备 |
autogroup:shared | src | 接受了设备共享邀请的外部用户, 不是 tailnet 成员 |
tag
-
定义标签及标签所有者 (仅标签所有者可以使用该标签)
{ "tagOwners": { "tag:server": ["[email protected]"], "tag:infrastructure": [], // No tag owners defined } }- 只有 dave 能给设备打
tag:server这个标签 []表示没有具名 owner, 默认只有 Owner/Admin/Network Admin 能用
- 只有 dave 能给设备打
-
给设备添加标签
- 在管理控制台配置
- 通过 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