概述
- tailscale官方服务
- 中心点:官方节点发现服务器(后台: https://login.tailscale.com/admin/machines )
- 3个登录账号,100个端点 auth key (free和pro用户)
- 客户端:每个设备包括本地服务器也是一个端点,google登录每个节点,同一个账号下形成互通
- windows有安装包或scoop install
- linux可以上docker
- 官方子域名/公网IP,无损直接ssh使用
- 非常流畅,无需代理
- 中心点:官方节点发现服务器(后台: https://login.tailscale.com/admin/machines )
- headscale私有化
- 中心点:headscale申请端口,headscale-admin管理后台
〇、架构总览(Control Plane / Data Plane / Relay Plane 三面分离)
Tailscale 私有化部署(Headscale)后,体系拆解为三个独立平面和一个传输层:
┌─────────────────────────────────────────────────────────────────────────┐
│ 协 调 面 (Control Plane) │
│ Headscale 服务端 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ 身份认证 │ │ 节点发现 │ │ ACL 策略引擎 │ │
│ │ auth key │ │ 交换打洞信息 │ │ grants 权限规则 │ │
│ │ Google OAuth │ │ 分配 IP │ │ tag/group 管理 │ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
│ ⚠ 不碰任何用户数据流 — 只负责"牵线" │
├─────────────────────────────────────────────────────────────────────────┤
│ 转 发 面 (Relay Plane) — DERP │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 角色:P2P 打洞失败时的保底转发通道 │ │
│ │ 触发条件:两端均为对称型 NAT / 企业防火墙 / 移动宽带 │ │
│ │ 安全:即使走中继,数据已被 WireGuard 端到端加密 │ │
│ │ 中继服务器(官方/自建 derper)只搬运密文,无法解密 │ │
│ │ 部署方案: │ │
│ │ ① Tailscale 官方全球 DERP(默认,无需配置) │ │
│ │ ② Headscale Embedded DERP(自建内置中继) │ │
│ │ ③ 独立 derper 服务(完全私有、不限速) │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
↑ WireGuard 协议 — 端到端加密
│ P2P 直连 ↔ DERP 中继 自动切换(对上层透明)
↓ 每个节点一个 100.64.0.0/10 虚拟 IP
┌─────────────────────────────────────────────────────────────────────────┐
│ 数 据 面 (Data Plane) │
│ WireGuard 加密隧道 — 实际业务流量通道 │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ 节点 A │ ═══ P2P 直连 ═══ ▶ 节点 B │ │
│ │ 100.64.x.1 │ (打洞成功) │ 100.64.x.2 │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
│ │ ┌──────────────┐ │ │
│ └─────│ DERP 中继 │─────────────┘ │
│ │ (打洞失败时) │ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
端点 (Endpoints) 与分组 (Groups)
| 端点分组 | Tag | 职责 | 访问权限 |
|---|---|---|---|
| 管理节点 | group:admin | 拥有打 tag 权限,管理整个 tailnet 的 ACL 策略 | *:* 全通 |
| 服务器 | tag:server | 提供 SSH/HTTP/数据库等业务服务 | 可主动连所有 member 的任意端口 |
| 成员设备 | tag:member | 个人笔记本/工作站/手机等消费端 | 只能连 server 的指定端口(如 22,80,443) |
| 临时设备 | Ephemeral | CI/CD 构建机、一次性容器等,每次启动需重新认证 | 受 ACL 约束,不持久化状态 |
三种协议与传输关系
| 协议 | 层面 | 用途 | 加密 |
|---|---|---|---|
| WireGuard (L3 tunnel over UDP) | 数据面 | P2P 加密隧道,承载 SSH/HTTP/任意 TCP/UDP 业务流量 | 端到端 Curve25519 + ChaCha20Poly1305 |
| DERP (HTTP over TLS) | 转发面 | P2P 打洞失败时的中继转发,对 WireGuard 包做二次封装 | 传输层 TLS + WireGuard 双层加密 |
| Headscale API (HTTPS) | 控制面 | 节点注册、auth key 验证、打洞信息交换、ACL 下发 | HTTPS(不承载业务数据) |
连接状态判断
$ tailscale status 100.64.x.1 node-a linux active; tx 1024 rx 2048; direct ← P2P 直连(数据不过任何服务器) 100.64.x.2 node-b linux active; tx 512 rx 768; relay ← 中继转发(打洞失败,走 DERP)
架构设计原则
- 控制面不碰数据:Headscale 只做认证、发现、策略下发,绝对不转发业务流量。类比电话交换机的"接通即挂断"。
- 数据面端到端加密:WireGuard 隧道在客户端之间直接建立,密钥仅存在于两端,Headscale 和 DERP 都无法解密。
- 透明回退:P2P 直连失败自动切换到 DERP 中继,过程中 TCP 连接不中断,上层应用无感知。
- 最小暴露:member 只能访问 server 的指定端口(如 SSH 22 / Web 80/443),member 之间默认不通,server 可自由出站。
- 状态持久化:TS_STATE_DIR 保存设备证书和 WireGuard 密钥,避免重启后变成新设备导致 ACL 失效。
协议栈叠放 (Protocol Stack) — 常见协议在架构中的位置
WireGuard 工作在 Layer 3(网络层),创建一个虚拟网卡(tun0),分配 100.64.0.0/10 虚拟 IP。所有上层协议(HTTP/HTTPS/SSH/任意 TCP/UDP)都跑在 WireGuard 隧道内部,对外表现为 UDP 包或 DERP TLS 流。
┌────────────────────────────────────────────────────────────────────┐ │ 实 际 业 务 流 量 │ │ │ │ SSH HTTP HTTPS │ │ (TCP/22) (TCP/80) (TCP/443) │ │ │ │ │ │ │ └─────────────────┴─────────────────┘ │ │ │ │ │ TCP / UDP │ │ (传输层 — Transport Layer) │ │ │ │ │ ┌─────────▼─────────┐ │ │ │ WireGuard Tunnel │ ← 虚拟网卡 tun0 │ │ │ 100.64.x.x 虚拟IP │ ← 每个节点一个 │ │ │ Layer 3 加密隧道 │ ← Curve25519 + ChaCha20Poly1305 │ │ └─────────┬─────────┘ │ │ │ │ ├────────────────────────┼────────────────────────────────────────────┤ │ P2P 直连路径 │ DERP 中继路径 │ │ │ │ │ ┌────────▼──────┐ │ ┌───────────▼───────────┐ │ │ │ WireGuard │ │ │ DERP (HTTP over TLS) │ │ │ │ UDP 包 │ │ │ 将 WireGuard 包封装 │ │ │ │ 明文 dst:41641│ │ │ 为 HTTPS 请求 │ │ │ │ (内容加密) │ │ │ dst:443 → derper │ │ │ └───────┬───────┘ │ └───────────┬───────────┘ │ │ │ │ │ │ │ ▼ │ ▼ │ │ Internet │ Internet │ └────────────────────────────────────────────────────────────────────┘
实际场景示例:SSH 到 100.64.x.2
# 你执行 $ ssh user@100.64.x.2 # 背后实际发生的协议栈(从内到外): ┌─────────────────────────────────────────────────────┐ │ ① SSH 握手 (TCP/22) │ │ ↓ 这是你要传输的数据 │ │ ② TCP 分段 → IP 包 (src:100.64.x.1 → dst:100.64.x.2)│ │ ↓ WireGuard 虚拟网卡拦截这个 IP 包 │ │ ③ WireGuard 加密整个 IP 包 │ │ ↓ 结果是一个密文 UDP 包 │ │ ④ 封装为 UDP 包 (src:公网IP:41641 → dst:公网IP:41641) │ │ ↓ 或者封装为 HTTPS 请求发往 DERP (打洞失败时) │ │ ⑤ 真正的物理网卡发送 │ └─────────────────────────────────────────────────────┘ # 协议栈全景:从 wire 到应用 ┌─────────────────────────────────────────────┐ │ 应用层 │ SSH / HTTP / HTTPS (明文在本地) │ │ 传输层 │ TCP / UDP │ │ 网络层 │ IP (100.64.x.x) │ │ ── WireGuard 加密隧道(对 OS 透明)──────── │ │ 传输层 │ UDP (端口 41641) │ │ 网络层 │ IP (公网 IP) │ │ 链路层 │ 以太网 / Wi-Fi │ └─────────────────────────────────────────────┘
ACL 端口控制的真实含义
ACL 规则: {"src": ["tag:member"], "dst": ["tag:server"], "ip": ["22", "80", "443"]}
这句的意思是:在 WireGuard 隧道内部的 IP 包层面,
member 发向 server (100.64.x.2) 的 TCP 包,目标端口只允许 22/80/443。
端口 3306 (MySQL)、5432 (PostgreSQL)、8080 等默认被拒绝。
这不是防火墙规则(不是 iptables),而是 WireGuard 节点间 ACL,
由每个节点的 tailscale 守护进程在本地 enforce:
出站包在进入 WireGuard 隧道前被拦截检查,不符合 grants 的不予通过。
各协议在不同层面的角色汇总
| 协议 | OSI 层面 | 在 Tailscale 架构中的角色 |
|---|---|---|
| SSH | 应用层 (TCP/22) | 跑在 WireGuard 隧道内部,是你要传输的"数据"本身。Tailscale SSH 模式甚至可免密钥管理直接登录。 |
| HTTP | 应用层 (TCP/80) | 同样跑在 WireGuard 内部。访问 100.64.x.2:80 就像访问局域网 IP。 |
| HTTPS | 应用层 (TCP/443) | WireGuard 隧道内部再加一层 TLS,双层加密(隧道级 + 应用级)。 |
| TCP | 传输层 | WireGuard 隧道内承载的主流传输协议。隧道内的 TCP 包被 WireGuard 整体加密,外部不可见。 |
| UDP | 传输层 | 双重角色:既是隧道内载荷(DNS/QUIC/VoIP),也是隧道本身的传输载体(WireGuard 使用 UDP 41641)。 |
| WireGuard | 隧道层 (L3 over UDP) | 在 UDP 之上建立虚拟 Layer 3 网络,对 OS 呈现为 tun0 网卡。所有业务流量经它加密进入物理网络。 |
| DERP | 中继层 (HTTP/TLS) | HTTPS (TCP/443) 封装 WireGuard 包,当 P2P UDP 打洞失败时回退使用。双层加密(TLS + WireGuard)。 |
常用命令
net start tailscale
tailscale up
tailscale login --authkey xxxxxxxx
tailscale down
tailscale status
tailscale metrics
tailscale appc-routes
tailscale drive
tailscale logout
tailscale switch单人多机
- 每个端点都登录google账号即可
- 这里google即是账号权限,也是端点权限
多人局域
架构
Google 账号 → 仅控制台管理(不认证设备) ├─ tag:server (Server A) ← auth key for server └─ tag:member (用户组) ← 每人一个 auth key ┌────────────── groups ──────────────────┐ │ group:admin = ["xxx@gmail.com] │ ← 唯一能打 tag 的人 ├───────────── tags(成员)───────────────┤ │ tag:server → Server A │ ← 管理员打 tag │ tag:member → 用户甲 │ ← auth key 自带 │ tag:member → 用户乙 │ ← auth key 自带 └────────────────────────────────────────┘ ┌────────────────────────────────────────────┐ │ tag:server → *:* │ │ ✅ server 可以主动连 member 的任意端口 │ ├────────────────────────────────────────────┤ │ tag:member → tag:server:22,80,443,4180 │ │ ✅ member 可以主动连 server 的指定端口 │ ← member到member的访问没有配置 └────────────────────────────────────────────┘权限配置: https://login.tailscale.com/admin/acls/file
{ // 定义管理员和你自己的组 "groups": { "group:kc217": ["your-google-email@gmail.com"] }, // 定义 tag 及谁能打 "tagOwners": { "tag:server": ["group:kc217"], "tag:member": ["group:kc217"] }, // 权限规则 "grants": [ // 管理员全通 {"src": ["group:kc217"], "dst": ["*"], "ip": ["*"]}, // tag:member 只能访问 server 的指定端口 {"src": ["tag:member"], "dst": ["tag:server"], "ip": ["22", "80", "443", "2222", "4180"]}, // server 可以自由出站 {"src": ["tag:server"], "dst": ["*"], "ip": ["*"]}, ], }添加成员auth key: https://login.tailscale.com/admin/settings/keys
Description:密钥名称 Reusable:认证单次或多次,如果是单次则客户端用一次则直接失效,但认证状态可以永久有效 Expiration:失效期1-90天,认证行为有效期,而非认证后的认证状态有效期 Ephemeral:临时权限,每次登录都需要认证 Tags:关联tag
docker-compose.yml
services:
tailscale:
image: tailscale/tailscale:stable # 使用官方长期维护的稳定版标签
container_name: tailscale
restart: always
privileged: true # 必须:给予网络管理特权以创建 tun 虚拟网卡
network_mode: "host" # 必须:使用 host 模式实现最优的 P2P 穿透打洞性能
# 👇 新增下面两个环境变量,彻底关掉临时节点模式
environment:
- TS_AUTHKEY=tskey-auth-xxxxxxxxxxxxxxx
- TS_EPHEMERAL=false
- TS_STATE_DIR=/var/lib/tailscale
# 👇 强行清空容器内的代理环境变量,让它走原生非代理网络(国内大部分时间可以直接握手)
- HTTP_PROXY=
- HTTPS_PROXY=
- http_proxy=
- https_proxy=
volumes:
- ./data/tailscale:/var/lib/tailscale # 核心持久化:保存设备证书和状态,防止重启后重连/变成新设备
- /dev/net/tun:/dev/net/tun # 必须:映射宿主机的网络隧道设备
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro # 严格统一时区,防止证书因时间错乱失效
# 资源约束:防止由于网络风暴、DDoS或异常流量压垮公司服务器
deploy:
resources:
limits:
cpus: '0.50' # 限制最多使用 50% 的单核 CPU
memory: 256M # 限制最多使用 512MB 内存