【实用的开源工具】RustDesk 自建服务器:把远程桌面的 ID 和中继放在自己手里

阅读约 11 分钟
【实用的开源工具】RustDesk 自建服务器:把远程桌面的 ID 和中继放在自己手里

「实用的开源工具」系列:我只收集值得用的开源项目,写清楚它能做什么、怎么部署、有哪些坑,并在文末标明出处。内容整理自官方文档,核对日期 2026-10-31,具体版本以官方为准。这篇只讲服务端(自建 ID 服务器和中继服务器),客户端只涉及“怎么指向你的服务器”。

项目信息卡

项目说明
名称RustDesk(客户端)与 RustDesk Server OSS(服务端)
做什么远程桌面软件。服务端负责让两台设备互相找到对方(ID/信令),直连不通时再中继流量
许可证GitHub 上显示:客户端仓库 rustdesk/rustdesk 是 AGPL-3.0;服务端仓库 rustdesk/rustdesk-server 也是 AGPL-3.0(两个仓库都带 AGPL v3 的许可证文件)。其他仓库或闭源部分我没有逐个核对
服务端最近版本1.1.16(2026-07-20 发布,查询于 2026-10-31);客户端最近版本 1.5.0(2026-09-30 发布)
项目状态两个仓库都未归档,客户端最近一次推送是 2026-10-31,服务端是 2026-10-10
服务端组成hbbs:ID/会合(信令)服务器;hbbr:中继服务器;仓库里还有命令行工具 rustdesk-utils
官方镜像rustdesk/rustdesk-server(只含程序)、rustdesk/rustdesk-server-s6(用 s6 同时启动两个程序,并带几个便利变量)
需要开放的端口至少 TCP 21115、21116、21117 和 UDP 21116,必须对公网开放(详见下文)
OSS 与 Pro官方文档把服务端分成两个选项:RustDesk Server OSS(免费开源,含 hbbs 和 hbbr,社区支持,手动部署)和 RustDesk Server Pro(面向企业,有网页控制台、API、OIDC、LDAP、2FA、设备管理、访问控制、多中继管理等)。这篇只讲 OSS

它能做什么

官方的说明是:自建后你自己掌握 ID 和中继基础设施,把部署数据留在自己管理的系统上。它的工作方式(文档原意):

  1. 只要设备上的 RustDesk 在运行,就会不断向 ID 服务器(hbbs)报告自己当前的地址和端口。
  2. 设备 A 要连设备 B 时,先问 ID 服务器,ID 服务器尝试让两边通过“打洞”直接连接。
  3. 打洞失败时,才通过中继服务器(hbbr)转发。文档说大多数情况下打洞能成功,中继用不上。

适合:自己有一台公网 IP 的小服务器,想让自己的 RustDesk 客户端走自己的服务器。不适合:想要网页管理后台、账号体系、设备分组的人,这些在官方文档里属于 Pro。

端口:哪些必须对外

官方文档给的端口表(OSS 相关的部分):

端口协议属于用途
21115TCPhbbsNAT 类型测试
21116TCP 和 UDPhbbsUDP 用于 ID 注册和心跳;TCP 用于 TCP 打洞和连接服务。TCP 和 UDP 都要开
21117TCPhbbr中继
21118TCPhbbsWebSocket,仅为网页客户端
21119TCPhbbrWebSocket,仅为网页客户端
21114TCPhbbs仅 Pro 的网页控制台/API,OSS 用不到

官方原话:21115 到 21117 是让 RustDesk 能工作的最低要求端口,负责信令、中继和 NAT 穿透。不用网页客户端,21118 和 21119 就不用开。

和“反向代理后面只暴露 127.0.0.1”不同,这里的 21115 到 21117 必须对公网可达,客户端要直接连这些端口。

官方安装页给的 ufw 命令是开放 21114:21119/tcp 和 21116/udp。按上面的表,OSS 只用最小集合时可以这样写(这是我根据端口表缩小的,不是官方原文):

bash
ufw allow 21115:21117/tcp
ufw allow 21116/udp

安全警告(官方文档原文意思): 打开 21118/21119 时,hbbs/hbbr 会信任 WebSocket 连接里的 X-Real-IP 和 X-Forwarded-For 头来判断客户端 IP,而且不验证这些头。直接能访问这两个端口的人可以伪造任意 IP,绕过按 IP 的限速和封禁,也会让日志里的 IP 失真。所以用网页客户端时,这两个端口只应通过一个自己设置 X-Real-IP 的反向代理暴露,并用防火墙限制只有代理能连;不用网页客户端就保持关闭。

部署(Docker Compose)

官方文档的结论:多数 Linux 服务器上,Docker Compose 加 network_mode: "host" 是最简单可靠的方式。先建目录:

bash
mkdir -p /opt/rustdesk && cd /opt/rustdesk

compose.yaml(结构来自官方 Docker 文档,我只把镜像从 latest 改成固定版本 1.1.16):

