Marius Schwarz 4 år sedan
incheckning
ab1f728a7b
7 ändrade filer med 1244 tillägg och 0 borttagningar
  1. 1 0
      .gitignore
  2. 5 0
      Cargo.lock
  3. 9 0
      Cargo.toml
  4. 805 0
      src/dns.rs
  5. 77 0
      src/main.rs
  6. 2 0
      src/net.rs
  7. 345 0
      src/server.rs

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+/target

+ 5 - 0
Cargo.lock

@@ -0,0 +1,5 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "dns-client"
+version = "0.1.0"

+ 9 - 0
Cargo.toml

@@ -0,0 +1,9 @@
+[package]
+name = "dns-client"
+version = "0.1.0"
+authors = ["Marius Schwarz <marius.schwarz97@gmail.com>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]

+ 805 - 0
src/dns.rs

@@ -0,0 +1,805 @@
+use std::net::{Ipv4Addr, Ipv6Addr};
+use std::net::UdpSocket;
+
+
+
+pub struct DnsPacket {
+    pub header: DnsHeader,
+    pub questions: Vec<DnsQuestion>,
+    pub answers: Vec<DnsRecord>,
+    pub authorities: Vec<DnsRecord>,
+    pub resources: Vec<DnsRecord>
+}
+
+
+impl DnsPacket {
+
+    pub fn new(query_type: QueryType, qname: &str) -> Self {
+
+        let id = 6677;
+        let mut header = DnsHeader::new(id);
+        header.recursion_desired = true;
+        let mut questions = Vec::new();
+        questions.push(DnsQuestion::new(String::from(qname), query_type));
+
+        DnsPacket {
+            header,
+            questions,
+            answers: Vec::new(),
+            authorities: Vec::new(),
+            resources: Vec::new(),
+        }
+    }
+
+    pub fn empty() -> Self {
+        let id = 6677;
+        let header = DnsHeader::new(id);
+
+        DnsPacket {
+            header,
+            questions: Vec::new(),
+            answers: Vec::new(),
+            authorities: Vec::new(),
+            resources: Vec::new(),
+        }
+    }
+
+    pub fn from_bytes(buffer: &mut BytePacketBuffer) -> Self {
+
+        let header = DnsHeader::from(buffer).unwrap();
+
+        let mut questions = Vec::new();
+        let mut answers = Vec::new();
+        let mut authorities = Vec::new();
+        let mut resources = Vec::new();
+
+        for _ in 0..header.question_count {
+            let question = DnsQuestion::from(buffer);
+            questions.push(question)
+        }
+
+        for _ in 0..header.answer_count {
+            let answer = DnsRecord::from(buffer);
+            answers.push(answer)
+        }
+
+        for _ in 0..header.authority_count {
+            let authority = DnsRecord::from(buffer);
+            authorities.push(authority)
+        }
+
+        for _ in 0..header.authority_count {
+            let rec = DnsRecord::from(buffer);
+            resources.push(rec)
+        }
+
+        DnsPacket {
+            header,
+            questions,
+            answers,
+            authorities,
+            resources
+        }
+    }
+
+    pub fn write(&mut self, buffer: &mut BytePacketBuffer) -> Result<(), &str> {
+        self.header.question_count = self.questions.len() as u16;
+        self.header.answer_count = self.answers.len() as u16;
+        self.header.authority_count = self.authorities.len() as u16;
+        self.header.add_count = self.resources.len() as u16;
+
+        self.header.write(buffer).unwrap();
+
+        for question in &self.questions {
+            question.write(buffer).unwrap();
+        }
+        for rec in &self.answers {
+            rec.write(buffer).unwrap();
+        }
+        for rec in &self.authorities {
+            rec.write(buffer).unwrap();
+        }
+        for rec in &self.resources {
+            rec.write(buffer).unwrap();
+        }
+
+        Ok(())
+    }
+
+
+    pub fn send(&mut self, server: (&str, u16)) -> DnsPacket {
+
+        let mut req_buffer = BytePacketBuffer::new();
+        self.write(&mut req_buffer).unwrap();
+
+        let socket = UdpSocket::bind(("0.0.0.0", 43210)).unwrap();
+        socket.send_to(&req_buffer.buf[0..req_buffer.pos], server).unwrap();
+
+        let mut rec_buffer = BytePacketBuffer::new();
+        socket.recv_from(&mut rec_buffer.buf).unwrap();
+
+        let response = DnsPacket::from_bytes(&mut rec_buffer);
+
+        return response;
+    }
+}
+
+
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum ResultCode {
+    NOERROR = 0,
+    FORMERR = 1,
+    SERVFAIL = 2,
+    NXDOMAIN = 3,
+    NOTIMP = 4,
+    REFUSED = 5,
+}
+
+impl ResultCode {
+
+    pub fn from_num(num: u8) -> Self {
+        match num {
+            1 => ResultCode::FORMERR,
+            2 => ResultCode::SERVFAIL,
+            3 => ResultCode::NXDOMAIN,
+            4 => ResultCode::NOTIMP,
+            5 => ResultCode::REFUSED,
+            0 | _ => ResultCode::NOERROR,
+        }
+    }
+}
+
+// The holy  grail, the DNS Header itself
+#[derive(Clone, Debug)]
+pub struct DnsHeader {
+    pub id: u16,                    // 16 bits
+    pub query_response: bool,       // 1 bit
+    pub operation_code: u8,         // 4 bits
+    pub authoritative_answer: bool, // 1 bit
+    pub truncated_message: bool,    // 1 bit
+    pub recursion_desired: bool,    // 1 bit
+    pub recursion_available: bool,  // 1 bit
+    pub z: u8,                      // 3 bits
+    pub result_code: ResultCode,  // 4 bits
+    pub question_count: u16,        // 16 bits
+    pub answer_count: u16,          // 16 bits
+    pub authority_count: u16,       // 16 bits
+    pub add_count: u16,             // 16 bits
+}
+
+impl DnsHeader {
+
+    // returns a plain DnsHeader
+    pub fn new(id: u16) -> Self {
+        DnsHeader {
+            id,
+            query_response: false,
+            operation_code: 0,
+            authoritative_answer: false,
+            truncated_message: false,
+            recursion_desired: false,
+            recursion_available: false,
+            z: 0,
+            result_code: ResultCode::NOERROR,
+            question_count: 0,
+            answer_count: 0,
+            authority_count: 0,
+            add_count: 0
+        }
+    }
+
+
+    pub fn from(buffer: &mut BytePacketBuffer) -> Result<Self, &str> {
+        let id = buffer.read_u16().unwrap();
+        let flags = buffer.read_u16().unwrap();
+        let bit1 = (flags >> 8) as u8;      // Most significant byte
+        let bit2 = (flags & 0xFF) as u8;    // Least significant byte
+
+        // parse the DNS Header from a 512 byte buffer
+        Ok(DnsHeader {
+            id,
+            recursion_desired: (bit1 & (1 << 0)) > 0,
+            truncated_message: (bit1 & (1 << 1)) > 0,
+            authoritative_answer: (bit1 & (1 << 2)) > 0,
+            operation_code: (bit1 >> 3) & 0xF,
+            query_response: (bit1 >> 7) > 0,
+
+            result_code: ResultCode::from_num(bit2 & 0x0F),
+            z: (bit2 >> 0x4) & 0x7,
+            recursion_available: (bit2 >> 7) > 0,
+
+            question_count: buffer.read_u16().unwrap(),
+            answer_count: buffer.read_u16().unwrap(),
+            authority_count: buffer.read_u16().unwrap(),
+            add_count: buffer.read_u16().unwrap(),
+        })
+    }
+
+    pub fn write(&self, buffer: &mut BytePacketBuffer) -> Result<(), &str> {
+        buffer.write_u16(self.id).unwrap();
+
+        buffer.write_u8(
+            (self.recursion_desired as u8)
+            | ((self.truncated_message as u8) << 1)
+            | ((self.authoritative_answer as u8) << 2)
+            | (self.operation_code << 3)
+            | ((self.query_response as u8) << 7) as u8
+            ).unwrap();
+
+        buffer.write_u8(
+            (self.result_code as u8)
+            | ((self.z as u8) << 6)
+            | ((self.recursion_available as u8) << 7)
+            ).unwrap();
+
+        buffer.write_u16(self.question_count).unwrap();
+        buffer.write_u16(self.answer_count).unwrap();
+        buffer.write_u16(self.authority_count).unwrap();
+        buffer.write_u16(self.add_count).unwrap();
+        Ok(())
+    }
+}
+
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug, Ord, PartialOrd, Hash)]
+pub enum QueryType {
+    UNKNOWN(u16),
+    A,      // = 1
+    NS,     // = 2
+    CNAME,  // = 5
+    MX,     // = 15
+    AAAA,   // 28
+    TXT,    // 16
+}
+
+impl QueryType {
+    pub fn to_num(&self) -> u16 {
+        match *self {
+            QueryType::UNKNOWN(x) => x,
+            QueryType::A        => 1,
+            QueryType::NS       => 2,
+            QueryType::CNAME    => 5,
+            QueryType::MX       => 15,
+            QueryType::TXT      => 16,
+            QueryType::AAAA     => 28,
+        }
+    }
+
+    pub fn from_num(num: u16) -> Self {
+        match num {
+            1   => QueryType::A,
+            2   => QueryType::NS,
+            5   => QueryType::CNAME,
+            15  => QueryType::MX,
+            16  => QueryType::TXT,
+            28  => QueryType::AAAA,
+            _ => QueryType::UNKNOWN(num),
+        }
+
+    }
+}
+
+
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct DnsQuestion {
+    pub name: String,
+    pub qtype: QueryType
+}
+
+impl DnsQuestion {
+
+    pub fn new(name: String, qtype: QueryType) -> Self {
+        DnsQuestion {
+            name,
+            qtype
+        }
+    }
+
+    pub fn from(buffer: &mut BytePacketBuffer) -> Self {
+
+        let name = buffer.read_qname().unwrap();
+        let qtype = QueryType::from_num(buffer.read_u16().unwrap());
+        let _ = buffer.read_u16().unwrap();
+        DnsQuestion {
+            name,
+            qtype
+        }
+    }
+
+    pub fn write(&self, buffer: &mut BytePacketBuffer) -> Result<(), &str> {
+
+        buffer.write_qname(&self.name).unwrap();
+        let qtype_num = self.qtype.to_num();
+        buffer.write_u16(qtype_num).unwrap();
+        buffer.write_u16(1).unwrap();
+
+        Ok(())
+    }
+
+}
+
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)]
+pub enum DnsRecord {
+    UNKNOWN {
+        domain: String,
+        qtype: QueryType,
+        data_len: u16,
+        ttl: u32
+    },
+    A {
+        domain: String,
+        addr: Ipv4Addr,
+        ttl: u32
+    },
+    NS {
+        domain: String,
+        host: String,
+        ttl: u32
+    },
+    CNAME {
+        domain: String,
+        host: String,
+        ttl: u32
+    },
+    MX {
+        domain: String,
+        priority: u16,
+        host: String,
+        ttl: u32
+    },
+    AAAA {
+        domain: String,
+        addr: Ipv6Addr,
+        ttl: u32
+    },
+    TXT {
+        domain: String,
+        len: u8,
+        txt: String,
+        ttl: u32
+    },
+}
+
+impl DnsRecord {
+
+    pub fn from(buffer: &mut BytePacketBuffer) -> Self {
+        let domain = buffer.read_qname().unwrap();
+        let qtype_num = buffer.read_u16().unwrap();
+        let qtype = QueryType::from_num(qtype_num);
+        let _  = buffer.read_u16().unwrap();    // CLASS (should always be IN)
+        let ttl = buffer.read_u32().unwrap();
+        let data_len = buffer.read_u16().unwrap();
+
+        match qtype {
+            QueryType::A => {
+                let raw_addr = buffer.read_u32().unwrap();
+                let addr = Ipv4Addr::new(
+                    ((raw_addr >> 24) & 0xFF) as u8,
+                    ((raw_addr >> 16) & 0xFF) as u8,
+                    ((raw_addr >> 8) & 0xFF) as u8,
+                    ((raw_addr) & 0xFF) as u8);
+                DnsRecord::A {
+                    domain,
+                    addr,
+                    ttl
+                }
+            },
+            QueryType::UNKNOWN(_) => {
+                buffer.step(data_len as usize).unwrap();
+
+                DnsRecord::UNKNOWN {
+                    domain,
+                    qtype,
+                    data_len,
+                    ttl
+                }
+            },
+            QueryType::AAAA => {
+                let raw_addr0 = buffer.read_u32().unwrap();
+                let raw_addr1 = buffer.read_u32().unwrap();
+                let raw_addr2 = buffer.read_u32().unwrap();
+                let raw_addr3 = buffer.read_u32().unwrap();
+
+                let addr = Ipv6Addr::new(
+                    ((raw_addr0 >> 16) & 0xFF) as u16,
+                    ((raw_addr0 >> 0) & 0xFF) as u16,
+                    ((raw_addr1 >> 16) & 0xFF) as u16,
+                    ((raw_addr1 >> 0) & 0xFF) as u16,
+                    ((raw_addr2 >> 16) & 0xFF) as u16,
+                    ((raw_addr2 >> 0) & 0xFF) as u16,
+                    ((raw_addr3 >> 16) & 0xFF) as u16,
+                    ((raw_addr3 >> 0) & 0xFF) as u16);
+                DnsRecord::AAAA {
+                    domain,
+                    addr,
+                    ttl
+                }
+            },
+            QueryType::NS => {
+
+                let ns = buffer.read_qname().unwrap();
+                DnsRecord::NS {
+                    domain,
+                    host: ns,
+                    ttl
+                }
+            },
+            QueryType::CNAME => {
+
+                let cname =  buffer.read_qname().unwrap();
+                DnsRecord::CNAME {
+                    domain,
+                    host: cname,
+                    ttl
+                }
+            },
+            QueryType::MX => {
+
+                let priority = buffer.read_u16().unwrap();
+                let mx = buffer.read_qname().unwrap();
+                DnsRecord::MX {
+                    domain,
+                    priority,
+                    host: mx,
+                    ttl
+                }
+            },
+            QueryType::TXT => {
+
+                let txt_len = buffer.read().unwrap();
+
+                let mut s = Vec::with_capacity(txt_len as usize);
+
+                for _ in 0..txt_len {
+                    s.push(buffer.read().unwrap());
+                }
+                let txt =  String::from_utf8_lossy(&s).to_string();
+                DnsRecord::TXT {
+                    domain,
+                    len: txt_len as u8,
+                    txt,
+                    ttl
+                }
+            }
+        }
+    }
+
+    pub fn write(&self, buffer: &mut BytePacketBuffer) -> Result<usize, &str> {
+        let start_pos = buffer.pos();
+
+        match *self {
+            DnsRecord::A {
+                ref domain,
+                ref addr,
+                ttl
+            } => {
+                buffer.write_qname(domain).unwrap();
+                buffer.write_u16(QueryType::A.to_num()).unwrap();
+                buffer.write_u16(1).unwrap();
+                buffer.write_u32(ttl).unwrap();
+                buffer.write_u16(4).unwrap();
+
+                let oct = addr.octets();
+                buffer.write_u8(oct[0]).unwrap();
+                buffer.write_u8(oct[1]).unwrap();
+                buffer.write_u8(oct[2]).unwrap();
+                buffer.write_u8(oct[3]).unwrap();
+            }
+            DnsRecord::AAAA {
+                ref domain,
+                ref addr,
+                ttl
+            } => {
+                buffer.write_qname(domain).unwrap();
+                buffer.write_u16(QueryType::AAAA.to_num()).unwrap();
+                buffer.write_u16(1).unwrap();   // CLASS `IN`
+                buffer.write_u32(ttl).unwrap(); // TTL
+                buffer.write_u16(8).unwrap();   // Length
+
+                for oct in addr.segments().iter() {
+                    buffer.write_u16(*oct).unwrap();
+                }
+
+            },
+            DnsRecord::NS {
+                ref domain,
+                ref host,
+                ttl
+            } => {
+                buffer.write_qname(domain).unwrap();
+                buffer.write_u16(QueryType::NS.to_num()).unwrap();
+                buffer.write_u16(1).unwrap();
+                buffer.write_u32(ttl).unwrap();
+
+                let pos = buffer.pos();
+                buffer.write_u16(0).unwrap();
+                buffer.write_qname(host).unwrap();
+
+                let size = buffer.pos() - (pos + 2);
+                buffer.set_u16(pos, size as u16).unwrap();
+
+            },
+            DnsRecord::CNAME {
+                ref domain,
+                ref host,
+                ttl
+            } => {
+                buffer.write_qname(domain).unwrap();
+                buffer.write_u16(QueryType::CNAME.to_num()).unwrap();
+                buffer.write_u16(1).unwrap();
+                buffer.write_u32(ttl).unwrap();
+
+                let pos = buffer.pos();
+                buffer.write_u16(0).unwrap();       // write temporary size
+                buffer.write_qname(host).unwrap();  // write host
+
+                let size = buffer.pos() - (pos + 2);
+                buffer.set_u16(pos, size as u16).unwrap();
+            },
+            DnsRecord::MX {
+                ref domain,
+                priority,
+                ref host,
+                ttl
+            } => {
+                buffer.write_qname(domain).unwrap();
+                buffer.write_u16(QueryType::MX.to_num()).unwrap();
+                buffer.write_u16(1).unwrap();
+                buffer.write_u32(ttl).unwrap();
+
+
+                let pos = buffer.pos();
+                buffer.write_u16(0).unwrap();       // write temporary size
+                buffer.write_u16(priority).unwrap();
+                buffer.write_qname(host).unwrap();  // write host
+
+                let size = buffer.pos() - (pos + 2);
+                buffer.set_u16(pos, size as u16).unwrap();
+            },
+            DnsRecord::TXT {
+                ref domain,
+                len,
+                ref txt,
+                ttl
+            } => {
+                buffer.write_qname(domain).unwrap();
+                buffer.write_u16(QueryType::TXT.to_num()).unwrap();
+                buffer.write_u16(1).unwrap();
+                buffer.write_u32(ttl).unwrap();
+
+                let pos = buffer.pos();
+                buffer.write_u16(0).unwrap();       // write temporary size
+
+                buffer.write_u8(len).unwrap();
+                for byte in txt.as_bytes() {
+                    buffer.write_u8(*byte).unwrap();  // write byte by byte
+                }
+
+                let size = buffer.pos() - (pos + 2);
+                buffer.set_u16(pos, size as u16).unwrap();
+            },
+            DnsRecord::UNKNOWN {..} => {
+                return Err("Unknown DnsRecord");
+            },
+        }
+
+        Ok(buffer.pos() - start_pos)
+    }
+}
+
+
+/// Buffer containing the full DNS Packet
+pub struct BytePacketBuffer {
+    pub buf: [u8; 512],
+    pub pos: usize,
+}
+
+
+impl BytePacketBuffer {
+
+    pub fn new() -> Self {
+        BytePacketBuffer { buf: [0; 512] ,pos: 0}
+    }
+
+    pub fn pos(&self) -> usize {
+        self.pos
+    }
+
+    pub fn step(&mut self, steps: usize) -> Result<(), &str> {
+        self.pos += steps;
+        Ok(())
+    }
+
+    pub fn seek(&mut self, pos: usize) -> Result<(), &str> {
+        self.pos = pos;
+        Ok(())
+    }
+
+    /// Read a single byte from the buffer
+    pub fn read(&mut self) -> Result<u8, &str> {
+        if self.pos >= 512 {
+            return Err("End of Buffer");
+        }
+
+        let ret = self.buf[self.pos];
+        self.pos += 1;
+        Ok(ret)
+    }
+
+    pub fn get(&self, pos: usize) -> Result<u8, &str> {
+        if pos >= 512 {
+            return Err("End of Buffer");
+        }
+        Ok(self.buf[pos])
+    }
+
+    pub fn get_range(&self, start: usize, len: usize) -> Result<&[u8], &str> {
+        if (start + len) >= 512 {
+            return Err("End of Buffer");
+        }
+        Ok(&self.buf[start..start+len])
+    }
+
+    pub fn read_u16(&mut self) -> Result<u16, &str> {
+        if self.pos >= 512 {
+            return Err("End of Buffer");
+        }
+
+        let mut res = (self.read().unwrap() as u16) << 8;
+        res |=  self.read()? as u16;
+        Ok(res)
+    }
+
+    pub fn read_u32(&mut self) -> Result<u32, &str> {
+        if self.pos >= 512 {
+            return Err("End of Buffer");
+        }
+
+        // Hack: calling ? on read() results in error
+        // "Second mutable borrow occurs here"
+        let mut res = (self.read().unwrap() as u32) << 24;
+        res |=  (self.read().unwrap() as u32) << 16;
+        res |=  (self.read().unwrap() as u32) << 8;
+        res |=  self.read()? as u32;
+        Ok(res)
+    }
+
+    /// Reading Domain Name in the following format
+    /// [len][name][len][name] [...]
+    /// The first [len] can be a jump to another position in the buffer
+    /// if the two most sign. bits are set (0xC0)
+    fn read_qname(&mut self) -> Result<String, &str> {
+
+
+        let mut lpos = self.pos;
+        let mut jumped = false;
+        let mut num_jmps = 0;
+        let max_jmps = 5;
+        // delimiter to split the domain names
+        let mut delim = "";
+
+        let mut outstr = String::from("");
+
+        // begin reading the domain names
+        loop {
+
+            // prevent endless looping jmps
+            if num_jmps >= max_jmps {
+                return Err("too many jumps");
+            }
+
+            let len = self.get(lpos).unwrap() as usize;
+            if (len & 0xC0) == 0xC0 {
+
+                if !jumped {
+                    self.seek(lpos + 2).unwrap();
+                }
+
+                // This indicates a jump to another location in the buffer
+                // the location is indicated by the following byte
+
+                let sb = self.get(lpos + 1).unwrap() as u16;
+                let sb = ((self.get(lpos).unwrap() as u16 ^ 0xC0) << 8) as u16 | sb;
+
+                // set the position to the jmp location
+                lpos = sb as usize;
+                jumped = true;
+                num_jmps += 1;
+
+                continue;
+            }
+            else {
+                // Read regular domain name
+                lpos += 1;
+                // if the len is 0, this means that the final part of
+                // the domain names is arrived
+                if len == 0 {
+                    break
+                }
+                outstr.push_str(delim);
+                let domain = &String::from_utf8_lossy(self.get_range(lpos, len).unwrap()).to_lowercase();
+                outstr.push_str(domain);
+                delim = ".";
+                // move forward the local pos
+                lpos += len;
+            }
+
+
+        }
+
+        if !jumped {
+            self.seek(lpos).unwrap();
+        }
+        Ok(outstr)
+    }
+
+    fn write(&mut self, val: u8) -> Result<(), &str> {
+        if self.pos >= 512  {
+            return Err("End of buffer");
+        }
+
+        self.buf[self.pos] = val;
+        self.pos += 1;
+        Ok(())
+    }
+
+    fn write_u8(&mut self, val: u8) -> Result<(), &str> {
+        self.write(val)
+    }
+
+    fn write_u16(&mut self, val: u16) -> Result<(), &str> {
+
+        self.write_u8((val >> 8) as u8).unwrap();
+        self.write_u8((val & 0xFF) as u8).unwrap();
+        Ok(())
+    }
+    fn write_u32(&mut self, val: u32) -> Result<(), &str> {
+
+        self.write_u8(((val >> 24) & 0xFF) as u8).unwrap();
+        self.write_u8(((val >> 16) & 0xFF) as u8).unwrap();
+        self.write_u8(((val >> 8) & 0xFF) as u8).unwrap();
+        self.write_u8(((val >> 0) & 0xFF) as u8).unwrap();
+        Ok(())
+    }
+
+    fn write_qname(&mut self, qname: &str) -> Result<(), &str> {
+
+        for label in qname.split(".") {
+            let len = label.len();
+
+            if len > 0x3F {
+                return Err("Single Label exeeds 63 characters");
+            }
+
+            self.write_u8(len as u8).unwrap();
+
+            for b in label.as_bytes() {
+                self.write_u8(*b as u8).unwrap();
+            }
+        }
+
+        self.write_u8(0).unwrap();
+        Ok(())
+    }
+
+    fn set(&mut self, pos: usize, val: u8) -> Result<(), &str> {
+
+        if pos >= 512 {
+            return Err("End of Buffer");
+        }
+        self.buf[pos] = val;
+        Ok(())
+    }
+    fn set_u16(&mut self, pos: usize, val: u16) -> Result<(), &str> {
+
+        if pos >= 511 {
+            return Err("End of Buffer");
+        }
+        self.buf[pos] = ((val >> 8) & 0xFF) as u8;
+        self.buf[pos+1] = (val & 0xFF) as u8;
+        Ok(())
+    }
+}

