mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-07 10:14:35 +00:00
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:
@@ -401,8 +401,8 @@ pub(crate) async fn wait_for_connect_futures<Fut, Ret, E>(
|
||||
mut futures: FuturesUnordered<Fut>,
|
||||
) -> Result<Ret, TunnelError>
|
||||
where
|
||||
Fut: Future<Output = Result<Ret, E>> + Send + Sync,
|
||||
E: std::error::Error + Into<TunnelError> + Send + Sync + 'static,
|
||||
Fut: Future<Output = Result<Ret, E>> + Send,
|
||||
E: std::error::Error + Into<TunnelError> + Send + 'static,
|
||||
{
|
||||
// return last error
|
||||
let mut last_err = None;
|
||||
|
||||
@@ -8,6 +8,7 @@ use std::fmt::Debug;
|
||||
|
||||
use tokio::time::error::Elapsed;
|
||||
|
||||
use crate::common::dns::socket_addrs;
|
||||
use crate::proto::common::TunnelInfo;
|
||||
|
||||
use self::packet_def::ZCPacket;
|
||||
@@ -169,13 +170,14 @@ impl std::fmt::Debug for dyn TunnelListener {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub(crate) trait FromUrl {
|
||||
fn from_url(url: url::Url, ip_version: IpVersion) -> Result<Self, TunnelError>
|
||||
async fn from_url(url: url::Url, ip_version: IpVersion) -> Result<Self, TunnelError>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
pub(crate) fn check_scheme_and_get_socket_addr_ext<T>(
|
||||
pub(crate) async fn check_scheme_and_get_socket_addr_ext<T>(
|
||||
url: &url::Url,
|
||||
scheme: &str,
|
||||
ip_version: IpVersion,
|
||||
@@ -187,10 +189,10 @@ where
|
||||
return Err(TunnelError::InvalidProtocol(url.scheme().to_string()));
|
||||
}
|
||||
|
||||
Ok(T::from_url(url.clone(), ip_version)?)
|
||||
Ok(T::from_url(url.clone(), ip_version).await?)
|
||||
}
|
||||
|
||||
pub(crate) fn check_scheme_and_get_socket_addr<T>(
|
||||
pub(crate) async fn check_scheme_and_get_socket_addr<T>(
|
||||
url: &url::Url,
|
||||
scheme: &str,
|
||||
ip_version: IpVersion,
|
||||
@@ -202,7 +204,7 @@ where
|
||||
return Err(TunnelError::InvalidProtocol(url.scheme().to_string()));
|
||||
}
|
||||
|
||||
Ok(T::from_url(url.clone(), ip_version)?)
|
||||
Ok(T::from_url(url.clone(), ip_version).await?)
|
||||
}
|
||||
|
||||
fn default_port(scheme: &str) -> Option<u16> {
|
||||
@@ -217,9 +219,17 @@ fn default_port(scheme: &str) -> Option<u16> {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl FromUrl for SocketAddr {
|
||||
fn from_url(url: url::Url, ip_version: IpVersion) -> Result<Self, TunnelError> {
|
||||
let addrs = url.socket_addrs(|| default_port(url.scheme()))?;
|
||||
async fn from_url(url: url::Url, ip_version: IpVersion) -> Result<Self, TunnelError> {
|
||||
let addrs = socket_addrs(&url, || default_port(url.scheme()))
|
||||
.await
|
||||
.map_err(|e| {
|
||||
TunnelError::InvalidAddr(format!(
|
||||
"failed to resolve socket addr, url: {}, error: {}",
|
||||
url, e
|
||||
))
|
||||
})?;
|
||||
tracing::debug!(?addrs, ?ip_version, ?url, "convert url to socket addrs");
|
||||
let addrs = addrs
|
||||
.into_iter()
|
||||
@@ -239,8 +249,9 @@ impl FromUrl for SocketAddr {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl FromUrl for uuid::Uuid {
|
||||
fn from_url(url: url::Url, _ip_version: IpVersion) -> Result<Self, TunnelError> {
|
||||
async fn from_url(url: url::Url, _ip_version: IpVersion) -> Result<Self, TunnelError> {
|
||||
let o = url.host_str().unwrap();
|
||||
let o = uuid::Uuid::parse_str(o).map_err(|e| TunnelError::InvalidAddr(e.to_string()))?;
|
||||
Ok(o)
|
||||
|
||||
@@ -85,7 +85,8 @@ impl QUICTunnelListener {
|
||||
impl TunnelListener for QUICTunnelListener {
|
||||
async fn listen(&mut self) -> Result<(), TunnelError> {
|
||||
let addr =
|
||||
check_scheme_and_get_socket_addr::<SocketAddr>(&self.addr, "quic", IpVersion::Both)?;
|
||||
check_scheme_and_get_socket_addr::<SocketAddr>(&self.addr, "quic", IpVersion::Both)
|
||||
.await?;
|
||||
let (endpoint, server_cert) = make_server_endpoint(addr).unwrap();
|
||||
self.endpoint = Some(endpoint);
|
||||
self.server_cert = Some(server_cert);
|
||||
@@ -149,11 +150,9 @@ impl QUICTunnelConnector {
|
||||
#[async_trait::async_trait]
|
||||
impl TunnelConnector for QUICTunnelConnector {
|
||||
async fn connect(&mut self) -> Result<Box<dyn Tunnel>, super::TunnelError> {
|
||||
let addr = check_scheme_and_get_socket_addr_ext::<SocketAddr>(
|
||||
&self.addr,
|
||||
"quic",
|
||||
self.ip_version,
|
||||
)?;
|
||||
let addr =
|
||||
check_scheme_and_get_socket_addr_ext::<SocketAddr>(&self.addr, "quic", self.ip_version)
|
||||
.await?;
|
||||
let local_addr = if addr.is_ipv4() {
|
||||
"0.0.0.0:0"
|
||||
} else {
|
||||
|
||||
@@ -230,12 +230,13 @@ fn get_tunnel_for_server(conn: Arc<Connection>) -> impl Tunnel {
|
||||
}
|
||||
|
||||
impl RingTunnelListener {
|
||||
fn get_addr(&self) -> Result<uuid::Uuid, TunnelError> {
|
||||
async fn get_addr(&self) -> Result<uuid::Uuid, TunnelError> {
|
||||
check_scheme_and_get_socket_addr::<Uuid>(
|
||||
&self.listerner_addr,
|
||||
"ring",
|
||||
super::IpVersion::Both,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,13 +247,13 @@ impl TunnelListener for RingTunnelListener {
|
||||
CONNECTION_MAP
|
||||
.lock()
|
||||
.await
|
||||
.insert(self.get_addr()?, self.conn_sender.clone());
|
||||
.insert(self.get_addr().await?, self.conn_sender.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn accept(&mut self) -> Result<Box<dyn Tunnel>, TunnelError> {
|
||||
tracing::info!("waiting accept new conn of key: {}", self.listerner_addr);
|
||||
let my_addr = self.get_addr()?;
|
||||
let my_addr = self.get_addr().await?;
|
||||
if let Some(conn) = self.conn_receiver.recv().await {
|
||||
if conn.server.id == my_addr {
|
||||
tracing::info!("accept new conn of key: {}", self.listerner_addr);
|
||||
@@ -292,7 +293,8 @@ impl TunnelConnector for RingTunnelConnector {
|
||||
&self.remote_addr,
|
||||
"ring",
|
||||
super::IpVersion::Both,
|
||||
)?;
|
||||
)
|
||||
.await?;
|
||||
let entry = CONNECTION_MAP
|
||||
.lock()
|
||||
.await
|
||||
|
||||
@@ -59,7 +59,8 @@ impl TunnelListener for TcpTunnelListener {
|
||||
async fn listen(&mut self) -> Result<(), TunnelError> {
|
||||
self.listener = None;
|
||||
let addr =
|
||||
check_scheme_and_get_socket_addr::<SocketAddr>(&self.addr, "tcp", IpVersion::Both)?;
|
||||
check_scheme_and_get_socket_addr::<SocketAddr>(&self.addr, "tcp", IpVersion::Both)
|
||||
.await?;
|
||||
|
||||
let socket2_socket = socket2::Socket::new(
|
||||
socket2::Domain::for_address(addr),
|
||||
@@ -190,7 +191,8 @@ impl TcpTunnelConnector {
|
||||
impl super::TunnelConnector for TcpTunnelConnector {
|
||||
async fn connect(&mut self) -> Result<Box<dyn Tunnel>, super::TunnelError> {
|
||||
let addr =
|
||||
check_scheme_and_get_socket_addr_ext::<SocketAddr>(&self.addr, "tcp", self.ip_version)?;
|
||||
check_scheme_and_get_socket_addr_ext::<SocketAddr>(&self.addr, "tcp", self.ip_version)
|
||||
.await?;
|
||||
if self.bind_addrs.is_empty() {
|
||||
self.connect_with_default_bind(addr).await
|
||||
} else {
|
||||
|
||||
@@ -477,7 +477,8 @@ impl TunnelListener for UdpTunnelListener {
|
||||
&self.addr,
|
||||
"udp",
|
||||
IpVersion::Both,
|
||||
)?;
|
||||
)
|
||||
.await?;
|
||||
|
||||
let socket2_socket = socket2::Socket::new(
|
||||
socket2::Domain::for_address(addr),
|
||||
@@ -781,7 +782,8 @@ impl super::TunnelConnector for UdpTunnelConnector {
|
||||
&self.addr,
|
||||
"udp",
|
||||
self.ip_version,
|
||||
)?;
|
||||
)
|
||||
.await?;
|
||||
if self.bind_addrs.is_empty() || addr.is_ipv6() {
|
||||
self.connect_with_default_bind(addr).await
|
||||
} else {
|
||||
@@ -963,6 +965,7 @@ mod tests {
|
||||
"udp",
|
||||
IpVersion::Both,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let socket2_socket = socket2::Socket::new(
|
||||
socket2::Domain::for_address(addr),
|
||||
|
||||
@@ -121,7 +121,7 @@ impl WSTunnelListener {
|
||||
#[async_trait::async_trait]
|
||||
impl TunnelListener for WSTunnelListener {
|
||||
async fn listen(&mut self) -> Result<(), TunnelError> {
|
||||
let addr = SocketAddr::from_url(self.addr.clone(), IpVersion::Both)?;
|
||||
let addr = SocketAddr::from_url(self.addr.clone(), IpVersion::Both).await?;
|
||||
let socket2_socket = socket2::Socket::new(
|
||||
socket2::Domain::for_address(addr),
|
||||
socket2::Type::STREAM,
|
||||
@@ -182,7 +182,7 @@ impl WSTunnelConnector {
|
||||
tcp_socket: TcpSocket,
|
||||
) -> Result<Box<dyn Tunnel>, TunnelError> {
|
||||
let is_wss = is_wss(&addr)?;
|
||||
let socket_addr = SocketAddr::from_url(addr.clone(), ip_version)?;
|
||||
let socket_addr = SocketAddr::from_url(addr.clone(), ip_version).await?;
|
||||
let domain = addr.domain();
|
||||
let host = socket_addr.ip();
|
||||
let stream = tcp_socket.connect(socket_addr).await?;
|
||||
@@ -205,12 +205,8 @@ impl WSTunnelConnector {
|
||||
let tls_conn =
|
||||
tokio_rustls::TlsConnector::from(Arc::new(get_insecure_tls_client_config()));
|
||||
let domain_or_ip = match domain {
|
||||
None => {
|
||||
host.to_string()
|
||||
}
|
||||
Some(domain) => {
|
||||
domain.to_string()
|
||||
}
|
||||
None => host.to_string(),
|
||||
Some(domain) => domain.to_string(),
|
||||
};
|
||||
let stream = tls_conn
|
||||
.connect(domain_or_ip.try_into().unwrap(), stream)
|
||||
@@ -274,7 +270,7 @@ impl WSTunnelConnector {
|
||||
#[async_trait::async_trait]
|
||||
impl TunnelConnector for WSTunnelConnector {
|
||||
async fn connect(&mut self) -> Result<Box<dyn Tunnel>, super::TunnelError> {
|
||||
let addr = SocketAddr::from_url(self.addr.clone(), self.ip_version)?;
|
||||
let addr = SocketAddr::from_url(self.addr.clone(), self.ip_version).await?;
|
||||
if self.bind_addrs.is_empty() || addr.is_ipv6() {
|
||||
self.connect_with_default_bind(addr).await
|
||||
} else {
|
||||
|
||||
@@ -548,7 +548,8 @@ impl WgTunnelListener {
|
||||
impl TunnelListener for WgTunnelListener {
|
||||
async fn listen(&mut self) -> Result<(), super::TunnelError> {
|
||||
let addr =
|
||||
check_scheme_and_get_socket_addr::<SocketAddr>(&self.addr, "wg", IpVersion::Both)?;
|
||||
check_scheme_and_get_socket_addr::<SocketAddr>(&self.addr, "wg", IpVersion::Both)
|
||||
.await?;
|
||||
let socket2_socket = socket2::Socket::new(
|
||||
socket2::Domain::for_address(addr),
|
||||
socket2::Type::DGRAM,
|
||||
@@ -705,7 +706,8 @@ impl super::TunnelConnector for WgTunnelConnector {
|
||||
&self.addr,
|
||||
"wg",
|
||||
self.ip_version,
|
||||
)?;
|
||||
)
|
||||
.await?;
|
||||
|
||||
if addr.is_ipv6() {
|
||||
return self.connect_with_ipv6(addr).await;
|
||||
|
||||
Reference in New Issue
Block a user