ソースを参照

initial commit

Marius Schwarz 4 年 前
コミット
1348d914ae
9 ファイル変更1565 行追加0 行削除
  1. 2 0
      .gitignore
  2. 14 0
      Cargo.toml
  3. 15 0
      Makefile
  4. 12 0
      README.md
  5. BIN
      img/basic-tunnel.png
  6. 790 0
      src/dns.rs
  7. 111 0
      src/main.rs
  8. 184 0
      src/message.rs
  9. 437 0
      src/server.rs

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+/target
+Cargo.lock

+ 14 - 0
Cargo.toml

@@ -0,0 +1,14 @@
+[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]
+base64 = "0.13.0"
+tun = "0.5.1"
+packet = "0.1.4"
+hex = "0.4.3"
+rand = "0.8.3"

+ 15 - 0
Makefile

@@ -0,0 +1,15 @@
+server:
+	cargo build
+	sudo ./target/debug/dns-client --tunnel-server
+
+client:
+	cargo build
+	sudo ./target/debug/dns-client --tunnel-client --tun
+nw:
+	# clean the iptables rules
+	sudo iptables -F
+	sudo iptables -t nat -F
+	echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
+	sudo iptables -A FORWARD -i tun1 -o wlp4s0 -j ACCEPT
+	#sudo iptables -t nat -A POSTROUTING -s 10.0.0.1/24 -o wlp4s0 -j SNAT --to-source 192.168.2.78
+	sudo iptables -t nat -A POSTROUTING -s 10.0.0.1/24 -o wlp4s0 -j MASQUERADE

+ 12 - 0
README.md

@@ -0,0 +1,12 @@
+# DNS VPN (DNS Tunnel)
+
+
+## DNS
+
+This contains a short implementation of the DNS protocol, inspired by the documentation from @EmilHernvall
+https://github.com/EmilHernvall/dnsguide/blob/master/chapter5.md
+
+
+## Tunnel
+
+TBD

BIN
img/basic-tunnel.png


+ 790 - 0
src/dns.rs

@@ -0,0 +1,790 @@
+use std::net::{Ipv4Addr, Ipv6Addr};
+use std::net::UdpSocket;
+use rand::{Rng};
+
+/// Raw DNS packet
+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 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 mut rng = rand::thread_rng();
+        let port: u16 = rng.gen_range(1001..65000) as u16;
+        let socket = UdpSocket::bind(("0.0.0.0", port)).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_string();
+                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(())
+    }
+}

+ 111 - 0
src/main.rs

@@ -0,0 +1,111 @@
+mod dns;
+mod message;
+mod server;
+
+use server::*;
+use message::{MessageQueue, MessageType};
+use std::env;
+use std::io::{Read, Write};
+use std::time::Duration;
+use std::thread;
+use tun;
+
+
+fn main() {
+
+
+    let args: Vec<String> =env::args().collect();
+    let port: u16 = 1053; // default port for the tunnel server
+
+    // When used as server component
+    if args.contains(&"--tunnel-server".to_string()) {
+
+        // create a new tunnel server
+        let mut server = DnsTunnel::new_server("swrzm.de".to_string(), port);
+        server.serve();
+
+    } else if args.contains(&"--tunnel-client".to_string()) {
+
+        // connect to the tunnel server
+        let tunnel = DnsTunnel::new("swrzm.de".to_string(), "192.168.122.1".to_string(), port);
+        let poll_tunnel = tunnel.clone();
+
+        tunnel.connect().expect("[-] Failed to connect to server");
+        poll_tunnel.connect().expect("[-] Failed to connect to server");
+
+        // Creating Tun interface with addr. 10.0.0.1
+        let mut read_config = tun::Configuration::default();
+        read_config.address((10, 0, 0, 2))
+               .netmask((255, 255, 255, 0))
+               .up();
+        let mut write_config = tun::Configuration::default();
+        write_config.address((10, 0, 0, 4))
+               .netmask((255, 255, 255, 0))
+               .up();
+
+        let mut read_dev = tun::create(&read_config).unwrap();
+        let mut write_dev = tun::create(&write_config).unwrap();
+        let mut msg_queue = MessageQueue::new();
+
+        // Create a new thread to handle the incoming packets, and resend ehm to the original
+        // destination
+        let polling_thread = thread::spawn(move || {
+            let mut should_sleep = true;
+            loop {
+                if let Some(pkt) = poll_tunnel.poll() {
+                    match pkt.msg_type {
+                        MessageType::DATA => {
+                            msg_queue.insert_msg(pkt);
+                            should_sleep = false;
+                        },
+                        MessageType::DATAFIN => {
+                            msg_queue.insert_msg(pkt);
+                            should_sleep = true;
+                        },
+                        _ => {
+                        }
+                    }
+                }
+
+                for pkt in &msg_queue.packets {
+                    write_dev.write(pkt).unwrap();
+                }
+                // clear the packets
+                msg_queue.packets.clear();
+
+                if should_sleep {
+                    thread::sleep(Duration::from_millis(5));
+                }
+            }
+
+        });
+        let client_thread = thread::spawn(move || {
+            println!("[+] Started client thread");
+            // create a new thread for the tunnel
+            let mut buf = [0; 4096];
+            let mut amount: usize;
+            loop {
+
+                amount = read_dev.read(&mut buf).unwrap();
+                if amount == 0 {
+                    continue;
+                }
+                let packet = &buf[0 .. amount];
+                /*
+                match ip::Packet::new(packet) {
+                    Ok(ip::Packet::V4(pkt)) => {
+                        println!("[CLIENT -> SERVER] Captured packet: Src: {:?} Dst: {:?}", pkt.source(), pkt.destination());
+                    }
+                    _ => {
+                    }
+                }
+                */
+                tunnel.send_bytes(packet.to_vec());
+            }
+        });
+
+        // Wait until both threads are finished
+        client_thread.join().unwrap();
+        polling_thread.join().unwrap();
+    }
+}

