☰
RustDesk自建远程方案:编译客户端并固化服务器地址与Key
2026/10/5 13:39:19 网站建设 项目流程

最近又把 RustDesk 的自建链路完整走了一遍:服务器端自己编译 hbbs/hbbr,客户端也自己编译,并且把自建 ID 服务器地址和 key 直接写进了客户端里。折腾完之后最大的感受是,一旦服务器和 key 不用手动填,整个分发体验完全不一样——给别人发一个安装包,对方装上打开就能连你自己的服务器,不用解释什么叫 ID 服务器、什么叫 key,更不用在多个输入框之间来回切。这篇文章我就把整个过程中我认为最关键的几个环节,包括服务端部署、客户端编译、以及三种把服务器信息固化进客户端的方法,原原本本记录下来,给打算自己搞一套 RustDesk 远程方案的朋友做个参考。

1. 为什么非要把服务器和 key 编进客户端不可

1.1 公共服务器与自建服务器的差距

RustDesk 官方公共服务器对个人偶尔用一下来说是够的,但一旦你把它当日常工具,问题马上会浮现:高峰期连接不稳、跨地域延迟忽高忽低、中继带宽有限。更重要的是,数据链路完全不受你控制,这对企业用户或者对隐私比较敏感的人来讲,始终是个心结。

自建之后,整套链路都在自己手里:客户端向你的 ID 服务器注册身份、两个设备互相发现、中继服务器转发流量,全走你自己的机器和带宽。这在企业内网、跨地域小团队、或者单纯喜欢数据可控的个人场景里,价值非常明显。

1.2 真正的痛点不是部署,而是客户端配置

服务端部署好之后,你自己用很简单,填一下地址和 key 就行。但如果你要把客户端分发给同事、客户,或者家里好几台设备重装系统,问题就来了——非技术用户面对"ID 服务器""中继服务器""Key"这几个输入框,很容易卡住。

key 尤其容易错。它是服务器生成的 ed25519 公钥,一长串 base64 字符串,复制粘贴时前面多一个空格、或者换行被带进去,都会导致连接失败,界面上弹出一个很费解的提示。我见到的"key 值未知"错误,多半就是这么来的。

1.3 三种"写入"方式的利弊对比

把服务器地址和 key 固化进客户端,常见有三条路:编译期改默认值、预置配置文件、安装后脚本注入。我分别试过,先给个对比。

方案侵入性分发体验适用场景
编译期改默认值每次升级要重新改最好,开箱即用固定服务器的团队长期使用
预置配置文件/数据库无,拷贝文件即可好,但要在首次启动前放好批量机器、临时分发
界面手动填写无差,依赖使用者操作个人自用、个位数设备

实际项目中我倾向于组合使用:编译期改默认值解决"开箱即用"的问题,配置文件预置应对那些老版本客户端或者不想重新编译的机器。

2. 服务端先行:hbbs/hbbr 部署与 key 生成

2.1 服务端源码编译

RustDesk 的服务端是独立仓库rustdesk-server,包含两个核心二进制:hbbs是 ID 服务器和信令服务器,负责设备注册与连接协商;hbbr是中继服务器,负责在无法直连时为两端转发流量。

编译过程很简单:

git clone https://github.com/rustdesk/rustdesk-server.git cd rustdesk-server cargo build --release

编译产物在target/release/目录下,我们需要的是hbbs和hbbr这两个文件。如果你的服务器内存偏小,编译时间会比较长,建议放到 2G 内存以上的机器上操作,或者干脆用官方 release 里的预编译二进制。标题既然讲自己编译,这里就走源码编译路线。

2.2 首次运行生成 key

把hbbs、hbbr放到服务器的固定目录,比如/opt/rustdesk-server/,然后第一次启动:

cd /opt/rustdesk-server ./hbbs -r your-server.com:21117 ./hbbr

第一次运行后,目录下会生成id_ed25519和id_ed25519.pub两个文件。id_ed25519.pub里的内容,就是客户端设置界面需要填的那个 key。这串公钥相当于服务器身份凭证:客户端拿着它,才能确认自己连的服务器确实是你搭的那台,防止中间人冒充。

这里有一个非常容易踩的坑:id_ed25519私钥必须备份好,并且不要随意删除。一旦服务端目录被清空导致重新生成密钥,所有已经配置好的客户端都会弹出 key 不匹配的提示,全部要重新改配置,相当痛苦。

