windows changed to tun-rs for better performance

This commit is contained in:
alex 2026-06-30 11:50:54 +08:00
parent d0ec1e29c6
commit e8f4498806
4 changed files with 658 additions and 148 deletions

581
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -50,6 +50,7 @@ default-net = "0.22.0"
socket2 = "0.6.3"
hostname = "0.4.2"
sysinfo = "0.38.4"
tun-rs = {version="2.8.5", features=["async"]}
# rolling-file = { path = "../rolling-file" }
[target.'cfg(unix)'.dependencies]

View File

@ -1,22 +1,20 @@
use std::net::SocketAddr;
use std::sync::atomic::{Ordering};
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::time::Duration;
use crate::config::{TCP_PING_TIME};
use crate::config::TCP_PING_TIME;
use crate::network::ipv6::run_ipv6;
use crate::network::{
get_edge, ping_to_sn, read_and_parse_packet, TunTapPacketHandler,
};
use crate::network::{get_edge, ping_to_sn, read_and_parse_packet, TunTapPacketHandler};
use crate::tcp::{init_quic_conn, send_stun_request};
use crate::utils::{send_to_sock, CommandLine};
use crate::{ConnectionInfo};
use crate::ConnectionInfo;
use bytes::BytesMut;
use etherparse::{PacketBuilder};
use sdlan_sn_rs::peer::{SdlanSock};
use etherparse::PacketBuilder;
use sdlan_sn_rs::peer::SdlanSock;
use sdlan_sn_rs::utils::{get_current_timestamp, ip_to_string, is_multi_broadcast};
use sdlan_sn_rs::utils::{Mac, Result};
use tokio::net::{UdpSocket};
use tokio::net::UdpSocket;
use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio_util::sync::CancellationToken;
@ -120,7 +118,11 @@ pub async fn async_main(
Ok(())
}
async fn run_edge_loop(eee: &'static Node, global_dns_rx: Receiver<(Vec<u8>, SocketAddr)>, cancel: CancellationToken) {
async fn run_edge_loop(
eee: &'static Node,
global_dns_rx: Receiver<(Vec<u8>, SocketAddr)>,
cancel: CancellationToken,
) {
ping_to_sn().await;
{
let cancel2 = cancel.clone();
@ -202,7 +204,7 @@ pub async fn loop_socket_v4(
}
async fn receive_dns_reply(sock: &Arc<UdpSocket>) -> Option<Vec<u8>> {
let mut reply = vec![0;1024];
let mut reply = vec![0; 1024];
if let Ok((size, _from)) = sock.recv_from(&mut reply).await {
if size == 0 {
// closed
@ -214,7 +216,11 @@ async fn receive_dns_reply(sock: &Arc<UdpSocket>) -> Option<Vec<u8>> {
None
}
async fn loop_tap(eee: &'static Node, mut dns_rx: Receiver<(Vec<u8>, SocketAddr)>, cancel: CancellationToken) {
async fn loop_tap(
eee: &'static Node,
mut dns_rx: Receiver<(Vec<u8>, SocketAddr)>,
cancel: CancellationToken,
) {
debug!("loop tap");
let (tx, mut rx) = channel(10);
tokio::spawn(async {
@ -293,23 +299,23 @@ async fn loop_tap(eee: &'static Node, mut dns_rx: Receiver<(Vec<u8>, SocketAddr)
}
#[cfg(any(feature = "tun", target_os = "windows"))]
fn get_data_from_tun_with_layer2_zeroed(eee: &Node) -> BytesMut {
async fn get_data_from_tun_with_layer2_zeroed(eee: &Node) -> BytesMut {
let mut temp = BytesMut::zeroed(1514);
// let mut temp = BytesMut::with_capacity(1514);
let mut data_buf = temp.split_off(14);
let Ok(size) = eee.device.recv(&mut data_buf) else {
let Ok(size) = eee.device.recv(&mut data_buf).await else {
return BytesMut::new();
};
data_buf.truncate(size);
temp.unsplit(data_buf);
temp
}
#[cfg(not(feature = "tun"))]
fn get_data_from_tap_with_layer2(eee: &Node) -> BytesMut {
async fn get_data_from_tap_with_layer2(eee: &Node) -> BytesMut {
let mut buf = BytesMut::zeroed(1514);
let Ok(size) = eee.device.recv(&mut buf) else {
let Ok(size) = eee.device.recv(&mut buf).await else {
return BytesMut::new();
};
buf.truncate(size);
@ -318,16 +324,14 @@ fn get_data_from_tap_with_layer2(eee: &Node) -> BytesMut {
async fn get_tun_flow(eee: &'static Node, tx: Sender<BytesMut>) {
loop {
let buf = tokio::task::spawn_blocking(|| {
let buf = {
#[cfg(any(feature = "tun", target_os = "windows"))]
let data = get_data_from_tun_with_layer2_zeroed(eee);
#[cfg(all(not(feature = "tun"), not(target_os="windows")))]
let data = get_data_from_tap_with_layer2(eee);
let data = get_data_from_tun_with_layer2_zeroed(eee).await;
#[cfg(all(not(feature = "tun"), not(target_os = "windows")))]
let data = get_data_from_tap_with_layer2(eee).await;
data
})
.await
.unwrap();
};
if buf.len() == 0 {
return;
@ -367,11 +371,7 @@ async fn edge_send_packet_to_net(eee: &Node, data: BytesMut) {
return;
}
*/
if let Err(e) = eee
.device
.handle_packet_from_device(data)
.await
{
if let Err(e) = eee.device.handle_packet_from_device(data).await {
error!("failed to handle packet from device: {}", e.to_string());
}
}

View File

@ -4,7 +4,8 @@ use etherparse::{Ethernet2Header, IpHeaders, NetSlice, SlicedPacket, TransportSl
use ipnet::Ipv4Net;
use sdlan_sn_rs::config::SDLAN_DEFAULT_TTL;
use sdlan_sn_rs::utils::{
BROADCAST_MAC, Result, SDLanError, aes_encrypt, ip_to_string, is_multi_broadcast, net_bit_len_to_mask
aes_encrypt, ip_to_string, is_multi_broadcast, net_bit_len_to_mask, Result, SDLanError,
BROADCAST_MAC,
};
use std::io::{Error, ErrorKind};
use std::net::Ipv4Addr;
@ -13,6 +14,7 @@ use std::process::Command;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use tracing::{debug, error, info};
use tun_rs::AsyncDevice;
use wintun;
use crate::network::{
@ -28,13 +30,130 @@ use super::device::{DeviceConfig, Mode};
use super::TunTapPacketHandler;
pub struct Iface {
device: AsyncDevice,
if_idx: u32,
name: String,
}
impl Iface {
fn new(path: &str, name: &str) -> Self {
let dev = tun_rs::DeviceBuilder::new()
.wintun_file(path.to_string())
.name(name)
.layer(tun_rs::Layer::L3)
.build_async()
.expect("failed to create tun");
let idx = dev.if_index().expect("failed to get if index");
Self {
device: dev,
if_idx: idx,
name: name.to_string(),
}
}
}
impl Iface {
pub fn get_if_idx(&self) -> u32 {
self.if_idx
}
pub async fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
self.device.recv(buf).await
}
pub async fn send(&self, content: &[u8]) -> std::io::Result<usize> {
self.device.send(content).await
}
pub fn reload_config(&self, node: &Node, device_config: &DeviceConfig, network_domain: &str) {
let netbit = device_config.get_net_bit();
let ip = device_config.get_ip();
if netbit == 0 || ip == 0 {
error!("reload config's ip is 0");
return;
}
let mask = net_bit_len_to_mask(netbit);
let ip = ip_to_string(&ip);
let netbit = ip_to_string(&net_bit_len_to_mask(netbit));
let mut cmd = Command::new("netsh");
debug!("name={}, addr={}, mask={}", self.name, ip, netbit);
let command = cmd
.creation_flags(0x08000000)
.arg("interface")
.arg("ip")
.arg("set")
.arg("address")
.arg(&format!("name=\"{}\"", self.name))
.arg("source=static")
.arg(&format!("addr={}", ip))
.arg(&format!("mask={}", netbit));
let res = command.status();
// let res = command.output();
match res {
Ok(r) => {
if r.success() {
debug!("netsh ok");
} else {
error!("failed to run netsh, returned {:?}", r.code())
}
}
Err(e) => {
error!("failed to run netsh: {}", e.to_string());
}
}
let mut cmd = Command::new("netsh");
let command = cmd
.creation_flags(0x08000000)
.arg("interface")
.arg("ipv4")
.arg("set")
.arg("subinterface")
.arg(&format!("\"{}\"", self.name))
.arg(format!("mtu={}", device_config.mtu))
.arg("store=persistent");
let res = command.status();
match res {
Ok(r) => {
if r.success() {
debug!("netsh2 ok");
} else {
error!("failed to run netsh set mtu, returned {:?}", r.code())
}
}
Err(e) => {
error!("failed to run netsh2: {}", e.to_string());
}
}
// let gw = ip_to_string(&default_gw);
// debug!("gw = {}", ip);
if let Err(e) = set_dns(&self.name, network_domain, &ip, self.if_idx) {
error!("failed to set dns: {:?}", e);
} else {
debug!("set dns ok");
}
node.route_table.apply_system(self.if_idx);
}
}
pub struct IfaceOld {
if_idx: u32,
name: String,
_adapter: Arc<wintun::Adapter>,
session: Arc<wintun::Session>,
}
impl Iface {
impl IfaceOld {
pub fn get_if_idx(&self) -> u32 {
self.if_idx
}
@ -55,11 +174,12 @@ impl Iface {
}
pub fn send(&self, content: &[u8]) -> std::io::Result<usize> {
let Ok(mut pkt) = self
.session
.allocate_send_packet(content.len() as u16) else {
error!("failed to allocate send packet");
return Err(std::io::Error::new(std::io::ErrorKind::Other, "failed to allocate send packet"));
let Ok(mut pkt) = self.session.allocate_send_packet(content.len() as u16) else {
error!("failed to allocate send packet");
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"failed to allocate send packet",
));
};
let buf: &mut [u8] = pkt.bytes_mut();
buf.copy_from_slice(content);
@ -310,7 +430,7 @@ impl TunTapPacketHandler for Iface {
// println!("got ip packet");
// println!("got data: {:?}", rest);
match edge.device.send(rest) {
match edge.device.send(rest).await {
Ok(size) => {
debug!("send to tun {} bytes", size);
}
@ -730,13 +850,18 @@ impl TunTapPacketHandler for Iface {
}
fn create_wintun(path: &str, name: &str) -> std::io::Result<Iface> {
Ok(Iface::new(path, name))
/*
let wt = unsafe { wintun::load_from_path(path) }.expect("failed to load wintun");
let adapter = match wintun::Adapter::open(&wt, name) {
Ok(a) => a,
Err(_e) => {
let Ok(adapt) = wintun::Adapter::create(&wt, name, "Punchnet", None) else {
return Err(std::io::Error::new(std::io::ErrorKind::Other, "failed to create Punch adapter"));
let Ok(adapt) = wintun::Adapter::create(&wt, name, "Punchnet", None) else {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"failed to create Punch adapter",
));
};
adapt
}
@ -746,7 +871,10 @@ fn create_wintun(path: &str, name: &str) -> std::io::Result<Iface> {
.expect("failed to get adapter index");
// println!("idx = {}", idx);
let Ok(sess) = adapter.start_session(wintun::MAX_RING_CAPACITY) else {
return Err(std::io::Error::new(std::io::ErrorKind::Other, "failed to start session, maybe one process is running, or not running with admin?"));
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"failed to start session, maybe one process is running, or not running with admin?",
));
};
let session = Arc::new(sess);
Ok(Iface {
@ -755,6 +883,7 @@ fn create_wintun(path: &str, name: &str) -> std::io::Result<Iface> {
session,
name: name.to_owned(),
})
*/
}
pub fn new_iface(name: &str, _mode: Mode) -> std::io::Result<Iface> {
@ -778,8 +907,13 @@ pub fn set_dns(name: &str, _network_domain: &str, gw: &str, ifidx: u32) -> Resul
.creation_flags(0x08000000)
.status()?;
if !res.success() {
error!("failed to add route for dns 100.100.100.100: {:?}", res.code());
return Err(SDLanError::IOError("failed to add route for dns".to_owned()));
error!(
"failed to add route for dns 100.100.100.100: {:?}",
res.code()
);
return Err(SDLanError::IOError(
"failed to add route for dns".to_owned(),
));
}
//println!("res1: {}", res.status.success());