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 std::fmt;
|
||||||
use tun::Error;
|
use tun::Error;
|
||||||
|
|
||||||
// Here we will recieve bytes and try to get their destanation & apply Rules for them.
|
// Here we will recieve bytes and try to get their destanation & apply Rules for them.
|
||||||
use crate::config::Config;
|
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 {
|
impl fmt::Display for PacketInfo {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
if self.version() == &IpVersion::V4 {
|
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 {
|
pub fn sniff_raw_packets(packet: &Packet) -> SniffedPacket {
|
||||||
let ver = packet[0] >> 4;
|
let ver = packet[0] >> 4;
|
||||||
match ver {
|
match ver {
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,4 @@
|
||||||
|
mod dns;
|
||||||
pub mod headers;
|
pub mod headers;
|
||||||
mod metadata;
|
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