From 8ffc2f12e48f9184e633baa39e0503aa0993a635 Mon Sep 17 00:00:00 2001 From: "Sijie.Sun" Date: Sat, 9 Aug 2025 16:16:09 +0800 Subject: [PATCH] optimize the condition of enabling kcp (#1210) --- EasyTier.code-workspace | 2 ++ easytier/locales/app.yml | 12 +++++++ easytier/src/common/config.rs | 3 +- easytier/src/easytier-core.rs | 24 ++++++++++++-- easytier/src/gateway/kcp_proxy.rs | 10 +----- easytier/src/gateway/socks5.rs | 10 +++++- easytier/src/peers/foreign_network_manager.rs | 4 +++ easytier/src/peers/peer_manager.rs | 32 +++++++++++++++++++ easytier/src/peers/route_trait.rs | 7 ++++ easytier/src/proto/common.proto | 5 ++- easytier/src/tests/three_node.rs | 19 ++++++++--- 11 files changed, 110 insertions(+), 18 deletions(-) diff --git a/EasyTier.code-workspace b/EasyTier.code-workspace index 9e4f1ac..ebe4413 100644 --- a/EasyTier.code-workspace +++ b/EasyTier.code-workspace @@ -44,5 +44,7 @@ "prettier.enable": false, "editor.formatOnSave": true, "editor.formatOnSaveMode": "modifications", + "editor.formatOnPaste": false, + "editor.formatOnType": true, } } \ No newline at end of file diff --git a/easytier/locales/app.yml b/easytier/locales/app.yml index 5f2c17c..d817a8a 100644 --- a/easytier/locales/app.yml +++ b/easytier/locales/app.yml @@ -190,6 +190,18 @@ core_clap: foreign_relay_bps_limit: en: "the maximum bps limit for foreign network relay, default is no limit. unit: BPS (bytes per second)" zh-CN: "作为共享节点时,限制非本地网络的流量转发速率,默认无限制,单位 BPS (字节每秒)" + tcp_whitelist: + en: "tcp port whitelist. Supports single ports (80) and ranges (8000-9000)" + zh-CN: "TCP 端口白名单。支持单个端口(80)和范围(8000-9000)" + udp_whitelist: + en: "udp port whitelist. Supports single ports (53) and ranges (5000-6000)" + zh-CN: "UDP 端口白名单。支持单个端口(53)和范围(5000-6000)" + disable_relay_kcp: + en: "if true, disable relay kcp packets. avoid consuming too many bandwidth. default is false" + zh-CN: "如果为true,则禁止节点转发 KCP 数据包,防止过度消耗流量。默认值为false" + enable_relay_foreign_network_kcp: + en: "if true, allow relay kcp packets from foreign network. default is false (not forward foreign network kcp packets)" + zh-CN: "如果为true,则作为共享节点时也可以转发其他网络的 KCP 数据包。默认值为false(不转发)" core_app: panic_backtrace_save: diff --git a/easytier/src/common/config.rs b/easytier/src/common/config.rs index c607a46..776f64d 100644 --- a/easytier/src/common/config.rs +++ b/easytier/src/common/config.rs @@ -40,7 +40,8 @@ pub fn gen_default_flags() -> Flags { bind_device: true, enable_kcp_proxy: false, disable_kcp_input: false, - disable_relay_kcp: true, + disable_relay_kcp: false, + enable_relay_foreign_network_kcp: false, accept_dns: false, private_mode: false, enable_quic_proxy: false, diff --git a/easytier/src/easytier-core.rs b/easytier/src/easytier-core.rs index 291d4b4..b5d1a79 100644 --- a/easytier/src/easytier-core.rs +++ b/easytier/src/easytier-core.rs @@ -515,7 +515,7 @@ struct NetworkOptions { #[arg( long, value_delimiter = ',', - help = "TCP port whitelist. Supports single ports (80) and ranges (8000-9000)", + help = t!("core_clap.tcp_whitelist").to_string(), num_args = 0.. )] tcp_whitelist: Vec, @@ -523,10 +523,28 @@ struct NetworkOptions { #[arg( long, value_delimiter = ',', - help = "UDP port whitelist. Supports single ports (53) and ranges (5000-6000)", + help = t!("core_clap.udp_whitelist").to_string(), num_args = 0.. )] udp_whitelist: Vec, + + #[arg( + long, + env = "ET_DISABLE_RELAY_KCP", + help = t!("core_clap.disable_relay_kcp").to_string(), + num_args = 0..=1, + default_missing_value = "true" + )] + disable_relay_kcp: Option, + + #[arg( + long, + env = "ET_ENABLE_RELAY_FOREIGN_NETWORK_KCP", + help = t!("core_clap.enable_relay_foreign_network_kcp").to_string(), + num_args = 0..=1, + default_missing_value = "true" + )] + enable_relay_foreign_network_kcp: Option, } #[derive(Parser, Debug)] @@ -875,6 +893,8 @@ impl NetworkOptions { .foreign_relay_bps_limit .unwrap_or(f.foreign_relay_bps_limit); f.multi_thread_count = self.multi_thread_count.unwrap_or(f.multi_thread_count); + f.disable_relay_kcp = self.disable_relay_kcp.unwrap_or(f.disable_relay_kcp); + f.enable_relay_foreign_network_kcp = self.enable_relay_foreign_network_kcp.unwrap_or(f.enable_relay_foreign_network_kcp); cfg.set_flags(f); if !self.exit_nodes.is_empty() { diff --git a/easytier/src/gateway/kcp_proxy.rs b/easytier/src/gateway/kcp_proxy.rs index 866edbb..0dced50 100644 --- a/easytier/src/gateway/kcp_proxy.rs +++ b/easytier/src/gateway/kcp_proxy.rs @@ -230,15 +230,7 @@ impl TcpProxyForKcpSrcTrait for TcpProxyForKcpSrc { } async fn check_dst_allow_kcp_input(&self, dst_ip: &Ipv4Addr) -> bool { - let peer_map: Arc = - self.0.get_peer_manager().get_peer_map(); - let Some(dst_peer_id) = peer_map.get_peer_id_by_ipv4(dst_ip).await else { - return false; - }; - let Some(peer_info) = peer_map.get_route_peer_info(dst_peer_id).await else { - return false; - }; - peer_info.feature_flag.map(|x| x.kcp_input).unwrap_or(false) + self.0.get_peer_manager().check_allow_kcp_to_dst(&IpAddr::V4(*dst_ip)).await } } diff --git a/easytier/src/gateway/socks5.rs b/easytier/src/gateway/socks5.rs index 4ca0f65..7e29862 100644 --- a/easytier/src/gateway/socks5.rs +++ b/easytier/src/gateway/socks5.rs @@ -751,8 +751,16 @@ impl Socks5Server { continue; }; + let Some(peer_mgr_arc) = peer_mgr.upgrade() else { + tracing::error!("peer manager is dropped"); + continue; + }; + + let dst_allow_kcp = peer_mgr_arc.check_allow_kcp_to_dst(&dst_addr.ip()).await; + tracing::debug!("dst_allow_kcp: {:?}", dst_allow_kcp); + let connector: Box + Send> = - if kcp_endpoint.is_none() { + if kcp_endpoint.is_none() || !dst_allow_kcp { Box::new(SmolTcpConnector { net: net.smoltcp_net.clone(), entries: entries.clone(), diff --git a/easytier/src/peers/foreign_network_manager.rs b/easytier/src/peers/foreign_network_manager.rs index d69c08d..ab8be11 100644 --- a/easytier/src/peers/foreign_network_manager.rs +++ b/easytier/src/peers/foreign_network_manager.rs @@ -163,6 +163,10 @@ impl ForeignNetworkEntry { config.set_network_identity(network.clone()); config.set_hostname(Some(format!("PublicServer_{}", global_ctx.get_hostname()))); + let mut flags = config.get_flags(); + flags.disable_relay_kcp = !global_ctx.get_flags().enable_relay_foreign_network_kcp; + config.set_flags(flags); + let foreign_global_ctx = Arc::new(GlobalCtx::new(config)); foreign_global_ctx .replace_stun_info_collector(Box::new(global_ctx.get_stun_info_collector().clone())); diff --git a/easytier/src/peers/peer_manager.rs b/easytier/src/peers/peer_manager.rs index 948eee8..8c3c303 100644 --- a/easytier/src/peers/peer_manager.rs +++ b/easytier/src/peers/peer_manager.rs @@ -1360,6 +1360,38 @@ impl PeerManager { tracing::info!("close_peer_conn in foreign network manager done: {:?}", ret); ret } + + pub async fn check_allow_kcp_to_dst(&self, dst_ip: &IpAddr) -> bool { + let route = self.get_route(); + let Some(dst_peer_id) = route.get_peer_id_by_ip(dst_ip).await else { + return false; + }; + let Some(peer_info) = route.get_peer_info(dst_peer_id).await else { + return false; + }; + + // check dst allow kcp input + if !peer_info.feature_flag.map(|x| x.kcp_input).unwrap_or(false) { + return false; + } + + let next_hop_policy = Self::get_next_hop_policy( self.global_ctx.get_flags().latency_first); + // check relay node allow relay kcp. + let Some(next_hop_id) = route.get_next_hop_with_policy(dst_peer_id, next_hop_policy).await else { + return false; + }; + + let Some(next_hop_info) = route.get_peer_info(next_hop_id).await else { + return false; + }; + + // check next hop allow kcp relay + if next_hop_info.feature_flag.map(|x| x.no_relay_kcp).unwrap_or(false) { + return false; + } + + true + } } #[cfg(test)] diff --git a/easytier/src/peers/route_trait.rs b/easytier/src/peers/route_trait.rs index d18e5ba..83e19a3 100644 --- a/easytier/src/peers/route_trait.rs +++ b/easytier/src/peers/route_trait.rs @@ -86,6 +86,13 @@ pub trait Route { None } + async fn get_peer_id_by_ip(&self, ip: &std::net::IpAddr) -> Option { + match ip { + std::net::IpAddr::V4(v4) => self.get_peer_id_by_ipv4(v4).await, + std::net::IpAddr::V6(v6) => self.get_peer_id_by_ipv6(v6).await, + } + } + async fn list_peers_own_foreign_network( &self, _network_identity: &NetworkIdentity, diff --git a/easytier/src/proto/common.proto b/easytier/src/proto/common.proto index ad9da5b..057bfe1 100644 --- a/easytier/src/proto/common.proto +++ b/easytier/src/proto/common.proto @@ -28,7 +28,7 @@ message FlagsInConfig { bool enable_kcp_proxy = 18; // does this peer allow kcp input bool disable_kcp_input = 19; - // allow relay kcp packets (for public server, this can reduce the throughput) + // disable relay local network kcp packets bool disable_relay_kcp = 20; bool proxy_forward_by_system = 21; @@ -46,6 +46,9 @@ message FlagsInConfig { uint64 foreign_relay_bps_limit = 26; uint32 multi_thread_count = 27; + + // enable relay foreign network kcp packets + bool enable_relay_foreign_network_kcp = 28; } message RpcDescriptor { diff --git a/easytier/src/tests/three_node.rs b/easytier/src/tests/three_node.rs index 30283f8..82ee09b 100644 --- a/easytier/src/tests/three_node.rs +++ b/easytier/src/tests/three_node.rs @@ -1150,6 +1150,8 @@ pub async fn port_forward_test( #[values(true, false)] no_tun: bool, #[values(64, 1900)] buf_size: u64, #[values(true, false)] enable_kcp: bool, + #[values(true, false)] dst_disable_kcp_input: bool, + #[values(true, false)] disable_relay_kcp: bool, ) { prepare_linux_namespaces(); @@ -1183,14 +1185,23 @@ pub async fn port_forward_test( proto: "udp".to_string(), }, ]); + + let mut flags = cfg.get_flags(); + flags.no_tun = no_tun; + flags.enable_kcp_proxy = enable_kcp; + cfg.set_flags(flags); } else if cfg.get_inst_name() == "inst3" { cfg.add_proxy_cidr("10.1.2.0/24".parse().unwrap(), None) .unwrap(); + let mut flags = cfg.get_flags(); + flags.disable_kcp_input = dst_disable_kcp_input; + cfg.set_flags(flags); + } else if cfg.get_inst_name() == "inst2" { + let mut flags = cfg.get_flags(); + flags.disable_relay_kcp = disable_relay_kcp; + cfg.set_flags(flags); } - let mut flags = cfg.get_flags(); - flags.no_tun = no_tun; - flags.enable_kcp_proxy = enable_kcp; - cfg.set_flags(flags); + cfg }, false,