Skip to main content

hickory_server/server/
mod.rs

1// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! `Server` component for hosting a domain name servers operations.
9
10use std::{
11    fmt, io,
12    net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
13    sync::Arc,
14    time::Duration,
15};
16
17use bytes::Bytes;
18use futures_util::StreamExt;
19use ipnet::IpNet;
20#[cfg(feature = "__tls")]
21use rustls::{ServerConfig, server::ResolvesServerCert};
22#[cfg(feature = "__tls")]
23use tokio::time::timeout;
24use tokio::{net, task::JoinSet};
25#[cfg(feature = "__tls")]
26use tokio_rustls::TlsAcceptor;
27use tokio_util::sync::CancellationToken;
28use tracing::{debug, info, warn};
29
30#[cfg(feature = "metrics")]
31use crate::metrics::ResponseHandlerMetrics;
32#[cfg(feature = "__h3")]
33use crate::net::h3::h3_server::H3Server;
34#[cfg(feature = "__quic")]
35use crate::net::quic::QuicServer;
36#[cfg(feature = "__tls")]
37use crate::net::tls::{default_provider, tls_from_stream};
38use crate::{
39    access::AccessControl,
40    net::{
41        BufDnsStreamHandle, NetError,
42        runtime::{TokioRuntimeProvider, TokioTime, iocompat::AsyncIoTokioAsStd},
43        tcp::TcpStream,
44        udp::UdpStream,
45        xfer::Protocol,
46    },
47    proto::{
48        op::{Header, LowerQuery, MessageType, Metadata, ResponseCode, SerialMessage},
49        rr::Record,
50        serialize::binary::{BinDecodable, BinDecoder},
51    },
52    zone_handler::{MessageRequest, MessageResponseBuilder, Queries},
53};
54
55#[cfg(feature = "__https")]
56mod h2_handler;
57#[cfg(feature = "__h3")]
58mod h3_handler;
59#[cfg(feature = "__quic")]
60mod quic_handler;
61mod request_handler;
62pub use request_handler::{Request, RequestHandler, RequestInfo, ResponseInfo};
63mod response_handler;
64pub use response_handler::{ResponseHandle, ResponseHandler};
65mod timeout_stream;
66pub use timeout_stream::TimeoutStream;
67
68// TODO, would be nice to have a Slab for buffers here...
69/// A Futures based implementation of a DNS server
70pub struct Server<T: RequestHandler> {
71    context: Arc<ServerContext<T>>,
72    join_set: JoinSet<Result<(), NetError>>,
73}
74
75impl<T: RequestHandler> Server<T> {
76    /// Creates a new ServerFuture with the specified Handler.
77    pub fn new(handler: T) -> Self {
78        Self::with_access(handler, [], [])
79    }
80
81    /// Creates a new ServerFuture with the specified Handler and denied/allowed networks
82    pub fn with_access(
83        handler: T,
84        denied_networks: impl IntoIterator<Item = IpNet>,
85        allowed_networks: impl IntoIterator<Item = IpNet>,
86    ) -> Self {
87        let mut access = AccessControl::default();
88        access.insert_deny(denied_networks);
89        access.insert_allow(allowed_networks);
90
91        Self {
92            context: Arc::new(ServerContext {
93                handler,
94                access,
95                shutdown: CancellationToken::new(),
96            }),
97            join_set: JoinSet::new(),
98        }
99    }
100
101    /// Register a UDP socket. Should be bound before calling this function.
102    pub fn register_socket(&mut self, socket: net::UdpSocket) {
103        self.join_set
104            .spawn(handle_udp(socket, self.context.clone()));
105    }
106
107    /// Register a TcpListener to the Server. This should already be bound to either an IPv6 or an
108    ///  IPv4 address.
109    ///
110    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
111    ///  to not make this too low depending on use cases.
112    ///
113    /// # Arguments
114    /// * `listener` - a bound TCP socket
115    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
116    ///   requests within this time period will be closed. In the future it should be
117    ///   possible to create long-lived queries, but these should be from trusted sources
118    ///   only, this would require some type of whitelisting.
119    /// * `response_buffer_size` - size of the buffer for outgoing responses per connection
120    pub fn register_listener(
121        &mut self,
122        listener: net::TcpListener,
123        timeout: Duration,
124        response_buffer_size: usize,
125    ) {
126        self.join_set.spawn(handle_tcp(
127            listener,
128            timeout,
129            response_buffer_size,
130            self.context.clone(),
131        ));
132    }
133
134    /// Register a TlsListener to the Server. The TlsListener should already be bound to either an
135    /// IPv6 or an IPv4 address.
136    ///
137    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
138    ///  to not make this too low depending on use cases.
139    ///
140    /// The TLS `ServerConfig` should be configured with TLS 1.3 support and the DoT ALPN protocol
141    /// enabled.
142    ///
143    /// # Arguments
144    /// * `listener` - a bound TCP (needs to be on a different port from standard TCP connections) socket
145    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
146    ///   requests within this time period will be closed. In the future it should be
147    ///   possible to create long-lived queries, but these should be from trusted sources
148    ///   only, this would require some type of whitelisting.
149    /// * `tls_config` - rustls server config
150    #[cfg(feature = "__tls")]
151    pub fn register_tls_listener_with_tls_config(
152        &mut self,
153        listener: net::TcpListener,
154        handshake_timeout: Duration,
155        tls_config: Arc<ServerConfig>,
156    ) -> io::Result<()> {
157        self.join_set.spawn(handle_tls(
158            listener,
159            tls_config,
160            handshake_timeout,
161            self.context.clone(),
162        ));
163        Ok(())
164    }
165
166    /// Register a TlsListener to the Server by providing a rustls `ResolvesServerCert`. The
167    /// TlsListener should already be bound to either an IPv6 or an IPv4 address.
168    ///
169    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
170    ///  to not make this too low depending on use cases.
171    ///
172    /// # Arguments
173    /// * `listener` - a bound TCP (needs to be on a different port from standard TCP connections) socket
174    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
175    ///   requests within this time period will be closed. In the future it should be
176    ///   possible to create long-lived queries, but these should be from trusted sources
177    ///   only, this would require some type of whitelisting.
178    /// * `server_cert_resolver` - resolver for the certificate and key used to announce to clients
179    #[cfg(feature = "__tls")]
180    pub fn register_tls_listener(
181        &mut self,
182        listener: net::TcpListener,
183        timeout: Duration,
184        server_cert_resolver: Arc<dyn ResolvesServerCert>,
185    ) -> io::Result<()> {
186        Self::register_tls_listener_with_tls_config(
187            self,
188            listener,
189            timeout,
190            Arc::new(default_tls_server_config(b"dot", server_cert_resolver)?),
191        )
192    }
193
194    /// Register a TcpListener for HTTPS (h2) to the Server for supporting DoH (DNS-over-HTTPS). The TcpListener should already be bound to either an
195    /// IPv6 or an IPv4 address.
196    ///
197    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
198    ///  to not make this too low depending on use cases.
199    ///
200    /// # Arguments
201    /// * `listener` - a bound TCP (needs to be on a different port from standard TCP connections) socket
202    /// * `handshake_timeout` - timeout duration of incoming requests, any connection that does not send
203    ///   requests within this time period will be closed. In the future it should be
204    ///   possible to create long-lived queries, but these should be from trusted sources
205    ///   only, this would require some type of whitelisting.
206    /// * `server_cert_resolver` - resolver for the certificate and key used to announce to clients
207    /// * `dns_hostname` - the DNS hostname of the H2 server.
208    /// * `http_endpoint` - the HTTP endpoint of the H2 server.
209    #[cfg(feature = "__https")]
210    pub fn register_https_listener(
211        &mut self,
212        listener: net::TcpListener,
213        handshake_timeout: Duration,
214        server_cert_resolver: Arc<dyn ResolvesServerCert>,
215        dns_hostname: Option<String>,
216        http_endpoint: String,
217    ) -> io::Result<()> {
218        self.join_set.spawn(h2_handler::handle_h2(
219            listener,
220            handshake_timeout,
221            server_cert_resolver,
222            dns_hostname,
223            http_endpoint,
224            self.context.clone(),
225        ));
226        Ok(())
227    }
228
229    /// Register a TcpListener for HTTPS (h2) for supporting DoH with the given TLS config.
230    ///
231    /// The TcpListener should already be bound to either an IPv6 or an IPv4 address.
232    ///
233    /// The TLS `ServerConfig` should be configured with TLS 1.3 support and the DoH ALPN protocol
234    /// enabled.
235    ///
236    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
237    ///  to not make this too low depending on use cases.
238    ///
239    /// # Arguments
240    /// * `listener` - a bound TCP (needs to be on a different port from standard TCP connections) socket
241    /// * `handshake_timeout` - timeout duration of incoming requests, any connection that does not send
242    ///   requests within this time period will be closed. In the future it should be
243    ///   possible to create long-lived queries, but these should be from trusted sources
244    ///   only, this would require some type of whitelisting.
245    /// * `tls_config` - a customized `ServerConfig` to use for TLS.
246    /// * `dns_hostname` - the DNS hostname of the H2 server.
247    /// * `http_endpoint` - the HTTP endpoint of the H2 server.
248    #[cfg(feature = "__https")]
249    pub fn register_https_listener_with_tls_config(
250        &mut self,
251        listener: net::TcpListener,
252        handshake_timeout: Duration,
253        tls_config: Arc<ServerConfig>,
254        dns_hostname: Option<String>,
255        http_endpoint: String,
256    ) -> io::Result<()> {
257        self.join_set.spawn(h2_handler::handle_h2_with_acceptor(
258            listener,
259            handshake_timeout,
260            TlsAcceptor::from(tls_config),
261            dns_hostname,
262            http_endpoint,
263            self.context.clone(),
264        ));
265        Ok(())
266    }
267
268    /// Register a UdpSocket to the Server for supporting DoQ (DNS-over-QUIC). The UdpSocket should already be bound to either an
269    /// IPv6 or an IPv4 address.
270    ///
271    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
272    ///  to not make this too low depending on use cases.
273    ///
274    /// # Arguments
275    /// * `socket` - a bound UDP socket
276    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
277    ///   requests within this time period will be closed. In the future it should be
278    ///   possible to create long-lived queries, but these should be from trusted sources
279    ///   only, this would require some type of whitelisting.
280    /// * `server_cert_resolver` - resolver for certificate and key used to announce to clients
281    /// * `dns_hostname` - the DNS hostname of the DoQ server.
282    #[cfg(feature = "__quic")]
283    pub fn register_quic_listener(
284        &mut self,
285        socket: net::UdpSocket,
286        timeout: Duration,
287        server_cert_resolver: Arc<dyn ResolvesServerCert>,
288    ) -> io::Result<()> {
289        let cx = self.context.clone();
290        self.join_set.spawn(quic_handler::handle_quic(
291            socket,
292            timeout,
293            server_cert_resolver,
294            cx,
295        ));
296        Ok(())
297    }
298
299    /// Register a UdpSocket for supporting DoQ (DNS-over-QUIC) with the provided TLS config.
300    ///
301    /// The UdpSocket should already be bound to either an IPv6 or an IPv4 address.
302    ///
303    /// The TLS `ServerConfig` should be configured with TLS 1.3 support and the DoQ ALPN protocol
304    /// enabled.
305    ///
306    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
307    ///  to not make this too low depending on use cases.
308    ///
309    /// # Arguments
310    /// * `socket` - a bound UDP socket
311    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
312    ///   requests within this time period will be closed. In the future it should be
313    ///   possible to create long-lived queries, but these should be from trusted sources
314    ///   only, this would require some type of whitelisting.
315    /// * `tls_config` - a customized ServerConfig to use for TLS.
316    /// * `dns_hostname` - the DNS hostname of the DoQ server.
317    #[cfg(feature = "__quic")]
318    pub fn register_quic_listener_and_tls_config(
319        &mut self,
320        socket: net::UdpSocket,
321        timeout: Duration,
322        tls_config: Arc<ServerConfig>,
323    ) -> Result<(), NetError> {
324        let cx = self.context.clone();
325
326        self.join_set.spawn(quic_handler::handle_quic_with_server(
327            QuicServer::with_socket_and_tls_config(socket, tls_config)?,
328            timeout,
329            cx,
330        ));
331        Ok(())
332    }
333
334    /// Register a UdpSocket to the Server for supporting DoH3 (DNS-over-HTTP/3). The UdpSocket should already be bound to either an
335    /// IPv6 or an IPv4 address.
336    ///
337    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
338    ///  to not make this too low depending on use cases.
339    ///
340    /// # Arguments
341    /// * `listener` - a bound TCP (needs to be on a different port from standard TCP connections) socket
342    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
343    ///   requests within this time period will be closed. In the future it should be
344    ///   possible to create long-lived queries, but these should be from trusted sources
345    ///   only, this would require some type of whitelisting.
346    /// * `server_cert_resolver` - resolver for certificate and key used to announce to clients
347    #[cfg(feature = "__h3")]
348    pub fn register_h3_listener(
349        &mut self,
350        socket: net::UdpSocket,
351        timeout: Duration,
352        server_cert_resolver: Arc<dyn ResolvesServerCert>,
353        dns_hostname: Option<String>,
354    ) -> io::Result<()> {
355        self.join_set.spawn(h3_handler::handle_h3(
356            socket,
357            timeout,
358            server_cert_resolver,
359            dns_hostname,
360            self.context.clone(),
361        ));
362        Ok(())
363    }
364
365    /// Register a UdpSocket for supporting DoH3 (DNS-over-HTTP/3) with the specified TLS config.
366    ///
367    /// The UdpSocket should already be bound to either an IPv6 or an IPv4 address.
368    ///
369    /// The TLS `ServerConfig` should be configured with TLS 1.3 support and the DoH3 ALPN protocol
370    /// enabled.
371    ///
372    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
373    ///  to not make this too low depending on use cases.
374    ///
375    /// # Arguments
376    /// * `listener` - a bound TCP (needs to be on a different port from standard TCP connections) socket
377    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
378    ///   requests within this time period will be closed. In the future it should be
379    ///   possible to create long-lived queries, but these should be from trusted sources
380    ///   only, this would require some type of whitelisting.
381    /// * `tls_config` - a customized ServerConfig to use for TLS.
382    #[cfg(feature = "__h3")]
383    pub fn register_h3_listener_with_tls_config(
384        &mut self,
385        socket: net::UdpSocket,
386        timeout: Duration,
387        tls_config: Arc<ServerConfig>,
388        dns_hostname: Option<String>,
389    ) -> Result<(), NetError> {
390        self.join_set.spawn(h3_handler::handle_h3_with_server(
391            H3Server::with_socket_and_tls_config(socket, tls_config)?,
392            timeout,
393            dns_hostname,
394            self.context.clone(),
395        ));
396        Ok(())
397    }
398
399    /// Triggers a graceful shutdown the server. All background tasks will stop accepting
400    /// new connections and the returned future will complete once all tasks have terminated.
401    pub async fn shutdown_gracefully(&mut self) -> Result<(), NetError> {
402        self.context.shutdown.cancel();
403
404        // Wait for the server to complete.
405        self.block_until_done().await
406    }
407
408    /// Returns a reference to the [`CancellationToken`] used to gracefully shut down the server.
409    ///
410    /// Once cancellation is requested, all background tasks will stop accepting new connections,
411    /// and `block_until_done()` will complete once all tasks have terminated.
412    pub fn shutdown_token(&self) -> &CancellationToken {
413        &self.context.shutdown
414    }
415
416    /// This will run until all background tasks complete. If one or more tasks return an error,
417    /// one will be chosen as the returned error for this future.
418    pub async fn block_until_done(&mut self) -> Result<(), NetError> {
419        if self.join_set.is_empty() {
420            warn!("block_until_done called with no pending tasks");
421            return Ok(());
422        }
423
424        let mut out = Ok(());
425        while let Some(join_result) = self.join_set.join_next().await {
426            match join_result {
427                Ok(Ok(())) => continue,
428                Ok(Err(e)) => out = Err(e),
429                Err(e) => return Err(NetError::from(format!("internal error in spawn: {e}"))),
430            }
431        }
432
433        out
434    }
435}
436
437async fn handle_udp(
438    socket: net::UdpSocket,
439    cx: Arc<ServerContext<impl RequestHandler>>,
440) -> Result<(), NetError> {
441    debug!("registering udp: {:?}", socket);
442
443    // create the new UdpStream, the IP address isn't relevant, and ideally goes essentially no where.
444    //   the address used is acquired from the inbound queries
445    let (mut stream, stream_handle) =
446        UdpStream::<TokioRuntimeProvider>::with_bound(socket, ([127, 255, 255, 254], 0).into());
447
448    let mut inner_join_set = JoinSet::new();
449    loop {
450        let message = tokio::select! {
451            message = stream.next() => match message {
452                None => break,
453                Some(message) => message,
454            },
455            _ = cx.shutdown.cancelled() => break,
456        };
457
458        let message = match message {
459            Err(error) => {
460                warn!(%error, "error receiving message on udp_socket");
461                if is_unrecoverable_socket_error(&error) {
462                    break;
463                }
464                continue;
465            }
466            Ok(message) => message,
467        };
468
469        let src_addr = message.addr();
470        debug!("received udp request from: {}", src_addr);
471
472        // verify that the src address is safe for responses
473        if let Err(e) = sanitize_src_address(src_addr) {
474            warn!(
475                "address can not be responded to {src_addr}: {e}",
476                src_addr = src_addr,
477                e = e
478            );
479            continue;
480        }
481
482        let cx = cx.clone();
483        let stream_handle = stream_handle.with_remote_addr(src_addr);
484        inner_join_set.spawn(async move {
485            cx.handle_raw_request(message, Protocol::Udp, stream_handle)
486                .await;
487        });
488
489        reap_tasks(&mut inner_join_set);
490    }
491
492    if cx.shutdown.is_cancelled() {
493        Ok(())
494    } else {
495        // TODO: let's consider capturing all the initial configuration details so that the socket could be recreated...
496        Err(NetError::from("unexpected close of UDP socket"))
497    }
498}
499
500async fn handle_tcp(
501    listener: net::TcpListener,
502    timeout: Duration,
503    response_buffer_size: usize,
504    cx: Arc<ServerContext<impl RequestHandler>>,
505) -> Result<(), NetError> {
506    debug!("register tcp: {listener:?}");
507    let mut inner_join_set = JoinSet::new();
508    loop {
509        let (tcp_stream, src_addr) = tokio::select! {
510            tcp_stream = listener.accept() => match tcp_stream {
511                Ok((t, s)) => (t, s),
512                Err(error) => {
513                    debug!(%error, "error receiving TCP tcp_stream error");
514                    if is_unrecoverable_socket_error(&error) {
515                        break;
516                    }
517                    continue;
518                },
519            },
520            _ = cx.shutdown.cancelled() => {
521                // A graceful shutdown was initiated. Break out of the loop.
522                break;
523            },
524        };
525
526        // verify that the src address is safe for responses
527        if let Err(error) = sanitize_src_address(src_addr) {
528            warn!(
529                %src_addr, %error,
530                "address can not be responded to (TCP)",
531            );
532            continue;
533        }
534
535        // and spawn to the io_loop
536        let cx = cx.clone();
537        inner_join_set.spawn(async move {
538            debug!(%src_addr, "accepted TCP request");
539            // take the created stream...
540            let (buf_stream, stream_handle) = TcpStream::from_stream_with_buffer_size(
541                AsyncIoTokioAsStd(tcp_stream),
542                src_addr,
543                response_buffer_size,
544            );
545            let mut timeout_stream = TimeoutStream::new(buf_stream, timeout);
546
547            while let Some(message) = timeout_stream.next().await {
548                let message = match message {
549                    Ok(message) => message,
550                    Err(error) => {
551                        debug!(%src_addr, %error, "error in TCP request stream");
552                        // we're going to bail on this connection...
553                        return;
554                    }
555                };
556
557                // we don't spawn here to limit clients from getting too many resources
558                cx.handle_raw_request(message, Protocol::Tcp, stream_handle.clone())
559                    .await;
560            }
561        });
562
563        reap_tasks(&mut inner_join_set);
564    }
565
566    if cx.shutdown.is_cancelled() {
567        Ok(())
568    } else {
569        Err(NetError::from("unexpected close of socket"))
570    }
571}
572
573#[cfg(feature = "__tls")]
574async fn handle_tls(
575    listener: net::TcpListener,
576    tls_config: Arc<ServerConfig>,
577    handshake_timeout: Duration,
578    cx: Arc<ServerContext<impl RequestHandler>>,
579) -> Result<(), NetError> {
580    debug!(?listener, "registered tls");
581    let tls_acceptor = TlsAcceptor::from(tls_config);
582
583    let mut inner_join_set = JoinSet::new();
584    loop {
585        let (tcp_stream, src_addr) = tokio::select! {
586            tcp_stream = listener.accept() => match tcp_stream {
587                Ok((t, s)) => (t, s),
588                Err(error) => {
589                    debug!(%error, "error receiving TLS tcp_stream error");
590                    if is_unrecoverable_socket_error(&error) {
591                        break;
592                    }
593                    continue;
594                },
595            },
596            _ = cx.shutdown.cancelled() => {
597                // A graceful shutdown was initiated. Break out of the loop.
598                break;
599            },
600        };
601
602        // verify that the src address is safe for responses
603        if let Err(error) = sanitize_src_address(src_addr) {
604            warn!(
605                %src_addr, %error,
606                "address can not be responded to (TLS)",
607            );
608            continue;
609        }
610
611        let cx = cx.clone();
612        let tls_acceptor = tls_acceptor.clone();
613        // kick out to a different task immediately, let them do the TLS handshake
614        inner_join_set.spawn(async move {
615            debug!(%src_addr, "starting TLS request");
616
617            // perform the TLS
618            let Ok(tls_stream) = timeout(handshake_timeout, tls_acceptor.accept(tcp_stream)).await
619            else {
620                warn!("tls timeout expired during handshake");
621                return;
622            };
623
624            let tls_stream = match tls_stream {
625                Ok(tls_stream) => AsyncIoTokioAsStd(tls_stream),
626                Err(error) => {
627                    debug!(%src_addr, %error, "tls handshake error");
628                    return;
629                }
630            };
631            debug!(%src_addr, "accepted TLS request");
632            let (buf_stream, stream_handle) = tls_from_stream(tls_stream, src_addr);
633            let mut timeout_stream = TimeoutStream::new(buf_stream, handshake_timeout);
634            while let Some(message) = timeout_stream.next().await {
635                let message = match message {
636                    Ok(message) => message,
637                    Err(error) => {
638                        debug!(
639                            %src_addr, %error,
640                            "error in TLS request stream",
641                        );
642
643                        // kill this connection
644                        return;
645                    }
646                };
647
648                cx.handle_raw_request(message, Protocol::Tls, stream_handle.clone())
649                    .await;
650            }
651        });
652
653        reap_tasks(&mut inner_join_set);
654    }
655
656    if cx.shutdown.is_cancelled() {
657        Ok(())
658    } else {
659        Err(NetError::from("unexpected close of socket"))
660    }
661}
662
663/// Reap finished tasks from a `JoinSet`, without awaiting or blocking.
664fn reap_tasks(join_set: &mut JoinSet<()>) {
665    while join_set.try_join_next().is_some() {}
666}
667
668/// Construct a default `ServerConfig` for the given ALPN protocol and server cert resolver.
669#[cfg(feature = "__tls")]
670pub fn default_tls_server_config(
671    protocol: &[u8],
672    server_cert_resolver: Arc<dyn ResolvesServerCert>,
673) -> io::Result<ServerConfig> {
674    let mut config = ServerConfig::builder_with_provider(Arc::new(default_provider()))
675        .with_safe_default_protocol_versions()
676        .map_err(|e| io::Error::other(format!("error creating TLS acceptor: {e}")))?
677        .with_no_client_auth()
678        .with_cert_resolver(server_cert_resolver);
679
680    config.alpn_protocols = vec![protocol.to_vec()];
681
682    Ok(config)
683}
684
685#[derive(Clone)]
686pub(super) struct ReportingResponseHandler<R: ResponseHandler> {
687    pub(super) request_meta: Metadata,
688    queries: Vec<LowerQuery>,
689    pub(super) protocol: Protocol,
690    src_addr: SocketAddr,
691    handler: R,
692    #[cfg(feature = "metrics")]
693    metrics: ResponseHandlerMetrics,
694}
695
696#[async_trait::async_trait]
697impl<R: ResponseHandler> ResponseHandler for ReportingResponseHandler<R> {
698    async fn send_response<'a>(
699        &mut self,
700        response: crate::zone_handler::MessageResponse<
701            '_,
702            'a,
703            impl Iterator<Item = &'a Record> + Send + 'a,
704            impl Iterator<Item = &'a Record> + Send + 'a,
705            impl Iterator<Item = &'a Record> + Send + 'a,
706            impl Iterator<Item = &'a Record> + Send + 'a,
707        >,
708    ) -> Result<ResponseInfo, NetError> {
709        let response_info = self.handler.send_response(response).await?;
710
711        let id = self.request_meta.id;
712        let rid = response_info.id;
713        if id != rid {
714            warn!("request id:{id} does not match response id:{rid}");
715            debug_assert_eq!(id, rid, "request id and response id should match");
716        }
717
718        let rflags = response_info.flags();
719        let answer_count = response_info.counts().answers;
720        let authority_count = response_info.counts().authorities;
721        let additional_count = response_info.counts().additionals;
722        let response_code = response_info.response_code;
723
724        info!(
725            "request:{id} src:{proto}://{addr}#{port} {op} qflags:{qflags} response:{code:?} rr:{answers}/{authorities}/{additionals} rflags:{rflags}",
726            id = rid,
727            proto = self.protocol,
728            addr = self.src_addr.ip(),
729            port = self.src_addr.port(),
730            op = self.request_meta.op_code,
731            qflags = self.request_meta.flags(),
732            code = response_code,
733            answers = answer_count,
734            authorities = authority_count,
735            additionals = additional_count,
736            rflags = rflags
737        );
738        for query in self.queries.iter() {
739            info!(
740                "query:{query}:{qtype}:{class}",
741                query = query.name(),
742                qtype = query.query_type(),
743                class = query.query_class()
744            );
745        }
746
747        #[cfg(feature = "metrics")]
748        self.metrics.update(self, &response_info);
749
750        Ok(response_info)
751    }
752}
753
754struct ServerContext<T> {
755    handler: T,
756    access: AccessControl,
757    shutdown: CancellationToken,
758}
759
760impl<T: RequestHandler> ServerContext<T> {
761    async fn handle_raw_request(
762        &self,
763        message: SerialMessage,
764        protocol: Protocol,
765        response_handler: BufDnsStreamHandle,
766    ) {
767        let (message, src_addr) = message.into_parts();
768        let response_handler = ResponseHandle::new(src_addr, response_handler, protocol);
769
770        self.handle_request(Bytes::from(message), src_addr, protocol, response_handler)
771            .await;
772    }
773
774    async fn handle_request(
775        &self,
776        message_bytes: Bytes,
777        src_addr: SocketAddr,
778        protocol: Protocol,
779        response_handler: impl ResponseHandler,
780    ) {
781        let mut decoder = BinDecoder::new(&message_bytes);
782        let Ok(header) = Header::read(&mut decoder) else {
783            // This will only fail if the message is less than twelve bytes long. Such messages are
784            // definitely not valid DNS queries, so it should be fine to return without sending a
785            // response.
786            return;
787        };
788
789        if !self.access.allow(src_addr.ip()) {
790            info!(
791                "request:Refused src:{proto}://{addr}#{port}",
792                proto = protocol,
793                addr = src_addr.ip(),
794                port = src_addr.port(),
795            );
796
797            let queries = match Queries::read(&mut decoder, header.counts.queries as usize) {
798                Ok(queries) => queries,
799                Err(_) => Queries::empty(),
800            };
801            error_response_handler(
802                protocol,
803                src_addr,
804                header,
805                queries,
806                ResponseCode::Refused,
807                "request refused",
808                response_handler,
809            )
810            .await;
811
812            return;
813        }
814
815        // Attempt to decode the message
816        let request = match MessageRequest::read(&mut decoder, header) {
817            Ok(message) => Request {
818                message,
819                raw: message_bytes,
820                src: src_addr,
821                protocol,
822            },
823            Err(error) => {
824                // We failed to parse the request due to some issue in the message, but the header is available, so we can respond
825                let queries = Queries::empty();
826
827                error_response_handler(
828                    protocol,
829                    src_addr,
830                    header,
831                    queries,
832                    ResponseCode::FormErr,
833                    error,
834                    response_handler,
835                )
836                .await;
837
838                return;
839            }
840        };
841
842        if request.message.metadata.message_type == MessageType::Response {
843            // Don't process response messages to avoid DoS attacks from reflection.
844            return;
845        }
846
847        let id = request.message.metadata.id;
848        let qflags = request.message.metadata.flags();
849        let qop_code = request.message.metadata.op_code;
850        let message_type = request.message.metadata.message_type;
851        let is_dnssec = request
852            .message
853            .edns
854            .as_ref()
855            .is_some_and(|edns| edns.flags().dnssec_ok);
856
857        debug!(
858            "request:{id} src:{proto}://{addr}#{port} type:{message_type} dnssec:{is_dnssec} {op} qflags:{qflags}",
859            id = id,
860            proto = request.protocol(),
861            addr = request.src().ip(),
862            port = request.src().port(),
863            message_type = message_type,
864            is_dnssec = is_dnssec,
865            op = qop_code,
866            qflags = qflags
867        );
868        for query in request.queries.queries().iter() {
869            debug!(
870                "query:{query}:{qtype}:{class}",
871                query = query.name(),
872                qtype = query.query_type(),
873                class = query.query_class()
874            );
875        }
876
877        // The reporter will handle making sure to log the result of the request
878        let queries = request.queries.queries().to_vec();
879        let reporter = ReportingResponseHandler {
880            request_meta: request.metadata,
881            queries,
882            protocol: request.protocol(),
883            src_addr: request.src(),
884            handler: response_handler,
885            #[cfg(feature = "metrics")]
886            metrics: ResponseHandlerMetrics::default(),
887        };
888
889        self.handler
890            .handle_request::<_, TokioTime>(&request, reporter)
891            .await;
892    }
893}
894
895// method to return an error to the client
896async fn error_response_handler(
897    protocol: Protocol,
898    src_addr: SocketAddr,
899    header: Header,
900    queries: Queries,
901    response_code: ResponseCode,
902    error: impl fmt::Display,
903    response_handler: impl ResponseHandler,
904) {
905    // debug for more info on why the message parsing failed
906    debug!(
907        "request:{id} src:{proto}://{addr}#{port} type:{message_type} {op}:{response_code}:{error}",
908        id = header.id,
909        proto = protocol,
910        addr = src_addr.ip(),
911        port = src_addr.port(),
912        message_type = header.message_type,
913        op = header.op_code,
914        response_code = response_code,
915        error = error,
916    );
917
918    // The reporter will handle making sure to log the result of the request
919    let mut reporter = ReportingResponseHandler {
920        request_meta: header.metadata,
921        queries: queries.queries().to_vec(),
922        protocol,
923        src_addr,
924        handler: response_handler,
925        #[cfg(feature = "metrics")]
926        metrics: ResponseHandlerMetrics::default(),
927    };
928
929    let response = MessageResponseBuilder::new(&queries, None);
930    let result = reporter
931        .send_response(response.error_msg(&header, response_code))
932        .await;
933
934    if let Err(error) = result {
935        warn!(%error, "failed to return FormError to client");
936    }
937}
938
939/// Checks if the IP address is safe for returning messages
940///
941/// Examples of unsafe addresses are any with a port of `0`
942///
943/// # Returns
944///
945/// Error if the address should not be used for returned requests
946fn sanitize_src_address(src: SocketAddr) -> Result<(), String> {
947    // currently checks that the src address aren't either the undefined IPv4 or IPv6 address, and not port 0.
948    if src.port() == 0 {
949        return Err(format!("cannot respond to src on port 0: {src}"));
950    }
951
952    fn verify_v4(src: Ipv4Addr) -> Result<(), String> {
953        if src.is_unspecified() {
954            return Err(format!("cannot respond to unspecified v4 addr: {src}"));
955        }
956
957        if src.is_broadcast() {
958            return Err(format!("cannot respond to broadcast v4 addr: {src}"));
959        }
960
961        // TODO: add check for is_reserved when that stabilizes
962
963        Ok(())
964    }
965
966    fn verify_v6(src: Ipv6Addr) -> Result<(), String> {
967        if src.is_unspecified() {
968            return Err(format!("cannot respond to unspecified v6 addr: {src}"));
969        }
970
971        Ok(())
972    }
973
974    // currently checks that the src address aren't either the undefined IPv4 or IPv6 address, and not port 0.
975    match src.ip() {
976        IpAddr::V4(v4) => verify_v4(v4),
977        IpAddr::V6(v6) => verify_v6(v6),
978    }
979}
980
981fn is_unrecoverable_socket_error(err: &io::Error) -> bool {
982    matches!(
983        err.kind(),
984        io::ErrorKind::NotConnected | io::ErrorKind::ConnectionAborted
985    )
986}
987
988#[cfg(test)]
989mod tests {
990    use super::*;
991    use crate::zone_handler::Catalog;
992    use futures_util::future;
993    #[cfg(feature = "__tls")]
994    use rustls::{
995        pki_types::{CertificateDer, PrivateKeyDer},
996        sign::{CertifiedKey, SingleCertAndKey},
997    };
998    use std::net::SocketAddr;
999    use test_support::subscribe;
1000    use tokio::net::{TcpListener, UdpSocket};
1001    use tokio::time::timeout;
1002
1003    #[tokio::test]
1004    async fn abort() {
1005        subscribe();
1006
1007        let endpoints = Endpoints::new().await;
1008
1009        let endpoints2 = endpoints.clone();
1010        let (abortable, abort_handle) = future::abortable(async move {
1011            let mut server_future = Server::new(Catalog::new());
1012            endpoints2.register(&mut server_future).await;
1013            server_future.block_until_done().await
1014        });
1015
1016        abort_handle.abort();
1017        abortable.await.expect_err("expected abort");
1018
1019        endpoints.rebind_all().await;
1020    }
1021
1022    #[tokio::test]
1023    async fn graceful_shutdown() {
1024        subscribe();
1025        let mut server_future = Server::new(Catalog::new());
1026        let endpoints = Endpoints::new().await;
1027        endpoints.register(&mut server_future).await;
1028
1029        timeout(Duration::from_secs(2), server_future.shutdown_gracefully())
1030            .await
1031            .expect("timed out waiting for the server to complete")
1032            .expect("error while awaiting tasks");
1033
1034        endpoints.rebind_all().await;
1035    }
1036
1037    #[test]
1038    fn test_sanitize_src_addr() {
1039        // ipv4 tests
1040        assert!(sanitize_src_address(SocketAddr::from(([192, 168, 1, 1], 4_096))).is_ok());
1041        assert!(sanitize_src_address(SocketAddr::from(([127, 0, 0, 1], 53))).is_ok());
1042
1043        assert!(sanitize_src_address(SocketAddr::from(([0, 0, 0, 0], 0))).is_err());
1044        assert!(sanitize_src_address(SocketAddr::from(([192, 168, 1, 1], 0))).is_err());
1045        assert!(sanitize_src_address(SocketAddr::from(([0, 0, 0, 0], 4_096))).is_err());
1046        assert!(sanitize_src_address(SocketAddr::from(([255, 255, 255, 255], 4_096))).is_err());
1047
1048        // ipv6 tests
1049        assert!(
1050            sanitize_src_address(SocketAddr::from(([0x20, 0, 0, 0, 0, 0, 0, 0x1], 4_096))).is_ok()
1051        );
1052        assert!(sanitize_src_address(SocketAddr::from(([0, 0, 0, 0, 0, 0, 0, 1], 4_096))).is_ok());
1053
1054        assert!(sanitize_src_address(SocketAddr::from(([0, 0, 0, 0, 0, 0, 0, 0], 4_096))).is_err());
1055        assert!(sanitize_src_address(SocketAddr::from(([0, 0, 0, 0, 0, 0, 0, 0], 0))).is_err());
1056        assert!(
1057            sanitize_src_address(SocketAddr::from(([0x20, 0, 0, 0, 0, 0, 0, 0x1], 0))).is_err()
1058        );
1059    }
1060
1061    #[derive(Clone)]
1062    struct Endpoints {
1063        udp_addr: SocketAddr,
1064        tcp_addr: SocketAddr,
1065        #[cfg(feature = "__tls")]
1066        rustls_addr: SocketAddr,
1067        #[cfg(feature = "__https")]
1068        https_rustls_addr: SocketAddr,
1069        #[cfg(feature = "__quic")]
1070        quic_addr: SocketAddr,
1071        #[cfg(feature = "__h3")]
1072        h3_addr: SocketAddr,
1073    }
1074
1075    impl Endpoints {
1076        async fn new() -> Self {
1077            let udp = UdpSocket::bind("127.0.0.1:0").await.unwrap();
1078            let tcp = TcpListener::bind("127.0.0.1:0").await.unwrap();
1079            #[cfg(feature = "__tls")]
1080            let rustls = TcpListener::bind("127.0.0.1:0").await.unwrap();
1081            #[cfg(feature = "__https")]
1082            let https_rustls = TcpListener::bind("127.0.0.1:0").await.unwrap();
1083            #[cfg(feature = "__quic")]
1084            let quic = UdpSocket::bind("127.0.0.1:0").await.unwrap();
1085            #[cfg(feature = "__h3")]
1086            let h3 = UdpSocket::bind("127.0.0.1:0").await.unwrap();
1087
1088            Self {
1089                udp_addr: udp.local_addr().unwrap(),
1090                tcp_addr: tcp.local_addr().unwrap(),
1091                #[cfg(feature = "__tls")]
1092                rustls_addr: rustls.local_addr().unwrap(),
1093                #[cfg(feature = "__https")]
1094                https_rustls_addr: https_rustls.local_addr().unwrap(),
1095                #[cfg(feature = "__quic")]
1096                quic_addr: quic.local_addr().unwrap(),
1097                #[cfg(feature = "__h3")]
1098                h3_addr: h3.local_addr().unwrap(),
1099            }
1100        }
1101
1102        async fn register<T: RequestHandler>(&self, server: &mut Server<T>) {
1103            server.register_socket(UdpSocket::bind(self.udp_addr).await.unwrap());
1104            server.register_listener(
1105                TcpListener::bind(self.tcp_addr).await.unwrap(),
1106                Duration::from_secs(1),
1107                32,
1108            );
1109
1110            #[cfg(feature = "__tls")]
1111            {
1112                let cert_key = rustls_cert_key();
1113                server
1114                    .register_tls_listener(
1115                        TcpListener::bind(self.rustls_addr).await.unwrap(),
1116                        Duration::from_secs(30),
1117                        cert_key,
1118                    )
1119                    .unwrap();
1120            }
1121
1122            #[cfg(feature = "__https")]
1123            {
1124                let cert_key = rustls_cert_key();
1125                server
1126                    .register_https_listener(
1127                        TcpListener::bind(self.https_rustls_addr).await.unwrap(),
1128                        Duration::from_secs(1),
1129                        cert_key,
1130                        None,
1131                        "/dns-query".into(),
1132                    )
1133                    .unwrap();
1134            }
1135
1136            #[cfg(feature = "__quic")]
1137            {
1138                let cert_key = rustls_cert_key();
1139                server
1140                    .register_quic_listener(
1141                        UdpSocket::bind(self.quic_addr).await.unwrap(),
1142                        Duration::from_secs(1),
1143                        cert_key,
1144                    )
1145                    .unwrap();
1146            }
1147
1148            #[cfg(feature = "__h3")]
1149            {
1150                let cert_key = rustls_cert_key();
1151                server
1152                    .register_h3_listener(
1153                        UdpSocket::bind(self.h3_addr).await.unwrap(),
1154                        Duration::from_secs(1),
1155                        cert_key,
1156                        None,
1157                    )
1158                    .unwrap();
1159            }
1160        }
1161
1162        async fn rebind_all(&self) {
1163            UdpSocket::bind(self.udp_addr).await.unwrap();
1164            TcpListener::bind(self.tcp_addr).await.unwrap();
1165            #[cfg(feature = "__tls")]
1166            TcpListener::bind(self.rustls_addr).await.unwrap();
1167            #[cfg(feature = "__https")]
1168            TcpListener::bind(self.https_rustls_addr).await.unwrap();
1169            #[cfg(feature = "__quic")]
1170            UdpSocket::bind(self.quic_addr).await.unwrap();
1171            #[cfg(feature = "__h3")]
1172            UdpSocket::bind(self.h3_addr).await.unwrap();
1173        }
1174    }
1175
1176    #[cfg(feature = "__tls")]
1177    fn rustls_cert_key() -> Arc<dyn ResolvesServerCert> {
1178        use rustls::pki_types::pem::PemObject;
1179        use std::env;
1180
1181        let server_path = env::var("TDNS_WORKSPACE_ROOT").unwrap_or_else(|_| "../..".to_owned());
1182        let cert_chain =
1183            CertificateDer::pem_file_iter(format!("{server_path}/tests/test-data/cert.pem"))
1184                .unwrap()
1185                .collect::<Result<Vec<_>, _>>()
1186                .unwrap();
1187
1188        let key = PrivateKeyDer::from_pem_file(format!("{server_path}/tests/test-data/cert.key"))
1189            .unwrap();
1190
1191        let certified_key = CertifiedKey::from_der(cert_chain, key, &default_provider()).unwrap();
1192        Arc::new(SingleCertAndKey::from(certified_key))
1193    }
1194
1195    #[test]
1196    fn task_reap_on_empty_joinset() {
1197        let mut joinset = JoinSet::new();
1198
1199        // this should return immediately
1200        reap_tasks(&mut joinset);
1201    }
1202
1203    #[tokio::test]
1204    async fn task_reap_on_nonempty_joinset() {
1205        let mut joinset = JoinSet::new();
1206        let t = joinset.spawn(tokio::time::sleep(Duration::from_secs(2)));
1207
1208        // this should return immediately since no task is ready
1209        reap_tasks(&mut joinset);
1210        t.abort();
1211
1212        // this should also return immediately since the task has been aborted
1213        reap_tasks(&mut joinset);
1214    }
1215}