From 495b01e507869c19755cfab9aff4c615ae6b8a75 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 26 Apr 2026 05:13:47 +0000 Subject: [PATCH 1/3] fix(deps): update rust crate hickory-resolver to 0.26 --- Cargo.lock | 177 ++++++++++++++++++++------ crates/shadowsocks-service/Cargo.toml | 2 +- crates/shadowsocks/Cargo.toml | 2 +- 3 files changed, 137 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2e330c89b989..8f94c138bfe2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -948,18 +948,6 @@ dependencies = [ "cfg-if", ] -[[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 = "env_filter" version = "1.0.0" @@ -1294,9 +1282,9 @@ dependencies = [ [[package]] name = "h3" -version = "0.0.7" +version = "0.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfb059a4f28a66f186ed16ad912d142f490676acba59353831d7cb45a96b0d3" +checksum = "10872b55cfb02a821b69dc7cf8dc6a71d6af25eb9a79662bec4a9d016056b3be" dependencies = [ "bytes", "fastrand", @@ -1308,9 +1296,9 @@ dependencies = [ [[package]] name = "h3-quinn" -version = "0.0.9" +version = "0.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d482318ae94198fc8e3cbb0b7ba3099c865d744e6ec7c62039ca7b6b6c66fbf" +checksum = "8b2e732c8d91a74731663ac8479ab505042fbf547b9a207213ab7fbcbfc4f8b4" dependencies = [ "bytes", "futures", @@ -1367,65 +1355,89 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] -name = "hickory-proto" -version = "0.25.2" +name = "hickory-net" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +checksum = "0c61c8db47fae51ba9f8f2a2748bd87542acfbe22f2ec9cf9c8ec72d1ee6e9a6" dependencies = [ "async-trait", "bytes", "cfg-if", "data-encoding", - "enum-as-inner", "futures-channel", "futures-io", "futures-util", "h2", "h3", "h3-quinn", + "hickory-proto", "http", "idna", "ipnet", - "once_cell", + "jni 0.22.4", "pin-project-lite", "quinn", - "rand 0.9.4", - "ring", + "rand 0.10.1", "rustls", - "serde", "thiserror 2.0.18", "tinyvec", "tokio", "tokio-rustls", "tracing", "url", - "webpki-roots 0.26.11", + "webpki-roots", +] + +[[package]] +name = "hickory-proto" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a916d0494600d99ecb15aadfab677ad97c4de559e8f1af0c129353a733ac1fcc" +dependencies = [ + "data-encoding", + "idna", + "ipnet", + "jni 0.22.4", + "once_cell", + "prefix-trie", + "rand 0.10.1", + "ring", + "serde", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "url", ] [[package]] name = "hickory-resolver" -version = "0.25.2" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" +checksum = "a10bd64d950b4d38ca21e25c8ae230712e4955fb8290cfcb29a5e5dc6017e544" dependencies = [ "cfg-if", "futures-util", + "hickory-net", "hickory-proto", "ipconfig", + "ipnet", + "jni 0.22.4", "moka", + "ndk-context", "once_cell", "parking_lot", "quinn", - "rand 0.9.4", + "rand 0.10.1", "resolv-conf", "rustls", "serde", "smallvec", + "system-configuration 0.7.0", "thiserror 2.0.18", "tokio", "tokio-rustls", "tracing", - "webpki-roots 0.26.11", + "webpki-roots", ] [[package]] @@ -1554,7 +1566,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "socket2 0.6.3", - "system-configuration", + "system-configuration 0.6.1", "tokio", "tower-service", "tracing", @@ -1751,6 +1763,9 @@ name = "ipnet" version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +dependencies = [ + "serde", +] [[package]] name = "iprange" @@ -1845,19 +1860,68 @@ dependencies = [ "cesu8", "cfg-if", "combine", - "jni-sys", + "jni-sys 0.3.0", "log", "thiserror 1.0.69", "walkdir", "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.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "jobserver" version = "0.1.34" @@ -2192,6 +2256,12 @@ dependencies = [ "tempfile", ] +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + [[package]] name = "nix" version = "0.31.2" @@ -2518,6 +2588,17 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prefix-trie" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23370be78b7e5bcbb0cab4a02047eb040279a693c78daad04c2c5f1c24a83503" +dependencies = [ + "either", + "ipnet", + "num-traits", +] + [[package]] name = "prettyplease" version = "0.2.37" @@ -2945,7 +3026,7 @@ checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", - "jni", + "jni 0.21.1", "log", "once_cell", "rustls", @@ -3331,7 +3412,7 @@ dependencies = [ "trait-variant", "tun", "url", - "webpki-roots 1.0.7", + "webpki-roots", "windows-sys 0.61.2", "zstd", ] @@ -3373,6 +3454,16 @@ 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" @@ -3561,6 +3652,17 @@ dependencies = [ "system-configuration-sys", ] +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.9.4", + "system-configuration-sys", +] + [[package]] name = "system-configuration-sys" version = "0.6.0" @@ -4264,15 +4366,6 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "webpki-roots" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" -dependencies = [ - "webpki-roots 1.0.7", -] - [[package]] name = "webpki-roots" version = "1.0.7" diff --git a/crates/shadowsocks-service/Cargo.toml b/crates/shadowsocks-service/Cargo.toml index 31e43fab9ebf..b03dfc77710e 100644 --- a/crates/shadowsocks-service/Cargo.toml +++ b/crates/shadowsocks-service/Cargo.toml @@ -165,7 +165,7 @@ http-body-util = { version = "0.1", optional = true } http = { version = "1.1", optional = true } httparse = { version = "1.9", optional = true } -hickory-resolver = { version = "0.25", optional = true, features = ["serde"] } +hickory-resolver = { version = "0.26", optional = true, features = ["serde"] } idna = "1.0" ipnet = "2.10" diff --git a/crates/shadowsocks/Cargo.toml b/crates/shadowsocks/Cargo.toml index ca6928e25415..3246c38ae688 100644 --- a/crates/shadowsocks/Cargo.toml +++ b/crates/shadowsocks/Cargo.toml @@ -86,7 +86,7 @@ tokio = { version = "1.9.0", features = [ "time", ] } -hickory-resolver = { version = "0.25", optional = true } +hickory-resolver = { version = "0.26", optional = true } arc-swap = { version = "1.7", optional = true } notify = { version = "8.0", optional = true } From cf7b54b233d98be881ec7f4c40f3f959e1bc2a91 Mon Sep 17 00:00:00 2001 From: zonyitoo Date: Sun, 26 Apr 2026 23:40:29 +0800 Subject: [PATCH 2/3] fix: compat hickory-resolver 0.26 --- crates/shadowsocks-service/src/config.rs | 57 ++++++---- crates/shadowsocks-service/src/dns/mod.rs | 4 +- .../src/local/dns/client_cache.rs | 12 +- .../src/local/dns/dns_resolver.rs | 27 +++-- .../src/local/dns/server.rs | 104 +++++++++--------- .../src/local/dns/upstream.rs | 57 +++++++--- .../src/local/fake_dns/processor.rs | 16 ++- .../src/local/fake_dns/tcp_server.rs | 15 ++- .../src/local/fake_dns/udp_server.rs | 12 +- .../src/dns_resolver/hickory_dns_resolver.rs | 44 ++++---- .../shadowsocks/src/dns_resolver/resolver.rs | 16 ++- 11 files changed, 211 insertions(+), 153 deletions(-) diff --git a/crates/shadowsocks-service/src/config.rs b/crates/shadowsocks-service/src/config.rs index 644b48c94aad..54933ad9cf77 100644 --- a/crates/shadowsocks-service/src/config.rs +++ b/crates/shadowsocks-service/src/config.rs @@ -59,7 +59,7 @@ use std::{ use cfg_if::cfg_if; #[cfg(feature = "hickory-dns")] -use hickory_resolver::config::{NameServerConfig, ResolverConfig}; +use hickory_resolver::config::{ConnectionConfig, NameServerConfig, ResolverConfig}; #[cfg(feature = "local-tun")] use ipnet::IpNet; #[cfg(feature = "local-fake-dns")] @@ -2655,31 +2655,34 @@ impl Config { /// 1. `[(unix|tcp|udp)://]host[:port][,host[:port]]...` /// 2. Pre-defined. Like `google`, `cloudflare` pub fn set_dns_formatted(&mut self, dns: &str) -> Result<(), Error> { + #[cfg(feature = "hickory-dns")] + use hickory_resolver::config::{CLOUDFLARE, GOOGLE, QUAD9}; + self.dns = match dns { "system" => DnsConfig::System, #[cfg(feature = "hickory-dns")] - "google" => DnsConfig::HickoryDns(ResolverConfig::google()), + "google" => DnsConfig::HickoryDns(ResolverConfig::udp_and_tcp(&GOOGLE)), #[cfg(all(feature = "hickory-dns", feature = "dns-over-tls"))] - "google_tls" => DnsConfig::HickoryDns(ResolverConfig::google_tls()), + "google_tls" => DnsConfig::HickoryDns(ResolverConfig::tls(&GOOGLE)), #[cfg(all(feature = "hickory-dns", feature = "dns-over-https"))] - "google_https" => DnsConfig::HickoryDns(ResolverConfig::google_https()), + "google_https" => DnsConfig::HickoryDns(ResolverConfig::https(&GOOGLE)), #[cfg(all(feature = "hickory-dns", feature = "dns-over-h3"))] - "google_h3" => DnsConfig::HickoryDns(ResolverConfig::google_h3()), + "google_h3" => DnsConfig::HickoryDns(ResolverConfig::h3(&GOOGLE)), #[cfg(feature = "hickory-dns")] - "cloudflare" => DnsConfig::HickoryDns(ResolverConfig::cloudflare()), + "cloudflare" => DnsConfig::HickoryDns(ResolverConfig::udp_and_tcp(&CLOUDFLARE)), #[cfg(all(feature = "hickory-dns", feature = "dns-over-tls"))] - "cloudflare_tls" => DnsConfig::HickoryDns(ResolverConfig::cloudflare_tls()), + "cloudflare_tls" => DnsConfig::HickoryDns(ResolverConfig::tls(&CLOUDFLARE)), #[cfg(all(feature = "hickory-dns", feature = "dns-over-https"))] - "cloudflare_https" => DnsConfig::HickoryDns(ResolverConfig::cloudflare_https()), + "cloudflare_https" => DnsConfig::HickoryDns(ResolverConfig::https(&CLOUDFLARE)), #[cfg(feature = "hickory-dns")] - "quad9" => DnsConfig::HickoryDns(ResolverConfig::quad9()), + "quad9" => DnsConfig::HickoryDns(ResolverConfig::udp_and_tcp(&QUAD9)), #[cfg(all(feature = "hickory-dns", feature = "dns-over-tls"))] - "quad9_tls" => DnsConfig::HickoryDns(ResolverConfig::quad9_tls()), + "quad9_tls" => DnsConfig::HickoryDns(ResolverConfig::tls(&QUAD9)), #[cfg(all(feature = "hickory-dns", feature = "dns-over-https"))] - "quad9_https" => DnsConfig::HickoryDns(ResolverConfig::quad9_https()), + "quad9_https" => DnsConfig::HickoryDns(ResolverConfig::https(&QUAD9)), nameservers => self.parse_dns_nameservers(nameservers)?, }; @@ -2689,8 +2692,6 @@ impl Config { #[cfg(any(feature = "hickory-dns", feature = "local-dns"))] fn parse_dns_nameservers(&mut self, nameservers: &str) -> Result { - use hickory_resolver::proto::xfer::Protocol; - #[cfg(all(unix, feature = "local-dns"))] if let Some(nameservers) = nameservers.strip_prefix("unix://") { // A special DNS server only for shadowsocks-android @@ -2739,7 +2740,7 @@ impl Config { // // For example: // `192.168.1.100,192.168.1.101,3.4.5.6` - let mut c = ResolverConfig::new(); + let mut nameservers_config = Vec::new(); for part in nameservers.split(',') { let socket_addr = if let Ok(socket_addr) = part.parse::() { socket_addr @@ -2754,20 +2755,30 @@ impl Config { return Err(e); }; - if protocol.enable_udp() { - let ns_config = NameServerConfig::new(socket_addr, Protocol::Udp); - c.add_name_server(ns_config); - } - if protocol.enable_tcp() { - let ns_config = NameServerConfig::new(socket_addr, Protocol::Tcp); - c.add_name_server(ns_config); + if protocol.enable_tcp() && protocol.enable_udp() { + let mut tcp_config = ConnectionConfig::tcp(); + tcp_config.port = socket_addr.port(); + let mut udp_config = ConnectionConfig::udp(); + udp_config.port = socket_addr.port(); + let ns_config = NameServerConfig::new(socket_addr.ip(), true, vec![tcp_config, udp_config]); + nameservers_config.push(ns_config); + } else if protocol.enable_udp() { + let mut udp_config = ConnectionConfig::udp(); + udp_config.port = socket_addr.port(); + let ns_config = NameServerConfig::new(socket_addr.ip(), true, vec![udp_config]); + nameservers_config.push(ns_config); + } else if protocol.enable_tcp() { + let mut tcp_config = ConnectionConfig::tcp(); + tcp_config.port = socket_addr.port(); + let ns_config = NameServerConfig::new(socket_addr.ip(), true, vec![tcp_config]); + nameservers_config.push(ns_config); } } - Ok(if c.name_servers().is_empty() { + Ok(if nameservers_config.is_empty() { DnsConfig::System } else { - DnsConfig::HickoryDns(c) + DnsConfig::HickoryDns(ResolverConfig::from_parts(None, vec![], nameservers_config)) }) } diff --git a/crates/shadowsocks-service/src/dns/mod.rs b/crates/shadowsocks-service/src/dns/mod.rs index 048915f1c5b5..aef20b609e4e 100644 --- a/crates/shadowsocks-service/src/dns/mod.rs +++ b/crates/shadowsocks-service/src/dns/mod.rs @@ -33,7 +33,7 @@ pub async fn build_dns_resolver( let mut opts_opt = None; if let Some(dns_cache_size) = dns_cache_size { let mut opts = ResolverOpts::default(); - opts.cache_size = dns_cache_size; + opts.cache_size = dns_cache_size as u64; opts_opt = Some(opts); } @@ -59,7 +59,7 @@ pub async fn build_dns_resolver( let mut opts_opt = None; if let Some(dns_cache_size) = dns_cache_size { let mut opts = ResolverOpts::default(); - opts.cache_size = dns_cache_size; + opts.cache_size = dns_cache_size as u64; opts_opt = Some(opts); } diff --git a/crates/shadowsocks-service/src/local/dns/client_cache.rs b/crates/shadowsocks-service/src/local/dns/client_cache.rs index ef5f0e3a296b..1ccb53366ae9 100644 --- a/crates/shadowsocks-service/src/local/dns/client_cache.rs +++ b/crates/shadowsocks-service/src/local/dns/client_cache.rs @@ -10,7 +10,7 @@ use std::{ time::Duration, }; -use hickory_resolver::proto::{ProtoError, op::Message}; +use hickory_resolver::proto::op::Message; use log::{debug, trace}; use tokio::sync::Mutex; @@ -18,7 +18,7 @@ use shadowsocks::{config::ServerConfig, net::ConnectOpts, relay::socks5::Address use crate::local::context::ServiceContext; -use super::upstream::DnsClient; +use super::upstream::{DnsClient, DnsClientResult}; #[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] enum DnsClientKey { @@ -51,7 +51,7 @@ impl DnsClientCache { msg: Message, connect_opts: &ConnectOpts, is_udp: bool, - ) -> Result { + ) -> DnsClientResult { let key = match is_udp { true => DnsClientKey::UdpLocal(ns), false => DnsClientKey::TcpLocal(ns), @@ -66,7 +66,7 @@ impl DnsClientCache { ns: &Address, msg: Message, is_udp: bool, - ) -> Result { + ) -> DnsClientResult { let key = match is_udp { true => DnsClientKey::UdpRemote(ns.clone()), false => DnsClientKey::TcpRemote(ns.clone()), @@ -75,7 +75,7 @@ impl DnsClientCache { } #[cfg(unix)] - pub async fn lookup_unix_stream>(&self, ns: &P, msg: Message) -> Result { + pub async fn lookup_unix_stream>(&self, ns: &P, msg: Message) -> DnsClientResult { let mut last_err = None; for _ in 0..self.retry_count { @@ -113,7 +113,7 @@ impl DnsClientCache { connect_opts: Option<&ConnectOpts>, context: Option<&ServiceContext>, svr_cfg: Option<&ServerConfig>, - ) -> Result { + ) -> DnsClientResult { let mut last_err = None; for _ in 0..self.retry_count { let create_fn = async { diff --git a/crates/shadowsocks-service/src/local/dns/dns_resolver.rs b/crates/shadowsocks-service/src/local/dns/dns_resolver.rs index e328fd994711..20d12750c399 100644 --- a/crates/shadowsocks-service/src/local/dns/dns_resolver.rs +++ b/crates/shadowsocks-service/src/local/dns/dns_resolver.rs @@ -76,7 +76,7 @@ impl DnsResolver { { Ok(msg) => return Ok(msg), Err(err) => { - last_err = err.into(); + last_err = io::Error::new(io::ErrorKind::Other, err); } } } @@ -85,7 +85,7 @@ impl DnsResolver { match self.client_cache.lookup_local(ns, msg, &self.connect_opts, false).await { Ok(msg) => return Ok(msg), Err(err) => { - last_err = err.into(); + last_err = io::Error::new(io::ErrorKind::Other, err); } } } @@ -98,14 +98,17 @@ impl DnsResolver { .client_cache .lookup_unix_stream(path, msg) .await - .map_err(From::from), + .map_err(|err| io::Error::new(io::ErrorKind::Other, err)), } } } impl DnsResolve for DnsResolver { async fn resolve(&self, host: &str, port: u16) -> io::Result> { - let mut name = Name::from_utf8(host)?; + let mut name = match Name::from_utf8(host) { + Ok(name) => name, + Err(err) => return Err(io::Error::new(ErrorKind::InvalidInput, err)), + }; name.set_fqdn(true); let mut queryv4 = Query::new(); @@ -116,12 +119,12 @@ impl DnsResolve for DnsResolver { queryv4.set_query_type(RecordType::A); queryv6.set_query_type(RecordType::AAAA); - let mut msgv4 = Message::new(); - msgv4.set_recursion_desired(true); + let mut msgv4 = Message::query(); + msgv4.metadata.recursion_desired = true; msgv4.add_query(queryv4); - let mut msgv6 = Message::new(); - msgv6.set_recursion_desired(true); + let mut msgv6 = Message::query(); + msgv6.metadata.recursion_desired = true; msgv6.add_query(queryv6); match future::join(self.lookup(msgv4), self.lookup(msgv6)).await { @@ -171,10 +174,10 @@ impl DnsResolve for DnsResolver { fn store_dns(res: Message, port: u16) -> Vec { let mut vaddr = Vec::new(); - for record in res.answers() { - match record.data() { - RData::A(addr) => vaddr.push(SocketAddr::new(Ipv4Addr::from(*addr).into(), port)), - RData::AAAA(addr) => vaddr.push(SocketAddr::new(Ipv6Addr::from(*addr).into(), port)), + for record in res.answers { + match record.data { + RData::A(addr) => vaddr.push(SocketAddr::new(Ipv4Addr::from(addr).into(), port)), + RData::AAAA(addr) => vaddr.push(SocketAddr::new(Ipv6Addr::from(addr).into(), port)), rdata => { trace!("skipped rdata {:?}", rdata); } diff --git a/crates/shadowsocks-service/src/local/dns/server.rs b/crates/shadowsocks-service/src/local/dns/server.rs index 72e6a2f52b97..9a2ca1cb7dcf 100644 --- a/crates/shadowsocks-service/src/local/dns/server.rs +++ b/crates/shadowsocks-service/src/local/dns/server.rs @@ -19,7 +19,7 @@ use futures::{ future::{self, Either}, }; use hickory_resolver::proto::{ - op::{Message, OpCode, Query, header::MessageType, response_code::ResponseCode}, + op::{Message, MessageType, OpCode, Query, ResponseCode}, rr::{DNSClass, Name, RData, RecordType}, }; use log::{debug, error, info, trace, warn}; @@ -321,7 +321,7 @@ impl DnsTcpServer { Ok(m) => m, Err(err) => { error!("dns tcp {} parse message failed, error: {}", peer_addr, err); - return Err(err.into()); + return Err(io::Error::new(io::ErrorKind::Other, err)); } }; @@ -329,11 +329,14 @@ impl DnsTcpServer { Ok(m) => m, Err(err) => { error!("dns tcp {} lookup error: {}", peer_addr, err); - return Err(err); + return Err(io::Error::new(io::ErrorKind::Other, err)); } }; - let mut buf = respond_message.to_vec()?; + let mut buf = match respond_message.to_vec() { + Ok(buf) => buf, + Err(err) => return Err(io::Error::new(io::ErrorKind::Other, err)), + }; let length = buf.len(); buf.resize(length + 2, 0); buf.copy_within(..length, 2); @@ -480,7 +483,10 @@ impl DnsUdpServer { } }; - let buf = respond_message.to_vec()?; + let buf = match respond_message.to_vec() { + Ok(buf) => buf, + Err(err) => return Err(io::Error::new(io::ErrorKind::Other, err)), + }; listener.send_to(&buf, peer_addr).await?; Ok(()) @@ -639,10 +645,10 @@ fn should_forward_by_response( if let Some(acl) = acl { if let Ok(local_response) = local_response { let mut names = HashSet::new(); - names.insert(query.name()); + names.insert(query.name.clone()); macro_rules! examine_name { ($name:expr_2021, $is_answer:expr_2021) => {{ - names.insert($name); + names.insert($name.to_owned()); if $is_answer { if let Some(value) = check_name_in_proxy_list(acl, $name) { value @@ -656,13 +662,14 @@ fn should_forward_by_response( } macro_rules! examine_record { ($rec:ident, $is_answer:expr_2021) => { - if let RData::CNAME(name) = $rec.data() { + if let RData::CNAME(ref cname) = $rec.data { + let name = &cname.0; if $is_answer { if let Some(value) = check_name_in_proxy_list(acl, name) { return value; } } - names.insert(name); + names.insert(name.to_owned()); continue; } if $is_answer && !query.query_type().is_any() && $rec.record_type() != query.query_type() { @@ -673,13 +680,13 @@ fn should_forward_by_response( ); return true; } - let forward = match $rec.data() { - RData::A(ip) => acl.check_ip_in_proxy_list(&IpAddr::V4((*ip).into())), - RData::AAAA(ip) => acl.check_ip_in_proxy_list(&IpAddr::V6((*ip).into())), + let forward = match $rec.data { + RData::A(ref ip) => acl.check_ip_in_proxy_list(&IpAddr::V4((*ip).into())), + RData::AAAA(ref ip) => acl.check_ip_in_proxy_list(&IpAddr::V6((*ip).into())), // MX records cause type A additional section processing for the host specified by EXCHANGE. - RData::MX(mx) => examine_name!(mx.exchange(), $is_answer), + RData::MX(ref mx) => examine_name!(&mx.exchange, $is_answer), // NS records cause both the usual additional section processing to locate a type A record... - RData::NS(name) => examine_name!(name, $is_answer), + RData::NS(ref name) => examine_name!(&name.0, $is_answer), RData::PTR(_) => unreachable!(), _ => acl.is_default_in_proxy_list(), }; @@ -688,19 +695,18 @@ fn should_forward_by_response( } }; } - for rec in local_response.answers() { - if !names.contains(rec.name()) { + for rec in local_response.answers.iter() { + if !names.contains(&rec.name) { warn!( "local DNS response contains unexpected name {} for query {}", - rec.name(), - query + rec.name, query ); return true; } examine_record!(rec, true); } - for rec in local_response.additionals() { - if names.contains(rec.name()) { + for rec in local_response.additionals.iter() { + if names.contains(&rec.name) { examine_record!(rec, false); } } @@ -736,29 +742,27 @@ impl DnsClient { local_addr: &NameServerAddr, remote_addr: &Address, ) -> io::Result { - let mut message = Message::new(); - message.set_id(request.id()); - message.set_recursion_desired(true); - message.set_recursion_available(true); - message.set_message_type(MessageType::Response); + let mut message = Message::response(request.id, request.op_code); + message.metadata.recursion_desired = true; + message.metadata.recursion_available = true; - if !request.recursion_desired() { + if !request.metadata.recursion_desired { // RD is required by default. Otherwise it may not get valid respond from remote servers - message.set_recursion_desired(false); - message.set_response_code(ResponseCode::NotImp); - } else if request.op_code() != OpCode::Query || request.message_type() != MessageType::Query { + message.metadata.recursion_desired = false; + message.metadata.response_code = ResponseCode::NotImp; + } else if request.op_code != OpCode::Query || request.message_type != MessageType::Query { // Other ops are not supported - message.set_response_code(ResponseCode::NotImp); - } else if request.query_count() > 0 { + message.metadata.response_code = ResponseCode::NotImp; + } else if !request.queries.is_empty() { // Make queries according to ACL rules - let (r, forward) = self.acl_lookup(&request.queries()[0], local_addr, remote_addr).await; + let (r, forward) = self.acl_lookup(&request.queries[0], local_addr, remote_addr).await; if let Ok(result) = r { - for rec in result.answers() { + for rec in result.answers.iter() { trace!("dns answer: {:?}", rec); - match rec.data() { + match rec.data { RData::A(ip) => { self.context .add_to_reverse_lookup_cache(Ipv4Addr::from(*ip).into(), forward) @@ -773,9 +777,9 @@ impl DnsClient { } } message = result; - message.set_id(request.id()); + message.metadata.id = request.id; } else { - message.set_response_code(ResponseCode::ServFail); + message.metadata.response_code = ResponseCode::ServFail; } } Ok(message) @@ -860,9 +864,8 @@ impl DnsClient { } async fn lookup_remote_inner(&self, query: &Query, remote_addr: &Address) -> io::Result { - let mut message = Message::new(); - message.set_id(rand::random()); - message.set_recursion_desired(true); + let mut message = Message::query(); + message.metadata.recursion_desired = true; message.add_query(query.clone()); // Query UDP and TCP @@ -873,14 +876,14 @@ impl DnsClient { self.client_cache .lookup_remote(&self.context, server.server_config(), remote_addr, message, false) .await - .map_err(From::from) + .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) } Mode::UdpOnly => { let server = self.balancer.best_udp_server(); self.client_cache .lookup_remote(&self.context, server.server_config(), remote_addr, message, true) .await - .map_err(From::from) + .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) } Mode::TcpAndUdp => { // Query TCP & UDP simultaneously @@ -912,11 +915,11 @@ impl DnsClient { match future::select(tcp_fut, udp_fut).await { Either::Left((res, next)) => match res { Ok(o) => Ok(o), - Err(..) => next.await.map_err(From::from), + Err(..) => next.await.map_err(|err| io::Error::new(io::ErrorKind::Other, err)), }, Either::Right((res, next)) => match res { Ok(o) => Ok(o), - Err(..) => next.await.map_err(From::from), + Err(..) => next.await.map_err(|err| io::Error::new(io::ErrorKind::Other, err)), }, } } @@ -939,9 +942,8 @@ impl DnsClient { } async fn lookup_local_inner(&self, query: &Query, local_addr: &NameServerAddr) -> io::Result { - let mut message = Message::new(); - message.set_id(rand::random()); - message.set_recursion_desired(true); + let mut message = Message::query(); + message.metadata.recursion_desired = true; message.add_query(query.clone()); match *local_addr { @@ -965,9 +967,13 @@ impl DnsClient { match future::select(udp_query, tcp_query).await { Either::Left((Ok(m), ..)) => Ok(m), - Either::Left((Err(..), next)) => next.await.map_err(From::from), + Either::Left((Err(..), next)) => { + next.await.map_err(|err| io::Error::new(io::ErrorKind::Other, err)) + } Either::Right((Ok(m), ..)) => Ok(m), - Either::Right((Err(..), next)) => next.await.map_err(From::from), + Either::Right((Err(..), next)) => { + next.await.map_err(|err| io::Error::new(io::ErrorKind::Other, err)) + } } } #[cfg(unix)] @@ -975,7 +981,7 @@ impl DnsClient { .client_cache .lookup_unix_stream(path, message) .await - .map_err(From::from), + .map_err(|err| io::Error::new(io::ErrorKind::Other, err)), } } } diff --git a/crates/shadowsocks-service/src/local/dns/upstream.rs b/crates/shadowsocks-service/src/local/dns/upstream.rs index fc67330a4516..19fb9873cde2 100644 --- a/crates/shadowsocks-service/src/local/dns/upstream.rs +++ b/crates/shadowsocks-service/src/local/dns/upstream.rs @@ -12,7 +12,11 @@ use std::{ use byteorder::{BigEndian, ByteOrder}; use bytes::{BufMut, BytesMut}; -use hickory_resolver::proto::{ProtoError, ProtoErrorKind, op::Message}; +use hickory_resolver::proto::{ + ProtoError, + op::{Message, UpdateMessage}, + serialize::binary::DecodeError, +}; use log::{error, trace}; use lru_time_cache::{Entry, LruCache}; use shadowsocks::{ @@ -39,6 +43,34 @@ use crate::{ net::{FlowStat, MonProxySocket, MonProxyStream, packet_window::PacketWindowFilter}, }; +/// DnsClient API errors +#[derive(thiserror::Error, Debug)] +pub enum DnsClientError { + /// hickory-dns proto DecodeError + #[error("{0}")] + DnsDecodeError(#[from] DecodeError), + + /// hickory-dns proto ProtoError + #[error("{0}")] + DnsProtoError(#[from] ProtoError), + + /// std::io::Error + #[error("{0}")] + IoError(#[from] io::Error), + + #[error("UDP packet id overflows")] + UdpPacketIdOverflows, + + #[error("UDP packet id out of window")] + UdpPacketIdOutOfWindow, + + #[error("Timeout")] + Timeout, +} + +/// DnsClient API Result type +pub type DnsClientResult = Result; + /// Collection of various DNS connections #[allow(clippy::large_enum_variant)] pub enum DnsClient { @@ -123,23 +155,20 @@ impl DnsClient { /// Make a DNS lookup #[allow(dead_code)] - pub async fn lookup(&mut self, mut msg: Message) -> Result { + pub async fn lookup(&mut self, mut msg: Message) -> DnsClientResult { self.inner_lookup(&mut msg).await } /// Make a DNS lookup with timeout - pub async fn lookup_timeout(&mut self, mut msg: Message, timeout: Duration) -> Result { + pub async fn lookup_timeout(&mut self, mut msg: Message, timeout: Duration) -> DnsClientResult { match time::timeout(timeout, self.inner_lookup(&mut msg)).await { Ok(Ok(msg)) => Ok(msg), Ok(Err(error)) => Err(error), - Err(..) => Err(ProtoErrorKind::Timeout.into()), + Err(..) => Err(DnsClientError::Timeout), } } - async fn inner_lookup(&mut self, msg: &mut Message) -> Result { - // Make a random ID - msg.set_id(rand::random()); - + async fn inner_lookup(&mut self, msg: &mut Message) -> DnsClientResult { trace!("DNS lookup {:?}", msg); match *self { @@ -151,7 +180,7 @@ impl DnsClient { let mut recv_buf = [0u8; 512]; let n = socket.recv(&mut recv_buf).await?; - Message::from_vec(&recv_buf[..n]) + Message::from_vec(&recv_buf[..n]).map_err(Into::into) } #[cfg(unix)] Self::UnixStream { ref mut stream } => stream_query(stream, msg).await, @@ -164,7 +193,7 @@ impl DnsClient { } => { control.packet_id = match control.packet_id.checked_add(1) { Some(i) => i, - None => return Err(ProtoErrorKind::Message("packet id overflows").into()), + None => return Err(DnsClientError::UdpPacketIdOverflows), }; let bytes = msg.to_vec()?; @@ -185,11 +214,11 @@ impl DnsClient { ns, server_control.packet_id ); - return Err(ProtoErrorKind::Message("packet id out of window").into()); + return Err(DnsClientError::UdpPacketIdOutOfWindow); } } - Message::from_vec(&recv_buf[..n]) + Message::from_vec(&recv_buf[..n]).map_err(Into::into) } } } @@ -268,7 +297,7 @@ impl DnsClient { } } -pub async fn stream_query(stream: &mut S, r: &Message) -> Result +pub async fn stream_query(stream: &mut S, r: &Message) -> DnsClientResult where S: AsyncRead + AsyncWrite + Unpin, { @@ -293,5 +322,5 @@ where } stream.read_exact(&mut rsp_bytes).await?; - Message::from_vec(&rsp_bytes) + Message::from_vec(&rsp_bytes).map_err(Into::into) } diff --git a/crates/shadowsocks-service/src/local/fake_dns/processor.rs b/crates/shadowsocks-service/src/local/fake_dns/processor.rs index cdc7d7d293d0..0a1bb1b825e5 100644 --- a/crates/shadowsocks-service/src/local/fake_dns/processor.rs +++ b/crates/shadowsocks-service/src/local/fake_dns/processor.rs @@ -3,7 +3,7 @@ use std::io; use hickory_resolver::proto::{ - op::{Header, Message, OpCode, header::MessageType, response_code::ResponseCode}, + op::{Message, MessageType, OpCode, ResponseCode, UpdateMessage}, rr::{ DNSClass, RData, Record, RecordType, rdata::{A, AAAA}, @@ -14,14 +14,12 @@ use log::{debug, trace, warn}; use super::manager::FakeDnsManager; pub async fn handle_dns_request(req_message: &Message, manager: &FakeDnsManager) -> io::Result { - let mut rsp_message = Message::new(); - let rsp_header = Header::response_from_request(req_message.header()); - rsp_message.set_header(rsp_header); + let mut rsp_message = Message::response(req_message.id(), req_message.op_code); - if req_message.op_code() != OpCode::Query || req_message.message_type() != MessageType::Query { - rsp_message.set_response_code(ResponseCode::NotImp); + if req_message.op_code != OpCode::Query || req_message.message_type != MessageType::Query { + rsp_message.metadata.response_code = ResponseCode::NotImp; } else { - for query in req_message.queries() { + for query in req_message.queries.iter() { // Copy all the queries into response. rsp_message.add_query(query.clone()); @@ -45,7 +43,7 @@ pub async fn handle_dns_request(req_message: &Message, manager: &FakeDnsManager) expire_duration.as_secs() as u32, RData::A(A(ip_addr)), ); - record.set_dns_class(query.query_class()); + record.dns_class = query.query_class(); rsp_message.add_answer(record); } RecordType::AAAA => { @@ -56,7 +54,7 @@ pub async fn handle_dns_request(req_message: &Message, manager: &FakeDnsManager) expire_duration.as_secs() as u32, RData::AAAA(AAAA(ip_addr)), ); - record.set_dns_class(query.query_class()); + record.dns_class = query.query_class(); rsp_message.add_answer(record); } _ => { diff --git a/crates/shadowsocks-service/src/local/fake_dns/tcp_server.rs b/crates/shadowsocks-service/src/local/fake_dns/tcp_server.rs index 25115e15afe8..b1feb27889f0 100644 --- a/crates/shadowsocks-service/src/local/fake_dns/tcp_server.rs +++ b/crates/shadowsocks-service/src/local/fake_dns/tcp_server.rs @@ -10,8 +10,8 @@ use std::{ use byteorder::{BigEndian, ByteOrder}; use bytes::{BufMut, BytesMut}; use hickory_resolver::proto::{ - op::{Message, response_code::ResponseCode}, - serialize::binary::{BinEncodable, BinEncoder, EncodeMode}, + op::{Message, ResponseCode}, + serialize::binary::{BinEncodable, BinEncoder}, }; use log::{error, trace}; use shadowsocks::{ServerAddr, lookup_then, net::TcpListener as ShadowTcpListener}; @@ -130,7 +130,7 @@ impl FakeDnsTcpServer { Ok(m) => m, Err(err) => { error!("dns tcp {} parse message failed, error: {}", peer_addr, err); - return Err(err.into()); + return Err(io::Error::new(io::ErrorKind::Other, err)); } }; @@ -139,14 +139,17 @@ impl FakeDnsTcpServer { Err(err) => { error!("failed to handle DNS request, error: {}", err); - Message::error_msg(req_message.id(), req_message.op_code(), ResponseCode::ServFail) + Message::error_msg(req_message.id, req_message.op_code, ResponseCode::ServFail) } }; let mut rsp_buffer = Vec::with_capacity(2 + 512); rsp_buffer.resize(2, 0); - let mut rsp_encoder = BinEncoder::with_offset(&mut rsp_buffer, 2, EncodeMode::Normal); - rsp_message.emit(&mut rsp_encoder)?; + let mut rsp_encoder = BinEncoder::with_offset(&mut rsp_buffer, 2); + if let Err(err) = rsp_message.emit(&mut rsp_encoder) { + error!("failed to encode DNS response, error: {}", err); + return Err(io::Error::new(io::ErrorKind::Other, err)); + } let rsp_length = (rsp_buffer.len() - 2) as u16; BigEndian::write_u16(&mut rsp_buffer[0..2], rsp_length); diff --git a/crates/shadowsocks-service/src/local/fake_dns/udp_server.rs b/crates/shadowsocks-service/src/local/fake_dns/udp_server.rs index 68b59ac2172b..89a61a5ba037 100644 --- a/crates/shadowsocks-service/src/local/fake_dns/udp_server.rs +++ b/crates/shadowsocks-service/src/local/fake_dns/udp_server.rs @@ -2,7 +2,7 @@ use std::{io, net::SocketAddr, sync::Arc, time::Duration}; -use hickory_resolver::proto::op::{Message, response_code::ResponseCode}; +use hickory_resolver::proto::op::{Message, ResponseCode}; use log::error; use shadowsocks::{ServerAddr, lookup_then, net::UdpSocket as ShadowUdpSocket}; use tokio::time; @@ -69,11 +69,17 @@ impl FakeDnsUdpServer { Err(err) => { error!("failed to handle DNS request, error: {}", err); - Message::error_msg(req_message.id(), req_message.op_code(), ResponseCode::ServFail) + Message::error_msg(req_message.id, req_message.op_code, ResponseCode::ServFail) } }; - let rsp_buffer = rsp_message.to_vec()?; + let rsp_buffer = match rsp_message.to_vec() { + Ok(b) => b, + Err(err) => { + error!("failed to encode DNS response, error: {}", err); + return Err(io::Error::new(io::ErrorKind::Other, err)); + } + }; let _ = self.listener.send_to(&rsp_buffer, peer_addr).await; } } diff --git a/crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs b/crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs index 88d0301856fd..be7a04fe31b7 100644 --- a/crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs +++ b/crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs @@ -12,13 +12,9 @@ use std::{ use futures::ready; use hickory_resolver::{ - ResolveError, Resolver, + Resolver, config::{LookupIpStrategy, ResolverConfig, ResolverOpts}, - name_server::GenericConnector, - proto::{ - runtime::{RuntimeProvider, TokioHandle, TokioTime, iocompat::AsyncIoTokioAsStd}, - udp::DnsUdpSocket, - }, + net::runtime::{DnsUdpSocket, RuntimeProvider, TokioHandle, TokioTime, iocompat::AsyncIoTokioAsStd}, }; use log::{error, trace}; use tokio::{io::ReadBuf, net::UdpSocket}; @@ -130,29 +126,23 @@ impl RuntimeProvider for ShadowDnsRuntimeProvider { } } -/// Shadowsocks DNS ConnectionProvider -pub type ShadowDnsConnectionProvider = GenericConnector; - /// Shadowsocks DNS resolver /// /// A customized hickory-dns-resolver -pub type DnsResolver = Resolver; +pub type DnsResolver = Resolver; /// Create a `hickory-dns` asynchronous DNS resolver pub async fn create_resolver( dns: Option, opts: Option, connect_opts: ConnectOpts, -) -> Result { +) -> io::Result { // Customized dns resolution match dns { Some(conf) => { trace!("initializing DNS resolver with config {:?}", conf,); - let mut builder = DnsResolver::builder_with_config( - conf, - ShadowDnsConnectionProvider::new(ShadowDnsRuntimeProvider::new(connect_opts)), - ); + let mut builder = DnsResolver::builder_with_config(conf, ShadowDnsRuntimeProvider::new(connect_opts)); if let Some(opts) = opts { *builder.options_mut() = opts; } @@ -167,15 +157,19 @@ pub async fn create_resolver( trace!("initializing DNS resolver with opts {:?}", resolver_opts); - Ok(builder.build()) + match builder.build() { + Ok(resolver) => Ok(resolver), + Err(err) => { + error!("initialize DNS resolver with config failed, error: {}", err); + Err(io::Error::new(io::ErrorKind::Other, err)) + } + } } // To make this independent, if targeting macOS, BSD, Linux, or Windows, we can use the system's configuration // Android doesn't have /etc/resolv.conf. None => { - match DnsResolver::builder(ShadowDnsConnectionProvider::new(ShadowDnsRuntimeProvider::new( - connect_opts, - ))) { + match DnsResolver::builder(ShadowDnsRuntimeProvider::new(connect_opts)) { Ok(mut builder) => { let opts = builder.options_mut(); // NOTE: timeout will be set by config (for example, /etc/resolv.conf on UNIX-like system) @@ -188,13 +182,17 @@ pub async fn create_resolver( trace!("initializing DNS resolver with system-config opts {:?}", opts); - Ok(builder.build()) + match builder.build() { + Ok(resolver) => Ok(resolver), + Err(err) => { + error!("initialize DNS resolver with config failed, error: {}", err); + Err(io::Error::new(io::ErrorKind::Other, err)) + } + } } Err(err) => { error!("initialize DNS resolver with system-config failed, error: {}", err); - Err(ResolveError::from( - "current platform doesn't support hickory-dns resolver with system configured".to_owned(), - )) + Err(io::Error::new(io::ErrorKind::Other, err)) } } } diff --git a/crates/shadowsocks/src/dns_resolver/resolver.rs b/crates/shadowsocks/src/dns_resolver/resolver.rs index da49ca8a336c..a25859cec40b 100644 --- a/crates/shadowsocks/src/dns_resolver/resolver.rs +++ b/crates/shadowsocks/src/dns_resolver/resolver.rs @@ -380,9 +380,11 @@ impl DnsResolver { }, #[cfg(feature = "hickory-dns")] Self::HickoryDnsSystem { ref inner, .. } => match inner.resolver.load().lookup_ip(addr).await { - Ok(lookup_result) => Ok(EitherResolved::HickoryDnsSystem( - lookup_result.into_iter().map(move |ip| SocketAddr::new(ip, port)), - )), + Ok(lookup_result) => { + let result: Vec = + lookup_result.iter().map(move |ip| SocketAddr::new(ip, port)).collect(); + Ok(EitherResolved::HickoryDnsSystem(result.into_iter())) + } Err(err) => { let err = Error::other(format!("dns resolve {addr}:{port} error: {err}")); Err(err) @@ -390,9 +392,11 @@ impl DnsResolver { }, #[cfg(feature = "hickory-dns")] Self::HickoryDns(ref resolver) => match resolver.lookup_ip(addr).await { - Ok(lookup_result) => Ok(EitherResolved::HickoryDns( - lookup_result.into_iter().map(move |ip| SocketAddr::new(ip, port)), - )), + Ok(lookup_result) => { + let result: Vec = + lookup_result.iter().map(move |ip| SocketAddr::new(ip, port)).collect(); + Ok(EitherResolved::HickoryDns(result.into_iter())) + } Err(err) => { let err = Error::other(format!("dns resolve {addr}:{port} error: {err}")); Err(err) From ced1e52df435fd6f6a2f311b92b926444cc81d92 Mon Sep 17 00:00:00 2001 From: zonyitoo Date: Mon, 27 Apr 2026 00:35:30 +0800 Subject: [PATCH 3/3] fix: remove unused import --- crates/shadowsocks-service/src/local/dns/upstream.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/shadowsocks-service/src/local/dns/upstream.rs b/crates/shadowsocks-service/src/local/dns/upstream.rs index 19fb9873cde2..b98b1a945bb1 100644 --- a/crates/shadowsocks-service/src/local/dns/upstream.rs +++ b/crates/shadowsocks-service/src/local/dns/upstream.rs @@ -12,11 +12,7 @@ use std::{ use byteorder::{BigEndian, ByteOrder}; use bytes::{BufMut, BytesMut}; -use hickory_resolver::proto::{ - ProtoError, - op::{Message, UpdateMessage}, - serialize::binary::DecodeError, -}; +use hickory_resolver::proto::{ProtoError, op::Message, serialize::binary::DecodeError}; use log::{error, trace}; use lru_time_cache::{Entry, LruCache}; use shadowsocks::{