+ 77 - 0
src/main.rs

@@ -0,0 +1,77 @@
+mod dns;
+mod server;
+
+use dns::*;
+use server::*;
+use std::env;
+use std::process;
+use std::io::{stdin, stdout, Write};
+
+fn main() {
+
+
+    let args: Vec<String> =env::args().collect();
+    let mut port: u16 = 1053; // default port
+
+
+    // check if the `--port` parameter ist set
+    if args.contains(&"--port".to_string()) {
+        let idx = args.iter().position(|x| x == "--port").unwrap() + 1;
+
+        if idx < args.len() {
+            port = match args[idx].parse() {
+                Ok(p) => p,
+                Err(_) => {
+                    println!("[-] Port must be an integer");
+                    process::exit(1);
+                }
+            }
+        } else {
+            println!("[-] Missing port argument, defaulting to {}", port);
+        }
+    }
+
+    if args.contains(&"--server".to_string()) {
+        println!("[+] Starting DNS Server on port {}", port);
+        DnsServer::serve(port);
+    } else if args.contains(&"--tunnel-server".to_string()) {
+        DnsTunnel::tunnel_server(port);
+    } else if args.contains(&"--tunnel-client".to_string()) {
+        if args.contains(&"--chat".to_string()) {
+            let tunnel = DnsTunnel::new("swrzm.de".to_string(), "127.0.0.1".to_string(), port);
+            tunnel.connect();
+            loop {
+                print!(">> ");
+                let mut inp = String::new();
+                let _=stdout().flush();
+                stdin().read_line(&mut inp).expect("Did not enter a correct string");
+                inp.pop();
+                tunnel.send_string(inp);
+            }
+        } else {
+            println!("[-] --data needed");
+        }
+    }
+
+
+    let qname = "_acme-challenge.swrzm.de";
+    let qname = "google.de";
+    let qtype = QueryType::A;
+
+    //let server = ("8.8.8.8", 53);
+    let server = ("216.239.32.10", 53);
+
+    let mut pkt = DnsPacket::new(qtype, qname);
+
+    let response = pkt.send(server);
+
+    println!("{:#?}", response.header);
+
+    for q in response.questions {
+        println!("{:#?}", q);
+    }
+    for a in response.answers {
+        println!("{:#?}", a);
+    }
+
+}

