65.9K
CodeProject 正在变化。 阅读更多。
Home

Tor.NET - 一个托管的 Tor 网络库

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.96/5 (49投票s)

2016年1月21日

CPOL

25分钟阅读

viewsIcon

186421

downloadIcon

5156

一个托管库,用于启动和/或连接到 Tor 网络,以进行 SOCKS5 通信和中间人代理托管。

 

目录

  1. 引言
  2. 背景
    1. 什么是 Tor?
    2. Tor 为我的通信提供了哪些安全保障?
    3. Tor 网络中的路由器有多值得信赖?
    4. Tor 有哪些支持?
    5. 为什么我不能直接将 Tor 用作 HTTP 代理?
  3. 要求
  4. 理解协议
    1. SOCKS 端口
    2. 控制端口
  5. Using the Code
    1. 入门
    2. 配置进程
    3. 使用 Web 代理
    4. 使用 SOCKS5 代理
    5. 控制进程
    6. 监控进程
    7. 监控日志
  6. 测试
  7. 参考文献
  8. 历史

引言

Tor 网络是一个不断扩展且极其有用的网络通信工具。它不仅有助于掩盖数据传输,还提供了一种访问其他无法访问的内容或网络目的地的方法。

Tor 进程并不难理解。该进程在两个端口上监听套接字连接:SOCKS 端口和控制端口。通过这些端口,我们能够请求连接到任何地址(出口节点在电路中可以访问的地址),并控制 Tor 进程。

这个库的目的是提供一个托管解决方案,用于自动化 Tor 进程可用的一些任务,并教育内部进程如何实现这样一个网络。

背景

什么是 Tor?

Tor 是一个精密且成熟的路由器网络(也称为中继),用于路由网络通信,而不是直接连接到目标端点。简单来说,它是一系列连接在世界各地的计算机,它们接收数据并进行网络版的“传包裹”游戏。

Tor 由路由器组成,它们共同形成电路。电路是路由器链,可用于连接到目标 IP 地址和端口号,从而在客户端和服务器之间安全地传输信息。处理与目标 实际 连接的路由器被认为是“出口节点”,因为它是处理请求的电路中的最后一个路由器。

当 Tor 进程构建电路后,会为其中一个(或多个)电路创建一个“OR 连接”。此 OR 连接由应用程序用于所有请求,直到电路关闭(过期、手动关闭或发生错误导致关闭)或电路被认为不适合处理所请求的负载。

一个 OR 连接可以承载多个“流”。这些流是客户端和服务器之间传输数据的通信。流通常生命周期较短,因为有些会因不活动而超时,而另一些可能会被服务器关闭。但是,如果流关闭,这不一定意味着父 OR 连接也会关闭。

Tor 为我的通信提供了哪些安全保障?

Tor 旨在加密内容在路由器之间传递时的内容。当初始请求创建并传输第一个数据包时,数据在分发前会被加密。Tor 进程为电路中的每个路由器生成不同的加密密钥,以便数据包的来源保持模糊。

电路中的每个路由器都只能看到电路中的一个“跳”。跳是链中路由器的数量。电路中间的路由器只能看到上一个路由器和下一个路由器:它不了解原始请求来自何处。

这种在链中使用路由器的方法有助于模糊数据包的来源,并保护数据包的内容。监视您的 PC 网络通信的恶意第三方可能能够通过检查套接字连接的目标 IP 地址(和端口号)以及分析 HTTP 头数据(即使通过 HTTPS 也会分派指示连接到地址的 CONNECT 请求)来解密 HTTP 请求上的信息。

使用 Tor 网络,对目标 IP 地址(和端口号)的请求甚至可以在离开您的 PC 之前进行加密。对于监视您的网络通信的第三方来说,这将很难解密。此外,第三方只会知道电路中第一个路由器的 IP 地址。

Tor 网络中的路由器有多值得信赖?

Tor 网络上的标准路由器仅充当中介,将数据从一个路由器移动到另一个路由器。这些路由器不是“出口节点”,并且不了解正在传输的内容(因为数据已加密,内容难以解密)。

然而,出口节点负责将内容分派到目标地址。这意味着出口节点必须能够解密传输的信息,这可能会暴露您的数据。此外,出口节点知道您希望连接到的 IP 地址和端口,进一步暴露了您的请求内容。