yaml
services:
  hbbs:
    container_name: hbbs
    image: rustdesk/rustdesk-server:1.1.16
    command: hbbs
    volumes:
      - ./data:/root
    network_mode: "host"
    depends_on:
      - hbbr
    restart: unless-stopped
  hbbr:
    container_name: hbbr
    image: rustdesk/rustdesk-server:1.1.16
    command: hbbr
    volumes:
      - ./data:/root
    network_mode: "host"
    restart: unless-stopped

启动:

bash
docker compose up -d
docker compose logs hbbs
  • 我在 Docker Hub 的标签列表里看到 1.1.16、1 和 latest,与 GitHub 最近版本一致;你部署时请再确认标签存在。
  • 官方文档说明 --net=host 只在 Linux 上有效,好处是 hbbs/hbbr 能看到真实的来访 IP,而不是容器 IP(172.17.0.1)。遇到连接问题的平台可以去掉它;去掉后就要自己写 ports 映射。官方仓库里的 docker-compose.yml 就是不用 host 网络的写法:映射 21115、21116(TCP 和 UDP)、21118、21117、21119,并给 hbbs 加上 -r rustdesk.example.com:21117。
  • 因为是 host 网络,上面没有 ports,也就无法像其他文章那样“只绑定 127.0.0.1”。端口是否对外,要靠防火墙控制。
  • ./data 同时挂给 hbbs 和 hbbr(容器内 /root)。官方文档说明 hbbs 首次运行时在工作目录或数据目录里生成密钥文件。

没有 Compose 时,官方也给了 docker run 的写法:

bash
sudo docker run --name hbbs -v ./data:/root -td --net=host --restart unless-stopped rustdesk/rustdesk-server hbbs
sudo docker run --name hbbr -v ./data:/root -td --net=host --restart unless-stopped rustdesk/rustdesk-server hbbr

官方还提供了 Podman Quadlet 示例、Windows(PM2 或 NSSM)、Synology 的部署文档,见文末出处。

第一次使用:拿公钥,填到客户端

1. 拿公钥。 官方说明:密钥通常在 hbbs 第一次运行时生成,放在数据目录里的 id_ed25519.pub。按上面的 Compose,就是:

bash
cat /opt/rustdesk/data/id_ed25519.pub

同目录的 id_ed25519 是私钥,不要外传,只把 .pub 里的内容给客户端。官方还特别说明,这个 Key 是用于连接加密的公钥,和购买 Pro 时拿到的授权 key 不是一回事。

2. 客户端设置。 官方的手动配置步骤:在 RustDesk 主界面,点自己 ID 旁边的菜单按钮 ⋮,进入 Network,用管理员权限解锁后填写:

字段填什么
ID Server你的 hbbs 主机名或 IP,例如 hbbs.example.com,也可以带端口 hbbs.example.com:21116。连接两端(本机和被控端)都要填
Relay Server可以留空,RustDesk 会自动推断;它指的是 hbbr(端口 21117)
API Server仅 Pro 用
Key上一步 id_ed25519.pub 的内容
  1. 批量配置。 官方文档列出了导出再导入服务器配置(设置 → Network → 解锁 → Export/Import Server Config,再点 Apply)、部署脚本,以及命令行 rustdesk.exe --config <配置串>。配置串可以从客户端 “Settings → Network” 得到。定制客户端生成器是 Pro 才有的功能。
  1. 验证:两台设备都配置好后,互相用对方的 ID 连一次。如果连不上,先回头核对端口、公钥和两端的 ID Server。

反向代理?一般不需要

RustDesk 的 21115 到 21117 是 TCP/UDP 直连端口,不是普通的 HTTP 服务,没有“前面套个 Nginx 就行”的做法。官方文档里的反向代理只用于 WebSocket(网页客户端等):它写的示例是把 /ws/id 转发到 http://127.0.0.1:21118,把 /ws/relay 转发到 http://127.0.0.1:21119,并带上 Upgrade、Connection、X-Real-IP、X-Forwarded-For 等头。这个示例出现在官方 Pro 的 FAQ 页面里,我没有核实它是否同样适用于 OSS 的网页客户端,所以这里不展开,请直接看原文。

官方还提到一种只开 TCP 443 的方式:所有通信走 WSS 中继,此时没有点对点直连。

可选配置

下面都来自仓库的 docs/environment-variables.md,其中带 🅴 的变量只能通过进程环境设置。要在 Compose 里加,可以像官方示例那样写 environment:。

变量说明
ALWAYS_USE_RELAYY 强制所有会话走中继(禁用直连打洞),默认 N
RELAY-SERVERS(或 -r)中继用了不同地址或非标准端口时才需要设置;中继与 hbbs 同地址、端口 21117 时留空即可
KEY(或 -k)hbbs 默认值是 -,即加载或生成密钥对
PORT(或 -p)主端口,hbbs 默认 21116,会同时占用 PORT-1(NAT 测试)和 PORT+2(WebSocket);hbbr 默认 21117
RUST_LOG日志级别,默认 info;必须设在进程环境里,写在 .env 或配置文件里无效
DB_URLSQLite 数据库路径,默认 ./db_v2.sqlite3

