LocalSync2026-09-08
用「Tailscale + 自建 DERP」把本地 DeepSeek Harness Web 远程访问从皱眉提速到 25ms
起因是一条慢到让人皱眉的 Cloudflare 隧道,经过一波三折的排障与两台云服务器的折腾,最终把远程访问延迟从 350~475ms 压到 23~42ms。本文按「起因 → 方案 → 实施 → 踩坑 → 结果」完整复盘,所有真实域名、IP、账号、密钥均已脱敏为占位符。
一、起因:人在外面,要访问办公室电脑上的 DSH
真正想做这件事的原因很简单:DSH(DeepSeek Harness)Web 跑在办公室一台常开机的 Windows 电脑上(HTTP 监听 127.0.0.1:3080),但我人经常不在办公室——在家里、在路上、用手机或另一台电脑,都需要随时打开它:看看运行中的任务、继续未完成的会话、取结果、发指令。
对远程访问的要求就三条:
- 在外面任何设备都能打开(不一定跟办公室同网);
- 体验接近本地,不能卡成幻灯片;
- 不能裸奔公网(DSH 能执行命令,还有人机会话数据,等闲之辈碰不得)。
第一版方案是「Cloudflare Tunnel + Worker Basic Auth」:公网域名(如 dsh.example.com)+ 固定密码,任何地方输密码就能进。可用,但慢:
- CF 边缘绕行:公网请求落到的 Cloudflare 边缘节点可能离你很远(实测曾落到欧洲节点,跨了大半个地球);
- 家宽上行带宽:所有数据都从办公室家宽上传出去,上传带宽通常只有 10~30Mbps,这是硬上限。
既然该机器上本来就装着 Tailscale(基于 WireGuard 的私有组网,默认点对点直连、流量不经过任何厂家服务器),于是决定研究用它实现"又快又安全的外出访问"。本文就是这条路上从起因、踩坑到结果的完整复盘。
二、方案对比
| 方案 | 公网可达 | 认证方式 | 实测延迟 |
|---|---|---|---|
| Cloudflare Tunnel + 密码 | ✅ 是 | 用户名 + 密码 | 慢(边缘绕行 + 上行带宽) |
| Tailscale 直连(同网/打洞成功) | ❌ 仅 tailnet | 设备身份(登录同一账号) | 28ms(NAS 实测) |
| Tailscale + 官方海外中继 | ❌ 仅 tailnet | 设备身份 | 350~475ms(美西中继) |
| Tailscale + 自建国内 DERP | ❌ 仅 tailnet | 设备身份 | 23~42ms(北京中继) |
三、环境
- 本机:Windows,DSH Web 监听
127.0.0.1:3080(pm2 托管),已装 Tailscale(tailnet 内有 NAS、另一台办公室电脑等多台设备) - 客户端:另一台 Windows 电脑(同一 tailnet),需要访问本机 DSH
- 云服务器(可选,用于自建 DERP):新加坡一台、北京一台
四、第一步:Tailscale 直连
4.1 先搞懂 DSH 的 /api 信任围栏
DSH Web 对 /api 请求有一个防 DNS 重绑定的信任围栏(trustedHosts):只有 Host 头命中回环或白名单的请求才放行,否则一律 403。这个名单不是认证,只是告诉 DSH"这些主机名是我自己的"。
所以用任何非回环域名访问 DSH,都必须先把主机名加进白名单。DSH 的 Web profile 补丁文件(cordis.patch.yml)里这样写:
- id: connection
config:
trustedHosts: ['<你的公网域名>', '<你的ts.net主机名>', ...ctx.webRuntime.trustedHosts]
改完重启 DSH Web 生效。效果验证:请求 /api/xxx 从 403 forbidden 变成 404 not found(说明已越过围栏、进入正常路由)。
4.2 一条命令拿到 HTTPS:tailscale serve
tailscale serve --bg http://127.0.0.1:3080
- 自动签发证书,得到
https://<主机名>.<tailnet>.ts.net(443 端口、无需带端口号) - 仅 tailnet 内设备可访问(这就是"不需要密码"的原因,见第七节)
--bg后台常驻,配置存在 tailscaled 状态里,重启自动恢复
⚠️ 首次使用会提示 "Serve is not enabled on your tailnet":需要 tailnet 管理员在后台(
https://login.tailscale.com/f/serve)点一次开关,之后才能用。
4.3 webserver 保持回环绑定
serve 是在本机完成的 TLS 终结 + 反代,它连的是 127.0.0.1:3080,所以 DSH 的 webserver 保持 127.0.0.1 绑定即可,不要开 0.0.0.0:
- 好处:不向局域网暴露一个带命令执行能力的服务
- 如果开了 0.0.0.0,DSH 会自动把本机各网卡 IPv4(含 Tailscale 100.x)加入 /api 信任名单,裸 IP 也能访问——但整个局域网都可达,风险自担
五、为什么还是慢?——直连与中继
Tailscale 数据面默认点对点直连(WireGuard 加密,不经服务器);只有 NAT 打洞失败才退回 DERP 中继。
定位工具:
tailscale ping <对端主机名> # via DERP(xxx)=中继;via IP:port=直连
tailscale netcheck # 看 UDP、NAT 类型、所有中继延迟
实测结果:
| 对端 | 路径 | 延迟 |
|---|---|---|
| NAS | 直连(IPv6 直连) | 28ms ✅ |
| 另一台办公室电脑 | DERP(sea/sfo) 美西中继 | 350~475ms ❌ |
两台电脑之间:netcheck 显示两端 UDP 都通、NAT 映射都稳定,却打不出直连——中国跨运营商 UDP 报文被丢弃 + 客户端无 IPv6,打洞数据包到不了对端,只能走中继。而官方中继全在海外(美西 ~170ms、新加坡 ~300ms),这就是慢的根。
结论:要么打通直连(路由器端口转发),要么把中继搬近一点(自建 DERP)。
六、自建 DERP(核心提速手段)
6.1 为什么选北京
官方中继都在海外;自建一个国内节点,延迟直接从 170~300ms 掉到几十毫秒。实测北京节点(腾讯云)延迟 39.8ms,成为全网最近中继。
6.2 部署 derper(北京节点为例)
① 编译 derper 二进制
服务器装 Go(注意:系统源里的 Go 版本可能不够新,derper 要求更高的 Go 版本;直接用官方 tarball 最稳):
cd /tmp && curl -O https://go.dev/dl/go1.26.8.linux-amd64.tar.gz \
&& mkdir -p /opt/go1.26.8 && tar -C /opt/go1.26.8 --strip-components=1 -xzf go1.26.8.tgz
export PATH=/opt/go1.26.8/bin:$PATH GOTOOLCHAIN=local GOSUMDB=sum.golang.org
go install tailscale.com/cmd/derper@latest
② 证书(DNS-01,不需要占用 80 端口)
用 acme.sh + Cloudflare DNS API 签发,务必装 fullchain(只装叶子证书会因缺中间 CA 被客户端拒绝):
export CF_Email=<你的CF邮箱> CF_Key=<你的CF API Key>
acme.sh --issue --dns dns_cf -d derp-bj.example.com --keylength ec-256 --server letsencrypt
acme.sh --install-cert -d derp-bj.example.com --ecc \
--fullchain-file /etc/derper/certs/<域名>.crt \
--key-file /etc/derper/certs/<域名>.key \
--reloadcmd "systemctl restart derper"
③ systemd 常驻
[Unit]
Description=Tailscale DERP relay server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/root/go/bin/derper -hostname derp-bj.example.com -certmode manual -certdir /etc/derper/certs -a :8443 -http-port 8088 -stun-port 3478
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
④ 放行端口(两层!)
- 服务器 OS 防火墙(firewalld):
bash
firewall-cmd --permanent --add-port=8443/tcp --add-port=8088/tcp --add-port=3478/udp && firewall-cmd --reload - 云服务商安全组(控制台层,SSH 管不到):入站 TCP 8443、UDP 3478。戴轻量云/腾讯云都容易在这层被挡——OS 防火墙开了但公网还是不通,先查安全组。
⑤ DNS:derp-bj.example.com 的 A 记录指向服务器公网 IP,必须灰云(不代理),DERP 走原始 TLS 不能被中间层接管。
6.3 把节点登记进 tailnet:derpMap
Tailscale 管理后台 → Access Controls(ACL 策略),在 JSON 顶层加 derpMap:
"derpMap": {
"OmitDefaultRegions": false,
"Regions": {
"901": {
"RegionID": 901,
"RegionCode": "bj",
"RegionName": "Beijing",
"Nodes": [
{
"Name": "901a",
"RegionID": 901,
"HostName": "derp-bj.example.com",
"IPv4": "<公网IP>",
"DERPPort": 8443,
"STUNPort": 3478
}
]
}
}
}
⚠️ 踩坑:
RegionCode只能放在 Region 这一层,Node 里不能有,否则保存报json: unknown field "RegionCode"。
6.4 让节点真正被用上
保存 derpMap 后,两端的 Tailscale 服务都要重启,让"家区域"重新评估:
# Windows:管理员 PowerShell
Restart-Service Tailscale
关键规律:中继路径按"接收方的家区域"决定——这台机器切到北京没用,对端设备也得切(实测对端还锁在旧金山时,ping 依旧 via DERP(sea);对端重启后立刻变 via DERP(bj))。
6.5 验证
tailscale netcheck # 看自定义区域延迟是否出现(通常 10~40ms)
tailscale debug derp 901 # 直连 DERP 节点做握手+STUN 测试
tailscale ping <对端> # 看实际路径:via DERP(bj) in ~25ms
七、治本可选:路由器端口转发(彻底不用中继)
中继再好也是中继。直接打通 NAT 就能把中继整个省掉:
- tailscaled 默认监听 UDP 41641(
netstat可确认); - 办公室路由器加一条:UDP 41641 → 本机内网 IP;
- 给本机做 DHCP 固定 IP(按 MAC 绑定)——不然 IP 一变规则就失效,这才是"要重加"的真正原因;
- 完成后
tailscale ping从via DERP(bj)变成via <IP>:41641,直连 10~30ms。
八、为什么 ts.net 链接不需要 Token?——私网访问的四层机制
第一次见到 https://<主机名>.<tailnet>.ts.net/ 直接就能打开、连密码都不要,很多人会心里一紧:"这样安全吗?"其实这条链接的公网暴露面为零,它把"认证"前移到了设备身份层——能打开,恰恰是因为你已经是"自己人"。四层机制层层封死:
① 域名解析层(DNS):*.ts.net 下的机器名只由 Tailscale 的 MagicDNS 提供给同一 tailnet 的登录设备。公网 DNS 服务器查不到该机器的记录——外人拿到完整链接也解析不出 IP。
② 路由层(不可达私网段):即使解析成功,得到的也是 100.64.0.0/10(CGNAT)段内的 Tailscale 专有地址(如 100.83.x.x)。该地址段在公网路由器上不可路由——数据包既发不出、也进不来。
③ 传输层(WireGuard 加密):tailnet 设备之间是端到端 WireGuard 隧道;即使报文经由公网中转(如 DERP 中继),内容对任何中间者都是密文。
④ 身份层(登录即钥匙):要"拥有"那个 100.x 地址,设备必须先通过你账号的登录认证(SSO + 设备授权)加入 tailnet。能打开这个链接 = 已经证明"这台设备是你账号里的设备"。想让某人失效?后台把设备移除/吊销密钥即可,不用改任何密码。
对比一下公网入口:CF 隧道 https://dsh.example.com 是真·公网可达——世界上任何人敲这个域名都能触达 Cloudflare 边缘,所以门口必须挂密码锁;而 ts.net 入口的"门"在你登录 Tailscale 那一刻就锁好了,公网上根本无门可敲。
安全要点:
- 安全重心 = Tailscale 账号本身:登录用的身份提供商(如 Google)务必开启两步验证(2FA)与强密码;
- 想更严可以加 ACL:限制只有特定设备/标签能访问本机的 443 端口;
- DSH 内部的配置/凭据类特权 API 仍锁定回环(
trustedHosts只是"信任域名名单",不是认证)——即使 tailnet 设备也调不到,纵深防御多一层。
九、成功结果
延迟对比
| 阶段 | 路径 | 实测延迟 |
|---|---|---|
| ① Cloudflare 隧道 | 公网 + 密码 | 慢(边缘绕行、欧洲节点) |
| ② Tailscale 官方美西中继 | DERP(sea/sfo) | 350~475ms |
| ③ 自建北京 DERP | DERP(bj) | 23~42ms(约 10 倍提升) |
| ④ 路由器转发(待做) | 直连 | ~10~30ms |
最终入口清单
https://<主机名>.<tailnet>.ts.net:tailnet 私网 HTTPS,日常主力(无需密码,设备身份即钥匙)——在外面任何登录同一 tailnet 的设备(手机/Mac/笔记本)打开即是秒开,等于把办公室的 DSH 揣进了兜里https://dsh.example.com:CF 隧道公网入口(带密码),异地无 Tailscale 时的兜底
安全说明
为什么 ts.net 链接不需要密码?因为:
*.ts.net域名只由 MagicDNS 提供给同一账号的登录设备,公网解析不到;- 解析结果是
100.x的 Tailscale 私网段,公网不可路由; - 全程 WireGuard 加密;"身份鉴权"发生在登录 Tailscale 那一步——不是你的设备,链接就是死的。
建议:给登录用的身份提供商(如 Google)开启两步验证;DSH 本身的配置/凭据类特权 API 仍锁定回环(私网访问也调不到),属于第三方服务的纵深防御设计。
十、踩坑汇总(一图流)
| # | 坑 | 现象 | 解法 |
|---|---|---|---|
| 1 | DSH webserver host 校验严格 | CLI 传具体 IP/0.0.0.0 被拒 | 只允许 127.0.0.1/0.0.0.0;走补丁文件改 |
| 2 | 不声明 trustedHosts | 非回环域名 /api 全 403 | 把 ts.net 域名/公网域名加进白名单 |
| 3 | tailscale serve 未开启 | 提示"not enabled on your tailnet" | 管理员后台点一次性开关 |
| 4 | 官方中继全在海外 | 国内互访 170~480ms | 自建国内节点 |
| 5 | 跨运营商 UDP 被丢 | 双方 UDP 通却打不直连 | 接受中继 或 路由器端口转发 |
| 6 | 系统源 Go 版本旧 | 编译报 require go >= x.x.x | 官方 tarball + GOTOOLCHAIN=local |
| 7 | 服务端 GOSUMDB=off | 工具链下载校验失败 | 显式 GOSUMDB=sum.golang.org |
| 8 | Windows 远程 ssh 环境污染 | 远端 PATH 是 Windows 路径、引号被剥 | 命令改写成脚本文件 scp 上去执行 |
| 9 | derper http 端口冲突 | bind address already in use | nginx 占 80/8080,改用 8088 |
| 10 | 证书只装叶子 | 客户端报证书链错误 | acme.sh 装 fullchain |
| 11 | 云安全组 | OS 防火墙开了公网仍不通 | 控制台安全组放行 8443/3478 |
| 12 | derpMap 字段位置 | 保存报 unknown field | RegionCode 只能放 Region 层 |
| 13 | 中继按接收方家区域 | 只切一端没效果 | 两端都重启 Tailscale 重评估 |
| 14 | acme.sh 安装超时 | 国内服务器 github 拉不动 | 从已装好的服务器把脚本转传过去 |
| 15 | Windows schannel 不认新 LE 根 | curl 报 "Failed extracting certificate chain" | 用 openssl s_client 验证;tailscaled(Go) 不受影响 |
十一、工具清单
tailscale serve / status / netcheck / ping / debug derp:链路诊断全家桶acme.sh(DNS-01 签发证书)derper(Tailscale 官方中继程序,go install tailscale.com/cmd/derper@latest)cloudflared(CF 隧道,公网兜底入口)

评论