1个不稳定版本
0.1.0 | 2021年4月11日 |
---|
#2144 in 网络编程
30KB
491 行
tokio-sando
这是一个基于tokio的简单代理服务器实现。
代理服务器位于客户端和客户端目标之间(日语中的"sando"意为三明治)。它将代表其客户端从目标请求数据。换句话说,代理本质上充当VPN。请参阅工作原理以了解更多信息。
如何运行
打开两个终端。一个用于服务器,一个用于客户端。
- 将
127.0.0.1 proxy.tokio.sando
添加到您的/etc/hosts
proxy.tokio.sando
是在domain.crt
中注册的主机名。
- 在服务器端,运行
./server
。 - 在客户端,运行
./client
。./client
基于curl
。请确保其版本高于7.68.0
。否则,我们无法并行发送HTTP请求。
高级设置
您可以使用正则表达式设置目标URL的模式。例如,您可以运行以下命令
服务器端
cargo run -- 127.0.0.1:7878 --pkcs12 domain.p12 --password "^G#=QVbVhh7Bt8t9L" --destination-pattern "([a-z]).(mozilla|rust-lang).org"
客户端
# Work
curl -vp --proxy "https://proxy.tokio.sando:7878" --proxy-cacert domain.crt "https://rust-lang.net.cn/"
# Work
curl -vp --proxy "https://proxy.tokio.sando:7878" --proxy-cacert domain.crt "https://www.mozilla.org/en-US/"
# Won't work. Doesn't match "([a-z]).(mozilla|rust-lang).org" pattern
curl -vp --proxy "https://proxy.tokio.sando:7878" --proxy-cacert domain.crt "https://en.wikipedia.org/"
生成证书
此仓库包含一个内置证书。如果证书已过期或您希望生成自己的证书,请运行以下命令
-
openssl req \ -newkey rsa:2048 -nodes -keyout domain.key \ -x509 -days 365 -out domain.crt
- 将
proxy.tokio.sando
替换为Common Name
,在client.sh
中已注册的domain.crt
- 如果您更改了
domain.crt
的文件名,请也在client.sh
中进行更新
- 将
-
openssl pkcs12 \ -inkey domain.key \ -in domain.crt \ -export -out domain.p12
- 将
server.sh
中的密码^G#=QVbVhh7Bt8t9L
替换为您的新密码 - 如果您更改了
domain.p12
的文件名,请也在server.sh
中进行更新
- 将
-
现在
server.sh
和client.sh
应该可以使用您自己的证书工作了
工作原理
client proxy destination
| | |
* <--- 1 ---> * |
| | |
* ---- 2 ---> * ---- 3 ---> *
| | |
* <--- 5 ---- * <--- 4 ---- *
| | |
* ----------> * ----------> * relay data: client -> destination
| | |
* <---------- * <---------- * relay data: destination -> client
| | |
- 客户端和代理之间的 TCP 和 TLS 握手(现在为 HTTPS)
- 客户端向代理发送 HTTP CONNECT 请求
- 代理建立到客户端 目的 的 TCP 通道
- 一旦建立上述 TCP 通道
- 通知客户端 HTTP 隧道 已建立
- 现在代理可以通过隧道在客户端和 目的 之间中继数据
用例
代理的一个用例是保护隐私的服务。一旦代理建立了隧道,如果通过隧道中继的数据是 HTTPS,客户端可以匿名地与 目的 通信。目的知道客户端的请求,但不知道客户端是谁。代理知道客户端和目的都是谁,但不知道他们在谈论什么。
这里有一个演示是 giphy 搜索。打开两个终端。一个是服务器,一个是客户端。
-
如果
127.0.0.1 proxy.tokio.sando
还不在,请将其添加到您的/etc/hosts
-
在服务器端,运行
./server
,如果服务器仅用于 giphy 服务,请运行以下命令cargo run -- 127.0.0.1:7878 \ --pkcs12 domain.p12 \ # or your own PKCS12 file --password "^G#=QVbVhh7Bt8t9L" \ # or your new password if using your own PKCS12 file --destination-pattern "api.giphy.com" # Server only accept HTTP CONNECT to "api.giphy.com"
-
在客户端,运行
./giphy_search.sh
以匿名搜索 gif。
请确保 HTTP CONNECT 请求(要求在客户端和目的之间中继数据)使用 HTTPS 协议。否则,如果隧道通信在 HTTP 中,代理将知道客户端和目的之间传输的内容,因为 HTTP 以纯文本形式传输数据。
待办事项
- 隐私感知
- 找到一种方法强制客户端使用 HTTPS 在隧道中传输数据
- 至少可以通过嗅探中继的数据来说明这一点
- 找到一种方法强制客户端使用 HTTPS 在隧道中传输数据
- 更灵活的设置
- 添加超时设置
- 如果连接挂起一段时间,则关闭连接。这应该有助于结束具有未知错误的连接
- HTTP 版本检查
- 代理应该能够要求最低的 HTTP 版本
- 最大并行连接数
- 代理应该能够限制并行连接的数量,以控制资源
- 添加超时设置
- 更好的错误/响应处理
- 原因:目前,如果抛出
std::io::Error
,则连接会被终止。代理应该向客户端发送响应,指示遇到的问题,而不是静默地断开连接。一旦客户端和代理之间的TLS建立,代理应该能够向客户端发送消息。 - 如果客户端请求不完整或无效,则向客户端发送
400 Bad Request
。- 使用特定的错误枚举进行请求解析应该是有帮助的。
- 如果代理无法连接到客户端的目的地,则向客户端返回错误。
- 如果转发数据有问题,则向客户端返回错误。
- 在隧道中转发数据时应该有一个超时机制。
- 对于隧道模块使用特定的错误枚举应该是有帮助的。
- 在代理服务器响应中添加更多详细的错误消息。现在响应只包含状态码。
- 原因:目前,如果抛出
- 测试
- 添加性能基准。需要与并行请求一起工作。
- 为请求解析测试添加更多边缘情况。
- 对不同类型的错误添加测试。
- 流量控制/统计
- 实时流量统计监控和控制
- 即使出错,也要收集传输的字节数,只要代理已经转发了数据。
- 现在,代理仅在连接成功完成后才显示统计信息。即使隧道转发或其他失败有错误,也应该知道已传输了多少数据。
- 内存
- 更好的缓冲区大小控制
- 现在解析HTTP请求和转发数据的缓冲区大小是固定的。在服务器上有大量并行HTTP请求且内存有限时,需要更复杂的控制。
- 更好的缓冲区大小控制
- 日志系统
- 将日志消息写入文件,而不是仅打印到屏幕上。
- 为日志设置不同的级别。一些日志仅用于调试。
- 构建时间/代码大小
- 评估是否需要从tokio中获取
full
功能。
- 评估是否需要从tokio中获取
依赖关系
~5–17MB
~218K SLoC