此翻译是使用机器学习生成的,可能不是100%准确。 查看英文版本

I2P:技术介绍

I2P架构和运行的技术介绍

注意:本文档最初由jrandom于2003年编写。虽然我们努力保持其时效性,但部分信息可能已过时或不完整。传输和加密部分的内容截至2025年1月是最新的。

简介

I2P是一个可扩展、自组织、弹性的分组交换匿名网络层,在此基础上可以运行任意数量的不同匿名或安全意识应用程序。这些应用程序中的每一个都可以在不担心自由路由混合网络正确实现的情况下,做出自己的匿名性、延迟和吞吐量权衡,使它们能够将自己的活动与已经在I2P上运行的更大匿名用户集合混合在一起。

现有的应用程序已经提供了典型互联网活动的全部范围——匿名网页浏览、网站托管、聊天、文件共享、电子邮件、博客和内容聚合,以及其他几个正在开发中的应用程序。

  • 网页浏览:使用任何支持代理的现有浏览器。
  • 聊天:IRC 和其他协议
  • 文件共享:I2PSnark 和其他应用程序
  • 电子邮件:susimail 和其他应用程序
  • 博客:使用任何本地 web 服务器,或可用的插件

与托管在内容分发网络(如 FreenetGNUnet )中的网站不同,I2P 上托管的服务是完全交互式的——有传统的网络风格搜索引擎、公告板、可以评论的博客、数据库驱动的网站,以及无需本地安装即可查询静态系统(如 Freenet)的桥接服务。

有了所有这些启用匿名功能的应用程序,I2P承担了面向消息中间件的角色——应用程序表示它们想要向加密标识符(“destination”)发送一些数据,I2P负责确保数据安全且匿名地到达目的地。I2P还捆绑了一个简单的 库,允许I2P的匿名尽力而为消息以可靠、有序的流传输,透明地提供针对网络高带宽延迟积调优的基于TCP的拥塞控制算法。虽然已有几个简单的SOCKS代理可用于将现有应用程序接入网络,但它们的价值有限,因为几乎每个应用程序都会例行性地暴露在匿名环境中属于敏感信息的内容。唯一安全的方式是全面审核应用程序以确保正确运行,为了协助完成这项工作,我们提供了各种语言的一系列API,可用于充分利用网络。

I2P不是一个研究项目——无论是学术、商业还是政府项目——而是一个工程努力,旨在做任何必要的事情来为那些需要匿名的人提供足够的匿名级别。自2003年初以来,它一直在积极开发中,拥有一名全职开发者和来自世界各地的专门兼职贡献者团队。I2P上完成的所有工作都是开源的,可在网站 上免费获取,大部分代码直接发布到公有领域,但使用了一些BSD风格许可证下的加密例程。从事I2P工作的人员不控制人们发布客户端应用程序的许可证,现有几个GPL许可的应用程序(I2PTunnelsusimailI2PSnark 、I2P-Bote、I2Phex等)。I2P的资金完全来自捐赠,目前在任何司法管辖区都没有获得税收减免,因为许多开发者本身就是匿名的。


操作

概述

要理解I2P的运作方式,了解几个关键概念至关重要。首先,I2P严格区分参与网络的软件(一个"router")和与各个应用程序关联的匿名端点(“destinations”)。某人正在运行I2P通常不是秘密。隐藏的是用户在做什么(如果有的话)的信息,以及特定destination连接到哪个router。终端用户通常在其router上会有几个本地destinations——例如,一个代理到IRC服务器,另一个支持用户的匿名网络服务器(“I2P Site”),另一个用于I2Phex实例,另一个用于torrents等。

另一个需要理解的关键概念是"tunnel"。tunnel 是通过明确选择的 router 列表的定向路径。使用分层加密,因此每个 router 只能解密单个层级。解密信息包含下一个 router 的 IP,以及要转发的加密信息。每个 tunnel 都有一个起点(第一个 router,也称为"gateway")和一个终点。消息只能单向发送。要回发消息,需要另一个 tunnel。

Inbound and outbound tunnel schematic
图1:存在两种类型的tunnel:inbound和outbound。

存在两种类型的 tunnel:“outbound” tunnel 将消息从 tunnel 创建者发送出去,而 “inbound” tunnel 将消息带给 tunnel 创建者。结合这两种 tunnel 允许用户相互发送消息。发送者(上图中的"Alice")建立一个 outbound tunnel,而接收者(上图中的"Bob")创建一个 inbound tunnel。inbound tunnel 的网关可以接收来自任何其他用户的消息,并将它们发送直到端点(“Bob”)。outbound tunnel 的端点需要将消息发送到 inbound tunnel 的网关。为此,发送者(“Alice”)在她的加密消息中添加指令。一旦 outbound tunnel 的端点解密消息,它将获得将消息转发到正确的 inbound 网关(通往"Bob"的网关)的指令。

需要理解的第三个关键概念是I2P的**“network database”(或"netDb")——一对用于共享网络元数据的算法。承载的两种元数据类型是“routerInfo”“leaseSet”**——routerInfo为router提供联系特定router所需的数据(它们的公钥、传输地址等),而leaseSet为router提供联系特定目标所需的信息。一个leaseSet包含多个"leases"。每个lease都指定一个tunnel网关,允许到达特定目标。lease中包含的完整信息:

  • tunnel 的入站网关,允许到达特定目的地。
  • tunnel 过期的时间。
  • 一对公钥,用于加密消息(通过 tunnel 发送并到达目的地)。

