电脑在家,人在外面,想打开一个开发页面、连一下数据库,或者看一眼自己的小设备,问题经常先卡在网络上:没有公网 IP,地址会变,路由器不方便配端口转发,还要考虑暴露哪些服务。

Tailscale 解决的是这段连接。设备加入同一个私有网络,并得到相应访问许可后,就可以通过稳定的地址或名称互访,使用体验很像“都在一个局域网里”。

这篇先用我本机的实际配置讲清它是什么,再聊远程开发、NAS、手机和 ESP32 能怎么接进来。配置核对是实际记录,后面的玩法是示例与构思,没有把“看得到设备”当成“已经测通所有服务”。

“万物都能局域网”,可以怎样理解

Tailscale 在已有网络之上组织一张私有 IP 网络,叫作 tailnet。两台设备可以分别在家中 Wi-Fi、手机热点或云端,不必真的接在同一台路由器上。

它基于 WireGuard 加密传输,帮助设备协商连接并尝试直连;直连困难时,可以通过 DERP 或已配置的 Peer Relay 中继。节点之间的数据仍受加密保护,但走中继和走直连,延迟与吞吐可能明显不同。不能把“能连上”理解成“保证满速”。连接方式说明、加密说明分别解释了这两件事。

这里的“局域网”是访问体验的比喻。Tailscale 主要工作在 L3 网络层,不会把各地设备自动变成同一个以太网广播域。一些依赖广播、多播或 mDNS 的自动发现功能,需要另外处理;游戏、打印机或投屏设备,也不能一概承诺安装后就能自动发现。官方 OSI 说明对此有明确区分。

实际使用时,先记住三个动作:找到目标设备的地址或名称,确认目标服务在运行,再检查访问权限。 Tailscale 提供网络连接,SSH、文件共享、网页和远程桌面仍由对应的软件提供。

我的本机配置:先是一张简单的三节点网络

2026 年 10 月 23 日,我对本机客户端做了一次只读核对:

项目这次实际看到的状态
本机macOS,Tailscale App,版本 1.104.1
运行状态Running,虚拟网络接口已启用
本机可见的其他节点一台 Linux、一台 Mac;核对时均显示在线
MagicDNStailnet 已启用,本机接受 Tailscale DNS 配置
接受子网路由本机设置已开启
发布子网路由本机没有发布任何网段
出口节点本机没有选择出口节点
Tailscale SSH 服务端开关本机未开启
Serve / Funnel本机没有配置服务发布

这份配置还很基础:已经加入网络并能看到其他节点,尚未扩展成家庭网关或网页发布入口。 状态里的“在线”并不能证明 SSH、数据库或网页端口一定可达;本次也没有做异地连接、吞吐或稳定性测试。

设备名、地址和账户信息没有直接贴出来。下文的 work-mac、dev-linux 都是示例名称,使用时要换成自己的设备名。

Tailscale 当前可见节点与 Serve、子网网关候选玩法示意

自绘拓扑示意。顶部对应本次可见的节点类型;下部是尚未配置和验证的玩法,不是实机截图或测速结果。

MagicDNS 让连接更容易记

开启 MagicDNS 后,可以用设备名称代替一串数字地址。例如,目标 Linux 主机已经运行普通 SSH 服务,且网络策略允许访问时,可以这样连接:

ssh developer@dev-linux

名称只解决“去哪里”,不会替目标创建用户、开启 SSH 或跳过密钥认证。MagicDNS 也不会自动为子网路由后面的每台打印机、NAS、ESP32 注册名称。MagicDNS和连接设备指南可以作为入门参考。

先从三个能落地的用途开始

以下是可采用的用法,命令中的主机名和账户均为示例;本次没有据此修改现有机器。

远程开发:把计算和环境留在原来的机器

一台机器负责放代码、依赖和运行环境,另一台通过 SSH 或编辑器的 Remote SSH 连接。Tailscale 负责把两端接起来,编辑器和目标机器继续做各自的事。

例如,用普通 SSH 登录后检查日志、启动开发服务,或者用 rsync 同步一个项目目录。目标主机仍要启用 SSH,并配好账户、密钥和访问规则。

这里容易混淆两个名字:

  • 普通 SSH 走 Tailscale 网络:沿用系统 SSH 服务和它原来的认证方式。
  • Tailscale SSH:专门启用的功能,由 Tailscale 管理相应 SSH 连接的身份与授权。

