From 7165f328a8c850adf0810f804834e23f6fc3c83e Mon Sep 17 00:00:00 2001 From: erebe Date: Wed, 19 Jun 2024 20:34:53 +0000 Subject: [PATCH] fix dns over TLS and HTTPS --- Cargo.lock | 20 +++++++++++++++++--- Cargo.toml | 2 +- src/dns.rs | 33 +++++++++++++++++++++++++-------- src/main.rs | 10 +++++----- 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c432d46..ee414ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -305,7 +305,7 @@ dependencies = [ "log", "pin-project-lite", "rustls 0.22.4", - "rustls-native-certs", + "rustls-native-certs 0.7.0", "rustls-pemfile 2.1.2", "rustls-pki-types", "serde", @@ -983,6 +983,7 @@ dependencies = [ "once_cell", "rand", "rustls 0.21.12", + "rustls-native-certs 0.6.3", "rustls-pemfile 1.0.4", "thiserror", "tinyvec", @@ -1008,6 +1009,7 @@ dependencies = [ "rand", "resolv-conf", "rustls 0.21.12", + "rustls-native-certs 0.6.3", "smallvec", "thiserror", "tokio", @@ -1140,7 +1142,7 @@ dependencies = [ "hyper-util", "log", "rustls 0.22.4", - "rustls-native-certs", + "rustls-native-certs 0.7.0", "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", @@ -2002,6 +2004,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework", +] + [[package]] name = "rustls-native-certs" version = "0.7.0" @@ -3091,7 +3105,7 @@ dependencies = [ "pin-project", "ppp", "regex", - "rustls-native-certs", + "rustls-native-certs 0.7.0", "rustls-pemfile 2.1.2", "scopeguard", "serde", diff --git a/Cargo.toml b/Cargo.toml index 73ac072..db02fc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ clap = { version = "4.5.6", features = ["derive", "env"] } fast-socks5 = { version = "0.9.6", features = [] } fastwebsockets = { version = "0.7.2", features = ["upgrade", "simd", "unstable-split"] } futures-util = { version = "0.3.30" } -hickory-resolver = { version = "0.24.1", features = ["tokio", "dns-over-https-rustls", "dns-over-rustls"] } +hickory-resolver = { version = "0.24.1", features = ["tokio", "dns-over-https-rustls", "dns-over-rustls", "native-certs"] } ppp = { version = "2.2.0", features = [] } # For config file parsing diff --git a/src/dns.rs b/src/dns.rs index 08d8a87..62866eb 100644 --- a/src/dns.rs +++ b/src/dns.rs @@ -1,6 +1,6 @@ -use anyhow::anyhow; +use anyhow::{anyhow, Context}; use futures_util::FutureExt; -use hickory_resolver::config::{NameServerConfig, ResolverConfig, ResolverOpts}; +use hickory_resolver::config::{NameServerConfig, Protocol, ResolverConfig, ResolverOpts}; use hickory_resolver::name_server::{GenericConnector, RuntimeProvider, TokioRuntimeProvider}; use hickory_resolver::proto::iocompat::AsyncIoTokioAsStd; use hickory_resolver::proto::TokioTime; @@ -67,10 +67,24 @@ impl DnsResolver { // otherwise, use the specified resolvers let mut cfg = ResolverConfig::new(); for resolver in resolvers.iter() { - let (protocol, port) = match resolver.scheme() { - "dns" => (hickory_resolver::config::Protocol::Udp, resolver.port().unwrap_or(53)), - "dns+https" => (hickory_resolver::config::Protocol::Https, resolver.port().unwrap_or(443)), - "dns+tls" => (hickory_resolver::config::Protocol::Tls, resolver.port().unwrap_or(853)), + let (protocol, port, tls_sni) = match resolver.scheme() { + "dns" => (Protocol::Udp, resolver.port().unwrap_or(53), None), + "dns+https" => { + let tls_sni = resolver + .query_pairs() + .find(|(k, _)| k == "sni") + .with_context(|| "Missing `sni` query parameter for dns over https")? + .1; + (Protocol::Https, resolver.port().unwrap_or(443), Some(tls_sni.to_string())) + } + "dns+tls" => { + let tls_sni = resolver + .query_pairs() + .find(|(k, _)| k == "sni") + .with_context(|| "Missing `sni` query parameter for dns over tls")? + .1; + (Protocol::Tls, resolver.port().unwrap_or(853), Some(tls_sni.to_string())) + } _ => return Err(anyhow!("invalid protocol for dns resolver")), }; let host = resolver @@ -87,7 +101,10 @@ impl DnsResolver { Host::Ipv4(ip) => SocketAddr::V4(SocketAddrV4::new(ip, port)), Host::Ipv6(ip) => SocketAddr::V6(SocketAddrV6::new(ip, port, 0, 0)), }; - cfg.add_name_server(NameServerConfig::new(sock, protocol)) + + let mut ns = NameServerConfig::new(sock, protocol); + ns.tls_dns_name = tls_sni; + cfg.add_name_server(ns); } let mut opts = ResolverOpts::default(); @@ -174,4 +191,4 @@ impl RuntimeProvider for TokioRuntimeProviderWithSoMark { Box::pin(socket) } -} +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 541eb37..443014f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -248,8 +248,8 @@ struct Client { /// Dns resolver to use to lookup ips of domain name. Can be specified multiple time /// Example: /// dns://1.1.1.1 for using udp - /// dns+https://1.1.1.1 for using dns over HTTPS - /// dns+tls://8.8.8.8 for using dns over TLS + /// dns+https://1.1.1.1?sni=loudflare-dns.com for using dns over HTTPS + /// dns+tls://8.8.8.8?sni=dns.google for using dns over TLS /// To use libc resolver, use /// system://0.0.0.0 /// @@ -286,8 +286,8 @@ struct Server { /// Can be specified multiple time /// Example: /// dns://1.1.1.1 for using udp - /// dns+https://1.1.1.1 for using dns over HTTPS - /// dns+tls://8.8.8.8 for using dns over TLS + /// dns+https://1.1.1.1?sni=loudflare-dns.com for using dns over HTTPS + /// dns+tls://8.8.8.8?sni=dns.google for using dns over TLS /// To use libc resolver, use /// system://0.0.0.0 #[arg(long, verbatim_doc_comment)] @@ -1316,4 +1316,4 @@ async fn main() { } tokio::signal::ctrl_c().await.unwrap(); -} +} \ No newline at end of file