diff --git a/src/commands/setup.rs b/src/commands/setup.rs index 14c731932..ff72484d5 100644 --- a/src/commands/setup.rs +++ b/src/commands/setup.rs @@ -11,6 +11,7 @@ use crate::network::{core_utils, types}; use clap::Parser; use log::{debug, info}; use std::collections::HashMap; +use std::env; use std::fs; use std::net::IpAddr; use std::path::Path; @@ -70,6 +71,19 @@ impl Setup { let mut response: HashMap = HashMap::new(); + let dns_port = match env::var("NETAVARK_DNS_PORT") { + Ok(port_string) => match port_string.parse() { + Ok(port) => port, + Err(e) => { + return Err(NetavarkError::Message(format!( + "Invalid NETAVARK_DNS_PORT {}: {}", + port_string, e + ))) + } + }, + Err(_) => 53, + }; + // Perform per-network setup for (net_name, network) in network_options.network_info.iter() { debug!( @@ -186,6 +200,7 @@ impl Setup { subnet_v4: net_v4, container_ip_v6: addr_v6, subnet_v6: net_v6, + dns_port: if network.dns_enabled { dns_port } else { 53 }, }; // Need to enable sysctl localnet so that traffic can pass // through localhost to containers @@ -255,7 +270,8 @@ impl Setup { } }; - let mut aardvark_interface = Aardvark::new(path_string, rootless, aardvark_bin); + let mut aardvark_interface = + Aardvark::new(path_string, rootless, aardvark_bin, dns_port); if let Err(er) = aardvark_interface.commit_netavark_entries( network_options.container_name, diff --git a/src/commands/teardown.rs b/src/commands/teardown.rs index dcaab1ac7..543c87998 100644 --- a/src/commands/teardown.rs +++ b/src/commands/teardown.rs @@ -9,6 +9,7 @@ use crate::network::types::Subnet; use crate::{firewall, network}; use clap::Parser; use log::debug; +use std::env; use std::net::IpAddr; use std::path::Path; @@ -45,11 +46,25 @@ impl Teardown { } }; + let dns_port = match env::var("NETAVARK_DNS_PORT") { + Ok(port_string) => match port_string.parse() { + Ok(port) => port, + Err(e) => { + return Err(NetavarkError::Message(format!( + "Invalid NETAVARK_DNS_PORT {}: {}", + port_string, e + ))) + } + }, + Err(_) => 53, + }; + if Path::new(&aardvark_bin).exists() { // stop dns server first before netavark clears the interface let path = Path::new(&config_dir).join("aardvark-dns"); if let Ok(path_string) = path.into_os_string().into_string() { - let mut aardvark_interface = Aardvark::new(path_string, rootless, aardvark_bin); + let mut aardvark_interface = + Aardvark::new(path_string, rootless, aardvark_bin, dns_port); if let Err(er) = aardvark_interface.delete_from_netavark_entries(network_options.clone()) { @@ -144,6 +159,7 @@ impl Teardown { subnet_v4: net_v4, container_ip_v6: addr_v6, subnet_v6: net_v6, + dns_port: if network.dns_enabled { dns_port } else { 53 }, }; let td = TeardownPortForward { config: spf, diff --git a/src/dns/aardvark.rs b/src/dns/aardvark.rs index 783f6109f..01b2c3a58 100644 --- a/src/dns/aardvark.rs +++ b/src/dns/aardvark.rs @@ -34,14 +34,17 @@ pub struct Aardvark { pub rootless: bool, // path to the aardvark-dns binary pub aardvark_bin: String, + // port to bind to + pub port: String, } impl Aardvark { - pub fn new(config: String, rootless: bool, aardvark_bin: String) -> Self { + pub fn new(config: String, rootless: bool, aardvark_bin: String, port: u16) -> Self { Aardvark { config, rootless, aardvark_bin, + port: port.to_string(), } } @@ -94,7 +97,7 @@ impl Aardvark { "--config", &self.config, "-p", - "53", + &self.port, "run", ]); diff --git a/src/firewall/varktables/types.rs b/src/firewall/varktables/types.rs index 6c0535822..8071a8dbb 100644 --- a/src/firewall/varktables/types.rs +++ b/src/firewall/varktables/types.rs @@ -413,6 +413,24 @@ pub fn get_port_forwarding_chains<'a>( netavark_hashed_dn_chain.create = true; } + // Create redirection for aardvark-dns on non-standard port + if pfwd.dns_port != 53 { + if let Some(gateway) = network_address.gateway { + let mut gateway_ip_value = gateway.to_string(); + if is_ipv6 { + gateway_ip_value = format!("[{}]", gateway_ip_value) + } + netavark_hostport_dn_chain.create = true; + netavark_hostport_dn_chain.build_rule(VarkRule::new( + format!( + "-j {} -d {} -p {} --dport {} --to-destination {}:{}", + DNAT, gateway, "udp", 53, gateway_ip_value, pfwd.dns_port + ), + Some(TeardownPolicy::OnComplete), + )); + } + } + for i in pfwd.port_mappings.clone() { if let Ok(ip) = i.host_ip.parse::() { match ip { diff --git a/src/network/internal_types.rs b/src/network/internal_types.rs index a7311b53e..6b919dba5 100644 --- a/src/network/internal_types.rs +++ b/src/network/internal_types.rs @@ -55,6 +55,9 @@ pub struct PortForwardConfig { // subnet associated with the ipv6 address. // Must be set if the v6 address is set. pub subnet_v6: Option, + // port used by DNS that should create forwarding rules + // forwarding is not setup if this is 53. + pub dns_port: u16, } /// IPAMAddresses is used to pass ipam information around