+ 2 - 0
src/net.rs

@@ -0,0 +1,2 @@
+
+

+ 345 - 0
src/server.rs

@@ -0,0 +1,345 @@
+use std::net::UdpSocket;
+use crate::dns::*;
+use std::str;
+
+pub struct DnsServer {
+}
+
+impl DnsServer {
+    pub fn serve(port: u16) {
+        let socket = UdpSocket::bind(("0.0.0.0", port)).unwrap();
+
+        // starting main loop
+        loop {
+            DnsServer::handle_query(&socket);
+        }
+
+    }
+
+    fn handle_query(socket: &UdpSocket) {
+
+        let mut response_buffer = BytePacketBuffer::new();
+
+        // receive into response buffer
+        let (_, src) = socket.recv_from(&mut response_buffer.buf).unwrap();
+
+        let mut packet = DnsPacket::from_bytes(&mut response_buffer);
+
+        // create the response packet
+        let mut resp_packet = DnsPacket::empty();
+        resp_packet.header.id = packet.header.id;
+        resp_packet.header.recursion_desired = packet.header.recursion_desired;
+        resp_packet.header.recursion_available = true;
+        resp_packet.header.query_response = true;
+
+        // if there is exactly one question
+        if let Some(question) = packet.questions.pop() {
+            println!("[*] Received query: {:?}", question);
+
+
+            if let Ok(result) = DnsServer::lookup(&question.name, &question.qtype) {
+
+                for rec  in result.answers {
+                    println!("-> Answer: {:?}", rec);
+                    resp_packet.answers.push(rec);
+                }
+                for rec  in result.authorities {
+                    println!("-> Authority: {:?}", rec);
+                    resp_packet.authorities.push(rec);
+                }
+                for rec  in result.resources {
+                    println!("-> Resource: {:?}", rec);
+                    resp_packet.resources.push(rec);
+                }
+                // if the lookup was successfull
+
+                // push the original question
+                resp_packet.questions.push(question);
+
+            } else {
+                resp_packet.header.result_code = ResultCode::SERVFAIL;
+            }
+
+
+        } else {
+            resp_packet.header.result_code = ResultCode::FORMERR;
+        }
+
+        // write  the packet to a buffer and send via socket
+        let mut res_buffer = BytePacketBuffer::new();
+        resp_packet.write(&mut res_buffer).unwrap();
+
+        socket.send_to(res_buffer.get_range(0, res_buffer.pos()).unwrap(), src).unwrap();
+
+
+    }
+
+    fn lookup(qname: &str, qtype: &QueryType) -> Result<DnsPacket, &'static str> {
+
+        // use googles DNS mainly as primary DNS
+        let server = ("8.8.8.8", 53);
+
+        let mut pkt = DnsPacket::new(*qtype, qname);
+
+        let mut req_buffer = BytePacketBuffer::new();
+        pkt.write(&mut req_buffer).unwrap();
+
+        let socket = UdpSocket::bind(("0.0.0.0", 43210)).unwrap();
+        socket.send_to(&req_buffer.buf[0..req_buffer.pos], server).unwrap();
+
+        let mut rec_buffer = BytePacketBuffer::new();
+        socket.recv_from(&mut rec_buffer.buf).unwrap();
+
+        let response = DnsPacket::from_bytes(&mut rec_buffer);
+
+        return Ok(response);
+    }
+}
+
+
+pub struct DnsTunnel {
+    server: String,
+    domain: String,
+    port: u16,
+}
+
+impl DnsTunnel {
+
+    /// Craft a new instance of a DNS Tunnel
+    /// ip: IP of the DNS tunnel server
+    /// port: port of the DNS tunnel server
+    pub fn new(domain: String, server: String, port: u16) -> DnsTunnel {
+        DnsTunnel { server, port, domain }
+    }
+    pub fn connect(&self) -> Result<(), &str> {
+        if !self.check_connection() {
+            println!("[-] DNS Tunnel not reachable");
+            return Err("");
+        }
+        println!("[+] Successfully connected to DNS Tunnel");
+        Ok(())
+    }
+
+    pub fn send_string(&self, data: String) -> Result<(), &str> {
+
+        if !self.init_send() {
+            return Err("Failed to initialize data transfer");
+        }
+
+        // At this point, split the data in chunks of XX bytes and send each
+        // chunk to the server until all the data is finished.
+        // Close the connection by sending an `END` packet.
+        if data.len() > 63 {
+            // split the data in chunks of 63 bytes
+            let chunks = data.as_bytes()
+                .chunks(63)
+                .map(str::from_utf8)
+                .collect::<Result<Vec<&str>, _>>()
+                .unwrap();
+
+            for chunk in chunks {
+                // Send the actual DATA after the tunnel is established
+                println!("[DBG]: Sending Chunk: {}", chunk);
+
+                // send the chunk
+                self.send_chunk(chunk);
+            }
+        } else {
+            self.send_chunk(&data);
+        }
+
+
+        // Close the data transfer by sending a `END` message
+        if !self.close_send() {
+            return Err("Failed to finish data transfer");
+        }
+
+        Ok(())
+
+    }
+
+    /// keeps open a listener to transfer data via DNS tunneling
+    pub fn tunnel_server(port: u16) {
+
+        let mut full_data: String = String::new();
+
+        println!("[+] Started DNS tunnel, ready to receive data...");
+        let socket = UdpSocket::bind(("0.0.0.0", port)).unwrap();
+
+        // starting main loop
+        loop {
+            let mut response_buffer = BytePacketBuffer::new();
+
+            // receive into response buffer
+            let (_, src) = socket.recv_from(&mut response_buffer.buf).unwrap();
+
+            let mut packet = DnsPacket::from_bytes(&mut response_buffer);
+
+            if packet.questions.len() >= 1 {
+                let quest = &packet.questions[0];
+                if quest.qtype == QueryType::TXT {
+
+                    let data = &quest.name;
+
+                    if !data.contains("init") &&
+                        !data.contains("start") &&
+                        !data.contains("end") {
+                        let mut data: Vec<&str> = data.split(".").collect();
+                        let data = data[0];
+                        full_data.push_str(data);
+
+                    } else if data.contains("end") {
+                        println!("[*] Message: {}", full_data);
+                        full_data = String::new();
+                    }
+                    //if data.contains("tun") {
+                        let mut ret_pkt = DnsTunnel::get_txt_response(packet, "ACK".to_string());
+                        let res_buffer = DnsTunnel::get_buffer(&mut ret_pkt);
+                        socket.send_to(res_buffer.get_range(0, res_buffer.pos()).unwrap(), src).unwrap();
+                    //}
+                    //let data = DnsServer::decode(data);
+                }
+            }
+        }
+    }
+
+    /// Check if the remote server answers a simple `TUN` message with the
+    /// answer `ACK`, this means that the server is available and can
+    /// send back data.
+    fn send_chunk(&self, message: &str) -> bool {
+
+        // Craft new request with `INIT`
+        let mut pkt = self.get_txt_request(&self.domain, message.to_string());
+        let resp = pkt.send((&self.server, self.port));
+
+        // Check the answers
+        if resp.answers.len() < 1 {
+            return false;
+        }
+
+        let record = match &resp.answers[0] {
+            DnsRecord::TXT {
+                ref domain,
+                len,
+                ref txt,
+                ttl
+            } => {
+                if txt == "ACK" {
+                    return true;
+                }
+            }
+            _ => {
+                    return false;
+            }
+        };
+        return false;
+    }
+
+    fn check_connection(&self) -> bool {
+        self.send_chunk("INIT")
+    }
+
+    // Init the data transfer by sending a `START` message
+    fn init_send(&self) -> bool {
+        self.send_chunk("START")
+    }
+    // Closea the data transfer by sending an `END` message
+    fn close_send(&self) -> bool {
+        self.send_chunk("END")
+    }
+
+    /// Sends the data suplied in `data` via DNS tunneling to the server
+    /*
+    pub fn tunnel_client(port: u16, data: &String) {
+
+        let mut established = false;
+
+        println!("Sending {}", data);
+        let mut pkt = DnsTunnel::get_txt_request("swrzm.de", "TUN".to_string());
+
+        let server = ("127.0.0.1", 1053);
+        let resp = pkt.send(server);
+        if resp.answers.len() >= 1 {
+            let data = &resp.answers[0];
+
+            let data = match data {
+            DnsRecord::TXT {
+                ref domain,
+                len,
+                ref txt,
+                ttl
+            } => txt,
+                _ => ""
+            };
+            if data == "ACK" {
+                established = true;
+                println!("Received ACK, tunnel established");
+            }
+        }
+
+
+        if established {
+
+            if data.len() > 63 {
+                let chunks = data.as_bytes()
+                    .chunks(63)
+                    .map(str::from_utf8)
+                    .collect::<Result<Vec<&str>, _>>()
+                    .unwrap();
+                for split in chunks {
+                    // Send the actual DATA after the tunnel is established
+                    println!("Sending Chunk: {}", split);
+
+                    let mut pkt = DnsTunnel::get_txt_request("swrzm.de", split.to_string());
+                    pkt.send(server);
+                }
+            } else {
+                // Send the actual DATA after the tunnel is established
+                let mut pkt = DnsTunnel::get_txt_request("swrzm.de", data.to_string());
+                pkt.send(server);
+            }
+
+
+            // Send END Packet
+            let mut pkt = DnsTunnel::get_txt_request("swrzm.de", "END".to_string());
+            let resp = pkt.send(server);
+
+        }
+
+    }
+    */
+    fn get_txt_response(ref_pkt: DnsPacket, data: String) -> DnsPacket {
+        let mut packet = DnsPacket::empty();
+        packet.header.id = ref_pkt.header.id;
+        packet.header.recursion_desired = ref_pkt.header.recursion_desired;
+        packet.header.recursion_available = true;
+        packet.header.query_response = true;
+        packet.header.result_code = ResultCode::NOERROR;
+        let domain = &ref_pkt.questions[0].name;
+
+        let answer = DnsRecord::TXT {
+            domain: domain.to_string(),
+            len: data.len() as u8,
+            ttl: 7766,
+            txt: data
+        };
+        packet.answers.push(answer);
+        return packet;
+
+    }
+    fn get_txt_request(&self, domain: &str, data: String) -> DnsPacket {
+        let mut packet = DnsPacket::empty();
+        let full_domain = format!("{}.{}", data, domain);
+        let question = DnsQuestion{ name: full_domain, qtype: QueryType::TXT};
+        packet.questions.push(question);
+
+        packet
+    }
+
+    fn get_buffer(pkt: &mut DnsPacket) -> BytePacketBuffer {
+        let mut res_buffer = BytePacketBuffer::new();
+        pkt.write(&mut res_buffer).unwrap();
+        return res_buffer;
+    }
+
+}