结论:设备身份 JWT 只是建立 Athena 长连接的「门票」,不是本机每个 RPC 方法的授权。本地方法映射没有逐方法角色/权限检查,getMessage() 只要求服务名存在于 SERVICE_LIST;而 WebRTC 本机服务默认监听 127.0.0.1:5001,其 /stream 请求体可自选数据通道名单。因此远程 RPC 与直播应归入独立、非实时的服务域,并把 sendcan 等控制路径排除在通用数据通道之外。
连接、调度与故障路径
manager_thread() 在 DongleId 缺失或为 UnregisteredDevice 时,不启动 manage_athenad/uploader。athenad.main() 用本地私钥签发身份 JWT,作为 jwt cookie 连接 ATHENA_HOST(默认 wss://athena.comma.ai),断开后以带随机抖动的退避重连。网络会话的服务端授权规则不在本地仓库中。
| 组件 | 关键函数 | 边界 |
|---|---|---|
| 接收 | ws_recv() |
文本/二进制帧进入共享 recv_queue;收到 ping 写 LastAthenaPingTime,超过 70 秒无 ping 触发重连。 |
| RPC | jsonrpc_handler()、rpc.handle() |
以方法名查全局 dispatcher,异常转 JSON-RPC 错误;本地方法映射没有逐方法角色/权限检查,也不验证 jsonrpc 版本字段。 |
| 发送 | send_queue_push()、ws_send() |
回复高优先级、日志转发低优先级;按 4096 字符分 WebSocket 帧。共享队列在重连时仍是进程级对象,不能当成精确一次的 RPC 事务。 |
| 活性 | ws_manage() |
根据 IsOffroad 调整 TCP keepalive;仅是连接活性参数,不决定 RPC 授权范围。 |
rpc.handle() 对未识别方法返回 METHOD_NOT_FOUND,参数类型错误返回 INVALID_PARAMS,普通异常返回 SERVER_ERROR;这些错误映射是协议处理,不是权限策略。连接建立后 handle_long_poll() 会启动接收、发送、连接管理、四个上传、日志转发和可配置数量的 RPC worker;worker 将请求原文写事件日志,敏感载荷需另行评估。上传生命周期还有几处状态语义:HTTP 200/201/401/403/412 均结束该队列项,不能把队列移除等同于远端成功存储;cancelUpload() 只标记队列内 ID,正在执行的传输并未由该函数直接中止。此外片段创建在非 PC 平台要求 IsOffroad。
RPC 能力清单
| 能力 | 关键入口 | 源码约束与注意点 |
|---|---|---|
| 设备与网络查询 | getVersion()、getPublicKey()、getSimInfo() |
查询版本、设备公钥、SIM/网络元数据;公开公钥不同于公开私钥,但返回数据仍须考虑设备隐私。 |
| 消息读取 | getMessage() |
可订阅任一注册服务并等待一条消息。该 RPC 是广范围读能力,不能直接授予通用第三方插件。 |
| 日志枚举 | listDataDirectory()、scan_dir() |
从 Paths.log_root() 递归列路径并按前缀筛选;递归时不跟随目录符号链接。 |
| 指定 URL 上传 | uploadFilesToUrls()、_do_upload() |
队列入口拒绝空、绝对或含 .. 的文件名,检查文件存在,随后向请求中的 URL 发 PUT;没有目的域名 allowlist。 |
| 上传生命周期 | upload_handler()、cancelUpload() |
过期 31 天丢弃、计费网络可推迟/中断、特定网络错误重试至最多 30 次。队列移除不等于远端成功存储。 |
| 本地代理 | startLocalProxy() |
仅允许 LOCAL_PORT_WHITELIST={22}(8022 兼容映射到 22),再桥到 127.0.0.1;白名单约束本地目标端口,不是对 remote_ws_uri 的域名校验。 |
| 直播 | startStream() |
固定宽路摄像头、输出 carState/deviceState;仅在持久 CarParams.notCar 为真时声明入站 testJoystick。 |
WebRTC 本机入口与数据桥
webrtcd.main() 默认监听 127.0.0.1:5001,HTTP handler 提供 /stream、/schema、/notify,但在 WebrtcdHandler._dispatch_request() 中没有独立鉴权检查。不能据此推断外部网络可直接访问默认监听地址;本机其他进程、端口转发或修改 --host 后的暴露面需要单独控制。
handle_get_stream() 只要求 JSON content type。会话时限很具体:生成 Answer 限时 30 秒,建立连接限时 15 秒,普通会话最长 300 秒;包含 testJoystick 的 body 会话走不限时等待断开的分支。无会话 5 秒后 schedule_teardown() 清除 IsLiveStreaming。
数据桥的关键不对称在于:远端 Athena 的 startStream() 固定了服务名单,但直接调用本机 /stream 的请求体可自选名单;StreamSession.message_handler() 对入站普通消息仅按本会话 bridge_services_in 名单过滤,代码中没有按主题风险等级的统一许可层。所以必须区分「默认 Athena 调用约束」和「本机服务自身约束」。
/schema 仅检验字段属于 log.Event 且非废弃字段,/notify 向当前会话广播提供的 JSON;CerealOutgoingMessageProxy.update() 把订阅主题转 JSON 发数据通道。handle_post_notify() 的假通道探针确认:通知按当前会话列表逐个广播,某通道发送异常被忽略,即使没有会话也返回 HTTP 200 OK——该返回值只代表本机 handler 完成遍历,不是远端客户端已收到通知的回执。
自制硬件与插件化要求
- 将远程 RPC 与直播纳入独立、非实时服务域。插件注册清单需声明具体 RPC、日志文件和 cereal 主题读写权限;不能把设备身份 JWT 直接作为所有本机方法的全权令牌。
- 本机
/stream、/notify和桥接写主题应由受信任调用方认证并用固定 allowlist 约束;尤其是sendcan、carControl等控制路径不能成为通用数据通道的可写目标。 - 上传能力应限制可访问目录的真实路径、目标 URL/域名与重定向策略,并把「服务端接受」「传输完成」「HTTP 拒绝」「重试耗尽」表示为不同状态。
- 验证矩阵至少包括:断网/重连时队列隔离,恶意 RPC 参数与超大消息,本机端口被非预期进程访问,symlink/路径边界,计费网络切换,会话竞争与清理,权限拒绝及行车状态切换。
以上均为建议的重构验收,不是当前源码已经提供的保证;现有测试并未证明服务端授权、HTTP 本机访问控制、敏感主题限制、外发 URL 范围或实车会话时序。
常见问题
设备 JWT 等于本机方法的授权吗?
不等于。JWT 只用于建立 Athena 长连接;rpc.handle() 以方法名查全局 dispatcher,本地方法映射没有逐方法角色/权限检查。因此不能把设备身份 JWT 当作所有本机方法的全权令牌。
getMessage() 有按主题分级的权限吗?
没有。它只要求服务名存在于 SERVICE_LIST,没有按主题敏感度进一步分级。这是广范围读能力,不能直接授予通用第三方插件。
WebRTC 本机服务是默认对外开放的吗?
不是。它默认监听 127.0.0.1:5001,且 _dispatch_request() 中没有独立鉴权检查。但本机其他进程、端口转发或修改 --host 后的暴露面需单独控制,不能据此断言对外可访问。
为什么说 /stream 的名单约束与 Athena 的不是一回事?
因为远端 Athena 的 startStream() 固定了服务名单,而直接调用本机 /stream 的请求体可自选名单;message_handler() 仅按本会话 bridge_services_in 过滤,没有按主题风险等级的统一许可层。
延伸阅读
- WebRTC 会话生命周期与 HTTP 边界 —— 承接本文会话时限与本机入口。
- 设备身份注册:JWT 从哪来,能证明什么 —— 承接本文设备身份与授权范围的区分。
- 路段下载的鉴权:令牌、会话与缓存各自管什么 —— 承接远程数据访问的授权边界。
- UDS 诊断工具为什么不能随手调:只读、会话与写 ECU 的分权设计 —— 承接控制路径与只读能力的权限分层。
- 片段导出:离线视频任务的边界与状态 —— 承接本文
VideoClips相关能力。
参考资料
- 项目 02 ——
openpilot-research/REMOTE_RPC_WEBRTC_BOUNDARIES_DEEP_DIVE.md(取用了 Athena 连接与调度、RPC 能力清单、WebRTC 本机入口与数据桥、插件化要求)。 - 项目 02 ——
openpilot-research/DEVICE_IDENTITY_REGISTRATION_DEEP_DIVE.md(仅用于确认设备 JWT 的来源与注册前提)。
说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。
更新记录
首次发布 2026-10-11 最近核对:2026-10-11
发表回复