⚠️ AI 生成标识 · 本文由 AI Agent 协助撰写,人类作者审核发布。
痛点:手机上的梯子和内网服务,永远二选一
用 Tailscale 组了个人网络之后,一个长期痛点困扰着我:安卓手机一次只能开一个 VPN。
安卓的 VpnService API 只允许创建一张 TUN 虚拟网卡,所以:
- 开梯子 App → 能上外网,但连不了家里的内网服务(NAS、服务器、监控)
- 开 Tailscale → 能访问家里内网,但上不了外网(Google、YouTube 全被墙)
出门在外,我只能在两个 App 之间来回切换,一天折腾无数次。更别提移动网络下 Tailscale 打洞失败,还得忍受绕地球半圈的中继延迟。
这篇文章记录我的组网架构大升级:如何用一个”出口节点”同时解决”回家 + 翻墙”两个需求,顺便把中继带宽提升了 3.8 倍。
Part 1:中继带宽升级——先测速,别猜
现状:5Mbps 中继是瓶颈
我的 tailnet 有 8 台设备,主力中继节点是一台 5Mbps 小带宽服务器。打洞失败的设备(手机在移动网络下几乎必失败)要走 DERP 中继,实测:
1
iperf3 -c <节点IP> -p 5201 -t 20
结果:标称 5Mbps,实际只有 3.5Mbps——中继要转发流量,实际吞吐比标称低 30% 以上。这速度连 720p 视频都卡。
升级:高带宽中继节点 + 设备偏好
加了一台高带宽服务器当中继节点后,实测 13.5Mbps(快 3.8 倍)。但 Tailscale 客户端默认选延迟最低的节点,并不会自动用高带宽那个。解决方案是设备级偏好命令:
1
sudo tailscale debug force-prefer-derp <RegionID>
它是运行时命令,重启失效,所以用 systemd 持久化:
1
2
3
4
5
6
7
8
9
10
11
12
13
# /etc/systemd/system/tailscale-prefer-derp.service
[Unit]
Description=Force Tailscale DERP preference
After=tailscaled.service
Wants=tailscaled.service
[Service]
Type=oneshot
ExecStart=/usr/bin/tailscale debug force-prefer-derp 901
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
兜底验证:主节点挂了不断网
升级过程中还发现高带宽节点一直”拒客”(derper 容器 socket 挂载失效,身份校验失败),修好后做了个关键实验:强制偏好高带宽节点,然后直接停掉它的容器——
1
2
pong from server via DERP(jdy-tj) in 19ms
direct connection not established
结论:force-prefer-derp 是”偏好”而非”锁定”——首选节点不可达时,客户端自动 fallback 到 DERP map 里的其他节点。也就是说”高带宽为主 + 低带宽兜底”天然成立,不用写任何监控脚本。
Part 2:出口节点——手机的一键解决方案
思路:让手机”回家 + 翻墙”一体化
既然安卓只能开一个 VPN,那就让 Tailscale 一个 App 干两件事:
1
2
3
4
5
6
7
手机(只开 Tailscale)
↓ Tailscale 隧道(优先走高带宽中继)
家庭服务器(Exit Node 出口节点)
↓ iptables 透明代理重定向
代理软件(Clash 系,规则分流)
↓ 国内直连 / 国外走代理节点
外网
出口节点配置(家庭服务器侧)
家庭服务器宣告出口并批准路由(管理后台):
1
sudo tailscale up --advertise-exit-node
流量接管靠 iptables——把从 Tailscale 接口进来的流量重定向到本地代理的透明端口(redir-port),DNS 也交给代理的 fake-ip 处理:
1
2
3
4
5
6
7
8
9
10
11
12
iptables -t nat -N EXIT_PROXY
# 内网/保留/Tailscale 网段直连(不代理)
for net in 0.0.0.0/8 10.0.0.0/8 127.0.0.0/8 169.254.0.0/16 \
172.16.0.0/12 192.168.0.0/16 100.64.0.0/10 \
224.0.0.0/4 240.0.0.0/4; do
iptables -t nat -A EXIT_PROXY -d "$net" -j RETURN
done
# TCP → 代理透明端口;DNS → 代理 fake-ip
iptables -t nat -A EXIT_PROXY -p tcp -j REDIRECT --to-ports 7893
iptables -t nat -A EXIT_PROXY -p udp --dport 53 -j REDIRECT --to-ports 53
# 只作用于 Tailscale 接口进来的流量
iptables -t nat -A PREROUTING -i tailscale0 -j EXIT_PROXY
手机端:一个开关搞定
手机 Tailscale App 里点一下 marlin-server → Use as exit node,然后关掉梯子 App——以后:
- 国内 App:走家里出口 IP(在外的体验和在家一样)
- 国外流量:自动走代理节点翻墙
- 家里内网服务:照常访问
再也不用切换梯子。
事故插曲:在 Docker 主机上启用 Exit Node 的坑
升级过程中我踩了一个差点把整个基础设施搞没的坑,必须单独记录:
在”运行 Docker 的服务器”上启用 exit node(作为客户端)会导致全容器断网。
Tailscale 启用 exit node 时,会把本机所有本地网段(恰好覆盖全部 Docker bridge 网段 172.16.0.0/12)连同默认路由写进独立路由表 52,而策略路由 ip rule 5270 优先级高于 main 表:
1
2
3
ip route get 172.18.0.3
# 故障时:172.18.0.3 dev tailscale0 table 52 ← 被劫持进隧道黑洞
# 正常时:172.18.0.3 dev br-xxxx src 172.18.0.1
所有发往容器的流量被丢进隧道、永不到达本地 bridge——我自己的 AI Agent 也因此失联(它走本地代理,代理指向容器)。修复只需一条命令:
1
sudo tailscale set --exit-node=
预防:Docker 主机上如需启用 exit node,加一条防护规则让 Docker 网段走 main 表:
1
ip rule add to 172.16.0.0/12 lookup main priority 5269 # 优先级高于 5270
架构升级前后对比
| 维度 | 升级前 | 升级后 |
|---|---|---|
| 中继带宽 | 5Mbps(实测 3.5Mbps) | 13.5Mbps(快 3.8 倍) |
| 高带宽节点挂了 | 走国外节点(150ms+) | 自动切回低带宽兜底(不断网) |
| 手机梯子与内网 | 二选一,来回切换 | 一个 Tailscale 全搞定 |
| 手机在外访问内网 | 打洞失败绕地球 | 高带宽中继直连 |
| 手机外网访问 | 依赖梯子 App | 出口节点自动分流 |
总结
这次架构升级解决了三个实际问题:
- 带宽:标称 ≠ 实际,用 iperf3 测速后用
force-prefer-derp让设备偏好高带宽中继,3.8 倍提升 - 兜底:
force-prefer-derp是”偏好”不是”锁定”,主节点挂了自动 fallback,网络不断 - 手机痛点:一个 Exit Node 出口节点 + 透明代理,让安卓手机单 TUN 限制下同时获得”回家 + 翻墙”能力,从此告别梯子与内网的二选一
最后一条教训留给你:生产环境上任何”临时测试命令”都可能瞬间让整个基础设施失联——对网络路由变更保持敬畏,Docker 主机上尤其如此。
本文所有命令均在 Linux 环境验证。Tailscale 版本 1.102.x。