I2P 提案 #166: 基于身份/主机的隧道类型

Proposal 166
开放
Author eyedeekay
Created 2024-05-27
Last Updated 2024-08-27
Target Version 0.9.65

主机感知的 HTTP 代理隧道类型提案

这是一个通过引入新的 HTTP 代理隧道类型来解决常规 HTTP-over-I2P 使用中的“共享身份问题”的提案。此隧道类型具有补充行为,旨在防止或限制可能的敌对隐藏服务运营商通过针对特定用户代理(浏览器)和 I2P 客户端应用程序进行跟踪的效用。

什么是“共享身份”问题?

当加密地址覆盖网络上的用户代理与另一个用户代理共享加密身份时,就会发生“共享身份”问题。这种情况发生在,例如,Firefox 和 GNU Wget 都被配置为使用相同的 HTTP 代理。

在这种情况下,服务器有可能收集和存储用于回复活动的加密地址(目的地)。它可以将此视为一个“指纹”,因为它源自加密,因此始终 100% 唯一。这意味着通过共享身份问题观察到的可链性是完美的。

但这是个问题吗? ^^^^^^^^^^^^^^^^^^^^

当说相同协议的用户代理希望断开链接时,共享身份问题就是个问题。在这个 Reddit 线程的上下文中,它首次被提及,已删除的评论可通过 pullpush.io 访问。 当时 我是最活跃的回应者之一,当时 我认为这个问题很小。在过去的 8 年里,情况和我对它的看法发生了变化,我现在认为,随着更多网站有能力“识别”特定用户,恶意目的地关联带来的威胁大大增加。

这种攻击的进入门槛非常低。它只需要一个隐藏服务运营商操作多个服务。对于同时访问多个站点的攻击,这是唯一的要求。对于非同时链接,这些服务之一必须是托管“账户”的服务,这些账户属于被跟踪的单个用户。

目前,任何托管用户帐户的服务运营商都可以通过利用共享身份问题将它们与他们控制的任何站点的活动关联起来。只要他们操作不止一个服务并且有兴趣为用户创建配置文件,Mastodon、Gitlab 甚至简单的论坛都可能是伪装的攻击者。这种监视可能是为了跟踪、经济利益或与情报相关的原因。目前有数十个大运营商可以进行这种攻击并从中获得有意义的数据。我们目前主要信任他们不会这样做,但可能不在乎我们意见的参与者很容易出现。

这直接涉及到一个相当基本的清晰网页上的配置文件构建形式,组织可以将他们网站上的互动与他们控制的网络上的互动关联起来。在 I2P 上,由于加密目的地是唯一的,因此即使没有地理定位的附加功能,这种技术有时也可以更加可靠。

共享身份对于仅使用 I2P 来混淆地理位置的用户没有用处。它也不能用于破坏 I2P 的路由。这只是一个上下文身份管理的问题。

  • 不可能使用共享身份问题来定位 I2P 用户。
  • 不可能使用共享身份问题来链接非同时发生的 I2P 会话。

但是,在可能非常常见的情况下,可以利用它来降低 I2P 用户的匿名性。这些情况之所以常见,一个原因是我们鼓励使用支持“标签”操作的网页浏览器 Firefox。

  • 在支持请求第三方资源的任何网页浏览器中,总是可以从共享身份问题中产生指纹。
  • 停用 JavaScript 对共享身份问题帮助。
  • 如果能够通过“传统”浏览器指纹识别来建立非同时会话之间的链接,则可以通过共同身份转移应用,潜在地启用一种非同时的链接策略。
  • 如果能够在清网活动和 I2P 身份之间建立链接,例如,如果目标在同时具有 I2P 和清网存在的网站上登录,则可以通过共享身份转移应用,潜在地实现完全去匿名化。

您如何看待共享身份问题的严重性,取决于您(或者更确切地说,具有潜在不知情期望的“用户”)认为应用的“上下文身份”在何处。有几种可能:

  1. HTTP 既是应用又是上下文身份 - 这就是现在的工作方式。所有 HTTP 应用共享一个身份。
  2. 进程是应用和上下文身份 - 当应用使用像 SAMv3 或 I2CP 这样的 API 时,它如何工作,其中应用创建其身份并控制其生命周期。
  3. HTTP 是应用,但主机是上下文身份 - 这是本提案的目标,将每个主机视为一个潜在的“网络应用”,并将威胁面视为此类。

是否可解决? ^^^^^^^^^^^^^^^

可能无法制作一个能够智能响应可能情况下的代理,其操作可能会削弱应用的匿名性。然而,可以构建一个能够智能响应行为可预测的特定应用的代理。例如,在现代网页浏览器中,用户预计会开多个标签页,他们会浏览多个通过主机名区分的网站。

这使我们能够通过为与 HTTP 代理一起使用的每个主机提供自己的目的地来改进此类型的 HTTP 用户代理的 HTTP 代理行为。这项更改使得无法使用共享身份问题来推导一个可用来关联客户端活动和两个主机的指纹,因为这两个主机将不再共享返回身份。

