Tailscale 私有网络实战:一条命令把所有设备安全地连进一张虚拟局域网


设备多了以后,绕不开一个朴素的需求:如果有三台 VPS、家里有 NAS、手上有笔记本和手机,怎么让它们像在同一张局域网里一样方便地互相访问?传统的做法是配一套 WireGuard 或 OpenVPN 全家桶,但手动维护每台设备的对端配置、公网 IP、密钥分发,很快就变成一场谁能记得住地址的游戏。Tailscale 把"自建 VPN"这件事重新定义了一遍:它在 WireGuard 的基础上,把配置分发、密钥管理、NAT 穿透和自动中继都抽象成一条命令,让你把散落各地的设备一键并入一张虚拟局域网(tailnet)。这篇讲清它背后到底做了什么,以及怎么把它用顺手——包括合并与子网路由、访问控制,以及自托管 Headscale 时需要考虑的东西。

一、理解 Tailscale 只做一件事:让"异地设备"像"内网设备"一样互访

Tailscale 的核心是一个叫"tailnet(尾巴网)"的虚拟网络:你注册的设备接入后,每台设备都会得到一个固定的虚拟 IP(100.x.y.z 网段),此后无论它在家里、公司还是云上,只要上线就能彼此直连。它内部确实是基于 WireGuard 的加密隧道,但让你面对的不是一堆 peer 配置,而是统一的"登录即入网"。

它背后有两套关键机制解决"加密隧道怎么连得起来"这个麻烦:一是协调机制——一台叫 coordination server 的中央服务负责管"哪些设备属于同一个 tailnet、各自的公钥与最新地址",设备上线时从这个协调服务拉取并建立 peer 关系,这就是 Tailscale 自动配置分发的根本;二是 NAT 穿透——两台在 NAT 后的设备怎么互相发现并直连,靠的是 STUN 探测与 UDP 打洞,打通不了时再走 DERP 中继节点兜底。把这些抽象掉之后,"配置 VPN"变成了"装客户端 + 登录"。

二、最小上手:装一条命令,设备就入网了

加入 tailnet 的体验被压缩到极致。在每台设备上安装客户端然后登录即可,常见的 Linux/服务器场景用 tailscale up 触发认证:

# Linux 服务器
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
# 若 headless / 服务器没有浏览器,用 authKey
sudo tailscale up --authkey=tskey-auth-xxxx

# 在另一台设备也 up 之后,彼此就会出现在 tailnet 里
tailscale status

手机、笔记本装官方客户端扫码登录即可,Mac、Windows、iOS、Android 都有客户端。入网之后你会发现一个立即生效的事实:你不再需要记住"这台服务在哪个 IP"来访问它,用虚拟 IP 或它能解析主机名就行,而且这些服务首页原本只监听 localhost 的场景,也可以只监听 tailnet 网卡上,等于多了一层"只有我自己的设备能碰"的边界——这对自托管服务的安全是肉眼可见的提升。

三、子网路由:把"一整段内网"也接进 tailnet

很多服务的设备(NAS、路由器上的 Web、打印机)装不了 Tailscale 客户端。Tailscale 用"子网路由(subnet router)"解决:让一台能装客户端的设备(比如那台 NAS 旁边的树莓派、或者一台 VPS)把它的整个局域网广播进 tailnet,其他 tailnet 设备就能像访问本地网段一样访问这台设备背后的所有内网 IP,无需在每台内网设备上装客户端。

# 在担任"子网路由"的机器上,把 192.168.1.0/24 广播进 tailnet
sudo tailscale up --advertise-routes=192.168.1.0/24
# 然后在协调后台/tailscale上接受这些路由(approve),
# 让需要的设备配上 --accept-routes 就能访问
sudo tailscale up --accept-routes

用子网路由时有两个值得留意的点。一是"广告路由要去后台批准"——默认不被接受,这是避免误广播的安全设计。二是它把内网设备暴露给了 tailnet 里所有信任的设备,所以你的 ACL 要同步收紧(见下一节),不然等于把家里内网的门开给了所有入网终端。

四、ACL:tailnet 是有边界的,别让权限变成"人人平等"