本机的 RunSSH 是关闭的,不能因此推断系统 SSH 也关闭。反过来,安装 macOS App 也不等于开启了 Tailscale SSH 服务端。官方目前将其服务端支持范围列为 Linux 和 macOS 开源 CLI 版本;普通 macOS App 用户仍可使用系统 SSH。Tailscale SSH 文档列出了这些边界。

开发数据库:优先建立一条明确的访问路径

我本机还保留着 MySQL、Redis 和 PostgreSQL 的 Docker 开发配置。这类环境很适合讨论远程调试,但网络接通不代表数据库权限也自动准备好了。

一个便于理解的办法是用 SSH 隧道。假设 PostgreSQL 在 work-mac 上监听 127.0.0.1:5432,系统 SSH 已配置好,可以在访问端执行:

ssh -N -L 127.0.0.1:15432:127.0.0.1:5432 developer@work-mac

然后让访问端的数据库工具连接 127.0.0.1:15432。这里第二个 127.0.0.1 指向 SSH 目标机器,数据库账户与密码仍按原服务要求填写。

这是一条待验证的连接方案,不是本次成功连接的记录。若直接通过 Tailscale 地址访问数据库,还要分别检查服务监听地址、Docker 端口映射、主机防火墙和 tailnet 访问规则;没有必要为了“方便”就把所有数据库端口一起放开。

手机看本地网页:Serve 比记住一堆端口更顺手

假设 Mac 上有一个开发页面,正在 http://127.0.0.1:3000 提供服务。装了 Tailscale 的手机可以通过 Serve 访问它。

macOS 上先按所用发行版本的说明准备命令行工具,确认终端能运行 tailscale version;装了图形 App,不一定已经把裸命令放进 PATH。CLI 文档列出了对应方式。

# 示例:在网页所在的 Mac 上运行
# 需要 tailnet 已满足相应 HTTPS 配置与访问权限
tailscale serve 3000

命令会显示 tailnet 内的访问 URL。需要开启 HTTPS 等前置能力时,客户端会引导相应设置;本次写作没有执行这条发布命令。前台运行的示例通常可用 Ctrl+C 停止。

使用公开可信的 HTTPS 证书,还要留意:证书中的机器名和 tailnet DNS 名称会进入公开证书透明度记录,命名时不要带敏感信息。这不等于服务因此向公网开放,访问范围仍由所用入口和规则决定。HTTPS 说明解释了这一区别。

这让只监听 localhost 的网页有了私有访问入口,适合手机测试页面、查看个人面板,或者访问自己的开发工具。应用原有的登录和业务权限仍要保留;被代理并不等于自动获得完整的应用鉴权。

macOS App 可以用 Serve 代理端口,直接分享文件或目录则有发行版本限制。因此这里使用“代理一个已经运行的 HTTP 服务”,而不是直接分享整个项目文件夹。Serve 说明和示例有具体用法。

设备装不了客户端,就让网关带它进来

NAS、路由器、打印机和小硬件,并不是每一种都能直接安装 Tailscale。可以分成两类:

接入方式适合的设备访问时注意什么
设备自己运行客户端支持的平台主机、部分 NAS使用它的 Tailscale 地址或名称,连接原有服务
通过子网路由器接入没有客户端、但已有局域网服务的设备访问其局域网 IP;网关、路由批准与权限需另行配置

**子网路由器(subnet router)**通常是一台常开的电脑、Linux 主机或其他受支持设备。它一边加入 tailnet,一边能访问目标局域网,把特定网段的流量转发过去。配置涉及路由发布、批准、访问规则以及必要的 IP 转发;不是装好客户端就自动覆盖整个家庭网络。子网路由文档给出了完整流程。

这也是 NAS、媒体库和文件共享的一种接入思路。网络通道准备好后,仍然使用原来的网页、SMB 或媒体客户端和账户。Tailscale 不会自动创建共享目录,也不会把 NAS 变成同步盘;不同 NAS 平台还有各自的配置要求。官方 NAS 使用指南适合继续查阅。

还有一个容易忽略的边界:加密隧道到子网网关结束,网关到普通局域网设备的那一段,取决于原来的应用协议。 如果终端用的是明文 HTTP,就不能说 WireGuard 一直加密到了终端芯片。架构说明解释了这种转发方式。

