Reqwest via httpS proxy fails

โš“ Rust    ๐Ÿ“… 2025-11-06    ๐Ÿ‘ค surdeus    ๐Ÿ‘๏ธ 6      

surdeus

In a simple setup to test reqwest with different proxies (http, https, socks5) and backends (native-tls, rust-tls), I get persistent errors with HTTPS proxies. With native-tls:

What doesnโ€™t work:

  1. HTTPS requests via HTTP and HTTPS proxies

What works:

  1. HTTP requests via HTTP and HTTPS proxies
  2. HTTP and HTTPS requests via SOCKS5 proxies
  3. HTTP and HTTPS requests without proxies

With rustls-tls, in addition to the above, I also get failing HTTP requests via SOCKS5 proxies.

When I try openssl s_client, it works.

When I use another python tool (httpie), everything works.

I am not sure if it is my configuration or reqwest itself. Any help would be greatly appreciated!

FYI:

Log (redacted)

[2025-11-06T12:03:39Z DEBUG reqwest::connect] starting new connection: https://thisismyip.com/
[2025-11-06T12:03:39Z DEBUG reqwest::connect] proxy(http://188.114.96.138/) intercepts 'https://thisismyip.com/'
[2025-11-06T12:03:39Z TRACE reqwest::connect] tunneling HTTPS over proxy
[2025-11-06T12:03:39Z TRACE reqwest::retry] shouldn't retry!
[2025-11-06T12:03:39Z ERROR hello_world] resp_https (via http proxy). CheckProxyError: error sending request for url (https://thisismyip.com/).

[2025-11-06T12:03:40Z DEBUG reqwest::connect] starting new connection: https://thisismyip.com/
[2025-11-06T12:03:40Z DEBUG reqwest::connect] proxy(http://188.114.96.138/) intercepts 'https://thisismyip.com/'
[2025-11-06T12:03:40Z TRACE reqwest::connect] tunneling HTTPS over proxy
[2025-11-06T12:03:40Z TRACE reqwest::retry] shouldn't retry!
[2025-11-06T12:03:40Z ERROR hello_world] resp_https (via HTTPS proxy). CheckProxyError: error sending request for url (https://thisismyip.com/).

Cargo.toml

[package]
name = "hello_world"
version = "0.1.0"
edition = "2024"

[dependencies]
reqwest = { version = "0.12.24", features = ["native-tls", "socks"] }
tokio = { version = "1.48.0", features = ["full"] }
log = "0.4.28"
env_logger = "0.11.8"
dotenvy = "0.15.7"

user@laptop:~$ openssl s_client -connect 84.17.47.148:9002
Connecting to 84.17.47.148
CONNECTED(00000003)
Can't use SSL_get_servername
depth=2 C=US, O=Internet Security Research Group, CN=ISRG Root X1
verify return:1
depth=1 C=US, O=Let's Encrypt, CN=R13
verify return:1
depth=0 CN=amsterdam-rack401.nodes.gen4.ninja
verify return:1
---

user@laptop:~$ https --json --proxy ``http://84.17.47.148:9002`` ``https://thisismyip.com/``
HTTP/1.1 200 OK
Alt-Svc: h3=":443"; ma=86400
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html; charset=UTF-8
Date: Thu, 06 Nov 2025 12:16:18 GMT
Server: nginx
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: PHP/8.4.14

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

My actual code:

use std::time::Duration;
use std::path::Path;
use dotenvy::dotenv;
use reqwest::{retry, Client, Proxy};
use log::{info, debug, trace, error};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    dotenvy::from_path(Path::new("src/.env"))?;
    //dotenv().expect(".env file not found!"); //Set environment variables from .env file
    env_logger::init(); //Initialize logging with env_logger

    make_request().await?;
    Ok(())
}

async fn make_request() -> Result<(), Box<dyn std::error::Error>> {
    // Basic HTTP proxy
    let proxy_url_http = "http://188.114.96.138:80";
    let proxy_url_https = "http://84.17.47.148:9002";
    let proxy_url_socks5 = "socks5://37.221.193.221:19138";

    let http_proxy = Proxy::all(proxy_url_http)?;
    let https_proxy = Proxy::all(proxy_url_https)?;
    let socks5_proxy = Proxy::all(proxy_url_socks5)?;

    let target_url_http = "http://httpforever.com/";
    let target_url_https = "https://thisismyip.com/";

    {
        //Request without proxy, to both URLs
        debug!("##### Request without proxy, to both URLs #####");

        let client = Client::builder()
            //.connection_verbose(true)
            .build()?;

        let mut resp_http = client.get(target_url_http).send().await?;
        let mut resp_https = client.get(target_url_https).send().await?;

        let mut text_http = resp_http.text().await.unwrap();
        let mut text_https = resp_https.text().await.unwrap();

        String::split_off(&mut text_http, 50);
        String::split_off(&mut text_https, 50);

        debug!("RESPONSE resp_http Chunk: [{}]", text_http);
        debug!("RESPONSE resp_https Chunk: [{}]", text_https);
    }
    {
        //Request via http proxy, to both URLs
        debug!("##### Request via HTTP proxy, to both URLs #####");

        let client = Client::builder()
            //.connection_verbose(true)
            .connect_timeout(Duration::from_secs(10))  // Time to establish connection
            .timeout(Duration::from_secs(60))          // Total request timeout
            .read_timeout(Duration::from_secs(30))     // Time to read response data
            .proxy(http_proxy)
            .build()?;

        let mut resp_http = client.get(target_url_http).send().await;

        match resp_http {
            Ok(resp) => {
                let mut text_http = resp.text().await.unwrap();
                let _ = String::split_off(&mut text_http, 50);
                debug!("RESPONSE resp_http Chunk (via http proxy): [{}]", text_http);
            },
            Err(e) => {
                error!("resp_http (via http proxy). CheckProxyError: {}.",e);
            },
        }

        let mut resp_https = client.get(target_url_https).send().await;

        match resp_https {
            Ok(resp) => {
                let mut text_https = resp.text().await.unwrap();
                let _ = String::split_off(&mut text_https, 50);
                debug!("RESPONSE resp_https Chunk (via http proxy): [{}]", text_https);
            },
            Err(e) => {
                error!("resp_https (via http proxy). CheckProxyError: {}.",e);
            },
        }
    }
    {
        //Request via https proxy, to both URLs
        debug!("##### Request via HTTPS proxy, to both URLs #####");
       
        let client = Client::builder()
            //.connection_verbose(true)
            .connect_timeout(Duration::from_secs(10))  // Time to establish connection
            .timeout(Duration::from_secs(60))          // Total request timeout
            .read_timeout(Duration::from_secs(30))     // Time to read response data
            .proxy(https_proxy)
            .build()?;

        let mut resp_http = client.get(target_url_http).send().await;
        match resp_http {
            Ok(resp)  => {
                let mut text_http = resp.text().await.unwrap();
                let _ = String::split_off(&mut text_http, 50);
                debug!("RESPONSE resp_http Chunk (via HTTPS proxy): [{}]", text_http);
            },
            Err(e) => {
                error!("resp_http (via HTTPS proxy). CheckProxyError: {}.",e);
            },
        }

        let mut resp_https = client.get(target_url_https).send().await;
        match resp_https {
            Ok(resp)  => {
                let mut text_https = resp.text().await.unwrap();
                let _ = String::split_off(&mut text_https, 50);
                debug!("RESPONSE resp_https Chunk (via HTTPS proxy): [{}]", text_https);
            },
            Err(e) => {
                error!("resp_https (via HTTPS proxy). CheckProxyError: {}.",e);
            },
        }
    }
    {
        //Request via socks5 proxy, to both URLs
        debug!("##### Request via socks5 proxy, to both URLs #####");

        let client = Client::builder()
            //.connection_verbose(true)
            .connect_timeout(Duration::from_secs(10))  // Time to establish connection
            .timeout(Duration::from_secs(60))          // Total request timeout
            .read_timeout(Duration::from_secs(30))     // Time to read response data
            .proxy(socks5_proxy)
            .build()?;

        let mut resp_http = client.get(target_url_http).send().await;
        match resp_http {
            Ok(resp)  => {
                let mut text_http = resp.text().await.unwrap();
                let _ = String::split_off(&mut text_http, 50);
                debug!("RESPONSE resp_http Chunk (via socks5 proxy): [{}]", text_http);
            },
            Err(e) => {
                error!("resp_http (via socks5 proxy). CheckProxyError: {}.",e);
            },
        }

        let mut resp_https = client.get(target_url_https).send().await;
        match resp_https {
            Ok(resp)  => {
                let mut text_https = resp.text().await.unwrap();
                let _ = String::split_off(&mut text_https, 50);
                debug!("RESPONSE resp_https Chunk (via socks5 proxy): [{}]", text_https);
            },
            Err(e) => {
                error!("resp_https (via socks5 proxy). CheckProxyError: {}.",e);
            },
        }
    }
    Ok(())
}

2 posts - 2 participants

Read full topic

๐Ÿท๏ธ Rust_feed