Change padding length strategy; PADME is a bad fit for DNS

This commit is contained in:
Frank Denis 2020-01-20 20:26:46 +01:00
parent 76c28cf48e
commit 072a6c0672
4 changed files with 20 additions and 12 deletions

View file

@ -21,7 +21,6 @@ base64 = "0.11"
futures = "0.3"
hyper = { version = "0.13", default-features = false, features = ["stream"] }
native-tls = { version = "0.2.3", optional = true }
padme-padding = "0.1"
tokio = { version = "0.2", features = ["rt-threaded", "time", "tcp", "udp", "stream"] }
tokio-tls = { version = "0.3", optional = true }

View file

@ -1,4 +1,3 @@
pub const BLOCK_SIZE: usize = 128;
pub const DNS_QUERY_PARAM: &str = "dns";
pub const MAX_DNS_QUESTION_LEN: usize = 512;
pub const MAX_DNS_RESPONSE_LEN: usize = 4096;

View file

@ -1,7 +1,5 @@
use anyhow::{ensure, Error};
use byteorder::{BigEndian, ByteOrder};
use padme_padding::Padme;
use std::cmp;
const DNS_HEADER_SIZE: usize = 12;
const DNS_MAX_HOSTNAME_SIZE: usize = 256;
@ -210,7 +208,18 @@ pub fn set_edns_max_payload_size(packet: &mut Vec<u8>, max_payload_size: u16) ->
Ok(())
}
pub fn add_edns_padding(packet: &mut Vec<u8>, min_size: usize) -> Result<(), Error> {
fn padded_len(unpadded_len: usize) -> usize {
const BOUNDARIES: [usize; 16] = [
64, 128, 192, 256, 320, 384, 512, 704, 768, 896, 960, 1024, 1088, 1152, 2688, 4080,
];
BOUNDARIES
.iter()
.find(|&&boundary| boundary >= unpadded_len)
.copied()
.unwrap_or(DNS_MAX_PACKET_SIZE)
}
pub fn add_edns_padding(packet: &mut Vec<u8>) -> Result<(), Error> {
let mut packet_len = packet.len();
ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet");
ensure!(packet_len <= DNS_MAX_PACKET_SIZE, "Large packet");
@ -244,8 +253,7 @@ pub fn add_edns_padding(packet: &mut Vec<u8>, min_size: usize) -> Result<(), Err
edns_offset
}
};
ensure!(packet_len < DNS_MAX_PACKET_SIZE, "Large packet");
let padding_len = cmp::max(min_size, Padme::padding_len(packet_len));
let padding_len = padded_len(packet_len) - packet_len;
let mut edns_padding_prr = vec![b'X'; 4 + padding_len];
BigEndian::write_u16(&mut edns_padding_prr[0..], DNS_PTYPE_PADDING);
BigEndian::write_u16(&mut edns_padding_prr[2..], padding_len as u16);
@ -261,14 +269,14 @@ pub fn add_edns_padding(packet: &mut Vec<u8>, min_size: usize) -> Result<(), Err
0xffff - edns_rdlen as usize >= edns_padding_prr_len,
"EDNS section too large for padding"
);
BigEndian::write_u16(
&mut packet[edns_rdlen_offset..],
edns_rdlen + edns_padding_prr_len as u16,
);
ensure!(
DNS_MAX_PACKET_SIZE - packet_len >= edns_padding_prr_len,
"Large packet"
);
BigEndian::write_u16(
&mut packet[edns_rdlen_offset..],
edns_rdlen + edns_padding_prr_len as u16,
);
packet.extend(&edns_padding_prr);
Ok(())
}

View file

@ -203,7 +203,9 @@ impl DoH {
Ok(ttl) => ttl,
}
};
dns::add_edns_padding(&mut packet, BLOCK_SIZE).map_err(|_| DoHError::TooLarge)?;
dns::add_edns_padding(&mut packet)
.map_err(|_| DoHError::TooLarge)
.ok();
let packet_len = packet.len();
let response = Response::builder()
.header(hyper::header::CONTENT_LENGTH, packet_len)