欢迎光临

VPS自建虚拟组网中心:ZeroTier + Tailscale跨地域内网互通实战指南

为什么需要自建虚拟组网

在现代分布式团队和多云架构中,跨地域、跨云的内网互通是一个高频刚需。传统的 IPSec/SSL VPN 部署繁琐,对 NAT 穿透能力弱;而商用 SaaS 组网方案(如 Tailscale 官方控制服务器、ZeroTier 官方网络)虽然开箱即用,但存在免费额度限制、节点数据经过第三方服务器、定制化能力有限等问题。

本教程在 VPS 上自建 ZeroTier Moon 和 Tailscale Headscale 控制平面,实现完全自主可控的跨地域虚拟组网。方案同时覆盖两种主流组网协议栈,让读者根据实际场景灵活选择,也可双栈并行部署互为容灾。

虚拟组网架构示意

ZeroTier 与 Tailscale 技术对比

两者都是面向”无 VPN 配置体验”的覆盖网络(Overlay Network)方案,但底层协议哲学完全不同,选型前必须理解差异。

维度 ZeroTier Tailscale
底层协议 自研二层虚拟交换(类似 VXLAN) WireGuard(三层点对点隧道)
地址层 MAC + IPv4/IPv6(二层可达) 100.64.0.0/10 CGNAT 段
NAT 穿透 STUN + UPnP + Root 服务器中继 STUN + DERP 中继 + UPnP/PMP
自建控制面 Moon(加速中继,控制器仍依赖官方) HeadScale(完全替代官方控制服务器)
移动端支持 iOS / Android 官方 App iOS / Android 官方 App
分包大小 约 5MB 约 20MB(含 WireGuard 内核模块)
典型场景 跨机房 L2 互通、容器直连 开发远程办公、K8s 节点互联

简单总结:ZeroTier 更像”全球虚拟交换机”,适合需要二层直连的场景(如容器网络、虚拟机迁移);Tailscale 更像”自动配置的 WireGuard”,性能优异、密钥管理干净,适合远程办公和服务网格。下面分别讲解两种方案的自建部署。

环境准备与基础配置

本教程使用一台位于公网的 VPS 作为控制平面节点,规格建议:2 核 CPU、2GB 内存、Ubuntu 22.04 LTS。控制面对外只暴露 HTTPS 端口,数据平面通过 NAT 穿透尽量走直连,无法直连时才走中继。

首先更新系统并安装基础依赖:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 更新系统
apt update && apt upgrade -y

# 安装基础工具
apt install -y curl wget gnupg ufw fail2ban

# 配置防火墙基线
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 9993/udp    # ZeroTier 数据面
ufw --force enable

# 启用 BBR 拥塞控制(提升中继链路性能)
echo 'net.core.default_qdisc=fq' >> /etc/sysctl.conf
echo 'net.ipv4.tcp_congestion_control=bbr' >> /etc/sysctl.conf
sysctl -p

注意 9993/udp 必须开放,这是 ZeroTier 的数据平面端口;Tailscale 的 WireGuard 端口则动态协商,无需手动放行。下面分别部署两套控制面。

部署 ZeroTier Moon 加速节点

ZeroTier 的官方 Root 服务器位于欧美,国内节点访问延迟高且容易超时。Moon 节点是 ZeroTier 提供的中继加速器,相当于自建的 Root 服务器,可显著降低 NAT 穿透失败时的中继延迟。

首先安装 ZeroTier 客户端并加入网络:


1
2
3
4
5
6
7
8
9
10
# 安装 ZeroTier
curl -s https://install.zerotier.com | sudo bash

# 启动并启用服务
systemctl enable --now zerotier-one

# 加入你已经在官方控制台创建的网络
zerotier-cli join <你的16位Network ID>

# 在 https://my.zerotier.com 控制台授权该节点

接下来生成 Moon 配置并启动 Moon 节点:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 进入 ZeroTier 工作目录
cd /var/lib/zerotier-one

# 生成 Moon 身份与配置
zerotier-idtool initmoon identity.public > moon.json