加入 tailnet 的设备越多,越要回答"谁可以访问谁"。Tailscale 用一组基于标签的 ACL 规则(可以在网页后台或版本化的 policy.json 里写)来定义访问边界。它的基本单元是"谁(src)/ 对谁(dst)/ 以什么端口(ports)"。一个把"服务器组"和"个人设备"分隔开的示例:

{
  "acls": [
    // 我的手机/笔记本可以访问服务器组的所有端口
    { "src": ["user:me"], "dst": ["tag:servers:*"] },
    // 服务器组之间默认不互开管理端口
    { "src": ["tag:servers"], "dst": ["tag:servers:*"] }
  ],
  "tagOwners": {
    "tag:servers": ["user:me"]
  }
}

原则和任何纵深防御一致:默认最小权限,只有显式放行才可达。标签(tag)可以把一批服务器归组,由管理员而非普通客户端贴标签,避免"每个登录用户都能给设备贴 tag 再互相控制"。把 ACL 思路放进 tailnet 后,网络虚拟化带来的便利才不成为安全上的要求——这不是"能不能连"的问题,而是"谁该连谁"的定义题。

五、自托管 Headscale:想完全掌控协调端怎么做

如果不想把"设备清单 + 公钥"的这一份协调数据放在第三方,Tailscale 生态提供了开源的 Headscale——相当于自建一版协调服务器,客户端仍用官方 Tailscale 客户端,只要把登录服务器指到你的 Headscale 上,就能完全掌控协调层。自托管 Headscale 的场景,通常是"更看重数据主权"或"不想依赖外部协调服务"。

# 用 Docker 起一个 Headscale
docker run -d --name headscale -p 8080:8080 \
  -v /srv/headscale:/var/lib/headscale \
  headscale/headscale:latest server

# 客户端指向自建协调端登录
sudo tailscale up --login-server=http://your-headscale:8080 \
  --authkey=tskey-auth-your-key

自托管 Headscale 之后,"注册的每台设备、公钥、路由"都落在你自己的服务里,等于掌握了 tailnet 的控制面。作为交换,你要自己运维它、负责它的高可用和备份——因为一旦协调端挂了,新设备无法入网、路由变动无法同步。对多数人来说,先体验官方协调端把路径跑通,再按需求评估是否下移到 Headscale,是更稳的节奏,别一上手就给自己多堆一套要维护的控制面。

六、和安全边界一起想:Tailscale 不是"公网服务的替代品"

把 Tailscale 用在自托管栈里,最常见的健康用法是"把不该暴露在公网的服务留在内网,通过 tailnet 在信任终端间访问",而不是把原本要公开的服务全改成走 tailnet。它不是 CDN,也不负责公网对外流量;相反,它是"面向你自己的私域连接"。所以我的建议是把它们分开:公开服务走前面的反向代理 + 防火墙 + 认证(和之前聊的 Authelia 那类方案是一类思路),私密管理入口走 tailnet——两者各司其职,风险面也会更清晰。

最后留意一个容易被忽视的坑:Tailscale 的 UDP 数据是加密的,但"有没有打洞成功"会影响体验。打洞失败会回落 DERP 中继,延迟升高、带宽受限——如果某条链路一直慢,先 tailscale ping 看是走直连还是走 DERP,再排查 NAT 类型,别一慢就以为是服务的问题。

结语

Tailscale 的实质,是把"自建 VPN"从"手抄一堆 peer 配置"变成"一键登录入网",用协调服务 + WireGuard + NAT 穿透 + 自动中继,把异地的设备像内网一样连起来。用顺手的关键有三点:入网后把服务监听收敛到 tailnet、用子网路由延展到整段内网、用 ACL 收紧谁可以访问谁。当设备规模变大或主权要求变高,再用 Headscale 自托管协调端。它不是公网服务的替代,而是"私密连接"的正确工具——把该暴露的交给反代,把该私有的放进 tailnet,你的自托管体系在便利和安全上就同时往前踏了一步。


手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

OpenResty 网关实战:用 Lua 给 Nginx 加上限流、鉴权与灰度分流

Authelia 统一身份认证实战:给反向代理前加一道 2FA 单点登录闸门

评 论
更换验证码