Router 自身直接将其 routerInfo 发送到 netDb,而 leaseSet 则通过出站 tunnel 发送(leaseSet 需要匿名发送,以避免将 router 与其 leaseSet 关联起来)。

我们可以结合上述概念在网络中建立成功的连接。

为了建立自己的入站和出站 tunnel,Alice 在 netDb 中进行查找以收集 routerInfo。通过这种方式,她收集了可以作为 tunnel 中跳点的对等节点列表。然后她可以向第一个跳点发送构建消息,请求构建 tunnel 并要求该 router 将构建消息继续转发,直到 tunnel 构建完成。

请求其他 router 的信息

Build tunnel using router information
图2:Router信息用于构建tunnel。

当Alice想要向Bob发送消息时,她首先在netDb中查找Bob的leaseSet,以获得他当前的入站tunnel网关。然后她选择自己的一条出站tunnel,并将消息发送到其中,同时指示出站tunnel的端点将消息转发到Bob的其中一个入站tunnel网关。当出站tunnel端点接收到这些指令时,它会按要求转发消息,当Bob的入站tunnel网关接收到消息时,消息会沿着tunnel转发到Bob的router。如果Alice希望Bob能够回复消息,她需要将自己的destination明确地作为消息本身的一部分进行传输。这可以通过引入更高层级的层来实现,这在streaming 库中完成。Alice也可以通过将她最新的LeaseSet与消息捆绑在一起来缩短响应时间,这样Bob在回复时就不需要进行netDb查找,但这是可选的。

使用 LeaseSets 连接隧道
图 3:LeaseSets 用于连接出站和入站隧道。

虽然tunnel本身具有分层加密来防止网络内部对等节点的未授权披露(正如传输层本身防止网络外部对等节点的未授权披露一样),但仍有必要添加额外的端到端加密层,以对出站tunnel端点和入站tunnel网关隐藏消息。这种"garlic encryption “让Alice的router将多个消息包装成单个"garlic消息”,加密到特定的公钥,使得中介对等节点无法确定garlic中有多少消息、这些消息说了什么,或者这些单独的clove的目的地在哪里。对于Alice和Bob之间的典型端到端通信,garlic将被加密到Bob的leaseSet中发布的公钥,允许在不泄露Bob自己router公钥的情况下对消息进行加密。

另一个需要记住的重要事实是,I2P完全基于消息传输,某些消息可能会在传输过程中丢失。使用I2P的应用程序可以使用面向消息的接口并处理自己的拥塞控制和可靠性需求,但大多数应用程序最好重用提供的streaming 库,将I2P视为基于流的网络。


Tunnels

入站和出站tunnel的工作原理类似。tunnel gateway累积多个tunnel消息,最终将它们预处理为适合tunnel传输的格式。接下来,gateway加密预处理后的数据并将其转发到第一跳。该节点和后续tunnel参与者在验证消息不是重复消息后,会添加一层加密,然后将其转发到下一个节点。最终,消息到达端点,在那里消息被重新分离并按请求转发。区别在于tunnel创建者的行为——对于入站tunnel,创建者是端点,他们只需解密所有添加的层级;而对于出站tunnel,创建者是gateway,他们预先解密所有层级,这样在添加所有逐跳加密层级后,消息在tunnel端点以明文形式到达。

选择特定节点来传递消息以及它们的特定顺序对于理解I2P的匿名性和性能特征都很重要。虽然netDb(见下文)有自己的标准来选择要查询的节点以及存储条目的节点,但tunnel创建者可以在单个tunnel中以任何顺序(甚至任意次数)使用网络中的任何节点。如果完美的延迟和容量数据在全球范围内已知,那么选择和排序将由客户端的特定需求结合其威胁模型来驱动。不幸的是,匿名收集延迟和容量数据并非易事,而且依赖不可信的节点来提供此信息会带来严重的匿名性影响。

从匿名性角度来看,最简单的技术是从整个网络中随机选择 peers,随机排序它们,并永远按该顺序使用这些 peers。从性能角度来看,最简单的技术是选择具有必要空闲容量的最快 peers,将负载分散到不同的 peers 上以处理透明故障转移,并在容量信息发生变化时重建 tunnel。虽然前者既脆弱又低效,后者需要无法获取的信息且匿名性不足。I2P 正在努力提供一系列 peer 选择策略,结合匿名性感知的测量代码,根据 peers 的配置文件来组织它们。

作为基础,I2P 通过测量与其交互的对等节点的间接行为来持续分析这些节点——例如,当一个对等节点在1.3秒内响应 netDb 查询时,该往返延迟会被记录到所有参与两个 tunnel(入站和出站)的 router 的配置文件中,请求和响应通过这些 tunnel 传递,同时也记录到被查询对等节点的配置文件中。直接测量(如传输层延迟或拥塞)不作为配置文件的一部分使用,因为这些可以被操纵并与测量 router 关联,使其面临简单的攻击。在收集这些配置文件的过程中,对每个配置文件运行一系列计算来总结其性能——延迟、处理大量活动的能力、当前是否过载,以及它们与网络的集成程度。然后将这些计算结果与活跃对等节点进行比较,将 router 组织成四个层级——快速且高容量、高容量、未故障和故障。这些层级的阈值是动态确定的,虽然目前使用的是相当简单的算法,但存在其他替代方案。

