diff --git a/easytier/src/gateway/kcp_proxy.rs b/easytier/src/gateway/kcp_proxy.rs index a9ee61bb..37ddbab7 100644 --- a/easytier/src/gateway/kcp_proxy.rs +++ b/easytier/src/gateway/kcp_proxy.rs @@ -13,7 +13,6 @@ use kcp_sys::{ packet_def::KcpPacket, stream::KcpStream, }; -use pnet::packet::ipv4::Ipv4Packet; use prost::Message; use tokio::{select, task::JoinSet}; @@ -191,7 +190,7 @@ impl NatDstConnector for NatDstKcpConnector { _cidr_set: &CidrSet, _global_ctx: &GlobalCtx, hdr: &PeerManagerHeader, - _ipv4: &Ipv4Packet, + _ipv4: &Ipv4Addr, _real_dst_ip: &mut Ipv4Addr, ) -> bool { hdr.from_peer_id == hdr.to_peer_id && hdr.is_kcp_src_modified() @@ -213,8 +212,8 @@ impl TcpProxyForWrappedSrcTrait for TcpProxyForKcpSrc { &self.0 } - fn set_src_modified(hdr: &mut PeerManagerHeader, modified: bool) -> &mut PeerManagerHeader { - hdr.set_kcp_src_modified(modified) + fn mark_src_modified(hdr: &mut PeerManagerHeader) -> &mut PeerManagerHeader { + hdr.mark_kcp_src_modified() } async fn check_dst_allow_wrapped_input(&self, dst_ip: &Ipv4Addr) -> bool { diff --git a/easytier/src/gateway/quic_proxy.rs b/easytier/src/gateway/quic_proxy.rs index 45dddd18..12593ef8 100644 --- a/easytier/src/gateway/quic_proxy.rs +++ b/easytier/src/gateway/quic_proxy.rs @@ -24,7 +24,6 @@ use bytes::{BufMut, Bytes, BytesMut}; use dashmap::DashMap; use derivative::Derivative; use derive_more::{Constructor, Deref, DerefMut, From, Into}; -use pnet::packet::ipv4::Ipv4Packet; use prost::Message; use quinn::udp::{EcnCodepoint, RecvMeta, Transmit}; use quinn::{AsyncUdpSocket, Endpoint, RecvStream, SendStream, StreamId, TokioRuntime, UdpPoller}; @@ -376,7 +375,7 @@ impl NatDstConnector for NatDstQuicConnector { _cidr_set: &CidrSet, _global_ctx: &GlobalCtx, hdr: &PeerManagerHeader, - _ipv4: &Ipv4Packet, + _ipv4: &Ipv4Addr, _real_dst_ip: &mut Ipv4Addr, ) -> bool { hdr.from_peer_id == hdr.to_peer_id && hdr.is_quic_src_modified() @@ -401,8 +400,8 @@ impl TcpProxyForWrappedSrcTrait for TcpProxyForQuicSrc { } #[inline] - fn set_src_modified(hdr: &mut PeerManagerHeader, modified: bool) -> &mut PeerManagerHeader { - hdr.set_quic_src_modified(modified) + fn mark_src_modified(hdr: &mut PeerManagerHeader) -> &mut PeerManagerHeader { + hdr.mark_quic_src_modified() } #[inline] diff --git a/easytier/src/gateway/tcp_proxy.rs b/easytier/src/gateway/tcp_proxy.rs index 877a2a0b..aed77620 100644 --- a/easytier/src/gateway/tcp_proxy.rs +++ b/easytier/src/gateway/tcp_proxy.rs @@ -51,7 +51,7 @@ pub(crate) trait NatDstConnector: Send + Sync + Clone + 'static { cidr_set: &CidrSet, global_ctx: &GlobalCtx, hdr: &PeerManagerHeader, - ipv4: &Ipv4Packet, + ipv4: &Ipv4Addr, real_dst_ip: &mut Ipv4Addr, ) -> bool; fn transport_type(&self) -> TcpProxyEntryTransportType; @@ -90,16 +90,15 @@ impl NatDstConnector for NatDstTcpConnector { cidr_set: &CidrSet, global_ctx: &GlobalCtx, hdr: &PeerManagerHeader, - ipv4: &Ipv4Packet, + ipv4: &Ipv4Addr, real_dst_ip: &mut Ipv4Addr, ) -> bool { let is_exit_node = hdr.is_exit_node(); - if !(cidr_set.contains_v4(ipv4.get_destination(), real_dst_ip) + if !(cidr_set.contains_v4(*ipv4, real_dst_ip) || is_exit_node || global_ctx.no_tun() - && Some(ipv4.get_destination()) - == global_ctx.get_ipv4().as_ref().map(Ipv4Inet::address)) + && Some(*ipv4) == global_ctx.get_ipv4().as_ref().map(Ipv4Inet::address)) { return false; } @@ -885,33 +884,47 @@ impl TcpProxy { let ipv4_inet = self.get_local_inet()?; let ipv4_addr = ipv4_inet.address(); - let hdr = packet.peer_manager_header().unwrap().clone(); - - if hdr.packet_type != PacketType::Data as u8 || hdr.is_no_proxy() { - return None; - }; - - let payload_bytes = packet.mut_payload(); - - let ipv4 = Ipv4Packet::new(payload_bytes)?; - if ipv4.get_version() != 4 || ipv4.get_next_level_protocol() != IpNextHeaderProtocols::Tcp { - return None; + { + let hdr = packet.peer_manager_header().unwrap(); + if (hdr.packet_type != PacketType::Data as u8 + && hdr.packet_type != PacketType::DataWithKcpSrcModified as u8 + && hdr.packet_type != PacketType::DataWithQuicSrcModified as u8) + || hdr.is_no_proxy() + { + return None; + }; } - let mut real_dst_ip = ipv4.get_destination(); + let origin_ip = { + let payload_bytes = packet.mut_payload(); + let ipv4 = Ipv4Packet::new(payload_bytes)?; + if ipv4.get_version() != 4 + || ipv4.get_next_level_protocol() != IpNextHeaderProtocols::Tcp + { + return None; + } + + ipv4.get_destination() + }; + let mut real_dst_ip = origin_ip; + let hdr = packet.mut_peer_manager_header().unwrap(); if !self.connector.check_packet_from_peer( &self.cidr_set, &self.global_ctx, - &hdr, - &ipv4, + hdr, + &origin_ip, &mut real_dst_ip, ) { return None; } - tracing::trace!(ipv4 = ?ipv4, cidr_set = ?self.cidr_set, "proxy tcp packet received"); + // restore to data packet + hdr.packet_type = PacketType::Data as u8; + tracing::trace!(ipv4 = ?origin_ip, cidr_set = ?self.cidr_set, "proxy tcp packet received"); + + let payload_bytes = packet.mut_payload(); let ip_packet = Ipv4Packet::new(payload_bytes).unwrap(); let tcp_packet = TcpPacket::new(ip_packet.payload()).unwrap(); diff --git a/easytier/src/gateway/wrapped_proxy.rs b/easytier/src/gateway/wrapped_proxy.rs index 87d28b43..64eeddc7 100644 --- a/easytier/src/gateway/wrapped_proxy.rs +++ b/easytier/src/gateway/wrapped_proxy.rs @@ -12,7 +12,7 @@ use pnet::packet::{ use tokio::io::{copy_bidirectional, AsyncRead, AsyncWrite}; use tokio_util::io::InspectReader; -use crate::tunnel::packet_def::PeerManagerHeader; +use crate::tunnel::packet_def::{PacketType, PeerManagerHeader}; use crate::{ common::{acl_processor::PacketInfo, error::Result}, gateway::tcp_proxy::{NatDstConnector, TcpProxy}, @@ -69,7 +69,7 @@ impl ProxyAclHandler { pub(crate) trait TcpProxyForWrappedSrcTrait: Send + Sync + 'static { type Connector: NatDstConnector; fn get_tcp_proxy(&self) -> &Arc>; - fn set_src_modified(hdr: &mut PeerManagerHeader, modified: bool) -> &mut PeerManagerHeader; + fn mark_src_modified(hdr: &mut PeerManagerHeader) -> &mut PeerManagerHeader; async fn check_dst_allow_wrapped_input(&self, dst_ip: &Ipv4Addr) -> bool; } @@ -84,6 +84,12 @@ impl> NicPacket return true; } + let hdr = zc_packet.mut_peer_manager_header().unwrap(); + if hdr.packet_type != PacketType::Data as u8 { + // already handled by other proxy + return false; + } + let data = zc_packet.payload(); let ip_packet = Ipv4Packet::new(data).unwrap(); if ip_packet.get_version() != 4 @@ -141,7 +147,7 @@ impl> NicPacket let hdr = zc_packet.mut_peer_manager_header().unwrap(); hdr.to_peer_id = self.get_tcp_proxy().get_my_peer_id().into(); - Self::set_src_modified(hdr, true); + Self::mark_src_modified(hdr); true } } diff --git a/easytier/src/tunnel/packet_def.rs b/easytier/src/tunnel/packet_def.rs index ed4f84fe..101ef1d7 100644 --- a/easytier/src/tunnel/packet_def.rs +++ b/easytier/src/tunnel/packet_def.rs @@ -77,6 +77,10 @@ pub enum PacketType { NoiseHandshakeMsg1 = 13, NoiseHandshakeMsg2 = 14, NoiseHandshakeMsg3 = 15, + + // used internally, + DataWithKcpSrcModified = 18, + DataWithQuicSrcModified = 19, } bitflags::bitflags! { @@ -86,8 +90,9 @@ bitflags::bitflags! { const EXIT_NODE = 0b0000_0100; const NO_PROXY = 0b0000_1000; const COMPRESSED = 0b0001_0000; - const KCP_SRC_MODIFIED = 0b0010_0000; - const QUIC_SRC_MODIFIED = 0b1000_0000; + // deprecated flags, can be reused. + // const KCP_SRC_MODIFIED = 0b0010_0000; + // const QUIC_SRC_MODIFIED = 0b1000_0000; const NOT_SEND_TO_TUN = 0b0100_0000; const _ = !0; @@ -192,38 +197,24 @@ impl PeerManagerHeader { self } - pub fn set_kcp_src_modified(&mut self, modified: bool) -> &mut Self { - let mut flags = PeerManagerHeaderFlags::from_bits(self.flags).unwrap(); - if modified { - flags.insert(PeerManagerHeaderFlags::KCP_SRC_MODIFIED); - } else { - flags.remove(PeerManagerHeaderFlags::KCP_SRC_MODIFIED); - } - self.flags = flags.bits(); + pub fn mark_kcp_src_modified(&mut self) -> &mut Self { + assert_eq!(self.packet_type, PacketType::Data as u8); + self.packet_type = PacketType::DataWithKcpSrcModified as u8; self } pub fn is_kcp_src_modified(&self) -> bool { - PeerManagerHeaderFlags::from_bits(self.flags) - .unwrap() - .contains(PeerManagerHeaderFlags::KCP_SRC_MODIFIED) + self.packet_type == PacketType::DataWithKcpSrcModified as u8 } - pub fn set_quic_src_modified(&mut self, modified: bool) -> &mut Self { - let mut flags = PeerManagerHeaderFlags::from_bits(self.flags).unwrap(); - if modified { - flags.insert(PeerManagerHeaderFlags::QUIC_SRC_MODIFIED); - } else { - flags.remove(PeerManagerHeaderFlags::QUIC_SRC_MODIFIED); - } - self.flags = flags.bits(); + pub fn mark_quic_src_modified(&mut self) -> &mut Self { + assert_eq!(self.packet_type, PacketType::Data as u8); + self.packet_type = PacketType::DataWithQuicSrcModified as u8; self } pub fn is_quic_src_modified(&self) -> bool { - PeerManagerHeaderFlags::from_bits(self.flags) - .unwrap() - .contains(PeerManagerHeaderFlags::QUIC_SRC_MODIFIED) + self.packet_type == PacketType::DataWithQuicSrcModified as u8 } pub fn set_not_send_to_tun(&mut self, not_send_to_tun: bool) -> &mut Self {