Wildcard support

This commit is contained in:
Xnoe 2026-04-12 03:26:25 +01:00
parent 79fee04aef
commit 8e7220f704
Signed by: xnoe
GPG Key ID: 45AC398F44F0DAFE
5 changed files with 76 additions and 10 deletions

2
Cargo.lock generated
View File

@ -254,7 +254,7 @@ dependencies = [
]
[[package]]
name = "rust-dnsproxy-thing"
name = "rust-dns-selective-routing"
version = "0.1.0"
dependencies = [
"anyhow",

View File

@ -1,5 +1,5 @@
[package]
name = "rust-dnsproxy-thing"
name = "rust-dns-selective-routing"
version = "0.1.0"
edition = "2024"

View File

@ -15,7 +15,7 @@ impl<'a, T> Cursor<'a, T> {
pub fn next(&mut self) -> Option<&T> {
let next_index = self.index + 1;
if next_index >= self.buf.len() {
if next_index > self.buf.len() {
None
} else {
let v = &self.buf[self.index];
@ -25,7 +25,7 @@ impl<'a, T> Cursor<'a, T> {
}
pub fn seek(&mut self, location: usize) -> Result<(), ()> {
if location >= self.buf.len() {
if location > self.buf.len() {
Err(())
} else {
self.index = location;
@ -35,7 +35,7 @@ impl<'a, T> Cursor<'a, T> {
pub fn next_slice(&mut self, amount: usize) -> Option<&'a [T]> {
let next_index = self.index + amount;
if next_index >= self.buf.len() {
if next_index > self.buf.len() {
None
} else {
let slice = &self.buf[self.index..next_index];
@ -50,7 +50,7 @@ impl<'a, T> Cursor<'a, T> {
pub fn forward(&mut self, amount: usize) -> Result<(), ()> {
let next_index = self.index + amount;
if next_index >= self.buf.len() {
if next_index > self.buf.len() {
Err(())
} else {
self.index = next_index;

View File

@ -17,7 +17,7 @@ impl IpPool {
return None;
}
let last_address_number = u32::MAX & !subnet_prefix_mask;
let mut pool = VecDeque::with_capacity(last_address_number as usize);
let mut pool = VecDeque::with_capacity((last_address_number + 1) as usize);
for number in 0..=(last_address_number as usize) {
pool.push_back(Ipv4Addr::from(base_addr_int + (number as u32)));
}

View File

@ -278,7 +278,8 @@ async fn handle_dns_response(buf: &[u8], reply_buf: &mut Vec<u8>, tcp: bool) ->
if !FwmarkConfigMap
.lock()
.await
.contains_key(&parts_to_dns_name(&qname_parts))
.get(&parts_to_dns_name(&qname_parts))
.is_some()
{
eprintln!("Not forging due to non-matching qname.");
forge = false;
@ -401,8 +402,66 @@ struct Forwarding {
ttl: u32,
}
enum FwmarkDomainMatchType {
Exact,
Suffix
}
struct FwmarkConfig {
entries: Vec<(FwmarkDomainMatchType, Vec<Vec<u8>>, u32)>
}
impl FwmarkConfig {
fn new() -> Self {
Self {
entries: Vec::new()
}
}
fn insert(&mut self, dns_name: Vec<u8>, fwmark: u32) {
self.entries.push(
(
FwmarkDomainMatchType::Exact,
dns_name_to_parts(&mut Cursor::from(dns_name.as_slice())).unwrap(),
fwmark
)
);
}
fn insert_wildcard(&mut self, suffix_parts: Vec<Vec<u8>>, fwmark: u32) {
self.entries.push(
(
FwmarkDomainMatchType::Suffix,
suffix_parts,
fwmark
)
);
}
fn get(&self, dns_name: &Vec<u8>) -> Option<u32> {
let parts = dns_name_to_parts(&mut Cursor::from(dns_name.as_slice())).unwrap();
for (match_type, _parts, fwmark) in &self.entries {
match match_type {
FwmarkDomainMatchType::Exact => {
if parts == *_parts {
return Some(*fwmark)
}
},
FwmarkDomainMatchType::Suffix => {
if parts.ends_with(_parts.as_slice()) {
return Some(*fwmark)
}
}
}
}
None
}
}
lazy_static! {
static ref FwmarkConfigMap: Mutex<HashMap<Vec<u8>, u32>> = Mutex::new(HashMap::new());
static ref FwmarkConfigMap: Mutex<FwmarkConfig> = Mutex::new(FwmarkConfig::new());
static ref ForwardingMap: Mutex<HashMap<Vec<u8>, Vec<Forwarding>>> = Mutex::new(HashMap::new());
static ref IpAllocator: Mutex<IpPool> =
Mutex::new(IpPool::new(Ipv4Addr::new(100, 64, 0, 0), 24).unwrap());
@ -534,8 +593,15 @@ async fn main() -> anyhow::Result<()> {
if let Some(v) = map.get("domains") {
let mut fwmark_config = FwmarkConfigMap.lock().await;
for (domain, fwmark) in v.iter() {
let dns_name = string_to_dns_name(domain.to_string());
let parts = dns_name_to_parts(&mut Cursor::from(&dns_name)).unwrap();
if let Ok(fwmark) = fwmark.parse::<u32>() {
let _ = fwmark_config.insert(string_to_dns_name(domain.to_string()), fwmark);
if *parts.get(0).unwrap() == vec![b'*'] {
let _ = fwmark_config.insert_wildcard(parts[1..].to_vec(), fwmark);
} else {
let _ = fwmark_config.insert(dns_name, fwmark);
}
}
}
}