批处理跑在入队之前 — 时钟快了 2.4 秒
目标
把表示方式各不相同的五台主机的日志汇集到同一条轴上,找出在时间层级中被孤立的主机,通过请求与响应的矛盾求出时钟误差的下限,然后区分能用校正解释的和不能解释的,撰写时间可信性陈述书。
为什么重要
调查和审计问的都是“什么先发生”。这个答案来自记录中的时间,而记录中的时间,是留下它的机器的时钟所显示的值。相差 2 秒左右的时钟,会在没有人察觉的情况下颠倒因果。隔离网络中没有外部时间源,所有人都对齐到网络内的一个时间源,所以彼此的顺序虽然一致,绝对时间却得不到保证。如果陈述书中不写这个局限,日后整份文档就会崩塌。
为什么用数据来判定
实验用的 Pod 没有 capability,所以无法使用 chronyc、ntpdate,系统时钟也无法修改。因此本实验只依据同步状态报告和日志来判定。在真实现场,提交给监理的也不是命令输出,而是这个判定的结果,chronyc tracking 与 sources 的输出所处的位置,就是这里 sync.json 所放的位置。这是本实验的假设。
步骤
- 用
python3在/root/clock/data中创建sync.json、meta.json、五份日志和requests.csv。 - 把五份日志以
host,seq,epoch_ms,evt的格式汇集到/root/clock/normalized.csv,并把不带偏移量的日志误当作 UTC 来读的影响写入/root/clock/naive.json。 - 把每台主机的时间源链写入
/root/clock/chain.json,把到不了所声明时间源的主机写入/root/clock/isolated.txt。 - 把响应早于请求的案例写入
/root/clock/paradox.csv,把时钟误差的下限写入/root/clock/bound.json。 - 把同一台主机日志内时间发生倒退的位置写入
/root/clock/backward.csv。 - 把用偏移量校正后的时间写入
/root/clock/corrected.csv,把校正前后的矛盾数写入/root/clock/paradox_after.json。 - 把每台主机的记录可信等级,以
host,level,reason的格式写入/root/clock/trust.csv。 - 在
/root/clock/statement.json和/root/clock/statement.md中撰写时间可信性陈述书。
参考
- 日志的表示规则在
/root/clock/data/meta.json中。如果把不带偏移量的日志当作 UTC 来读,会偏移九个小时。 - 第 7 步的判定规则按顺序应用。层级未到达则为
설명안됨,否则日志中有倒退时为설명안됨,否则校正之后该主机仍卷入矛盾时为설명안됨,否则曾卷入校正前的矛盾则为보정으로설명됨,其余为확인됨。reason依次为계통미도달、역행、보정후모순、보정필요、없음。 - 校正公式为
참값 = 관측값 - offset_ms。符号弄反,矛盾反而会增加。 - 常见错误 1:把
epoch_ms当作实数。请四舍五入为整数毫秒后写入。 - 常见错误 2:把同步与时间戳证明当作同一回事来写。二者是不同的层面,由 RFC 3161 负责后者。
- 标准文档:RFC 5905、RFC 3339、NIST SP 800-92。
创建同步报告和五台主机的日志
用 python3 在 /root/clock/data 中创建 sync.json、meta.json、从 node-a.log 到 node-e.log 的日志,以及 requests.csv。直接使用不含随机数的生成脚本。
隔离网络里没有可以下载的样本,所以先亲自创建数据。不使用随机数,才能保证无论谁运行多少次,得到的数据都相同,彼此的判定才能比对。评分器会把数据转换成标准形式并核对指纹,所以手工修改的话,后面的步骤会全部被卡住。
把四种表示方式汇集到同一条轴上
在 /root/clock/normalized.csv 中,第一行写 host,seq,epoch_ms,evt,写入五份日志的全部事件。在 /root/clock/naive.json 中写入 naive_utc_hosts、shifted_events、shift_hours。
epoch_ms 是以 UTC 为基准的整数毫秒。带偏移量的可以直接读取,不带偏移量的必须按 meta.json 所告知的时区来读。把它当作 UTC 来读会偏移几个小时,就是 naive.json 的内容。
沿着时间源层级一直追踪到底
在 /root/clock/chain.json 中以列表形式写入每台主机所追踪的时间源链,并把到不了所声明时间源的主机写入 /root/clock/isolated.txt,每行一个。
链从该主机的 source 开始,一步一步追踪。遇到 LOCAL,或者再次遇到已经走过的名称,就在那里停止,并把那个名称也放入链中。所声明的时间源本身,不参与孤立的判定。
用响应早于请求的案例求误差的下限
在 /root/clock/paradox.csv 中,第一行写 req_id,sender,receiver,delta_ms,写入 delta_ms 为负数的案例,并在 /root/clock/bound.json 中写入 min_skew_ms、sender、receiver。
delta_ms 是接收时间减去发送时间所得的值。如果为负数,就意味着两个时钟至少相差这么多,而最大负数的绝对值就是下限。下限用正数书写。
找出同一台主机内时间发生倒退的位置
在 /root/clock/backward.csv 中,第一行写 host,seq,prev_epoch_ms,epoch_ms,写入同一台主机的日志中时间比前一行更小的位置。
按主机,依 seq 顺序读取,并与前一行的时间比较。请按主机分开查看,不要混在一起。发生时间倒退的区间,其记录的顺序不能作为依据。
用偏移量校正,看剩下什么
在 /root/clock/corrected.csv 中,第一行写 host,seq,epoch_ms,写入校正后的时间,并在 /root/clock/paradox_after.json 中写入 before、after、remaining。
校正就是从观测值中减去该主机的 offset_ms。符号弄反,矛盾反而会增加。请求也用同样的方法,在两侧校正之后重新统计负数,剩下的就是无法用时钟解释的真正缺陷。
为每台主机评定记录可信等级
在 /root/clock/trust.csv 中,第一行写 host,level,reason,对有日志的五台主机做出判定。规则按实验说明中的顺序应用。
规则只应用最先符合的那一条。层级到达不了的主机,不必再看其他依据,直接判定为无法解释的那个韩文值(韩文,意为“无法解释”)。校正前卷入了矛盾、但校正后消失的,是可以有条件使用的区间。
撰写同时写明可信与不可信内容的陈述书
在 /root/clock/statement.json 中写入 root、root_has_external_reference、confirmed、corrected、unexplained、min_skew_ms、remaining_contradictions,并在 /root/clock/statement.md 中写 ## 판단、## 근거、## 믿을 수 없는 것、## 남은 의심 四个小节,不少于 500 字。
陈述书中的值不要手工统计,而要取自与前面步骤相同的计算。时间源是否拥有外部基准,取决于该时间源的 source 是什么。不可信的主机要写出名字,读的人才知道该排除什么来阅读。