1

I purchased an http proxy(supported http tunnel), but have no rust example code, I try to use the crate surf, but not found the proxy way, I have to implement it by myself. following is my code:

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.1\r\n\r\n").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.1\r\n\r\n").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);
}

got error:

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

I don't know what went wrong.

Anunaki
  • 763
  • 2
  • 8
  • 18

1 Answers1

0

I'm not an a rust expert, but I see that there are errors on the protocol level:

... CONNECT www.domain.com:443 HTTP/1.1\n\n ...

First, it should be \r\n\r\n not \n\n. More importantly, one must wait for the HTTP response of the proxy and only establish the TLS connection after one got the full response. Otherwise the plain HTTP response of the proxy will be interpreted as reply inside the TLS handshake and thus the handshake will fail. See also Wikipedia for a short example of this handshake.

... GET https://www.example.com/ HTTP/1.1\r\n\r\n ...

This is not a valid HTTP/1.1 request. It is missing at least the Host header and the request line should only contain the path / and not the full URL.

If you really want to implement HTTP yourself instead of using libraries, please study the actual standards instead of second-guessing how the protocol might work.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • after modify \n -> \r\n, the result is same. – Anunaki Jan 10 '21 at 08:26
  • @Anunaki: You need to fix __all__ problems, not only the first one mentioned. Note that I even explicitly mentioned the second problem (failure to read proxies response) as **more importantly** since failure to address this will cause the TLS handshake to fail. – Steffen Ullrich Jan 10 '21 at 08:33