避免打洞环路

This commit is contained in:
lbl8603
2024-04-24 23:04:01 +08:00
parent 18eb4af016
commit 7dc4161f2f
2 changed files with 36 additions and 6 deletions
+18 -1
View File
@@ -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<Vec<u8>>)>,
external_route: ExternalRoute,
}
impl Punch {
@@ -193,6 +195,7 @@ impl Punch {
punch_model: PunchModel,
is_tcp: bool,
tcp_socket_sender: AcceptSocketSender<(TcpStream, SocketAddr, Option<Vec<u8>>)>,
external_route: ExternalRoute,
) -> Self {
let mut port_vec: Vec<u16> = (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);
}
}
+18 -5
View File
@@ -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<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
nat_test: NatTest,
route: AllowExternalRoute,
external_route: ExternalRoute,
#[cfg(feature = "ip_proxy")]
ip_proxy_map: Option<IpProxyMap>,
}
@@ -50,6 +51,7 @@ impl ClientPacketHandler {
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
nat_test: NatTest,
route: AllowExternalRoute,
external_route: ExternalRoute,
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
) -> 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);