使用这些概要文件数据,最简单合理的节点选择策略是从顶层(快速且高容量)随机选择节点,这目前已部署在客户端隧道中。探索隧道(用于 netDb 和隧道管理)从"未失效"层随机选择节点(也包括"更好"层中的 router),允许节点更广泛地采样 router,实际上是通过随机化的爬山算法 优化节点选择。然而,仅这些策略确实会通过前驱节点和 netDb 收集攻击泄露有关 router 顶层节点的信息。因此,存在几种替代方案,虽然负载均衡不够均匀,但能够应对特定类别攻击者发起的攻击。

通过选择一个随机密钥并根据对等节点与该密钥的异或距离对其进行排序,可以根据对等节点的故障率和层级的流失率来减少前驱攻击和收集攻击中泄露的信息。另一个处理 netDb 收集攻击的简单策略是固定入站 tunnel 网关,同时随机化 tunnel 中更深层的对等节点。为了应对客户端联系的对手发起的前驱攻击,出站 tunnel 端点也需要保持固定。选择在最暴露点固定哪个对等节点当然需要对持续时间有所限制,因为所有对等节点最终都会失效,所以可以采用被动调整或主动避免的方式来模拟其他 router 的平均故障间隔时间。这两种策略可以结合使用,使用固定的暴露对等节点和基于异或的 tunnel 内部排序。更严格的策略是固定潜在 tunnel 的确切对等节点和排序,只有在所有节点同意每次都以相同方式参与时才使用单个对等节点。这与基于异或的排序不同,前驱攻击中每个对等节点的前驱和后继始终相同,而异或排序只确保它们的顺序不会改变。

如前所述,I2P 目前(版本 0.8)包含了上述分层随机策略,使用基于 XOR 的排序。有关 tunnel 操作、管理和节点选择机制的更详细讨论,可以在 tunnel 规范 中找到。


Network Database (netDb,网络数据库)

如前所述,I2P的netDb用于共享网络的元数据。这在网络数据库 页面中有详细说明,但下面提供了基本解释。

所有I2P router都包含本地netDb,但并非所有router都参与DHT或响应leaseSet查找。那些参与DHT并响应leaseSet查找的router被称为"floodfill"。Router可以手动配置为floodfill,或者如果它们有足够的容量并满足可靠运行的其他条件,就会自动成为floodfill。

其他 I2P router 会通过向 floodfill 发送简单的 ‘store’ 和 ’lookup’ 查询来存储和查找数据。如果 floodfill router 收到 ‘store’ 查询,它会使用 Kademlia 算法 将信息传播到其他 floodfill router。’lookup’ 查询目前的工作方式有所不同,以避免一个重要的安全问题。当执行查找时,floodfill router 不会将查找转发给其他节点,而是总是自己回答(如果它有请求的数据)。

网络数据库中存储了两种类型的信息。

  • RouterInfo 存储特定 I2P router 的信息以及如何联系它
  • LeaseSet 存储特定目标的信息(例如 I2P 网站、电子邮件服务器…)

所有这些信息都由发布方签名,并由使用或存储该信息的任何 I2P router 进行验证。此外,数据包含时间信息,以避免存储旧条目和可能的攻击。这也是为什么 I2P 捆绑了维护正确时间所需的代码,偶尔查询一些 SNTP 服务器(默认为 pool.ntp.org 轮询)并在传输层检测 router 之间的时钟偏差。

一些额外的备注也很重要。

  • 未发布和加密的 leaseSet: 有时只希望特定的人能够访问某个目标。这可以通过不在 netDb 中发布目标来实现。但是,您需要通过其他方式传输目标信息。这由"加密 leaseSet"支持。这些 leaseSet 只能由拥有解密密钥的人解码。

  • 引导过程: 引导 netDb 相当简单。一旦 router 成功接收到一个可达对等节点的 routerInfo,它就可以向该 router 查询网络中其他 router 的引用。目前,一些用户将他们的 routerInfo 文件发布到网站上以提供这些信息。I2P 会自动连接到其中一个网站来收集 routerInfo 文件并进行引导。I2P 将这个引导过程称为"reseeding"。

  • 查找可扩展性: I2P 网络中的查找是迭代式的,而非递归式的。如果从某个 floodfill 的查找失败,查找将重复向下一个最近的 floodfill 进行。floodfill 不会递归地向另一个 floodfill 请求数据。迭代式查找可以扩展到大型 DHT 网络。


传输协议

router 之间的通信需要在防范外部对手的同时提供保密性和完整性,并验证所联系的 router 确实是应该接收特定消息的那个 router。router 之间具体如何通信并不关键——在不同时期已经使用了三种不同的协议来提供这些基本需求。

