|
@@ -1,6 +1,8 @@
|
|
|
use std::net::UdpSocket;
|
|
|
use crate::dns::*;
|
|
|
use std::str;
|
|
|
+use crate::utilities::*;
|
|
|
+
|
|
|
|
|
|
pub struct DnsServer {
|
|
|
}
|
|
@@ -167,6 +169,9 @@ impl DnsTunnel {
|
|
|
let socket = UdpSocket::bind(("0.0.0.0", port)).unwrap();
|
|
|
|
|
|
// starting main loop
|
|
|
+ let mut poll_status = PollStatus::NONE;
|
|
|
+
|
|
|
+
|
|
|
loop {
|
|
|
let mut response_buffer = BytePacketBuffer::new();
|
|
|
|
|
@@ -180,34 +185,107 @@ impl DnsTunnel {
|
|
|
if quest.qtype == QueryType::TXT {
|
|
|
|
|
|
let data = &quest.name;
|
|
|
+ let mut data: Vec<&str> = data.split(".").collect();
|
|
|
+ let data = data[0];
|
|
|
|
|
|
- if !data.contains("init") &&
|
|
|
- !data.contains("start") &&
|
|
|
- !data.contains("end") {
|
|
|
+ let data = b64decode(data);
|
|
|
+ let data = String::from_utf8_lossy(&xor(&data, 0xF5)).to_string();
|
|
|
+
|
|
|
+ if !data.contains("INIT") &&
|
|
|
+ !data.contains("START") &&
|
|
|
+ !data.contains("POLL") &&
|
|
|
+ !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") {
|
|
|
+ } else if data.contains("END") {
|
|
|
println!("[*] Message: {}", full_data);
|
|
|
full_data = String::new();
|
|
|
+ } else if data.contains("POLL") {
|
|
|
+ match poll_status {
|
|
|
+ PollStatus::NONE => {
|
|
|
+ // Enter Polling Mode
|
|
|
+ println!("[*] Polling Recieved");
|
|
|
+ let mut ret_pkt = DnsTunnel::get_txt_response(&packet, "START".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();
|
|
|
+ poll_status = PollStatus::STARTED;
|
|
|
+ },
|
|
|
+ PollStatus::STARTED => {
|
|
|
+ let data = "DAFUQISTHISSHIT";
|
|
|
+ // Send the data
|
|
|
+ let mut ret_pkt = DnsTunnel::get_txt_response(&packet, data.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();
|
|
|
+ poll_status = PollStatus::FINISHED;
|
|
|
+ },
|
|
|
+ PollStatus::FINISHED => {
|
|
|
+ // Send STOP message
|
|
|
+ let mut ret_pkt = DnsTunnel::get_txt_response(&packet, "END".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();
|
|
|
+ poll_status = PollStatus::NONE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
- //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();
|
|
|
- //}
|
|
|
+ // return ACk
|
|
|
+ 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);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// this is not only checking for an `ACK` as answer, but gets the returned
|
|
|
+ /// data
|
|
|
+ fn send_recv(&self, message: &str) -> Result<String, ()> {
|
|
|
+
|
|
|
+ // Take care of the encoding
|
|
|
+ let bytes = xor(message.as_bytes(), 0xF5);
|
|
|
+ let message = &b64encode(bytes);
|
|
|
+
|
|
|
+ // 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 Err(());
|
|
|
+ }
|
|
|
+
|
|
|
+ let record = match &resp.answers[0] {
|
|
|
+ DnsRecord::TXT {
|
|
|
+ ref domain,
|
|
|
+ len,
|
|
|
+ ref txt,
|
|
|
+ ttl
|
|
|
+ } => {
|
|
|
+ return Ok(txt.to_string())
|
|
|
+ }
|
|
|
+ _ => {
|
|
|
+ return Err(());
|
|
|
+ }
|
|
|
+ };
|
|
|
+ return Err(());
|
|
|
+
|
|
|
+ }
|
|
|
/// 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 {
|
|
|
|
|
|
+
|
|
|
+ // Take care of the encoding
|
|
|
+ let bytes = xor(message.as_bytes(), 0xF5);
|
|
|
+ let message = &b64encode(bytes);
|
|
|
+
|
|
|
// 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));
|
|
@@ -248,67 +326,34 @@ impl DnsTunnel {
|
|
|
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");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
+ pub fn poll(&self) -> Result<String, ()> {
|
|
|
|
|
|
- if established {
|
|
|
+ let mut wait_for_data = false;
|
|
|
+ let mut return_data = String::new();
|
|
|
|
|
|
- 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);
|
|
|
+ loop {
|
|
|
+ if let Ok(data) = self.send_recv("POLL") {
|
|
|
+ match &data[..] {
|
|
|
+ "START" => {
|
|
|
+ println!("Start");
|
|
|
+ wait_for_data = true;
|
|
|
+ },
|
|
|
+ "END" => {
|
|
|
+ println!("END");
|
|
|
+ wait_for_data = false;
|
|
|
+ return Ok(return_data);
|
|
|
+ },
|
|
|
+ _ => {
|
|
|
+ return_data.push_str(&data);
|
|
|
+ }
|
|
|
|
|
|
- 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);
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
+ Err(())
|
|
|
}
|
|
|
- */
|
|
|
- fn get_txt_response(ref_pkt: DnsPacket, data: String) -> DnsPacket {
|
|
|
+
|
|
|
+ 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;
|
|
@@ -342,4 +387,34 @@ impl DnsTunnel {
|
|
|
return res_buffer;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ fn split_data(data: String) -> Vec<String> {
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ */
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+enum PollStatus {
|
|
|
+ NONE,
|
|
|
+ STARTED,
|
|
|
+ FINISHED,
|
|
|
}
|