描述: ^^^^^^^^^^^^

将创建一个新的 HTTP 代理并将其添加到隐藏服务管理器(I2PTunnel)中。新的 HTTP 代理将作为 I2PSocketManagers 的“多路复用器”运行。多路复用器本身没有目的地。成为多路复用的一部分的每个 I2PSocketManager 都有其自己的本地目的地和自己的隧道池。I2PSocketManagers 是由多路复用器按需创建的,其中“需求”是首次访问新主机。可以通过提前创建一个或多个 I2PSocketManager 并在多路复用器之外存储它们来优化 I2PSocketManagers 的创建。这可能会提高性能。

还有一个拥有自身目的地的附加 I2PSocketManager 被设置为任何没有 I2P 目的地的网站(例如任何清网网站)的“外代理”载体。这实际上使所有外代理使用成为单一的上下文身份,但注意为隧道配置的多个外代理将导致正常的“黏性”外代理旋转,其中每个外部代理只会收到一个网站的请求。这几乎相当于在清网中通过目的地隔离 HTTP-over-I2P 代理的行为。

资源考虑: ’’’’’’’’’’’’’’’’’’’’’’''

新 HTTP 代理比现有的 HTTP 代理需要更多的资源。它将:

  • 潜在地构建更多的隧道和 I2PSocketManagers
  • 构建隧道更频繁

每一个都需要以下内容:

  • 本地计算资源
  • 来自对等端的网络资源

设置: ’’’’’’’''

为了尽量减少增加的资源使用的影响,代理应配置为尽可能减少使用。不属于父代理的多路复用代理应配置为:

  • 多路复用的 I2PSocketManager 在其隧道池中构建 1 个入隧道和 1 个出隧道
  • 多路复用的 I2PSocketManager 默认采用 3 跳。
  • 在不活动 10 分钟后关闭套接字
  • 由多路复用器启动的 I2PSocketManagers 共享多路复用器的生命周期。多路复用的隧道在父多路复用器“消亡”之前不会“销毁”。

图示: ^^^^^^^^^

下图显示了与“是个问题吗”部分中的“可能性1”相对应的 HTTP 代理的当前操作。可以看到,HTTP 代理直接与 I2P 网站交互,仅使用一个目的地。在这种情况下,HTTP 是应用,同时也是上下文身份。

**当前情况:HTTP 是应用,HTTP 是上下文身份**
                                                          __-> 外代理 <-> i2pgit.org
                                                         /
   浏览器 <-> HTTP 代理(一个目的地)<-> I2PSocketManager <---> idk.i2p
                                                         \__-> translate.idk.i2p
                                                          \__-> git.idk.i2p

下图显示了与"是个问题吗"部分中的"可能性3"相对应的主机感知的 HTTP 代理的操作。在这种情况下,HTTP 是应用,但主机定义了上下文身份,其中每个 I2P 网站与不同的 HTTP 代理交互,每个主机都有唯一的目的地。这防止了多个站点的运营者能够区分同一人在访问他们运营的多个站点时的情况。

**更改后:HTTP 是应用,主机是上下文身份**
                                                        __-> I2PSocketManager(目的地 A - 仅外代理) <--> i2pgit.org
                                                       /
   浏览器 <-> HTTP 代理多路复用器(无目的地) <---> I2PSocketManager(目的地 B)<--> idk.i2p
                                                       \__-> I2PSocketManager(目的地 C)<--> translate.idk.i2p
                                                        \__-> I2PSocketManager(目的地 C)<--> git.idk.i2p

状态: ^^^^^^^

一个符合本提案较旧版本的主机感知代理的 Java 实现已在 idk 的分支下提供:i2p.i2p.2.6.0-browser-proxy-post-keepalive 连接在引用中。该版本正在进行大量修订,以便将更改分解为较小部分。

具有不同功能的实现已使用 SAMv3 库在 Go 中编写,它们可能对嵌入其他 Go 应用程序或 go-i2p 有用,但不适合 Java I2P。此外,它们缺乏交互式工作的良好支持与加密的 leaseSets。

附录:i2psocks

不需要实施新的隧道类型或更改现有的 I2P 代码,就可以通过结合 I2PTunnel 现有的工具(这些工具在隐私社区中已经广泛可用并经过测试)来实现其他类型客户端的简单应用感知隔离。然而,这种方法做出了一个困难的假设,这对于 HTTP 和许多其他类型的潜在 I2P 客户而言都不是真的。

大致来说,下面的脚本将生成一个应用感知的 SOCKS5 代理并将基础命令 SOCKSI 化:

#! /bin/sh
command_to_proxy="$@"
java -jar ~/i2p/lib/i2ptunnel.jar -wait -e 'sockstunnel 7695'
torsocks --port 7695 $command_to_proxy

附录:攻击的示例实现

一个针对 HTTP 用户代理的共享身份攻击的示例实现 已存在数年。额外的示例如在 idk 的 prop166 存储库simple-colluder 子目录中可用。这些示例是故意设计用于演示攻击有效,并需要修改(虽然很小)才能变成真实攻击。