2.3 端口清单与防火墙放行

服务端需要放行的端口有规律,整理成一张表方便对照:

端口协议用途
21115TCPNAT 类型检测
21116TCP + UDP客户端注册与信令交换,UDP 为主
21117TCPhbbr 中继数据传输
21118TCPWeb 客户端支持,可选
21119TCPWeb 中继支持,可选

如果你在云服务器上部署,除了服务器本身的防火墙(iptables/firewalld/ufw),还要检查云控制台的安全组规则,两个地方都得放行。国内用户如果喜欢用宝塔面板,也要在面板防火墙里同步放行这些端口,不然客户端能 ping 通机器,但连接总是超时。

2.4 用 systemd 守护进程

nohup ... &在调试阶段没问题,但生产环境我更推荐用 systemd 托管,防止进程挂掉后没人管。写两个 service 文件,分别守护hbbs和hbbr,启动命令里带上-r参数指定中继地址,并设置开机自启。

# /etc/systemd/system/rustdesk-hbbs.service [Unit] Description=RustDesk ID Server After=network.target [Service] Type=simple WorkingDirectory=/opt/rustdesk-server ExecStart=/opt/rustdesk-server/hbbs -r your-server.com:21117 Restart=always RestartSec=3 [Install] WantedBy=multi-user.target

hbbr的 service 文件照葫芦画瓢,ExecStart 换成/opt/rustdesk-server/hbbr即可。

3. 客户端编译环境:版本选型与依赖准备

3.1 RustDesk 客户端的两个时代

RustDesk 客户端源码变化很大,网上教程用的是老版本(v1.1.x,Sciter UI),而现在已经普遍切换到 Flutter UI 的新版本(v1.2+、v1.3+)。两代产品的编译方式和源码路径都不一样,如果你跟着老教程走,很可能会卡在某一步找不到对应文件。

我的建议是:直接用当前官方 release tag,比如 v1.3.x,不要盲目追 master。master 分支处于持续开发状态,今天能编译,明天可能因为一个依赖变更就报错。锁定稳定版本,遇到问题也好查。

git clone https://github.com/rustdesk/rustdesk.git cd rustdesk git checkout v1.3.x

3.2 Linux 编译环境

在 Linux 下编译 Linux 客户端,需要准备 Rust 工具链和一堆系统依赖。Rust 安装用 rustup 官方脚本即可:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

系统库方面,Ubuntu/Debian 系大致需要这些:

sudo apt install build-essential pkg-config cmake git \ libgtk-3-dev libssl-dev libasound2-dev libavcodec-dev \ libavformat-dev libavutil-dev libswscale-dev \ libx11-dev libxext-dev libxinerama-dev libxcursor-dev \ libxdamage-dev libxfixes-dev libxi-dev libxkbcommon-dev \ libvpx-dev libopus-dev

不同版本的依赖列表会变,最权威的还是仓库里的 README 和build.py脚本。我的经验是,把build-essential、pkg-config、libssl-dev、libgtk-3-dev这几个装好,大部分编译错误就能消掉一半。

3.3 Windows 编译环境

Windows 下编译 Windows 客户端,条件会多一点:

  1. 安装 Visual Studio Build Tools 2019 或 2022,勾选"使用 C++ 的桌面开发"工作负载。
  2. 安装 Rust 的 MSVC 工具链。
  3. 安装 vcpkg,并配置VCPKG_ROOT环境变量。
  4. 通过 vcpkg 安装 RustDesk 依赖的 C 库,比如libvpx。
git clone https://github.com/microsoft/vcpkg.git cd vcpkg .\bootstrap-vcpkg.bat .\vcpkg install libvpx:x64-windows-static $env:VCPKG_ROOT = "C:\path\to\vcpkg"

在 Windows 上最稳妥的编译方式,是用"x64 Native Tools Command Prompt for VS"打开终端,再执行 cargo 命令。否则容易遇到link.exe找不到的问题。

3.4 新版 Flutter UI 的额外步骤

如果你拉取的是 Flutter UI 版本,编译时还需要 Flutter SDK。桌面客户端通常是先编译 Rust 核心,再构建 Flutter 界面层。手动步骤繁琐,官方提供了build.py脚本,建议直接用:

python build.py --flutter --release

这个脚本会处理 Rust 和 Flutter 两部分的构建,并且自动把它们打包成安装包。如果你想验证自己的代码修改,也可以先只跑cargo build --release,构建单独的 Rust 可执行文件。