I2P目前支持两种传输协议:基于TCP的NTCP2 和基于UDP的SSU2 。这些协议已取代了之前版本的协议NTCPSSU ,后者现已被弃用。两种协议都支持IPv4和IPv6。通过同时支持TCP和UDP传输,I2P能够有效穿越大多数防火墙,包括那些旨在阻止限制性审查制度下流量的防火墙。NTCP2和SSU2被设计为使用现代加密标准,提高流量识别抗性,增强效率和安全性,并使NAT穿越更加稳定。router在netDb中发布每个支持的传输和IP地址。能够访问公共IPv4和IPv6网络的router通常会发布四个地址,对应NTCP2/SSU2与IPv4/IPv6的每个组合。

SSU2 支持并扩展了 SSU 的目标。SSU2 与其他现代基于 UDP 的协议(如 Wireguard 和 QUIC)有很多相似之处。除了通过 UDP 可靠传输网络消息外,SSU2 还为点对点、协作式 IP 地址检测、防火墙检测和 NAT 穿透提供了专门的功能。如 SSU 规范 中所述:

此协议的目标是提供安全、经过身份验证、半可靠和无序的消息传递,仅向第三方暴露最少量的易识别数据。它应支持高度通信以及TCP友好的拥塞控制,并可能包括PMTU检测。它应能够以足够满足家庭用户需求的速率高效传输大量数据。此外,它应支持应对网络障碍的技术,如大多数NAT或防火墙。

NTCP2 支持并扩展了 NTCP 的目标。它使用现代加密标准,通过 TCP 提供高效且完全加密的网络消息传输,并具备抵御流量识别的能力。

I2P 同时支持多种传输协议。通过"投标"来选择出站连接的特定传输协议。每种传输协议都会为连接进行投标,这些投标的相对值决定了优先级。传输协议可能会根据是否已经与对等节点建立了连接而给出不同的投标。

bid(优先级)值取决于具体实现,可能会根据流量条件、连接数量和其他因素而变化。router 还会在网络数据库中发布其对入站连接的传输偏好,以每个传输和地址的传输"成本"形式表示。


密码学

I2P在多个协议层使用密码学进行加密、身份验证和验证。主要的协议层包括:传输层、tunnel构建消息、tunnel层加密、网络数据库消息和端到端(garlic)消息。I2P的原始设计使用了一小套在当时被认为是安全的密码学原语。这些包括ElGamal非对称加密、DSA-SHA1签名、AES256/CBC对称加密和SHA-256哈希。随着可用计算能力的增加和密码学研究在多年来的大幅发展,I2P需要升级其原语和协议。因此,我们添加了"加密类型"和"签名类型"的概念,并扩展了我们的协议以包含这些标识符并指示支持。这使我们能够定期更新和扩展网络对现代密码学的支持,并为网络的新原语提供未来保障,而不会破坏向后兼容性或需要网络更新的"统一升级日"。一些签名和加密类型也保留用于实验性使用。

目前在大多数协议层中使用的加密原语包括 X25519 密钥交换、EdDSA 签名、ChaCha20/Poly1305 认证对称加密,以及 SHA-256 哈希。AES256 仍用于 tunnel 层加密。这些现代协议用于绝大多数网络通信。包括 ElGamal、ECDSA 和 DSA-SHA1 在内的较旧原语在与旧版 router 通信时,仍被大多数实现支持以保持向后兼容性。一些旧协议已被弃用和/或完全移除。在不久的将来,我们将开始研究向后量子 (PQ) 或混合 PQ 加密和签名的迁移,以维护我们强大的安全标准。

这些密码学基元组合在一起,为I2P提供了针对各种对手的分层防护。在最底层,router间通信受到传输层安全的保护。通过传输层传递的tunnel 消息有自己的分层加密。各种其他消息在"garlic消息"内传递,这些消息也是加密的。

Garlic Messages

Garlic 消息是"洋葱"分层加密的扩展,允许单个消息的内容包含多个"瓣"——完整形式的消息以及它们各自的传递指令。当消息本应以明文形式通过不应访问该信息的对等节点时,消息就会被包装成 garlic 消息——例如,当一个 router 想要请求另一个 router 参与 tunnel 时,它们会将请求包装在 garlic 内,使用接收 router 的公钥加密该 garlic,并通过 tunnel 转发。另一个例子是当客户端想要向目标发送消息时——发送方的 router 会将该数据消息(连同其他一些消息)包装成 garlic,使用接收方 leaseSet 中发布的公钥加密该 garlic,并通过适当的 tunnel 转发。

加密层内每个瓣片附带的"指令"包括请求该瓣片在本地转发、转发到远程router或远程router上的远程tunnel的能力。这些指令中有字段允许对等节点请求延迟传递直到满足特定时间或条件,但在部署非平凡延迟 之前不会被执行。可以明确地路由garlic消息任意跳数而无需构建tunnel,甚至可以通过将tunnel消息包装在garlic消息中并在传递到tunnel中下一跳之前转发若干跳来重新路由tunnel消息,但这些技术目前在现有实现中未被使用。

会话标签

作为一个不可靠、无序、基于消息的系统,I2P 使用非对称和对称加密算法的简单组合来为 garlic 消息提供数据机密性和完整性。原始组合被称为 ElGamal/AES+SessionTags,但这是一种过于冗长的方式来描述简单使用 2048 位 ElGamal、AES256、SHA256 和 32 字节随机数的方法。虽然这个协议仍然受支持,但网络的大部分已经迁移到新协议 ECIES-X25519-AEAD-Ratchet。这个协议结合了 X25519、ChaCha20/Poly1305 和同步 PRNG 来生成 32 字节随机数。下面将简要描述这两个协议。

