upload working
This commit is contained in:
parent
369c3617bc
commit
6a2c1ec15d
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -93,6 +93,12 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.22.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64ct"
|
name = "base64ct"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
@ -251,7 +257,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dnstp"
|
name = "dnstp"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"dnstplib",
|
"dnstplib",
|
||||||
@ -261,8 +267,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dnstp-client"
|
name = "dnstp-client"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"base64",
|
||||||
"clap",
|
"clap",
|
||||||
"dnstplib",
|
"dnstplib",
|
||||||
"log",
|
"log",
|
||||||
@ -272,9 +279,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dnstplib"
|
name = "dnstplib"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm-siv",
|
"aes-gcm-siv",
|
||||||
|
"base64",
|
||||||
"log",
|
"log",
|
||||||
"p256",
|
"p256",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
|
@ -5,4 +5,9 @@ members = [
|
|||||||
"dnstp",
|
"dnstp",
|
||||||
"dnstp-client",
|
"dnstp-client",
|
||||||
"dnstp-server",
|
"dnstp-server",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[workspace.package]
|
||||||
|
version = "0.1.1"
|
||||||
|
authors = ["sarsoo <andy@sarsoo.xyz>"]
|
||||||
|
documentation = "https://sarsoo.github.io/dnstp"
|
@ -1,6 +1,8 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "dnstp-client"
|
name = "dnstp-client"
|
||||||
version = "0.1.0"
|
version.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
documentation.workspace = true
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
@ -11,4 +13,5 @@ dnstplib = { path = "../dnstp" }
|
|||||||
clap = { version = "4.5.11", features = ["derive"] }
|
clap = { version = "4.5.11", features = ["derive"] }
|
||||||
log = "0.4.22"
|
log = "0.4.22"
|
||||||
simplelog = "0.12.2"
|
simplelog = "0.12.2"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
base64 = "0.22.1"
|
@ -1,6 +1,6 @@
|
|||||||
use crate::NetSettings;
|
use crate::NetSettings;
|
||||||
|
|
||||||
pub fn download(net_settings: NetSettings)
|
pub fn download(_net_settings: NetSettings)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
@ -15,6 +15,7 @@ use crate::test::send_test_requests;
|
|||||||
use crate::upload::upload;
|
use crate::upload::upload;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(name = "DNSTP")]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
struct Args {
|
struct Args {
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
@ -33,7 +34,7 @@ enum Command {
|
|||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
net_options: NetSettings,
|
net_options: NetSettings,
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
value: String
|
value: Vec<String>
|
||||||
},
|
},
|
||||||
/// Download a payload from the remote server
|
/// Download a payload from the remote server
|
||||||
Download {
|
Download {
|
||||||
|
@ -4,7 +4,7 @@ use std::thread;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use log::info;
|
use log::info;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use dnstplib::client_crypto_context::ClientCryptoContext;
|
use dnstplib::session::client_crypto_context::ClientCryptoContext;
|
||||||
use dnstplib::DomainConfig;
|
use dnstplib::DomainConfig;
|
||||||
use dnstplib::message::DNSMessage;
|
use dnstplib::message::DNSMessage;
|
||||||
use dnstplib::net::{DNSSocket, NetworkMessage};
|
use dnstplib::net::{DNSSocket, NetworkMessage};
|
||||||
@ -42,10 +42,12 @@ pub fn send_test_requests(args: NetSettings)
|
|||||||
|
|
||||||
let bytes = message.to_bytes();
|
let bytes = message.to_bytes();
|
||||||
|
|
||||||
tx_channel.send(Box::new(NetworkMessage {
|
if let Err(_) = tx_channel.send(Box::new(NetworkMessage {
|
||||||
buffer: Box::new(bytes),
|
buffer: Box::new(bytes),
|
||||||
peer: args.address.parse().unwrap()
|
peer: args.address.parse().unwrap()
|
||||||
}));
|
})) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
thread::sleep(Duration::from_secs(1));
|
thread::sleep(Duration::from_secs(1));
|
||||||
}
|
}
|
||||||
|
@ -3,16 +3,14 @@ use std::sync::{Arc, Mutex};
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use log::info;
|
use log::info;
|
||||||
use rand::RngCore;
|
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
use dnstplib::client_crypto_context::ClientCryptoContext;
|
use dnstplib::session::{ClientCryptoContext, generate_client_handshake_message, generate_string_encryption_message};
|
||||||
use dnstplib::{DomainConfig, send_message};
|
use dnstplib::{DomainConfig, send_message};
|
||||||
use dnstplib::message::{Direction, DNSHeader, DNSMessage, DNSQuestion, Opcode, QClass, QType, ResponseCode};
|
|
||||||
use dnstplib::net::DNSSocket;
|
use dnstplib::net::DNSSocket;
|
||||||
use dnstplib::processor::ResponseProcesor;
|
use dnstplib::processor::ResponseProcesor;
|
||||||
use crate::NetSettings;
|
use crate::NetSettings;
|
||||||
|
|
||||||
pub fn upload(net_settings: NetSettings, value: String)
|
pub fn upload(net_settings: NetSettings, values: Vec<String>)
|
||||||
{
|
{
|
||||||
let address = SocketAddr::from(([127, 0, 0, 1], 0));
|
let address = SocketAddr::from(([127, 0, 0, 1], 0));
|
||||||
|
|
||||||
@ -35,39 +33,7 @@ pub fn upload(net_settings: NetSettings, value: String)
|
|||||||
|
|
||||||
info!("sending handshake...");
|
info!("sending handshake...");
|
||||||
|
|
||||||
let message = DNSMessage {
|
let message = generate_client_handshake_message(&mut OsRng, &domain_config, crypto_context.clone(), &net_settings.address);
|
||||||
header: DNSHeader {
|
|
||||||
id: OsRng.next_u32() as u16,
|
|
||||||
direction: Direction::Request,
|
|
||||||
opcode: Opcode::Query,
|
|
||||||
authoritative: false,
|
|
||||||
truncation: false,
|
|
||||||
recursion_desired: false,
|
|
||||||
recursion_available: false,
|
|
||||||
valid_zeroes: true,
|
|
||||||
response: ResponseCode::NoError,
|
|
||||||
question_count: 2,
|
|
||||||
answer_record_count: 0,
|
|
||||||
authority_record_count: 0,
|
|
||||||
additional_record_count: 0,
|
|
||||||
},
|
|
||||||
questions: vec![
|
|
||||||
DNSQuestion {
|
|
||||||
qname: domain_config.get_fq_key_endpoint(),
|
|
||||||
qtype: QType::A,
|
|
||||||
qclass: QClass::Internet,
|
|
||||||
},
|
|
||||||
DNSQuestion {
|
|
||||||
qname: crypto_context.lock().unwrap().get_public_key_domain(&domain_config.base_domain),
|
|
||||||
qtype: QType::A,
|
|
||||||
qclass: QClass::Internet,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
answer_records: vec![],
|
|
||||||
authority_records: vec![],
|
|
||||||
additional_records: vec![],
|
|
||||||
peer: net_settings.address.parse().unwrap(),
|
|
||||||
};
|
|
||||||
|
|
||||||
send_message(message, &tx_channel);
|
send_message(message, &tx_channel);
|
||||||
|
|
||||||
@ -78,4 +44,19 @@ pub fn upload(net_settings: NetSettings, value: String)
|
|||||||
}
|
}
|
||||||
|
|
||||||
info!("crypto complete, sending data");
|
info!("crypto complete, sending data");
|
||||||
|
|
||||||
|
for v in values {
|
||||||
|
|
||||||
|
info!("sending [{}]", v);
|
||||||
|
|
||||||
|
if let Ok(encryption_message) = generate_string_encryption_message(
|
||||||
|
v,
|
||||||
|
&mut OsRng,
|
||||||
|
&domain_config,
|
||||||
|
crypto_context.clone(),
|
||||||
|
&net_settings.address
|
||||||
|
) {
|
||||||
|
send_message(encryption_message, &tx_channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,6 +1,8 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "dnstp"
|
name = "dnstp"
|
||||||
version = "0.1.0"
|
version.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
documentation.workspace = true
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ use dnstplib::processor::RequestProcesor;
|
|||||||
|
|
||||||
/// Command-line arguments for configuring the server
|
/// Command-line arguments for configuring the server
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(name = "DNSTPd")]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
struct Args {
|
struct Args {
|
||||||
/// Addresses to bind server to
|
/// Addresses to bind server to
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "dnstplib"
|
name = "dnstplib"
|
||||||
version = "0.1.0"
|
version.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
documentation.workspace = true
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
publish = ["sargit"]
|
publish = ["sargit"]
|
||||||
|
|
||||||
@ -12,4 +14,5 @@ urlencoding = "2.1.3"
|
|||||||
|
|
||||||
rand_core = { version = "0.6.4", features = ["getrandom"] }
|
rand_core = { version = "0.6.4", features = ["getrandom"] }
|
||||||
p256 = { version = "0.13.2", features = ["ecdh"] }
|
p256 = { version = "0.13.2", features = ["ecdh"] }
|
||||||
aes-gcm-siv = "0.11.1"
|
aes-gcm-siv = "0.11.1"
|
||||||
|
base64 = "0.22.1"
|
@ -49,14 +49,6 @@ pub fn get_shared_asym_secret(secret: &EphemeralSecret, opposing_public_key: &St
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn generate_aes_nonce() -> Nonce
|
|
||||||
// {
|
|
||||||
// let mut nonce_buffer: [u8; 12] = [0; 12];
|
|
||||||
// &OsRng.fill_bytes(&mut nonce_buffer);
|
|
||||||
//
|
|
||||||
// Nonce::from(nonce_buffer)
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// Generate a safe nonce to use in symmetric encryption
|
/// Generate a safe nonce to use in symmetric encryption
|
||||||
pub fn generate_aes_nonce() -> Nonce
|
pub fn generate_aes_nonce() -> Nonce
|
||||||
{
|
{
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
//! # Common Functionality
|
//! # Common Functionality
|
||||||
//! The vast majority of functionality is in this library crate. The client and server executable crates are really just wiring up bits and pieces from this library.
|
//! The vast majority of functionality is in this library crate. The client and server executable crates are really just wiring up bits and pieces from this library.
|
||||||
|
|
||||||
pub mod message_parser;
|
|
||||||
|
|
||||||
mod byte;
|
mod byte;
|
||||||
pub mod processor;
|
pub mod processor;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
@ -10,10 +8,9 @@ pub mod net;
|
|||||||
pub mod string;
|
pub mod string;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
pub mod clients;
|
pub mod session;
|
||||||
pub mod client_crypto_context;
|
|
||||||
|
|
||||||
use std::sync::mpsc::{Sender};
|
use std::sync::mpsc::Sender;
|
||||||
use log::error;
|
use log::error;
|
||||||
pub use config::DomainConfig;
|
pub use config::DomainConfig;
|
||||||
use crate::message::DNSMessage;
|
use crate::message::DNSMessage;
|
||||||
|
@ -102,29 +102,29 @@ impl DNSHeader {
|
|||||||
{
|
{
|
||||||
let mut header_bytes: [u8; 12] = [0; 12];
|
let mut header_bytes: [u8; 12] = [0; 12];
|
||||||
|
|
||||||
apply_split_bytes(&mut header_bytes, self.id, crate::message_parser::ID_START);
|
apply_split_bytes(&mut header_bytes, self.id, crate::message::message_parser::ID_START);
|
||||||
|
|
||||||
let mut flags: u16 = 0;
|
let mut flags: u16 = 0;
|
||||||
|
|
||||||
if self.direction == Response {
|
if self.direction == Response {
|
||||||
flags |= 0b1 << crate::message_parser::DIRECTION_SHIFT;
|
flags |= 0b1 << crate::message::message_parser::DIRECTION_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags |= (self.opcode as u16) << crate::message_parser::OPCODE_SHIFT;
|
flags |= (self.opcode as u16) << crate::message::message_parser::OPCODE_SHIFT;
|
||||||
|
|
||||||
flags |= (self.authoritative as u16) << crate::message_parser::AUTHORITATIVE_SHIFT;
|
flags |= (self.authoritative as u16) << crate::message::message_parser::AUTHORITATIVE_SHIFT;
|
||||||
flags |= (self.truncation as u16) << crate::message_parser::TRUNCATION_SHIFT;
|
flags |= (self.truncation as u16) << crate::message::message_parser::TRUNCATION_SHIFT;
|
||||||
flags |= (self.recursion_desired as u16) << crate::message_parser::RECURSION_DESIRED_SHIFT;
|
flags |= (self.recursion_desired as u16) << crate::message::message_parser::RECURSION_DESIRED_SHIFT;
|
||||||
flags |= (self.recursion_available as u16) << crate::message_parser::RECURSION_AVAILABLE_SHIFT;
|
flags |= (self.recursion_available as u16) << crate::message::message_parser::RECURSION_AVAILABLE_SHIFT;
|
||||||
|
|
||||||
flags |= self.response as u16;
|
flags |= self.response as u16;
|
||||||
|
|
||||||
apply_split_bytes(&mut header_bytes, flags, crate::message_parser::FLAGS_START);
|
apply_split_bytes(&mut header_bytes, flags, crate::message::message_parser::FLAGS_START);
|
||||||
|
|
||||||
apply_split_bytes(&mut header_bytes, self.question_count, crate::message_parser::QUESTION_COUNT_START);
|
apply_split_bytes(&mut header_bytes, self.question_count, crate::message::message_parser::QUESTION_COUNT_START);
|
||||||
apply_split_bytes(&mut header_bytes, self.answer_record_count, crate::message_parser::ANSWER_RECORD_COUNT_START);
|
apply_split_bytes(&mut header_bytes, self.answer_record_count, crate::message::message_parser::ANSWER_RECORD_COUNT_START);
|
||||||
apply_split_bytes(&mut header_bytes, self.authority_record_count, crate::message_parser::AUTHORITY_RECORD_COUNT_START);
|
apply_split_bytes(&mut header_bytes, self.authority_record_count, crate::message::message_parser::AUTHORITY_RECORD_COUNT_START);
|
||||||
apply_split_bytes(&mut header_bytes, self.additional_record_count, crate::message_parser::ADDITIONAL_RECORD_COUNT_START);
|
apply_split_bytes(&mut header_bytes, self.additional_record_count, crate::message::message_parser::ADDITIONAL_RECORD_COUNT_START);
|
||||||
|
|
||||||
header_bytes
|
header_bytes
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ impl DNSMessage {
|
|||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn protocol_error_from_request(&self, error_code: RequestError) -> DNSMessage
|
pub fn protocol_error_from_request(&self, _error_code: RequestError) -> DNSMessage
|
||||||
{
|
{
|
||||||
let txt = Box::new(TXTRdata::from(String::new()));
|
let txt = Box::new(TXTRdata::from(String::new()));
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use crate::byte;
|
use crate::byte;
|
||||||
use crate::message::{DNSMessage, Direction, DNSHeader, Opcode, ResponseCode, QuestionParseError, questions_from_bytes, records_from_bytes, RecordParseError};
|
use crate::message::{DNSMessage, Direction, DNSHeader, Opcode, ResponseCode, QuestionParseError, questions_from_bytes, records_from_bytes, RecordParseError};
|
||||||
use crate::net::NetworkMessage;
|
use crate::net::NetworkMessage;
|
||||||
use crate::message_parser::MessageParseError::{HeaderParse, QuesionsParse};
|
use crate::message::MessageParseError::{HeaderParse, QuesionsParse};
|
||||||
|
|
||||||
pub const ID_START: usize = 0;
|
pub const ID_START: usize = 0;
|
||||||
pub const FLAGS_START: usize = 2;
|
pub const FLAGS_START: usize = 2;
|
@ -3,8 +3,10 @@ pub mod header;
|
|||||||
pub mod question;
|
pub mod question;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
pub mod record;
|
pub mod record;
|
||||||
|
pub mod message_parser;
|
||||||
|
|
||||||
pub use question::{DNSQuestion, QClass, QType, QuestionParseError, questions_to_bytes, questions_from_bytes};
|
pub use question::{DNSQuestion, QClass, QType, QuestionParseError, questions_from_bytes, questions_to_bytes};
|
||||||
pub use record::{ResourceRecord, RawRData, RData, ARdata, AAAARdata, TXTRdata, RecordParseError, records_to_bytes, records_from_bytes};
|
pub use record::{AAAARdata, ARdata, RawRData, RData, RecordParseError, records_from_bytes, records_to_bytes, ResourceRecord, TXTRdata};
|
||||||
pub use header::{DNSHeader, Direction, Opcode, ResponseCode, HEADER_SIZE};
|
pub use header::{Direction, DNSHeader, HEADER_SIZE, Opcode, ResponseCode};
|
||||||
pub use message::DNSMessage;
|
pub use message::DNSMessage;
|
||||||
|
pub use message_parser::*;
|
@ -19,7 +19,7 @@ fn one_question_back_and_forth() {
|
|||||||
let mut q_bytes = q.to_bytes();
|
let mut q_bytes = q.to_bytes();
|
||||||
q_bytes.append(&mut vec![0, 0, 0, 0, 0, 0]);
|
q_bytes.append(&mut vec![0, 0, 0, 0, 0, 0]);
|
||||||
|
|
||||||
let (q_reconstructed, q_remaining) = questions_from_bytes(q_bytes, 1).unwrap();
|
let (q_reconstructed, _q_remaining) = questions_from_bytes(q_bytes, 1).unwrap();
|
||||||
|
|
||||||
assert_questions_eq!(q, q_reconstructed[0]);
|
assert_questions_eq!(q, q_reconstructed[0]);
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ fn two_questions_back_and_forth() {
|
|||||||
|
|
||||||
q_bytes.append(&mut q2_bytes);
|
q_bytes.append(&mut q2_bytes);
|
||||||
|
|
||||||
let (q_reconstructed, q_remaining) = questions_from_bytes(q_bytes, 2).unwrap();
|
let (q_reconstructed, _q_remaining) = questions_from_bytes(q_bytes, 2).unwrap();
|
||||||
|
|
||||||
assert_questions_eq!(q, q_reconstructed[0]);
|
assert_questions_eq!(q, q_reconstructed[0]);
|
||||||
assert_questions_eq!(q2, q_reconstructed[1]);
|
assert_questions_eq!(q2, q_reconstructed[1]);
|
||||||
@ -76,7 +76,7 @@ fn three_questions_back_and_forth() {
|
|||||||
q_bytes.append(&mut q2_bytes);
|
q_bytes.append(&mut q2_bytes);
|
||||||
q_bytes.append(&mut q3_bytes);
|
q_bytes.append(&mut q3_bytes);
|
||||||
|
|
||||||
let (q_reconstructed, q_remaining) = questions_from_bytes(q_bytes, 3).unwrap();
|
let (q_reconstructed, _q_remaining) = questions_from_bytes(q_bytes, 3).unwrap();
|
||||||
|
|
||||||
assert_questions_eq!(q, q_reconstructed[0]);
|
assert_questions_eq!(q, q_reconstructed[0]);
|
||||||
assert_questions_eq!(q2, q_reconstructed[1]);
|
assert_questions_eq!(q2, q_reconstructed[1]);
|
||||||
|
@ -28,7 +28,7 @@ fn one_answer_back_and_forth() {
|
|||||||
let mut q_bytes = q.to_bytes();
|
let mut q_bytes = q.to_bytes();
|
||||||
q_bytes.append(&mut vec![0, 0, 0, 0, 0, 0]);
|
q_bytes.append(&mut vec![0, 0, 0, 0, 0, 0]);
|
||||||
|
|
||||||
let (q_reconstructed, q_remaining) = records_from_bytes(q_bytes, 1).unwrap();
|
let (q_reconstructed, _q_remaining) = records_from_bytes(q_bytes, 1).unwrap();
|
||||||
|
|
||||||
assert_record_eq!(q, q_reconstructed[0]);
|
assert_record_eq!(q, q_reconstructed[0]);
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ fn two_answers_back_and_forth() {
|
|||||||
q_bytes.append(&mut q_2.to_bytes());
|
q_bytes.append(&mut q_2.to_bytes());
|
||||||
q_bytes.append(&mut vec![0, 0, 0, 0, 0, 0]);
|
q_bytes.append(&mut vec![0, 0, 0, 0, 0, 0]);
|
||||||
|
|
||||||
let (q_reconstructed, q_remaining) = records_from_bytes(q_bytes, 2).unwrap();
|
let (q_reconstructed, _q_remaining) = records_from_bytes(q_bytes, 2).unwrap();
|
||||||
|
|
||||||
assert_record_eq!(q, q_reconstructed[0]);
|
assert_record_eq!(q, q_reconstructed[0]);
|
||||||
assert_record_eq!(q_2, q_reconstructed[1]);
|
assert_record_eq!(q_2, q_reconstructed[1]);
|
||||||
|
@ -84,10 +84,12 @@ impl DNSSocket {
|
|||||||
Ok((read_count, peer)) => {
|
Ok((read_count, peer)) => {
|
||||||
|
|
||||||
if read_count > HEADER_SIZE {
|
if read_count > HEADER_SIZE {
|
||||||
message_sender.send(Box::new(NetworkMessage {
|
if let Err(_) = message_sender.send(Box::new(NetworkMessage {
|
||||||
buffer: buf,
|
buffer: buf,
|
||||||
peer
|
peer
|
||||||
}));
|
})) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
debug!("skipping processing message from [{}], message isn't longer than standard header", peer);
|
debug!("skipping processing message from [{}], message isn't longer than standard header", peer);
|
||||||
@ -155,11 +157,15 @@ impl DNSSocket {
|
|||||||
{
|
{
|
||||||
// if let Some(t) = &mut self.thread {
|
// if let Some(t) = &mut self.thread {
|
||||||
if let Some(k) = &self.rx_thread_killer {
|
if let Some(k) = &self.rx_thread_killer {
|
||||||
k.send(());
|
if let Err(_) = k.send(()) {
|
||||||
|
|
||||||
|
}
|
||||||
// t.join();
|
// t.join();
|
||||||
}
|
}
|
||||||
if let Some(k) = &self.tx_thread_killer {
|
if let Some(k) = &self.tx_thread_killer {
|
||||||
k.send(());
|
if let Err(_) = k.send(()) {
|
||||||
|
|
||||||
|
}
|
||||||
// t.join();
|
// t.join();
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
|
@ -7,8 +7,7 @@ use std::net::SocketAddr;
|
|||||||
use log::error;
|
use log::error;
|
||||||
pub use request::RequestProcesor;
|
pub use request::RequestProcesor;
|
||||||
pub use response::ResponseProcesor;
|
pub use response::ResponseProcesor;
|
||||||
use crate::message::{QuestionParseError, RecordParseError};
|
use crate::message::{QuestionParseError, RecordParseError, HeaderParseError, MessageParseError};
|
||||||
use crate::message_parser::{HeaderParseError, MessageParseError};
|
|
||||||
|
|
||||||
pub fn print_error(e: MessageParseError, peer: &SocketAddr)
|
pub fn print_error(e: MessageParseError, peer: &SocketAddr)
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::sync::mpsc::Sender;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use log::{error, info};
|
||||||
|
use crate::session::clients::Clients;
|
||||||
|
use crate::message::DNSMessage;
|
||||||
|
use crate::net::NetworkMessagePtr;
|
||||||
|
use crate::processor::RequestProcesor;
|
||||||
|
|
||||||
|
impl RequestProcesor {
|
||||||
|
pub fn handle_download_request(r: DNSMessage, _sending_channel: &Sender<NetworkMessagePtr>, clients: &Arc<Mutex<Clients>>, peer: SocketAddr)
|
||||||
|
{
|
||||||
|
info!("[{}] received download request", peer);
|
||||||
|
let client_id = &r.questions[0].qname;
|
||||||
|
|
||||||
|
if let Err(_) = clients.lock().unwrap().bump_last_seen(client_id) {
|
||||||
|
error!("[{}] failed to bump last seen time", peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use p256::ecdh::EphemeralSecret;
|
use p256::ecdh::EphemeralSecret;
|
||||||
use crate::clients::Client;
|
use crate::session::clients::Client;
|
||||||
use crate::crypto::{asym_to_sym_key, get_random_asym_pair, get_shared_asym_secret, trim_public_key};
|
use crate::crypto::{asym_to_sym_key, get_random_asym_pair, get_shared_asym_secret, trim_public_key};
|
||||||
use crate::message::{ARdata, DNSMessage, QClass, QType, ResourceRecord};
|
use crate::message::{ARdata, DNSMessage, QClass, QType, ResourceRecord};
|
||||||
use crate::message::record::CnameRdata;
|
use crate::message::record::CnameRdata;
|
||||||
|
@ -2,13 +2,12 @@ use std::net::SocketAddr;
|
|||||||
use std::sync::{Arc, mpsc, Mutex};
|
use std::sync::{Arc, mpsc, Mutex};
|
||||||
use std::sync::mpsc::{Receiver, Sender};
|
use std::sync::mpsc::{Receiver, Sender};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use log::{error, info};
|
use log::{debug, error, info};
|
||||||
use crate::clients::Clients;
|
use crate::session::Clients;
|
||||||
use crate::config::DomainConfig;
|
use crate::config::DomainConfig;
|
||||||
|
|
||||||
use crate::message::{DNSMessage, QType};
|
use crate::message::{DNSMessage, QType, parse_message};
|
||||||
use crate::net::{NetworkMessagePtr};
|
use crate::net::{NetworkMessagePtr};
|
||||||
use crate::message_parser::parse_message;
|
|
||||||
use crate::processor::print_error;
|
use crate::processor::print_error;
|
||||||
use crate::processor::request::encryption::{decode_key_request, DecodeKeyRequestError};
|
use crate::processor::request::encryption::{decode_key_request, DecodeKeyRequestError};
|
||||||
use crate::{RequestError, send_message};
|
use crate::{RequestError, send_message};
|
||||||
@ -60,7 +59,7 @@ impl RequestProcesor {
|
|||||||
|
|
||||||
match parse_message(*m) {
|
match parse_message(*m) {
|
||||||
Ok(r) => {
|
Ok(r) => {
|
||||||
info!("received dns message: {:?}", r);
|
debug!("received dns message: {:?}", r);
|
||||||
|
|
||||||
// If there is a question containing the protocol base domain, treat it as a dnstp request
|
// If there is a question containing the protocol base domain, treat it as a dnstp request
|
||||||
// (handshake, upload, download) and handle as such
|
// (handshake, upload, download) and handle as such
|
||||||
@ -156,20 +155,6 @@ impl RequestProcesor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_download_request(r: DNSMessage, sending_channel: &Sender<NetworkMessagePtr>, clients: &Arc<Mutex<Clients>>, peer: SocketAddr)
|
|
||||||
{
|
|
||||||
info!("[{}] received download request", peer);
|
|
||||||
let client_id = &r.questions[0].qname;
|
|
||||||
clients.lock().unwrap().bump_last_seen(client_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_upload_request(r: DNSMessage, sending_channel: &Sender<NetworkMessagePtr>, clients: &Arc<Mutex<Clients>>, peer: SocketAddr)
|
|
||||||
{
|
|
||||||
info!("[{}] received upload request", peer);
|
|
||||||
let client_id = &r.questions[0].qname;
|
|
||||||
clients.lock().unwrap().bump_last_seen(client_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_message_channel(&mut self) -> Option<Sender<NetworkMessagePtr>>
|
pub fn get_message_channel(&mut self) -> Option<Sender<NetworkMessagePtr>>
|
||||||
{
|
{
|
||||||
self.message_channel.clone()
|
self.message_channel.clone()
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use crate::string::encode_domain_name;
|
use crate::string::encode_domain_name;
|
||||||
use super::*;
|
// use super::*;
|
||||||
use super::encryption::*;
|
use super::encryption::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn encryption()
|
fn encryption()
|
||||||
{
|
{
|
||||||
let (private, public) = get_key_request_with_base_domain(String::from("sarsoo.xyz"));
|
let (_private, public) = get_key_request_with_base_domain(String::from("sarsoo.xyz"));
|
||||||
|
|
||||||
let encoded = encode_domain_name(&public);
|
let _encoded = encode_domain_name(&public);
|
||||||
// let decoded = decode_domain_name();
|
// let decoded = decode_domain_name();
|
||||||
|
|
||||||
assert_eq!(1, 1);
|
assert_eq!(1, 1);
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::sync::mpsc::Sender;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use aes_gcm_siv::Nonce;
|
||||||
|
use log::{info, error};
|
||||||
|
use base64::prelude::*;
|
||||||
|
|
||||||
|
// use std::fs::OpenOptions;
|
||||||
|
// use std::io::prelude::*;
|
||||||
|
|
||||||
|
use crate::session::clients::Clients;
|
||||||
|
use crate::crypto::decrypt;
|
||||||
|
use crate::message::DNSMessage;
|
||||||
|
use crate::net::NetworkMessagePtr;
|
||||||
|
use crate::processor::RequestProcesor;
|
||||||
|
|
||||||
|
impl RequestProcesor {
|
||||||
|
pub fn handle_upload_request(r: DNSMessage, _sending_channel: &Sender<NetworkMessagePtr>, clients: &Arc<Mutex<Clients>>, peer: SocketAddr)
|
||||||
|
{
|
||||||
|
info!("[{}] received upload request", peer);
|
||||||
|
let client_id = &r.questions[0].qname;
|
||||||
|
|
||||||
|
if let Err(_) = clients.lock().unwrap().bump_last_seen(client_id) {
|
||||||
|
error!("[{}] failed to bump last seen time", peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
let encrypted_value = BASE64_STANDARD.decode(r.questions[1].qname.clone());
|
||||||
|
let nonce_value = BASE64_STANDARD.decode(r.questions[2].qname.clone());
|
||||||
|
|
||||||
|
match (encrypted_value, nonce_value) {
|
||||||
|
(Ok(encrypted_value), Ok(nonce_value)) => {
|
||||||
|
let nonce = Nonce::from_slice(nonce_value.as_slice());
|
||||||
|
let decrypted = decrypt(clients.lock().unwrap().get_shared_key(client_id).unwrap(), nonce, &encrypted_value).unwrap();
|
||||||
|
let decrypted_string = String::from_utf8(decrypted).unwrap();
|
||||||
|
|
||||||
|
info!("[{}] decrypted [{}] from peer", peer, decrypted_string.as_str());
|
||||||
|
|
||||||
|
// let mut file = OpenOptions::new()
|
||||||
|
// .read(true)
|
||||||
|
// .write(true)
|
||||||
|
// .append(true)
|
||||||
|
// .create(true)
|
||||||
|
// .open(client_id)
|
||||||
|
// .unwrap();
|
||||||
|
//
|
||||||
|
// if let Err(e) = file.write(decrypted_string.as_bytes()) {
|
||||||
|
// error!("[{}] couldn't write to file: {}", peer, e);
|
||||||
|
// }
|
||||||
|
// if let Err(e) = file.write("\n".as_bytes()) {
|
||||||
|
// error!("[{}] couldn't write to file: {}", peer, e);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
(Err(e), _) => {
|
||||||
|
error!("[{}] failed to decode encrypted value from peer: {}", peer, e);
|
||||||
|
}
|
||||||
|
(_, Err(e)) => {
|
||||||
|
error!("[{}] failed to decode nonce from peer: {}", peer, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use crate::client_crypto_context::ClientCryptoContext;
|
use crate::session::client_crypto_context::ClientCryptoContext;
|
||||||
use crate::crypto::{asym_to_sym_key, get_shared_asym_secret};
|
use crate::crypto::{asym_to_sym_key, get_shared_asym_secret};
|
||||||
use crate::message::DNSMessage;
|
use crate::message::DNSMessage;
|
||||||
use crate::string::get_fattened_public_key;
|
use crate::string::get_fattened_public_key;
|
||||||
|
@ -3,10 +3,10 @@ mod encryption;
|
|||||||
use std::sync::{Arc, mpsc, Mutex};
|
use std::sync::{Arc, mpsc, Mutex};
|
||||||
use std::sync::mpsc::{Receiver, Sender};
|
use std::sync::mpsc::{Receiver, Sender};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use log::{error, info};
|
use log::{error, info, debug};
|
||||||
use crate::client_crypto_context::ClientCryptoContext;
|
use crate::session::client_crypto_context::ClientCryptoContext;
|
||||||
use crate::net::raw_request::NetworkMessagePtr;
|
use crate::net::raw_request::NetworkMessagePtr;
|
||||||
use crate::message_parser::parse_message;
|
use crate::message::parse_message;
|
||||||
use crate::processor::print_error;
|
use crate::processor::print_error;
|
||||||
use crate::processor::response::encryption::{decode_key_response, DecodeKeyResponseError};
|
use crate::processor::response::encryption::{decode_key_response, DecodeKeyResponseError};
|
||||||
use crate::string::DomainDecodeError;
|
use crate::string::DomainDecodeError;
|
||||||
@ -39,7 +39,7 @@ impl ResponseProcesor {
|
|||||||
|
|
||||||
match parse_message(*m) {
|
match parse_message(*m) {
|
||||||
Ok(r) => {
|
Ok(r) => {
|
||||||
info!("received dns message: {:?}", r);
|
debug!("received dns message: {:?}", r);
|
||||||
|
|
||||||
match decode_key_response(&r, crypto_context.clone())
|
match decode_key_response(&r, crypto_context.clone())
|
||||||
{
|
{
|
||||||
|
@ -73,4 +73,15 @@ impl Clients {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_shared_key(&mut self, client_id: &String) -> Result<&Aes256GcmSiv, ()>
|
||||||
|
{
|
||||||
|
match self.client_map.get_mut(client_id)
|
||||||
|
{
|
||||||
|
None => Err(()),
|
||||||
|
Some(client) => {
|
||||||
|
Ok(&client.shared_key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
115
dnstp/src/session/message_generator.rs
Normal file
115
dnstp/src/session/message_generator.rs
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use base64::Engine;
|
||||||
|
use base64::prelude::BASE64_STANDARD;
|
||||||
|
use rand_core::{OsRng, RngCore};
|
||||||
|
use crate::crypto::{encrypt, generate_aes_nonce};
|
||||||
|
use crate::DomainConfig;
|
||||||
|
use crate::message::{Direction, DNSHeader, DNSMessage, DNSQuestion, Opcode, QClass, QType, ResponseCode};
|
||||||
|
use crate::session::ClientCryptoContext;
|
||||||
|
|
||||||
|
pub fn generate_client_handshake_message(rand: &mut OsRng, domain_config: &DomainConfig, crypto_context: Arc<Mutex<ClientCryptoContext>>, peer: &String) -> DNSMessage {
|
||||||
|
get_client_handshake_message(
|
||||||
|
rand.next_u32() as u16,
|
||||||
|
domain_config.get_fq_key_endpoint(),
|
||||||
|
crypto_context.lock().unwrap().get_public_key_domain(&domain_config.base_domain),
|
||||||
|
peer
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_client_handshake_message(msg_id: u16, key_domain: String, public_key_domain: String, peer: &String) -> DNSMessage {
|
||||||
|
DNSMessage {
|
||||||
|
header: DNSHeader {
|
||||||
|
id: msg_id,
|
||||||
|
direction: Direction::Request,
|
||||||
|
opcode: Opcode::Query,
|
||||||
|
authoritative: false,
|
||||||
|
truncation: false,
|
||||||
|
recursion_desired: false,
|
||||||
|
recursion_available: false,
|
||||||
|
valid_zeroes: true,
|
||||||
|
response: ResponseCode::NoError,
|
||||||
|
question_count: 2,
|
||||||
|
answer_record_count: 0,
|
||||||
|
authority_record_count: 0,
|
||||||
|
additional_record_count: 0,
|
||||||
|
},
|
||||||
|
questions: vec![
|
||||||
|
DNSQuestion {
|
||||||
|
qname: key_domain,
|
||||||
|
qtype: QType::A,
|
||||||
|
qclass: QClass::Internet,
|
||||||
|
},
|
||||||
|
DNSQuestion {
|
||||||
|
qname: public_key_domain,
|
||||||
|
qtype: QType::A,
|
||||||
|
qclass: QClass::Internet,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
answer_records: vec![],
|
||||||
|
authority_records: vec![],
|
||||||
|
additional_records: vec![],
|
||||||
|
peer: peer.parse().unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_string_encryption_message(value: String, rand: &mut OsRng, domain_config: &DomainConfig, crypto_context: Arc<Mutex<ClientCryptoContext>>, peer: &String) -> Result<DNSMessage, ()> {
|
||||||
|
|
||||||
|
let nonce = generate_aes_nonce();
|
||||||
|
let encrypted = encrypt(&crypto_context.lock().unwrap().shared_key.clone().unwrap(), &nonce, &value.clone().into_bytes());
|
||||||
|
|
||||||
|
if let Ok(e) = encrypted {
|
||||||
|
let encrypted_string = BASE64_STANDARD.encode(e);
|
||||||
|
let nonce_string = BASE64_STANDARD.encode(nonce);
|
||||||
|
|
||||||
|
return Ok(get_string_encryption_message(
|
||||||
|
rand.next_u32() as u16,
|
||||||
|
crypto_context.lock().unwrap().get_public_key_domain(&domain_config.base_domain),
|
||||||
|
encrypted_string,
|
||||||
|
nonce_string,
|
||||||
|
peer
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_string_encryption_message(msg_id: u16, public_key_domain: String, encrypted_string: String, nonce_string: String, peer: &String) -> DNSMessage {
|
||||||
|
DNSMessage {
|
||||||
|
header: DNSHeader {
|
||||||
|
id: msg_id,
|
||||||
|
direction: Direction::Request,
|
||||||
|
opcode: Opcode::Query,
|
||||||
|
authoritative: false,
|
||||||
|
truncation: false,
|
||||||
|
recursion_desired: false,
|
||||||
|
recursion_available: false,
|
||||||
|
valid_zeroes: true,
|
||||||
|
response: ResponseCode::NoError,
|
||||||
|
question_count: 3,
|
||||||
|
answer_record_count: 0,
|
||||||
|
authority_record_count: 0,
|
||||||
|
additional_record_count: 0,
|
||||||
|
},
|
||||||
|
questions: vec![
|
||||||
|
DNSQuestion {
|
||||||
|
qname: public_key_domain,
|
||||||
|
qtype: QType::A,
|
||||||
|
qclass: QClass::Internet,
|
||||||
|
},
|
||||||
|
DNSQuestion {
|
||||||
|
qname: encrypted_string,
|
||||||
|
qtype: QType::A,
|
||||||
|
qclass: QClass::Internet,
|
||||||
|
},
|
||||||
|
DNSQuestion {
|
||||||
|
qname: nonce_string,
|
||||||
|
qtype: QType::A,
|
||||||
|
qclass: QClass::Internet,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
answer_records: vec![],
|
||||||
|
authority_records: vec![],
|
||||||
|
additional_records: vec![],
|
||||||
|
peer: peer.parse().unwrap(),
|
||||||
|
}
|
||||||
|
}
|
7
dnstp/src/session/mod.rs
Normal file
7
dnstp/src/session/mod.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
pub mod clients;
|
||||||
|
pub mod client_crypto_context;
|
||||||
|
mod message_generator;
|
||||||
|
|
||||||
|
pub use clients::Clients;
|
||||||
|
pub use client_crypto_context::ClientCryptoContext;
|
||||||
|
pub use message_generator::{generate_client_handshake_message, generate_string_encryption_message};
|
Loading…
Reference in New Issue
Block a user