Search code examples
rusttcpdnsudp

Can't receive DNS queries over TCP


When I send DNS query to root server for com name servers over UDP, it's working just fine, but the message is truncated. When I retry over TCP, the Root server does not times out.

use std::net::TcpStream;
use std::io::Write;

fn main() {
    let mut stream = TcpStream::connect("199.9.14.201:53")
        .unwrap();

    stream.write(&[251, 188, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 99, 111, 109, 0, 0, 2, 0, 1])
        .expect("ugh");

    let mut buf: [u8; 1000] = [1; 1000];
    match stream.peek(&mut buf) {
        Ok(..) => {
            println!("{:?}", buf);
        }

        Err(e) => {
            println!("{:?}", e);
        }
    }

    
    println!("Hello, world!");
}

Solution

  • From RFC 1035 section 4.2.2:

    Messages sent over TCP connections use server port 53 (decimal). The message is prefixed with a two byte length field which gives the message length, excluding the two byte length field. This length field allows the low-level processing to assemble a complete message before beginning to parse it.

    I looks like your code does not include the required message length. Thus the first two bytes of your message are treated as length which describe a length much larger than what you has send. Therefore the server is waiting for more data.