Rust匿名网络Tor协议实现库tor-proto的使用,支持高性能加密通信和隐私保护

tor-proto - Tor协议核心实现的Rust库

概述

tor-proto crate是Arti项目的核心,该项目旨在用Rust实现Tor。大多数人不应直接使用这个crate,因为它的API对于大多数用途来说过于底层,而且很容易以不安全或侵犯隐私的方式误用它们。

大多数人应该使用arti-client crate。这个crate主要对那些想要在底层访问Tor协议的人感兴趣。

核心概念

本质上,Tor与其他Tor实例建立称为"通道"的连接。这些通道使用TLS实现。每个通道复用多个匿名多跳"电路",这些电路作为客户端和电路上不同中继之间的"中继消息"的可靠传输。最后,每个电路复用多个"流",每个流大致对应于一个应用级请求。

这个crate实现了实现这些通道、电路和流的逻辑、协议和加密。它使用Rust异步代码和future相关特性,旨在与(几乎)任何符合futures API的执行器实现一起工作。它也应该与(几乎)任何暴露AsyncRead和AsyncWrite特性的TLS实现一起工作。

不在这个crate中

这个crate不实现基于这里Tor协议的高级协议,如洋葱服务或Tor目录协议。它也不决定何时、如何或何处建立通道和电路:这是高级crate的角色。

这个crate也没有超时支持,所以这里的每个网络操作都有可能无限期地阻塞当前任务。超时是另一个在更高层次添加的必要部分。

为了创建通道和电路,你需要了解一些Tor中继。目前,tor-netdir crate是最简单的方法。

要查看这个crate的实际应用,请参阅arti-client库或arti CLI。

设计说明

这个crate的API结构限制了异步运行时的使用:除非必要,它不会启动任务或创建计时器。

尽可能情况下,这个crate避免在用于网络活动的相同函数中进行公钥加密。这使得更高级别的代码更容易并行化或围绕公钥操作进行yield。

此外,这个crate尽量避免知道或编码关于其对象(通道、电路、流)"用途"的信息。也就是说,尽可能情况下,我们编码对象应该如何表现,而不是它应该这样表现的原因。例如,这个crate中的Circuit对象记住电路构建的路径,但不记住电路的用途,或它可能用于什么。其他crate负责强制执行这种规则。

为什么要这样将行为与目的分开?我们这样做是为了避免我们在C tor实现中遇到的一种逻辑过载,其中使用信息与行为设置不分开。由于使用信息可用,在代码库的所有点上,C tor代码在许多地方已经收敛于涉及该使用信息的复杂逻辑,以便设置单个行为。因此,在C tor中添加新种类的使用或行为已经变得相当复杂。我们试图在Arti中避免这种复杂性。

限制

所有这些都还在进行中,在完成之前需要彻底重构。

这是一个仅限客户端的实现;不支持中继需要的操作。

缺少的功能太多,无法一一列举。

文档或示例不足。

这个crate是我第一次尝试在Rust中使用异步,可能相当笨拙。

我敢打赌这个代码中某处有死锁。我修复了所有我能找到或想到的,但找到一个好方法来消除我们拥有的每一个锁会很好。

许可证:MIT OR Apache-2.0

完整示例代码

use tor_proto::{circuit::ClientCirc, stream::DataStream};
use tor_rtcompat::Runtime;

async fn example<R: Runtime>(runtime: R) -> Result<(), tor_proto::Error> {
    // 创建一个Tor通道
    let chan = tor_proto::channel::Channel::new(
        runtime,
        "example.com:443".parse().unwrap(),
        None,
    ).await?;

    // 创建一个电路
    let circ = ClientCirc::new(chan).await?;

    // 创建一个数据流
    let stream = DataStream::new(circ).await?;

    // 使用流进行通信
    stream.write_all(b"GET / HTTP/1.0\r\n\r\n").await?;
    let mut buf = Vec::new();
    stream.read_to_end(&mut buf).await?;
    
    println!("Received: {}", String::from_utf8_lossy(&buf));
    Ok(())
}

这个示例展示了如何使用tor-proto创建一个Tor通道、电路和数据流,并进行简单的HTTP请求。请注意,实际使用时需要提供适当的运行时实现和正确的Tor中继信息。

对于大多数应用场景,建议使用更高层次的arti-client crate,它提供了更简单易用的API和更好的隐私保护默认设置。

扩展完整示例

use std::io::{self, Read, Write};
use tor_proto::{circuit::ClientCirc, stream::DataStream};
use tor_rtcompat::{TcpProvider, TokioNativeTlsRuntime};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建Tokio运行时
    let runtime = TokioNativeTlsRuntime::current()?;
    
    // 创建TCP连接提供者
    let tcp_provider = TcpProvider::new();
    
    // 创建Tor通道
    let chan = tor_proto::channel::Channel::new(
        runtime.clone(),
        "example.com:443".parse()?,
        Some(&tcp_provider),
    ).await?;
    
    // 创建Tor电路
    let circ = ClientCirc::new(chan).await?;
    
    // 创建数据流
    let mut stream = DataStream::new(circ).await?;
    
    // 发送HTTP请求
    stream.write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n")?;
    
    // 读取响应
    let mut response = Vec::new();
    stream.read_to_end(&mut response)?;
    
    // 打印响应
    println!("Response:\n{}", String::from_utf8_lossy(&response));
    
    Ok(())
}

这个扩展示例展示了:

  1. 如何设置Tokio运行时
  2. 如何使用TCP提供者
  3. 如何发送完整的HTTP/1.1请求
  4. 如何处理响应数据

注意:实际使用时需要正确处理错误和配置Tor网络目录。