简单的回答是,使用 Tor 是一项可能承担也可能不承担的风险。不应在明知恶意出口节点可能保留传输的任何信息的情况下传输高度敏感的数据(尽管通过 Tor 网络执行的 HTTPS 请求会降低风险)。出口节点不了解数据从何处传输或将响应发送到何处,但它肯定可以被操纵来分析请求内容以提取敏感信息(例如银行详细信息)。

Tor 有哪些支持?

Tor 已成为用户在互联网上安全交互的极其流行的工具。最近的事件(此处不提及)增加了人们对增强安全互联网浏览和混淆请求内容的兴趣。

然而,这并不意味着 Tor 被接受为第三方监视器的通用解决方案。有些 ISP 和网站谴责使用 Tor 作为网络协议,并积极尝试抑制其使用。某些网站如果检测到 Tor 网络是连接源,将阻止访问,而某些 ISP 旨在阻止可能源自 Tor 的端口和通信。

尽管如此,Tor 网络仍在不断扩展。新的路由器和出口节点不断轮换和添加,以增加分布:Tor 网络规模越大,ISP 或网站检测到该服务是通信协议的可能性就越小。

为什么我不能直接将 Tor 用作 HTTP 代理?

这是一个常见的误解。有些人试图在他们的本地机器上启动 Tor 进程,为 SOCKS 端口提供一个端口号,然后配置他们的浏览器指向 Tor 进程。这将无法工作。

Tor 是一个 SOCKS 代理,这意味着它能够连接到 IP 地址和端口,但它不理解 HTTP 请求。SOCKS 代理有一系列必须明确遵循的协议才能建立连接。在典型的 SOCKS 代理中,可能需要额外的身份验证(使用凭据),然后才能开始任何连接尝试。然而,Tor 在连接时不需要任何凭据。

SOCKS 代理和 HTTP 代理之间的主要区别在于后者理解 HTTP 请求。HTTP 代理能够分析 HTTP 请求的头部以确定信息应如何路由,并执行与向服务器传输 HTTP 数据以及从服务器接收 HTTP 数据相关的所有操作。

SOCKS 代理只能按照指示行事。它被告知需要连接到某个地址,之后它将尝试建立连接。如果连接失败,它将返回一个按照 SOCKS 协议构造的错误数据包。如果连接成功,它将充当客户端和服务器之间的“缓冲区”流。当 SOCKS 代理收到数据时,它会立即将该内容转发到对端连接。

因此,当尝试将 Tor 用作 Web 代理时,它将失败,因为它需要执行一系列命令才能使用。这个托管库旨在弥合两者之间的差距。

要求

此库充当 Tor 进程的包装器或容器。它负责连接到(并可选择启动)Tor 应用程序,并提供用于监视服务状态和通过网络进行通信的接口。

首先,您需要下载 Tor 应用程序的副本。这可以通过遵循以下说明完成

  1. 导航到 Tor 下载页面
  2. 展开“Microsoft Windows”选项。
  3. 下载“专家捆绑包”

专家捆绑包包含所有 Tor 应用程序文件,不包括配置的浏览器。这些文件是使用此库开始使用 Tor 网络所必需的。

此库要求在创建新客户端时指定 tor.exe 可执行文件的路径。因此,建议将上述捆绑包中包含的文件作为项目的一部分(复制设置设置为始终)或提取到可访问的公共位置(程序数据、应用程序数据等)。

该捆绑包包含在创建 Tor 网络客户端时将启动的可执行文件,并包含两个地理 IP 地址文件,可用于将 IP 地址解析为相对国家/地区代码。

注意

Tor.NET 库要求的最低版本为 0.2.0.9,因为此版本为多个控制命令引入了 v3 目录结构。任何低于此版本的客户端都将引发异常。

理解协议

两个托管端口使用不同的通信协议。SOCKS 端口使用 SOCKS5 协议标准,而控制端口使用一系列 ASCII 通信。本节详细介绍了允许 Tor.NET 库利用该进程的已实现协议。

SOCKS 端口

Tor 进程托管的 SOCKS 端口需要使用 SOCKS5 协议。如前所述,这不是一个简单的“连接并发送”端口,而是需要一些握手才能建立连接和路由数据。SOCKS5 协议在 互联网工程任务组网站 上有详细描述。但为简单起见,我将简要总结一下过程。

当 SOCKS 端口上接受套接字时,客户端发送一个描述我们的连接如何建立的请求。这采用以下字节形式

05 01 00

