mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-07 02:09:06 +00:00
fix peer establish direct conn with subnet proxy to one of local interface (#1782)
* fix peer establish direct conn with subnet proxy to one of local interface * fix peer mgr ref loop
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::net::IpAddr;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::{
|
||||
hash::Hasher,
|
||||
sync::{Arc, Mutex},
|
||||
@@ -257,6 +257,13 @@ impl GlobalCtx {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_ip_local_virtual_ip(&self, ip: &IpAddr) -> bool {
|
||||
match ip {
|
||||
IpAddr::V4(v4) => self.get_ipv4().map(|x| x.address() == *v4).unwrap_or(false),
|
||||
IpAddr::V6(v6) => self.get_ipv6().map(|x| x.address() == *v6).unwrap_or(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_network_identity(&self) -> NetworkIdentity {
|
||||
self.config.get_network_identity()
|
||||
}
|
||||
@@ -303,18 +310,6 @@ impl GlobalCtx {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_port_in_running_listeners(&self, port: u16, is_udp: bool) -> bool {
|
||||
let check_proto = |listener_proto: &str| {
|
||||
let listener_is_udp = matches!(listener_proto, "udp" | "wg");
|
||||
listener_is_udp == is_udp
|
||||
};
|
||||
self.running_listeners
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.any(|x| x.port() == Some(port) && check_proto(x.scheme()))
|
||||
}
|
||||
|
||||
pub fn get_vpn_portal_cidr(&self) -> Option<cidr::Ipv4Cidr> {
|
||||
self.config.get_vpn_portal_config().map(|x| x.client_cidr)
|
||||
}
|
||||
@@ -447,6 +442,46 @@ impl GlobalCtx {
|
||||
// NOTICE: p2p only is conflict with latency first
|
||||
self.config.get_flags().latency_first && !self.p2p_only
|
||||
}
|
||||
|
||||
fn is_port_in_running_listeners(&self, port: u16, is_udp: bool) -> bool {
|
||||
let check_proto = |listener_proto: &str| {
|
||||
let listener_is_udp = matches!(listener_proto, "udp" | "wg");
|
||||
listener_is_udp == is_udp
|
||||
};
|
||||
self.running_listeners
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.any(|x| x.port() == Some(port) && check_proto(x.scheme()))
|
||||
}
|
||||
|
||||
#[tracing::instrument(ret, skip(self))]
|
||||
pub fn should_deny_proxy(&self, dst_addr: &SocketAddr, is_udp: bool) -> bool {
|
||||
let _g = self.net_ns.guard();
|
||||
let ip = dst_addr.ip();
|
||||
// first check if ip is virtual ip
|
||||
// then try bind this ip, if succ means it is local ip
|
||||
let dst_is_local_virtual_ip = self.is_ip_local_virtual_ip(&ip);
|
||||
// this is an expensive operation, should be called sparingly
|
||||
// 1. tcp/kcp/quic call this only after proxy conn is established
|
||||
// 2. udp cache the result in nat entry
|
||||
let dst_is_local_phy_ip = std::net::UdpSocket::bind(format!("{}:0", ip)).is_ok();
|
||||
|
||||
tracing::trace!(
|
||||
"check should_deny_proxy: dst_addr={}, dst_is_local_virtual_ip={}, dst_is_local_phy_ip={}, is_udp={}",
|
||||
dst_addr,
|
||||
dst_is_local_virtual_ip,
|
||||
dst_is_local_phy_ip,
|
||||
is_udp
|
||||
);
|
||||
|
||||
if dst_is_local_virtual_ip || dst_is_local_phy_ip {
|
||||
// if is local ip, make sure the port is not one of the listening ports
|
||||
self.is_port_in_running_listeners(dst_addr.port(), is_udp)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user