SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 更新于 2026-08-22

如何自托管 RustDesk 中继服务器

在 VPS 上运行 RustDesk hbbs 和 hbbr,配置 Ed25519 密钥、固定镜像标签并锁定端口。了解 21117 中继流量如何计费,以及何时会消耗套餐带宽。

自托管 RustDesk 中继服务器是什么

自托管 RustDesk 中继服务器是在一台 VPS 上运行的两个守护进程。hbbs 是 ID 和会合服务器:它注册每个客户端 ID,并让两个客户端彼此建立连接。hbbr 是中继服务器:它传输会话数据,但只处理无法直接通信的会话。大多数指南会安装这两个服务,帮助您完成配对,然后就此结束。下面介绍其余工作:作为访问控制的密钥、端口、升级方式和带宽。

两个守护进程都包含在同一个镜像中,即 rustdesk/rustdesk-server,并从同一目录读取同一对 Ed25519 密钥。Ed25519 是一种公钥签名方案。这对密钥决定服务器会与哪些客户端通信,系统背后没有用户数据库。

hbbs 和 hbbr:哪个守护进程会消耗带宽

hbbs 的流量很小且基本恒定:用于注册 ID、发送心跳,以及完成用于介绍两个对等端的简短交互。它全天运行,但几乎不产生带宽成本。

hbbr 的流量就是会话本身。屏幕帧向一个方向传输,键盘和鼠标输入向另一个方向传输,每个中继字节都会先到达 VPS,然后再次从 VPS 发出。如果服务商只统计出站流量,中继会话产生的成本大约等于会话速率。如果服务商统计总传输量,成本大约是其两倍。

中继是备用路径,不是正常路径。hbbs 首先尝试让两个客户端直接连接,并通过位于各自前方的 NAT(网络地址转换)执行打洞。连接成功后,会话完全不会经过 hbbr,也不会消耗 VPS 的传输额度。如果一端位于会为每个目标分配新端口的 NAT 后方,或者防火墙丢弃打洞连接,会话就会回退到 hbbr,每个帧都会经过 VPS。

一个环境变量会取消这种选择。ALWAYS_USE_RELAY=Y 在 hbbs 上会强制所有会话经过 hbbr。RustDesk 文档在其中一个 Compose 示例中展示了该变量,因此它经常被直接复制。这样可以让连接更可预测,但也会让出站流量实际产生费用。只有在你确实决定这样配置时才设置它,不要因为复制粘贴了示例就设置。

自托管 RustDesk 服务器需要哪些端口

以下端口号已于 17 August 2026 根据 RustDesk 服务器文档和 rustdesk-server 仓库进行核对。

  • TCP 21115,在 hbbs 上:NAT 类型测试。
  • UDP 21116,在 hbbs 上:ID 注册和心跳。未开放此端口时,无论其他端口是否开放,客户端都不会上线。
  • TCP 21116,在 hbbs 上:TCP 打洞和连接服务。
  • TCP 21117,在 hbbr 上:中继服务。会话数据通过此端口传输,因此它是产生流量费用的端口。
  • TCP 21118 在 hbbs 上,TCP 21119 在 hbbr 上:WebSocket,供浏览器客户端使用。不使用浏览器客户端时,请关闭这两个端口。
  • TCP 21114 是 RustDesk Server Pro 的 Web 控制台端口。开源版本不会监听此端口。

使用固定镜像标签安装 hbbs 和 hbbr

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 -k _
    volumes:
      - ./data:/root
    network_mode: "host"
    restart: unless-stopped
mkdir -p ~/rustdesk
cd ~/rustdesk
# save the block above as ~/rustdesk/compose.yml before this line
sudo docker compose up -d
sudo docker compose ps

两个服务都应读取 running。在配置防火墙前,先确认监听端口已存在。

sudo ss -tlnp | grep -E ':2111[5-7]'
sudo ss -ulnp | grep ':21116'

您应看到 21115、21116 和 21117 上的 TCP 监听,以及 21116 上的 UDP 监听。缺少 UDP 这一行表示 hbbs 未运行,因为客户端通过该监听器进行注册。

该文件中的 4 项设置都是有意配置的。标签为 1.1.16,这是截至 August 2026 的当前版本,于 20 July 2026 发布,而不是 latest,因为 latest 表示最近推送的版本,而 6 个月后的 docker compose pull 可能会为您提供一个从未测试过的服务器。network_mode: "host" 将主机接口直接绑定到容器,这是 RustDesk 文档建议的方式,也决定了防火墙的行为。./data:/root 将镜像的工作目录映射到主机,因此密钥对会保存到可以备份的位置。hbbr -k _ 是相对于上游示例的唯一修改,因为默认配置会让中继服务对任何人开放。如果您还不熟悉 Compose,在 VPS 上运行 Docker Compose 介绍了文件格式和生命周期命令。

