1use std::future::Future;
9use std::marker::Unpin;
10use std::net::{IpAddr, SocketAddr};
11#[cfg(feature = "__quic")]
12use std::net::{Ipv4Addr, Ipv6Addr};
13use std::pin::Pin;
14#[cfg(any(feature = "__tls", feature = "__https"))]
15use std::sync::Arc;
16
17#[cfg(feature = "__https")]
18use hickory_net::h2::HttpsClientStream;
19#[cfg(feature = "__tls")]
20use rustls::DigitallySignedStruct;
21#[cfg(feature = "__tls")]
22use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
23#[cfg(feature = "__tls")]
24use rustls::crypto::{CryptoProvider, verify_tls12_signature, verify_tls13_signature};
25#[cfg(feature = "__tls")]
26use rustls::pki_types::{CertificateDer, ServerName, UnixTime};
27#[cfg(not(feature = "__tls"))]
28use tracing::warn;
29
30#[cfg(feature = "__h3")]
31use crate::net::h3::H3ClientStream;
32#[cfg(feature = "__quic")]
33use crate::net::quic::QuicClientStream;
34#[cfg(feature = "__tls")]
35use crate::net::tls::{client_config, default_provider, tls_exchange_with_bind_addr};
36use crate::{
37 config::{ConnectionConfig, ProtocolConfig},
38 name_server_pool::PoolContext,
39 net::{
40 NetError,
41 runtime::RuntimeProvider,
42 tcp::TcpClientStream,
43 udp::UdpClientStream,
44 xfer::{DnsExchange, DnsHandle},
45 },
46};
47
48pub trait ConnectionProvider: 'static + Clone + Send + Sync + Unpin {
51 type Conn: DnsHandle + Clone + Send + Sync + 'static;
53 type FutureConn: Future<Output = Result<Self::Conn, NetError>> + Send + 'static;
55 type RuntimeProvider: RuntimeProvider;
57
58 fn new_connection(
60 &self,
61 ip: IpAddr,
62 config: &ConnectionConfig,
63 cx: &PoolContext,
64 ) -> Result<Self::FutureConn, NetError>;
65
66 fn runtime_provider(&self) -> &Self::RuntimeProvider;
68}
69
70impl<P: RuntimeProvider> ConnectionProvider for P {
71 type Conn = DnsExchange<P>;
72 type FutureConn = Pin<Box<dyn Future<Output = Result<Self::Conn, NetError>> + Send + 'static>>;
73 type RuntimeProvider = P;
74
75 fn new_connection(
76 &self,
77 ip: IpAddr,
78 config: &ConnectionConfig,
79 cx: &PoolContext,
80 ) -> Result<Self::FutureConn, NetError> {
81 let remote_addr = SocketAddr::new(ip, config.port);
82 match (&config.protocol, self.quic_binder()) {
83 (ProtocolConfig::Udp, _) => {
84 let (timeout, os_port_selection, avoid_local_udp_ports, bind_addr, provider) = (
85 cx.options.timeout,
86 cx.options.os_port_selection,
87 cx.options.avoid_local_udp_ports.clone(),
88 config.bind_addr,
89 self.clone(),
90 );
91
92 Ok(Box::pin(async move {
93 Ok(UdpClientStream::builder(remote_addr, provider)
94 .with_timeout(Some(timeout))
95 .with_os_port_selection(os_port_selection)
96 .avoid_local_ports(avoid_local_udp_ports)
97 .with_bind_addr(bind_addr)
98 .exchange())
99 }))
100 }
101 (ProtocolConfig::Tcp, _) => Ok(Box::pin(TcpClientStream::exchange(
102 remote_addr,
103 config.bind_addr,
104 cx.options.timeout,
105 Some(cx.options.max_active_requests),
106 self.clone(),
107 ))),
108 #[cfg(feature = "__tls")]
109 (ProtocolConfig::Tls { server_name }, _) => {
110 let Ok(server_name) = ServerName::try_from(&**server_name) else {
111 return Err(NetError::from(format!(
112 "invalid server name: {server_name}"
113 )));
114 };
115
116 let server_name = server_name.to_owned();
117 Ok(Box::pin(tls_exchange_with_bind_addr(
118 remote_addr,
119 config.bind_addr,
120 server_name,
121 cx.tls.clone(),
122 cx.options.timeout,
123 Some(cx.options.max_active_requests),
124 self.clone(),
125 )))
126 }
127 #[cfg(feature = "__https")]
128 (ProtocolConfig::Https { server_name, path }, _) => {
129 let mut builder =
130 HttpsClientStream::builder(Arc::new(cx.tls.clone()), self.clone());
131 builder.request_timeout(cx.options.timeout);
132 if let Some(bind_addr) = config.bind_addr {
133 builder.bind_addr(bind_addr);
134 }
135 Ok(Box::pin(builder.exchange(
136 remote_addr,
137 server_name.clone(),
138 path.clone(),
139 )))
140 }
141
142 #[cfg(feature = "__quic")]
143 (ProtocolConfig::Quic { server_name }, Some(binder)) => {
144 let bind_addr = config.bind_addr.unwrap_or(match remote_addr {
145 SocketAddr::V4(_) => SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0),
146 SocketAddr::V6(_) => SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0),
147 });
148
149 Ok(Box::pin(
150 QuicClientStream::builder()
151 .crypto_config(cx.tls.clone())
152 .request_timeout(cx.options.timeout)
153 .exchange(
154 binder.bind_quic(bind_addr, remote_addr)?,
155 remote_addr,
156 server_name.clone(),
157 self.clone(),
158 ),
159 ))
160 }
161 #[cfg(feature = "__h3")]
162 (
163 ProtocolConfig::H3 {
164 server_name,
165 path,
166 disable_grease,
167 },
168 Some(binder),
169 ) => {
170 let bind_addr = config.bind_addr.unwrap_or(match remote_addr {
171 SocketAddr::V4(_) => SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0),
172 SocketAddr::V6(_) => SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0),
173 });
174
175 Ok(Box::pin(
176 H3ClientStream::builder()
177 .crypto_config(cx.tls.clone())
178 .disable_grease(*disable_grease)
179 .request_timeout(cx.options.timeout)
180 .exchange(
181 binder.bind_quic(bind_addr, remote_addr)?,
182 remote_addr,
183 server_name.clone(),
184 path.clone(),
185 self.clone(),
186 ),
187 ))
188 }
189 #[cfg(feature = "__quic")]
190 (ProtocolConfig::Quic { .. }, None) => {
191 Err(NetError::from("runtime provider does not support QUIC"))
192 }
193 #[cfg(feature = "__h3")]
194 (ProtocolConfig::H3 { .. }, None) => {
195 Err(NetError::from("runtime provider does not support QUIC"))
196 }
197 }
198 }
199
200 fn runtime_provider(&self) -> &Self::RuntimeProvider {
201 self
202 }
203}
204
205pub struct TlsConfig {
207 #[cfg(feature = "__tls")]
209 pub config: rustls::ClientConfig,
210}
211
212impl TlsConfig {
213 pub fn new() -> Result<Self, NetError> {
215 Ok(Self {
216 #[cfg(feature = "__tls")]
217 config: client_config()?,
218 })
219 }
220
221 #[cfg(feature = "__tls")]
226 pub fn insecure_skip_verify(&mut self) {
227 self.config
228 .dangerous()
229 .set_certificate_verifier(Arc::new(NoCertificateVerification::default()))
230 }
231
232 #[cfg(not(feature = "__tls"))]
237 pub fn insecure_skip_verify(&mut self) {
238 warn!("asked to skip TLS verification without TLS support")
239 }
240}
241
242#[cfg(feature = "__tls")]
247#[derive(Debug)]
248struct NoCertificateVerification(CryptoProvider);
249
250#[cfg(feature = "__tls")]
251impl Default for NoCertificateVerification {
252 fn default() -> Self {
253 Self(default_provider())
254 }
255}
256
257#[cfg(feature = "__tls")]
258impl ServerCertVerifier for NoCertificateVerification {
259 fn verify_server_cert(
260 &self,
261 _end_entity: &CertificateDer<'_>,
262 _intermediates: &[CertificateDer<'_>],
263 _server_name: &ServerName<'_>,
264 _ocsp: &[u8],
265 _now: UnixTime,
266 ) -> Result<ServerCertVerified, rustls::Error> {
267 Ok(ServerCertVerified::assertion())
268 }
269
270 fn verify_tls12_signature(
271 &self,
272 message: &[u8],
273 cert: &CertificateDer<'_>,
274 dss: &DigitallySignedStruct,
275 ) -> Result<HandshakeSignatureValid, rustls::Error> {
276 verify_tls12_signature(
277 message,
278 cert,
279 dss,
280 &self.0.signature_verification_algorithms,
281 )
282 }
283
284 fn verify_tls13_signature(
285 &self,
286 message: &[u8],
287 cert: &CertificateDer<'_>,
288 dss: &DigitallySignedStruct,
289 ) -> Result<HandshakeSignatureValid, rustls::Error> {
290 verify_tls13_signature(
291 message,
292 cert,
293 dss,
294 &self.0.signature_verification_algorithms,
295 )
296 }
297
298 fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
299 self.0.signature_verification_algorithms.supported_schemes()
300 }
301}
302
303#[cfg(all(
304 test,
305 feature = "tokio",
306 any(feature = "webpki-roots", feature = "rustls-platform-verifier"),
307 any(
308 feature = "__tls",
309 feature = "__https",
310 feature = "__quic",
311 feature = "__h3"
312 )
313))]
314mod tests {
315 #[cfg(feature = "__quic")]
316 use std::net::IpAddr;
317
318 use test_support::subscribe;
319
320 use crate::TokioResolver;
321 #[cfg(any(feature = "__tls", feature = "__https"))]
322 use crate::config::CLOUDFLARE;
323 #[cfg(any(
324 feature = "__tls",
325 feature = "__https",
326 feature = "__quic",
327 feature = "__h3"
328 ))]
329 use crate::config::GOOGLE;
330 use crate::config::ResolverConfig;
331 #[cfg(feature = "__quic")]
332 use crate::config::ServerGroup;
333 #[cfg(feature = "__quic")]
334 use crate::config::ServerOrderingStrategy;
335 use crate::net::runtime::TokioRuntimeProvider;
336 #[cfg(feature = "__quic")]
337 use crate::net::tls::client_config;
338
339 #[cfg(feature = "__h3")]
340 #[tokio::test]
341 async fn test_google_h3() {
342 subscribe();
343 h3_test(ResolverConfig::h3(&GOOGLE)).await
344 }
345
346 #[cfg(feature = "__h3")]
347 async fn h3_test(config: ResolverConfig) {
348 let mut builder =
349 TokioResolver::builder_with_config(config, TokioRuntimeProvider::default());
350 builder.options_mut().server_ordering_strategy = ServerOrderingStrategy::UserProvidedOrder;
352 let resolver = builder.build().unwrap();
353
354 let response = resolver
355 .lookup_ip("www.example.com.")
356 .await
357 .expect("failed to run lookup");
358
359 assert_ne!(response.iter().count(), 0);
360
361 let response = resolver
363 .lookup_ip("www.example.com.")
364 .await
365 .expect("failed to run lookup");
366
367 assert_ne!(response.iter().count(), 0);
368 }
369
370 #[cfg(feature = "__quic")]
371 #[tokio::test]
372 async fn test_adguard_quic() {
373 subscribe();
374
375 let config = client_config().unwrap();
377
378 let group = ServerGroup {
379 ips: &[
380 IpAddr::from([94, 140, 14, 140]),
381 IpAddr::from([94, 140, 14, 141]),
382 IpAddr::from([0x2a10, 0x50c0, 0, 0, 0, 0, 0x1, 0xff]),
383 IpAddr::from([0x2a10, 0x50c0, 0, 0, 0, 0, 0x2, 0xff]),
384 ],
385 server_name: "unfiltered.adguard-dns.com",
386 path: "/dns-query",
387 };
388
389 quic_test(ResolverConfig::quic(&group), config).await
390 }
391
392 #[cfg(feature = "__quic")]
393 async fn quic_test(config: ResolverConfig, tls_config: rustls::ClientConfig) {
394 let mut resolver_builder =
395 TokioResolver::builder_with_config(config, TokioRuntimeProvider::default());
396 resolver_builder.options_mut().try_tcp_on_error = true;
397 resolver_builder.options_mut().server_ordering_strategy =
399 ServerOrderingStrategy::UserProvidedOrder;
400 resolver_builder = resolver_builder.with_tls_config(tls_config);
401 let resolver = resolver_builder.build().unwrap();
402
403 let response = resolver
404 .lookup_ip("www.example.com.")
405 .await
406 .expect("failed to run lookup");
407
408 assert_ne!(response.iter().count(), 0);
409
410 let response = resolver
412 .lookup_ip("www.example.com.")
413 .await
414 .expect("failed to run lookup");
415
416 assert_ne!(response.iter().count(), 0);
417 }
418
419 #[cfg(feature = "__https")]
420 #[tokio::test]
421 async fn test_google_https() {
422 subscribe();
423 https_test(ResolverConfig::https(&GOOGLE)).await
424 }
425
426 #[cfg(feature = "__https")]
427 #[tokio::test]
428 async fn test_cloudflare_https() {
429 subscribe();
430 https_test(ResolverConfig::https(&CLOUDFLARE)).await
431 }
432
433 #[cfg(feature = "__https")]
434 async fn https_test(config: ResolverConfig) {
435 let mut resolver_builder =
436 TokioResolver::builder_with_config(config, TokioRuntimeProvider::default());
437 resolver_builder.options_mut().try_tcp_on_error = true;
438 let resolver = resolver_builder.build().unwrap();
439
440 let response = resolver
441 .lookup_ip("www.example.com.")
442 .await
443 .expect("failed to run lookup");
444
445 assert_ne!(response.iter().count(), 0);
446
447 let response = resolver
449 .lookup_ip("www.example.com.")
450 .await
451 .expect("failed to run lookup");
452
453 assert_ne!(response.iter().count(), 0);
454 }
455
456 #[cfg(feature = "__tls")]
457 #[tokio::test]
458 async fn test_google_tls() {
459 subscribe();
460 tls_test(ResolverConfig::tls(&GOOGLE)).await
461 }
462
463 #[cfg(feature = "__tls")]
464 #[tokio::test]
465 async fn test_cloudflare_tls() {
466 subscribe();
467 tls_test(ResolverConfig::tls(&CLOUDFLARE)).await
468 }
469
470 #[cfg(feature = "__tls")]
471 async fn tls_test(config: ResolverConfig) {
472 let mut resolver_builder =
473 TokioResolver::builder_with_config(config, TokioRuntimeProvider::default());
474 resolver_builder.options_mut().try_tcp_on_error = true;
475 let resolver = resolver_builder.build().unwrap();
476
477 let response = resolver
478 .lookup_ip("www.example.com.")
479 .await
480 .expect("failed to run lookup");
481
482 assert_ne!(response.iter().count(), 0);
483 }
484}