支持ipv6
This commit is contained in:
@@ -118,7 +118,7 @@ A virtual network tool (VPN)
|
||||
### Todo
|
||||
|
||||
- 桌面UI(测试中)
|
||||
- 支持Ipv6
|
||||
- 支持Ipv6(1.2.2已支持客户端之间的ipv6,待支持客户端和服务端之间的ipv6通信)
|
||||
|
||||
### 常见问题
|
||||
<details> <summary>展开</summary>
|
||||
|
||||
@@ -62,6 +62,8 @@
|
||||
| `>=`8 | aes_gcm | AES256-GCM |
|
||||
| 1~8位 | aes_cbc | AES128-CBC |
|
||||
| `>=`8 | aes_cbc | AES256-CBC |
|
||||
### --finger
|
||||
开启数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启,开启会损耗一部分性能
|
||||
|
||||
### --relay
|
||||
禁用p2p,在网络环境很差时,只使用服务器中转效果可能更好(可以配合--tcp参数一起使用)
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -83,7 +83,7 @@ pub fn command_list(vnt: &Vnt) -> Vec<DeviceItem> {
|
||||
let nat_type = format!("{:?}", nat_info.nat_type);
|
||||
let public_ips: Vec<String> = 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<String> = 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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<RouteItem>) {
|
||||
|
||||
+48
-18
@@ -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<UdpSocket>,
|
||||
pub(crate) main_channel_ipv6: Option<Arc<UdpSocket>>,
|
||||
//在udp的基础上,可以选择使用tcp和服务端通信
|
||||
pub(crate) main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>,
|
||||
pub(crate) route_table: DashMap<Ipv4Addr, Vec<Route>>,
|
||||
pub(crate) route_table_time: DashMap<(RouteKey, Ipv4Addr), AtomicCell<Instant>>,
|
||||
pub(crate) route_table_time: DashMap<(RouteKey, Ipv4Addr), Instant>,
|
||||
pub(crate) status_receiver: Receiver<Status>,
|
||||
pub(crate) status_sender: Sender<Status>,
|
||||
pub(crate) udp_map: DashMap<usize, Arc<UdpSocket>>,
|
||||
@@ -37,12 +41,13 @@ pub struct Context {
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new(main_channel: Arc<UdpSocket>, main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>, _channel_num: usize) -> Self {
|
||||
pub fn new(main_channel: Arc<UdpSocket>, main_channel_ipv6: Option<Arc<UdpSocket>>, main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>, _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<u16> {
|
||||
pub fn main_local_ipv4_port(&self) -> io::Result<u16> {
|
||||
self.inner.main_channel.local_addr().map(|k| k.port())
|
||||
}
|
||||
pub fn main_local_ipv6_port(&self) -> io::Result<u16> {
|
||||
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<usize> {
|
||||
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<usize> {
|
||||
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<usize> {
|
||||
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<usize> {
|
||||
@@ -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<Vec<Route>> {
|
||||
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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<Ipv4Addr>,
|
||||
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<Ipv4Addr>,
|
||||
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 => {
|
||||
|
||||
+22
-6
@@ -54,6 +54,7 @@ pub struct Vnt {
|
||||
pub struct VntUtil {
|
||||
config: Config,
|
||||
main_channel: UdpSocket,
|
||||
main_channel_ipv6: Option<UdpSocket>,
|
||||
main_tcp_channel: Option<TcpStream>,
|
||||
response: Option<RegResponse>,
|
||||
iface: Option<(DeviceWriter, DeviceReader)>,
|
||||
@@ -64,6 +65,15 @@ pub struct VntUtil {
|
||||
impl VntUtil {
|
||||
pub async fn new(config: Config) -> io::Result<VntUtil> {
|
||||
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<DashMap<Ipv4Addr, NatInfo>> = 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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<AtomicCell<CurrentDeviceInfo>>,
|
||||
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])?;
|
||||
|
||||
@@ -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();
|
||||
|
||||
+54
-16
@@ -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<Ipv4Addr> {
|
||||
pub fn local_ipv4() -> io::Result<Ipv4Addr> {
|
||||
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<Ipv4Addr> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_ipv6() -> io::Result<Ipv6Addr> {
|
||||
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<String>,
|
||||
@@ -53,8 +91,8 @@ impl NatTest {
|
||||
mut stun_server: Vec<String>,
|
||||
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<String>,
|
||||
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,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user