# 编辑 moon.json,添加 stableEndpoints 为本机公网 IP
# 找到 "stableEndpoints": [] 这一行,改为:
# "stableEndpoints": ["你的VPS公网IP/9993"]
vim moon.json

# 生成 Moon 签名文件(生成 .moon 文件)
zerotier-idtool genmoon moon.json
# 输出类似:000000xxxxxxxxxx.moon

# 创建 moons.d 目录并放入签名文件
mkdir -p moons.d
mv *.moon moons.d/

# 重启 ZeroTier 使 Moon 生效
systemctl restart zerotier-one

# 验证 Moon 节点已上线
zerotier-cli listmoons
# 应输出 moon 节点的 ID 与 orbit 信息

客户端节点要使用这个自建 Moon,需要将

1
.moon

文件复制到客户端的

1
moons.d/

目录,或通过命令行快速加入:


1
2
3
4
5
# 在客户端执行(替换 Moon ID 和 VPS IP)
zerotier-cli orbit <Moon ID> <Moon ID>

# 验证已 orbit 到自建 Moon
zerotier-cli listpeers -j | jq '.[] | select(.role=="MOON")'

加入自建 Moon 后,国内节点之间的延迟通常从 200ms+ 降到 30ms 以内,且即使官方 Root 不稳定也不影响组网。配合 ZeroTier 官方控制器做网络授权即可,Moon 节点本身不参与授权流程。

部署 HeadScale:完全自建的 Tailscale 控制服务器

相比 ZeroTier 的 Moon(仅加速,授权仍依赖官方),HeadScale 是 Tailscale 控制服务器的完整开源替代,节点注册、密钥分发、ACL 策略全部自主掌控,无需任何 Tailscale 官方账号。

安装 HeadScale 服务端


1
2
3
4
5
6
7
8
9
10
11
# 下载最新版本(以 v0.23 为例)
HEADSCALE_VERSION=v0.23.0
wget https://github.com/juanfont/headscale/releases/download/${HEADSCALE_VERSION}/headscale_${HEADSCALE_VERSION#v}_linux_amd64 -O /usr/local/bin/headscale
chmod +x /usr/local/bin/headscale

# 创建配置目录
mkdir -p /etc/headscale
mkdir -p /var/lib/headscale

# 生成配置文件
headscale generate-config > /etc/headscale/config.yaml

编辑

1
/etc/headscale/config.yaml

关键配置项:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server_url: https://hs.yourdomain.com:443
listen_addr: 127.0.0.1:8080
metrics_listen_addr: 127.0.0.1:9090

# 数据库
database:
  type: sqlite
  sqlite.path: /var/lib/headscale/db.sqlite

# DERP 中继服务器(可自建,这里先用 Tailscale 官方)
derp:
  server.enabled: false
  urls:
    - https://controlplane.tailscale.com/derpmapdefault

# 自动接受节点(生产环境建议改为 false,手动审批)
auto_register: false

# IP 段分配
ip_prefixes:
  - 100.64.0.0/10

# 策略 ACL(默认全互通,按需收敛)
acl_policy_path: ""

创建 systemd 服务单元:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cat > /etc/systemd/system/headscale.service <<'EOF'
[Unit]
Description=HeadScale Tailscale Control Server
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/headscale serve
Environment=HEADSCALE_CONFIG=/etc/headscale/config.yaml
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now headscale
systemctl status headscale --no-pager

配置 Nginx 反向代理与 HTTPS

HeadScale 监听 127.0.0.1:8080,需要 Nginx 暴露 HTTPS 并申请证书。这里使用 acme.sh 自动签发 Let’s Encrypt 证书。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
apt install -y nginx

# 签发证书(替换域名)
curl https://get.acme.sh | sh
~/.acme.sh/acme.sh --register-account -m admin@yourdomain.com
~/.acme.sh/acme.sh --issue -d hs.yourdomain.com --nginx
~/.acme.sh/acme.sh --install-cert -d hs.yourdomain.com \
  --key-file /etc/nginx/ssl/hs.key \
  --fullchain-file /etc/nginx/ssl/hs.crt \
  --reloadcmd "systemctl reload nginx"

