支持ipv6服务端

This commit is contained in:
lubeilin
2023-12-24 12:00:44 +08:00
parent 26d68ac059
commit 37080af275
4 changed files with 16 additions and 91 deletions
+8 -67
View File
@@ -1,27 +1,26 @@
use std::{io, thread};
use std::collections::HashMap;
use std::io::{Read, Write};
use std::net::{Ipv4Addr, Shutdown, SocketAddr};
use std::net::TcpStream;
use std::net::UdpSocket as StdUdpSocket;
use std::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
use std::sync::Arc;
use std::time::{Duration, Instant};
use std::{io, thread};
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::RwLock;
use tokio::net::UdpSocket;
use tokio::sync::watch::{channel, Receiver, Sender};
use crate::channel::{Route, RouteKey, Status, TCP_ID, UDP_ID};
use crate::channel::punch::NatType;
use crate::channel::{Route, RouteKey, Status, TCP_ID, UDP_ID, UDP_V6_ID};
use crate::core::status::VntWorker;
use crate::handle::recv_handler::ChannelDataHandler;
use crate::handle::CurrentDeviceInfo;
use crate::handle::recv_handler::ChannelDataHandler;
pub struct ContextInner {
//udp用于打洞、服务端通信(可选)
pub(crate) main_channel: Arc<StdUdpSocket>,
pub(crate) main_channel_ipv6: Option<Arc<StdUdpSocket>>,
//在udp的基础上,可以选择使用tcp和服务端通信
pub(crate) main_tcp_channel: Option<std::sync::mpsc::SyncSender<Vec<u8>>>,
pub(crate) route_table: RwLock<HashMap<Ipv4Addr, Vec<(Route, AtomicCell<Instant>)>>>,
@@ -41,7 +40,6 @@ pub struct Context {
impl Context {
pub fn new(
main_channel: Arc<StdUdpSocket>,
main_channel_ipv6: Option<Arc<StdUdpSocket>>,
main_tcp_channel: Option<std::sync::mpsc::SyncSender<Vec<u8>>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
_channel_num: usize,
@@ -52,7 +50,6 @@ impl Context {
let (status_sender, status_receiver) = channel(Status::Cone);
let inner = Arc::new(ContextInner {
main_channel,
main_channel_ipv6,
main_tcp_channel,
route_table: RwLock::new(HashMap::with_capacity(16)),
status_receiver,
@@ -75,18 +72,12 @@ impl Context {
}
pub fn close(&self) -> io::Result<()> {
let _ = self.inner.status_sender.send(Status::Close);
if let Ok(port) = self.main_local_ipv4_port() {
if let Ok(port) = self.main_local_udp_port() {
let _ = StdUdpSocket::bind("127.0.0.1:0")?.send_to(
b"stop",
SocketAddr::V4(std::net::SocketAddrV4::new(Ipv4Addr::LOCALHOST, port)),
);
}
if let Ok(port) = self.main_local_ipv6_port() {
let _ = StdUdpSocket::bind("[::]:0")?.send_to(
b"stop",
SocketAddr::V6(std::net::SocketAddrV6::new(Ipv6Addr::LOCALHOST, port, 0, 0)),
);
}
if let Some(tcp) = &self.inner.main_tcp_channel {
let _ = tcp.send(vec![]);
}
@@ -111,32 +102,18 @@ impl Context {
pub fn switch_to_symmetric(&self) {
let _ = self.inner.status_sender.send(Status::Symmetric);
}
pub fn main_local_ipv4_port(&self) -> io::Result<u16> {
pub fn main_local_udp_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"))
}
}
fn insert_udp(&self, id: usize, udp: Arc<UdpSocket>) {
self.inner.udp_map.write().insert(id, udp);
}
fn remove_udp(&self, id: usize) {
self.inner.udp_map.write().remove(&id);
}
#[inline]
pub fn 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.send_to(buf, addr)
} else {
Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
}
} else {
self.inner.main_channel.send_to(buf, addr)
}
self.inner.main_channel.send_to(buf, addr)
}
pub fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
@@ -209,13 +186,6 @@ impl Context {
}
}
UDP_ID => self.inner.main_channel.send_to(buf, route_key.addr),
UDP_V6_ID => {
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
udp_ipv6.send_to(buf, route_key.addr)
} else {
Err(io::Error::new(io::ErrorKind::Other, "not ipv6 udp"))
}
}
_ => {
if let Some(udp) = self.get_udp_by_route(route_key) {
return udp.send_to(buf, route_key.addr).await;
@@ -238,13 +208,6 @@ impl Context {
}
}
UDP_ID => self.inner.main_channel.send_to(buf, route_key.addr),
UDP_V6_ID => {
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
udp_ipv6.send_to(buf, route_key.addr)
} else {
Err(io::Error::new(io::ErrorKind::Other, "not ipv6 udp"))
}
}
_ => {
if let Some(udp) = self.get_udp_by_route(route_key) {
return udp.try_send_to(buf, route_key.addr);
@@ -584,28 +547,6 @@ impl Channel {
})
.unwrap();
}
if let Some(main_channel_ipv6) = &context.inner.main_channel_ipv6 {
let worker = worker.worker("main_channel_ipv6");
let context = context.clone();
let main_channel_ipv6 = main_channel_ipv6.clone();
let handler = handler.clone();
let buf_sender = buf_sender.clone();
thread::Builder::new()
.name("ipv6-recv".into())
.spawn(move || {
log::info!("启动udp v6");
Self::main_start_(
worker,
context,
UDP_V6_ID,
main_channel_ipv6,
handler,
buf_sender,
head_reserve,
)
})
.unwrap();
}
{
let worker = worker.worker("main_channel_1");
let context = context.clone();
-1
View File
@@ -7,7 +7,6 @@ pub mod sender;
const TCP_ID: usize = 0;
const UDP_ID: usize = 1;
const UDP_V6_ID: usize = 2;
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Status {
+7 -21
View File
@@ -57,7 +57,6 @@ 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)>,
@@ -67,24 +66,14 @@ pub struct VntUtil {
impl VntUtil {
pub fn new(config: Config) -> io::Result<VntUtil> {
let address: SocketAddr = format!("[::]:{}", config.port).parse().unwrap();
//单个udp用同步的性能更好,但是代理和多端口监听用异步更方便,这里将两者结合起来
let main_channel = UdpSocket::bind(format!("0.0.0.0:{}", config.port))?;
let socket = socket2::Socket::new(socket2::Domain::IPV6,socket2::Type::DGRAM,None)?;
socket.set_only_v6(false)?;
socket.bind(&address.into())?;
let main_channel:UdpSocket = socket.into();
main_channel.set_write_timeout(Some(Duration::from_secs(5)))?;
main_channel.set_read_timeout(Some(Duration::from_secs(2)))?;
let main_channel_ipv6 = if config.punch_model != PunchModel::IPv4 {
match UdpSocket::bind(format!("[::]:{}", config.port)) {
Ok(main_channel_ipv6) => {
main_channel_ipv6.set_write_timeout(Some(Duration::from_secs(5)))?;
Some(main_channel_ipv6)
}
Err(e) => {
log::warn!("绑定ipv6地址失败:{}", e);
None
}
}
} else {
None
};
let server_cipher = if config.server_encrypt {
let mut key = [0u8; 32];
rand::thread_rng().fill(&mut key);
@@ -95,7 +84,6 @@ impl VntUtil {
Ok(VntUtil {
config,
main_channel,
main_channel_ipv6,
main_tcp_channel: None,
response: None,
iface: None,
@@ -256,7 +244,6 @@ impl VntUtil {
};
let context = Context::new(
Arc::new(self.main_channel),
self.main_channel_ipv6.map(|v| Arc::new(v)),
tcp_sender,
current_device.clone(),
1,
@@ -282,11 +269,10 @@ impl VntUtil {
let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected));
let public_ip = response.public_ip;
let public_port = response.public_port;
let local_port = context.main_local_ipv4_port().unwrap_or(0);
let local_port = context.main_local_udp_port().unwrap_or(0);
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);
let ipv6_addr = crate::nat::local_ipv6_addr(local_port);
// NAT检测
let nat_test = NatTest::new(
config.stun_server.clone(),
+1 -2
View File
@@ -592,9 +592,8 @@ impl ChannelDataHandler {
.build()
.unwrap()
.block_on(async move {
let local_port = context.main_local_ipv4_port().unwrap_or(0);
let local_port = context.main_local_udp_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 = nat_test
.re_test(