1 use crate::errors::*;
2 use crate::*;
3 
4 use byteorder::{BigEndian, ByteOrder};
5 use ipext::IpExt;
6 use siphasher::sip128::Hasher128;
7 use std::hash::Hasher;
8 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
9 use std::sync::Arc;
10 use tokio::net::UdpSocket;
11 
12 pub const ANONYMIZED_DNSCRYPT_QUERY_MAGIC: [u8; 10] =
13     [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00];
14 
15 pub const ANONYMIZED_DNSCRYPT_OVERHEAD: usize = 16 + 2;
16 
17 pub const RELAYED_CERT_CACHE_SIZE: usize = 1000;
18 pub const RELAYED_CERT_CACHE_TTL: u32 = 600;
19 
handle_anonymized_dns( globals: Arc<Globals>, client_ctx: ClientCtx, relayed_packet: &[u8], ) -> Result<(), Error>20 pub async fn handle_anonymized_dns(
21     globals: Arc<Globals>,
22     client_ctx: ClientCtx,
23     relayed_packet: &[u8],
24 ) -> Result<(), Error> {
25     ensure!(
26         relayed_packet.len() > ANONYMIZED_DNSCRYPT_OVERHEAD,
27         "Short packet"
28     );
29     let ip_bin = &relayed_packet[..16];
30     let ip_v6 = Ipv6Addr::new(
31         BigEndian::read_u16(&ip_bin[0..2]),
32         BigEndian::read_u16(&ip_bin[2..4]),
33         BigEndian::read_u16(&ip_bin[4..6]),
34         BigEndian::read_u16(&ip_bin[6..8]),
35         BigEndian::read_u16(&ip_bin[8..10]),
36         BigEndian::read_u16(&ip_bin[10..12]),
37         BigEndian::read_u16(&ip_bin[12..14]),
38         BigEndian::read_u16(&ip_bin[14..16]),
39     );
40     let ip = match ip_v6.to_ipv4() {
41         Some(ip_v4) => IpAddr::V4(ip_v4),
42         None => IpAddr::V6(ip_v6),
43     };
44     #[cfg(feature = "metrics")]
45     globals.varz.anonymized_queries.inc();
46 
47     ensure!(IpExt::is_global(&ip), "Forbidden upstream address");
48     ensure!(
49         !globals.anonymized_dns_blacklisted_ips.contains(&ip),
50         "Blacklisted upstream IP"
51     );
52     let port = BigEndian::read_u16(&relayed_packet[16..18]);
53     ensure!(
54         (globals.anonymized_dns_allow_non_reserved_ports && port >= 1024)
55             || globals.anonymized_dns_allowed_ports.contains(&port),
56         "Forbidden upstream port"
57     );
58     let upstream_address = SocketAddr::new(ip, port);
59     ensure!(
60         !globals.listen_addrs.contains(&upstream_address)
61             && globals.external_addr != Some(upstream_address),
62         "Would be relaying to self"
63     );
64     let encrypted_packet = &relayed_packet[ANONYMIZED_DNSCRYPT_OVERHEAD..];
65     let encrypted_packet_len = encrypted_packet.len();
66     ensure!(
67         encrypted_packet_len >= ANONYMIZED_DNSCRYPT_QUERY_MAGIC.len() + DNS_HEADER_SIZE
68             && encrypted_packet_len <= DNSCRYPT_UDP_QUERY_MAX_SIZE,
69         "Unexpected encapsulated query length"
70     );
71     ensure!(
72         encrypted_packet_len > 8 && [0u8, 0, 0, 0, 0, 0, 0, 1] != encrypted_packet[..8],
73         "Protocol confusion with QUIC"
74     );
75     debug_assert!(DNSCRYPT_UDP_QUERY_MIN_SIZE > ANONYMIZED_DNSCRYPT_QUERY_MAGIC.len());
76     ensure!(
77         encrypted_packet[..ANONYMIZED_DNSCRYPT_QUERY_MAGIC.len()]
78             != ANONYMIZED_DNSCRYPT_QUERY_MAGIC,
79         "Loop detected"
80     );
81     let ext_socket = match globals.external_addr {
82         Some(x) => UdpSocket::bind(x).await?,
83         None => match upstream_address {
84             SocketAddr::V4(_) => {
85                 UdpSocket::bind(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0))).await?
86             }
87             SocketAddr::V6(s) => {
88                 UdpSocket::bind(SocketAddr::V6(SocketAddrV6::new(
89                     Ipv6Addr::UNSPECIFIED,
90                     0,
91                     s.flowinfo(),
92                     s.scope_id(),
93                 )))
94                 .await?
95             }
96         },
97     };
98     ext_socket.connect(&upstream_address).await?;
99     ext_socket.send(encrypted_packet).await?;
100     let mut response = vec![0u8; DNSCRYPT_UDP_RESPONSE_MAX_SIZE];
101     let (response_len, is_certificate_response) = loop {
102         let fut = ext_socket.recv_from(&mut response[..]);
103         let (response_len, response_addr) = fut.await?;
104         if response_addr != upstream_address {
105             continue;
106         }
107         if is_encrypted_response(&response, response_len) {
108             break (response_len, false);
109         }
110         if is_certificate_response(&response, encrypted_packet) {
111             break (response_len, true);
112         }
113     };
114     response.truncate(response_len);
115     if is_certificate_response {
116         let mut hasher = globals.hasher;
117         hasher.write(&relayed_packet[..ANONYMIZED_DNSCRYPT_OVERHEAD]);
118         hasher.write(&dns::qname(encrypted_packet)?);
119         let packet_hash = hasher.finish128().as_u128();
120         let cached_response = {
121             match globals.cert_cache.lock().get(&packet_hash) {
122                 None => None,
123                 Some(response) if !(*response).has_expired() => {
124                     trace!("Relayed certificate cached");
125                     let mut cached_response = (*response).clone();
126                     cached_response.set_tid(dns::tid(encrypted_packet));
127                     Some(cached_response.into_response())
128                 }
129                 Some(_) => {
130                     trace!("Relayed certificate expired");
131                     None
132                 }
133             }
134         };
135         match cached_response {
136             None => {
137                 globals.cert_cache.lock().insert(
138                     packet_hash,
139                     CachedResponse::new(&globals.cert_cache, response.clone()),
140                 );
141             }
142             Some(cached_response) => response = cached_response,
143         }
144     }
145 
146     #[cfg(feature = "metrics")]
147     globals.varz.anonymized_responses.inc();
148 
149     respond_to_query(client_ctx, response).await
150 }
151 
152 #[inline]
is_encrypted_response(response: &[u8], response_len: usize) -> bool153 fn is_encrypted_response(response: &[u8], response_len: usize) -> bool {
154     (DNSCRYPT_UDP_RESPONSE_MIN_SIZE..=DNSCRYPT_UDP_RESPONSE_MAX_SIZE).contains(&response_len)
155         && response[..DNSCRYPT_RESPONSE_MAGIC_SIZE] == DNSCRYPT_RESPONSE_MAGIC
156 }
157 
is_certificate_response(response: &[u8], query: &[u8]) -> bool158 fn is_certificate_response(response: &[u8], query: &[u8]) -> bool {
159     let prefix = b"2.dnscrypt-cert.";
160     if !((DNS_HEADER_SIZE + prefix.len() + 4..=DNS_MAX_PACKET_SIZE).contains(&query.len())
161         && (DNS_HEADER_SIZE + prefix.len() + 4..=DNS_MAX_PACKET_SIZE).contains(&response.len())
162         && dns::tid(response) == dns::tid(query)
163         && dns::is_response(response)
164         && !dns::is_response(query))
165     {
166         debug!("Unexpected relayed cert response");
167         return false;
168     }
169     let qname = match (dns::qname(query), dns::qname(response)) {
170         (Ok(response_qname), Ok(query_qname)) if response_qname == query_qname => query_qname,
171         _ => {
172             debug!("Relayed cert qname response didn't match the query qname");
173             return false;
174         }
175     };
176     if qname.len() <= prefix.len() || &qname[..prefix.len()] != prefix {
177         debug!("Relayed cert qname response didn't start with the standard prefix");
178         return false;
179     }
180     true
181 }
182