reqwest icon indicating copy to clipboard operation
reqwest copied to clipboard

Reqwest v0.12.20 failed when accessing ipv6 via SOCKS5 proxy

Open sigoden opened this issue 5 months ago • 11 comments

When using reqwest v0.12.20 to access a TLS v1.3 network through a SOCKS5 proxy, an error occurs.

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let client = reqwest::Client::builder()
    .proxy(reqwest::Proxy::all("socks5://127.0.0.1:1080")?)
    .build()?;
    let res = client.get("https://openrouter.ai/api/v1/models").send().await?;
    let data: serde_json::Value = res.json().await?;
    println!("{data}");
    Ok(())
}
[dependencies]
anyhow = "1"
serde_json = "1"
reqwest = { version = "0.12.20", features = ["json", "socks"] }
tokio = { version = "1", features = ["full"] }
Error: error sending request

Caused by:
    0: client error (Connect)
    1: invalid authority

If you downgrade reqwest to v0.12.19, it will work properly.

-reqwest = { version = "0.12.20", features = ["json", "socks"] }
+reqwest = { version = "=0.12.19", features = ["json", "socks"] }

sigoden avatar Jun 30 '25 01:06 sigoden

Maybe related to https://github.com/seanmonstar/reqwest/pull/2726/ and https://github.com/seanmonstar/reqwest/pull/2732

Xuanwo avatar Jun 30 '25 02:06 Xuanwo

I tried it on macOS and it worked fine. Maybe it's a dependency cache issue? I've already run cargo update

Image

0x676e67 avatar Jun 30 '25 13:06 0x676e67

I've tested it on macOS as well, and the same issue occurs. Image

Reqwest was upgraded to v0.12.21, but the bug still exists.

There's no issue with the SOCKS5. If you change the URL to one using TLS v1.2, such as (https://httpbin.org/ip), everything works fine.

sigoden avatar Jun 30 '25 23:06 sigoden

Are you able to turn on trace logs for reqwest?

seanmonstar avatar Jun 30 '25 23:06 seanmonstar

Image

2025-07-01T00:20:34.002121Z TRACE hyper_util::client::legacy::pool: checkout waiting for idle connection: ("https", openrouter.ai)
2025-07-01T00:20:34.002777Z TRACE hyper_util::client::legacy::pool: checkout dropped for ("https", openrouter.ai)
Error: error sending request for url (https://openrouter.ai/api/v1/models)

Caused by:
    0: client error (Connect)
    1: error connecting to socks proxy
    2: invalid authority

sigoden avatar Jul 01 '25 00:07 sigoden

Hm, reqwest uses just the log crate at the moment. But I think I see where the error may be coming from, it might be when the destination resolves to IPv6.

seanmonstar avatar Jul 01 '25 00:07 seanmonstar

Image

2025-07-01T00:20:34.002121Z TRACE hyper_util::client::legacy::pool: checkout waiting for idle connection: ("https", openrouter.ai)
2025-07-01T00:20:34.002777Z TRACE hyper_util::client::legacy::pool: checkout dropped for ("https", openrouter.ai)
Error: error sending request for url (https://openrouter.ai/api/v1/models)

Caused by:
    0: client error (Connect)
    1: error connecting to socks proxy
    2: invalid authority

Can you try socks5h? It helps to troubleshoot DNS resolution issues

0x676e67 avatar Jul 01 '25 00:07 0x676e67

socks5h did work Image

2025-07-01T00:33:07.545940Z TRACE hyper_util::client::legacy::pool: checkout waiting for idle connection: ("https", openrouter.ai)
2025-07-01T00:33:07.546018Z TRACE hyper_util::client::legacy::connect::http: Http::connect; scheme=Some("socks5h"), host=Some("127.0.0.1"), port=Some(Port(1080))
2025-07-01T00:33:07.546041Z DEBUG hyper_util::client::legacy::connect::http: connecting to 127.0.0.1:1080
2025-07-01T00:33:07.546166Z DEBUG hyper_util::client::legacy::connect::http: connected to 127.0.0.1:1080
2025-07-01T00:33:08.100522Z TRACE hyper_util::client::legacy::client: http1 handshake complete, spawning background dispatcher task
2025-07-01T00:33:08.100582Z TRACE hyper_util::client::legacy::client: waiting for connection to be ready
2025-07-01T00:33:08.100761Z TRACE hyper_util::client::legacy::client: connection is ready
2025-07-01T00:33:08.100798Z TRACE hyper_util::client::legacy::pool: checkout dropped for ("https", openrouter.ai)
2025-07-01T00:33:08.860793Z TRACE hyper_util::client::legacy::pool: put; add idle connection for ("https", openrouter.ai)
2025-07-01T00:33:08.860906Z DEBUG hyper_util::client::legacy::pool: pooling idle connection for ("https", openrouter.ai)
2025-07-01T00:33:08.862217Z TRACE hyper_util::client::legacy::pool: idle interval checking for expired
{"data":[{"architecture":{"input_modalities":["text"],"instruct_type":null,"modality":"text->text","output_modalities":["text"],"tokenizer":"Other"},"canonical_slug":"baidu/e

sigoden avatar Jul 01 '25 00:07 sigoden

Since I don't have an IPv6 environment. I looked through the code carefully. The source of the error may be due to an error in parsing the Uri: https://github.com/seanmonstar/reqwest/blob/b739726c4a2e47470346777062817af4f35feef2/src/connect.rs#L1309

Maybe you can debug the error point to solve the problem faster.

0x676e67 avatar Jul 01 '25 01:07 0x676e67

This should be a problem caused by converting IPv6 SocketAddr directly to String. URI requires [] to include...

mod tests {
    use http::Uri;
    use std::net::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};

    #[test]
    fn test_socketaddr_ip_to_uri_format() {
        let port = 8080;

        // IPv4 address: direct concatenation should parse successfully
        let ipv4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), port);
        let host = ipv4.ip().to_string();
        let uri = format!("http://{}:{}", host, port).parse::<Uri>();
        assert!(uri.is_ok(), "IPv4 direct concatenation should be parsed successfully");

        // IPv6 address without brackets: should fail to parse
        let ipv6 = SocketAddr::new(IpAddr::V6(Ipv6Addr::LOCALHOST), port);
        let host = ipv6.ip().to_string();
        let uri = format!("http://{}:{}", host, port).parse::<Uri>();
        assert!(uri.is_err(), "IPv6 without brackets should fail to parse");

        // IPv6 address with brackets: should parse successfully
        let host = format!("[{}]", ipv6.ip());
        let uri = format!("http://{}:{}", host, port).parse::<Uri>();
        assert!(uri.is_ok(), "IPv6 with brackets should be parsed successfully");
    }
}

0x676e67 avatar Jul 01 '25 01:07 0x676e67

#2753 solved the problem.

Image

sigoden avatar Jul 01 '25 01:07 sigoden