如果 hbbr 迁移到第二台服务器,必须告知 hbbs 新地址:传入 -r relay.example.com:21117,或设置 RELAY-SERVERS 环境变量。在单台服务器上无需设置该项。

Ed25519 密钥对用于访问控制

首次启动时,hbbs 会在其工作目录中生成 id_ed25519id_ed25519.pub。使用上面的挂载配置后,这两个文件都会出现在主机上。

ls -l ~/rustdesk/data/
sudo cat ~/rustdesk/data/id_ed25519.pub

id_ed25519.pub 包含一个 base64 字符串。请将该字符串填入每个客户端的 Key 字段。id_ed25519 是私钥部分,绝不能离开服务器。公钥不属于机密信息,因为它本来就会复制到每个客户端配置中。私钥属于机密信息:持有私钥的任何人都可以搭建一个客户端会信任的服务器。

现在就备份这两个文件,不要等到配置了 20 个客户端之后。

sudo tar czf ~/rustdesk-keys.tgz -C ~/rustdesk/data id_ed25519 id_ed25519.pub
sudo chmod 600 ~/rustdesk-keys.tgz

将该归档复制到服务器之外。下面说明这一步为什么比其他步骤都重要。删除 ~/rustdesk/data,或者在新的 VPS 上重建服务时没有复制该文件,hbbs 就会在下次启动时生成新的密钥对。每个客户端仍保存旧公钥,因此 hbbs 会拒绝该客户端,客户端也会离线。运行 sudo cat ~/rustdesk/data/id_ed25519.pub,并将其与任意客户端的 Key 字段进行比较:两个字符串不再匹配,这个不匹配就是故障的全部原因。修复此问题需要手动编辑每台机器上的设置,包括原本依赖 RustDesk 访问的机器。

密钥不是会话密码,混淆两者会导致用户漏掉其中一项。密钥决定服务器与哪些客户端通信。受控机器上的永久密码或一次性代码决定谁可以在该机器上打开会话。两者都需要配置;其中一项配置正确,也不能弥补另一项过弱的问题。

为什么未经过身份验证的中继存在问题

默认情况下,hbbr 不检查任何内容。RustDesk 配置文档对此有明确说明:密钥为空时,没有匹配密钥的客户端也可以使用中继。默认使用空密钥,是为了避免新用户首次运行时遇到密钥不匹配错误。代价是,任何发现 TCP 21117 地址的人,都可以通过你的 VPS 中继会话流量,消耗你的传输配额,并使用你的 IP 地址。

command: hbbr -k _ 可解决这个问题。_ 参数会让 hbbr 从工作目录加载密钥对。由于两个容器挂载了同一个 ./data,加载的就是 hbbs 已生成的密钥对。整个过程不需要手动复制文件,因此不会出现密钥不一致。

共享卷是最容易配置错误的部分。为 hbbr 指定独立目录后,它会生成另一组不同的密钥对。此时 hbbs 和 hbbr 使用的密钥不一致,所有经中继的会话都会失败,但直连会话仍可正常工作。这个现象容易误导:RustDesk 能连接部分对端,却无法连接其他对端,具体取决于打洞是否成功。使用一个 ls -l ~/rustdesk/data/ 显示同一组 id_ed25519 密钥对,即可排除这种问题。

将客户端指向您的服务器

在每台机器上打开 RustDesk,然后依次进入 Settings、Network 和 ID/Relay Server。

  • ID Server:填写您的主机名,例如 rustdesk.example.com。如果未指定其他端口,客户端使用端口 21116。
  • Relay Server:如果 hbbr 与 hbbs 运行在同一台主机上,请留空。
  • API Server:请留空。开源服务器不提供 API Server。
  • Key:粘贴 id_ed25519.pub 中的 base64 字符串,必须完全一致,末尾不能有空格。

此时主窗口应显示客户端已就绪。如果没有显示,说明 UDP 21116 未到达 hbbs,因为注册和心跳均通过 UDP 运行,其他设置无法使 ID 服务上线。

限制端口,避免中继服务对外开放

由于容器使用 host 网络,因此容器前没有 Docker NAT 规则,ufw 规则会按预期生效。

