Files
曾志威 5db6b9ef68
ci / rust (push) Canceled after 0s
ci / web (push) Canceled after 0s
ci / package-preview (push) Canceled after 0s
ci / package-installer (push) Canceled after 0s
ci / linux-agent (push) Canceled after 0s
ci / edge-service (push) Canceled after 0s
ci / coturn-pop (push) Canceled after 0s
ci / package-windows-host (push) Canceled after 0s
Initial commit
2026-08-14 00:35:42 +08:00

364 lines
24 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RemoteDesk Linux 被控端设计
## 1. 目标
RemoteDesk Linux Agent 是安装在 Linux 被控机器上的自研组件。它不使用 xrdp、GNOME Remote Desktop 或 KDE KRdp,负责把当前图形会话或命令行终端安全地交付给 Windows 客户端。
首个稳定版本支持:
- 已登录的 Wayland 和 Xorg 用户会话。
- 无图形环境的纯命令行终端会话。
- 用户首次确认后的设备配对。
- PipeWire 屏幕和系统音频捕获。
- libei/Portal 键盘与鼠标控制。
- H.264 视频、Opus 音频和 WebRTC 直连。
- 文本剪贴板、动态分辨率和断线恢复。
- GNOME 与 KDE Plasma 的主流发行版。
登录界面、任意合成器的永久无人值守和内核级抓屏不属于首个稳定版本。
## 2. 进程模型
```text
Windows Client
|
TLS WebSocket (pairing/signaling)
|
remotedesk-agentd root/system service
|
authenticated Unix Socket
|
+---------------------------+
| |
remotedesk-agent-session remotedesk-shell-session
graphical user service target user process
| |
+----+---------+----------+ +--- PTY/login shell
| | | +--- reliable terminal channel
Portal/X11 PipeWire Encoder
| | |
libei/XTest video/audio H.264/Opus
```
### 2.1 remotedesk-agentd
系统守护进程由 systemd 启动,职责严格限制为:
- 维护被控设备身份和已配对客户端公钥。
- 提供配对及会话信令入口。
- 通过 logind 发现当前图形用户会话。
- 验证并联络对应的用户会话 Agent。
- 验证终端权限并创建已降权的 PTY 会话进程。
- 管理版本兼容、健康状态和升级切换。
- 按明确策略调用可选的最小权限 Helper。
它不得读取桌面帧、音频、剪贴板、终端或文件内容,也不得持有用户的 PipeWire 流。
### 2.2 remotedesk-agent-session
用户会话进程通过 `systemd --user` 启动,并绑定到图形会话生命周期。职责包括:
- 请求并恢复 RemoteDesktop/ScreenCast Portal 授权。
- 消费 PipeWire 视频和音频节点。
- 通过 libei/EIS 接收远端输入。
- 进行色彩转换、硬件编码和 WebRTC 发送。
- 管理用户剪贴板及文件接收确认。
- 在本地显示连接状态和终止入口。
注销用户时进程和所有远程会话必须结束。
### 2.3 remotedesk-shell-session
终端会话进程由 `agentd` 在授权后创建。它通过 PAM 建立目标用户会话,完成补充组、GID、UID、工作目录和环境降权,然后创建 PTY 并执行允许的登录 Shell。
每个终端连接拥有独立进程。进程只接收终端字节流、窗口尺寸、信号和会话控制消息,不具备读取桌面或其他用户会话的能力。配对授权可明确允许 `root`(UID 0)会话;未列入授权的用户仍会被拒绝。
## 3. 本地 IPC
`agentd` 与用户会话进程使用 Unix Domain Socket 通信。每个已登录用户拥有独立 Socket,目录由 systemd/runtime directory 创建,不使用可预测的 `/tmp` 文件。
IPC 连接必须验证:
- Socket 文件所有者和权限。
- 对端 UID、PID 和安全标签。
- 用户是否对应有效的 logind 图形会话。
- Agent 主次版本是否兼容。
- 每条会话请求是否携带短期、单次使用的随机令牌。
IPC 只传递配对后的客户端身份、会话控制消息和 WebRTC 信令,不转发视频帧或终端内容。
## 4. Agent 生命周期
```text
Boot
-> agentd Ready
-> Client Paired
-> Desktop: User Login -> session Agent Registered
-> Terminal: PAM Session -> shell Session Spawned
-> Session Requested/Negotiated
-> Streaming or Terminal Active
-> Disconnecting
-> Resources Released
```
任何阶段失败都必须反向释放已创建资源,包括 Portal Session、PipeWire Stream、编码器、WebRTC Peer 和临时令牌。
## 5. 首次配对
Agent 安装时生成设备身份密钥,私钥仅由 `agentd` 读取。配对流程:
1. Linux 本地用户在 Agent 状态界面开启配对,生成短时一次性配对码。
2. Windows 客户端输入地址和配对码。
3. 双方通过 TLS 交换设备公钥和能力摘要。
4. Linux 本地界面显示客户端名称和公钥指纹,用户确认。
5. `agentd` 保存允许的客户端公钥、权限和创建时间。
6. 配对码立即作废,后续使用设备密钥认证。
配对记录可以授予独立权限:查看桌面、控制输入、打开终端、剪贴板、音频、文件传输和无人值守尝试。撤销记录后,现有会话立即结束。
## 6. Wayland 捕获与控制
### 6.1 Portal 会话
用户会话 Agent 通过 xdg-desktop-portal 创建远程桌面/屏幕共享会话,选择显示器并请求键鼠控制。首次请求由桌面环境显示系统授权窗口。
Agent 记录以下能力,而不是假设存在:
- 显示器和窗口捕获。
- DMA-BUF 或内存帧。
- 键盘、相对鼠标、绝对鼠标和触控。
- Portal 恢复令牌及其持久模式。
- 剪贴板接口。
- 系统音频捕获。
如果某项能力不可用,客户端必须禁用对应按钮并展示具体原因。
### 6.2 PipeWire 视频路径
默认零拷贝路径:
```text
PipeWire DMA-BUF
-> GPU color conversion/scale
-> VA-API/NVENC/AMF encoder
-> encoded frame
-> WebRTC RTP
```
零拷贝成立必须同时满足:
- PipeWire buffer 带可导入的 DMA-BUF fd、modifier 和 fence/synchronization 信息。
- Agent 根据 DMA-BUF 的 DRM device/render node 选择同一物理 GPU 的 video processor 和编码器。
- 色彩转换与分辨率缩放在同一 GPU 或可验证的共享 surface 路径完成。
- 硬件编码器直接导入 GPU surfaceAgent 不 map 原始像素,也不通过 `appsink` 取帧。
- buffer 生命周期延续到编码器完成消费,再归还 PipeWire;队列满时丢弃旧帧而不是复制保活。
不同驱动分别验证 VA-API、NVENC/EGL-CUDA 等实际导入路径,不能因为元素名称包含硬件编码器就判定零拷贝。DMA-BUF modifier 不兼容或发生跨 GPU copy 时,状态必须降为 `gpu_copy``cpu_upload`
Agent GPU 策略:
- `capture_device`:默认,跟随 PipeWire DMA-BUF 或 Xorg DRI3 pixmap 所属 DRM render node。
- `manual(adapter_identity)`:只在所选 Adapter 能直接导入捕获 surface 时生效;严格模式不允许为使用另一块 GPU 而复制原始帧。
- 稳定身份使用 PCI/DRM render node/driver 组合,不能持久化临时枚举序号。
显式 compatibility 回退路径:
```text
PipeWire memory frame
-> software color conversion
-> hardware/software encoder
-> WebRTC RTP
```
每个帧对象必须引用计数并设置明确的所有权,避免 PipeWire 回调线程等待编码完成。捕获、编码和传输使用有界队列;出现积压时丢弃旧视频帧,不能阻塞输入和控制消息。
配置 `zero_copy_policy`
- `required_end_to_end`:默认。Agent 端任何 CPU 映射、跨 GPU copy 或软件编码都会终止媒体协商;还必须等待客户端报告已验证的 D3D11 零拷贝路径。
- `compatibility`:仅由用户显式开启,允许 PipeWire memory frame、GPU upload 或软件编码,并显示实际回退状态。
### 6.3 输入模型
Windows 客户端发送统一输入事件:
- 键盘:USB HID Usage、按下/释放、修饰键状态。
- 文本:Unicode 文本提交,处理无法由物理键盘布局表达的字符。
- 鼠标:标准化绝对坐标、相对移动、按键和高精度滚轮。
- 显示:事件携带显示器 ID 与拓扑版本,防止分辨率变化后位置错误。
Agent 优先通过 Portal 提供的 libei/EIS 通道注入输入。`uinput` 仅作为明确开启的兼容性后端,并由独立最小权限 Helper 处理。
### 6.4 音频与剪贴板
- 系统音频从 PipeWire 获取,编码为 Opus。
- 麦克风回传后续增加,默认关闭。
- 剪贴板优先使用 RemoteDesktop 会话关联的 Portal 接口。
- 仅在桌面能力允许时启用图片或文件剪贴板。
- 剪贴板内容不写日志、不落盘,并设置单项大小限制。
当前 Portal 剪贴板尚未接入,Wayland 会话不得据此声明剪贴板能力。协议 minor 15 已实现的范围仅为 X11 与 Windows 控制 helper 之间的 UTF-8 文本:`clipboard_read``clipboard_write` 独立授权,发送方先 Offer,收到匹配 Request 后才发送最多 32 KiB 的 canonical Base64 Data;接收方验证 sequence、长度、SHA-256、UTF-8、NUL 和规范换行,并用最近内容摘要阻止回写循环。root `agentd` 只做方向授权和结构化消息转发,不调用 X11 或 Win32 剪贴板 API。
## 7. Xorg 捕获与控制
Xorg 后端由同一个用户会话 Agent 提供,但不复用 Wayland Portal
- 从 logind 会话环境获取 `DISPLAY` 和对应用户的 `XAUTHORITY`
- 使用 XRandR 枚举显示器及监听拓扑变化。
- 默认使用 XComposite 获取目标 pixmap、XDamage 跟踪变化,再通过 DRI3 `BufferFromPixmap` 导出 DMA-BUF 并直接交给同 GPU 硬件编码器。
- XSync/Present fence 或驱动等效机制负责生产者与编码器同步,未确认完成前不复用 pixmap buffer。
- XShm/XImage 只属于显式 `compatibility` 模式。
- 使用 XTest 注入键盘和鼠标,键盘事件沿用统一 HID/Unicode 模型。
- 画面进入与 Wayland 相同的编码、WebRTC 和质量控制管线。
- 音频继续通过 PipeWire 获取。
Xorg 只有在 XComposite/DRI3 导出的 DMA-BUF 成功直达同一 GPU 编码器且没有 CPU map 时才报告 `zero_copy`。驱动、合成器或 pixmap 格式不支持导出时,默认拒绝图形会话;用户显式选择 `compatibility` 后才允许 XShm/XImage,并在客户端持续显示性能降级。不可通过 `xhost +`、复制其他用户 Cookie 或关闭 X server 访问控制来解决权限问题。
### 7.1 多显示器捕获
Wayland Portal 和 XRandR 的显示器枚举统一转换为协议 `DisplayLayout`。稳定 ID 不使用数组索引;矩形保留主屏左侧/上方的负坐标,scale 使用有理数,布局变化递增 generation。用户可选择主屏、全部显示器或自定义子集。
Agent 对每个选中显示器分别记录捕获 surface、DRM Adapter、import probe 和原始矩形,再生成组合桌面边界与输入坐标映射。分辨率上限作用于组合桌面画布,在保留各屏相对位置和比例的前提下统一缩放,不改变 Wayland/Xorg 实体模式。热插拔、旋转、DPI、分辨率或选择变化会清除旧选择与编码证明、递增 pipeline epoch 并请求新关键帧。
严格零拷贝要求所有选中显示器都能导入同一个目标编码 Adapter,且每屏均无 CPU map、跨 GPU copy 或 opaque 路径。任一屏失败则整个多屏严格会话失败;Compatibility 可以逐屏记录 `CrossAdapterCopy``CpuUpload``Software``Opaque`,但不能把组合后的结果提升为零拷贝。
输入事件包含稳定显示器 ID、布局 generation 和源物理坐标。Agent 只接受当前 generation 且坐标位于对应显示器矩形内的事件,随后再映射到 libei 或 XTest,避免拓扑变化后点击错误屏幕。
## 8. 纯命令行终端
命令行模式独立于桌面媒体管线,适用于没有安装桌面环境的 Linux:
```text
Windows Terminal View
-> reliable DataChannel
-> remotedesk-shell-session
-> PTY
-> user login shell
```
终端协议包含原始 UTF-8 字节、窗口行列、POSIX 信号、退出状态和会话恢复序号。Windows 客户端使用终端模拟器解析 ANSI/VT 序列,滚动缓存保存在客户端。
安全规则:
- 设备配对权限必须单独允许终端。
- 配置将客户端设备映射到允许登录的普通用户。
- PAM 负责账户状态、时间限制和会话审计。
- 启动 Shell 前清理环境,只传递白名单变量。
- 禁止把用户传入内容拼接为 root 命令行。
- `sudo``su` 和审计策略完全遵循目标系统配置。
- 断线后只保留有限宽限期和有界输出环形缓冲区。
## 9. 差网络处理
Linux Agent 的媒体管线必须导出 TWCC/GCC 目标码率、RTT、丢包、抖动、NACK 和 PLI 指标。质量控制器按状态动态更新编码码率、帧率和缩放档位:
- 轻微丢包先降低码率,不立即降低桌面分辨率。
- 持续或突发丢包再降低帧率和分辨率。
- 收到 PLI 时请求 IDR,并限制关键帧频率。
- 输入和音频队列优先于视频。
- 严重丢包时暂停文件传输并限制剪贴板大对象。
- 网络恢复后使用较长窗口逐级升档。
分辨率请求作用于捕获后的 scaler/caps 和编码器,不修改 Wayland/Xorg 实体显示模式。Agent 公布源尺寸、最小/最大编码尺寸、像素数上限、对齐要求和是否支持运行时重配;请求越界时返回结构化错误或明确的 capability clamp。切换成功后递增 generation、请求关键帧,并重新发布源尺寸与实际编码尺寸。输入坐标始终基于源显示器拓扑映射,不以降采样后的编码尺寸直接注入。
鼠标移动允许丢弃过期事件,键盘和鼠标按键必须可靠发送。断线恢复后双方同步输入状态,避免远端出现卡键。完整策略见 [差网络自适应设计](network-adaptation.md)。
## 10. 媒体和控制协议
WebRTC 负责 DTLS-SRTP、媒体时钟、丢包反馈和拥塞控制。Agent 不自行设计视频网络协议。
控制消息使用版本化 Protobuf,并在 DataChannel 上传输。协议包头至少包含:
```text
protocol_major
protocol_minor
session_id
message_type
sequence
monotonic_timestamp
payload
```
兼容规则:
- 主版本不同则拒绝会话并返回升级提示。
- 次版本能力通过握手位图协商。
- 未识别的可选字段忽略,未识别的必需能力拒绝。
- 输入、心跳和媒体控制使用独立 DataChannel,避免大剪贴板阻塞输入。
## 11. 编码策略
第一版以 H.264 为强制共同编码格式,Opus 为音频格式。能力协商顺序:
1. 枚举客户端解码能力。
2. 枚举 Linux GPU 和驱动编码能力。
3. 将捕获 surface 的 DRM device 与编码器 Adapter 对齐,再选择双方都支持的编码器和像素格式。
4. 用短帧验证 DMA-BUF/GPU surface 是否在无 CPU map 的情况下被编码器导入。
5. 根据 `zero_copy_policy` 同时确认 Agent 编码路径和客户端解码/呈现路径;默认任一端失败即拒绝。
6. 会话中监控编码耗时,超限时降低帧率或分辨率。
办公模式对文字区域保留较高质量并降低静态刷新;动态模式缩短编码队列并提高帧率。HEVC、AV1 和区域编码在 H.264 稳定后增加。
## 12. 无人值守边界
Wayland 的安全模型决定了通用 Agent 不能无提示控制任意会话。
支持层级定义为:
| 等级 | 能力 | 首版 |
|---|---|---|
| L1 | 用户在线并确认本次 Portal 授权 | 支持 |
| L2 | 首次确认后,使用 Portal 恢复令牌再次连接 | 按桌面能力支持 |
| L3 | 用户已登录但锁屏 | 按发行版验证 |
| L4 | 显示管理器登录界面 | 不承诺,需按合成器适配 |
| L5 | 无显示器、无图形用户会话 | 桌面不支持;命令行支持 |
客户端必须显示目标机器当前支持的等级,不能把 L1 描述为完整无人值守。
## 13. 安装与升级
Linux 发布物至少提供 DEB 和 RPM:
```text
/usr/bin/remotedesk-agentd
/usr/bin/remotedesk-agent-session
/usr/libexec/remotedesk-shell-session
/usr/lib/systemd/system/remotedesk-agentd.service
/usr/lib/systemd/user/remotedesk-agent-session.service
/usr/share/applications/remotedesk-agent-settings.desktop
/usr/share/dbus-1/services/...
/usr/share/polkit-1/actions/...
```
安装脚本只创建系统服务、受限用户/目录和必要策略,不修改 SELinux/AppArmor 为宽松模式。升级采用先写新文件再切换的方式,协议不兼容时保留上一版本回滚能力。
当前 `0.2.9` 工程切片已经提供四个二进制、systemd system/user unit、静态 x64 便携包、musl DEB,以及 Ubuntu CI 的原生 DEB/RPM 构建。`agentd` 可完成设备身份、一次性配对、证书指纹固定、Ed25519 客户端认证、终端授权和文件传输;用户会话进程通过 `SO_PEERCRED` 校验的 Unix Socket 注册;终端 helper 通过 `runuser --login` 建立 PAM/PTY 会话,文件 helper 以授权普通用户身份将路径限制在用户主目录并执行大小/SHA-256 校验,协议 minor 4 还通过目标端实测 partial offset 和整文件重新哈希支持上传/下载断点续传,Windows 控制端已包含配套 helper。可选 Edge 客户端注册 60 秒 Presence 路由、每 30 秒续期、失败有限退避并在 SIGINT/SIGTERM 时限时注销;在线时每次信令 poll/ack 都使用设备私钥、时间戳和一次性 nonce 签名。普通 Intent 重新验证已配对 Client、permission 和 allowed user`pairing` Intent 只在 Agent 本机配对窗口有效时签发 relay,真正的一次性码仍在证书固定 TLS/WSS 内验证和消费。授权后 Agent 使用独立一次性票据主动连接 relay 并透明代理到本地 TLS listener。Windows 控制端录入 `pairing-code` 输出的设备公钥和证书指纹即可远程首次配对;成功后按证书指纹记录 Agent 公钥,后续已知设备同样无需 Client 连接 Agent 地址。`status --json` 和 WSS Hello/Status 会报告在线、信令能力、接受/拒绝计数和清洗后的错误,状态文件不含 URL、令牌、请求或配对码。
协议 minor 10 的源码包含 X11 兼容桌面:用户会话以 UID 固定的 `0600` Socket 注册 X11 捕获端点,Agentd 再次核对 Socket peer PID/UIDroot window 在源尺寸和像素上限验证后通过 `GetImage` 捕获,XTEST 输入根据当前用户 X server 的 keyboard mapping 解析 keysym。输入覆盖缩放绝对坐标、有界相对移动、五键鼠标、水平/垂直滚轮和键盘;Windows helper 显式抓取光标后合并 Raw Input 位移,失焦、重连和退出会解除抓取并释放输入。帧使用有界 zlib BGRA 分块、整帧 SHA-256 和成功呈现后的逐帧 ACKWindows 控制 helper 新增等比例软件 framebuffer、黑边输入排除、全屏与退出;跟随窗口模式合并 500 ms 内的连续变化,并在当前帧 ACK 后动态重配下一帧的 200..8192 捕获上限,不修改 Xorg 实体模式。Agent 根据真实编码耗时和呈现 ACK 调整 1..30 FPSzlib 模式另在 level 1..6 内调整压缩。异常断线按 1、2、4 秒最多重连三次;用户会话进程会先释放全部 XTEST 输入,再保留 15 秒 X11 连接、帧序列和自适应控制器,恢复令牌绑定 Client 指纹和 Linux 用户。每次 UI 启动会生成受限会话 ID,helper 只写不含地址、用户或凭据的诊断,并回传 RTT、压缩比例和采集/编解码/呈现耗时。接受的 Edge 桌面会话在 Agent/Client 两端创建真实 WebRTC PeerConnection;用户会话复用同一次 BGRA 捕获,以 GStreamer 选择 VA/VAAPI/NVENC/QSV/OpenH264/x264 编码器,输出 Annex-B AU。AU 通过 16 MiB 总上限、45 KiB 分块、严格顺序、canonical base64、精确长度和 SHA-256 的内部 IPC 后,由 agentd 交给绑定 session 过期时间、目标用户和 Client 指纹的 H.264 sender;断开时撤销。Windows helper 使用单 NAL/STAP-A/FU-A 重组、跨帧序号检测、PLI/关键帧恢复和一槽有界媒体邮箱,再经 Media Foundation H.264 MFT 输出同 device NV12 surface 并由 D3D11 VideoProcessor 呈现。第一张原生帧呈现后双方确认 H.264-only,停止完整 zlib 编码和传输;每张 H.264 的 sequence 呈现 ACK 驱动下一次捕获。解码、媒体、sender/encoder 或 ACK 失败会显式恢复 zlib。协议 minor 11 的 Wayland 源码在认证后请求 Portal,只接受单显示器 DMABUF 到 VA H.264 严格管线,首个 IDR 与 `reis` EIS Sender/设备/XKB keymap 就绪后才打开会话;媒体复用相同有界 H.264 IPC、WebRTC sender 和 Windows 呈现 ACK,输入按 stream/region `mapping_id` 注入,resize 先停止旧管线再重建并等待新 IDR。协议 minor 12 在意外断线时释放全部 EIS 输入和旧编码器,把 Portal/EIS 置入绑定 Client 指纹、Linux 用户及轮换令牌的 15 秒租约;新 WebRTC sender 就绪且绑定校验通过后才消费租约、重建编码器并从新 IDR 恢复。协议 minor 13 复用同一媒体内核,经证书固定和 Ed25519 认证后的直连 WSS 交换有界 SDP/ICE,并把授权精确绑定 Client 指纹、Linux 用户、尺寸和 FPS;只有 PeerConnection connected 且双方 ICE 完成后才进入桌面协议,失败则显式同步 abort/unavailable。minor 14 增加默认关闭的 `opus_audio` 协商,只捕获 Linux 系统输出 monitor,以固定 48 kHz 双声道、20 ms Opus 经 4 KiB 有界 IPC 和 SRTP 发送;Windows 使用有界队列、IronRDP Opus 解码和 WASAPI 播放,音频失败不会关闭视频,minor 13 及更旧客户端不会收到音频事件。显式关闭、媒体/输入错误和超时仍立即关闭 Portal。新增路径按要求尚未解析依赖、编译或在真实 GNOME/KDE/VA/音频设备上运行,因此相关运行时能力仍受保守平台开关控制。
协议 minor 15 进一步把 X11 selection、Windows `CF_UNICODETEXT` 工作线程和桌面协议状态机接通。用户会话只在 `clipboard_read` 为真时轮询并 Offer 本地 X11 文本,只在 `clipboard_write` 为真时接受 Client Offer、请求并写入;Windows 侧使用有界线程和 channel 隔离同步 Win32 API。该源码尚未编译或在真实 Windows/Xorg 剪贴板所有者之间验收,Wayland 剪贴板仍关闭。
Edge Presence 默认关闭。只有同时设置 `REMOTEDESK_EDGE_API_URL``REMOTEDESK_EDGE_PRESENCE_TOKEN``REMOTEDESK_EDGE_REGION``REMOTEDESK_EDGE_GATEWAY_ID` 才会启动;缺少任一项会拒绝启动。公网 URL 必须为 HTTPSHTTP 仅允许 loopbackPresence 令牌至少 32 字节且必须与管理员令牌、票据密钥分离。安装包只附注释模板,不生成或携带凭据。
Windows 控制端可在全局设置中保存无凭据的 Edge HTTPS Origin。首次配对时同时填写 Agent 本地命令输出的 `device_public_key` 和证书指纹,即可经 Edge 建立;缺少其中一项时 helper 保留直连回退。配对后 helper 把 Agent 公钥保存到 `RemoteDesk/Linux/agent/<certificate-sha256>`,该值不是秘密,但会决定 Edge 请求的目标设备身份,必须按完整性敏感数据保护。Linux helper 使用现有 Credential Manager Client key 公开提交签名 Intent,并以原始签名认证状态查询;它不接收 Edge 管理员或 Presence 令牌。Agent 返回授权后,两端分别使用角色绑定一次性票据连接 relay,终端和文件字节在 relay 内重新建立的证书固定 TLS/WSS 中传输。公网 relay authority 必须经系统信任 TLS/L4 入口发布,raw TCP 只允许 loopback。控制端 Linux Terminal 面板可查询或显式删除映射;删除后可再次经 Edge 或直连配对。
## 14. 安全检查项
- system daemon 媒体零接触。
- 所有外部输入先做长度、枚举和状态验证。
- 配对码限时、限次并带失败速率限制。
- 客户端权限可查看、修改和撤销。
- Portal 授权状态在 Linux 桌面上始终可见。
- 文件传输需要每次确认,保存路径不可目录穿越。
- 依赖生成 SBOM,并持续跟踪 GStreamer/WebRTC/PipeWire 安全更新。
- 崩溃转储默认排除视频帧、密钥和剪贴板缓冲区。
## 15. 首个开发切片
开发拆成三条窄路径,按顺序打通:
1. 基础:`agentd`、设备配对、受认证 IPC 和会话状态机。
2. 桌面:先打通 GNOME Wayland Portal/PipeWire,再复用媒体管线增加 Xorg/XDamage 后端。
3. 终端:完成 PAM 降权、PTY、可靠 DataChannel 和 Windows 终端控件。
三条路径稳定后再增加硬件编码验证、剪贴板、多显示器、KDE 和持久授权;系统输出 Opus 已进入源码链路,但仍需平台验收。