+ 184 - 0
src/message.rs

@@ -0,0 +1,184 @@
+#![allow(dead_code)]
+use std::collections::HashMap;
+use std::collections::hash_map::Entry;
+use rand;
+use hex;
+
+/// Message type to distinguish
+/// the different messages send via
+/// dns
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+pub enum MessageType {
+    POLL,       // 1
+    INIT,       // 2
+    ACK,        // 3
+    DATA,       // 4
+    DATAFIN,    // 5
+    UNKNOWN // _
+}
+
+
+impl MessageType {
+
+    pub fn from_str(input: &str) -> Self {
+        match input {
+            "1" => MessageType::POLL,
+            "2" => MessageType::INIT,
+            "3" => MessageType::ACK,
+            "4" => MessageType::DATA,
+            "5" => MessageType::DATAFIN,
+            _ => MessageType::UNKNOWN,
+        }
+    }
+
+    /// maps the enum to a string (num)
+    pub fn to_str(msg_type: MessageType) -> &'static str {
+        match msg_type {
+            MessageType::POLL       => "1",
+            MessageType::INIT       => "2",
+            MessageType::ACK        =>  "3",
+            MessageType::DATA       => "4",
+            MessageType::DATAFIN    => "5",
+            MessageType::UNKNOWN    => "0"
+        }
+    }
+}
+
+
+/// Every DNS message is packed into
+/// this Message Format
+/// Implemented in DNS via:
+/// [type].[id].[data].[domain].[tld]
+#[derive(Debug)]
+pub struct Message {
+    pub msg_type: MessageType,
+    pub msg_id: u16,
+    pub data: Vec<u8>
+}
+
+
+impl<'a> Message {
+
+    /// Craft a new message from data only, creating a unique `msg_id`
+    pub fn new(msg_type: MessageType, data: Vec<u8>) -> Self {
+        let msg_id = rand::random::<u16>();
+        Message { msg_type, msg_id, data}
+    }
+
+    /// Specifiy the ID of the packet to generate several messages
+    /// with the same ID
+    pub fn with_id(msg_type: MessageType, msg_id: u16, data: Vec<u8>) -> Self {
+        Message { msg_type, msg_id, data }
+    }
+
+    pub fn default() -> Self {
+        Message {msg_type: MessageType::INIT, msg_id: rand::random::<u16>(), data: Vec::new() }
+    }
+
+    /// parse a message form a subdomain string
+    pub fn from(subdomain: &str, full_domain: bool) -> Option<Self> {
+        // Split the subdomain at every dot and parse into Message Struct
+        let parts: Vec<&str> = subdomain.splitn(3, ".").collect();
+
+        let msg_type = MessageType::from_str(parts[0]);
+        let msg_id: u16 = parts[1].parse().unwrap();
+        let mut data: Vec<u8> = Vec::new();
+        let data_string: String;
+        if full_domain {
+            let tmp_data_string: Vec<&str> = parts[2].rsplitn(3, ".").collect();
+            data_string = tmp_data_string[2].replace(".", "");
+        } else {
+            data_string = parts[2].replace(".", "");
+        }
+        if data_string != "00" {
+            data = hex::decode(&data_string).unwrap();
+        }
+        Some(Message {msg_type, msg_id, data})
+    }
+
+    /// outputs the fields of the message struct in the
+    /// subdomain order [type].[id].[data]
+    pub fn to_string(&self) -> String {
+            let mut subdomain = String::new();
+            subdomain.push_str(MessageType::to_str(self.msg_type));
+            subdomain.push_str(".");
+            subdomain.push_str(&self.msg_id.to_string());
+            subdomain.push_str(".");
+
+            if self.data.len() == 0 {
+                subdomain.push_str("00");
+            } else {
+                // split the encoded data into chunks of 63 chars
+                // [type].[id].[data].[data]...[data]
+                let encoded_data = hex::encode(&self.data);
+                let chunked = self.split_chunks(&encoded_data);
+                for chunk in chunked {
+                    subdomain.push_str(chunk);
+                    subdomain.push_str(".");
+                }
+                subdomain.pop();
+            }
+            subdomain
+    }
+
+    fn split_chunks(&self, data: &'a String) -> Vec<&'a str> {
+
+        let chunks = data.as_bytes()
+            .chunks(62)
+            .map(std::str::from_utf8)
+            .collect::<Result<Vec<&str>, _>>()
+            .unwrap();
+        return chunks;
+    }
+}
+
+
+/// A handler the keeps a HashMap to track the unfinished
+/// packets via the unique packet ID
+#[derive(Debug)]
+pub struct MessageQueue {
+    pub packets: Vec<Vec<u8>>, // the packets that are already finished
+    tmp_packets: HashMap<u16, Vec<u8>>,  // the packets that need more data
+}
+
+
+impl MessageQueue {
+    pub fn new() -> Self {
+        MessageQueue { packets: Vec::new(), tmp_packets: HashMap::new() }
+    }
+
+
+    /// Takes a `Message` as input and includes it into the hashmap
+    /// according to the supplied ID
+    pub fn insert_msg(&mut self, msg: Message) {
+
+        match msg.msg_type {
+            MessageType::DATA => {
+                // For unfinished data packets, insert them
+                // into the `tmp_packets` HashMap, as there is more
+                // data to come
+                match self.tmp_packets.entry(msg.msg_id) {
+                    Entry::Occupied(mut entry) => { entry.get_mut().extend(&msg.data); }
+                    Entry::Vacant(entry) => { entry.insert(msg.data); }
+                };
+            },
+            MessageType::DATAFIN => {
+
+                match self.tmp_packets.entry(msg.msg_id) {
+                    Entry::Occupied(mut entry) => {
+                        entry.get_mut().extend(&msg.data);
+                        self.packets.push(entry.get().to_vec());
+                        entry.remove();
+                    }
+                    Entry::Vacant(_) => {
+                        if msg.data.len() > 0 {
+                            self.packets.push(msg.data);
+                        }
+                    }
+                };
+            },
+            _ => {}
+        }
+    }
+}
+