05 表示我们正在使用的套接字版本是 SOCKS5(SOCKS4 为 4)。01 表示我们提供了一种连接“方法”,它以 00 发送。方法 00 向代理指示我们不发送任何身份验证方法(Tor 不需要代理凭据)。

客户端从代理接收响应,我们期望套接字版本和接受的方法与分派的值一致。有效的响应将是

05 00

这表明 SOCKS5 已被接受,并且连接方法被接受为 00(无需身份验证)。任何其他值都将失败。

然后客户端发送连接到指定目标 IP 地址和端口号的请求。此分派的命令格式如下

05 01 00 01 XX XX XX XX YY YY

05 再次指示套接字版本。紧随其后的 01 指示代理应连接到指定目标。00 是当前未使用的保留字段。01 字段指示地址正在作为 IPv4 地址发送。XX 值指定与 IP 地址对应的字节,YY 值指定端口号。

如果地址以字符串形式发送(例如,如果我们指定代理应连接到域名而不是 IP 地址),则第四个字节中存储的 01 将更改为 03,这表示将紧随其后的是字符串长度和字符串。

05 01 00 03 XX YY YY YY .. ZZ ZZ

在上面,XX 值表示表示地址字符串的字节数。YY 值是地址中每个字符的单个字节。最终的 ZZ 值指定端口号。

一旦发送了上述任何命令,客户端就会读取连接命令的响应。返回的响应包含有关连接到的 IP 地址和端口号的信息。客户端已经知道它要连接到哪里,因此它会丢弃这些值(但将它们从套接字缓冲区中移除)。

当收到连接响应并验证为成功后,连接现在已准备好开始交换数据。写入代理连接的任何字节都将转发到目标端点,而从连接读取的字节将转发到客户端。

此协议的实现由 ForwardSocket 和 Socks5Processor 类管理。

控制端口

控制端口由 Tor 进程托管,它仅用作与服务交互的方法。它不提供任何用于建立网络通信的方法,但允许感兴趣方监视某些事件、配置客户端和收集数据。

该端口使用标准 ASCII 通信:接收文本命令并以文本响应。该端口几乎总是返回一个状态码,指示接收到的命令的成功或失败,后跟响应内容。每行都使用换行符和回车符分隔,但响应内容可能跨越一行或多行。这可以通过分析状态码之后立即返回的字符来进一步确定。

250 OK

当命令被接收和处理后,将返回上述响应。如果命令请求信息,OK 可能会被响应内容替换,但它不会跨越一行。客户端能够确定这是一个单行响应,因为 250 状态码后面有一个空格。

250-Name=Value
250-Name=Value
250 OK

上述响应表示一系列跨多行分割的值。当收到上述内容时,250 状态码后面的连字符(或减号)表示响应在下一行继续。在处理请求多个值的命令时,会收到这些响应。Tor 进程将值分割到多行上,以便于处理并有效管理空白。

250+Name=
Value 1
Value 2
.
250 OK

当命令请求的信息几乎肯定会超过一行时,会收到上述响应。多行响应由 250 状态码后面的加号确定,它通知连接的客户端继续读取行,直到匹配到单个句点符号。句点符号可以作为内容的一部分省略,但在此符号之前的所有行都应该被处理。

连接到控制端口需要使用 TCP 协议打开到 IP 地址和端口号的套接字。Tor 进程仅支持 TCP 通信。

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect("127.0.0.1", 9051);

连接后,控制端口将立即期望进行身份验证。在收到身份验证命令之前,不能将任何其他命令分派到控制端口。身份验证密码与针对进程配置的任何 HashedControlPassword 相关联。如果未为进程分配控制密码,则将接受空白值。

byte[] command = Encoding.ASCII.GetBytes("authenticate \"\"\r\n");
socket.Send(command);

控制端口将验证密码并返回指示身份验证是否成功的响应。250 状态码表示现在可以使用控制端口;否则,515 状态码表示失败。

byte[] buffer = new byte[128];
int received = socket.Receive(buffer);

if (received != 0)
{
    string response = Encoding.ASCII.GetString(buffer, 0, received);

    if (response.StartsWith("250"))
        ; // success
    else
        ; // failure
}

身份验证后,现在可以将任何受支持的控制命令发送到控制端口,并监视响应。Tor 进程支持的命令的完整列表在 Tor 控制规范 中有文档说明。

使用代码

入门

