OONI 如何分辨坏掉的测量数据:从启发式规则到匿名凭证¶
本文是 anoni.net 对下面这篇 OONI 工程文章的导读与摘要,带你逐节看懂原文在做什么,不是逐字翻译。原文另有约 20 张统计图与多份完整数据表,想看数据细节请直接读原文:
很多人靠 OONI 的公开数据集,判断「某个网站在某个国家连不连得上」,anoni.net 自己的 ASN 涵盖观测也建立在同一份数据上。只要有人往里面灌假数据,或设备设置错误产生误导性的纪录,这份数据的可信度就会被稀释。OONI 在最近一篇工程文章1里完整说明,他们如何找出这些坏掉的测量,以及新上线的匿名凭证(anonymous credentials)系统如何在不保存个人数据的前提下挡掉滥用。这套「不留个人数据也能评估谁值得信任」的做法,本身就是一个值得社区参考的隐私工程范例,后面第五节会回到这点。
OONI(Open Observatory of Network Interference,开放网络干扰观测站)是一个全球的网络审查观测项目,手机 app OONI Probe 会连上一份网站清单,回报每个网站在当地连不连得上,结果一律进到公开数据集。任何人都能下载这份数据做分析,好处是开放,代价是任何人也都能往里面送数据。这篇文章要回答的问题,就是在开放投稿的前提下,如何辨认并过滤掉品质有问题的测量。
这篇文章想解决的问题¶
OONI 想先用手上已经有的数据,建立一套辨认坏测量的基准,再看新的匿名凭证系统能把这个基准往上推多少。这里说的启发式(heuristic)是一组简单、成本低的判断规则,不追求百分之百准确,先用几条经验法则把可疑的测量筛出来。全文分成三大块:先用这些简单规则检查既有数据能揪出多少问题(既有启发式与四类发现),再想能补上哪些更高级的规则(新启发式),最后处理找到坏数据之后要用什么机制应对(缓解策略与匿名凭证)。
一、既有的指针与启发式(Existing metrics and heuristics|Approach & Methodology)¶
这一节先不动用任何新技术,只问一件事:光靠 OONI 现在就收得到的数据,能不能认出坏掉的测量?他们挑了四个不需要牺牲用户隐私的检查角度:IP 地理位置对不上、测量数量暴增、时间戳记兜不拢、操作系统与版本信息互相矛盾。每个角度原文都附了但书(caveat),说明什么情况下这个信号会误判。例如探针(probe)内置的 GeoIP 数据库可能过期,导致 probe_cc(探针回报的国码)本来就会跟真实 IP 对不上,分析时要先把这种正常误差滤掉。这一节是后面所有发现的方法论基础。
二、四类异常的实际发现(Assessment & Findings)¶
把上面四个角度实际套到数据上,得到四组发现。
IP 地理位置对不上¶
OONI 在 2025 年 3 月 19 到 21 日,于探针调用 /api/v1/check-in 端点时记录 log,比对探针自己回报的国码、ASN(自治系统编号)跟收集端看到的真实出口 IP。16,139 笔样本里有 1,196 笔对不上,约 7.41%。原文列出最常见的 10 组国码错配(回报国码对照真实 IP 所在国码):
| 回报国码 | 真实 IP 国码 | 笔数 |
|---|---|---|
| US 美国 | CA 加拿大 | 89 |
| CA 加拿大 | RU 俄罗斯 | 49 |
| CZ 捷克 | US 美国 | 43 |
| BS 巴哈马 | US 美国 | 36 |
| CA 加拿大 | US 美国 | 30 |
| CA 加拿大 | SG 新加坡 | 30 |
| CZ 捷克 | GB 英国 | 25 |
| CA 加拿大 | KH 柬埔寨 | 18 |
| AU 澳洲 | KH 柬埔寨 | 18 |
| US 美国 | DE 德国 | 16 |
追下去发现绝大多数对不上的来源是 VPN。出现最多的供应商是 Datacamp、Cloudflare、M247 这些已知的 VPN 机房,其中「回报加拿大、真实 IP 在俄罗斯」那 49 笔全部来自 Cloudflare,对应的是用 WARP 这类 VPN 的用户。表格里多数组合都是同一个道理,探针以为自己在 A 国,真实流量却从 B 国的 VPN 出口冒出来。结论是这些不一致几乎都跟 VPN 有关,没有看到明显可归因于恶意窜改或探针设置错误的量。
测量数量暴增¶
他们看每个探针在 1 分钟内跑出多少笔测量,正常的平均是 8 笔,99 百分位是 54 笔。筛出每分钟超过 200 笔的极端案例后,发现一个自称 ooniprobe-react-os、并非 OONI 官方发行版本的客户端。它只针对 probe_cc = CN(中国)送数据,以每分钟 200 笔(相当于每秒 3 笔)的速度送出 web_connectivity 测量,速率远超正常范围。更反常的是,这个来源送出测量的速度比同地区其他探针还快,量这么大却没有出现对应的网络瓶颈。另一个案例是缅甸在 2025 年 1 月 6 日出现的阵发性暴增。
时间戳记兜不拢¶
比对测量开始时间 measurement_start_time 跟 measurement_uid 里内含的时间戳,看有没有「太晚上传」或「时间来自未来」的纪录。2025 年 3 月 2 日到 4 月 1 日这段,3,440 多万笔测量里只有 0.82% 有时间异常,多数是过去、集中在 Linux。原文依平台拆解如下,Linux 的异常率 2.16% 明显高于其他平台:
| 平台 | 过去异常(>1h) | 未来异常(>1h) | 异常合计 | 该平台总量 | 异常率 |
|---|---|---|---|---|---|
| ios | 2,375 | 0 | 2,375 | 240,843 | 0.99% |
| windows | 34,192 | 24,938 | 59,130 | 10,503,040 | 0.56% |
| android | 21,132 | 5,509 | 26,641 | 10,389,320 | 0.26% |
| macos | 906 | 0 | 906 | 3,103,961 | 0.03% |
| linux | 185,322 | 7,908 | 193,230 | 8,947,716 | 2.16% |
这里有一个很具体的例子:大量异常来自委内瑞拉同一个 ASN,OONI 联系上当地伙伴后发现,是那批设备的时区被设错了。把委内瑞拉排除后,Linux 的异常数字大幅下降,其他平台几乎不变。设置错误就足以产生误导性的纪录,不必然是恶意。
操作系统与版本信息互相矛盾¶
检查软件名称跟平台兜不兜得起来,例如 software_name = ooniprobe-android 却标成 iOS。找到 718 笔 Android 软件跑在非 Android 平台上,其中一部分追出来是 OONI 团队成员自己开发用的机器,另一部分又是前面那个中国来源的 ooniprobe-react-os。他们也列出几个没见过的软件名称(Vladhog、murakami-ooniprobe、MySorgenia、Dismantle 等),逐一查证是什么来路。很多看起来可疑的数据,多半来自开发过程或第三方 fork,跟攻击无关。
四类发现合起来给出一个让人安心的结论:OONI 目前没有在数据里找到大量恶意污染,绝大多数异常来自 VPN、设置错误、开发机器或非官方分支。防御机制要做,但威胁目前不是迫在眉睫的大规模攻击。
这个结论对我们有直接意义。anoni.net 的 ASN 涵盖分析、Tor Relay 观测点都建立在 OONI 公开数据上,看到源头没有被大量污染,用起来可以比较放心。同时这四类发现也提醒我们,读 ASN 数据时 probe_cc 不等于当地实际的连接状况(ground truth)。VPN 造成的地理错配、时区设错这类噪声本来就存在,做分析时要记得先滤掉。
三、想再补上的新启发式(New heuristics)¶
既有规则之外,OONI 想再加几种更高级的侦测。定位一直是最大的难题,因为 GeoIP 数据库由探针自己查、又会过期。他们考虑的补强包括:向手机操作系统取得移动网络的国码与运营商代码(MCC/MNC)、询问操作系统的定位服务、或改在服务器端做 IP 到地点的对照。每种做法原文都附了限制,例如服务器端对照会被翻墙工具挡在中间、看不到真实 IP,问定位权限则可能引起用户疑虑。另外还想加上网络层与协定层的异常侦测,例如从 TLS 交握的指纹认出中间人设备(像是改写流量的杀毒软件)。
四、找到坏数据之后如何处理(Strategies for mitigating faulty measurements)¶
侦测只是第一步,接下来是处置。OONI 定了两条原则。第一,最终判定一笔测量是不是坏数据,要有人类审查介入,避免自动化把好数据误杀。第二,除非牵涉用户隐私,否则绝不回头修改已经送进来的数据。因为要有人类把关,处置只能在坏数据已经进入数据管线之后才做。可用的手段包括封锁行为异常的假名(pseudonym)、对投稿做限流、动态调整某地区某时段能接受的投稿量、或轮换签发密钥。这里的假名是匿名凭证系统给「同一个网络里的一台探针」的识别,同一网络内固定、跨网络无法被串连,也对应不到某个人的真实身分,第五节会说明它如何做到。文章也诚实点出两难:如果规定「只有半年以上的探针才能投稿」来挡 sybil 攻击(大量假身分灌数据),也会连带影响到正常新探针的投稿。
五、匿名凭证系统如何运作(Assessing the effectiveness of the solution)¶
匿名凭证系统是整篇的重点。先看「土法炼钢」的做法会踩到什么坑:给每个探针一个 ID、服务器端做白名单。问题是就算随机 ID,只要固定不变就足以辨识出单一探针,本身就是隐私灾难,而且探针换一个新 ID 就能绕过,变成打地鼠。如何在不长期保存个人数据的前提下,同时做到访问控制与信任评分,就成了这套系统要解决的核心矛盾。
这套机制用一个生活化的比喻就好懂。像酒吧门口只要你出示一张「证明我已成年」的证件,店员确认过关就好,不需要知道你叫什么、住哪里、生日是哪天。OONI 的凭证则用来证明另一组事情,这台探针的资历够老、投稿数量够多。
凭证由服务器签发,只存在探针本地、不存在服务器,也不会再次外传。它用密码学把探针的资历(age)与投稿数(msm_count)编码进去,而且只证明落在某个「区间」,例如「投稿超过 1000 笔」、「存在超过一周」,不透露精确值。用区间而非精确数字是刻意的设计,因为精确的投稿数几乎是独一无二的指纹,会反过来让探针被认出来,粗略的区间才不会泄漏身分。
投稿时,探针用凭证产生一段零知识证明(一种只证明某件事为真、但不透露细节的密码学方法),服务器只看到这段证明、看不到底下的真实数值,就能判断这笔测量符不符合访问规则,例如「这个国家、这个 ASN 的探针,要投稿满 1000 笔才收」。信任分数还会锁定在特定的国码与 ASN 组合,一台探针在某个网络累积的信誉,不能跨到另一个网络使用,这正是为了防止有人在低门槛网络先养好凭证、再拿去攻击别的网络。
具体走一遍会像这样:一台全新的探针一开始资历浅、投稿数低,很多严格规则都还进不去,只能先老实跑测量。每投一笔,服务器在验证通过后回一张更新过的凭证,把投稿数往上加一。日子久了、量累积够了,这台探针跨过「满一周」、「满 1000 笔」的门槛,之后送的测量就能被标成 verified。整个过程里,OONI 从头到尾没拿到这台探针的固定 ID,也没存下它的任何个人数据。
那有人会问,既然凭证只存在探针本地,拷贝一百份不就能假装成一百台各有信誉的探针?关键在前面说的网络内固定这个性质。同一个网络里,同一份凭证推导出来的假名是同一个,拷贝再多份,在同一个网络里仍然被看成同一台探针,不会变成一百个各自独立的可信身分。OONI 也很坦白,光靠凭证不能完全解决 sybil 攻击,彻底的防御要靠应用层的手段,例如限制新帐号注册速率、对每个区域的投稿量设上限。凭证的作用是提高攻击成本,逼对手先养出一批够老、送过够多测量的探针,没那么容易。
每笔测量最后会被标成 verified、unverified 或 failed 三种状态,数据用户可以自己决定要采信到什么程度。这套系统上线后,有些效果要长期观察才看得出来。OONI 会持续追踪 verified、unverified、failed 三类测量的比例变化,用来诊断是不是某次客户端更新让协定实作出现错误、或老探针没更新。他们也会统计各协定版本的探针数量,以及在服务器端跑一笔验证要花多少时间,及早抓出性能退化。
回到社区的角度,这套系统对 anoni.net 读者的价值不只在 OONI 自己。「如何在不保存个人数据的前提下做访问控制与信任评分」是很多系统都会遇到的难题,OONI 用区间揭露、凭证只存本地、放弃精准封锁来换取匿名性,这套取舍思路对关心隐私设计的人是很好的教材,也呼应我们社区个人隐私指引的主题。
小结:这份数据能不能放心用¶
OONI 的公开数据目前没有被大量恶意污染,看到的异常多半来自 VPN、时区设错、开发机器这类无心之过,可以放心继续用它来理解各地(包括你所在地区)的封锁状况。想更深入匿名凭证背后的密码学,OONI 另有两篇姊妹篇可以接着读:一篇谈这套系统的设计需求2,一篇宣布系统上线3。
原文十个大节回顾¶
看完全文,这张表把原文十个大节的重点与关键数字收在一起,方便日后回查或跳读。
| 原文大节 | 重点 | 关键数字或结论 |
|---|---|---|
| Existing metrics and heuristics|Approach | 用既有数据建立侦测基准 | 四个不牺牲隐私的检查角度 |
| IP geolocation mismatches | 探针回报位置对照真实 IP | 7.41% 对不上,多数是 VPN |
| Measurement volume anomalies | 单一探针投稿速率暴增 | 中国 ooniprobe-react-os 每秒 3 笔 |
| Timestamp inconsistencies | 测量时间戳前后兜不拢 | 0.82% 异常,委内瑞拉时区设错 |
| Probe OS, version metadata | 软件名称与平台互相矛盾 | 718 笔,含团队开发机 |
| New heuristics | 想再补上的高级侦测 | MCC/MNC、服务器端 GeoIP、TLS 指纹 |
| Mitigation strategies | 找到坏数据之后的处置 | 人类把关、不回改、限流、挡 sybil |
| Naive solution | 土法炼钢会踩的坑 | 固定 ID 就能去匿名,还会变打地鼠 |
| Anonymous credentials solution | 凭证式信任评分 | 区间揭露、只存本地、没有固定 ID |
| Future validation | 长期验证指针 | 追踪 verified/unverified/failed 比例 |
名词对照¶
原文用了不少 OONI 专有字段名词,这里整理一份对照,方便对照原文阅读。
| 名词 | 说明 |
|---|---|
| 启发式(heuristic) | 一组简单、成本低的判断规则,不追求完美,先把可疑的测量筛出来 |
| OONI Probe | OONI 的手机与桌面 app,会去连一份网站清单、回报每个网站在当地连不连得上 |
| probe(探针) | 运行测量的那台设备或那支程序 |
probe_cc |
探针回报的国码(country code) |
probe_asn |
探针回报的 ASN |
| ASN | 自治系统编号(Autonomous System Number),一段 IP 地址的管理单位,通常对应一家 ISP 或机构 |
msm_count |
该探针累积投稿的测量数(measurement count) |
| check-in 端点 | 探针开始测量前调用的 API,会回报自己的国码与 ASN |
web_connectivity |
OONI 最常见的测试,测某个网站在当地连不连得上 |
| ground truth | 当地实际的连接状况,拿来跟探针回报的数据对照的「真实答案」 |
| sybil 攻击 | 用大量假身分灌数据、扭曲观测结果的攻击 |
| pseudonym(假名) | 匿名凭证下代表「同区域、同 IP」一群探针的识别,不是个人身分 ID |
| verified、unverified、failed | 匿名凭证系统给每笔测量的三种信任标记 |