added exclusive_tcp, and error_report

This commit is contained in:
alex 2026-05-04 15:47:30 +08:00
parent a3977ba52a
commit 7767096909
10 changed files with 132 additions and 39 deletions

View File

@ -6,7 +6,7 @@ Wants=network.target
[Service]
Type=simple
WorkingDirectory=/usr/local/punchnet
ExecStart=/usr/local/punchnet/punchnet
ExecStart=/usr/local/punchnet/punchnet start
[Install]
WantedBy=multi-user.target

View File

@ -169,10 +169,23 @@ where T: Serialize + HMacCalculator,
};
// println!("status: {}", response.status());
let text = response.text().await.unwrap();
// let text = response.text().await.unwrap();
let text = match response.text().await {
Ok(text) => text,
Err(e) => {
return Err(SDLanError::IOError(format!("failed to get response text: {}", e)))
}
};
let data = match serde_json::from_str(&text) {
Ok(data) => data,
Err(e) => {
return Err(SDLanError::IOError(format!("failed to deserialize text: {}", e)))
}
};
// println!("got test: {}", text);
let data = serde_json::from_str(&text).unwrap();
// let data = serde_json::from_str(&text).unwrap();
// println!("response: {}", response.text().await.unwrap());
// let Ok(data) = response.json().await else {

View File