# Nginx 配置
cat > /etc/nginx/conf.d/headscale.conf <<'EOF'
server {
    listen 443 ssl http2;
    server_name hs.yourdomain.com;

    ssl_certificate /etc/nginx/ssl/hs.crt;
    ssl_certificate_key /etc/nginx/ssl/hs.key;
    ssl_protocols TLSv1.2 TLSv1.3;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
EOF

nginx -t && systemctl reload nginx

创建用户与命名空间


1
2
3
4
5
6
7
8
# 创建一个用户命名空间
curl -X POST http://127.0.0.1:8080/api/v1/user \
  -H "Content-Type: application/json" \
  -d '{"name":"dev-team"}'

# 生成预授权密钥(用于客户端注册)
headscale preauthkeys create --user dev-team --reusable
# 输出类似:hskey_xxxxxxxxxxxxxxxx

客户端接入与跨地域组网实战

服务端就绪后,在各地的 VPS、办公室网关、开发机上接入 Tailscale 客户端,并指向自建的 HeadScale 服务器。

Linux 客户端接入


1
2
3
4
5
6
7
8
9
10
11
12
13
# 安装 Tailscale
curl -fsSL https://tailscale.com/install.sh | sh

# 指向自建 HeadScale 登录
tailscale up \
  --login-server https://hs.yourdomain.com \
  --auth-key hskey_xxxxxxxxxxxxxxxx \
  --accept-routes \
  --accept-dns=false

# 验证连通
tailscale status
tailscale ping <对端节点名或100.64.x.x>

Windows / macOS 客户端

桌面端需要在登录界面点击 “Switch to custom server”,填入

1
https://hs.yourdomain.com

,然后用预授权密钥登录。如果使用 OAuth 接入,需要在 HeadScale 配置 OIDC 提供者(如 Authentik、Keycloak),配置

1
oidc

块即可。

跨地域子网路由共享

实际场景中,我们往往需要让远程办公的笔记本访问公司机房内的整个内网段,而不仅仅是单台节点。这时需要在机房网关上启用 Subnet Router 模式:


1
2
3
4
5
6
7
8
9
10
11
12
13
# 在机房网关 VPS 上启用子网路由
tailscale up \
  --login-server https://hs.yourdomain.com \
  --advertise-routes=10.0.0.0/24,192.168.10.0/24 \
  --accept-routes

# 在 HeadScale 服务端批准该路由
tailscale set --accept-routes

# 其他节点的客户端也需要 --accept-routes 才能收到路由表
# 验证路由表
ip route | grep 100.64
tailscale status | grep -i subnet

完成上述配置后,分布在三个地域的节点拓扑如下:

  • 北京办公室网关(自建 Moon + Tailscale 子网路由):暴露 10.0.0.0/24 内网
  • 上海机房 VPS(HeadScale 控制端 + ZeroTier Moon):暴露 192.168.10.0/24 内网
  • 远程开发笔记本(仅 Tailscale 客户端):通过 100.64.x.x 互联,可访问上述两个内网段

跨地域组网拓扑

安全加固与 ACL 策略

默认配置下所有 Tailscale 节点之间互通,生产环境必须通过 ACL 收敛暴露面。HeadScale 支持 Tailscale 原生的 HuJSON 格式 ACL。

编写

1
/etc/headscale/acl.hujson


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
  "groups": {
    "group:dev":   ["user-dev-team"],
    "group:ops":   ["user-ops-team"]
  },
  "tagOwners": {
    "tag:server":    ["group:ops"],
    "tag:workstation":["group:dev"]
  },
  "acls": [
    // 开发机只能访问服务器的 22/80/443 端口
    {"action":"accept", "src":["tag:workstation"], "dst":["tag:server:22,80,443"]},
    // 运维之间互通无限制
    {"action":"accept", "src":["group:ops"], "dst":["*:"]},
    // 默认拒绝其他所有流量
    {"action":"deny",   "src":["*"],         "dst":["*:"]}
  ]
}

在 config.yaml 中启用 ACL:


1
2
3
4
acl_policy_path: /etc/headscale/acl.hujson

# 重启 HeadScale
systemctl restart headscale

为节点打 Tag 需要在客户端登录时指定:


1
tailscale up --login-server https://hs.yourdomain.com --advertise-tags=tag:server