sudo ufw allow 22/tcp
sudo ufw allow 21115:21117/tcp
sudo ufw allow 21116/udp
sudo ufw enable
sudo ufw status numbered

仅在运行浏览器客户端时添加 21118:21119/tcp。启用 ufw 时保持第二个 SSH 会话处于打开状态,这样即使 SSH 规则配置错误,也不会把自己锁在服务器外。VPS 的 ufw 防火墙基础介绍默认策略和规则顺序。

现在说明一个容易踩坑的地方。如果改用 ports: 块发布端口(另一种 RustDesk supervisor 镜像示例采用这种方式),Docker 会写入自己的 DNAT 规则,数据包无需经过 ufw 规则所在的链即可到达容器。此时对 21117 设置 ufw deny 不会生效,中继服务会对互联网开放,尽管 ufw status 声称情况并非如此。Docker 发布的端口会绕过 ufw解释了链的处理顺序。使用 host 网络可以完全避免这个问题。如果确实要发布端口,请像反向代理后的 "127.0.0.1:21118:21118" 一样,将端口绑定到一个地址。

按源地址限制仅在客户端地址稳定时有效。

sudo ufw allow from 203.0.113.0/24 to any port 21115:21117 proto tcp
sudo ufw allow from 203.0.113.0/24 to any port 21116 proto udp

酒店网络中的笔记本电脑通常没有稳定的地址。因此,在这里,hbbr 上的密钥比防火墙发挥更大的实际作用。

升级保存密钥的堆栈

密钥位于绑定挂载中,而不在容器内。因此,只要不改动 ./data,升级就是安全的。

  1. 先备份数据目录:sudo tar czf ~/rustdesk-data-backup.tgz -C ~/rustdesk data
  2. 在 rustdesk-server releases 页面阅读新标签的发行说明。
  3. 编辑 compose.yml,将其中两处 image: 都改为新标签。
  4. 运行 sudo docker compose pull,然后运行 sudo docker compose up -d
  5. 运行 sudo cat ~/rustdesk/data/id_ed25519.pub,确认输出的字符串与客户端现有的字符串一致。

第 5 步是关键检查。服务器端密钥发生变化时通常不会明确提示,但会同时导致所有客户端失效。回滚时,将标签改回旧值,然后再次运行 up -d。这只有在固定了标签的情况下才有效:使用 latest 时,docker compose pull 已将名称移到新镜像上,因此不再有标签指向旧镜像。

通常导致密钥丢失的原因不是 docker compose down,因为该操作不会改动绑定挂载。更常见的原因是迁移到新的 VPS 时只复制了 compose.yml。请同时复制 ./data

监控有流量配额的套餐的出站流量

hbbr 是此堆栈中唯一可能消耗流量配额的组件。RustDesk 的 FAQ 指出,在 1920x1080 屏幕上,中继连接的流量介于 30 KB/s 和 3 MB/s 之间,普通办公操作约为 100 KB/s。这些是单个会话的公开数据,不是对您环境的测量结果。按每月 60 小时、每天 2 小时计算,结果如下。

ChartVPS egress from one relayed RustDesk session, 60 hours per month
The data behind this chart
[
  {
    "label": "Low end, 30 KB/s",
    "gb_per_month": 6.5
  },
  {
    "label": "Office work, 100 KB/s",
    "gb_per_month": 21.6
  },
  {
    "label": "High end, 3 MB/s",
    "gb_per_month": 648
  }
]

按普通办公操作的速率计算,一个会话每月约消耗 21.6 GB,任何套餐通常都不会注意到这个用量。按公开范围的最高速率计算,同样的 60 小时会消耗 648 GB;如果同时有 2 个会话以该速率运行,一个月内就会超过 1 TB 的流量配额。按最低速率计算则为 6.5 GB。这里的 GB 按 1000 MB 计算,这也是流量配额通常采用的计算方式。

docker stats 无法为您细分这部分流量,因为使用 host networking 的容器会共享主机的网络命名空间,因此其计数器实际记录的是主机的流量。以下两个工具可以使用。vnstat 可测量整台主机的流量:

sudo apt install -y vnstat
sudo systemctl enable --now vnstat
vnstat -m

整台主机意味着整台主机:如果此 VPS 还运行着其他传输实际数据的服务,例如每天晚上拉取手机图库的 自托管照片服务器,这些上传流量会与中继流量计入同一个月度统计项。

nftables 计数器可以单独测量中继流量:

sudo nft add table inet relaymeter
sudo nft add chain inet relaymeter out '{ type filter hook output priority 0 ; }'
sudo nft add rule inet relaymeter out tcp sport 21117 counter
sudo nft list table inet relaymeter

该规则不包含 verdict,因此只统计数据包和字节数,不会改变允许的流量;同时,它位于独立的表中,不会影响 ufw。它不是持久化的:如果希望重启后恢复,请将相同的行写入 /etc/nftables.conf。只有在会话实际进行中继时,计数器才会增长。如果没有您自己的设备连接,但计数器仍持续增长,说明有人找到了您的中继;这正是 hbbr -k _ 要防止的情况。

hbbr 还提供可以调低的速率限制。SINGLE_BANDWIDTH 默认将每个中继连接限制为 128 Mb/s,TOTAL_BANDWIDTH 默认将所有连接合计限制为 1024 Mb/s。设置 SINGLE_BANDWIDTH=8 后,单个会话的速率会限制在接近 1 MB/s。它限制的是速度,不是月度总量。因此,应将其视为防止单个会话占满链路的措施,而不是流量预算控制。

完全不需要中继时

对于个人环境,实际情况可能是您根本不需要这些组件。将两台机器加入同一个网状 VPN,然后直接连接隧道地址。这样不需要 hbbs、hbbr 或中继出口,也不需要升级 VPS 上的容器。

在要控制的机器上,在 RustDesk 的安全设置中启用直接 IP 访问。端口字段默认为 21118。尝试连接前,确认该端口正在监听:

ss -tlnp | grep 21118

然后使用对端的 VPN 地址连接,而不是使用 ID。RustDesk 的 FAQ 说明,这种模式下的连接未加密,因此应在隧道内使用,绝不要通过开放互联网连接。加密由隧道提供。

根据机器的归属选择方案。如果您需要支持不属于自己的机器,或对方不会安装 VPN 客户端,则应使用自托管的 hbbs 和 hbbr,因为对方只需使用 ID 和密码即可完成配置。如果所有机器都属于您,并且都可以保存密钥,则应使用支持直接 IP 访问的网状 VPN。WireGuard 与 Tailscale 的比较介绍了构建此类网状网络的两种常见方式;在 Linux VPS 上运行远程桌面介绍了另一种情况:您要访问屏幕的机器本身就是服务器。

FAQ

每个 RustDesk 会话都会经过我的中继吗?

不会。hbbs 会先尝试让两个客户端直接连接,并通过各自前方的 NAT 执行打洞。只有直连失败的会话才会回退到 hbbr,并且只有这些会话会消耗您的带宽。例外情况是 hbbs 上的 ALWAYS_USE_RELAY=Y,它会强制所有会话经过 hbbr,无论是否存在可用的直连路径。如果您在 Compose 文件中设置了该变量,每个会话的每个字节都会计入您的流量费用。

RustDesk 服务器密钥存储在哪里?如果丢失怎么办?

hbbs 首次启动时会在其工作目录中生成 id_ed25519id_ed25519.pub。官方镜像中的该目录是 /root,因此使用上文所示的卷挂载后,这些文件会出现在主机的 ./data 中。请将这两个文件备份到服务器之外的位置。如果文件丢失,hbbs 会在下次启动时生成一对新密钥,仍保存旧公钥的所有客户端都会被拒绝连接。除了手动修改每个客户端的 Key 字段之外,没有其他恢复方法。

自托管 RustDesk 服务器需要开放哪些端口?

需要开放 TCP 21115、21116 和 21117,以及 UDP 21116。hbbs 使用 21115 进行 NAT 类型测试,使用 21116 通过 UDP 执行 ID 注册和心跳,并通过 TCP 执行打洞。hbbr 使用 21117 提供中继。TCP 21118 和 21119 是浏览器客户端使用的 WebSocket 端口;如果您不使用浏览器客户端,请保持关闭。TCP 21114 属于 Pro Web 控制台,开源版本不需要该端口。

陌生人可以使用我自托管的 RustDesk 中继吗?

可以,前提是您使用默认配置运行 hbbr。RustDesk 文档指出,空密钥允许未配置匹配密钥的客户端使用中继。因此,任何知道您的主机名和端口 21117 的人都可以通过您的服务器传输流量。请使用 -k _ 运行 hbbr,使其从共享的 ./data 卷加载 hbbs 生成的同一对密钥。之后,只有配置了您的公钥的客户端才能通过您的服务器进行中继。