4. 把 ID 服务器和 key 写进客户端的三种做法

4.1 做法一:编译期改默认常量

这是最彻底的方案,也是标题里说的"写入客户端"的标准做法。思路很简单:RustDesk 客户端源码里必然存在一组默认服务器地址和默认 key,程序首次启动时会读这些默认值。我们只要把它们改成自己的服务器和公钥就行。

问题是,不同版本的源码位置差别很大,不能直接告诉你改哪个文件。我提供的通用定位方法是用 grep 搜索:

# 在 RustDesk 客户端源码根目录执行 grep -rn "rustdesk.com" --include="*.rs" src libs 2>/dev/null grep -rn "rendezvous" --include="*.rs" -i src libs 2>/dev/null

在 v1.1.x 时代,常见位置是src/common/constants.rs,里面会有一个类似RENDEZVOUS_SERVER的常量。在较新的版本中,这些默认值可能挪到了libs/hbb_common/src/config.rs之类的地方。找到之后,把默认服务器地址改成你自己的域名或 IP,把默认 key 改成id_ed25519.pub的内容。

下面是一个示意性的修改片段,不同版本字段名和路径可能不同,核心思路是一样的:

// 示意代码,实际位置以你搜索到的源码为准 pub const RENDEZVOUS_SERVER: &str = "your-server.com"; pub const KEY: &str = "你的 ed25519 公钥字符串,一长串 base64";

改完重新编译,客户端一启动就会拿这些值去连接你的服务器。这里有个非常关键的前提:目标机器上不能有旧的 RustDesk 配置。如果客户端已经运行过一次,本地存储的配置优先级高于编译期默认值,你改半天编译配置也不会生效。测试时要把~/.config/rustdesk(Linux)或%APPDATA%\RustDesk(Windows)删掉再启动。

4.2 做法二:预置配置文件

编译期改默认值有个问题:每次升级版本都要重新改、重新编译。如果你只是想快速批量设置一批机器,配置文件预置法更省事。

具体流程是这样的:

  1. 准备一台干净的测试机,安装官方或自编译的客户端。
  2. 打开设置界面,手动填入 ID 服务器地址、中继服务器地址和 key,确认能正常连接。
  3. 关闭客户端,找到配置文件。Windows 在%APPDATA%\RustDesk\,Linux 在~/.config/rustdesk/。
  4. 把里面保存服务器信息的文件(通常是RustDesk.toml或类似配置)复制出来,作为模板。

这里必须提醒一个非常容易翻车的细节:不要整个配置目录都拷走。config下还有id_ed25519和id_ed25519.pub,那是客户端自己的身份密钥,如果每台机器都用同一份,后果就是所有设备共享同一个设备 ID,互相抢注册,连接会变得一团乱。另外数据库文件包含地址簿等隐私数据,也不适合批量分发。

正确的做法是:只提取跟服务器、key 相关的配置内容,或者干脆把配置好的内容做成一个批处理/Shell 脚本,在客户端首次运行前写入目标机器的配置目录。Windows 下大致是这样一个思路:

@echo off mkdir "%APPDATA%\RustDesk\config" 2>nul echo [options] > "%APPDATA%\RustDesk\config\RustDesk.toml" echo custom-rendezvous-server=your-server.com >> "%APPDATA%\RustDesk\config\RustDesk.toml" echo key=your-public-key >> "%APPDATA%\RustDesk\config\RustDesk.toml"

字段名还是那句话:以你实际配置生成的真实文件为准,不要照抄网上任何一个模板。每个版本的存储结构都可能调整,最稳的方法永远是"先手动配置,再复制真实内容"。

4.3 做法三:安装后脚本注入

做法三适合已经装好客户端、跑过几次但配置不对的场景。它的本质跟做法二差不多,只是把写入配置的时机从"首次启动前"挪到"安装之后"。

可以用批处理脚本、PowerShell 脚本或者组策略来推送配置文件。如果你管理了一批已然运行过客户端的电脑,删配置目录会影响它们的设备身份,所以我不建议直接删了重来,而是只更新配置文件里服务器和 key 相关的条目,然后重启客户端。

这种方式的好处是不用重新编译,坏处是命令行里写明文 key,脚本本身的保管要注意权限,别让无关人员看到你的服务器公钥和地址。其实公钥本身不算敏感,但配合服务器地址暴露在公网上,容易被别人扫描利用,后面讲安全时再说。