和我的 ESP32 小团结合,可以怎么玩

我之前写过小团的实际项目。当前主要链路是 Mac 采集状态,再通过蓝牙传给 ESP32;下一步构思里也讨论过它还能怎样参与工作节奏。

结合 Tailscale,可以继续考虑两条路线:

路线一:手机访问 Mac,再由 Mac 和小团交互。 手机加入 tailnet,打开 Mac 上新增的控制页面或接口;Mac 再通过现有蓝牙链路与小团通信。例如查看任务状态、调整提醒或切换展示内容。控制接口、应用鉴权和固件命令都需要另外实现和验证,Mac 还得保持运行并处于蓝牙可达范围。

路线二:给有网络服务的 ESP32 提供子网访问。 如果某个 ESP32 项目本身提供了 HTTP 接口,或接入家中的 MQTT 服务,就可以研究通过子网网关访问这些局域网服务。这里的前提是它已经有对应的网络功能;当前小团的蓝牙链路不会因为安装了 Tailscale 就自动变成远程 HTTP API。

这两条都属于后续玩法。Tailscale 负责接通网络,设备交互仍要由具体项目完成,串口烧录、自动发现和远程唤醒也需要分别判断。

子网路由、出口节点、Serve 和 Funnel,各管哪一段

这几个名字经常一起出现,可以按目的来区分:

能力解决的问题
普通 tailnet 连接访问另一台已加入网络的设备
子网路由访问网关后面某个指定局域网的设备
出口节点(exit node)让客户端的普通互联网访问经另一台设备转发出去
Serve把本机服务提供给 tailnet 内获准的访问者
Funnel把指定本机服务提供给公网访问者

访问家里的 NAS 通常不要求开启出口节点。只有想让普通上网流量经指定设备出去,才考虑配置、批准并在客户端选择 exit node;速度也会受到出口机器和网络的限制。出口节点文档说明了这一点。

本机“接受子网路由”虽然是开启的,但没有选择出口节点,不能把这两个设置当成“已经全局走某台服务器”。

Funnel 则是另一种方向:让没有加入 tailnet 的人也能访问某个服务,适合准备好鉴权的演示站或 webhook 接收端。Funnel URL 是公网入口,不能当作“只有发给朋友才看得到”的私密链接。 平台支持范围和前置条件要按当前客户端核对;本机尚未配置,本篇不把它写成已验证功能。Funnel与设备分享的区别值得先看清楚。

真正连接不上时,按顺序缩小范围

可以先用这组命令查看设备和路径。示例中的 dev-linux 需要替换成真实目标:

tailscale version
tailscale status
tailscale ping --c=3 dev-linux

tailscale ping 可以帮助观察连接路径;它成功,不代表目标的 SSH、数据库或网页端口一定开放。继续按这条顺序查:

  1. 目标是否在线。 主机休眠、关机或断网时,网络工具不能代替它提供服务。
  2. 名称是否正确。 MagicDNS 名称与局域网的 .local 自动发现不是同一套机制;子网后方设备可先按其 IP 排查。
  3. 目标服务是否运行并监听正确地址。 一个只绑定远端 127.0.0.1 的服务,不能直接用那台机器的 Tailscale IP 访问,可以考虑 Serve 或 SSH 隧道。
  4. 网络规则和应用认证是否允许。 检查 tailnet 策略、主机防火墙,以及应用本身的账号与权限。
  5. 是否把连通问题和性能问题混在一起。 已经能打开服务但速度慢,再看直连/中继路径、两端带宽和设备负载。

新 tailnet 的初始访问策略通常比较宽松。设备变多之后,需要按用户、设备或服务缩小权限;ACL/grants 不会自动替普通数据库和文件服务配置它们的业务账户。Tailscale SSH、Serve 身份头或专门集成的应用能力,则是需要有意配置的另一层功能。访问控制说明可作为后续整理权限的入口。

对我这套配置来说,已经有了一个清楚的起点:Mac 和 Linux 节点可见,名称服务已启用。接下来可以先挑一个具体目标,例如“手机打开 Mac 的一个私有网页”,验证完整链路,再把它扩展到开发环境或小团。

“万物都能局域网”的实用之处,是把分散设备之间的连接变得容易组织;至于连上以后能做什么,仍然取决于我们在两端运行的服务和真正完成的交互。