From 4a6ac4a8b9fabbf0074288cecae08436281fd46e Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 30 Jun 2026 15:14:12 +0800 Subject: [PATCH] windows and linux changed to tun_rs --- .vscode/settings.json | 3 +- Cargo.toml | 2 +- src/network/node.rs | 27 ++- src/network/tun_linux.rs | 385 ++++++++++++--------------------------- src/network/tun_win.rs | 5 +- src/network/tuntap.rs | 8 + 6 files changed, 140 insertions(+), 290 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 47fa098..c4c8773 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,5 @@ { // "rust-analyzer.cargo.target": "x86_64-pc-windows-gnu", - // "rust-analyzer.cargo.target": "x86_64-unknown-linux-gnu", - + "rust-analyzer.cargo.target": "x86_64-unknown-linux-gnu", // "rust-analyzer.cargo.features": ["tun"] } \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index b86bf10..df5179f 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +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"]} +tun-rs = { version = "2.8.5", features = ["async"] } # rolling-file = { path = "../rolling-file" } [target.'cfg(unix)'.dependencies] diff --git a/src/network/node.rs b/src/network/node.rs index 52500f9..19e2a08 100755 --- a/src/network/node.rs +++ b/src/network/node.rs @@ -17,16 +17,17 @@ use tokio::sync::mpsc::Sender; use tracing::{debug, error, warn}; use crate::network::{ArpTable, RouteTable2}; -use crate::utils::DynamicDNSClient; use crate::pb::{ encode_to_tcp_message, encode_to_udp_message, SdlArpRequest, SdlEmpty, SdlStunProbe, SdlStunProbeReply, }; use crate::quic::quic_init; use crate::tcp::{get_quic_write_conn, NatType, PacketType, StunProbeAttr}; +use crate::utils::DynamicDNSClient; use crate::utils::Socket; use crate::{ - CommandLine, ConnectionInfo, DNSMatcher, ErrorReport, ErrorSeverity, MyEncryptor, RuleCache, get_base_dir, get_default_interface + get_base_dir, get_default_interface, CommandLine, ConnectionInfo, DNSMatcher, ErrorReport, + ErrorSeverity, MyEncryptor, RuleCache, }; use sdlan_sn_rs::peer::{IpSubnet, V6Info}; @@ -111,27 +112,23 @@ pub async fn init_edge( // let tcpsock = TCPSocket::build("121.4.79.234:1234").await?; let tcp_pong = Arc::new(AtomicU64::new(0)); - - let mode = if cfg!(not(feature = "tun")) { - Mode::Tap - } else { - Mode::Tun - }; - - let iface = match new_iface("dev", mode) { + let iface = match new_iface("dev") { Ok(iface) => iface, Err(e) => { if let Some(ref chan) = error_report_channel { println!("sending one panic"); - chan.send(ErrorReport { severity: ErrorSeverity::Panic, message: e.to_string() }).await; + chan.send(ErrorReport { + severity: ErrorSeverity::Panic, + message: e.to_string(), + }) + .await; return Err(e.into()); } else { panic!("new iface failed: {}", e.to_string()); } - }, + } }; - - + let edge = Node::new( mac, pubkey, @@ -320,7 +317,6 @@ pub struct Node { //cookie_match: DashMap>, pub cookie_match: Queryer, // packet_id_match: DashMap>, - exclusive_tcp: TcpListener, } @@ -478,7 +474,6 @@ impl Node { virtual_iface: Iface, tcp_listener: TcpListener, ) -> Self { - Self { #[cfg(any(feature = "tun", target_os = "windows"))] arp_table: ArpTable::new(), diff --git a/src/network/tun_linux.rs b/src/network/tun_linux.rs index d3abf7f..a134733 100755 --- a/src/network/tun_linux.rs +++ b/src/network/tun_linux.rs @@ -15,6 +15,8 @@ use sdlan_sn_rs::utils::{ip_to_string, is_ipv6_multicast, net_bit_len_to_mask, M use std::ffi::CStr; use std::ffi::{c_char, c_int}; use std::fs::{self, OpenOptions}; +#[cfg(feature = "tun")] +use std::hint::L3; #[cfg(not(feature = "tun"))] use std::net::IpAddr; use std::net::Ipv4Addr; @@ -25,7 +27,7 @@ use std::sync::atomic::Ordering; use sdlan_sn_rs::utils::Result; use std::io::{BufRead, BufReader, ErrorKind, Read, Write}; -use std::os::fd::AsRawFd; +use std::os::fd::{AsFd, AsRawFd}; use std::process::Command; use tracing::{debug, error, info, warn}; @@ -33,11 +35,11 @@ use tracing::{debug, error, info, warn}; #[cfg(feature = "tun")] use crate::caculate_crc; use crate::get_edge; -#[cfg(feature = "tun")] -use crate::network::parse_dns_payload; #[cfg(not(feature = "tun"))] use crate::network::{parse_dns_payload, ArpHdr, EthHdr, ARP_REPLY}; -use crate::network::{send_packet_to_net, Node}; +#[cfg(feature = "tun")] +use crate::network::{parse_dns_payload, LAYER}; +use crate::network::{send_packet_to_net, Node, LAYER}; #[cfg(not(feature = "tun"))] use crate::pb::SdlArpResponse; #[cfg(feature = "tun")] @@ -52,97 +54,46 @@ const RESOLV_FILE: &'static str = "/etc/resolv.conf"; const RESOLV_FILE_BACKUP: &'static str = "/etc/resolv.conf.punchnet.bak"; use crate::network::DNS_IP; -// #[link(name = "tuntap", kind="static")] -#[link(name = "tuntap")] -extern "C" { - fn tuntap_setup(fd: c_int, name: *mut u8, mode: c_int, packet_info: c_int) -> c_int; -} - #[allow(unused)] pub struct Iface { - fd: std::fs::File, - mode: Mode, + dev: tun_rs::AsyncDevice, name: String, has_resolvectl: bool, } -pub fn new_iface(tunname: &str, mode: Mode) -> std::io::Result { - match Iface::without_packet_info(tunname, mode) { - Err(e) => { - error!("failed to create tun: {}", e.as_str()); - Err(std::io::Error::new(ErrorKind::Other, "failed to create virtial device, is run with root?")) +pub fn new_iface(tunname: &str) -> std::io::Result { + match tun_rs::DeviceBuilder::new() + // .offload(true) + .layer(LAYER) + .enable(true) + .name(tunname) + .mtu(1280) + .packet_information(false) + .build_async() + { + Ok(dev) => { + let name = dev.name().unwrap().clone(); + Ok(Iface { + dev, + name, + has_resolvectl: check_has_resolvectl(), + }) + } + Err(e) => { + error!("failed to create tun: {}", e); + Err(std::io::Error::new( + ErrorKind::Other, + "failed to create virtial device, is run with root?", + )) } - Ok(iface) => Ok(iface), } } impl Iface { - pub fn get_if_idx(&self) -> u32 { 0 } - #[allow(unused)] - pub fn with_packet_info(ifname: &str, mode: Mode) -> Result { - Iface::open_tun(ifname, mode, true) - } - - pub fn without_packet_info(ifname: &str, mode: Mode) -> Result { - Iface::open_tun(ifname, mode, false) - } - - fn open_tun(ifname: &str, mode: Mode, need_packet_info: bool) -> Result { - let fs = match OpenOptions::new() - .read(true) - .write(true) - .open("/dev/net/tun") - { - Ok(fs) => fs, - Err(e) => panic!("failed to open tun: {}", e), - }; - let mut name_ptr: *mut u8 = null_mut(); - let mut success = false; - let mut _name = Vec::new(); - for i in 0..16 { - _name.clear(); - _name.extend_from_slice(ifname.as_bytes()); - _name.extend_from_slice(i.to_string().as_bytes()); - _name.extend_from_slice(&[0; 33]); - - name_ptr = _name.as_mut_ptr(); - - let result = unsafe { - tuntap_setup( - fs.as_raw_fd(), - name_ptr, - mode as c_int, - if need_packet_info { 1 } else { 0 }, - ) - }; - if result >= 0 { - success = true; - break; - } - } - if success { - let name = unsafe { - CStr::from_ptr(name_ptr as *const c_char) - .to_string_lossy() - .into_owned() - }; - let has_resolvectl = check_has_resolvectl(); - - Ok(Iface { - fd: fs, - mode, - name, - has_resolvectl, - }) - } else { - Err(SDLanError::NormalError("failed to setup tun")) - } - } - 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(); @@ -197,7 +148,13 @@ impl Iface { } // TODO: set dns should be opened - if let Err(e) = set_dns(self, node.take_over_dns, &self.name, network_domain, &ip_to_string(&default_gw)) { + if let Err(e) = set_dns( + self, + node.take_over_dns, + &self.name, + network_domain, + &ip_to_string(&default_gw), + ) { error!("failed to set dns: {}", e.as_str()); } } else { @@ -224,18 +181,24 @@ impl Iface { } } - if let Err(e) = set_dns(self, node.take_over_dns, &self.name, network_domain, &ip_to_string(&default_gw)) { + if let Err(e) = set_dns( + self, + node.take_over_dns, + &self.name, + network_domain, + &ip_to_string(&default_gw), + ) { error!("failed to set dns: {}", e.as_str()); } } } - pub fn recv(&self, buf: &mut [u8]) -> std::io::Result { - (&self.fd).read(buf) + pub async fn recv(&self, buf: &mut [u8]) -> std::io::Result { + self.dev.recv(buf).await } - pub fn send(&self, content: &[u8]) -> std::io::Result { - (&self.fd).write(content) + pub async fn send(&self, content: &[u8]) -> std::io::Result { + self.dev.send(content).await } } @@ -243,7 +206,7 @@ impl Iface { impl TunTapPacketHandler for Iface { async fn handle_packet_from_net(&self, data: &[u8]) -> std::io::Result<()> { // debug!("in tap mode, got data: {:?}", data); - match self.send(data) { + match self.send(data).await { Err(e) => { error!("failed to write to tap: {}", e.to_string()); return Err(e); @@ -252,158 +215,6 @@ impl TunTapPacketHandler for Iface { } } - #[cfg(feature = "abc")] - async fn handle_packet_from_device( - &self, - data: BytesMut, - // encrypt_key: &[u8], - ) -> std::io::Result<()> { - use etherparse::PacketHeaders; - - debug!("in tap mode2"); - let edge = get_edge(); - - let Ok(headers) = PacketHeaders::from_ethernet_slice(&data) else { - error!("failed to parse packet"); - return Ok(()); - }; - - if let Some(eth) = headers.link { - use etherparse::EtherType; - - if let Some(hdr) = eth.ethernet2() { - use bytes::Bytes; - - if hdr.ether_type == EtherType::ARP { - use crate::network::{ArpHdr, ARP_REQUEST}; - - let arp = ArpHdr::from_slice(&data); - match arp.opcode { - ARP_REQUEST => { - let dest_ip = ((arp.dipaddr[0] as u32) << 16) + arp.dipaddr[1] as u32; - - if edge.device_config.contains(&Ipv4Addr::from_bits(dest_ip)) { - let _ = edge.send_arp_request(dest_ip, dest_ip).await; - } else { - if let Some((_, real_ip)) = edge.route_table.lookup(dest_ip) { - let real_ip = u32::from_be_bytes(real_ip.octets()); - let _ = edge.send_arp_request(dest_ip, real_ip).await; - } - } - /* - let request = SdlArpRequest { - pkt_id: edge.get_next_packet_id(), - target_ip: dest_ip, - }; - - let req = encode_to_tcp_message(Some(request), PacketType::ArpRequest as u8).unwrap(); - let conn = get_quic_write_conn(); - debug!("sending arp request"); - let _ = conn.send(req).await; - */ - return Ok(()); - } - _other => { - // just do the following logic - } - } - } - - if let Some(ip) = headers.net { - match ip { - etherparse::NetHeaders::Ipv4(ipv4, _) => { - use crate::FiveTuple; - use etherparse::IpNumber; - - if let Some(transport) = headers.transport { - match ipv4.protocol { - IpNumber::TCP => { - if let Some(tcp) = transport.tcp() { - let out_five_tuple = FiveTuple { - src_ip: ipv4.source.into(), - dst_ip: ipv4.destination.into(), - src_port: tcp.source_port, - dst_port: tcp.destination_port, - proto: IpNumber::TCP.0, - }; - - edge.rule_cache.touch_packet(out_five_tuple); - } - - // is tcp - } - IpNumber::UDP => { - if let Some(udp) = transport.udp() { - let out_five_tuple = FiveTuple { - src_ip: ipv4.source.into(), - dst_ip: ipv4.destination.into(), - src_port: udp.source_port, - dst_port: udp.destination_port, - proto: IpNumber::UDP.0, - }; - edge.rule_cache.touch_packet(out_five_tuple); - } - } - _other => {} - } - } - - if u32::from_be_bytes(ipv4.destination) == DNS_IP { - // should send to dns - parse_dns_payload(edge, &headers.payload.slice()); - if let Err(e) = edge - .udp_sock_for_dns - .send_to(&data[14..], format!("{}:15353", edge.server_ip)) - .await - { - error!("failed to send request to 15353: {}", e); - } - // edge.udp_sock_for_dns.send_to() - return Ok(()); - } - } - _other => { - // just ignore - } - } - } - - let target = hdr.destination; - if is_ipv6_multicast(&target) { - return Ok(()); - } - let size = data.len(); - - let Ok(encrypted) = edge.encryptor.load().encrypt(&data) else { - // let Ok(encrypted) = edge.encryptor.read().unwrap().encrypt(&data) else { - // let Ok(encrypted) = aes_encrypt(encrypt_key, &data) else { - error!("failed to encrypt packet request"); - return Ok(()); - }; - let data_bytes = Bytes::from(encrypted); - let data = SdlData { - is_p2p: true, - network_id: edge.network_id.load(Ordering::Relaxed), - ttl: SDLAN_DEFAULT_TTL as u32, - src_mac: Vec::from(edge.device_config.get_mac()), - dst_mac: Vec::from(target), - data: data_bytes, - identity_id: edge.identity_id.load(), - session_token: edge.session_token.get(), - }; - let msg = encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap(); - - send_packet_to_net(edge, target, &msg, size as u64).await; - } else { - error!("erro 2"); - } - } else { - error!("erro 1"); - } - - Ok(()) - } - async fn handle_packet_from_device( &self, data: BytesMut, @@ -433,7 +244,7 @@ impl TunTapPacketHandler for Iface { if dest_ip == DNS_IP { error!("got dns ip"); edge.device_config.dns_mac; - write_arp_to_device(edge, edge.device_config.dns_mac, DNS_IP); + write_arp_to_device(edge, edge.device_config.dns_mac, DNS_IP).await; return Ok(()); } @@ -906,26 +717,39 @@ fn add_resolvectl(name: &str, network_domain: &str) -> Result<()> { .arg("dns") .arg(name) .arg("100.100.100.100") - .output()?.status.success() { + .output()? + .status + .success() + { error!("faield to run resolvectl dns"); - return Err(SDLanError::IOError("failed to resolvectl dns".to_owned())) + return Err(SDLanError::IOError("failed to resolvectl dns".to_owned())); } - if !Command::new("resolvectl") .arg("domain") .arg(name) // .arg(format!("~{}", network_domain)) .arg("~.") - .output()?.status.success() { + .output()? + .status + .success() + { error!("failed to run resolvectl domain"); - return Err(SDLanError::IOError("failed to resolvectl domain".to_owned())) + return Err(SDLanError::IOError( + "failed to resolvectl domain".to_owned(), + )); } Ok(()) } -fn set_dns(iface: &Iface, take_over_dns: bool, name: &str, network_domain: &str, gw: &str) -> Result<()> { +fn set_dns( + iface: &Iface, + take_over_dns: bool, + name: &str, + network_domain: &str, + gw: &str, +) -> Result<()> { error!("network_domain = {}", network_domain); if iface.has_resolvectl { add_resolvectl(name, network_domain)?; @@ -941,7 +765,7 @@ fn set_dns(iface: &Iface, take_over_dns: bool, name: &str, network_domain: &str, pub fn restore_dns(take_over_dns: bool) -> Result<()> { let eee = get_edge(); - if !eee.device.has_resolvectl && take_over_dns{ + if !eee.device.has_resolvectl && take_over_dns { // should restore /etc/resolv.conf restore_resolv_conf()?; } @@ -1126,9 +950,11 @@ pub fn del_route(net: &Ipv4Net, gw: &Ipv4Addr) -> Result<()> { .arg(net.to_string()) .arg("gw") .arg(gw.to_string()) - .output()?.status.success() { - - return Err(SDLanError::IOError("failed to delete route".to_owned())) + .output()? + .status + .success() + { + return Err(SDLanError::IOError("failed to delete route".to_owned())); } Ok(()) @@ -1141,8 +967,11 @@ pub fn add_route(net: &Ipv4Net, gw: &Ipv4Addr, _ifidx: u32) -> Result<()> { .arg(net.to_string()) .arg("gw") .arg(gw.to_string()) - .output()?.status.success() { - return Err(SDLanError::IOError("failed to delete route".to_owned())) + .output()? + .status + .success() + { + return Err(SDLanError::IOError("failed to delete route".to_owned())); } Ok(()) @@ -1152,9 +981,13 @@ pub fn set_disallow_routing() -> Result<()> { if !Command::new("sysctl") .arg("-w") .arg("net.ipv4.ip_forward=0") - .output()?.status.success() { - - return Err(SDLanError::IOError("failed to set ip_forward to 0".to_owned())) + .output()? + .status + .success() + { + return Err(SDLanError::IOError( + "failed to set ip_forward to 0".to_owned(), + )); } if !Command::new("iptables") @@ -1164,20 +997,29 @@ pub fn set_disallow_routing() -> Result<()> { .arg("POSTROUTING") .arg("-j") .arg("MASQUERADE") - .output()?.status.success() { - - return Err(SDLanError::IOError("failed to delete masquerade".to_owned())) + .output()? + .status + .success() + { + return Err(SDLanError::IOError( + "failed to delete masquerade".to_owned(), + )); } Ok(()) } -pub fn set_allow_routing() -> Result<()>{ +pub fn set_allow_routing() -> Result<()> { if !Command::new("sysctl") .arg("-w") .arg("net.ipv4.ip_forward=1") - .output()?.status.success() { - return Err(SDLanError::IOError("failed to set ip_forward to 1".to_owned())) + .output()? + .status + .success() + { + return Err(SDLanError::IOError( + "failed to set ip_forward to 1".to_owned(), + )); } if !Command::new("iptables") @@ -1187,9 +1029,11 @@ pub fn set_allow_routing() -> Result<()>{ .arg("POSTROUTING") .arg("-j") .arg("MASQUERADE") - .output()?.status.success() { - - return Err(SDLanError::IOError("failed to clear masquerade".to_owned())) + .output()? + .status + .success() + { + return Err(SDLanError::IOError("failed to clear masquerade".to_owned())); } if !Command::new("iptables") @@ -1199,8 +1043,11 @@ pub fn set_allow_routing() -> Result<()>{ .arg("POSTROUTING") .arg("-j") .arg("MASQUERADE") - .output()?.status.success() { - return Err(SDLanError::IOError("failed to add masquerade".to_owned())) + .output()? + .status + .success() + { + return Err(SDLanError::IOError("failed to add masquerade".to_owned())); } Ok(()) } @@ -1242,11 +1089,11 @@ pub async fn arp_reply_arrived(edge: &Node, data: SdlArpResponse) { let src_ip = data.origin_ip; - write_arp_to_device(edge, src_mac, src_ip); + write_arp_to_device(edge, src_mac, src_ip).await; } #[cfg(not(feature = "tun"))] -pub fn write_arp_to_device(edge: &Node, src_mac: Mac, src_ip: u32) { +pub async fn write_arp_to_device(edge: &Node, src_mac: Mac, src_ip: u32) { let dst_mac = edge.device_config.get_mac(); let dst_ip = edge.device_config.get_ip(); @@ -1271,7 +1118,7 @@ pub fn write_arp_to_device(edge: &Node, src_mac: Mac, src_ip: u32) { }; let data = hdr.marshal_to_bytes(); - if let Err(_e) = edge.device.send(&data) { + if let Err(_e) = edge.device.send(&data).await { error!("failed to write arp response to device"); } } diff --git a/src/network/tun_win.rs b/src/network/tun_win.rs index 637f922..f865426 100755 --- a/src/network/tun_win.rs +++ b/src/network/tun_win.rs @@ -19,7 +19,7 @@ use wintun; use crate::network::{ form_ethernet_packet, generate_arp_request, parse_dns_payload, send_packet_to_net, ArpHdr, - Node, ARP_REPLY, ARP_REQUEST, DNS_IP, + Node, ARP_REPLY, ARP_REQUEST, DNS_IP, LAYER, }; use crate::pb::{encode_to_udp_message, SdlArpResponse, SdlData}; use crate::tcp::PacketType; @@ -40,7 +40,8 @@ impl Iface { let dev = tun_rs::DeviceBuilder::new() .wintun_file(path.to_string()) .name(name) - .layer(tun_rs::Layer::L3) + .layer(LAYER) + .mtu(1280) .build_async() .expect("failed to create tun"); diff --git a/src/network/tuntap.rs b/src/network/tuntap.rs index adaae6e..7d70e1d 100755 --- a/src/network/tuntap.rs +++ b/src/network/tuntap.rs @@ -8,9 +8,17 @@ use sdlan_sn_rs::{ utils::{get_current_timestamp, ip_to_string, Mac, Result}, }; +#[cfg(feature = "tun")] +pub const LAYER: tun_rs::Layer = tun_rs::Layer::L3; + +#[cfg(not(feature = "tun"))] +pub const LAYER: tun_rs::Layer = tun_rs::Layer::L2; + use tracing::{debug, warn}; use tracing::error; +#[cfg(feature = "tun")] +use tun_rs::Layer; use crate::{ network::{form_ethernet_packet, send_packet_to_net, Node, RouteInfo},