4.4 我的选择:编译期为主,配置兜底

三种方式按实际使用场景分开:

  • 自己主力机、给家人朋友分发:编译期改默认值,一劳永逸。
  • 给公司同事批量部署:预置配置,脚本推送,节省重编译成本。
  • 临时帮别人调一下:远程指导手动填,或者脚本修一下配置。

我最推荐的组合是:编译期默认值 + 配置文件双保险。编译期保证全新安装的机器开箱即连,配置文件应对那些需要差异化覆盖的单台机器。

5. 完整编译流程与实测记录

5.1 Linux 下编译 Linux 客户端

我在一台 Ubuntu 22.04 机器上完整跑过一次,记录一下流程:

# 1. 安装系统依赖 sudo apt update sudo apt install build-essential pkg-config cmake git \ libgtk-3-dev libssl-dev libasound2-dev libavcodec-dev \ libavformat-dev libavutil-dev libswscale-dev \ libx11-dev libxext-dev libxinerama-dev libxcursor-dev \ libxdamage-dev libxfixes-dev libxi-dev libxkbcommon-dev \ libvpx-dev libopus-dev # 2. 安装 Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh source ~/.cargo/env # 3. 拉源码并切换到稳定版本 git clone https://github.com/rustdesk/rustdesk.git cd rustdesk git checkout v1.3.x # 4. 修改默认服务器地址和 key(按第四章做法一) # 5. 编译 cargo build --release

编译产物在target/release/rustdesk。首次编译时间比较长,取决于机器性能,二十分钟到一小时都正常,建议耐心等,不要中途 Ctrl+C。我看到很多新手在编译时看到一长串 warning 就以为报错了,其实只要最后没有error字样,就是成功。

在启动自己编译的客户端之前,务必先清理旧配置:

rm -rf ~/.config/rustdesk

然后运行./target/release/rustdesk,打开设置界面就能看到服务器地址已经变成了自己填的那个。

5.2 Windows 下编译 Windows 客户端

Windows 编译流程我在一台 Windows 11 机器上跑过。重点是要用 VS 的开发者命令行,否则后面链接阶段会找不到环境变量。

git clone https://github.com/rustdesk/rustdesk.git cd rustdesk git checkout v1.3.x # 设置 vcpkg 环境变量(如果还没设置) $env:VCPKG_ROOT = "C:\vcpkg" # 编译 cargo build --release

编译产物在target\release\rustdesk.exe。如果是 Flutter UI 版本,可以先执行python build.py --flutter --release,最终产物在target\release\下。

5.3 我踩过的编译错误

把几个典型报错和处理方式整理出来,应该能帮大家省不少时间。

错误现象原因解决办法
link.exe not found或找不到 MSVC 链接器没有使用 VS 开发者命令行打开 x64 Native Tools Command Prompt 再执行 cargo
vcpkg 安装依赖超时失败网络原因或依赖较多重试,必要时配置镜像源
OpenSSL 头文件找不到缺少libssl-dev/pkg-configLinux 安装libssl-dev,Windows 通过 vcpkg 安装 openssl
Flutter 构建报错或卡住Flutter 版本不一致或依赖未拉取执行flutter upgrade && flutter pub get
磁盘空间不足Rust 编译缓存很大清理target目录,或用外置盘做编译

还有一个通用建议:编译这类大型 Rust 项目,把CARGO_HOME和target目录放到空间充足的磁盘上,SSD 优先。机械硬盘编译 RustDesk 会让人怀疑人生。

5.4 验证编译产物确实写入了默认配置

编译完成后怎么确认默认值真的生效?可以先用一个干净环境运行客户端,然后直接看设置界面显示的是不是你自己的服务器。更快的办法是在源码里搜索替换后的字符是否还在:

grep -rn "your-server.com" target/release/ 2>/dev/null

不过二进制里字符串不一定明文可见,最靠谱的还是实机验证。我自己的测试流程是:清空配置目录、启动客户端、观察日志、开两台设备实际连一次。两台设备建立连接的那一刻,整套方案才算真正跑通。

6. 上线后的排查手段与安全边界

6.1 "key 值未知"的完整排查链路

这个报错可能是 RustDesk 自建玩家最常见的求助热点。所谓"key 值未知",本质是客户端本地保存的 key 和服务器实际公钥对不上。