1 回复

Rust匿名网络Tor协议实现库tor-proto的使用指南

概述

tor-proto是Rust语言实现的Tor协议库,提供了构建Tor网络客户端和服务器的核心功能,支持高性能加密通信和隐私保护。它是Artichoke项目的一部分,旨在提供安全、模块化的Tor实现。

主要特性

  • 完整的Tor协议实现
  • 高性能加密通信
  • 隐私保护功能
  • 模块化设计
  • 异步I/O支持

使用方法

添加依赖

首先在Cargo.toml中添加依赖:

[dependencies]
tor-proto = "0.9"
tokio = { version = "1.0", features = ["full"] }

基本示例:创建Tor客户端连接

use tor_proto::circuit::ClientCirc;
use tor_proto::stream::DataStream;
use tokio::io::{AsyncReadExt, AsyncWriteExt};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建Tor配置
    let config = tor_proto::circuit::ClientConfig::default();
    
    // 连接到Tor网络
    let circ = ClientCirc::create(
        config,
        tor_linkspec::OwnedChanTarget::builder()
            .ed_identity([0; 32].into())
            .build()?,
    ).await?;
    
    // 创建数据流
    let mut stream = circ.begin_stream("example.com:80").await?;
    
    // 发送HTTP请求
    stream.write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n").await?;
    
    // 读取响应
    let mut buf = vec![0; 1024];
    let n = stream.read(&mut buf).await?;
    println!("Response: {}", String::from_utf8_lossy(&buf[..n]));
    
    Ok(())
}

高级示例:构建简单的Tor隐藏服务

use tor_proto::relay::RelayCirc;
use tor_proto::stream::DataStream;
use tokio::io::{AsyncReadExt, AsyncWriteExt};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建隐藏服务配置
    let hs_config = tor_proto::relay::HsCircConfig::default();
    
    // 创建隐藏服务电路
    let circ = RelayCirc::create_hs(hs_config).await?;
    
    // 发布隐藏服务描述符
    circ.publish_hs_desc().await?;
    
    // 等待连接
    let (mut stream, request) = circ.accept_stream().await?;
    println!("Received connection for: {}", request);
    
    // 发送响应
    stream.write_all(b"HTTP/1.1 200 OK\r\n\r\nHello from Tor hidden service!").await?;
    
    Ok(())
}

完整示例代码

Tor客户端完整示例

use tor_proto::circuit::{ClientCirc, ClientConfig};
use tor_proto::stream::DataStream;
use tor_linkspec::OwnedChanTarget;
use tokio::io::{AsyncReadExt, AsyncWriteExt};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建自定义配置
    let config = ClientConfig::builder()
        .max_circuit_dirtiness(std::time::Duration::from_secs(1800))
        .build();
    
    // 构建通道目标
    let target = OwnedChanTarget::builder()
        .ed_identity([0; 32].into()) // 实际使用时应替换为真实身份
        .build()?;
    
    // 建立Tor电路连接
    let circ = ClientCirc::create(config, target).await?;
    
    // 创建到目标网站的数据流
    let mut stream = circ.begin_stream("example.com:80").await?;
    
    // 发送HTTP GET请求
    let request = b"GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n";
    stream.write_all(request).await?;
    
    // 读取完整响应
    let mut response = Vec::new();
    let mut buf = [0; 1024];
    loop {
        let n = stream.read(&mut buf).await?;
        if n == 0 {
            break;
        }
        response.extend_from_slice(&buf[..n]);
    }
    
    // 打印响应
    println!("Received {} bytes:\n{}", response.len(), String::from_utf8_lossy(&response));
    
    Ok(())
}

Tor隐藏服务完整示例

use tor_proto::relay::{RelayCirc, HsCircConfig};
use tor_proto::stream::DataStream;
use tokio::io::{AsyncReadExt, AsyncWriteExt};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建隐藏服务配置
    let hs_config = HsCircConfig::builder()
        .service_private_key(/* 实际使用时应设置私钥 */)
        .build();
    
    // 创建隐藏服务电路
    let circ = RelayCirc::create_hs(hs_config).await?;
    
    // 发布服务描述符
    circ.publish_hs_desc().await?;
    println!("Hidden service published successfully");
    
    // 监听连接
    loop {
        println!("Waiting for incoming connections...");
        
        // 接受新连接
        let (mut stream, request) = circ.accept_stream().await?;
        println!("New connection for: {}", request);
        
        // 处理连接
        tokio::spawn(async move {
            // 简单HTTP响应
            let response = b"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nHello from Tor hidden service!";
            if let Err(e) = stream.write_all(response).await {
                eprintln!("Failed to send response: {}", e);
            }
        });
    }
}

配置选项

use tor_proto::circuit::ClientConfig;

let config = ClientConfig::builder()
    .max_circuit_dirtiness(std::time::Duration::from_secs(3600))
    .initial_path_timeout(std::time::Duration::from_secs(60))
    .build();

安全注意事项

  1. 始终使用最新版本的tor-proto
  2. 妥善管理私钥和认证信息
  3. 定期更新Tor网络目录信息
  4. 注意日志中可能泄露隐私的信息

性能优化建议

  1. 复用电路而不是为每个请求创建新电路
  2. 使用连接池管理多个电路
  3. 预建电路以减少延迟
  4. 调整超时设置以适应网络条件

错误处理

match result {
    Ok(_) => println!("Success"),
    Err(tor_proto::Error::ProtocolViolation(e)) => eprintln!("Protocol error: {}", e),
    Err(tor_proto::Error::CircTimeout) => eprintln!("Circuit timeout"),
    Err(e) => eprintln!("Other error: {}", e),
}
回到顶部