← 知识库 / 未分类

自建远控中继踩坑记:从一台轻量服务器说起

用一台低配轻量服务器自建 RustDesk 中继,摆脱免费通道排队。记录从选型到上线踩过的五个坑,以及一个反直觉的调试技巧。

这是一次「想要少受点气」的折腾记录。免费远控通道排队排到怀疑人生,于是决定自己搭一个中转。

为什么要自建

用远控不算高频,但每次遇到「免费通道排队中,您是第 3 位」就很烦。市面上的免费方案要么限速、要么限时长、要么隔三差五弹广告让你升级。

而远控这件事,本质上只需要一个东西:一个能让两端找到彼此、并帮忙转发数据的中间人。这个东西的开源自建方案早就很成熟了,一台最便宜的云服务器就够。

于是手上那台只跑了个静态站点的低配轻量服务器,就顺手多接了一份活。

先把架构想清楚

自建远控中继其实只有两个组件:

组件干什么
ID / 打洞服务设备上线后向它登记「我是谁、在哪」,由它牵线做 NAT 打洞
中继服务打洞失败时的备胎,帮忙转发数据流

关键在于连接是有优先级的:

两端都登记 → 尝试 P2P 打洞
  ├── 成功 → 数据直接在两端之间跑,服务器完全不参与 ✅
  └── 失败 → 回落到中继,数据绕道服务器 ⚠️

这个优先级决定了整套方案是「免费好用」还是「带宽焦虑」——后面会看到,它也是最大的坑。

端口方面是固定的四个:三个 TCP 加一个 UDP。记住「有一个 UDP」,因为这是坑一号。

坑之一:那个被漏掉的 UDP 端口

配置防火墙的时候,我很自然地加了三个 TCP 端口。然后客户端连不上。

排查了半天才想起来:登记和心跳走的是 UDP,不是 TCP。

21115 TCP  → NAT 类型测试
21116 TCP  → 打洞
21116 UDP  → ★ 设备注册与心跳(就是这条)
21117 TCP  → 中继

为什么容易漏?因为前三个都是 TCP,第四行看上去像是前三行的重复(同一个端口号 21116),很容易在复制粘贴放行规则时被顺手忽略。

症状也很有迷惑性:客户端能启动、界面正常,但一直显示「未就绪 / 离线」。因为它在等一个永远没回来的 UDP 响应。

教训:端口清单要连协议一起抄,不要只抄端口号。看到「同号不同协议」的行,单独标出来。

坑之二:连上了 ≠ 直连

这是最阴的一个坑,因为它没有任何提示。

远控通了,画面流畅,你理所当然地认为走的是 P2P 直连。但实际上:

打洞失败会静默回落到中继,不中断会话、不弹任何提示。

也就是说,「能用」和「没花我的带宽」是两件事。而小带宽服务器的中继体验是:一旦回落,所有流量都要从这台机器绕一圈,速度和流量双杀。

判断方法有几个,最省事的两个:

方法一:悬停看提示。 远控窗口顶部有个连接状态小图标,鼠标悬停会显示 Direct / P2P(直连)还是 Relay(中继)。

⚠️ 这里有个细节:只看文字,别只看颜色。不同版本的图标配色居然不一样,甚至出现过「绿色代表中继、橙色代表直连」这种反直觉的配色。信文字。

方法二:用带宽上限反推。 这招我觉得挺巧妙——

中继速度不可能超过服务器带宽。所以:

服务器带宽中继的理论上限
3 Mbps≈ 375 KB/s
5 Mbps≈ 625 KB/s

于是传一个几百兆的文件看速度:只要明显超过 375 KB/s,就绝对不可能是中继,必然是直连。不需要登服务器、不需要装工具,看进度条就行。

反过来,如果速度死死贴着 375 KB/s 上不去——那就是在走中继,别怀疑网速了,就是这个原因。

教训:任何「有降级路径」的系统,都要显式确认当前走在哪条路径上。默认值不适合拿来当结论。

坑之三:「托盘唤出才能连」

这个现象很具体,也很好复现:

远控软件开着放后台一段时间,就连不上了。必须双击托盘图标把窗口唤出来,才能重新连上。

看到这个症状,基本可以直接下结论:后台服务没在跑,是图形界面在硬撑。

原理不难推:远控软件分成两部分——

部分身份行为
服务系统级身份运行开机自启,登录前就可用,不受窗口状态影响
图形界面当前登录用户窗口最小化/关闭后,会被系统当成”后台应用”节流甚至挂起

服务没跑的时候,连接职责就落到了图形界面进程上。而它一旦被系统节流,就停止向服务器发心跳——在别人眼里,这台机器就「离线」了。双击托盘图标把窗口唤醒,心跳恢复,于是又能连上。

判别方法只有一个,但一锤定音:

任务管理器 → 详细信息 → 找到远控进程 → 看「会话 ID」列

必须存在 SessionId = 0 的进程   ← 这才是服务进程
如果全是非 0 的值               ← 服务没跑,连接是图形界面在撑

修复要先确认服务状态和启动类型,然后补上失败自动重启策略——大多数安装默认这条是空的,意味着服务一旦被停就再也不会自己起来。

还有一个必须记住的操作禁令:

永远不要从托盘右键菜单选「退出」。

这个操作会把服务一起停掉。此后即使托盘图标还挂在那儿,服务已经没了,连接又退回给图形界面——于是又进入「放一会儿就连不上」的循环。