此外建议做以下加固:

  • 关闭 auto_register:所有新节点必须通过预授权密钥或 OIDC 登录,避免任意人接入
  • 定期轮换预授权密钥:通过
    1
    headscale preauthkeys expire

    让旧密钥失效

  • 启用 MagicDNS:让节点用域名互访,避免硬编码 IP
  • 限制控制面访问来源:在 Nginx 上对
    1
    /api/v1/

    加 IP 白名单或 basic auth

故障排查与运维监控

组网链路涉及 NAT 穿透、UDP 防火墙、DNS 解析等多个环节,故障定位需要分层排查。下面是常用的诊断命令与监控方案。

常用诊断命令


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# === ZeroTier ===
zerotier-cli listpeers -j | jq '.[] | {role, latency, version, paths}'
# 关注 role=MOON/ROOT 的 latency;若 latency 极高说明中继链路有问题

zerotier-cli listnetworks
# 查看当前节点加入的网络与分配的 IP

# === Tailscale / HeadScale ===
tailscale status
tailscale netcheck
# netcheck 会测试 NAT 类型、UDP 是否可达、DERP 中继延迟

tailscale ping --verbose <对端>
# 显示是直连还是走 DERP,以及 RTT

# 查看 HeadScale 注册的节点
curl -s http://127.0.0.1:8080/api/v1/node \
  -H "Authorization: Bearer <your-api-key>" | jq

构建监控大盘

使用 Prometheus 抓取 HeadScale 暴露的指标(端口 9090),关键指标包括:

  • 1
    headscale_node_count

    :注册节点总数

  • 1
    headscale_preauthkeys_count

    :有效预授权密钥数

  • 1
    tailscale_ping_latency_ms

    (需自建 exporter):节点间 RTT

快速接入 Prometheus 与 Grafana:


1
2
3
4
5
6
7
8
# prometheus.yml 追加 scrape 配置
scrape_configs:
  - job_name: 'headscale'
    static_configs:
      - targets: ['127.0.0.1:9090']

# Grafana 导入 dashboard:
# 使用 ID 17169(Tailscale Overview 社区大盘)并改为抓取自建 HeadScale 指标

常见故障速查表

症状 可能原因 解决方案
客户端一直停留在”connecting” NAT 类型对称且 UDP 被防火墙拦截 检查 ufw/iptables 是否放行 41641/udp,或配置自建 DERP
HeadScale 注册报 401 预授权密钥过期或 ACL 限制 重新生成 preauthkey,检查 ACL 中 src 是否包含该节点 tag
子网路由不通 对端未启用 –accept-routes 所有需要访问该子网的节点都必须加 –accept-routes
ZeroTier Moon 不生效 客户端未 orbit 或 Moon IP 配置错误 重新执行 zerotier-cli orbit,检查 moon.json 中 stableEndpoints
偶发断流 MTU 不匹配导致分片丢包 tailscale set –mtu=1280 或 zerotier-cli 设置 MTU

方案选型建议与总结

两种方案各有侧重,选型时建议结合业务特征:

  • 纯远程办公、K8s 节点互联:优先选 Tailscale + HeadScale。WireGuard 性能优异、ACL 完善、MagicDNS 体验好,自建后无节点数量限制。
  • 跨机房 L2 互通、容器网络直连、虚拟机热迁移:优先选 ZeroTier + Moon。二层可达特性可承载更灵活的网络拓扑。
  • 混合多云、对延迟敏感:双栈并行部署。ZeroTier 作为二层备份通道,Tailscale 作为日常主通道,互为容灾。

自建控制平面的核心收益是数据自主、节点无上限、可深度定制 ACL 与 DERP 路由。运维成本主要在证书续期、节点审批与 ACL 维护,建议配合 Ansible 或 Terraform 做配置漂移管理。完成本方案后,你就拥有了一个完全自主的跨地域虚拟组网中心,无论是分布式团队协作还是多云互联,都能在数分钟内把新节点接入全球互联的内网。

全球互联组网

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » VPS自建虚拟组网中心:ZeroTier + Tailscale跨地域内网互通实战指南
分享到: 更多 (0)