ElGamal/AES+SessionTags

当 router 第一次想要向另一个 router 加密 garlic 消息时,它们使用 ElGamal 加密 AES256 会话密钥的密钥材料,并在该加密的 ElGamal 块之后附加 AES256/CBC 加密的载荷。除了加密的载荷外,AES 加密部分还包含载荷长度、未加密载荷的 SHA256 哈希,以及一些"会话标签"——随机的 32 字节 nonce。下次发送方想要向另一个 router 加密 garlic 消息时,它们不会使用 ElGamal 加密新的会话密钥,而是简单地选择之前交付的会话标签之一,像之前一样使用 AES 加密载荷,使用与该会话标签一起使用的会话密钥,并在前面添加会话标签本身。当 router 接收到 garlic 加密消息时,它们检查前 32 字节是否匹配可用的会话标签——如果匹配,它们简单地进行 AES 解密消息,但如果不匹配,它们则对第一个块进行 ElGamal 解密。

每个会话标签只能使用一次,以防止内部攻击者不必要地将不同消息关联为同一路由器之间的通信。ElGamal/AES+SessionTag加密消息的发送方选择何时以及交付多少标签,为接收方预先储备足够的标签来处理一轮消息。Garlic消息可以通过将一个小的附加消息作为分片(“交付状态消息”)来检测成功的标签交付——当garlic消息到达预期接收方并成功解密时,这个小的交付状态消息是暴露的分片之一,并包含指令让接收方将该分片发送回原始发送方(当然是通过入站tunnel)。当原始发送方收到这个交付状态消息时,他们知道在garlic消息中打包的会话标签已成功交付。

Session tags 本身具有非常短的生存期,如果不使用就会被丢弃。此外,每个密钥存储的数量是有限的,密钥本身的数量也是如此——如果到达的太多,新消息或旧消息都可能被丢弃。发送方会跟踪使用 session tags 的消息是否成功传递,如果通信不充分,它可能会丢弃之前假定已正确传递的消息,回退到完整的昂贵 ElGamal 加密。

ECIES-X25519-AEAD-Ratchet

ElGamal/AES+SessionTags在多个方面需要大量开销。CPU使用率很高,因为ElGamal相当慢。带宽消耗过大,因为必须提前传送大量session tags,而且ElGamal公钥非常大。由于需要存储大量session tags,内存使用率很高。可靠性受到session tag传送丢失的影响。

ECIES-X25519-AEAD-Ratchet 被设计用来解决这些问题。X25519 用于密钥交换。ChaCha20/Poly1305 用于认证对称加密。加密密钥采用"双棘轮"机制或定期轮换。会话标签从 32 字节减少到 8 字节,并通过伪随机数生成器生成。该协议与 Signal 和 WhatsApp 中使用的 signal 协议有许多相似之处。这个协议在 CPU、内存和带宽方面大幅降低了开销。

会话标签由运行在会话两端的确定性同步PRNG生成,用于生成会话标签和会话密钥。该PRNG是一个使用SHA-256 HMAC的HKDF,并从X25519 DH结果中获取种子。会话标签永远不会提前传输;它们只与消息一起包含。接收方存储有限数量的会话密钥,按会话标签索引。发送方不需要存储任何会话标签或密钥,因为它们不会提前发送;可以按需生成。通过在发送方和接收方之间保持这个PRNG大致同步(接收方预计算下一个例如50个标签的窗口),消除了定期捆绑大量标签的开销。


未来

I2P的协议在大多数平台上都很高效,包括手机,并且对于大多数威胁模型来说都很安全。然而,有几个领域需要进一步改进,以满足面临强大国家赞助对手的用户需求,并应对持续的密码学进步和不断增长的计算能力威胁。jrandom在2003年提出了两个可能的功能:受限路由和可变延迟。虽然我们不再计划实现这些功能,但下面将对它们进行描述。

受限路由操作

I2P是一个覆盖网络,设计为运行在功能性分组交换网络之上,利用端到端原则来提供匿名性和安全性。虽然互联网由于NAT的使用不再完全采用端到端原则,但I2P确实需要网络的很大一部分是可达的——边缘可能有一些使用受限路由运行的peer节点,但I2P不包含适用于大多数peer节点不可达这种退化情况的合适路由算法。不过,它可以在采用此类算法的网络之上运行。

限制路由操作,即对可直接到达的对等节点存在限制,根据限制路由的处理方式不同,会产生几种不同的功能性和匿名性影响。在最基本的层面上,当对等节点位于不允许入站连接的NAT或防火墙后面时,就会存在限制路由。通过将分布式打洞技术集成到传输层中,这个问题在很大程度上得到了解决,使得位于大多数NAT和防火墙后面的用户无需任何配置就能接收主动连接。然而,这并不能限制对等节点IP地址在网络内部router的暴露,因为它们可以简单地通过已发布的introducer与该对等节点建立连接。