@ -167,7 +167,7 @@ async fn daemonize_me(
println!("hostname = {:?}", hostname);
*/
let _ = run_sdlan(
if let Err(e) = run_sdlan(
client_id,
mac,
CommandLine {
@ -196,8 +196,11 @@ async fn daemonize_me(
server,
Some(self_host_name),
None,
None,
)
.await;
.await {
panic!("failed to run_sdlan: {}", e.as_str());
};
let _ = rx.recv();

View File

@ -17,7 +17,7 @@ pub use network::{async_main, init_edge, NodeConfig, restore_dns};
pub use network::{RouteInfo, set_route_from_net};
use sdlan_sn_rs::utils::{Mac, save_to_file};
use serde::{Deserialize, Serialize};
use tokio::net::UdpSocket;
use tokio::net::{TcpListener, UdpSocket};
use tokio::sync::mpsc::{channel, Sender};
use tokio_util::sync::CancellationToken;
use tracing::{debug, error};
@ -59,13 +59,15 @@ pub async fn run_sdlan(
server_ip: String,
hostname: Option<String>,
connecting_chan: Option<Sender<ConnectionInfo>>, // start_stop_sender: Sender<String>,
// start_stop_receiver: Receiver<String>,
connecting_chan: Option<Sender<ConnectionInfo>>,
// report error to
error_report_channel: Option<Sender<ErrorReport>>,
) -> Result<()> {
let (start_stop_sender, start_stop_chan) = channel(20);
// let edge_uuid = create_or_load_uuid(&format!("{}/.id", get_base_dir()), None)?;
let node_conf = parse_config(edge_uuid, &args).await?;
let hostfile = format!("{}/.host", get_base_dir());
let host = create_or_load_uuid(&hostfile, Some(8))?;
@ -76,7 +78,19 @@ pub async fn run_sdlan(
let sock_dns = Arc::new(UdpSocket::bind("0.0.0.0:0").await?);
let udp_sock_for_global_dns = Arc::new(UdpSocket::bind("0.0.0.0:0").await?);
if let Err(e) = init_edge(
let exclusive_tcp = match TcpListener::bind("127.0.0.1:7653").await {
Ok(tcp) => tcp,
Err(e) => {
if let Some(ref chan) = error_report_channel {
chan.send(ErrorReport { severity: ErrorSeverity::Panic, message: "bind tcp failed, is process already running?".to_string() }).await;
return Err(e.into());
} else {
panic!("new iface failed: {}", e.to_string());
}
}
};
init_edge(
// &args.token,
// &args.network_code,
&args,
@ -91,11 +105,11 @@ pub async fn run_sdlan(
hostname,
server_ip,
install_channel.to_owned(),
error_report_channel,
exclusive_tcp,
)
.await
{
panic!("failed to init edge: {:?}", e);
}
.await?;
let _ = sender.send(true);
debug!("edge inited");

View File

@ -12,7 +12,7 @@ use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, AtomicU8, Ordering};
use std::sync::{Arc, Mutex, RwLock};
use std::time::Duration;
use tokio::io::AsyncReadExt;
use tokio::net::UdpSocket;
use tokio::net::{TcpListener, UdpSocket};
use tokio::sync::mpsc::Sender;
use tracing::{debug, error, warn};
@ -25,8 +25,7 @@ use crate::quic::quic_init;
use crate::tcp::{get_quic_write_conn, NatType, PacketType, StunProbeAttr};
use crate::utils::Socket;
use crate::{
get_base_dir, get_default_interface, CommandLine, ConnectionInfo, DNSMatcher, MyEncryptor,
RuleCache,
CommandLine, ConnectionInfo, DNSMatcher, ErrorReport, ErrorSeverity, MyEncryptor, RuleCache, get_base_dir, get_default_interface
};
use sdlan_sn_rs::peer::{IpSubnet, V6Info};
@ -57,6 +56,8 @@ pub async fn init_edge(
hostname: String,
server_ip: String,
install_channel: String,
error_report_channel: Option<Sender<ErrorReport>>,
exclusive_tcp: TcpListener,
) -> Result<()> {
// gen public key
let rsa_path = format!("{}/.client", get_base_dir());
@ -108,6 +109,27 @@ pub async fn init_edge(
// TODO: set the sn's tcp socket
// 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) {
Ok(iface) => iface,
Err(e) => {
if let Some(ref chan) = error_report_channel {
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,
@ -128,6 +150,9 @@ pub async fn init_edge(
server_ip,
install_channel,
args.take_dns,
error_report_channel,
iface,
exclusive_tcp,
);
edge.route_table
@ -288,9 +313,13 @@ pub struct Node {
nat_cookie: AtomicU32,
error_report_channel: Option<Sender<ErrorReport>>,
//cookie_match: DashMap<u32, oneshot::Sender<SdlStunProbeReply>>,
pub cookie_match: Queryer,
// packet_id_match: DashMap<u32, oneshot::Sender<RegisterSuperFeedback>>,
exclusive_tcp: TcpListener,
}
unsafe impl Sync for Node {}
@ -442,12 +471,11 @@ impl Node {
server_ip: String,
install_channel: String,
take_over_dns: bool,
// 是否需要上报错误信息
error_report_info: Option<Sender<ErrorReport>>,
virtual_iface: Iface,
tcp_listener: TcpListener,
) -> Self {
let mode = if cfg!(not(feature = "tun")) {
Mode::Tap
} else {
Mode::Tun
};
Self {
#[cfg(any(feature = "tun", target_os = "windows"))]
@ -485,7 +513,7 @@ impl Node {
nat_type: Mutex::new(NatType::Blocked),
device_config: DeviceConfig::new(mac, mtu),
device: new_iface("dev", mode),
device: virtual_iface,
authorized: AtomicBool::new(false),
// encrypt_key: RwLock::new(Arc::new(Vec::new())),
@ -519,9 +547,11 @@ impl Node {
// packet_id_match: DashMap::new(),
nat_cookie: AtomicU32::new(1),
cookie_match: Queryer::new(),
error_report_channel: error_report_info,
server_ip,
install_channel,
take_over_dns,
exclusive_tcp: tcp_listener,
}
}

View File

@ -24,7 +24,7 @@ use std::ptr::null_mut;
use std::sync::atomic::Ordering;
use sdlan_sn_rs::utils::Result;
use std::io::{BufRead, BufReader, Read, Write};
use std::io::{BufRead, BufReader, ErrorKind, Read, Write};
use std::os::fd::AsRawFd;
use std::process::Command;
@ -66,12 +66,13 @@ pub struct Iface {
has_resolvectl: bool,
}
pub fn new_iface(tunname: &str, mode: Mode) -> Iface {
pub fn new_iface(tunname: &str, mode: Mode) -> std::io::Result<Iface> {
match Iface::without_packet_info(tunname, mode) {
Err(e) => {
panic!("failed to create tun: {}", e.as_str());
error!("failed to create tun: {}", e.as_str());
Err(std::io::Error::new(ErrorKind::Other, "failed to create virtial device, is run with root?"))
}
Ok(iface) => iface,
Ok(iface) => Ok(iface),
}
}

View File

@ -55,10 +55,12 @@ impl Iface {
}
pub fn send(&self, content: &[u8]) -> std::io::Result<usize> {
let mut pkt = self
let Ok(mut pkt) = self
.session
.allocate_send_packet(content.len() as u16)
.unwrap();
.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);
self.session.send_packet(pkt);
@ -727,28 +729,35 @@ impl TunTapPacketHandler for Iface {
}*/
}
fn create_wintun(path: &str, name: &str) -> Iface {
fn create_wintun(path: &str, name: &str) -> std::io::Result<Iface> {
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) => wintun::Adapter::create(&wt, name, "Example", None)
.expect("failed to create tun adapter"),
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"));
};
adapt
}
};
let idx = adapter
.get_adapter_index()
.expect("failed to get adapter index");
// println!("idx = {}", idx);
let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY).unwrap());
Iface {
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?"));
};
let session = Arc::new(sess);
Ok(Iface {
if_idx: idx,
_adapter: adapter,
session,
name: name.to_owned(),
}
})
}
pub fn new_iface(name: &str, _mode: Mode) -> Iface {
pub fn new_iface(name: &str, _mode: Mode) -> std::io::Result<Iface> {
create_wintun("./wintun.dll", name)
// Ok(Box::new(create_wintun("/path/to/file")))
}

View File

@ -147,6 +147,8 @@ pub fn load_private_key_from_pem(path: impl AsRef<Path>) -> Option<PrivateKeyDer
return None;
};
let mut reader = BufReader::new(file);
let key = private_key(&mut reader).unwrap();
key
if let Ok(key) = private_key(&mut reader) {
return key
}
None
}

17
src/utils/error_report.rs Normal file
View File

@ -0,0 +1,17 @@
use serde::Serialize;
#[derive(Debug, Serialize)]
#[repr(u8)]
pub enum ErrorSeverity {
Panic,
Error,
Warning,
Info,
Log,
}
#[derive(Debug, Serialize)]
pub struct ErrorReport {
pub severity: ErrorSeverity,
pub message: String,
}

View File

@ -4,6 +4,7 @@ mod encrypter;
mod system_action;
mod file_configuration;
mod dns;
mod error_report;
use std::{fs::OpenOptions, io::Write, net::Ipv4Addr, path::Path};
use tracing::error;
@ -13,6 +14,7 @@ pub use command::*;
pub use acl_session::*;
pub use system_action::*;
pub use dns::*;
pub use error_report::*;
mod socks;
use rand::Rng;
@ -52,7 +54,9 @@ pub fn ip_string_to_u32(ip: &str) -> Result<u32> {
pub fn get_access_token() -> Option<CachedLoginInfo> {
let path = format!("{}/.access_token", get_base_dir());
if let Ok(content) = std::fs::read(&path) {
let data = serde_json::from_slice(&content).unwrap();
let Ok(data) = serde_json::from_slice(&content) else {
return None;
};
return Some(data);
}
None