中继的带宽限制也有默认值(单位 Mb/s):SINGLE_BANDWIDTH 128,TOTAL_BANDWIDTH 1024,LIMIT_SPEED 32。文档说明单个连接过了 DOWNGRADE_START_CHECK(默认 1800 秒)之后,平均速度超过 SINGLE_BANDWIDTH * DOWNGRADE_THRESHOLD 就会被限到 LIMIT_SPEED,即使中继本身很空闲。

资源方面,官方安装页的说法:硬件要求很低,最小配置的云服务器就够,树莓派也行;流量取决于打洞是否成功,走中继时一路连接大约 30 K/s 到 3 M/s(1920x1080 屏幕,取决于分辨率设置和画面变化),纯办公大约 100 K/s。

更新与卸载

官方文档说 Docker 是升级最简单、也最容易回滚的方式,但我没有读到专门的升级步骤,下面是通用做法。

更新:

bash
cd /opt/rustdesk
cp -a data data.bak-$(date +%F)       # 先备份密钥和数据库
# 把 compose.yaml 里两处镜像标签改成新版本(先确认标签存在)
docker compose pull
docker compose up -d

data/ 里有 id_ed25519、id_ed25519.pub 和 SQLite 数据库。只要密钥不变,客户端就不用重新配置。

卸载:

bash
cd /opt/rustdesk
docker compose down
  • 之后再删防火墙里的规则,例如 ufw delete allow 21116/udp,逐条对应你当时开的规则。
  • 删除 data/ 目录就等于丢掉私钥,以后重装会生成新密钥,所有客户端都要换成新的公钥(这是我据官方的密钥说明做的推断)。

踩坑清单

  1. 21116 要同时开 TCP 和 UDP。 官方强调:UDP 用于 ID 注册和心跳,TCP 用于打洞和连接服务,漏一个都会出问题。
  2. 最低要开的是 21115 到 21117。 21114 仅 Pro 使用,21118 和 21119 仅网页客户端使用,不用就不要开。
  3. WebSocket 端口会被伪造 IP。 官方警告:21118/21119 信任未验证的 X-Real-IP/X-Forwarded-For,直接暴露会让别人伪造 IP,绕过限速和封禁。
  4. 客户端必须填公钥,而且两端都要填 ID Server。 官方原话是 ID Server 要在“本地和远程两边”都填;Key 是 id_ed25519.pub 里的公钥,不是 Pro 的授权 key。
  5. hbbr 默认不校验密钥。 环境变量文档说,hbbr 的 KEY 默认是空,这是有意的,目的是避免密钥配对出错;代价是没有匹配密钥的客户端也能用你的中继,在暴露到公网的服务器上要自己权衡。要开启,需要给 hbbr 设置和 hbbs 相同的非空密钥(-k),我没有逐步验证这种配置。
  6. host 网络只在 Linux 上有效。 官方说明 --net=host 只在 Linux 生效;有连接问题的平台去掉它,再自己写端口映射。
  7. 在家里或办公室内网搭,同一局域网内可能连不上自己的公网域名。 官方有一篇 NAT Loopback 文档:服务器放在 NAT 后面时,服务端和客户端要么用内网 IP 互访,要么路由器支持并开启 NAT 回环(hairpin)。解决办法按官方顺序是:路由器开 NAT 回环、局域网内部署 DNS(AdGuard Home 或 Pi-hole)把域名指到内网 IP、或者改 hosts 文件(只适合少数设备,笔记本带到外面就连不上了)。
  8. 别把官方文档里的 latest 当成固定版本。 生产环境建议固定版本。注意文档与版本可能不同步:环境变量文档里提到 BIND(指定监听地址)“自 1.1.17 起可用”,而最近的发布是 1.1.16,所以你用 1.1.16 时不要依赖这个变量。
  9. s6 镜像和普通镜像支持的变量不同。 RELAY、ENCRYPTED_ONLY、KEY_PUB、KEY_PRIV 只在 rustdesk/rustdesk-server-s6 镜像里有效,普通的 rustdesk/rustdesk-server 镜像会忽略它们;s6 镜像的数据目录是 /data,普通镜像文档示例挂的是 /root。
  10. RUST_LOG 写进 .env 无效。 环境变量文档明确说它必须在启动前的进程环境里设置。
  11. 别混淆 DB_URL 和 DATABASE_URL。 官方说明运行时只读 DB_URL;仓库 .env 里的 DATABASE_URL 只用于编译时检查 SQL,设置了也没用。
  12. 私钥和数据库要备份。 id_ed25519 丢了,所有客户端都要换成新的公钥(据官方密钥说明的推断)。
  13. 第三方一键脚本要慎用。 官方安装页提到的 install.sh 托管在 Techahold 的仓库,并非 RustDesk 官方仓库;运行任何脚本前先读一遍,这是通用建议。
  14. AGPL-3.0 对修改后提供网络服务的人有要求。 如果你只是自己用官方镜像,一般不涉及;如果要改源码并对外提供服务,请自己读许可证全文,或咨询懂行的人(通用提醒,不是法律意见)。

出处

想要类似的东西?网站、Telegram 机器人、运维工具,说说你的需求。
发布需求

有想法或问题?去留言板留言 →