diff --git a/Cargo.toml b/Cargo.toml index 94ede09..782876d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,8 +17,8 @@ tls = ["native-tls", "tokio-tls"] [dependencies] base64 = "0.10" clap = "2.33.0" -futures = "0.1.28" -hyper = "0.12.33" +futures = "0.1.29" +hyper = "0.12.35" jemallocator = "0" native-tls = { version = "0.2.3", optional = true } tokio = "0.1.22" diff --git a/src/dns.rs b/src/dns.rs index e52c367..3b9a942 100644 --- a/src/dns.rs +++ b/src/dns.rs @@ -4,6 +4,9 @@ const DNS_MAX_PACKET_SIZE: usize = 65_535; const DNS_OFFSET_QUESTION: usize = DNS_HEADER_SIZE; const DNS_TYPE_OPT: u16 = 41; +const DNS_RCODE_SERVFAIL: u8 = 2; +const DNS_RCODE_REFUSED: u8 = 5; + #[inline] fn qdcount(packet: &[u8]) -> u16 { (u16::from(packet[4]) << 8) | u16::from(packet[5]) @@ -24,6 +27,16 @@ fn arcount(packet: &[u8]) -> u16 { (u16::from(packet[10]) << 8) | u16::from(packet[11]) } +#[inline] +pub fn rcode(packet: &[u8]) -> u8 { + packet[3] & 0x0f +} + +pub fn is_temporary_error(packet: &[u8]) -> bool { + let rcode = rcode(packet); + rcode == DNS_RCODE_SERVFAIL || rcode == DNS_RCODE_REFUSED +} + fn arcount_inc(packet: &mut [u8]) -> Result<(), &'static str> { let mut arcount = arcount(packet); if arcount == 0xffff { diff --git a/src/main.rs b/src/main.rs index e8cb462..3aa6670 100644 --- a/src/main.rs +++ b/src/main.rs @@ -302,9 +302,13 @@ impl DoH { return future::err(Error::UpstreamIssue); } packet.truncate(len); - let ttl = match dns::min_ttl(&packet, min_ttl, max_ttl, err_ttl) { - Err(_) => return future::err(Error::UpstreamIssue), - Ok(ttl) => ttl, + let ttl = if dns::is_temporary_error(&packet) { + err_ttl + } else { + match dns::min_ttl(&packet, min_ttl, max_ttl, err_ttl) { + Err(_) => return future::err(Error::UpstreamIssue), + Ok(ttl) => ttl, + } }; let packet_len = packet.len(); let response = Response::builder()