除了受限路由的功能处理之外,还有两个级别的受限操作可以用来限制IP地址的暴露——使用router特定的tunnel进行通信,以及提供"客户端router"。对于前者,router可以构建新的tunnel池或重用其探索性池,将其中一些tunnel的入站网关作为其routerInfo的一部分发布,以替代其传输地址。当对等节点想要与它们联系时,它们会在netDb中看到这些tunnel网关,并简单地通过其中一个已发布的tunnel向它们发送相关消息。如果受限路由后面的对等节点想要回复,它可以直接回复(如果它们愿意向对等节点暴露其IP)或通过其出站tunnel间接回复。当与对等节点有直接连接的router想要到达它时(例如转发tunnel消息),它们只需优先使用直接连接而不是已发布的tunnel网关。“客户端router"的概念简单地扩展了受限路由,不发布任何router地址。这样的router甚至不需要在netDb中发布其routerInfo,仅需向其联系的对等节点提供其自签名的routerInfo(这是传递router公钥所必需的)。

对于那些位于受限路由后的用户来说,存在一些权衡考虑,因为他们可能不太频繁地参与其他人的 tunnel,而且他们所连接的 router 能够推断出原本不会暴露的流量模式。另一方面,如果这种暴露的成本低于获得可用 IP 地址的成本,那么这可能是值得的。当然,这假设受限路由后的 router 所联系的对等节点不是恶意的——要么网络足够大,使用恶意对等节点进行连接的概率足够小,要么使用可信的(可能是临时的)对等节点。

受限路由非常复杂,总体目标已基本被放弃。几个相关的改进大大减少了对它们的需求。我们现在支持UPnP来自动打开防火墙端口。我们支持IPv4和IPv6。SSU2改进了地址检测、防火墙状态确定和协作式NAT打洞。SSU2、NTCP2和地址兼容性检查确保tunnel跳跃点在tunnel构建之前能够连接。GeoIP和国家识别使我们能够避开具有限制性防火墙的国家的对等节点。对这些防火墙后面"隐藏"router的支持已经得到改善。一些实现还支持连接到覆盖网络(如Yggdrasil)上的对等节点。

可变延迟

尽管 I2P 最初的主要工作集中在低延迟通信上,但它从一开始就考虑到了可变延迟服务的设计。在最基本的层面上,运行在 I2P 之上的应用程序可以提供中等和高延迟通信的匿名性,同时仍然将其流量模式与低延迟流量混合。但在内部,I2P 可以通过 garlic encryption 提供自己的中等和高延迟通信——指定消息应该在特定延迟后发送、在特定时间发送、在一定数量的消息通过后发送,或采用其他混合策略。通过分层加密,只有暴露延迟请求的 clove 的 router 才会知道该消息需要高延迟,这允许流量进一步与低延迟流量混合。一旦满足传输前提条件,持有该 clove(它本身很可能是一个 garlic 消息)的 router 就会按要求简单地转发它——转发到一个 router、一个 tunnel,或者最有可能的是转发到一个远程客户端目标。

可变延迟服务的目标需要大量资源来支持存储转发机制。这些机制可以并且已经在各种消息应用程序中得到支持,例如 i2p-bote。在网络层面,像 Freenet 这样的替代网络提供这些服务。我们已经决定不在 I2P router 层面追求这个目标。


相似系统

I2P的架构建立在面向消息的中间件概念、DHT拓扑结构、自由路由混合网络的匿名性和密码学,以及分组交换网络的适应性基础之上。其价值并非来自新颖的概念或算法,而是来自将现有系统和论文的研究成果进行精心工程化组合。虽然有几个值得在技术和功能方面进行比较的类似项目,但这里特别提出两个——Tor和Freenet。

另请参阅网络对比页面 。请注意,这些描述由 jrandom 在 2003 年撰写,可能不再准确。

Tor

网站

乍一看,Tor 和 I2P 在功能和匿名性方面有许多相似之处。虽然 I2P 的开发始于我们了解 Tor 早期阶段工作之前,但原始 onion routing 和 ZKS 项目的许多经验教训都被整合到了 I2P 的设计中。I2P 并没有构建一个本质上可信的、具有目录服务器的中心化系统,而是拥有一个自组织的网络数据库,每个节点都承担着分析其他 router 的责任,以确定如何最好地利用可用资源。另一个关键区别是,虽然 I2P 和 Tor 都使用分层有序路径(tunnel 和电路/流),但 I2P 从根本上是一个分组交换网络,而 Tor 从根本上是一个电路交换网络,这使得 I2P 能够透明地绕过拥塞或其他网络故障,操作冗余路径,并在可用资源之间进行负载均衡。虽然 Tor 通过提供集成的出口代理发现和选择功能来提供有用的出口代理功能,但 I2P 将这些应用层决策留给运行在 I2P 之上的应用程序——实际上,I2P 甚至将类似 TCP 的流媒体库本身外化到应用层,允许开发人员尝试不同的策略,利用他们的特定领域知识来提供更好的性能。

从匿名性角度来看,当比较核心网络时存在很多相似之处。然而,有几个关键差异。在处理内部对手或大多数外部对手时,I2P的单工tunnel仅通过查看流量本身就比Tor的双工circuit暴露一半的流量数据——HTTP请求和响应在Tor中会遵循相同路径,而在I2P中,构成请求的数据包会通过一个或多个出站tunnel发出,构成响应的数据包会通过一个或多个不同的入站tunnel返回。虽然I2P的节点选择和排序策略应该能充分解决前驱攻击问题,但如果需要切换到双向tunnel,我们可以简单地沿着相同的router构建入站和出站tunnel。