排查链路按顺序走一遍:

  1. 登录到服务器,进入 hbbs 部署目录,用cat id_ed25519.pub查看当前公钥。
  2. 在客户端设置界面,把 key 更新为刚才看到的完整字符串。复制时注意开头结尾有没有多出空格、是不是被换行截断了。
  3. 如果更新后仍然报错,关闭客户端,删除本地配置目录,再重新启动输入。
  4. 如果服务器有多台实例、或者曾经把旧目录拷贝过,确保客户端连的确实是生成这份公钥的那台机器。

我遇到最多的情况是:服务端透过宝塔或者其他面板重启过,目录被重建,密钥重新生成了,客户端还拿着旧 key 在连接。备份的重要性在这里体现得很充分。

6.2 连不上 ID 服务器时的排查链路

客户端如果一直显示无法连接服务器,不要急着怀疑源码。按这个顺序查:

  1. 检查端口是否可达:
nc -z -v your-server.com 21115 nc -z -v your-server.com 21116 nc -z -v your-server.com 21117
  1. 检查服务器防火墙:ufw status或firewall-cmd --list-all,确认 21115-21119 已放行。
  2. 检查云安全组:很多云厂商的安全组默认全关,单独放行端口才有效。
  3. 查看 hbbs 日志:启动 hbbs 时不要加--quiet,日志里会打印客户端注册、注册失败的详细信息。

有个容易被忽略的坑:21116 端口同时需要 TCP 和 UDP 放行。很多网络环境只放行 TCP,客户端能完成一部分握手,但后续的 UDP 通信直接被丢,现象就是反复超时。

6.3 中继服务器不转发的几个原因

两台设备无法直连时,流量会走 hbbr。中继不工作,现象是对方设备一直显示"连接中",然后失败。

常见原因:

  • 21117 端口没放行,客户端与 hbbr 建立不了连接。
  • 客户端填的中继服务器地址不对。新版客户端可以单独设置中继服务器,务必和 hbbs 的-r参数保持一致。
  • hbbr 进程没起来或死循环了。ps aux | grep hbbr看一眼,配合 systemd 的Restart=always解决。

如果确认端口和进程都正常,用两台不同网络环境(比如一个在移动网络、一个在宽带)的设备再测一次,很多时候是测试环境里两台机器其实可以直连,流量根本没走中继,导致你以为中继坏了。

6.4 安全边界与隐私保护

RustDesk 的 key 机制需要澄清一个概念:key 是服务器身份公钥,不是访问密码。拿到服务器地址和公钥的人,可以尝试向你的 ID 服务器注册自己的设备,所以服务器暴露在公网上时,必须有额外的保护意识。

几个我自己长期在用的安全习惯:

  1. id_ed25519私钥视为最高机密,绝不公开、不随客户端分发。
  2. 如果条件允许,在服务器防火墙层面限制来源 IP。只给自己固定出口 IP 放行 21115-21119,能挡掉大量扫描。
  3. 每台被控设备设置强访问密码。这是连接设备时真正起拦截作用的凭证。
  4. 定期备份 hbbs 部署目录。密钥丢了或变了,所有客户端都要重新配置,代价太大。
  5. 域名和服务器 IP 尽量不要频繁变更。客户端里写死的地址一旦变更,同样需要重新配置。

6.5 顺手还能改的:客户端名称与图标

既然已经走到编译客户端这一步,很多人会顺手把软件名称、图标一起改掉,让整个工具看起来更像"自家产品"。这个需求一般涉及资源文件和界面文案:Windows 图标和版本信息在.rc资源文件里,Flutter UI 的文字在flutter/lib/下的源码里。改起来不难,但每次升级版本都要维护一份 patch,个人自用的话自己权衡一下值不值。

最后的几点体会

把服务器地址和 key 编进客户端这个事,真正做起来比想象中简单,难点反而在版本差异的适配和旧配置的清理上。我个人现在已经养成了习惯:拿到新版本源码,先 grep 默认服务器常量的位置,改完再编译;同时保留一份配置文件模板,用于那些没法重编译的环境。整套方案跑顺之后,RustDesk 的使用体验基本可以做到"发给别人就用,不用任何解释"。

最后再提醒一句最关键的话:服务器端id_ed25519私钥千万保管好,丢一次,所有客户端的 key 都要跟着重配,那种批量改配置的酸爽,体验过一次就再也不想体验第二次了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询