Implement --virtual-dns-pool

This commit is contained in:
B. Blechschmidt 2024-08-28 23:06:37 +02:00
parent 3f76ccec97
commit 8c28f2e000
3 changed files with 13 additions and 46 deletions

View file

@ -6,6 +6,7 @@ use tproxy_config::IpCidr;
use std::ffi::OsString;
use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
use std::str::FromStr;
#[derive(Debug, Clone, clap::Parser)]
#[command(author, version, about = "Tunnel interface to proxy.", long_about = None)]
@ -76,6 +77,10 @@ pub struct Args {
#[arg(long, value_name = "IP", default_value = "8.8.8.8")]
pub dns_addr: IpAddr,
/// IP address pool to be used by virtual DNS in CIDR notation.
#[arg(long, value_name = "CIDR", default_value = "198.18.0.0/15")]
pub virtual_dns_pool: IpCidr,
/// IPs used in routing setup which should bypass the tunnel,
/// in the form of IP or IP/CIDR. Multiple IPs can be specified,
/// e.g. --bypass 3.4.5.0/24 --bypass 5.6.7.8
@ -132,6 +137,7 @@ impl Default for Args {
tcp_timeout: 600,
udp_timeout: 10,
verbosity: ArgVerbosity::Info,
virtual_dns_pool: IpCidr::from_str("198.18.0.0/15").unwrap(),
}
}
}

View file

@ -161,7 +161,7 @@ where
let dns_addr = args.dns_addr;
let ipv6_enabled = args.ipv6_enabled;
let virtual_dns = if args.dns == ArgDns::Virtual {
Some(Arc::new(Mutex::new(VirtualDns::new())))
Some(Arc::new(Mutex::new(VirtualDns::new(args.virtual_dns_pool))))
} else {
None
};

View file

@ -4,9 +4,9 @@ use std::{
collections::HashMap,
convert::TryInto,
net::{IpAddr, Ipv4Addr, Ipv6Addr},
str::FromStr,
time::{Duration, Instant},
};
use tproxy_config::IpCidr;
const MAPPING_TIMEOUT: u64 = 60; // Mapping timeout in seconds
@ -27,29 +27,17 @@ pub struct VirtualDns {
next_addr: IpAddr,
}
impl Default for VirtualDns {
fn default() -> Self {
let start_addr = Ipv4Addr::from_str("198.18.0.0").unwrap();
let prefix_len = 15;
let network_addr = calculate_network_addr(start_addr, prefix_len);
let broadcast_addr = calculate_broadcast_addr(start_addr, prefix_len);
impl VirtualDns {
pub fn new(ip_pool: IpCidr) -> Self {
Self {
trailing_dot: false,
next_addr: start_addr.into(),
next_addr: ip_pool.first_address(),
name_to_ip: HashMap::default(),
network_addr: IpAddr::from(network_addr),
broadcast_addr: IpAddr::from(broadcast_addr),
network_addr: ip_pool.first_address(),
broadcast_addr: ip_pool.last_address(),
lru_cache: LruCache::new_unbounded(),
}
}
}
impl VirtualDns {
pub fn new() -> Self {
VirtualDns::default()
}
/// Returns the DNS response to send back to the client.
pub fn generate_query(&mut self, data: &[u8]) -> Result<(Vec<u8>, String, IpAddr)> {
@ -160,30 +148,3 @@ impl VirtualDns {
}
}
}
fn calculate_network_addr(ip: std::net::Ipv4Addr, prefix_len: u8) -> std::net::Ipv4Addr {
let mask = (!0u32) << (32 - prefix_len);
let ip_u32 = u32::from_be_bytes(ip.octets());
std::net::Ipv4Addr::from((ip_u32 & mask).to_be_bytes())
}
fn calculate_broadcast_addr(ip: std::net::Ipv4Addr, prefix_len: u8) -> std::net::Ipv4Addr {
let mask = (!0u32) >> prefix_len;
let ip_u32 = u32::from_be_bytes(ip.octets());
std::net::Ipv4Addr::from((ip_u32 | mask).to_be_bytes())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cidr_addr() {
let start_addr = Ipv4Addr::from_str("198.18.0.0").unwrap();
let prefix_len = 15;
let network_addr = calculate_network_addr(start_addr, prefix_len);
let broadcast_addr = calculate_broadcast_addr(start_addr, prefix_len);
assert_eq!(network_addr, Ipv4Addr::from_str("198.18.0.0").unwrap());
assert_eq!(broadcast_addr, Ipv4Addr::from_str("198.19.255.255").unwrap());
}
}