From c0faa11ac175cf335e602dc11ad023de864fd5f5 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Sun, 13 Oct 2019 00:45:26 +0200 Subject: [PATCH] Return a HINFO record when a query is blocked This is extremely useful to understand why a query doesn't return e.g. IP addresses that resolve from other servers --- Cargo.toml | 2 +- src/dns.rs | 16 +++++++++++++++- src/resolver.rs | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2eb3c09..31a843f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ daemonize-simple = "0.1.2" derivative = "1.0.3" dnsstamps = "0.1.1" env_logger = { version="0.7.0", default-features = false, features = ["humantime"]} -failure = "0.1.5" +failure = "0.1.6" futures-preview = { version = "=0.3.0-alpha.19", features = ["async-await", "unstable", "cfg-target-has-atomic"] } jemallocator = "0.3.2" libsodium-sys-stable="1.18.1" diff --git a/src/dns.rs b/src/dns.rs index f568c08..2e7d41a 100644 --- a/src/dns.rs +++ b/src/dns.rs @@ -18,6 +18,7 @@ const DNS_FLAGS_CD: u16 = 1u16 << 4; const DNS_OFFSET_QUESTION: usize = DNS_HEADER_SIZE; const DNS_TYPE_OPT: u16 = 41; const DNS_TYPE_TXT: u16 = 16; +const DNS_TYPE_HINFO: u16 = 13; const DNS_CLASS_INET: u16 = 1; const DNS_RCODE_SERVFAIL: u8 = 2; @@ -462,7 +463,7 @@ pub fn serve_truncated(client_packet: Vec) -> Result, Error> { Ok(packet) } -pub fn serve_empty_response(client_packet: Vec) -> Result, Error> { +pub fn serve_blocked_response(client_packet: Vec) -> Result, Error> { ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet"); ensure!(qdcount(&client_packet) == 1, "No question"); ensure!( @@ -475,5 +476,18 @@ pub fn serve_empty_response(client_packet: Vec) -> Result, Error> { packet.truncate(offset + 4); an_ns_ar_count_clear(&mut packet); authoritative_response(&mut packet); + let hinfo_cpu = b"Query blocked"; + let hinfo_rdata = b"by the DNS server"; + let rdata_len = 1 + hinfo_cpu.len() + 1 + hinfo_rdata.len(); + ancount_inc(&mut packet)?; + packet.write_u16::(0xc000 + DNS_HEADER_SIZE as u16)?; + packet.write_u16::(DNS_TYPE_HINFO)?; + packet.write_u16::(DNS_CLASS_INET)?; + packet.write_u32::(60)?; + packet.write_u16::(rdata_len as _)?; + packet.push(hinfo_cpu.len() as u8); + packet.extend_from_slice(hinfo_cpu); + packet.push(hinfo_rdata.len() as u8); + packet.extend_from_slice(hinfo_rdata); Ok(packet) } diff --git a/src/resolver.rs b/src/resolver.rs index e66a2f4..a935009 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -152,7 +152,7 @@ pub async fn get_cached_response_or_resolve( if blacklist.find(&packet_qname) { #[cfg(feature = "metrics")] globals.varz.client_queries_blocked.inc(); - return dns::serve_empty_response(packet.to_vec()); + return dns::serve_blocked_response(packet.to_vec()); } } let original_tid = dns::tid(&packet);