这篇文章上次修改于 902 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

1 RustDesk 介绍

RustDesk 是类似于 TeamViewer 的远程控制 APP,核心语言是 Rust。

2 RustDesk 组成

2.1 服务端

源码:https://github.com/rustdesk/rustdesk-server-demo

目前服务端只是一个 demo。

包括 relay server 和 signaling server。

  • signaling server,监听 21116 端口,负责为客户端提供 peer 端的地址和公钥 pk、relay server 的地址,类似与 WebRTC 中的 signaling server。
  • relay server,监听 21117 端口,负责在多个客户端之间转发 video、audio 流,类似于 WebRTC 中的 STUN/TURN。

2.2 客户端

源码:https://github.com/rustdesk/rustdesk

代码执行流:

  • 启动后,src/ui.rs 会打开 ui/index.tis,同时启动 src/rendezvous_mediator.rs 向 signaling server 注册自己的 id 和公钥 pk。
  • 点击 “Connect” 后,会打开 ui/remote.tis,ui/remote.rs 中会创建 src/client.rs 与 peer 端进行交互。

组成:

  • libs:基础库
  • src/ui:前端。src/ui/index,UI 启动界面;src/ui/remote,控制 peer 端界面。
  • src/rendezvous_mediator.rs:当 APP 启动后,向 signaling server 请求注册自己的 id 和公钥 pk,并获取到 peer 端的 pk 和 address。
  • src/client.rs:当用户点击 “Connect” 按钮后,向 signaling server 发出与 peer 端直连的请求,如果请求成功,说明和 peer 端位于同一个网段,进而直接与 peer 端进行交互;否则,说明和 peer 端不位于同一个网段,需要 relay server 中转,进而与 relay server 交互。
  • src/server:包含了键盘、鼠标、音频、视频服务。
  • src/ipc.rs:负责 UI 和 src/server 的交互。

3 网络交互

3.1 两个客户端位于同一个网段下

当两个客户端位于同一个网段下时,不需要通过 relay server 中转。

img

位于同一个网段下的两个客户端建立安全连接过程:

  • 两个 client 启动后,都会生成自己的 (sk, pk),并把自己的 pk 注册到 signaling server 上。
  • 当 client A 想要向 client B 发起连接时,signaling server 会将 client B 的 pk 发送给 client A,并通知 client B 将 client B 的 signed id 发送给 client A。
  • client B 用自己的 sk 对 id 进行签名,得到 signed id,并生成 (B_pk_b, B_sk_b),将 signed id 和 B_pk_b 发送给 client A
  • client A 收到 client B 的 signed id 后,如果通过 client B 的 pk 解出了 id,说明 client B 的 signed id 正确。接着会生自己的 (A_pk_b, A_sk_b)、nonce 以及 symmetric_key,并采用 (nonce, B_pk_b, A_sk_b) 对 symmetric_pk 进行加密得到 sealed_symmetric_key,然后将 (sealed_symmetric_pk, A_pk_b) 发送给 client B
  • client B 生成 nonce,该 nonce 与 client A 的相等,采用 (nonce, A_pk_b, B_sk_b) 从 sealed_symmetirc_key 中解出 symmetric_key
  • 以后,client A 和 client B 进行通信时,都会用 symmetirc_key 进行加密和解密。

3.2 两个客户端不位于同一个网段下

在上一个图的基础上,会增加 relay server 的中转。比如当 5 punch hole request 失败后,client A 会向 relay server 发出 request relay,后面与 client B 的交互都会由 relay server 中转。