diff --git a/vnt/src/channel/punch.rs b/vnt/src/channel/punch.rs index 6342265..ee3de88 100644 --- a/vnt/src/channel/punch.rs +++ b/vnt/src/channel/punch.rs @@ -1,5 +1,5 @@ use std::collections::HashMap; -use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; use std::str::FromStr; use std::time::Duration; use std::{io, thread}; @@ -10,6 +10,7 @@ use rand::Rng; use crate::channel::context::Context; use crate::channel::sender::AcceptSocketSender; +use crate::external_route::ExternalRoute; #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum PunchModel { @@ -185,6 +186,7 @@ pub struct Punch { punch_model: PunchModel, is_tcp: bool, tcp_socket_sender: AcceptSocketSender<(TcpStream, SocketAddr, Option>)>, + external_route: ExternalRoute, } impl Punch { @@ -193,6 +195,7 @@ impl Punch { punch_model: PunchModel, is_tcp: bool, tcp_socket_sender: AcceptSocketSender<(TcpStream, SocketAddr, Option>)>, + external_route: ExternalRoute, ) -> Self { let mut port_vec: Vec = (1..65535).collect(); port_vec.push(65535); @@ -205,12 +208,20 @@ impl Punch { punch_model, is_tcp, tcp_socket_sender, + external_route, } } } impl Punch { fn connect_tcp(&self, buf: &[u8], addr: SocketAddr) -> bool { + if let IpAddr::V4(ip) = addr.ip() { + if self.external_route.route(&ip).is_some() { + log::warn!("跳过打洞目标{},防止环路 ", addr); + return false; + } + } + // mio是非阻塞的,不能立马判断是否能连接成功,所以用标准库的tcp match std::net::TcpStream::connect_timeout(&addr, Duration::from_millis(100)) { Ok(tcp_stream) => { @@ -263,6 +274,12 @@ impl Punch { let channel_num = self.context.channel_num(); for index in 0..channel_num { if let Some(ipv4_addr) = nat_info.local_udp_ipv4addr(index) { + if let IpAddr::V4(ip) = ipv4_addr.ip() { + if self.external_route.route(&ip).is_some() { + log::warn!("跳过打洞目标{},防止环路", ipv4_addr); + continue; + } + } let _ = self.context.send_main_udp(index, buf, ipv4_addr); } } diff --git a/vnt/src/handle/recv_data/client.rs b/vnt/src/handle/recv_data/client.rs index 06e09b7..8753da0 100644 --- a/vnt/src/handle/recv_data/client.rs +++ b/vnt/src/handle/recv_data/client.rs @@ -2,7 +2,7 @@ use parking_lot::RwLock; use protobuf::Message; use std::collections::HashMap; use std::io; -use std::net::{Ipv4Addr, Ipv6Addr}; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::sync::Arc; use packet::icmp::{icmp, Kind}; @@ -13,7 +13,7 @@ use crate::channel::context::Context; use crate::channel::punch::NatInfo; use crate::channel::{Route, RouteKey}; use crate::cipher::Cipher; -use crate::external_route::AllowExternalRoute; +use crate::external_route::{AllowExternalRoute, ExternalRoute}; use crate::handle::maintain::PunchSender; use crate::handle::recv_data::PacketHandler; use crate::handle::CurrentDeviceInfo; @@ -24,7 +24,7 @@ use crate::proto::message::{PunchInfo, PunchNatType}; use crate::protocol::body::ENCRYPTION_RESERVED; use crate::protocol::control_packet::ControlPacket; use crate::protocol::{ - control_packet, ip_turn_packet, other_turn_packet, NetPacket, Protocol, Version, MAX_TTL, + control_packet, ip_turn_packet, other_turn_packet, NetPacket, Protocol, MAX_TTL, }; use crate::tun_tap_device::tun_create_helper::DeviceAdapter; #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] @@ -38,6 +38,7 @@ pub struct ClientPacketHandler { peer_nat_info_map: Arc>>, nat_test: NatTest, route: AllowExternalRoute, + external_route: ExternalRoute, #[cfg(feature = "ip_proxy")] ip_proxy_map: Option, } @@ -50,6 +51,7 @@ impl ClientPacketHandler { peer_nat_info_map: Arc>>, nat_test: NatTest, route: AllowExternalRoute, + external_route: ExternalRoute, #[cfg(feature = "ip_proxy")] ip_proxy_map: Option, ) -> Self { Self { @@ -59,6 +61,7 @@ impl ClientPacketHandler { peer_nat_info_map, nat_test, route, + external_route, #[cfg(feature = "ip_proxy")] ip_proxy_map, } @@ -73,6 +76,16 @@ impl PacketHandler for ClientPacketHandler { context: &Context, current_device: &CurrentDeviceInfo, ) -> io::Result<()> { + let ip = match route_key.addr.ip() { + IpAddr::V4(ip) => Some(ip), + IpAddr::V6(ip) => ip.to_ipv4_mapped(), + }; + if let Some(ip) = ip { + if self.external_route.route(&ip).is_some() { + log::warn!("跳过in路由中的目标 {:?},防止环路 ", route_key); + return Ok(()); + } + } self.client_cipher.decrypt_ipv4(&mut net_packet)?; context .route_table @@ -213,7 +226,7 @@ impl ClientPacketHandler { ControlPacket::AddrRequest => match route_key.addr.ip() { std::net::IpAddr::V4(ipv4) => { let mut packet = NetPacket::new_encrypt([0; 12 + 6 + ENCRYPTION_RESERVED])?; - packet.set_version(Version::V1); + packet.set_default_version(); packet.set_protocol(Protocol::Control); packet.set_transport_protocol(control_packet::Protocol::AddrResponse.into()); packet.first_set_ttl(MAX_TTL); @@ -312,7 +325,7 @@ impl ClientPacketHandler { })?; let mut punch_packet = NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?; - punch_packet.set_version(Version::V1); + punch_packet.set_default_version(); punch_packet.set_protocol(Protocol::OtherTurn); punch_packet.set_transport_protocol(other_turn_packet::Protocol::Punch.into()); punch_packet.first_set_ttl(MAX_TTL);