作者注:本文所提及的攻击无法针对当前的 I2P 版本实施。

作为一个自组织的点对点网络,I2P 依赖参与网络的 router(路由器)具备一种共享机制,用于共享网络上有哪些内容以及如何到达这些内容的信息。I2P router 借助 NetDB(网络数据库)实现这种信息共享,NetDB 是一种基于 Kademlia 的 DHT,但已经过修改以适用于 I2P。NetDB 需要共享两类主要的条目:“RouterInfos”,对等体将使用它来直接与其他 router 通信;以及“LeaseSets(租约集)”,其他对等体将使用它通过匿名的 tunnel(隧道)与 I2P 客户端通信。router 之间经常相互交换 NetDB 条目,可以向某个 router 或客户端发送信息,或者从某个 router 或客户端请求信息。这意味着这些条目可能直接或间接地、以匿名或非匿名的方式抵达,具体取决于网络的需要以及客户端的能力。然而,作为一个匿名化网络,确保以匿名方式发送的信息不可能被以非匿名方式请求回来也很重要。同时,以非匿名方式发送的信息也必须不可能被匿名地请求回。如果上述任一情况成为可能,则可能实施关联攻击,使攻击者能够判断客户端与 router 是否共享对 NetDB 的共同视图。如果能够可靠地确定这两个目标共享对 NetDB 的共同视图,那么它们很有可能位于同一个 router 上,从而大幅削弱目标的匿名性。由于匿名化网络寥寥无几,而且 I2P 是唯一一个通过 DHT 的运作来共享路由表的网络,这类攻击几乎是 I2P 所独有的,解决这一问题对 I2P 的成功至关重要。

考虑以下场景:有一个 I2P router(路由器)托管着一个 I2P 客户端。该 router 发布了一个 RouterInfo(路由信息),而 I2P 客户端发布它的 LeaseSet(租约集)。由于它们都发布在 NetDB(网络数据库)中,其他 I2P routers 可以查询 NetDB 以了解如何与它们通信。这对于 I2P 所实现的这种类型的覆盖网络来说是正常且必不可少的。攻击者运行一个 I2P router,并在 NetDB 中查询目标 RouterInfo 和目标 LeaseSet。随后它构造一个新的 LeaseSet,该 LeaseSet 唯一,甚至可能是伪造的,并通过一个 tunnel(隧道)发送到其打算攻击的客户端对应的 LeaseSet。客户端处理该构造的 LeaseSet,并将其添加到自己的 NetDB 中。随后,攻击者使用其从 NetDB 获得的 RouterInfo,直接从该 router 请求取回其构造的 LeaseSet。如果收到该构造的 LeaseSet 作为回复,则攻击者可以断定目标客户端与目标 router 对 NetDB 的视图是一致的。

这是一个 NetDB 去匿名化攻击类别的简单示例,它依赖于先使用一个身份向他人的 NetDB 添加一条记录,然后再用另一个身份将其取回。在这种情况下,所涉及的身份是“router”和“客户端”身份。然而,在某些设计中,危害较小的客户端与客户端关联也有可能发生。针对这类攻击进行防御设计,需要为 router 提供一种能力,以便判断与一个潜在身份交换一条信息是否安全。

那么我们应该如何看待这个问题呢?我们在这里真正要处理的,其实是网络上不同“身份”的linkability(可关联性)。之所以会产生将它们关联起来的可能性,是因为所有这些身份共享一个共同的数据结构,这个数据结构会“记住”它与谁通信过,以及谁与它通信过。它还会“记住”这些通信是如何发生的。

不妨暂时把自己设想为攻击者。设想你正试图查明一位易容大师的真实身份。你确信自己见过他的真容,也确信你经常与他的某个伪装身份进行沟通。你会如何证明这个伪装身份与真实身份属于同一个人?我可能会把一个秘密告诉以伪装身份出现的那个人。如果那位未伪装的人随后借助这条秘密信息作出回应,那么我就可以判定未伪装的人知道这个秘密。在假定伪装中的那个人没有把这个秘密告知任何他人的前提下,我就可以推断未伪装的人与伪装中的人事实上是同一个人。无论这位易容大师戴上多少副面具,他终究只有一个头脑。

为了成功保护 I2P 客户端的身份,I2P 需要在伪装方面做得比上文所描述的“伪装大师”更好。它需要能够“remember”若干关于其如何参与 NetDB 的重要信息,并根据这些细节做出恰当的响应。它必须能够回忆起:

  • Whether a NetDB Entry was received directly, or received down a client tunnel
  • Whether a NetDB Entry was sent by a peer in response to our lookup, or sent unsolicited
  • Which NetDB Entry was received down Which client Tunnel
  • Multiple versions of the same entry for different client tunnels

从结构上看,处理这种模式最易理解且最可靠的方法是使用"Sub-DBs"(子数据库)。Sub-DB 是缩小版的 NetDB(网络数据库),用于帮助 NetDB 组织条目而不丢失跟踪。每个客户端都会获得一个供其自身使用的 Sub-DB,而 router 本身拥有一个功能完备的 NetDB。通过使用 Sub-DB,我们为这位“乔装大师”准备了一本按是谁与它分享这些秘密而分类的秘密索引。当请求发送给某个客户端时,它只会查找已经与该客户端通信过的条目;而当请求发送给某个 router 时,则只使用该 router 范围的 NetDB。通过这种方式,我们不仅解决了该攻击最简单的形式,还削弱了整个攻击类别的效力。