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(())
}
这个扩展示例展示了:
- 如何设置Tokio运行时
- 如何使用TCP提供者
- 如何发送完整的HTTP/1.1请求
- 如何处理响应数据
注意:实际使用时需要正确处理错误和配置Tor网络目录。
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();
安全注意事项
- 始终使用最新版本的tor-proto
- 妥善管理私钥和认证信息
- 定期更新Tor网络目录信息
- 注意日志中可能泄露隐私的信息
性能优化建议
- 复用电路而不是为每个请求创建新电路
- 使用连接池管理多个电路
- 预建电路以减少延迟
- 调整超时设置以适应网络条件
错误处理
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),
}