+ 437 - 0
src/server.rs

@@ -0,0 +1,437 @@
+// package only crates
+use crate::message::{Message, MessageType, MessageQueue};
+use crate::dns::*;
+use std::net::UdpSocket;
+use std::str;
+use std::thread;
+use std::io::{Write, Read};
+// using for the tun interface and parsing the packets
+use tun;
+// Channels for inter-thread communication
+use std::sync::mpsc::{Sender, Receiver};
+use std::sync::{mpsc, Arc, Mutex};
+use std::collections::VecDeque;
+
+
+/// Struct to keep track of the packets that need to
+/// be returned from SERVER -> CLIENT
+#[derive(Clone)]
+pub struct ReturnPacket {
+    pub data: Vec<u8>,
+    pub pkt_id: u16
+}
+
+impl ReturnPacket {
+    /// Construct a new packet with the supplied data and a unique `pkt_id`
+    pub fn new() -> Self {
+        ReturnPacket { data: Vec::new(), pkt_id: rand::random::<u16>() }
+    }
+}
+
+#[derive(Clone)]
+pub struct DnsTunnel {
+    server: String,
+    domain: String,
+    port: u16,
+    return_packet: ReturnPacket
+}
+
+impl<'a> 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, return_packet: ReturnPacket::new() }
+    }
+
+    /// keeps open a listener to transfer data via DNS tunneling
+    pub fn new_server(domain: String, port: u16) -> DnsTunnel {
+        DnsTunnel { server: String::new(), port, domain, return_packet: ReturnPacket::new() }
+    }
+
+    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 serve(&mut self) {
+
+
+        println!("[+] Started DNS tunnel, ready to receive data...");
+        let socket = UdpSocket::bind(("0.0.0.0", self.port)).unwrap();
+
+
+        // Starting TUN interface on the server side
+        // Creating Tun interface with addr. 10.0.0.1
+        let mut write_config = tun::Configuration::default();
+        let mut read_config = tun::Configuration::default();
+        write_config.address((10, 0, 0, 1))
+               .netmask((255, 255, 255, 0))
+               .mtu(1500)
+               .layer(tun::Layer::L3)
+               .up();
+        read_config.address((10, 0, 0, 3))
+               .netmask((255, 255, 255, 0))
+               .mtu(1500)
+               .layer(tun::Layer::L3)
+               .up();
+
+
+        println!("[*] Spawning tun interface");
+        let mut read_dev = tun::create(&read_config).unwrap();   // tun1
+        let mut write_dev = tun::create(&write_config).unwrap();  // tun0
+
+        //let mut queue = Arc::new(RwLock::new(VecDeque::new()));
+        let queue = Arc::new(Mutex::new(VecDeque::new()));
+        let sender_queue = queue.clone();
+        let recv_queue = queue.clone();
+
+        // channels to communicate
+        let (tx, rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = mpsc::channel();
+
+
+        // Create a new thread to handle the incoming packets (via DNS),
+        // and write ehm to the tun interface
+        thread::spawn(move ||
+
+            //let mut buf = [0; 4096];
+            loop {
+                // receive the packet from the receiver (coming from DNS)
+                let packet_from_dns = rx.recv().unwrap();
+                // write that packet into the tun interface
+                // (routing done via iptables)
+                write_dev.write(&packet_from_dns).expect("[-] Failed to write packet to device");
+            }
+        );
+
+
+        // Create a second thread to handle the incoming packets (from
+        // the tun interface) and send em back to the DNS client
+        // (via the polling interface)
+        thread::spawn(move || {
+            // create a new thread for the tunnel
+            let mut buf = [0; 4096];
+            loop {
+                let amount: usize;
+                amount = read_dev.read(&mut buf).unwrap();
+                if amount ==0 {
+                    continue;
+                }
+
+                let packet = &buf[0 .. amount];
+                /*
+                match ip::Packet::new(packet) {
+                    Ok(ip::Packet::V4(pkt)) => {
+                        println!("[SERVER -> CLIENT]: Captured packet: Src: {:?} Dst: {:?}", pkt.source(), pkt.destination());
+                    }
+                    _ => {
+                    }
+                }
+                */
+                sender_queue.lock().unwrap().push_back(packet.to_vec());
+            }
+        });
+
+
+        // starting main loop
+        let mut poll_status = PollStatus::NONE;
+
+        let mut message = String::new();
+
+        // A message queue to store the tmp_messages
+        let mut msg_queue = MessageQueue::new();
+
+        // The main DNS Tunnel loop that works with the different packet types
+        loop {
+            let mut response_buffer = BytePacketBuffer::new();
+
+            // receive into response buffer
+            let (_, src) = socket.recv_from(&mut response_buffer.buf).unwrap();
+
+            // decode the response as DNS packet
+            let packet = DnsPacket::from_bytes(&mut response_buffer);
+
+            // if there is no at least one question or not of type TXT
+            if packet.questions.len() < 1 ||
+                packet.questions[0].qtype != QueryType::TXT {
+                    continue;
+            }
+
+            // Exfiltrate the Data
+            let data = &packet.questions[0].name;
+            if let Some(recv_msg) = Message::from(data, true) {
+                // Return DNS Packet
+                let mut return_packet = DnsPacket::empty();
+
+                match recv_msg.msg_type {
+                    MessageType::INIT => {
+                        return_packet = DnsTunnel::build_response(&packet, MessageType::ACK, None, None);
+                    },
+                    MessageType::DATA => {
+                        // For data transfer from CLIENT -> SERVER
+                        msg_queue.insert_msg(recv_msg);  // insert into the message queue
+                        return_packet = DnsTunnel::build_response(&packet, MessageType::ACK, None, None);
+                    },
+                    MessageType::DATAFIN => {
+                        // Data transfer CLIENT -> SERVER finished
+                        msg_queue.insert_msg(recv_msg); // insert the last packet
+
+                        // take all the packets and send ehm to the
+                        // tun interface
+                        for packet in &msg_queue.packets {
+                            tx.send(packet.to_vec()).expect("[-] Failed to send packet via channel");
+                        }
+                        msg_queue.packets.clear();
+                    },
+                    MessageType::POLL => {
+                        // For data transfer from SERVER -> CLIENT
+                        match poll_status {
+                            PollStatus::NONE => {
+                                // Enter Polling Mode
+                                return_packet = DnsTunnel::build_response(&packet, MessageType::POLL, None, None);
+
+                                // create new return packet
+                                self.return_packet = ReturnPacket::new();
+
+
+                                // if the queue is empty, polling is done
+                                let queue = recv_queue.lock().unwrap(); // make mutex available
+                                if queue.is_empty() {
+                                    poll_status = PollStatus::NONE;
+                                } else {
+                                    poll_status = PollStatus::STARTED;
+                                }
+                            },
+                            PollStatus::STARTED => {
+
+                                // create placeholder variables
+                                let chunk: Vec<u8>;
+                                let pkt_id: u16;
+                                // max length for the data in one DNS packet
+                                let max_len: usize = (255 - self.domain.len() - 3 - 5 - 3) / 2;
+                                // unllock the global DeQueue
+                                let mut queue = recv_queue.lock().unwrap(); // make mutex available
+                                // if the global buffer is already empty,
+                                // get a new item from the queue and
+                                // send this in chunks to the client
+                                if self.return_packet.data.len() == 0 && queue.len() >= 1 {
+                                    self.return_packet.data = queue.pop_front().unwrap();
+                                    //self.return_packet.data = queue_rx.recv().unwrap();
+                                }
+                                if self.return_packet.data.len() >= max_len {
+                                    chunk = self.return_packet.data[..max_len].to_vec();
+                                    pkt_id = self.return_packet.pkt_id;
+                                    self.return_packet.data = self.return_packet.data[max_len..].to_vec();
+                                    return_packet = DnsTunnel::build_response(&packet, MessageType::DATA, Some(pkt_id), Some(chunk));
+                                } else {
+                                    // send the rest via the DATAFIN packet (<max_len)
+                                    chunk = self.return_packet.data.to_vec();
+                                    pkt_id = self.return_packet.pkt_id;
+                                    return_packet = DnsTunnel::build_response(&packet, MessageType::DATAFIN, Some(pkt_id), Some(chunk));
+                                    poll_status = PollStatus::NONE;
+                                    // reset the ReturnPacket
+                                    self.return_packet = ReturnPacket::new();
+                                }
+
+
+                            }
+                        }
+                    },
+                    _ => {
+                        message.push_str(&data);
+                    }
+
+                }
+                // return the response Packet
+                let res_buffer = DnsTunnel::get_buffer(&mut return_packet);
+                socket.send_to(res_buffer.get_range(0, res_buffer.pos()).unwrap(), src).unwrap();
+            }
+        }
+    }
+
+
+    pub fn poll(&self) -> Option<Message> {
+        // create a new POLL message
+        let poll_msg = Message::new(MessageType::POLL, Vec::new());
+
+        // send the msg and receive the outout
+        if let Some(msg) = self.send_and_recv_message(poll_msg) {
+            return Some(msg);
+        }
+        return None;
+    }
+    pub fn send_bytes(&self, bytes: Vec<u8>) {
+        // The MAX_LEN = 255 of the full domain
+        const MAX_LEN: usize = 255;
+        // substract len of domain, 3 (dots), 6 (id & type)
+        // devided by two as the encoded representation of a byte takes to
+        // characters
+        let data_len: usize = (MAX_LEN - self.domain.len() - 3 - 6) / 2;
+
+        // if the size of the data execeeds
+        if bytes.len() > data_len {
+            // split the data in chunks of 63 bytes
+            let chunks = bytes
+                .chunks(data_len)
+                .collect::<Vec<&[u8]>>();
+
+            let queue_id = rand::random::<u16>();
+
+            // send the chunks
+            for chunk in chunks {
+                // craft and send the chunk
+                let tmp_msg = Message::with_id(MessageType::DATA, queue_id, chunk.to_vec());
+                self.send_message(tmp_msg);
+            }
+            // send a DATAFIN packet if every chunk is send
+            let tmp_msg = Message::with_id(MessageType::DATAFIN, queue_id, Vec::new());
+            self.send_message(tmp_msg);
+        } else {
+            let single_msg = Message::new(MessageType::DATAFIN, bytes);
+            self.send_message(single_msg);
+        }
+
+    }
+
+
+    /// 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_and_recv_message(&self, msg: Message) -> Option<Message> {
+
+        // Craft new request from `msg`
+        let mut pkt = self.build_request(msg);
+
+        // send the request to the DNS Tunnel Server
+        let resp = pkt.send((&self.server, self.port));
+
+        // Check for any answers to that query
+        if resp.answers.len() < 1 {
+            return None;
+        }
+        // Parse the answer
+        match &resp.answers[0] {
+            DnsRecord::TXT {
+                ref domain,
+                len: _,
+                ref txt,
+                ttl: _
+            } => {
+                return Message::from(txt, false);
+            }
+            _ => {
+                return None;
+            }
+        };
+    }
+    /// 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_message(&self, msg: Message) -> bool {
+
+        // Craft new request from `msg`
+        let mut pkt = self.build_request(msg);
+
+        // send the request to the DNS Tunnel Server
+        let resp = pkt.send((&self.server, self.port));
+
+        // Check for any answers to that query
+        if resp.answers.len() < 1 {
+            return false;
+        }
+        // Parse the answer
+        match &resp.answers[0] {
+            DnsRecord::TXT {
+                ref domain,
+                len: _,
+                ref txt,
+                ttl: _
+            } => {
+                if let Some(return_message) = Message::from(txt, false) {
+                    if return_message.msg_type == MessageType::ACK {
+                        return true;
+                    }
+                }
+            }
+            _ => {
+                    return false;
+            }
+        };
+        return false;
+    }
+
+    /// Sends a `INIT` message to the server to check if the servern
+    /// returns a `ACK`
+    fn check_connection(&self) -> bool {
+        // create a INIT message with empty data field
+        let init_msg = Message::new(MessageType::INIT, Vec::new());
+        self.send_message(init_msg)
+    }
+
+    /// Creates a DNS reponse packet, taking a `DnsPacket` as reference
+    /// and a message struct that is send in ther TXT response field
+    fn build_response(ref_pkt: &DnsPacket,
+            msg_type: MessageType,
+            msg_id: Option<u16>,
+            data: Option<Vec<u8>>) -> DnsPacket {
+        // Create a empty DnsPacket as base, and fill it with
+        // the needed data from the reference packet
+        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 mut msg = Message::default();
+
+        if let Some(msg_id) = msg_id {
+            msg.msg_type = msg_type;
+            msg.msg_id = msg_id;
+        } else {
+            msg.msg_type = msg_type;
+        }
+
+        if let Some(data) = data {
+            msg.data = data;
+        }
+        let return_data = msg.to_string();
+        let answer = DnsRecord::TXT {
+            domain: domain.to_string(),
+            len: return_data.len() as u8,
+            ttl: 7766,
+            txt: return_data
+        };
+        packet.answers.push(answer);
+        return packet;
+
+    }
+    fn build_request(&self, msg: Message) -> DnsPacket {
+        let mut packet = DnsPacket::empty();
+        let full_domain = format!("{}.{}", &msg.to_string(), self.domain);
+        // build a DNS TXT query out of the message
+        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;
+    }
+}
+
+
+enum PollStatus {
+    NONE,
+    STARTED,
+}