Docker 自建 RustDesk 远程桌面服务器全攻略:从 OpenWrt 端口映射、双网卡冲突排查到虚拟显示器配置优化

为什么选择自建 RustDesk?

在远程控制需求日益增长的当下,商业远程桌面软件往往伴随着画质压缩、带宽限速或连接配额限制。RustDesk 是一款优秀的开源远程桌面替代方案。通过自建 ID 与中继服务器,不仅能将控制权与数据隐私完全掌握在自己手中,还能充分利用自家的公网带宽与 IPv6 直连优势,实现超低延迟的流畅体验。

官方网站:https://rustdesk.com/

GitHub地址:https://github.com/rustdesk/rustdesk

本文基于 Docker 环境,完整记录从服务端部署、路由器端口映射、路由冲突排查、无头(Headless)虚拟机显示驱动配置到性能优化的全套落地实操。

一、Docker Compose 服务端部署

推荐使用 host 网络模式部署 RustDesk 服务端,避免 Docker 虚拟网桥带来的 NAT 损耗,使服务端能直接捕获客户端的真实源 IP。

1. 编写配置文件

创建 docker-compose.yml 文件:

YAML

version: '3'

services:
  hbbs:
    container_name: rustdesk-hbbs
    image: rustdesk/rustdesk-server:latest
    # 替换 yourdomain.com 为实际绑定的 DDNS 域名或公网 IP
    command: hbbs -r yourdomain.com:21117 -k _
    volumes:
      - rustdesk-data:/root
    network_mode: "host"
    depends_on:
      - hbbr
    restart: unless-stopped

  hbbr:
    container_name: rustdesk-hbbr
    image: rustdesk/rustdesk-server:latest
    command: hbbr -k _
    volumes:
      - rustdesk-data:/root
    network_mode: "host"
    restart: unless-stopped

volumes:
  rustdesk-data:

2. 参数解析与安全建议

  • -r yourdomain.com:21117:指定中继服务器地址及端口。
  • -k _:强制启用 Key 公钥验证机制。未填写正确公钥的外来客户端将无法借用你的服务端,杜绝被公网扫描盗用流量。
  • 避免强制中继:切勿在环境变量中添加 ALWAYS_USE_RELAY=Y,否则会阻断客户端间的 P2P 直连(UDP 打洞及 IPv6 直连),导致不必要的转发延迟与卡顿。

3. 启动并获取公钥

Bash

# 启动容器
docker compose up -d

# 查看生成的公钥 Key
docker logs rustdesk-hbbs | grep "Key:"

二、OpenWrt 路由器防火墙与端口转发

为了让外网客户端正常访问内网的 RustDesk 实例,需要在主路由上放行并映射对应端口。

1. 端口映射规则汇总

端口范围协议用途说明
21115TCPNAT 类型测试与握手
21116TCP / UDPID 注册、心跳与 UDP 打洞通信(核心)
21117TCP中继数据转发(Relay)
21118 – 21119TCP网页端 Web Client 支持(可选)
processed 00d6ca07 7c95 4149 8328 c00b0ec52ae2

2. OpenWrt 转发配置规范

