diff --git a/easytier/src/gateway/kcp_proxy.rs b/easytier/src/gateway/kcp_proxy.rs index d3ec032..2623044 100644 --- a/easytier/src/gateway/kcp_proxy.rs +++ b/easytier/src/gateway/kcp_proxy.rs @@ -12,7 +12,12 @@ use kcp_sys::{ packet_def::KcpPacket, stream::KcpStream, }; -use pnet::packet::{ip::IpNextHeaderProtocols, ipv4::Ipv4Packet}; +use pnet::packet::{ + ip::IpNextHeaderProtocols, + ipv4::Ipv4Packet, + tcp::{TcpFlags, TcpPacket}, + Packet as _, +}; use prost::Message; use tokio::{io::copy_bidirectional, task::JoinSet}; @@ -138,7 +143,6 @@ impl NatDstConnector for NatDstKcpConnector { } fn check_packet_from_peer_fast(&self, _cidr_set: &CidrSet, _global_ctx: &GlobalCtx) -> bool { - // if kcp is turned off, the filter will not be added to the pipeline true } @@ -146,10 +150,11 @@ impl NatDstConnector for NatDstKcpConnector { &self, _cidr_set: &CidrSet, _global_ctx: &GlobalCtx, - _hdr: &PeerManagerHeader, + hdr: &PeerManagerHeader, _ipv4: &Ipv4Packet, ) -> bool { - true + // TODO: how to support net to net kcp proxy? + return hdr.from_peer_id == hdr.to_peer_id; } } @@ -201,6 +206,19 @@ impl NicPacketFilter for TcpProxyForKcpSrc { return false; } + // if no connection is established, only allow SYN packet + let tcp_packet = TcpPacket::new(ip_packet.payload()).unwrap(); + let is_syn = tcp_packet.get_flags() & TcpFlags::SYN != 0 + && tcp_packet.get_flags() & TcpFlags::ACK == 0; + if !is_syn + && !self.0.is_tcp_proxy_connection(SocketAddr::new( + IpAddr::V4(my_ipv4.address()), + tcp_packet.get_source(), + )) + { + return false; + } + zc_packet.mut_peer_manager_header().unwrap().to_peer_id = self.0.get_my_peer_id().into(); true diff --git a/easytier/src/gateway/tcp_proxy.rs b/easytier/src/gateway/tcp_proxy.rs index a95fc89..04c188d 100644 --- a/easytier/src/gateway/tcp_proxy.rs +++ b/easytier/src/gateway/tcp_proxy.rs @@ -795,4 +795,8 @@ impl TcpProxy { pub fn get_peer_manager(&self) -> &Arc { &self.peer_manager } + + pub fn is_tcp_proxy_connection(&self, src: SocketAddr) -> bool { + self.syn_map.contains_key(&src) || self.addr_conn_map.contains_key(&src) + } } diff --git a/easytier/src/instance/instance.rs b/easytier/src/instance/instance.rs index 04ba5d7..c437403 100644 --- a/easytier/src/instance/instance.rs +++ b/easytier/src/instance/instance.rs @@ -382,13 +382,6 @@ impl Instance { self.run_rpc_server().await?; - // run after tun device created, so listener can bind to tun device, which may be required by win 10 - self.ip_proxy = Some(IpProxy::new( - self.get_global_ctx(), - self.get_peer_manager(), - )?); - self.run_ip_proxy().await?; - if self.global_ctx.get_flags().enable_kcp_proxy { let src_proxy = KcpProxySrc::new(self.get_peer_manager()).await; src_proxy.start().await; @@ -401,6 +394,13 @@ impl Instance { self.kcp_proxy_dst = Some(dst_proxy); } + // run after tun device created, so listener can bind to tun device, which may be required by win 10 + self.ip_proxy = Some(IpProxy::new( + self.get_global_ctx(), + self.get_peer_manager(), + )?); + self.run_ip_proxy().await?; + self.udp_hole_puncher.lock().await.run().await?; self.peer_center.init().await; diff --git a/easytier/src/tests/three_node.rs b/easytier/src/tests/three_node.rs index e70b957..ea9041a 100644 --- a/easytier/src/tests/three_node.rs +++ b/easytier/src/tests/three_node.rs @@ -366,6 +366,7 @@ pub async fn subnet_proxy_three_node_test( #[values(true, false)] relay_by_public_server: bool, #[values(true, false)] enable_kcp_proxy: bool, #[values(true, false)] disable_kcp_input: bool, + #[values(true, false)] dst_enable_kcp_proxy: bool, ) { let insts = init_three_node_ex( proto, @@ -374,6 +375,7 @@ pub async fn subnet_proxy_three_node_test( let mut flags = cfg.get_flags(); flags.no_tun = no_tun; flags.disable_kcp_input = disable_kcp_input; + flags.enable_kcp_proxy = dst_enable_kcp_proxy; cfg.set_flags(flags); cfg.add_proxy_cidr("10.1.2.0/24".parse().unwrap()); }