From b097c2caa2a88703879349f1bfbf5dfa55d3cc71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jind=C5=99ich=20B=C3=A4r?= Date: Thu, 28 May 2026 16:00:53 +0200 Subject: [PATCH 1/2] fix(deps): migrate http3 DNS lookup from hickory-client to hickory-resolver hickory-client is being retired (subsumed into hickory-net per the 0.26 release notes) and never received a stable 0.26 release, which kept us pinned to hickory-proto 0.25.x and exposed to RUSTSEC-2026-0119 and RUSTSEC-2026-0120 plus the NSEC3 unbounded-loop advisory. Switching http3.rs to hickory-resolver 0.26.1 pulls in patched hickory-proto and drops the hard-coded 8.8.8.8 nameserver in favour of the system resolver config. --- Cargo.lock | 283 ++++++++++++++++++++++++++++++++++++--------- impit/Cargo.toml | 4 +- impit/src/http3.rs | 79 +++---------- 3 files changed, 247 insertions(+), 119 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a76b8802..88196a7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -330,6 +330,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core 0.10.1", +] + [[package]] name = "cmake" version = "0.1.57" @@ -442,6 +453,15 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -457,6 +477,24 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -673,24 +711,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "endian-type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" - -[[package]] -name = "enum-as-inner" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "equivalent" version = "1.0.2" @@ -926,6 +946,7 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -1021,49 +1042,75 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] -name = "hickory-client" -version = "0.25.2" +name = "hickory-net" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c466cd63a4217d5b2b8e32f23f58312741ce96e3c84bf7438677d2baff0fc555" +checksum = "e2295ed2f9c31e471e1428a8f88a3f0e1f4b27c15049592138d1eebe9c35b183" dependencies = [ + "async-trait", "cfg-if", "data-encoding", "futures-channel", + "futures-io", "futures-util", "hickory-proto", - "once_cell", - "radix_trie", - "rand", + "idna", + "ipnet", + "jni 0.22.4", + "rand 0.10.1", "thiserror 2.0.18", + "tinyvec", "tokio", "tracing", + "url", ] [[package]] name = "hickory-proto" -version = "0.25.2" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +checksum = "0bab31817bfb44672a252e97fe81cd0c18d1b2cf892108922f6818820df8c643" dependencies = [ - "async-trait", - "cfg-if", "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", "idna", "ipnet", + "jni 0.22.4", "once_cell", - "rand", + "prefix-trie", + "rand 0.10.1", "ring", "thiserror 2.0.18", "tinyvec", - "tokio", "tracing", "url", ] +[[package]] +name = "hickory-resolver" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d58d28879ceecde6607729660c2667a081ccdc082e082675042793960f178c" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-net", + "hickory-proto", + "ipconfig", + "ipnet", + "jni 0.22.4", + "moka", + "ndk-context", + "once_cell", + "parking_lot", + "rand 0.10.1", + "resolv-conf", + "smallvec", + "system-configuration", + "thiserror 2.0.18", + "tokio", + "tracing", +] + [[package]] name = "http" version = "1.4.0" @@ -1278,14 +1325,14 @@ name = "impit" version = "0.1.0" dependencies = [ "encoding", - "hickory-client", "hickory-proto", + "hickory-resolver", "hyper", "hyper-util", "log", "lol_html", "mime", - "rand", + "rand 0.9.4", "reqwest", "rustls", "rustls-platform-verifier", @@ -1344,11 +1391,27 @@ dependencies = [ "serde_core", ] +[[package]] +name = "ipconfig" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" +dependencies = [ + "socket2", + "widestring", + "windows-registry", + "windows-result", + "windows-sys 0.61.2", +] + [[package]] name = "ipnet" version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +dependencies = [ + "serde", +] [[package]] name = "itoa" @@ -1372,6 +1435,36 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn", +] + [[package]] name = "jni-sys" version = "0.3.1" @@ -1545,6 +1638,23 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "moka" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "equivalent", + "parking_lot", + "portable-atomic", + "smallvec", + "tagptr", + "uuid", +] + [[package]] name = "napi" version = "3.8.4" @@ -1606,19 +1716,16 @@ dependencies = [ ] [[package]] -name = "new_debug_unreachable" -version = "1.0.6" +name = "ndk-context" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] -name = "nibble_vec" -version = "0.1.0" +name = "new_debug_unreachable" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" -dependencies = [ - "smallvec", -] +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nohash-hasher" @@ -1632,6 +1739,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -1815,6 +1931,17 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "prefix-trie" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cf6e3177f0684016a5c209b00882e15f8bdd3f3bb48f0491df10cd102d0c6e7" +dependencies = [ + "either", + "ipnet", + "num-traits", +] + [[package]] name = "prettyplease" version = "0.2.37" @@ -1967,7 +2094,7 @@ dependencies = [ "bytes", "getrandom 0.3.4", "lru-slab", - "rand", + "rand 0.9.4", "ring", "rustc-hash", "rustls", @@ -2015,23 +2142,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] -name = "radix_trie" -version = "0.2.1" +name = "rand" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ - "endian-type", - "nibble_vec", + "rand_chacha", + "rand_core 0.9.5", ] [[package]] name = "rand" -version = "0.9.4" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ - "rand_chacha", - "rand_core", + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", ] [[package]] @@ -2041,7 +2169,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.5", ] [[package]] @@ -2053,6 +2181,12 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "redox_syscall" version = "0.5.18" @@ -2109,6 +2243,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "resolv-conf" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" + [[package]] name = "ring" version = "0.17.14" @@ -2198,7 +2338,7 @@ checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", - "jni", + "jni 0.21.1", "log", "once_cell", "rustls", @@ -2314,6 +2454,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", + "serde_derive", ] [[package]] @@ -2380,6 +2521,22 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" version = "1.0.2" @@ -2472,6 +2629,12 @@ dependencies = [ "libc", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "target-lexicon" version = "0.13.5" @@ -2959,6 +3122,12 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + [[package]] name = "winapi-util" version = "0.1.11" diff --git a/impit/Cargo.toml b/impit/Cargo.toml index d40371ba..3c842817 100644 --- a/impit/Cargo.toml +++ b/impit/Cargo.toml @@ -7,8 +7,8 @@ edition = "2021" [dependencies] encoding = "0.2.33" -hickory-client = "0.25.1" -hickory-proto = "0.25.1" +hickory-proto = "0.26.1" +hickory-resolver = "0.26.1" log = "0.4.22" mime = "0.3.17" reqwest = { version="0.13.1", features = ["json", "gzip", "brotli", "zstd", "deflate", "http3", "cookies", "stream", "socks"] } diff --git a/impit/src/http3.rs b/impit/src/http3.rs index e911d1c8..3d12823b 100644 --- a/impit/src/http3.rs +++ b/impit/src/http3.rs @@ -1,24 +1,16 @@ use std::collections::HashMap; use std::sync::Arc; -use tokio::sync::{Mutex, RwLock}; +use tokio::sync::RwLock; use hickory_proto::rr::rdata::svcb::SvcParamValue; -use hickory_proto::rr::{Name, RData}; -use hickory_proto::runtime::TokioRuntimeProvider; -use hickory_proto::ProtoError; - -use hickory_client::client::{Client, ClientHandle}; -use hickory_client::proto::runtime::iocompat::AsyncIoTokioAsStd; -use hickory_client::proto::tcp::TcpClientStream; +use hickory_proto::rr::{Name, RData, RecordType}; +use hickory_resolver::TokioResolver; use log::debug; -use tokio::net::TcpStream as TokioTcpStream; /// A struct encapsulating the components required to make HTTP/3 requests. pub struct H3Engine { - /// The DNS client used to resolve DNS queries. - client: Arc>>, - /// The background task that processes DNS queries. - bg_join_handle: Option>>, + /// The DNS resolver used to query HTTPS records for h3 discovery. + resolver: Option, /// A map of hosts that support HTTP/3. /// /// This is populated by the DNS queries and manual calls to `set_h3_support` (based on the `Alt-Svc` header). @@ -28,33 +20,17 @@ pub struct H3Engine { impl H3Engine { pub async fn init() -> Self { - // todo: use the DNS server from the system config - let (stream, sender) = TcpClientStream::>::new( - ([8, 8, 8, 8], 53).into(), - None, - None, - TokioRuntimeProvider::new(), - ); - let client_result = Client::new(stream, sender, None).await; - - match client_result { - Ok((client, bg)) => { - let bg_join_handle = tokio::spawn(bg); - - H3Engine { - client: Arc::new(Some(Mutex::new(client))), - bg_join_handle: Some(bg_join_handle), - h3_alt_svc: Arc::new(RwLock::new(HashMap::new())), - } - } + let resolver = match TokioResolver::builder_tokio().and_then(|builder| builder.build()) { + Ok(resolver) => Some(resolver), Err(err) => { - debug!("Failed to create DNS client for HTTP3 resolution: {}", err); - H3Engine { - client: Arc::new(None), - bg_join_handle: None, - h3_alt_svc: Arc::new(RwLock::new(HashMap::new())), - } + debug!("Failed to create DNS resolver for HTTP3 resolution: {}", err); + None } + }; + + H3Engine { + resolver, + h3_alt_svc: Arc::new(RwLock::new(HashMap::new())), } } @@ -71,23 +47,14 @@ impl H3Engine { Err(_) => return false, }; - if let Some(client) = self.client.as_ref() { - let response = { - let mut client = client.lock().await; - client - .query( - domain_name, - hickory_proto::rr::DNSClass::IN, - hickory_proto::rr::RecordType::HTTPS, - ) - .await - }; + if let Some(resolver) = self.resolver.as_ref() { + let response = resolver.lookup(domain_name, RecordType::HTTPS).await; let dns_h3_support = response.is_ok_and(|response| { response.answers().iter().any(|answer| { - if let RData::HTTPS(data) = answer.data() { - return data.svc_params().iter().any(|param| { - if let SvcParamValue::Alpn(alpn_protocols) = param.1.clone() { + if let RData::HTTPS(data) = &answer.data { + return data.0.svc_params.iter().any(|param| { + if let SvcParamValue::Alpn(alpn_protocols) = ¶m.1 { return alpn_protocols.0.iter().any(|alpn| alpn == "h3"); } @@ -115,11 +82,3 @@ impl H3Engine { cache.insert(host.to_owned(), supports_h3); } } - -impl Drop for H3Engine { - fn drop(&mut self) { - if let Some(join_handle) = self.bg_join_handle.as_ref() { - join_handle.abort(); - } - } -} From b98b2bb6864085b68fa6ff84032476cf653e6880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jind=C5=99ich=20B=C3=A4r?= Date: Thu, 28 May 2026 16:06:39 +0200 Subject: [PATCH 2/2] chore: run formatter --- impit/src/http3.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/impit/src/http3.rs b/impit/src/http3.rs index 3d12823b..0cefa059 100644 --- a/impit/src/http3.rs +++ b/impit/src/http3.rs @@ -23,7 +23,10 @@ impl H3Engine { let resolver = match TokioResolver::builder_tokio().and_then(|builder| builder.build()) { Ok(resolver) => Some(resolver), Err(err) => { - debug!("Failed to create DNS resolver for HTTP3 resolution: {}", err); + debug!( + "Failed to create DNS resolver for HTTP3 resolution: {}", + err + ); None } };