windows changed to tun-rs for better performance
This commit is contained in:
parent
8493f80bdd
commit
33ff338fd2
581
Cargo.lock
generated
581
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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]
|
||||
|
||||
@ -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 {
|
||||
@ -233,10 +239,10 @@ async fn loop_tap(eee: &'static Node, mut dns_rx: Receiver<(Vec<u8>, SocketAddr)
|
||||
if let Ok(mut dns) = simple_dns::Packet::parse(&data.0) {
|
||||
let transaction_id = dns.id();
|
||||
if let Some((ip, port, origin_transaction_id)) = eee.dns_matcher.get_client_info(transaction_id) {
|
||||
warn!("got dns reply from global 223.5.5.5, will send to {}:{}",
|
||||
warn!("got dns reply from global 223.5.5.5, will send to {}:{}",
|
||||
ip_to_string(&ip), port);
|
||||
|
||||
|
||||
|
||||
let dstmac = eee.device_config.get_mac();
|
||||
let srcmac = eee.device_config.dns_mac;
|
||||
|
||||
@ -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;
|
||||
@ -360,18 +364,14 @@ async fn read_and_parse_tun_packet(eee: &'static Node, buf: BytesMut) {
|
||||
async fn edge_send_packet_to_net(eee: &Node, data: BytesMut) {
|
||||
// debug!("edge send packet to net({} bytes): {:?}", data.len(), data);
|
||||
|
||||
/*
|
||||
/*
|
||||
let encrypt_key = eee.get_encrypt_key();
|
||||
if encrypt_key.len() == 0 {
|
||||
error!("drop tun packet due to encrypt key len is 0");
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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());
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user