Tor使用望远镜式tunnel创建方式带来了另一个匿名性问题,因为当电路中的数据单元通过对手节点时,简单的数据包计数和时序测量会暴露关于对手在电路中位置的统计信息。I2P的单向tunnel创建使用单个消息,因此不会暴露这些数据。保护tunnel中的位置很重要,否则对手将能够发起一系列强大的前驱攻击、交集攻击和流量确认攻击。

总的来说,Tor 和 I2P 在关注重点上互为补充——Tor 致力于提供高速匿名的互联网出口代理,而 I2P 则致力于提供一个去中心化的弹性网络本身。理论上,两者都可以用来实现这两个目的,但考虑到有限的开发资源,它们各有优缺点。I2P 开发者已经考虑过修改 Tor 以利用 I2P 设计的必要步骤,但对 Tor 在资源稀缺情况下可行性的担忧表明,I2P 的包交换架构将能够更有效地利用稀缺资源。

Freenet

网站

Freenet 在 I2P 设计的初期阶段发挥了重要作用——证明了完全包含在网络内部的充满活力的匿名社区的可行性,展示了可以避免出口代理固有的危险。I2P 的最初种子始于作为 Freenet 通信层的替代品,试图将可扩展、匿名和安全的点对点通信的复杂性从抗审查分布式数据存储的复杂性中分离出来。然而随着时间推移,Freenet 算法中固有的一些匿名性和可扩展性问题表明,I2P 的重点应该严格专注于提供通用的匿名通信层,而不是作为 Freenet 的组件。多年来,Freenet 开发者已经认识到旧设计中的弱点,促使他们建议需要一个"预混合"层来提供实质性的匿名性。换句话说,Freenet 需要运行在像 I2P 或 Tor 这样的混合网络之上,“客户端节点"通过混合网络向"服务器节点"请求和发布数据,然后服务器节点根据 Freenet 的启发式分布式数据存储算法获取和存储数据。

Freenet的功能与I2P非常互补,因为Freenet原生提供了许多用于操作中高延迟系统的工具,而I2P原生提供了适合提供足够匿名性的低延迟混合网络。从工程、匿名性、安全性和资源分配的角度来看,将混合网络与抗审查分布式数据存储分离的逻辑仍然是不言而喻的,因此希望Freenet团队能够朝着这个方向努力,如果不是简单地重用(或根据需要帮助改进)现有的混合网络如I2P或Tor的话。


附录 A:应用层

I2P本身并不做太多事情——它只是将消息发送到远程目标并接收针对本地目标的消息——大部分有趣的工作都在其上层进行。从本质上看,I2P可以被视为一个匿名且安全的IP层,而捆绑的streaming library 则是在其之上实现的匿名且安全的TCP层。除此之外,I2PTunnel 提供了一个通用的TCP代理系统,用于进入或离开I2P网络,同时各种网络应用程序为最终用户提供了更多功能。

流媒体库

I2P streaming library 可以被视为一个通用的流式接口(类似于 TCP socket),该实现支持滑动窗口协议 并进行了多项优化,以考虑 I2P 网络的高延迟特性。单个流可以调整最大数据包大小和其他选项,不过默认的 4KB 压缩设置似乎在重传丢失消息的带宽成本和多消息延迟之间取得了合理的平衡。

此外,考虑到后续消息的相对较高成本,streaming库的消息调度和传递协议已经过优化,允许传递的单个消息包含尽可能多的可用信息。例如,通过streaming库代理的小型HTTP事务可以在单次往返中完成——第一个消息捆绑了SYN、FIN和小负载(通常可以容纳HTTP请求),回复则捆绑了SYN、FIN、ACK和小负载(许多HTTP响应都能容纳)。虽然必须传输额外的ACK来告知HTTP服务器已收到SYN/FIN/ACK,但本地HTTP代理可以立即向浏览器传递完整响应。

总的来说,流库与TCP的抽象非常相似,具有滑动窗口、拥塞控制算法(包括慢启动和拥塞避免)以及通用的数据包行为(ACK、SYN、FIN、RST等)。

命名库和地址簿

更多信息请参阅命名和地址簿 页面。

开发者:mihi, Ragnarok

I2P 中的命名问题从一开始就是一个经常被讨论的话题,支持者涵盖了各种可能性的范围。然而,鉴于 I2P 对安全通信和去中心化操作的内在需求,传统的 DNS 风格命名系统显然不适用,“多数决定"的投票系统也是如此。相反,I2P 配备了一个通用命名库和一个基础实现,该实现被设计为基于本地名称到 destination 映射工作,以及一个名为"地址簿"的可选附加应用程序。地址簿是一个由信任网络驱动的安全、分布式且人类可读的命名系统,仅通过要求本地唯一性而不是全局唯一性来牺牲所有人类可读名称的全局唯一性要求。虽然 I2P 中的所有消息都通过其 destination 进行加密寻址,但不同的人可以拥有指向不同 destination 的本地地址簿条目"Alice”。人们仍然可以通过导入其信任网络中指定对等方的已发布地址簿、添加第三方提供的条目,或者(如果有些人使用先到先得的注册系统组织一系列已发布的地址簿)选择将这些地址簿视为名称服务器,模拟传统的 DNS 来发现新名称。

