fix: use custom DNS resolver (#1364)

* add DefaultResolver

* style: fmt

* chore: remove unused feature

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* chore: remove unused `ipconfig/computer` feature

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* chore: update `trust-dns-resolver`

* refactor: apply requested changes

* chore: revert `trust-dns-resolver` upgrade

I mistakenly thought `reqwest` already updated to the newest version, but it hasn't! (no release was made yet)

* refactor: cleanup

---------

Co-authored-by: GNQG <my.t.gnq+dev@gmail.com>
Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
Sculas 2023-09-17 01:51:07 +02:00 committed by GitHub
parent 04c5c00669
commit 6560225c03
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 196 additions and 2 deletions

View file

@ -37,7 +37,9 @@ tokio-tar = "0.3.0"
tokio-util = { version = "0.7.8", features = ["io"] }
tracing = "0.1.37"
# trust-dns-resolver must be kept in sync with the version reqwest uses
trust-dns-resolver = { version = "0.22.0", optional = true, default-features = false, features = ["dnssec-ring"] }
trust-dns-resolver = { version = "0.22.0", optional = true, features = ["dnssec-ring"] }
hyper = { version = "0.14.27", optional = true }
once_cell = { version = "1.18.0", optional = true }
url = "2.3.1"
xz2 = "0.1.7"
@ -78,7 +80,7 @@ native-tls = [
]
# Enable trust-dns-resolver so that features on it will also be enabled.
trust-dns = ["trust-dns-resolver", "reqwest/trust-dns"]
trust-dns = ["trust-dns-resolver", "default-net", "ipconfig", "hyper", "once_cell"]
# Experimental HTTP/3 client, this would require `--cfg reqwest_unstable`
# to be passed to `rustc`.
@ -91,6 +93,10 @@ cross-lang-fat-lto = ["zstd/fat-lto"]
gh-api-client = ["json"]
json = ["serde", "serde_json"]
[target."cfg(windows)".dependencies]
default-net = { version = "0.17.0", optional = true }
ipconfig = { version = "0.3.2", optional = true, default-features = false }
[package.metadata.docs.rs]
features = ["gh-api-client"]
rustdoc-args = ["--cfg", "docsrs"]

View file

@ -12,4 +12,7 @@ pub mod gh_api_client;
pub mod remote;
#[cfg(feature = "trust-dns")]
mod resolver;
mod utils;

View file

@ -18,6 +18,9 @@ use tracing::{debug, info, instrument};
pub use reqwest::{header, Error as ReqwestError, Method, StatusCode};
pub use url::Url;
#[cfg(feature = "trust-dns")]
use crate::resolver::TrustDnsResolver;
mod delay_request;
use delay_request::DelayRequest;
@ -107,6 +110,11 @@ impl Client {
.https_only(true)
.tcp_nodelay(false);
#[cfg(feature = "trust-dns")]
{
builder = builder.dns_resolver(Arc::new(TrustDnsResolver::default()));
}
#[cfg(feature = "__tls")]
{
let tls_ver = min_tls

View file

@ -0,0 +1,64 @@
use std::{net::SocketAddr, sync::Arc};
use hyper::client::connect::dns::Name;
use once_cell::sync::OnceCell;
use reqwest::dns::{Addrs, Resolve};
use trust_dns_resolver::config::{NameServerConfig, Protocol, ResolverConfig, ResolverOpts};
use trust_dns_resolver::TokioAsyncResolver;
#[derive(Debug, Default, Clone)]
pub struct TrustDnsResolver(Arc<OnceCell<TokioAsyncResolver>>);
impl Resolve for TrustDnsResolver {
fn resolve(&self, name: Name) -> reqwest::dns::Resolving {
let resolver = self.clone();
Box::pin(async move {
let resolver = resolver.0.get_or_try_init(new_resolver)?;
let lookup = resolver.lookup_ip(name.as_str()).await?;
let addrs: Addrs = Box::new(lookup.into_iter().map(|ip| SocketAddr::new(ip, 0)));
Ok(addrs)
})
}
}
fn new_resolver() -> Result<TokioAsyncResolver, Box<dyn std::error::Error + Send + Sync>> {
#[cfg(unix)]
{
let (config, opts) = trust_dns_resolver::system_conf::read_system_conf()?;
Ok(TokioAsyncResolver::tokio(config, opts)?)
}
#[cfg(windows)]
{
let mut config = ResolverConfig::new();
let opts = ResolverOpts::default();
let current_interface = default_net::get_default_interface()?;
ipconfig::get_adapters()?
.iter()
.filter_map(|adapter| {
if adapter.adapter_name() == current_interface.name {
Some(adapter.dns_servers())
} else {
None
}
})
.flatten()
.for_each(|addr| {
let socket_addr = SocketAddr::new(*addr, 53);
for protocol in [Protocol::Udp, Protocol::Tcp] {
config.add_name_server(NameServerConfig {
socket_addr,
protocol,
tls_dns_name: None,
trust_nx_responses: false,
#[cfg(feature = "rustls")]
tls_config: None,
bind_addr: None,
})
}
});
Ok(TokioAsyncResolver::tokio(config, opts)?)
}
}