fix dns query (#864)

1. dns resolver should be global unique so dns cache can work. avoid dns query influence hole punching.
2. when system dns failed, fallback to hickory dns.
This commit is contained in:
Sijie.Sun
2025-05-23 10:34:28 +08:00
committed by GitHub
parent 83d1ecc4da
commit 5a2fd4465c
14 changed files with 201 additions and 110 deletions
+4 -20
View File
@@ -2,17 +2,15 @@ use std::{net::SocketAddr, sync::Arc};
use crate::{
common::{
dns::{resolve_txt_record, RESOLVER},
error::Error,
global_ctx::ArcGlobalCtx,
stun::{get_default_resolver_config, resolve_txt_record},
},
tunnel::{IpVersion, Tunnel, TunnelConnector, TunnelError, PROTO_PORT_OFFSET},
};
use anyhow::Context;
use dashmap::DashSet;
use hickory_resolver::{
name_server::TokioConnectionProvider, proto::rr::rdata::SRV, TokioResolver,
};
use hickory_resolver::proto::rr::rdata::SRV;
use rand::{seq::SliceRandom, Rng as _};
use crate::proto::common::TunnelInfo;
@@ -58,14 +56,7 @@ impl DNSTunnelConnector {
&self,
domain_name: &str,
) -> Result<Box<dyn TunnelConnector>, Error> {
let resolver = TokioResolver::builder_tokio()
.unwrap_or(TokioResolver::builder_with_config(
get_default_resolver_config(),
TokioConnectionProvider::default(),
))
.build();
let txt_data = resolve_txt_record(domain_name, &resolver)
let txt_data = resolve_txt_record(domain_name)
.await
.with_context(|| format!("resolve txt record failed, domain_name: {}", domain_name))?;
@@ -120,13 +111,6 @@ impl DNSTunnelConnector {
) -> Result<Box<dyn TunnelConnector>, Error> {
tracing::info!("handle_srv_record: {}", domain_name);
let resolver = TokioResolver::builder_tokio()
.unwrap_or(TokioResolver::builder_with_config(
get_default_resolver_config(),
TokioConnectionProvider::default(),
))
.build();
let srv_domains = PROTO_PORT_OFFSET
.iter()
.map(|(p, _)| (format!("_easytier._{}.{}", p, domain_name), *p)) // _easytier._udp.{domain_name}
@@ -136,7 +120,7 @@ impl DNSTunnelConnector {
let srv_lookup_tasks = srv_domains
.iter()
.map(|(srv_domain, protocol)| {
let resolver = resolver.clone();
let resolver = RESOLVER.clone();
let responses = responses.clone();
async move {
let response = resolver.srv_lookup(srv_domain).await.with_context(|| {
+9 -6
View File
@@ -60,7 +60,8 @@ pub async fn create_connector_by_url(
let url = url::Url::parse(url).map_err(|_| Error::InvalidUrl(url.to_owned()))?;
let mut connector: Box<dyn TunnelConnector + 'static> = match url.scheme() {
"tcp" => {
let dst_addr = check_scheme_and_get_socket_addr::<SocketAddr>(&url, "tcp", ip_version)?;
let dst_addr =
check_scheme_and_get_socket_addr::<SocketAddr>(&url, "tcp", ip_version).await?;
let mut connector = TcpTunnelConnector::new(url);
if global_ctx.config.get_flags().bind_device {
set_bind_addr_for_peer_connector(
@@ -73,7 +74,8 @@ pub async fn create_connector_by_url(
Box::new(connector)
}
"udp" => {
let dst_addr = check_scheme_and_get_socket_addr::<SocketAddr>(&url, "udp", ip_version)?;
let dst_addr =
check_scheme_and_get_socket_addr::<SocketAddr>(&url, "udp", ip_version).await?;
let mut connector = UdpTunnelConnector::new(url);
if global_ctx.config.get_flags().bind_device {
set_bind_addr_for_peer_connector(
@@ -90,14 +92,14 @@ pub async fn create_connector_by_url(
Box::new(connector)
}
"ring" => {
check_scheme_and_get_socket_addr::<uuid::Uuid>(&url, "ring", IpVersion::Both)?;
check_scheme_and_get_socket_addr::<uuid::Uuid>(&url, "ring", IpVersion::Both).await?;
let connector = RingTunnelConnector::new(url);
Box::new(connector)
}
#[cfg(feature = "quic")]
"quic" => {
let dst_addr =
check_scheme_and_get_socket_addr::<SocketAddr>(&url, "quic", ip_version)?;
check_scheme_and_get_socket_addr::<SocketAddr>(&url, "quic", ip_version).await?;
let mut connector = QUICTunnelConnector::new(url);
if global_ctx.config.get_flags().bind_device {
set_bind_addr_for_peer_connector(
@@ -111,7 +113,8 @@ pub async fn create_connector_by_url(
}
#[cfg(feature = "wireguard")]
"wg" => {
let dst_addr = check_scheme_and_get_socket_addr::<SocketAddr>(&url, "wg", ip_version)?;
let dst_addr =
check_scheme_and_get_socket_addr::<SocketAddr>(&url, "wg", ip_version).await?;
let nid = global_ctx.get_network_identity();
let wg_config = WgConfig::new_from_network_identity(
&nid.network_name,
@@ -131,7 +134,7 @@ pub async fn create_connector_by_url(
#[cfg(feature = "websocket")]
"ws" | "wss" => {
use crate::tunnel::FromUrl;
let dst_addr = SocketAddr::from_url(url.clone(), ip_version)?;
let dst_addr = SocketAddr::from_url(url.clone(), ip_version).await?;
let mut connector = crate::tunnel::websocket::WSTunnelConnector::new(url);
if global_ctx.config.get_flags().bind_device {
set_bind_addr_for_peer_connector(