impl: started writting FakeDNS server (or 'dns hijack')
This commit is contained in:
parent
0d81bae32a
commit
927299baad
6 changed files with 183 additions and 43 deletions
136
src/sniffing/dns/dnsfaker.rs
Normal file
136
src/sniffing/dns/dnsfaker.rs
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
use hickory_resolver::{
|
||||
TokioResolver,
|
||||
config::{NameServerConfig, ResolverConfig},
|
||||
net::runtime::TokioRuntimeProvider,
|
||||
proto::rr::IntoName,
|
||||
};
|
||||
use rand::RngExt;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::sync::Arc;
|
||||
|
||||
struct FakeIPEntry {
|
||||
domain_name: String,
|
||||
address: IpAddr,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum IPStrategies {
|
||||
V4Only,
|
||||
V6Only,
|
||||
Any,
|
||||
}
|
||||
|
||||
enum Protocols {
|
||||
DoH,
|
||||
DoU,
|
||||
DoT,
|
||||
DoTCP,
|
||||
}
|
||||
|
||||
pub struct FakeIPStorage {
|
||||
entries: Vec<FakeIPEntry>,
|
||||
resolver: Option<TokioResolver>,
|
||||
}
|
||||
|
||||
pub trait FakeIPOptions {
|
||||
fn add_new(&mut self, domain: String) -> Ipv4Addr;
|
||||
async fn add_real_ip(
|
||||
&mut self,
|
||||
domain: String,
|
||||
ip_type: IPStrategies,
|
||||
) -> Result<IpAddr, std::io::Error>;
|
||||
fn init_resolver(&mut self, link: String, domain: String) -> Result<(), std::io::Error>;
|
||||
}
|
||||
|
||||
fn generate_ip_from(network: Ipv4Addr, prefix: u32) -> Ipv4Addr {
|
||||
let mut rng = rand::rng();
|
||||
|
||||
let network = u32::from(network);
|
||||
let host_bits = 32 - prefix;
|
||||
let host = rng.random_range(0..(1u32 << host_bits));
|
||||
|
||||
Ipv4Addr::from(network | host)
|
||||
}
|
||||
|
||||
impl FakeIPOptions for FakeIPStorage {
|
||||
fn init_resolver(&mut self, link: String, domain: String) -> Result<(), std::io::Error> {
|
||||
let server_string = link.to_lowercase();
|
||||
|
||||
let raw_protocol: Vec<&str> = server_string.split("://").collect();
|
||||
|
||||
let result = match raw_protocol[0] {
|
||||
"tls" => Protocols::DoT,
|
||||
"tcp" => Protocols::DoTCP,
|
||||
"https" => Protocols::DoH,
|
||||
"udp" => Protocols::DoU,
|
||||
_ => {
|
||||
panic!("Wrong resolver protocol");
|
||||
}
|
||||
};
|
||||
|
||||
let ns: NameServerConfig = match result {
|
||||
Protocols::DoT => {
|
||||
NameServerConfig::tls(raw_protocol[1].to_ip().unwrap(), Arc::from(domain))
|
||||
}
|
||||
Protocols::DoTCP => NameServerConfig::tcp(raw_protocol[1].to_ip().unwrap()),
|
||||
Protocols::DoU => NameServerConfig::udp(raw_protocol[1].to_ip().unwrap()),
|
||||
_ => panic!("Wrong IP/domain of resolver"),
|
||||
};
|
||||
|
||||
let config = ResolverConfig::from_parts(None, vec![], vec![ns]);
|
||||
|
||||
self.resolver = Some(
|
||||
TokioResolver::builder_with_config(config, TokioRuntimeProvider::default())
|
||||
.build()
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_new(&mut self, domain: String) -> Ipv4Addr {
|
||||
let gen_ip = generate_ip_from(Ipv4Addr::new(198, 18, 0, 0), 15);
|
||||
|
||||
let entry = FakeIPEntry {
|
||||
domain_name: domain,
|
||||
address: IpAddr::V4(gen_ip),
|
||||
};
|
||||
|
||||
self.entries.push(entry);
|
||||
gen_ip
|
||||
}
|
||||
async fn add_real_ip(
|
||||
&mut self,
|
||||
domain: String,
|
||||
ip_type: IPStrategies,
|
||||
) -> Result<IpAddr, std::io::Error> {
|
||||
let lookup = self
|
||||
.resolver
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.lookup_ip(&domain)
|
||||
.await
|
||||
.map_err(|e| std::io::Error::other(e))?;
|
||||
|
||||
let ip = lookup
|
||||
.into_iter()
|
||||
.find(|ip| match ip_type {
|
||||
IPStrategies::V4Only => ip.is_ipv4(),
|
||||
IPStrategies::V6Only => ip.is_ipv6(),
|
||||
IPStrategies::Any => true,
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::AddrNotAvailable,
|
||||
"No suitable IP address found",
|
||||
)
|
||||
})?;
|
||||
|
||||
self.entries.push(FakeIPEntry {
|
||||
domain_name: domain,
|
||||
address: ip,
|
||||
});
|
||||
|
||||
Ok(ip)
|
||||
}
|
||||
}
|
||||
1
src/sniffing/dns/mod.rs
Normal file
1
src/sniffing/dns/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub mod dnsfaker;
|
||||
|
|
@ -1,47 +1,10 @@
|
|||
use crate::sniffing::types::*;
|
||||
use std::fmt;
|
||||
use tun::Error;
|
||||
|
||||
// Here we will recieve bytes and try to get their destanation & apply Rules for them.
|
||||
use crate::config::Config;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Protocol {
|
||||
TCP,
|
||||
UDP,
|
||||
Unsupported(u8),
|
||||
}
|
||||
type SourceV4Ip = Ipv4;
|
||||
type SourceV6Ip = Ipv6;
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum IpVersion {
|
||||
V4,
|
||||
V6,
|
||||
}
|
||||
type Ipv4 = [u8; 4];
|
||||
type Ipv6 = [u16; 8];
|
||||
type Port = u16;
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PacketInfo {
|
||||
// <https://www.geeksforgeeks.org/computer-networks/what-is-ipv4/>
|
||||
V4 {
|
||||
src_ip: Ipv4,
|
||||
src_port: Port,
|
||||
dst_ip: Ipv4,
|
||||
dst_port: Port,
|
||||
protocol: Protocol,
|
||||
dns: bool,
|
||||
},
|
||||
// <https://www.geeksforgeeks.org/computer-networks/internet-protocol-version-6-ipv6-header/>
|
||||
V6 {
|
||||
src_ip: Ipv6,
|
||||
src_port: Port,
|
||||
dst_ip: Ipv6,
|
||||
dst_port: Port,
|
||||
protocol: Protocol,
|
||||
dns: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Display for PacketInfo {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.version() == &IpVersion::V4 {
|
||||
|
|
@ -155,11 +118,6 @@ impl PacketInfo {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: move these to some appropriate file for code readability.
|
||||
type GenericError = Box<dyn std::error::Error + Send + Sync + 'static>;
|
||||
type SniffedPacket = Result<PacketInfo, Box<dyn std::error::Error + Send + Sync + 'static>>;
|
||||
type Packet = [u8];
|
||||
|
||||
pub fn sniff_raw_packets(packet: &Packet) -> SniffedPacket {
|
||||
let ver = packet[0] >> 4;
|
||||
match ver {
|
||||
|
|
|
|||
|
|
@ -1,2 +1,4 @@
|
|||
mod dns;
|
||||
pub mod headers;
|
||||
mod metadata;
|
||||
pub mod types;
|
||||
|
|
|
|||
1
src/sniffing/sniffer.rs
Normal file
1
src/sniffing/sniffer.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
42
src/sniffing/types.rs
Normal file
42
src/sniffing/types.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#[derive(Debug, PartialEq)]
|
||||
pub enum PacketInfo {
|
||||
// <https://www.geeksforgeeks.org/computer-networks/what-is-ipv4/>
|
||||
V4 {
|
||||
src_ip: Ipv4,
|
||||
src_port: Port,
|
||||
dst_ip: Ipv4,
|
||||
dst_port: Port,
|
||||
protocol: Protocol,
|
||||
dns: bool,
|
||||
},
|
||||
// <https://www.geeksforgeeks.org/computer-networks/internet-protocol-version-6-ipv6-header/>
|
||||
V6 {
|
||||
src_ip: Ipv6,
|
||||
src_port: Port,
|
||||
dst_ip: Ipv6,
|
||||
dst_port: Port,
|
||||
protocol: Protocol,
|
||||
dns: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Protocol {
|
||||
TCP,
|
||||
UDP,
|
||||
Unsupported(u8),
|
||||
}
|
||||
pub type SourceV4Ip = Ipv4;
|
||||
pub type SourceV6Ip = Ipv6;
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum IpVersion {
|
||||
V4,
|
||||
V6,
|
||||
}
|
||||
pub type Ipv4 = [u8; 4];
|
||||
pub type Ipv6 = [u16; 8];
|
||||
pub type Port = u16;
|
||||
|
||||
pub type GenericError = Box<dyn std::error::Error + Send + Sync + 'static>;
|
||||
pub type SniffedPacket = Result<PacketInfo, Box<dyn std::error::Error + Send + Sync + 'static>>;
|
||||
pub type Packet = [u8];
|
||||
Loading…
Add table
Add a link
Reference in a new issue