在 OpenWrt 的 网络 -> 防火墙 -> 端口转发 中新建规则:

  • 名称rustdesk
  • 协议TCP + UDP
  • 源区域wan
  • 外部端口21114-21119
  • 目标区域lan
  • 内部 IP 地址:填写运行 Docker 的服务器内网 IP(例如 192.168.0.7
  • 内部端口:直接留空(系统默认 1:1 映射)或填 21114-21119
  • 高级设置:勾选 启用 NAT 环回
processed 5a5f103a d673 404b 84aa 916473a9bf8b

三、避坑实录:外网无法连接与常见故障排查

若内网连接正常但外网无法建立握手,通常由以下两类经典网络架构问题引起:

1. 双网卡同网段导致的“非对称路由”断流

在 ESXi / PVE 虚拟化环境中,如果虚拟机同时挂载了直通物理网卡和虚拟网卡,且两者处于同一子网并各自获取了默认网关:

  • 故障机理:外网请求从直通网卡进入,而虚拟机内核根据路由表将回包从另一张 DHCP 网卡发出。源 IP 不一致触发了防火墙状态表校验失败(RP_Filter),连接被直接丢弃。
  • 排查命令:Baship route
  • 解决办法:清理多余的默认路由,编辑 Netplan 配置文件(/etc/netplan/*.yaml),注释多余网卡的 DHCP 默认路由,仅保留唯一的静态网关配置后执行 sudo netplan apply

2. 启用 OpenWrt LAN 口 IP 动态伪装 (SNAT)

若内网网络拓扑较复杂,可在 OpenWrt 网络 -> 防火墙 -> 常规设置 中,找到 lan 区域并勾选 IP 动态伪装 (Masquerading)。这样路由器在转发外网请求时,会将源地址伪装为路由器的内网 IP,避开目标服务器的默认网关路由偏差。

四、无头虚拟机解决“没有显示器 (No Displays)”报错

在无物理显示器的 Windows 虚拟机或工控机中,RustDesk 提示“No Displays”是因为 Windows 原生 RDP 独占了虚拟显示通道,或者系统缺少活跃的桌面渲染输出。

processed a9f5515f a0be 41e3 bf56 e1584b0749fd

1. 部署 IddSampleDriver 虚拟显示驱动

  1. 下载开源虚拟显示驱动源码包(如 IddSampleDriver)。
  2. C:\ 根目录创建名为 IddSampleDriver 的文件夹,将配置文件 option.txt 放入其中(用于定义虚拟屏幕的分辨率列表,如 1920 1080 60)。
  3. 右键以管理员身份运行 installCert.bat 导入驱动签名证书。
  4. 打开 设备管理器 -> 操作 -> 添加过时硬件 -> 手动从列表选择 -> 从磁盘安装,选中 iddsampledriver.inf 完成安装。

2. 强制切回物理控制台

如果之前使用了 Windows 自带远程桌面(RDP),退出前必须在管理员终端中执行以下命令交还桌面控制权,避免系统挂起:

DOS

tscon 1 /dest:console

五、低延迟与画质性能调优

针对无独立显卡硬件编码单元的虚拟机,需调整配置以获得最佳流畅度:

  • 关闭被控端「启用硬件编解码」:缺少独立显卡时,强开硬编解码会引发丢帧和进程死锁;关闭后采用 CPU 软解(VP9/AV1)体验更为平稳。
  • 保持「启用 UDP 打洞」与「IPv6 P2P」:允许客户端在移动 5G 与家庭宽带间建立端到端直连,避开中继转发的带宽瓶颈。
  • 开启「移除桌面壁纸」:减少静态画面的冗余数据传输,降低编码负载。
  • 主控端限制 30 FPS:在主控端将帧率上限设为 30 FPS 并选择“平衡”画质,可显著降低虚拟机 CPU 占用。
processed 99ede813 c9d3 4833 ad33 331b085c46f8

常见问题解答 (FAQ)

Q1:RustDesk 客户端如何实现免配置一键安装?

Windows 官方安装包支持根据文件名自动载入配置。将安装包重命名为 rustdesk-host=域名,key=公钥.exe,双击打开即自动填入服务器与公钥。

Q2:自建定制包之后,后续客户端升级会丢失服务器配置吗?

不会。RustDesk 的程序逻辑与用户配置文件相互独立。客户端的服务器与公钥信息存储在 %APPDATA%\RustDesk\config\RustDesk2.toml 中,覆盖升级新版本不会重置该文件。

Q3:为什么打开客户端后长时间显示“连接中”或提示网络错误?

请依次检查:① 域名 DDNS 是否准确解析到当前公网 IP;② 21116 端口的 UDP 协议是否在路由器上成功放行;③ 服务端 Docker 容器是否正常运行且日志无报错。

Leave a Comment