server: update system dns settings on address reload

This commit is contained in:
Luna Yao
2026-04-06 11:54:50 +02:00
parent d9d211c5a4
commit a73a029c50
5 changed files with 93 additions and 10 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
pub mod config; pub mod config;
mod node; pub mod node;
mod node_mgr; mod node_mgr;
mod peer_mgr; mod peer_mgr;
pub mod server; pub mod server;
pub mod system; mod system;
mod utils; mod utils;
pub mod zone; pub mod zone;
+18 -3
View File
@@ -3,6 +3,7 @@ use crate::common::PeerId;
use crate::dns::config::{DNS_SERVER_ELECTION_INTERVAL, DNS_SERVER_RPC_ADDR}; use crate::dns::config::{DNS_SERVER_ELECTION_INTERVAL, DNS_SERVER_RPC_ADDR};
use crate::dns::peer_mgr::DnsPeerMgr; use crate::dns::peer_mgr::DnsPeerMgr;
use crate::dns::server::DnsServer; use crate::dns::server::DnsServer;
use crate::instance::instance::ArcNicCtx;
use crate::peers::peer_manager::PeerManager; use crate::peers::peer_manager::PeerManager;
use crate::peers::NicPacketFilter; use crate::peers::NicPacketFilter;
use crate::proto::dns::{DnsNodeMgrRpcClientFactory, DnsPeerMgrRpcServer, HeartbeatRequest}; use crate::proto::dns::{DnsNodeMgrRpcClientFactory, DnsPeerMgrRpcServer, HeartbeatRequest};
@@ -20,12 +21,19 @@ use uuid::Uuid;
pub struct DnsNode { pub struct DnsNode {
mgr: Arc<DnsPeerMgr>, mgr: Arc<DnsPeerMgr>,
#[cfg(feature = "tun")]
nic_ctx: ArcNicCtx, // TODO: REMOVE THIS
peer_mgr: Arc<PeerManager>, peer_mgr: Arc<PeerManager>,
global_ctx: ArcGlobalCtx, global_ctx: ArcGlobalCtx,
} }
impl DnsNode { impl DnsNode {
pub fn new(peer_mgr: Arc<PeerManager>, global_ctx: ArcGlobalCtx) -> Self { pub fn new(
peer_mgr: Arc<PeerManager>,
global_ctx: ArcGlobalCtx,
#[cfg(feature = "tun")] nic_ctx: ArcNicCtx, // TODO: REMOVE THIS
) -> Self {
let mgr = Arc::new(DnsPeerMgr::new(peer_mgr.clone())); let mgr = Arc::new(DnsPeerMgr::new(peer_mgr.clone()));
peer_mgr peer_mgr
.get_peer_rpc_mgr() .get_peer_rpc_mgr()
@@ -38,8 +46,9 @@ impl DnsNode {
Self { Self {
mgr, mgr,
global_ctx, nic_ctx,
peer_mgr, peer_mgr,
global_ctx,
} }
} }
@@ -71,7 +80,13 @@ impl DnsNode {
tracing::info!("won DNS server election, starting DnsServer"); tracing::info!("won DNS server election, starting DnsServer");
let server = Arc::new(DnsServer::new(self.peer_mgr.clone(), rpc)); let server = Arc::new(DnsServer::new(
self.peer_mgr.clone(),
self.global_ctx.clone(),
rpc,
#[cfg(feature = "tun")]
self.nic_ctx.clone(),
));
self.global_ctx.set_dns(Some(server.clone())); self.global_ctx.set_dns(Some(server.clone()));
tokio::join!( tokio::join!(
+67 -2
View File
@@ -1,5 +1,9 @@
use crate::common::config::ConfigLoader;
use crate::common::global_ctx::ArcGlobalCtx;
use crate::dns::node_mgr::DnsNodeMgr; use crate::dns::node_mgr::DnsNodeMgr;
use crate::dns::system;
use crate::dns::utils::addr::NameServerAddr; use crate::dns::utils::addr::NameServerAddr;
use crate::instance::instance::{ArcNicCtx, NicCtx};
use crate::peer_center::instance::PeerCenterPeerManagerTrait; use crate::peer_center::instance::PeerCenterPeerManagerTrait;
use crate::peers::peer_manager::PeerManager; use crate::peers::peer_manager::PeerManager;
use crate::peers::NicPacketFilter; use crate::peers::NicPacketFilter;
@@ -10,6 +14,7 @@ use crate::tunnel::packet_def::ZCPacket;
use crate::tunnel::tcp::TcpTunnelListener; use crate::tunnel::tcp::TcpTunnelListener;
use derivative::Derivative; use derivative::Derivative;
use derive_more::{Deref, DerefMut, From, Into}; use derive_more::{Deref, DerefMut, From, Into};
use futures_util::StreamExt;
use hickory_proto::rr::Record; use hickory_proto::rr::Record;
use hickory_proto::serialize::binary::{BinDecodable, BinEncoder}; use hickory_proto::serialize::binary::{BinDecodable, BinEncoder};
use hickory_proto::xfer::Protocol; use hickory_proto::xfer::Protocol;
@@ -19,6 +24,7 @@ use hickory_server::{
server::{Request, RequestHandler, ResponseHandler, ResponseInfo}, server::{Request, RequestHandler, ResponseHandler, ResponseInfo},
ServerFuture, ServerFuture,
}; };
use itertools::Itertools;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use pnet::packet::icmp::{IcmpTypes, MutableIcmpPacket}; use pnet::packet::icmp::{IcmpTypes, MutableIcmpPacket};
use pnet::packet::ip::IpNextHeaderProtocols; use pnet::packet::ip::IpNextHeaderProtocols;
@@ -28,6 +34,7 @@ use pnet::packet::{icmp, ipv4, udp, MutablePacket, Packet};
use std::collections::HashSet; use std::collections::HashSet;
use std::io; use std::io;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4}; use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4};
use std::path::Display;
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use tokio_util::sync::CancellationToken; use tokio_util::sync::CancellationToken;
@@ -152,7 +159,11 @@ impl Drop for DnsServerRuntime {
pub struct DnsServer { pub struct DnsServer {
mgr: Arc<DnsNodeMgr>, mgr: Arc<DnsNodeMgr>,
#[cfg(feature = "tun")]
nic_ctx: ArcNicCtx, // TODO: REMOVE THIS
peer_mgr: Arc<PeerManager>, peer_mgr: Arc<PeerManager>,
global_ctx: ArcGlobalCtx,
#[derivative(Debug = "ignore")] #[derivative(Debug = "ignore")]
catalog: DynamicCatalog, catalog: DynamicCatalog,
@@ -163,7 +174,12 @@ pub struct DnsServer {
const DNS_SERVER_LISTENER_TCP_TIMEOUT: Duration = Duration::from_secs(5); const DNS_SERVER_LISTENER_TCP_TIMEOUT: Duration = Duration::from_secs(5);
impl DnsServer { impl DnsServer {
pub fn new(peer_mgr: Arc<PeerManager>, rpc: StandAloneServer<TcpTunnelListener>) -> Self { pub fn new(
peer_mgr: Arc<PeerManager>,
global_ctx: ArcGlobalCtx,
rpc: StandAloneServer<TcpTunnelListener>,
#[cfg(feature = "tun")] nic_ctx: ArcNicCtx, // TODO: REMOVE THIS
) -> Self {
let mgr = Arc::new(DnsNodeMgr::new()); let mgr = Arc::new(DnsNodeMgr::new());
rpc.registry() rpc.registry()
@@ -171,7 +187,9 @@ impl DnsServer {
Self { Self {
mgr, mgr,
nic_ctx,
peer_mgr, peer_mgr,
global_ctx,
catalog: DynamicCatalog::new(), catalog: DynamicCatalog::new(),
addresses: Arc::new(Default::default()), addresses: Arc::new(Default::default()),
} }
@@ -208,6 +226,50 @@ impl DnsServer {
Ok(()) Ok(())
} }
async fn reload_addresses(
&self,
addresses: impl IntoIterator<Item = NameServerAddr>,
) -> anyhow::Result<()> {
let addresses: HashSet<_> = addresses.into_iter().collect();
#[cfg(feature = "tun")]
{
let nic_ctx = self.nic_ctx.lock().await;
if let Some(nic_ctx) = nic_ctx
.as_ref()
.and_then(|nic_ctx| nic_ctx.downcast_ref::<NicCtx>())
{
if let Some(system) = nic_ctx
.ifname()
.await
.map(|ifname| system::get(&ifname))
.transpose()?
.flatten()
{
let config = self.global_ctx.config.get_dns();
let domain = vec![config.domain.to_string()];
system.set_dns(&system::SystemConfig {
nameservers: addresses
.iter()
.filter_map(|a| {
(a.protocol == Protocol::Udp).then_some(a.addr.to_string())
})
.collect(),
search_domains: domain.clone(),
match_domains: domain
.into_iter()
.chain(config.zones.iter().map(|z| z.origin.to_string()))
.collect(),
})?;
}
}
}
*self.addresses.write() = addresses;
Ok(())
}
pub async fn run(&self) { pub async fn run(&self) {
let dirty = &self.mgr.dirty; let dirty = &self.mgr.dirty;
let mut runtime = None; let mut runtime = None;
@@ -226,7 +288,10 @@ impl DnsServer {
loop { loop {
dirty.addresses.notified().await; dirty.addresses.notified().await;
if dirty.addresses.reset() { if dirty.addresses.reset() {
*self.addresses.write() = self.mgr.iter_addresses().collect(); if let Err(e) = self.reload_addresses(self.mgr.iter_addresses()).await {
tracing::error!("failed to reload addresses: {:?}", e);
dirty.addresses.mark();
}
} }
tokio::time::sleep(Duration::from_secs(1)).await; tokio::time::sleep(Duration::from_secs(1)).await;
} }
+1 -1
View File
@@ -22,7 +22,7 @@ pub trait SystemConfigurator: Send + Sync {
} }
// TODO: move this to nic mod // TODO: move this to nic mod
fn get( pub fn get(
#[allow(unused_variables)] interface: &str, #[allow(unused_variables)] interface: &str,
) -> Result<Option<Box<dyn SystemConfigurator>>, anyhow::Error> { ) -> Result<Option<Box<dyn SystemConfigurator>>, anyhow::Error> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
+5 -2
View File
@@ -25,6 +25,7 @@ use crate::connector::direct::DirectConnectorManager;
use crate::connector::manual::{ConnectorManagerRpcService, ManualConnectorManager}; use crate::connector::manual::{ConnectorManagerRpcService, ManualConnectorManager};
use crate::connector::tcp_hole_punch::TcpHolePunchConnector; use crate::connector::tcp_hole_punch::TcpHolePunchConnector;
use crate::connector::udp_hole_punch::UdpHolePunchConnector; use crate::connector::udp_hole_punch::UdpHolePunchConnector;
use crate::dns::node::DnsNode;
use crate::gateway::icmp_proxy::IcmpProxy; use crate::gateway::icmp_proxy::IcmpProxy;
#[cfg(feature = "kcp")] #[cfg(feature = "kcp")]
use crate::gateway::kcp_proxy::{KcpProxyDst, KcpProxyDstRpcService, KcpProxySrc}; use crate::gateway::kcp_proxy::{KcpProxyDst, KcpProxyDstRpcService, KcpProxySrc};
@@ -127,10 +128,10 @@ impl IpProxy {
} }
#[cfg(feature = "tun")] #[cfg(feature = "tun")]
type NicCtx = super::virtual_nic::NicCtx; pub type NicCtx = super::virtual_nic::NicCtx;
#[cfg(feature = "tun")] #[cfg(feature = "tun")]
type ArcNicCtx = Arc<Mutex<Option<Box<dyn Any + 'static + Send>>>>; pub type ArcNicCtx = Arc<Mutex<Option<Box<dyn Any + 'static + Send>>>>;
pub struct InstanceRpcServerHook { pub struct InstanceRpcServerHook {
rpc_portal_whitelist: Vec<IpCidr>, rpc_portal_whitelist: Vec<IpCidr>,
@@ -469,6 +470,8 @@ pub struct Instance {
#[cfg(feature = "tun")] #[cfg(feature = "tun")]
nic_ctx: ArcNicCtx, nic_ctx: ArcNicCtx,
#[cfg(feature = "magic-dns")]
dns: DnsNode,
peer_packet_receiver: Arc<Mutex<PacketRecvChanReceiver>>, peer_packet_receiver: Arc<Mutex<PacketRecvChanReceiver>>,
peer_manager: Arc<PeerManager>, peer_manager: Arc<PeerManager>,