如前所述,一旦文件位于可访问的位置,就可以创建客户端。该库包含一个 Client 类,用作 Tor 进程的托管包装器。Client 类可以通过调用  Create CreateFrom 方法来启动,它们分别启动并连接到新进程,或连接到现有进程。

启动一个新的 Tor 进程

如果 Tor 尚未安装为系统服务,并且您没有连接到现有实例,则需要启动一个新的 Tor 进程。要启动新进程,您需要调用  Create() 方法,并向该方法提供一个 ClientCreateParams 对象。

ClientCreateParams createParams = new ClientCreateParams();
createParams.ConfigurationFile = "/path/to/config/file";
createParams.DefaultConfigurationFile = "/path/to/default/config/file";
createParams.ControlPassword = "";
createParams.ControlPort = 9051;
createParams.Path = "/path/to/tor/exe";

Client client = Client.Create(createParams);

客户端创建参数要求分配控制端口和应用程序路径。传递到 Client 对象的控制端口将始终覆盖配置文件中存储的任何值,因为库需要访问 Tor 进程的控制连接。

配置文件是包含 Tor 应使用的配置的兼容格式文档的路径。类似地,默认配置文件是一个包含当配置文件中找不到相应值时使用的值的文档。这两个参数不是必需的,但如果您计划使用设置预配置 Tor 客户端,则它们很有用。

控制密码用于与 Tor 控制连接进行身份验证。Tor 默认不使用控制密码,因此可以为空或空白。但是,如果已分配控制密码(使用 HashedControlPassword 配置),则此属性需要包含密码的纯文本版本。

该库将在尝试启动进程之前验证控制端口和应用程序路径。如果进程因权限问题或配置问题而无法启动,则会抛出 TorException。

注意

Windows Vista、7、8 和 10 可能需要额外的权限才能启动新进程。如果是这种情况,请确保 应用程序清单文件指定该进程将需要提升的权限。在调试启动 Tor 进程的应用程序时,您需要以管理员帐户运行 Visual Studio。 

连接到现有 Tor 进程

要连接到现有的 Tor 进程,需要使用 ClientRemoteParams 对象调用  CreateFrom() 方法。与创建参数不同,您不需要指定可执行路径或配置文件值。相反,必须提供一个托管 Tor 进程的有效地址。如果进程托管在本地机器上,则此 IP 地址应为 127.0.0.1

ClientRemoteParams remoteParams = new ClientRemoteParams();
remoteParams.Address = "127.0.0.1";
remoteParams.ControlPassword = "";
remoteParams.ControlPort = 9051;

Client client = Client.CreateFrom(remoteParams);

控制端口应为远程 Tor 进程托管的端口。由于我们没有启动新的 Tor 进程,我们无法控制控制端口号。相反,您可能需要手动读取 Tor 配置文件,或了解 Tor 进程配置的端口号。

启动时设置配置值

启动新的 Tor 进程时,可以通过将这些值用作命令行参数来覆盖配置文件中存在的其他配置。例如

tor.exe --AvoidDiskWrites 1

上述内容将始终覆盖配置文件中存储的 AvoidDiskWrites 配置。这对于在启动进程之前对其进行自定义很有用。此外,这允许更改 SOCKS 端口和控制端口值。

要在创建进程时发送配置覆盖,可以调用  SetConfig() 方法,并指定目标配置和值。传递到此方法的值应与 Tor.Config.Configuration 类中指定的类型一致。例如

createParams.SetConfig(ConfigurationNames.SocksPort, 8888);
createParams.SetConfig(ConfigurationNames.AvoidDiskWrites, true);

上述代码将启动 Tor 进程,监听端口 8888 上的 SOCKS 连接,并覆盖配置文件中指定的 AvoidDiskWrites 配置。如果将无效值传递到值字段(例如,如果将字符串传递到期望整数的配置中),则会抛出异常。

配置进程

Client 类包含不同的属性,用于以不同方式与服务交互。Configuration 属性允许用户在进程启动后更改进程的配置。更改配置值将导致客户端将新值分派到 Tor 进程。

client.Configuration.AvoidDiskWrites = true;
client.Configuration.FascistFirewall = true;

当分配上述属性时,每次分配都将导致 Configuration 类连接到 Tor 控制端口并发送“setconf”命令。此命令通知 Tor 进程更新其当前持有的配置。这些值保留在内存中,但不会影响配置文件的内容。分派的命令类似于以下内容

setconf AvoidDiskWrites=1
setconf FascistFirewall=1

