diff --git a/README.md b/README.md index 6a5ac05..0e1f34a 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ A virtual network tool (VPN) ### Todo - 桌面UI(测试中) -- 支持Ipv6 +- 支持Ipv6(1.2.2已支持客户端之间的ipv6,待支持客户端和服务端之间的ipv6通信) ### 常见问题
展开 diff --git a/vnt-cli/README.md b/vnt-cli/README.md index 77b79fc..8db37fd 100644 --- a/vnt-cli/README.md +++ b/vnt-cli/README.md @@ -62,6 +62,8 @@ | `>=`8 | aes_gcm | AES256-GCM | | 1~8位 | aes_cbc | AES128-CBC | | `>=`8 | aes_cbc | AES256-CBC | +### --finger +开启数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启,开启会损耗一部分性能 ### --relay 禁用p2p,在网络环境很差时,只使用服务器中转效果可能更好(可以配合--tcp参数一起使用) diff --git a/vnt-cli/src/command/entity.rs b/vnt-cli/src/command/entity.rs index 2e6e555..39ae7cf 100644 --- a/vnt-cli/src/command/entity.rs +++ b/vnt-cli/src/command/entity.rs @@ -9,7 +9,8 @@ pub struct Info { pub relay_server: String, pub nat_type: String, pub public_ips: String, - pub local_ip: String, + pub local_addr: String, + pub ipv6_addr: String, } #[derive(Serialize, Deserialize, Debug)] diff --git a/vnt-cli/src/command/mod.rs b/vnt-cli/src/command/mod.rs index db659f6..ee5b601 100644 --- a/vnt-cli/src/command/mod.rs +++ b/vnt-cli/src/command/mod.rs @@ -83,7 +83,7 @@ pub fn command_list(vnt: &Vnt) -> Vec { let nat_type = format!("{:?}", nat_info.nat_type); let public_ips: Vec = nat_info.public_ips.iter().map(|v| v.to_string()).collect(); let public_ips = public_ips.join(","); - let local_ip = nat_info.local_ip.to_string(); + let local_ip = nat_info.local_ipv4_addr.ip().to_string(); (nat_type, public_ips, local_ip) } else { ("".to_string(), "".to_string(), "".to_string()) @@ -136,7 +136,12 @@ pub fn command_info(vnt: &Vnt) -> Info { let nat_type = format!("{:?}", nat_info.nat_type); let public_ips: Vec = nat_info.public_ips.iter().map(|v| v.to_string()).collect(); let public_ips = public_ips.join(","); - let local_ip = nat_info.local_ip.to_string(); + let local_addr = nat_info.local_ipv4_addr.to_string(); + let ipv6_addr = if nat_info.ipv6_addr.ip().is_unspecified() { + "None".to_string() + } else { + nat_info.ipv6_addr.ip().to_string() + }; Info { name, virtual_ip, @@ -146,7 +151,8 @@ pub fn command_info(vnt: &Vnt) -> Info { relay_server, nat_type, public_ips, - local_ip, + local_addr, + ipv6_addr, } } diff --git a/vnt-cli/src/console_out/mod.rs b/vnt-cli/src/console_out/mod.rs index 9069aa6..e38fc57 100644 --- a/vnt-cli/src/console_out/mod.rs +++ b/vnt-cli/src/console_out/mod.rs @@ -13,7 +13,8 @@ pub fn console_info(status: Info) { println!("NAT type: {}", style(status.nat_type).green()); println!("Relay server: {}", style(status.relay_server).green()); println!("Public ips: {}", style(status.public_ips).green()); - println!("Local ip: {}", style(status.local_ip).green()); + println!("Local addr: {}", style(status.local_addr).green()); + println!("IPv6: {}", style(status.ipv6_addr).green()); } pub fn console_route_table(mut list: Vec) { diff --git a/vnt/src/channel/channel.rs b/vnt/src/channel/channel.rs index 1eed55d..b4c074f 100644 --- a/vnt/src/channel/channel.rs +++ b/vnt/src/channel/channel.rs @@ -2,28 +2,32 @@ use std::io; use std::net::{Ipv4Addr, SocketAddr}; use std::sync::Arc; use std::time::{Duration, Instant}; + +use byte_pool::{Block, BytePool}; use crossbeam_utils::atomic::AtomicCell; use dashmap::DashMap; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::{TcpStream, UdpSocket}; use tokio::net::tcp::OwnedReadHalf; use tokio::sync::watch::{channel, Receiver, Sender}; + use crate::channel::{Route, RouteKey, Status}; use crate::channel::punch::NatType; use crate::core::status::VntWorker; use crate::handle::CurrentDeviceInfo; use crate::handle::recv_handler::ChannelDataHandler; -use byte_pool::{Block, BytePool}; + lazy_static::lazy_static! { static ref POOL:BytePool = BytePool::new(); } pub struct ContextInner { //udp用于打洞、服务端通信(可选) pub(crate) main_channel: Arc, + pub(crate) main_channel_ipv6: Option>, //在udp的基础上,可以选择使用tcp和服务端通信 pub(crate) main_tcp_channel: Option>>, pub(crate) route_table: DashMap>, - pub(crate) route_table_time: DashMap<(RouteKey, Ipv4Addr), AtomicCell>, + pub(crate) route_table_time: DashMap<(RouteKey, Ipv4Addr), Instant>, pub(crate) status_receiver: Receiver, pub(crate) status_sender: Sender, pub(crate) udp_map: DashMap>, @@ -37,12 +41,13 @@ pub struct Context { } impl Context { - pub fn new(main_channel: Arc, main_tcp_channel: Option>>, current_device: Arc>, _channel_num: usize) -> Self { + pub fn new(main_channel: Arc, main_channel_ipv6: Option>, main_tcp_channel: Option>>, current_device: Arc>, _channel_num: usize) -> Self { //当前版本只支持一个通道 let channel_num = 1; let (status_sender, status_receiver) = channel(Status::Cone); let inner = Arc::new(ContextInner { main_channel, + main_channel_ipv6, main_tcp_channel, route_table: DashMap::with_capacity(16), route_table_time: DashMap::with_capacity(16), @@ -87,11 +92,37 @@ impl Context { pub fn switch_to_symmetric(&self) { let _ = self.inner.status_sender.send(Status::Symmetric); } - pub fn main_local_port(&self) -> io::Result { + pub fn main_local_ipv4_port(&self) -> io::Result { self.inner.main_channel.local_addr().map(|k| k.port()) } + pub fn main_local_ipv6_port(&self) -> io::Result { + if let Some(ipv6) = &self.inner.main_channel_ipv6{ + ipv6.local_addr().map(|k| k.port()) + }else{ + Err(io::Error::new(io::ErrorKind::Other, "not ipv6")) + } + } pub async fn send_main_udp(&self, buf: &[u8], addr: SocketAddr) -> io::Result { - self.inner.main_channel.send_to(buf, addr).await + if addr.is_ipv6() { + if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 { + udp_ipv6.send_to(buf, addr).await + } else { + Err(io::Error::new(io::ErrorKind::Other, "not ipv6")) + } + } else { + self.inner.main_channel.send_to(buf, addr).await + } + } + pub fn try_send_main_udp(&self, buf: &[u8], addr: SocketAddr) -> io::Result { + if addr.is_ipv6() { + if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 { + udp_ipv6.try_send_to(buf, addr) + } else { + Err(io::Error::new(io::ErrorKind::Other, "not ipv6")) + } + } else { + self.inner.main_channel.try_send_to(buf, addr) + } } pub async fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result { if let Some(sender) = &self.inner.main_tcp_channel { @@ -101,7 +132,7 @@ impl Context { Err(io::Error::new(io::ErrorKind::Other, "send_main err")) } } else { - self.inner.main_channel.send_to(buf, addr).await + self.send_main_udp(buf, addr).await } } pub fn try_send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result { @@ -112,7 +143,7 @@ impl Context { Err(io::Error::new(io::ErrorKind::Other, "try_send_main err")) } } else { - self.inner.main_channel.try_send_to(buf, addr) + self.try_send_main_udp(buf, addr) } } @@ -120,7 +151,8 @@ impl Context { for udp_ref in self.inner.udp_map.iter() { let udp = udp_ref.clone(); drop(udp_ref); - udp.send_to(buf, addr).await?; + //使用ipv6的udp发送ipv4报文会出错 + let _ = udp.send_to(buf, addr).await; } Ok(()) } @@ -135,17 +167,12 @@ impl Context { if !route.is_p2p() { if let Some(time) = self.inner.route_table_time.get(&(route.route_key(), *id)) { //借道传输时,长时间不通信的通道不使用 - if time.value().load().elapsed() > Duration::from_secs(6) { + if time.value().elapsed() > Duration::from_secs(6) { return Err(io::Error::new(io::ErrorKind::NotFound, "route time out")); } } } - - if let Some(udp_ref) = self.inner.udp_map.get(&route.index) { - let udp = udp_ref.value().clone(); - drop(udp_ref); - return udp.send_to(buf, route.addr).await; - } + return self.send_by_key(buf,&route.route_key()).await; } Err(io::Error::new(io::ErrorKind::NotFound, "route not found")) } @@ -238,7 +265,7 @@ impl Context { list.truncate(max_len); } } - self.inner.route_table_time.insert((key, id), AtomicCell::new(Instant::now())); + self.inner.route_table_time.insert((key, id), Instant::now()); } pub fn route(&self, id: &Ipv4Addr) -> Option> { if let Some(v) = self.inner.route_table.get(id) { @@ -312,8 +339,8 @@ impl Context { self.inner.route_table_time.remove(&(route_key, *id)); } pub fn update_read_time(&self, id: &Ipv4Addr, route_key: &RouteKey) { - if let Some(time) = self.inner.route_table_time.get(&(*route_key, *id)) { - time.value().store(Instant::now()); + if let Some(mut time) = self.inner.route_table_time.get_mut(&(*route_key, *id)) { + *time.value_mut() = Instant::now(); } } } @@ -465,6 +492,9 @@ impl Channel { if let Some((tcp_stream, receiver)) = tcp { tokio::spawn(Self::start_tcp(worker.worker("main_channel_tcp"), tcp_stream, receiver, context.inner.current_device.clone(), buf_sender.clone().unwrap(), head_reserve)); } + if let Some(main_channel_ipv6) = &context.inner.main_channel_ipv6 { + tokio::spawn(Self::start_(worker.worker("main_channel_ipv6"), context.clone(), main_channel_ipv6.clone(), handler.clone(), buf_sender.clone(), head_reserve, true)); + } tokio::spawn(Self::start_(worker.worker("main_channel_1"), context.clone(), main_channel.clone(), handler.clone(), buf_sender.clone(), head_reserve, true)); if relay { worker.stop_wait().await; diff --git a/vnt/src/channel/idle.rs b/vnt/src/channel/idle.rs index 06c95b7..4d4146a 100644 --- a/vnt/src/channel/idle.rs +++ b/vnt/src/channel/idle.rs @@ -27,7 +27,7 @@ impl Idle { loop { let mut max = Duration::from_secs(0); for entry in self.context.inner.route_table_time.iter() { - let last_read = entry.value().load().elapsed(); + let last_read = entry.value().elapsed(); if last_read >= self.read_idle { return Ok((entry.key().1.clone(), entry.key().0.clone())); } else { diff --git a/vnt/src/channel/punch.rs b/vnt/src/channel/punch.rs index 39592f2..9f4c110 100644 --- a/vnt/src/channel/punch.rs +++ b/vnt/src/channel/punch.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; use std::io; -use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; +use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; use std::time::Duration; use rand::prelude::SliceRandom; @@ -12,8 +12,8 @@ pub struct NatInfo { pub public_ips: Vec, pub public_port: u16, pub public_port_range: u16, - pub local_ip: Ipv4Addr, - pub local_port: u16, + pub local_ipv4_addr: SocketAddrV4, + pub ipv6_addr: SocketAddrV6, pub nat_type: NatType, } @@ -27,8 +27,8 @@ impl NatInfo { pub fn new(mut public_ips: Vec, public_port: u16, public_port_range: u16, - local_ip: Ipv4Addr, - local_port: u16, + local_ipv4_addr: SocketAddrV4, + ipv6_addr: SocketAddrV6, nat_type: NatType, ) -> Self { public_ips.retain(|ip| { !ip.is_loopback() && !ip.is_private() @@ -37,8 +37,8 @@ impl NatInfo { public_ips, public_port, public_port_range, - local_ip, - local_port, + local_ipv4_addr, + ipv6_addr, nat_type, } } @@ -70,8 +70,11 @@ impl Punch { if !self.context.need_punch(&id) { return Ok(()); } - if !nat_info.local_ip.is_unspecified() || nat_info.local_port != 0 { - let _ = self.context.send_main_udp(buf, SocketAddr::V4(SocketAddrV4::new(nat_info.local_ip, nat_info.local_port))).await; + if !nat_info.local_ipv4_addr.ip().is_unspecified() && nat_info.local_ipv4_addr.port() != 0 { + let _ = self.context.send_main_udp(buf, SocketAddr::V4(nat_info.local_ipv4_addr)).await; + } + if !nat_info.ipv6_addr.ip().is_unspecified() && nat_info.ipv6_addr.port() != 0 { + let _ = self.context.send_main_udp(buf, SocketAddr::V6(nat_info.ipv6_addr)).await; } match nat_info.nat_type { NatType::Symmetric => { diff --git a/vnt/src/core/mod.rs b/vnt/src/core/mod.rs index b0ec993..8184ed0 100644 --- a/vnt/src/core/mod.rs +++ b/vnt/src/core/mod.rs @@ -54,6 +54,7 @@ pub struct Vnt { pub struct VntUtil { config: Config, main_channel: UdpSocket, + main_channel_ipv6: Option, main_tcp_channel: Option, response: Option, iface: Option<(DeviceWriter, DeviceReader)>, @@ -64,6 +65,15 @@ pub struct VntUtil { impl VntUtil { pub async fn new(config: Config) -> io::Result { let main_channel = UdpSocket::bind("0.0.0.0:0").await?; + let main_channel_ipv6 = match UdpSocket::bind("[::]:0").await { + Ok(main_channel_ipv6) => { + Some(main_channel_ipv6) + } + Err(e) => { + log::warn!("绑定ipv6地址失败:{}",e); + None + } + }; let server_cipher = if config.server_encrypt { let mut key = [0 as u8; 32]; rand::thread_rng().fill(&mut key); @@ -74,6 +84,7 @@ impl VntUtil { Ok(VntUtil { config, main_channel, + main_channel_ipv6, main_tcp_channel: None, response: None, iface: None, @@ -150,9 +161,9 @@ impl VntUtil { let mtu = match self.config.mtu { None => { if self.config.password.is_none() { - 1430 + 1450 } else { - 1410 + 1420 } } Some(mtu) => { @@ -204,7 +215,9 @@ impl VntUtil { } else { (None, None) }; - let context = Context::new(Arc::new(self.main_channel), tcp_sender, current_device.clone(), 1); + let context = Context::new(Arc::new(self.main_channel), + self.main_channel_ipv6.map(|v| Arc::new(v)), + tcp_sender, current_device.clone(), 1); let punch = Punch::new(context.clone()); let idle = Idle::new(Duration::from_secs(16), context.clone()); let channel_sender = ChannelSender::new(context.clone()); @@ -216,11 +229,14 @@ impl VntUtil { let peer_nat_info_map: Arc> = Arc::new(DashMap::new()); let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected)); + let local_port = context.main_local_ipv4_port().unwrap_or(0); - let local_ip = crate::nat::local_ip()?; - let local_port = context.main_local_port()?; + let local_ipv4_addr = crate::nat::local_ipv4_addr(local_port); + let ipv6_port = context.main_local_ipv6_port().unwrap_or(0); + let ipv6_addr = crate::nat::local_ipv6_addr(ipv6_port); // NAT检测 - let nat_test = NatTest::new(config.stun_server.clone(), response.public_ip, response.public_port, local_ip, local_port).await; + let nat_test = NatTest::new(config.stun_server.clone(), response.public_ip, + response.public_port, local_ipv4_addr, ipv6_addr).await; let in_external_route = if config.in_ips.is_empty() { None } else { diff --git a/vnt/src/handle/heartbeat_handler.rs b/vnt/src/handle/heartbeat_handler.rs index 04c00e1..3934685 100644 --- a/vnt/src/handle/heartbeat_handler.rs +++ b/vnt/src/handle/heartbeat_handler.rs @@ -35,6 +35,7 @@ pub fn start_idle(mut worker: VntWorker, idle: Idle, sender: ChannelSender) { } async fn start_idle_(idle: Idle, sender: ChannelSender) -> io::Result<()> { + log::info!("启动空闲检查任务"); loop { let (peer_ip, route) = idle.next_idle().await?; log::info!( @@ -103,6 +104,7 @@ async fn start_heartbeat_( server_cipher: Cipher, ) -> io::Result<()> { let mut count = 0; + log::info!("启动心跳任务"); loop { if sender.is_close() { return Ok(()); @@ -129,6 +131,7 @@ async fn start_heartbeat_( if addr != current_dev.connect_server { let mut tmp = current_dev.clone(); tmp.connect_server = addr; + log::info!("服务端地址变化,旧地址:{},新地址:{}",current_dev.connect_server,addr); if current_device.compare_exchange(current_dev, tmp).is_ok() { current_dev.connect_server = addr; } diff --git a/vnt/src/handle/punch_handler.rs b/vnt/src/handle/punch_handler.rs index 2912832..de8b203 100644 --- a/vnt/src/handle/punch_handler.rs +++ b/vnt/src/handle/punch_handler.rs @@ -34,6 +34,7 @@ pub fn start(mut worker: VntWorker, receiver: Receiver<(Ipv4Addr, NatInfo)>, pub async fn start0(mut receiver: Receiver<(Ipv4Addr, NatInfo)>, mut punch: Punch, current_device: Arc>, client_cipher: Cipher, ) { + log::info!("启动打洞任务"); while let Some((peer_ip, nat_info)) = receiver.recv().await { if let Err(e) = start_(&client_cipher, &mut punch, ¤t_device, peer_ip, nat_info).await { log::warn!("网络打洞异常 {:?}", e); @@ -70,6 +71,7 @@ pub async fn start_punch( ) { let mut num = 0; let sleep_time = [3, 5, 7, 11, 13, 17, 19, 23, 29]; + log::info!("启动发起打洞请求任务"); loop { if sender.is_close() { break; @@ -135,8 +137,12 @@ pub fn punch_packet( .collect(); punch_reply.public_port = nat_info.public_port as u32; punch_reply.public_port_range = nat_info.public_port_range as u32; - punch_reply.local_ip = u32::from_be_bytes(nat_info.local_ip.octets()); - punch_reply.local_port = nat_info.local_port as u32; + punch_reply.local_ip = u32::from_be_bytes(nat_info.local_ipv4_addr.ip().octets()); + punch_reply.local_port = nat_info.local_ipv4_addr.port() as u32; + if !nat_info.ipv6_addr.ip().is_unspecified() { + punch_reply.ipv6_port = nat_info.ipv6_addr.port() as u32; + punch_reply.ipv6 = nat_info.ipv6_addr.ip().octets().to_vec(); + } punch_reply.nat_type = protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type)); let bytes = punch_reply.write_to_bytes()?; let mut net_packet = NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?; diff --git a/vnt/src/handle/recv_handler.rs b/vnt/src/handle/recv_handler.rs index 89c70bd..9905ed7 100644 --- a/vnt/src/handle/recv_handler.rs +++ b/vnt/src/handle/recv_handler.rs @@ -1,4 +1,4 @@ -use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; +use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; use std::sync::Arc; use crossbeam_utils::atomic::AtomicCell; @@ -370,11 +370,19 @@ impl ChannelDataHandler { let punch_info = PunchInfo::parse_from_bytes(net_packet.payload())?; let public_ips = punch_info.public_ip_list. iter().map(|v| { Ipv4Addr::from(v.to_be_bytes()) }).collect(); + let local_ipv4_addr = SocketAddrV4::new(Ipv4Addr::from(punch_info.local_ip.to_be_bytes()), punch_info.local_port as u16); + let ipv6_addr = if punch_info.ipv6.len() == 16 { + let ipv6: [u8; 16] = punch_info.ipv6.try_into().unwrap(); + SocketAddrV6::new(Ipv6Addr::from(ipv6), punch_info.ipv6_port as u16, 0, 0) + } else { + SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0) + }; + let peer_nat_info = NatInfo::new(public_ips, punch_info.public_port as u16, punch_info.public_port_range as u16, - Ipv4Addr::from(punch_info.local_ip.to_be_bytes()), - punch_info.local_port as u16, + local_ipv4_addr, + ipv6_addr, punch_info.nat_type.enum_value_or_default().into()); self.peer_nat_info_map.insert(source, peer_nat_info.clone()); if !punch_info.reply { @@ -386,8 +394,12 @@ impl ChannelDataHandler { punch_reply.public_port_range = nat_info.public_port_range as u32; punch_reply.nat_type = protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type)); - punch_reply.local_ip = u32::from_be_bytes(nat_info.local_ip.octets()); - punch_reply.local_port = nat_info.local_port as u32; + punch_reply.local_ip = u32::from_be_bytes(nat_info.local_ipv4_addr.ip().octets()); + punch_reply.local_port = nat_info.local_ipv4_addr.port() as u32; + if !nat_info.ipv6_addr.ip().is_unspecified() { + punch_reply.ipv6 = nat_info.ipv6_addr.ip().octets().to_vec(); + punch_reply.ipv6_port = nat_info.ipv6_addr.port() as u32; + } let bytes = punch_reply.write_to_bytes()?; let mut punch_packet = NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?; @@ -400,17 +412,18 @@ impl ChannelDataHandler { punch_packet.set_source(current_device.virtual_ip()); punch_packet.set_destination(source); punch_packet.set_payload(&bytes)?; - if !peer_nat_info.local_ip.is_unspecified() && peer_nat_info.local_port != 0 { - let mut packet = NetPacket::new_encrypt([0u8; 12 + ENCRYPTION_RESERVED])?; - packet.set_version(Version::V1); - packet.first_set_ttl(1); - packet.set_protocol(Protocol::Control); - packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into()); - packet.set_source(current_device.virtual_ip()); - packet.set_destination(source); - self.client_cipher.encrypt_ipv4(&mut packet)?; - let _ = context.send_main(packet.buffer(), SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port))).await; - } + // if !peer_nat_info.local_ip.is_unspecified() && peer_nat_info.local_port != 0 { + // let mut packet = NetPacket::new_encrypt([0u8; 12 + ENCRYPTION_RESERVED])?; + // packet.set_version(Version::V1); + // packet.first_set_ttl(1); + // packet.set_protocol(Protocol::Control); + // packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into()); + // packet.set_source(current_device.virtual_ip()); + // packet.set_destination(source); + // self.client_cipher.encrypt_ipv4(&mut packet)?; + // let _ = context.try_send_main_udp(packet.buffer(), + // SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port))); + // } if self.punch(source, peer_nat_info).await { self.client_cipher.encrypt_ipv4(&mut punch_packet)?; context.send_by_key(punch_packet.buffer(), route_key).await?; @@ -512,10 +525,13 @@ impl ChannelDataHandler { service_packet::Protocol::RegistrationRequest => {} service_packet::Protocol::RegistrationResponse => { let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?; - let local_port = context.main_local_port()?; - let local_ip = nat::local_ip()?; + let local_port = context.main_local_ipv4_port().unwrap_or(0); + let local_ipv4_addr = nat::local_ipv4_addr(local_port); + let local_port = context.main_local_ipv6_port().unwrap_or(0); + let ipv6_addr = nat::local_ipv6_addr(local_port); let nat_info = self.nat_test.re_test(Ipv4Addr::from(response.public_ip), - response.public_port as u16, local_ip, local_port).await; + response.public_port as u16, + local_ipv4_addr, ipv6_addr).await; context.switch(nat_info.nat_type); let new_ip = Ipv4Addr::from(response.virtual_ip); let current_ip = current_device.virtual_ip(); diff --git a/vnt/src/nat/mod.rs b/vnt/src/nat/mod.rs index e47a348..e4c6c6f 100644 --- a/vnt/src/nat/mod.rs +++ b/vnt/src/nat/mod.rs @@ -1,5 +1,5 @@ use std::io; -use std::net::{IpAddr, Ipv4Addr}; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; use std::net::UdpSocket; use std::sync::Arc; @@ -10,7 +10,7 @@ use crate::proto::message::PunchNatType; mod stun_test; -pub fn local_ip() -> io::Result { +pub fn local_ipv4() -> io::Result { let socket = UdpSocket::bind("0.0.0.0:0")?; socket.connect("8.8.8.8:80")?; let addr = socket.local_addr()?; @@ -24,6 +24,44 @@ pub fn local_ip() -> io::Result { } } +pub fn local_ipv6() -> io::Result { + let socket = UdpSocket::bind("[::]:0")?; + socket.connect("[2001:4860:4860::8888]:80")?; + let addr = socket.local_addr()?; + match addr.ip() { + IpAddr::V4(_) => { + Ok(Ipv6Addr::UNSPECIFIED) + } + IpAddr::V6(ip) => { + Ok(ip) + } + } +} + +pub fn local_ipv4_addr(port: u16) -> SocketAddrV4 { + match local_ipv4() { + Ok(ipv4) => { + SocketAddrV4::new(ipv4, port) + } + Err(e) => { + log::warn!("获取本地ipv4地址失败:{}",e); + SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0) + } + } +} + +pub fn local_ipv6_addr(port: u16) -> SocketAddrV6 { + match local_ipv6() { + Ok(ipv6) => { + SocketAddrV6::new(ipv6, port, 0, 0) + } + Err(e) => { + log::warn!("获取本地ipv6地址失败:{}",e); + SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0) + } + } +} + #[derive(Clone)] pub struct NatTest { stun_server: Vec, @@ -53,8 +91,8 @@ impl NatTest { mut stun_server: Vec, public_ip: Ipv4Addr, public_port: u16, - local_ip: Ipv4Addr, - local_port: u16, + local_ipv4_addr: SocketAddrV4, + ipv6_addr: SocketAddrV6, ) -> NatTest { let server = stun_server[0].clone(); stun_server.resize(3, server); @@ -62,8 +100,8 @@ impl NatTest { &stun_server, public_ip, public_port, - local_ip, - local_port, + local_ipv4_addr, + ipv6_addr, ).await; NatTest { stun_server, @@ -84,15 +122,15 @@ impl NatTest { &self, public_ip: Ipv4Addr, public_port: u16, - local_ip: Ipv4Addr, - local_port: u16, + local_ipv4_addr: SocketAddrV4, + ipv6_addr: SocketAddrV6, ) -> NatInfo { let info = NatTest::re_test_( &self.stun_server, public_ip, public_port, - local_ip, - local_port, + local_ipv4_addr, + ipv6_addr, ).await; *self.info.lock() = info.clone(); info @@ -101,8 +139,8 @@ impl NatTest { stun_server: &Vec, public_ip: Ipv4Addr, public_port: u16, - local_ip: Ipv4Addr, - local_port: u16, + local_ipv4_addr: SocketAddrV4, + ipv6_addr: SocketAddrV6, ) -> NatInfo { return match stun_test::stun_test_nat(stun_server.clone()).await { Ok((nat_type, ips, port_range)) => { @@ -117,8 +155,8 @@ impl NatTest { public_ips, public_port, port_range, - local_ip, - local_port, + local_ipv4_addr, + ipv6_addr, nat_type, ) } @@ -128,8 +166,8 @@ impl NatTest { vec![public_ip], public_port, 0, - local_ip, - local_port, + local_ipv4_addr, + ipv6_addr, NatType::Cone, ) }