ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

自建DERP中继服务器:从零部署到优化Tailscale组网延迟

自建DERP中继服务器:从零部署到优化Tailscale组网延迟 1. 为什么要自建 DERP先搞懂中继在组网里的角色1.1 DERP 到底解决什么问题我最早接触 Tailscale 组网的时候其实没把 DERP 当回事。反正设备少、都在国内使用官方默认的 DERP 节点打洞失败就绕一下慢就慢点。直到我把家里的 NAS、公司的办公机、还有一台挂在小鸡上的备用节点全都塞进同一个网络之后问题一下就冒出来了跨运营商、跨地区的中继流量全部挤在官方节点上延迟动不动 200ms 开外远程桌面卡成幻灯片。也就是从那时候开始我才认真研究起自建 DERP 中继服务器这回事。先解释一下 DERP 这个词。DERP 的全称是 Detoured Encrypted Routing Protocol翻译成大白话就是“绕路加密转发协议”。Tailscale 的组网逻辑是优先尝试 P2P 直连也就是让两台设备通过 NAT 穿透直接建立加密隧道这种模式下流量不经过任何中间服务器延迟最低、带宽最好。但现实世界里的网络环境很复杂运营商级 NAT、对称型 NAT、双端都在内网的情况下P2P 打洞经常失败。打洞打不通怎么办流量就只能走一台公网服务器做中继这台公网服务器就是 DERP 节点。很多刚接触 Tailscale 的人有个误区觉得只要组网成功所有流量都是点对点直连的。实际完全不是这样。Tailscale 的整个连接过程是先通过控制服务器交换节点信息然后尝试 P2P 打洞打洞的同时会预连一个 DERP 节点作为保底。如果几秒钟内打洞成功流量切换到直连DERP 链路自动断开如果打洞失败流量就会一直走 DERP 中继。所以 DERP 节点的质量直接决定了你在 NAT 穿透失败场景下的实际体验。自建 DERP 的核心价值就是把“中继路径”掌握在自己手里。官方 DERP 节点虽然覆盖广但总有几个问题绕不开一是部分地区的公网出口到官方节点之间的链路质量不稳定晚高峰丢包和抖动很严重二是官方节点是共享的所有免费用户的中继流量都挤在一起带宽和并发都受限制三是路由绕远比如国内设备通过官方 DERP 中继经常要把数据包发到海外节点再绕回来延迟直接翻倍。自己搭一个离自己网络近的节点这几类问题都能明显缓解。1.2 哪些场景值得自建哪些不要盲目跟风不是所有用 Tailscale 的人都需要自建 DERP。如果只是两三台设备组网而且所在网络环境 NAT 类型比较友好大部分连接都能直连成功那官方 DERP 足够用了。但如果你遇到下面这些情况自建 DERP 的收益会非常明显设备分布在多个城市且中间涉及跨运营商链路比如一台在公司电信网络、一台在家移动宽带NAT 穿透经常失败tailscale status里看到设备名后面挂着一堆relay标记流量全部走中继对远程桌面、SSH 这类交互式操作的延迟敏感官方中继节点绕路导致操作明显卡顿想要对中继节点有完全控制权比如限制哪些设备可以使用、查看日志、调整带宽策略或者单纯不想让流量经过别人维护的节点。反过来如果你的设备和目标机器都在同一个城市、同一个运营商而且确认大多数时候都是direct直连那自建 DERP 的收益就很小。我在一开始部署的时候也有过不切实际的期待以为换了自建节点所有流量都会变快后来实测才发现P2P 打洞成功的流量本来就不走 DERP换节点对这部分连接没有任何影响。所以自建 DERP 解决的是“打洞失败后的中继体验”不是“所有连接的加速器”这个定位一定要搞清楚。2. 部署前要先想清楚的几个问题2.1 服务器选型和网络要求自建 DERP 对服务器的性能要求其实很低。DERP 本质是一个加密转发服务主要吃带宽和连接数CPU 和内存的消耗非常小。我最初用一台 1 核 1G 的 VPS 跑中继带宽跑满 50Mbps 的时候CPU 占用也就 30% 左右内存稳定在 100MB 以内。所以选服务器的时候优先关注的不是配置而是网络质量。网络方面有几个硬性要求。第一服务器必须拥有公网 IP最好是独立 IP不要是运营商 NAT 出来的共享 IP否则 DERP 客户端连不上你自建的意义就没了。第二到你的常用设备之间的链路质量要好。我在选型时最看重的是延迟和丢包率会先通过 ping 和 traceroute 实测一下目标机器到这台服务器的质量特别是晚高峰时段的表现。第三带宽要够。DERP 中继是所有流量都经过服务器转发的带宽直接决定了你在打洞失败场景下的实际传输速度。如果目的是远程桌面这种交互操作5Mbps 上行基本够用如果还要传文件建议选带宽上限高一点的机器。还有一个容易忽略的点IPv6。现在不少 Tailscale 设备之间可以通过 IPv6 直连打洞成功率远高于 IPv4。如果服务器支持 IPv6 并且能正确配置DERP 节点本身也能同时监听 IPv6 地址对整体连接质量有正向帮助。我后来在服务端把 IPv6 也配上了某些原本走 IPv4 中继的流量直接变成了 IPv6 直连延迟降了一截。2.2 域名、证书和端口规划DERP 节点强制要求 HTTPS也就是说必须有一个域名并且需要有合法证书。原因很简单Tailscale 客户端只信任带有效 TLS 证书的 DERP 节点自签名证书不会用。所以部署前需要准备一个能正常解析到这台服务器公网 IP 的域名比如derp.example.com。端口规划上DERP 服务默认监听三个端口端口协议用途443TCPDERP 中继主流量80TCPLets Encrypt 证书自动续期验证3478UDPSTUN 服务用于辅助 NAT 穿透探测部署前最好确认一下这三类端口都是空闲的尤其是 443。如果服务器上已经跑了 Nginx、Caddy 或者其他 Web 服务占用了 443 端口需要先把现有服务迁移走或者给 DERP 换一个监听地址。80 端口同理证书自动签发需要用到它。3478 是 UDP 端口云服务商的安全组和服务器本机防火墙都要放行否则 STUN 探测会失败节点虽然能连但无法参与 NAT 穿透的辅助工作。证书方案我推荐直接用 Lets Encrypt 自动签发。DERP 程序内置了 ACME 客户端只要配置好域名和监听端口首次启动时自动申请证书到期自动续期全程不需要人工介入。如果你已经有了泛域名证书或者想用其他证书颁发机构的证书也可以用 manual 模式指定证书目录但日常使用没必要自己折腾自动签发省心得多。2.3 官方控制平面 vs 自建控制平面这里要提前想清楚一个关键问题你的自定义 DERP 节点要如何让 Tailscale 客户端知道。如果你用的是官方 Tailscale 账号标准做法是通过官方的企业版 DERP 地图功能把自定义 DERP 节点加入配置。但企业版需要付费订阅个人用户基本用不上。个人场景下更可行的方案是搭配自建控制平面使用比如 Headscale。Headscale 是开源的 Tailscale 控制服务器可以自己部署所有客户端通过它来分配身份和管理网络拓扑自定义 DERP 地图在 Headscale 配置里是很基础的功能。我最终选择的方案就是Headscale 独立 DERP 节点的组合。Headscale 负责设备认证和网络配置下发DERP 节点负责中继转发。两者可以部署在同一台服务器上也可以分开部署逻辑上互不依赖。如果只是验证 DERP 本身也可以先单独把 DERP 节点跑起来通过浏览器访问节点地址看到一个状态页面就说明服务已经正常工作了。等到真正接入组网的时候再把 DERP 地址配置到 Headscale 里。3. 服务端部署从零跑起一个 DERP 节点3.1 获取并编译 derper 二进制DERP 服务端的官方实现就在 Tailscale 的主仓库里是一个独立的命令行工具。部署方式有两种直接下载官方预编译产物或者从源码编译。我习惯从源码编译因为官方发布节奏快预编译产物不一定是最新版本而且编译过程很简单。编译环境需要安装 Go 语言版本要求一般看仓库的 go.mod。在服务器上执行# 安装基础依赖以 Debian/Ubuntu 为例 apt update apt install -y build-essential git # 安装 Go具体版本以官方仓库要求为准这里用 1.22 举例 wget https://go.dev/dl/go1.22.5.linux-amd64.tar.gz tar -C /usr/local -xzf go1.22.5.linux-amd64.tar.gz export PATH$PATH:/usr/local/go/bin # 拉取源码并编译 derper git clone https://github.com/tailscale/tailscale.git cd tailscale/cmd/derper go build -o /usr/local/bin/derper编译完成后可以用derper -help查看全部参数不同版本的参数略有差异部署前先阅读一下帮助信息再动手。我早期就是直接照着网上的旧教程写参数结果某个版本改了参数名启动直接报错排了半天才发现是版本问题。所以这条经验很重要跑任何开源工具之前先看一遍-help输出。3.2 首次运行与证书自动签发目录结构先规划好。我习惯把 DERP 的数据目录放在/var/lib/derper下面证书也统一存到这个目录方便备份和管理mkdir -p /var/lib/derper/certs然后运行 derper。假设你的域名是derp.example.com第一次启动命令如下/usr/local/bin/derper \ -hostnamederp.example.com \ -certmodeletsencrypt \ -certdir/var/lib/derper/certs \ -a:443 \ -http-port80 \ -stun-port3478参数说明-hostname是节点的域名证书会按这个域名签发-certmodeletsencrypt表示使用 Lets Encrypt 自动签发证书-certdir指定证书保存目录-a:443是主服务的监听地址-http-port80是 ACME 验证使用的 HTTP 端口-stun-port3478是 STUN 服务使用的 UDP 端口。首次启动后如果一切正常会看到类似日志输出说明证书申请成功并且 HTTPS 服务已经启动。这时候直接在浏览器里访问https://derp.example.com如果看到一个 DERP 的状态页面上面有服务信息说明节点已经跑通了。这一步是纯服务端自检不依赖任何控制平面配置我强烈建议在接入组网之前先做完。自检通过之后再往下走能省掉后面排查时的大量干扰项。如果你的服务器上有其他软件占用了 80 或 443 端口上面这步启动会失败。需要先把冲突解决掉或者把 DERP 的端口改掉。但改端口意味着客户端也要跟着改增加复杂度所以尽量保持标准端口不变。3.3 用 systemd 守护进程直接命令行运行有两个问题一是 SSH 断开后进程会退出二是崩溃后不会自动重启。生产环境一定要用 systemd 把它托管起来。创建服务文件vim /etc/systemd/system/derper.service内容如下[Unit] DescriptionTailscale DERP Server Afternetwork.target [Service] ExecStart/usr/local/bin/derper \ -hostnamederp.example.com \ -certmodeletsencrypt \ -certdir/var/lib/derper/certs \ -a:443 \ -http-port80 \ -stun-port3478 Restartalways RestartSec5 Userroot [Install] WantedBymulti-user.target这里用 Userroot 是因为 Lets Encrypt 证书目录和特权端口的权限问题个人服务器这样用没问题。如果你更讲究一点可以单独建一个 derper 用户给/var/lib/derper目录授权后以非 root 身份运行。不过要注意绑定 443 端口需要 CAP_NET_BIND_SERVICE 权限非 root 用户需要用ambient_capabilities或者端口重定向来绕配置会复杂不少。我的建议是个人场景直接用 root 跑简单可靠。然后启动并设置开机自启systemctl daemon-reload systemctl enable --now derper systemctl status derper3.4 防火墙和云安全组配置这个环节最容易踩坑。很多人的 DERP 服务明明已经启动了浏览器访问域名也能打开状态页但 Tailscale 客户端就是连不上排查到最后发现是防火墙没放行 UDP 3478 端口。以云服务器为例需要同时检查两层。第一层是云控制台的安全组确认放行 TCP 80、TCP 443、UDP 3478。第二层是服务器本机的防火墙如果用的是 ufw执行ufw allow 80/tcp ufw allow 443/tcp ufw allow 3478/udp ufw reload确认端口监听状态ss -lntup | grep -E :(80|443|3478)如果看到 derper 进程同时监听了 443 和 3478说明端口层面没问题了。STUN 服务用的是 UDP用ss -ulnp单独看一眼比较稳妥因为有些系统上ss -lntup默认只显示 TCP。部署完之后如果想确认公网层面的端口可达性可以用本机测试工具或者云控制台自带的“端口连通性检测”从外部打一下 TCP 443 和 UDP 3478确认没有中间链路拦截。4. 把自定义 DERP 接入组网并验证效果4.1 通过 Headscale 声明自定义 DERP如果按我前面说的方案走了 Headscale那在 Headscale 配置文件里声明自定义 DERP 节点就可以了。不同版本的 Headscale 字段名有些变动我用当前比较常见的格式来举例。在 Headscale 的config.yaml中关于 DERP 的配置大致如下derp: server: enabled: true region_id: 999 region_code: myderp region_name: My DERP Server stun_listen_addr: 0.0.0.0:3478 private_key_path: /var/lib/headscale/derp_server_private.key automatically_add_embedded_derp_region: true ipv4: 1.2.3.4 ipv6: urls: - https://control.example.com/derpmap paths: [] auto_update_enabled: true update_frequency: 24h其中derp.server.enabled表示是否启用 Headscale 内置的 DERP 服务。如果你已经单独部署了独立的 derper 进程可以不启用内置 DERP而是在derp.urls或derp.paths里指向你的 DERP 地图文件。社区里更常见的做法是直接把automatically_add_embedded_derp_region设为 true让 Headscale 内置的 DERP 节点自动加载自己的 region 信息。需要注意Headscale 和 derper 的关系是独立进程。Headscale 只负责把 DERP 节点信息下发给客户端真正的数据转发还是由 derper 进程完成。所以要么用 Headscale 内置 DERP要么单独跑 derper 然后在 Headscale 里声明它的地址两边不会自动联动。节点配置完成后重启 Headscale 服务让配置生效systemctl restart headscale然后用headscale debug derp命令检查一下 DERP 节点状态这个命令会返回当前控制平面下发的 DERP 地图和健康检查结果能看到你的自定义节点是否被客户端正常拉取。4.2 用 tailscale netcheck 和 status 验证节点质量客户端接入 Headscale 之后第一件要做的事是跑tailscale netcheck。这个命令会从客户端视角测试当前网络的 NAT 类型以及所有已知 DERP 节点的延迟情况tailscale netcheck输出里会列出每个 DERP 节点的latency。如果自定义节点配置正确且网络链路通畅你的节点应该会出现在列表里并且延迟数值会明显低于那些绕远路的官方节点。这一步是验证 DERP 接入是否成功的最直接证据。然后查看设备连接状态tailscale status这条命令的输出中每一行代表一个远端设备。如果设备后面的连接方式是direct说明是 P2P 直连如果显示relay derp-xxx说明当前流量正在走 DERP 中继括号里的名字就是实际使用的节点。举个例子。我在部署前家里设备到同城另一台设备显示的是relay derp-sfo延迟在 180ms 左右。部署完自定义节点后同样的两台设备变成relay derp-myderp延迟降到了 20ms 以内。这个对比效果非常直观。如果你的设备本来就是direct直连那即使配置了自定义 DERP也不会走中继这种情况不用慌说明你的 NAT 穿透是成功的。4.3 强制走 DERP 来验证中继链路有经验的读者会注意到如果大多数连接都成功打洞直连了你其实很难测到 DERP 中继的真实效果。这时候可以主动强制流量走中继。Tailscale 提供了一个调试参数可以临时禁用 P2P 直连强制所有流量走 DERPtailscale up --force-derp注意这个参数会改变客户端的当前连接模式测试完记得恢复。执行后再次tailscale status能看到所有远端设备都变成了relay状态此时去执行 ping 或者实际访问一下远端服务感受到的延迟就是真实的中继链路延迟。我用这个方法对比过官方 DERP 和自建 DERP 的效果。同样是强制走中继同城自建节点延迟 12ms官方海外节点延迟 190ms差距非常夸张。有一点要说明强行走 DERP 时带宽也受限于服务器带宽如果服务器上行带宽不够测出来的速度会很难看但这恰恰说明自建 DERP 的带宽规划很重要。5. 常见问题与排查记录5.1 证书和端口类问题浏览器能打开 DERP 状态页但客户端连接失败。这种情况十有八九是 UDP 3478 没有放行。DERP 数据转发走 TCP 443但 STUN 探测走 UDP 3478如果这个端口不通客户端虽然能看到节点却无法完成 NAT 辅助探测网络质量会大打折扣。排查命令# 在另一台外网机器上测试 UDP 端口 nc -u -v derp.example.com 3478Lets Encrypt 证书申请失败。最常见的原因是域名解析还没生效或者 80 端口被其他程序占用。ACME 验证流程是 Lets Encrypt 服务器通过 HTTP 访问你的 80 端口来验证域名所有权。如果 80 端口被 Nginx 占用了申请就会失败。用curl http://你的域名/.well-known/acme-challenge/测试一下是否能正常响应如果超时优先检查安全组和本机防火墙。证书过期后续期失败。derper 的 letsencrypt 模式默认会自动续期但续期同样依赖 80 端口可达。如果之后你在服务器上装了其他 Web 服务可能会把 80 端口挤掉续期随之失败。这时候要么调整 derper 的监听端口要么把证书续期逻辑改到 manual 模式配合外部 cron 任务处理。5.2 打洞失败和延迟高的问题很多用户反映 Tailscale 组网后延迟很高但看了tailscale status却显示direct这种情况跟 DERP 没关系问题出在 P2P 路径本身质量差。常见的诱因是跨运营商链路比如一方是电信、一方是联通虽然打洞成功但数据包走的运营商互联出口在晚高峰拥塞延迟和丢包都会上去。这种问题换 DERP 节点也没用因为直连路径并没有经过 DERP。如果是relay状态导致的延迟高自建 DERP 可以有效缓解。但还有一种情况需要注意即使你自建了节点如果客户端到自定义节点的链路本身质量很差中继延迟一样会高。所以选服务器时一定要实测目标设备到服务器的链路质量我就是因为一开始选了一家便宜但路由绕远的 VPS部署完发现延迟比官方节点还高最后换了一台同城线路才正常。如果你是两侧都开启了 IPv6 的现代网络设备可以优先把 IPv6 打洞通道优化好。我实测下来IPv6 的 P2P 打洞成功率远高于 IPv4很多原本需要走 DERP 中继的连接在 IPv6 环境下可以直接直连。5.3 Tailscale IP 无法远程桌面的排查思路这个热搜词背后的问题很典型设备在 Tailscale 网络里都能 ping 通但用 Tailscale IP 连远程桌面就是连不上。我从自己踩过的坑里总结出三个排查方向。第一远程桌面服务本身只监听了物理网卡的 IP没有监听 Tailscale 虚拟网卡的 IP。在目标机器上执行netstat -ano | findstr 3389查看监听地址如果只监听了0.0.0.0:3389反而没问题真正有问题的是 Windows 防火墙。第二Windows 防火墙的远程桌面入站规则默认只允许“专用网络”访问而 Tailscale 虚拟网卡经常被识别为“公用网络”导致 3389 端口被挡。解决方法是手动为 Tailscale 网卡所在网络配置文件切换为专用网络或者在防火墙高级设置里单独加一条允许 3389 入站的规则作用域限定在 Tailscale 网卡的那个网段。第三RDP 客户端工具默认可能没有正确关联 Tailscale 的 DNS 映射。如果你习惯用机器名访问而不是 IP需要确认 Headscale 或官方控制平面下发的 DNS 解析是否正常。用 IP 直连通常是最稳的排障手段先用tailscale ping通的 IP 直接连 RDP。5.4 Tailscale 安装后打不开浏览器的问题有部分用户会遇到 Tailscale 客户端安装后双击图标没反应或者没有自动弹出登录浏览器窗口的情况。这个问题跟自建 DERP 没有直接关系但在排障时经常碰到。Windows 版最典型的原因是 tailscaled 服务没有启动成功或者系统代理设置影响了默认浏览器的打开动作。比较省事的处理方式是在命令行里手动执行一次tailscale login如果用的是自建 Headscale 控制平面还需要带上--login-server参数tailscale login --login-server https://control.example.com这条命令会手动触发登录流程并在终端里输出一段登录 URL复制到浏览器打开即可。如果连 URL 都没输出说明客户端后台服务有问题需要去 Windows 服务管理器里确认 Tailscale 服务的状态再查看系统日志定位原因。5.5 自建 DERP 的防滥用配置最后想额外提醒一个安全点自建 DERP 节点如果不加任何访问控制它在公网上就是一个完全开放的转发服务任何人都可以把你当成免费中继节点使用不仅消耗带宽还可能产生安全风险。个人使用场景下至少要做到两点一是不要把你的节点地址到处公开二是在 derper 启动参数里加上客户端校验功能具体参数名称在你使用的版本里用derper -help查一下不同版本有差异。加了校验之后只有 Tailscale 网络内通过认证的设备才能使用这个节点其他请求会被拒绝。我在实际部署中还养成了一个习惯就是定期查看 derper 的访问日志和带宽监控。如果发现某个时间段的连接数异常暴涨优先检查是不是节点信息泄露了。自建服务本质上跟开源软件一样能力越大责任越大安全配置不能偷懒。从我个人经验来看自建 DERP 是 Tailscale 组网体验里性价比最高的一次优化。只需要一台带宽尚可的公网服务器、一个域名、半小时的配置时间就能把中继延迟从“不可用”拉回“可接受”。但也要再次强调DERP 不是银弹它只解决打洞失败后的中继问题。如果你的目标是让所有连接都快优先要做的还是优化 NAT 穿透环境让两端尽量直连。先把 DERP 这条保底路线铺好再把直连率提上去整个组网体验才会真正顺滑。
返回列表