题干与适用场景
请设计一个多租户 Certificate Transparency(CT)日志监控器。用户提交一个或多个域名后,系统持续检查公开 CT 日志,发现匹配证书或预证书时发送告警;同时要能证明日志数据没有被静默改写,并在日志停滞、证明失败或超过最大合并延迟时报警。
这道题适合系统设计、平台安全和证书基础设施岗位。回答重点是可验证的数据管道与故障边界,不是堆砌微服务名称。
面试官考察点
- 是否能区分监控器、浏览器策略和 CA 签发流程。
- 是否理解签名树头(STH)、Merkle inclusion proof、consistency proof 与 append-only 语义。
- 是否把最大合并延迟(MMD)转成可观测的调度与告警条件。
- 是否处理多日志、重复拉取、日志分叉、不可用和租户隔离。
- 是否给出可复核的存储、幂等、告警降噪和容量估算。
回答前需要澄清的问题
先确认四个边界:
- 监控范围是精确域名、注册域,还是还包括通配符与 SAN 中的名称?
- 目标是近实时发现,还是允许分钟级延迟?告警通道有哪些,是否需要值班升级?
- 需要监控公开日志全集,还是只监控若干可信日志?是否要求保存原始证书和证明材料?
- 多租户规模、保留周期、隐私要求与预算是多少?
若面试官没有补充,可以假设监控 100 个日志、每个日志每分钟轮询一次,端到端发现延迟目标为 5 分钟,并保留可审计证据。
30 秒回答框架
我会把系统拆成日志采集、密码学验证、证书匹配、告警和审计五层。每个日志维护已验证的树大小与最新 STH;采集器先验证 STH 签名,再按树大小增量拉取条目,并用 inclusion 或 consistency proof 检查 append-only。匹配层解析 SAN、通配符和注册域,告警层按租户策略去重和升级,审计层保存原始条目、STH、证明和哈希。核心指标是 STH 新鲜度、日志延迟、证明失败率、告警延迟和误报率;日志分叉或 MMD 违规会冻结该日志的可信状态并升级处理。
分步骤深入解答
1. 采集与状态机
为每个日志保存日志标识、公钥、当前可信树大小、最后验证 STH、最后拉取时间和状态。调度器按日志状态分配任务;正常状态增量拉取,短暂不可用采用指数退避,连续失败进入隔离状态。任务键使用日志标识加目标树大小,保证重试幂等。
2. 验证 STH 与 Merkle 证明
采集器先用日志公钥验证 STH 签名和时间字段,再检查树大小单调不减。首次同步可以获取一个完整快照;后续同步使用 consistency proof 证明新树包含旧树。每个匹配条目再用 inclusion proof 证明它确实属于该树。证明失败、树大小回退或签名错误都不能直接覆盖旧状态,应保留证据并把日志标成可疑。
3. 增量读取与完整性
按已确认树大小请求新区间,写入原始证书、预证书、日志索引和接收时间。服务端按条目标识去重,但不丢弃同一证书在不同日志中的出现。超过 MMD 仍没有可验证的新 STH 时,记录日志延迟并发出平台告警;不能把“没有匹配证书”误判成“日志没有新条目”。
4. 证书匹配与告警
解析证书 SAN、通配符、issuer、notBefore、notAfter 和证书指纹。匹配策略以注册域和显式名称为主,避免简单字符串包含造成误报。告警事件包含租户、名称、日志、证书指纹、首次观察时间和证据链接。相同指纹在短窗口内去重;新 issuer、短有效期、关键生产域等策略可以提高严重级别。
5. 存储、租户和恢复
热状态放在关系库或键值库,原始条目和证明放对象存储,按日志与树大小建立索引。事件写入不可变审计流,便于重放验证。租户查询只返回授权域名;采集器使用每日志限速和全局并发上限,避免压垮公开日志。丢失本地状态时,从最近可信 STH 恢复,再用 consistency proof 追上,不直接信任最新未验证游标。
6. 可观测性与故障处理
监控 STH age、MMD lag、已确认 tree size、抓取吞吐、proof failure、日志可用率、匹配率、告警延迟和重复率。日志服务不可用时继续保留最后可信状态并重试;日志分叉或一致性证明失败时暂停该日志的匹配结果,切换到其他日志并触发安全事件。告警服务失败时把事件写入持久队列,恢复后按事件 ID 投递,避免重复通知。
高质量示范回答
我会先定义“可信进度”:只有签名正确、树大小单调、并通过一致性证明的 STH 才能推进某个日志的游标。采集器为每个日志维护这个游标,并在任务中记录请求范围和重试令牌。首次运行获取基线,之后按树大小增量读取;每个条目保存证书指纹、SAN、日志位置、原始响应和验证证明。
匹配服务将 SAN 规范化后与租户关注名称比较,支持精确名称、注册域和明确的通配符规则。事件以“租户加指纹加日志”幂等键写入队列,通知服务按策略去重、升级和回执。审计存储保留 STH、proof、条目哈希和验证版本,使安全团队可以独立重放。
我会把日志异常视为数据可信度问题:签名错误、树回退、一致性证明失败或 MMD 超时都会生成高优先级平台事件,相关日志进入隔离状态,旧可信状态不被覆盖。容量上通过按日志分片、限速、批量读取和对象存储控制成本;多租户边界由授权查询和每租户配额保证。最终用 STH 新鲜度、proof failure、发现延迟、告警误报率和重放成功率验收。
常见错误
- 只轮询一个日志,忽略证书可能出现在多个日志。
- 只看证书文本,不验证 STH 签名与 Merkle proof。
- 用“最新请求成功”推进游标,导致未验证数据污染可信状态。
- 把 MMD 当成证书有效期,或完全不设置日志新鲜度告警。
- 用字符串包含匹配域名,误报相似名称和不相关 SAN。
- 发现同一指纹就全局去重,丢失跨日志出现位置。
- 日志异常时继续发送“证书未发现”的低置信度结论。
- 只保存最终告警,不保存原始条目、STH 和证明,无法审计。
追问及应对
如果日志返回了树回退怎么办?
拒绝推进游标,保存新旧 STH 和响应,冻结该日志并触发一致性异常告警。只有人工确认或重新建立可信基线后才恢复。
如何降低近实时轮询的成本?
按日志分片、批量读取新区间、动态调整轮询频率,并将冷证据放对象存储。安全告警的延迟目标不能通过跳过验证换取。
如何验证域名归属?
监控创建时要求 DNS、HTTP 或组织授权证明;之后只允许授权主体修改匹配规则,并记录变更审计。
监控器和浏览器 CT 策略有什么区别?
监控器负责发现和证明公开日志中的条目,浏览器策略负责决定证书是否满足连接要求;两者的失败处理和信任边界不同。
如何测试系统?
使用可控日志或录制响应注入签名错误、proof 错误、树回退、MMD 超时、重复条目和通知重试,验证游标不会错误前进、事件幂等且审计可重放。