RST instead of FIN in hyper using CONNECT

Rust noob here.

I'm using a CONNECT proxy (using TLS and HTTP2) and then making a HTTP/1.1 (or even HTTP/2) request to the target server. This works fine but after the response, the connection is closed via RST rather than FIN. I have confirmed this with a packet capture.

I tried with 'Connection: close' header for the request to target and the connection was closed via FIN from the proxy server.

What is it that I'm doing wrong here? Any pointers are appreciated!
Ideally, I would like the client to send the TLS close notify to shutdown TLS session normally between the client and proxy and then close the TCP socket using FIN.

async fn fetch_url(_url: hyper::Uri) -> Result<()> {
    // connect to proxy first
    let mut root_cert_store = rustls::RootCertStore::empty();
    root_cert_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());

    let mut config = rustls::ClientConfig::builder()
        .with_root_certificates(root_cert_store)
        .with_no_client_auth();

    let mut dangerous_config = rustls::ClientConfig::dangerous(&mut config);
    dangerous_config.set_certificate_verifier(Arc::new(NoCertificateVerification::new(
        provider::default_provider(),
    )));

    let connector = TlsConnector::from(Arc::new(config));

    let stream = TcpStream::connect("localhost:8000").await?;

    let domain = pki_types::ServerName::try_from("localhost")
        .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid dnsname"))?
        .to_owned();

    let mut tls_stream = connector.connect(domain, stream).await?;
    let io = TokioIo::new(tls_stream);

    let executor = hyper_util::rt::tokio::TokioExecutor::new();
    let (mut sender, conn) = hyper::client::conn::http2::handshake::<
        TokioExecutor,
        TokioIo<tokio_rustls::client::TlsStream<tokio::net::TcpStream>>,
        Empty<Bytes>,
    >(executor, io)
    .await?;

    tokio::task::spawn(async move {
        if let Err(err) = conn.await {
            println!("Connection failed: {:?}", err);
        }
    });

    println!("bulding request");

    let req = Request::builder()
        .method(Method::CONNECT)
        .version(Version::HTTP_2)
        .uri("http://google.com:80")
        .body(Empty::<Bytes>::new())?;

    println!("sending request: {:?}", req);
    let res = sender.send_request(req).await?;

    println!("{:?}", res);

    let upgraded = hyper::upgrade::on(res).await?;

    println!("{:?}", upgraded);
    // send the actually request
    {
        let (mut sender, conn) = hyper::client::conn::http1::handshake(upgraded).await?;
        tokio::task::spawn(async move {
            if let Err(err) = conn.await {
                println!("Connection failed: {:?}", err);
            }
        });

        let url = hyper::Uri::from_static("http://google.com/");
        let authority = url.authority().unwrap().clone();

        let path = url.path();
        let req = Request::builder()
            .uri(path)
            .header(hyper::header::HOST, authority.as_str())
            .body(Empty::<Bytes>::new())?;

        let mut res = sender.send_request(req).await?;

        while let Some(next) = res.frame().await {
            let frame = next?;
            if let Some(chunk) = frame.data_ref() {
                io::stdout().write_all(&chunk).await?;
            }
        }
    }
    // connection resets here

    Ok(())
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.