fix(deps): update rust crate hickory-resolver to 0.26 (#2114)

* fix(deps): update rust crate hickory-resolver to 0.26

* fix: compat hickory-resolver 0.26

* fix: remove unused import

* fix: removed unnecessary deref

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: zonyitoo <zonyitoo@gmail.com>
This commit is contained in:
renovate[bot]
2026-05-05 17:14:39 +08:00
committed by GitHub
co-authored by zonyitoo
parent 9fca88bc93
commit d817982cd1
14 changed files with 346 additions and 199 deletions
Generated
+135 -42
View File
@@ -975,18 +975,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"
@@ -1321,9 +1309,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",
@@ -1335,9 +1323,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",
@@ -1394,65 +1382,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]]
@@ -1590,7 +1602,7 @@ dependencies = [
"percent-encoding",
"pin-project-lite",
"socket2 0.6.3",
"system-configuration",
"system-configuration 0.6.1",
"tokio",
"tower-service",
"tracing",
@@ -1796,6 +1808,9 @@ name = "ipnet"
version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
dependencies = [
"serde",
]
[[package]]
name = "iprange"
@@ -1890,19 +1905,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"
@@ -2237,6 +2301,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"
@@ -2553,6 +2623,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"
@@ -2966,7 +3047,7 @@ checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784"
dependencies = [
"core-foundation 0.10.1",
"core-foundation-sys",
"jni",
"jni 0.21.1",
"log",
"once_cell",
"rustls",
@@ -3352,7 +3433,7 @@ dependencies = [
"trait-variant",
"tun",
"url",
"webpki-roots 1.0.7",
"webpki-roots",
"windows-sys 0.61.2",
"zstd",
]
@@ -3388,6 +3469,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"
@@ -3566,6 +3657,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"
@@ -4275,15 +4377,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"
+1 -1
View File
@@ -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"
+34 -23
View File
@@ -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<DnsConfig, Error> {
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::<SocketAddr>() {
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))
})
}
+2 -2
View File
@@ -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);
}
@@ -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<Message, ProtoError> {
) -> DnsClientResult<Message> {
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<Message, ProtoError> {
) -> DnsClientResult<Message> {
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<P: AsRef<Path>>(&self, ns: &P, msg: Message) -> Result<Message, ProtoError> {
pub async fn lookup_unix_stream<P: AsRef<Path>>(&self, ns: &P, msg: Message) -> DnsClientResult<Message> {
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<Message, ProtoError> {
) -> DnsClientResult<Message> {
let mut last_err = None;
for _ in 0..self.retry_count {
let create_fn = async {
@@ -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<Vec<SocketAddr>> {
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<SocketAddr> {
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);
}
@@ -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,46 +742,44 @@ impl DnsClient {
local_addr: &NameServerAddr,
remote_addr: &Address,
) -> io::Result<Message> {
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)
.add_to_reverse_lookup_cache(Ipv4Addr::from(ip).into(), forward)
.await
}
RData::AAAA(ip) => {
self.context
.add_to_reverse_lookup_cache(Ipv6Addr::from(*ip).into(), forward)
.add_to_reverse_lookup_cache(Ipv6Addr::from(ip).into(), forward)
.await
}
_ => (),
}
}
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<Message> {
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<Message> {
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)),
}
}
}
@@ -12,7 +12,7 @@ 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, serialize::binary::DecodeError};
use log::{error, trace};
use lru_time_cache::{Entry, LruCache};
use shadowsocks::{
@@ -39,6 +39,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<T> type
pub type DnsClientResult<T> = Result<T, DnsClientError>;
/// Collection of various DNS connections
#[allow(clippy::large_enum_variant)]
pub enum DnsClient {
@@ -123,23 +151,20 @@ impl DnsClient {
/// Make a DNS lookup
#[allow(dead_code)]
pub async fn lookup(&mut self, mut msg: Message) -> Result<Message, ProtoError> {
pub async fn lookup(&mut self, mut msg: Message) -> DnsClientResult<Message> {
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<Message, ProtoError> {
pub async fn lookup_timeout(&mut self, mut msg: Message, timeout: Duration) -> DnsClientResult<Message> {
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<Message, ProtoError> {
// Make a random ID
msg.set_id(rand::random());
async fn inner_lookup(&mut self, msg: &mut Message) -> DnsClientResult<Message> {
trace!("DNS lookup {:?}", msg);
match *self {
@@ -151,7 +176,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 +189,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 +210,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 +293,7 @@ impl DnsClient {
}
}
pub async fn stream_query<S>(stream: &mut S, r: &Message) -> Result<Message, ProtoError>
pub async fn stream_query<S>(stream: &mut S, r: &Message) -> DnsClientResult<Message>
where
S: AsyncRead + AsyncWrite + Unpin,
{
@@ -293,5 +318,5 @@ where
}
stream.read_exact(&mut rsp_bytes).await?;
Message::from_vec(&rsp_bytes)
Message::from_vec(&rsp_bytes).map_err(Into::into)
}
@@ -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<Message> {
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);
}
_ => {
@@ -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);
@@ -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;
}
}
+1 -1
View File
@@ -92,7 +92,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 }
@@ -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<ShadowDnsRuntimeProvider>;
/// Shadowsocks DNS resolver
///
/// A customized hickory-dns-resolver
pub type DnsResolver = Resolver<ShadowDnsConnectionProvider>;
pub type DnsResolver = Resolver<ShadowDnsRuntimeProvider>;
/// Create a `hickory-dns` asynchronous DNS resolver
pub async fn create_resolver(
dns: Option<ResolverConfig>,
opts: Option<ResolverOpts>,
connect_opts: ConnectOpts,
) -> Result<DnsResolver, ResolveError> {
) -> io::Result<DnsResolver> {
// 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))
}
}
}
@@ -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<SocketAddr> =
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<SocketAddr> =
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)