不过,I2P 并不推广使用类似 DNS 的服务,因为劫持站点造成的损害可能是巨大的——而且不安全的 destination 毫无价值。DNSsec 本身仍然依赖于注册商和证书颁发机构,而在 I2P 中,发送到 destination 的请求无法被拦截,回复也无法被伪造,因为它们是用 destination 的公钥加密的,而 destination 本身就是一对公钥和一个证书。另一方面,DNS 风格的系统允许查找路径上的任何名称服务器发起简单的拒绝服务和欺骗攻击。添加由某个集中式证书颁发机构签名认证响应的证书可以解决许多恶意名称服务器的问题,但仍会留下重放攻击以及恶意证书颁发机构攻击的漏洞。

投票式命名同样危险,特别是考虑到Sybil攻击在匿名系统中的有效性——攻击者可以简单地创建任意数量的peer并用每个peer进行"投票"来接管给定名称。工作量证明方法可以用来使身份创建变得有成本,但随着网络增长,联系所有人进行在线投票所需的负载是不现实的,或者如果不查询完整网络,可能会得到不同的答案集合。

然而,与互联网一样,I2P将命名系统的设计和操作保持在(类似IP的)通信层之外。捆绑的命名库包含一个简单的服务提供者接口,替代的命名系统可以插入其中,允许最终用户决定他们偏好的命名权衡方案。

I2PTunnel

开发者:mihi

I2PTunnel 可能是 I2P 最受欢迎且用途最广泛的客户端应用程序,允许在 I2P 网络内外进行通用代理。I2PTunnel 可以看作四个独立的代理应用程序——“client"接收入站 TCP 连接并将其转发到指定的 I2P 目标地址,“httpclient”(又称"eepproxy”)充当 HTTP 代理并将请求转发到相应的 I2P 目标地址(必要时查询命名服务),“server"在目标地址上接收入站 I2P 流连接并将其转发到指定的 TCP 主机+端口,以及"httpserver"通过解析 HTTP 请求和响应来扩展"server"功能,以实现更安全的操作。还有一个额外的"socksclient"应用程序,但由于前面提到的原因,不建议使用它。

I2P本身不是一个出口代理网络——混合网络中将数据转发进出混合网络所固有的匿名性和安全性问题使得I2P的设计专注于提供一个匿名网络,该网络能够满足用户的需求而无需外部资源。然而,I2PTunnel的"httpclient"应用程序提供了一个出口代理的接口——如果请求的主机名不以”.i2p"结尾,它会从用户提供的出口代理集合中随机选择一个目标并将请求转发给它们。这些目标只是由明确选择运行出口代理的志愿者运行的I2PTunnel"server"实例——默认情况下没有人是出口代理,运行出口代理也不会自动告诉其他人通过你进行代理。虽然出口代理确实有固有的弱点,但它们为使用I2P提供了一个简单的概念证明,并在威胁模型下提供了一些功能,这对某些用户来说可能是足够的。

I2PTunnel 使大多数正在使用的应用程序成为可能。指向网络服务器的"httpserver"让任何人都能运行自己的匿名网站(或"I2P Site”)——I2P 为此目的捆绑了一个网络服务器,但任何网络服务器都可以使用。任何人都可以运行指向匿名托管的 IRC 服务器之一的"client”,每个服务器都运行指向其本地 IRCd 的"server",并通过自己的"client" tunnel 在 IRCd 之间进行通信。终端用户还拥有指向 I2Pmail’s POP3 和 SMTP 目标的"client" tunnel(这些目标反过来只是指向 POP3 和 SMTP 服务器的"server"实例),以及指向 I2P 的 CVS 服务器的"client" tunnel,允许匿名开发。有时人们甚至运行"client"代理来访问指向 NNTP 服务器的"server"实例。

I2PSnark

I2PSnark 开发者:jrandom 等人,从 mjwSnark 客户端移植而来

I2PSnark 随 I2P 安装包一起提供,是一个简单的匿名 BitTorrent 客户端,具有多种子功能,通过简洁的 HTML 网页界面提供所有功能。

I2Pmail / Susimail

开发者:postman, susi23, mastiejaner

I2Pmail 与其说是一个应用程序,不如说是一项服务——postman 通过访问与 mastiejaner 共同开发的一系列组件的 I2PTunnel 实例,提供内部和外部电子邮件以及 POP3 和 SMTP 服务,允许人们使用他们首选的邮件客户端来匿名发送和接收邮件。然而,由于大多数邮件客户端会暴露大量识别信息,I2P 捆绑了 susi23 的基于网页的 susimail 客户端,该客户端专门针对 I2P 的匿名需求而构建。I2Pmail/mail.i2p 服务提供透明的病毒过滤以及通过 hashcash 增强配额的拒绝服务防护。此外,每个用户都可以在通过 mail.i2p outproxies 投递之前控制自己的批处理策略,这些 outproxies 与 mail.i2p SMTP 和 POP3 服务器是分离的——outproxies 和 inproxies 都通过 I2P 本身与 mail.i2p SMTP 和 POP3 服务器通信,因此即使那些非匿名位置被攻破,也无法访问用户的邮件账户或活动模式。

Was this page helpful?