为了将新的配置值保存到进程的配置文件中,必须调用  Save() 方法。这将向控制端口分派一个“saveconf”命令,通知 Tor 进程需要将值序列化到文件中。

client.Configuration.Save();

客户端还负责监控配置的外部更改。在任何给定时间,完全有可能有多个客户端连接到 Tor 控制端口,这意味着可以使用“setconf”命令更改进程的配置。为了使配置与进程同步,Configuration 类监听“CONF_CHANGED”事件,并在值更改时自动更新。

客户端支持少量配置,但并非所有值都受支持。有关支持的配置列表,请查阅 Configuration 类。该列表可以通过实现新的 ConfigurationNames 并实现关联的属性来扩展,但此阶段完全不支持某些功能(例如,值列表)。

对于一些使用对象而不是基本类型的配置,必须创建转换器将值从对象转换为字符串。这通过使用 TypeConverter 类实现,该类在  ReflectionHelper.Convert() 方法中引用,用于将值转换为字符串值以及从字符串值转换。在为配置实现更多对象时,应使用 TypeConverter 方法进行自动检测。

使用 Web 代理

如前所述,Tor 网络并非旨在用于即时 HTTP 代理通信。相反,必须实现 Web 代理。Tor.NET 库实现了一个自定义代理系统来处理从标准 SOCKS 通信到 HTTP 的转换。

为了使系统工作,在可配置端口上创建了一个 TCP 监听器。Client 类包含一个  Proxy 属性,其中包含托管 TCP 监听器的逻辑,以及一个可配置的  Port 属性。默认情况下,Proxy 类监听端口 8182 上的连接,但之后可以进行调整。

client.Proxy.Port = 9989;

这将关闭当前的 TCP 监听器并使用新端口重新创建它。这不会影响以前的 TCP 监听器已接受的连接。

使用 Web 代理就像访问  Proxy.WebProxy 属性一样简单。这是 IWebProxy 接口的实现,HttpWebRequest 对象支持该接口。

HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://domain.com");

if (client.Proxy.IsRunning)
    request.Proxy = client.Proxy.WebProxy;

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
    if (response.StatusCode == StatusCode.OK)
        ; // success
}

上述操作将起作用,前提是 Tor.NET 库能够在指定的代理端口上托管 TCP 侦听器。 IsRunning 属性有助于确定代理是否正在接受 TCP 连接。

使用 SOCKS5 代理

除了将 Tor.NET 库用作 HTTP 代理之外,还直接支持 SOCKS 协议。这可以在执行不一定是 HTTP 请求的其他网络请求时使用。例如,可以使用 SOCKS 协议连接到 IRC 网络,前提是 IRC 网络没有阻止已知的 Tor 出口节点。

using (Stream stream = client.GetStream("12.34.56.789", 1234))
{
    stream.Write(..);
    stream.Read(..);
}

 GetStream() 方法接受要连接的主机地址和端口号。Tor.NET 库将执行与连接到目标地址相关的所有握手,并打开一个用于通信的流。

控制进程

Client 类包含一个  Controller 属性,它提供了一些方法来控制服务的元素。该类中可用的方法旨在自动化到控制端口的连接和命令的分派。这些方法还对提供的参数执行验证。

 CleanCircuits()

这会通知服务,新的请求应该通过新的电路路由。这可以防止新请求重复使用以前使用过的旧电路。这还会清除客户端 DNS 缓存。

 CleanDNSCache()

这导致服务清除主机名的客户端 DNS 缓存。

 CloseCircuit(Circuit)

如果电路尚未关闭且未失败,则关闭该电路。已关闭的电路不能再被 Tor 用来生成 OR 连接或通信流。

 CloseStream(Stream, StreamReason)

如果流尚未关闭且未失败,则关闭该流。这相当于终止套接字连接。

 CreateCircuit()

这会通知服务应该构建一个新的电路,并且服务应该负责选择要使用的路由器。

 CreateCircuit(string[])

此函数与  CreateCircuit() 方法功能相同,但此方法接受一个包含路由器昵称或指纹的数组,这些路由器应用于构建电路。

 ExtendCircuit(Circuit, string[])

此功能与 CreateCircuit(string[]) 方法几乎相同,不同之处在于参数列表中指定的路由器将附加到现有电路的末尾。

监控进程