要收起窗口就用「关闭窗口」或最小化到托盘,不要点「退出」。

坑之四:欢迎来到「现代待机」

修完服务,本以为稳了。结果发现这台机器只支持一种睡眠模式(现代待机 / Modern Standby),连传统的 S3 都不支持。

现代待机的特点是:睡觉时网络还连着,但后台应用会被挂起。

所以「插电不睡眠」这件事必须先确认。查一下电源计划里的睡眠超时:

  • 交流(插电):建议设为从不
  • 直流(电池):笔记本上别盲目设成从不,那会把电池耗干 —— 更合理的做法是被控机保持插电

顺手记一个冷知识:中文系统上查服务恢复策略时,那个「重启延迟」的单位会被显示成微秒。别慌,实际是毫秒,是翻译 bug。

坑之五:别在小带宽服务器上测「高画质」

带宽是硬约束。3 Mbps 的服务器做中继,满速也就 375 KB/s,换算下来:

0.375 MB/s × 3600 s ≈ 1.32 GB/小时

一个月 200 GB 的流量包,如果全程满速中继,只够约 151 小时。

所以正确的期待是:

用途能不能行
看文档、点按钮、轻度运维✅ 没问题
局域网内互控✅ 走内网直连,完全不吃服务器
高清视频、大文件传输❌ 别指望,换网盘

顺带一个反直觉点:设备变多不会线性加重服务器负担。因为服务器只在打洞牵线阶段参与,直连成功后数据根本不经过它。真正会累积的是「同时有几对连接在走中继」。

顺手学会的一个调试技巧

这次还有一个意外收获,是关于「怎么摸清一个没文档的接口」。

自建过程中需要调用服务器面板的 API 来创建容器编排,但这个接口的字段名没有文档。正常做法是去翻源码或者猜,但这两样都费劲。

后来用了一个零副作用的探测方法:拿校验类接口当探针,靠报错反推字段名。

具体就是:

  1. 先传一个不存在的字段名。如果报错说某个字段 required,说明那个字段名是对的、只是值没给;如果报的是别的错,说明你传的这个名字被忽略了。
  2. 再传一个非法的枚举值。报「取值不在允许集合内」说明字段名对了,把候选值逐个试到返回成功为止。
  3. 全程选那种只校验不落盘的接口,不产生任何实际变更。

用这招五分钟就摸清了:内容字段叫 file 而不是 fileContent(猜 fileContent 会报「空内容」),来源字段只接受 edit 或 template。

还有一条纪律,是从这次踩坑里总结出来的:

接口返回「成功」不算数,只认实际状态。

创建编排返回了成功码,但列表里查不到——一度以为是失败。回读磁盘才发现文件早就写好了,只是那个列表接口统计口径不同(未启动的编排不列出)。

后来凡是这类操作,一律回读落盘结果:文件读出来对不对、端口是不是真在监听、进程的会话 ID 是不是 0。

「配置已就绪」和「运行时已接通」永远是两件事。

一个容易被忽略的安全问题

后来有人问我:能不能在别人的电脑上,临时远控自己家里的机器?

技术上完全可以,而且架构本身是安全的——远控会话是端到端加密的,中继服务器即使被打穿也解不开内容,它只能看到加密后的数据流。这正是自建中继最大的价值。

但风险不在中继,在那台陌生的电脑。

风险说明
键盘记录器你的固定密码是敲键盘输进去的。被记录 → 机器永久暴露,不只是这一次
配置残留服务器地址和密钥会留在那台机器的配置文件里
被安全软件拦便携版远控工具是已知的常见攻击手法,企业网、网吧的安全策略经常拦截告警——你的行为看起来就像攻击者

关键认知是:接入密钥保护的是「中继不被陌生人白嫖」,它并不限制谁能连你的被控端。 后者的唯一门槛就是那把永久的固定密码。

所以从陌生电脑连一次,等于把这把永久钥匙暴露一次。

比较合理的做法是:

  1. 首选用自己的手机——零安装、零残留、不触发告警。只看状态、点几下操作完全够用。
  2. 非要用电脑时,U 盘带便携版,配置写在 U 盘上,用完拔走。
  3. 只能装在本机时,用完立刻改掉固定密码,再清历史记录和配置目录。
  4. 会话里关掉剪贴板同步和文件传输,并且不要在里面输入银行或主密码——远端那台你信得过,本地这台不一定。

收尾

回头看,这套东西真正花时间的不是搭建,而是排障。而且踩的坑全都不在”网络不通”这个层面:

  • 漏了一个 UDP 端口
  • 一条静默降级路径
  • 一个没在跑的后台服务
  • 一个没注意到的睡眠模式

四个问题,看起来都像「连不上」,但根因分属防火墙、协议协商、进程模型、电源管理四个完全不同的层。

所以如果让我总结一条经验:

遇到「连不上」,先确定问题在哪一层,再动手。 端口探测能区分「防火墙没放行」(超时)和「服务没启动」(快速拒绝)——这两个症状很像,但修法完全相反。 服务类问题看进程会话 ID 是不是 0,比看服务状态更准。 而性能类问题,先确认走的是哪条路径。

以及那个反复出现的教训:任何「返回成功」都不能当作完成,要回读真实状态。

折腾完的收益是:不用再排队了,而且数据完全在自己手里。至于那台只跑静态站点的服务器——现在它一天多干两份活,看起来毫无怨言。