Rust:如何使用异步std+TLS+HTTP代理(HTTP隧道)



我购买了一个http代理(支持http隧道(,但没有锈蚀的示例代码,我尝试使用板条箱冲浪,但没有找到代理方式,我必须自己实现。以下是我的代码:

use async_std::task::block_on;
use std::error::Error;
use std::result::Result;
use futures::{AsyncWriteExt, AsyncReadExt};
use async_tls::TlsConnector;
use async_std::net::TcpStream;
const PROXY: &str = "200.200.200.200:8000"; // this is proxy / http tunnel / example IP
async fn http_get_with_proxy(url: &str, proxy: &str) -> Result<String, Box<dyn Error>> {
// 1. make proxy to build connection to target host
let mut stream = TcpStream::connect(proxy).await?;
let r = stream.write_all(format!("CONNECT www.domain.com:443 HTTP/1.1rnrn").as_bytes()).await?;
// 2. start SSL handshake process, resuse TCP stream.
let connector = TlsConnector::default();
let mut tls_stream = connector.connect("www.example.com", stream).await?;
// 3. send data with SSL protocal to proxy, proxy will forward data to target.
let r = tls_stream.write_all(format!("GET https://www.example.com/ HTTP/1.1rnrn").as_bytes()).await?;
let mut buf = String::new();
// 4. recv data from proxy.
let r = tls_stream.read_to_string(&mut buf).await;
Ok(buf)
}
fn main() {
let r = block_on( http_get_with_proxy("https://www.example.com/", PROXY));
dbg!(r);
}

得到错误:

[src/main.rs:35] r = Err(
Custom {
kind: InvalidData,
error: CorruptMessage,
},
)

我不知道出了什么问题。

我不是一个防锈专家,但我发现在协议级别上存在错误:

... CONNECT www.domain.com:443 HTTP/1.1nn ...

首先,它应该是rnrn而不是nn。更重要的是,必须等待代理的HTTP响应,并且只有在获得完整响应后才能建立TLS连接。否则,代理的纯HTTP响应将被解释为TLS握手内的回复,因此握手将失败。有关这种握手的简短示例,请参阅维基百科。

... GET https://www.example.com/ HTTP/1.1rnrn ...

这不是一个有效的HTTP/1.1请求。它至少缺少Host标头,请求行应该只包含路径/,而不是完整的URL。

如果你真的想自己实现HTTP而不是使用库,请研究实际的标准,而不是猜测协议的工作方式。

最新更新