除了能够控制进程之外,客户端还在后台进行事件监控,以同步电路、OR 连接和流信息。这通过打开与控制端口的持续连接并分派“setevents”命令来实现。这会通知 Tor 进程报告系统中发生的事件,例如电路何时构建或关闭,或者连接或流何时更改。

为了从实时更新中受益,可以在 Client 类的  Status 属性中的事件注册事件处理程序。可以监视的事件如下

 BandwidthChanged

每当 Tor 服务中估计的上一秒的下载和更新速率发生变化时,就会引发此事件。当请求通过连接分派时,这些值反映了自上次事件以来平均下载和上传的字节数。

 CircuitsChanged

当 Tor 服务中的电路发生更改时,就会引发此事件。当事件引发时,这表示  Circuits 属性包含新信息。

 ORConnectionsChanged

当 Tor 服务中的 OR 连接发生更改时,就会引发此事件。当事件引发时,这表示  ORConnections 属性包含新信息。

 StreamsChanged

当 Tor 服务中的流发生更改时,就会引发此事件。当事件引发时,这表示  Streams 属性包含新信息。

Status 属性还提供了获取服务当前状态的基本属性和方法。例如, GetAllRouters() 方法是一个开销很大的函数,它下载 Tor 进程关注的所有路由器的完整注册表。

所有属性都会向控制端口发出请求,因此执行可能不是即时的。如果 Tor 客户端无法连接到 Tor 进程的控制端口,则这些值可能无法代表进程中的实际值。

有些事件尚未实现,但可以轻松集成到库中。例如,“ADDRMAP”事件在地址解析时引发。

监控日志

Tor 应用程序生成内部日志消息,可以通过控制端口接收这些消息。此信息对于诊断客户端问题可能很有用。可用的日志级别包括

  • Debug
  • Notice
  • Info(信息)
  • Warn(警告)
  • Error(错误)

每个日志级别都使用“setevents”命令注册,响应通过 Client 类中的  Logging 属性路由。此属性包含用于自动注册对上述任何日志消息感兴趣的事件。每个引发的事件都包含一个 EventArgs 类实现 (LogEventArgs),其中包含收到的消息。

注册任何指定日志级别的通知就像向相应事件添加事件处理程序一样简单。如果您希望取消订阅日志消息,请确保从事件中删除所有事件处理程序。

client.Logging.DebugReceived += (s, e) => Console.WriteLine("[DEBUG] " + e.Message);
client.Logging.ErrorReceived += (s, e) => Console.WriteLine("[ERROR] " + e.Message);
注意

此功能在 Tor.NET 1.0.2 及更高版本中可用。

注意

使用日志功能可能会影响 Tor.NET 客户端以及关联的事件分发器的性能。建议避免注册除“Error”和“Warn”之外的所有日志消息。

测试

附加的项目文件包含一个 Tor.Tests 项目,其中包含一个使用 Tor.NET 库的简单 WinForms 应用程序。它启动 Tor 进程并针对  Status 属性注册事件处理程序。还有一个连接到  Configuration 属性的 PropertyGrid 控件,以便可以修改应用程序的配置。

Program.cs 文件包含大量用于原生互联网控制的导入和结构。这些方法用于设置应用程序的默认代理,指示 WebBrowser 控件通过 Tor 代理路由请求。如果打算将 Tor.NET 库与 WebBrowser 控件一起使用,我建议您从该类复制代码并将其集成到您的应用程序中。

关注点

该库旨在作为使用 Tor 网络的入口点。有些控制命令和事件尚未实现,主要原因是实现所有可能的方法将导致一个庞大的库,其中充满了方法和事件。我一直试图使该库相对较小且相对简单,因为它主要旨在启动 Tor 进程并提供通信桥梁。

话虽如此,如果对添加额外功能、事件和配置的需求很高,那么我可能会相应地扩展库的功能。

参考文献

历史

  • 版本 1.0.0 - Tor.NET 和文章的初始版本
  • 版本 1.0.1 - 库更新,包含修复和新增功能
    • 修复了使用“远程”客户端时忽略目标地址的问题。
    • 添加了配置“CircuitBuildTimeout”、“CircuitIdleTimeout”、“HardwareAcceleration”、“LearnCircuitBuildTimeout”
  • 版本 1.0.2 - 库更新,包含修复和新增功能
    • 修复了客户端除非引发 Dispose() 否则永远不会关闭进程的问题。
    • 修复了 Circuit 类中空路由器响应会引发异常的问题。
    • 添加了日志事件处理。
© . All rights reserved.