punchnet renamed

This commit is contained in:
asxalex 2025-09-30 11:31:05 +08:00
parent 7fa2ffa04d
commit 9a72c29870
17 changed files with 112 additions and 81 deletions

View File

@ -6,3 +6,6 @@ linker = "aarch64-linux-gnu-gcc"
[target.x86_64-pc-windows-gnu] [target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32-gcc" linker = "x86_64-w64-mingw32-gcc"
[build]
target = "x86_64-unknown-linux-gnu"

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ sdlan.exe
*.tar *.tar
*.tar.gz *.tar.gz
*.tgz *.tgz
/punchnet

50
Cargo.lock generated
View File

@ -1297,6 +1297,31 @@ dependencies = [
"prost", "prost",
] ]
[[package]]
name = "punchnet"
version = "1.0.0"
dependencies = [
"crc",
"crc32fast",
"dashmap 6.1.0",
"dns-lookup",
"etherparse",
"futures-util",
"local-ip-address",
"num_enum",
"once_cell",
"prost",
"prost-build",
"rand",
"rsa",
"sdlan-sn-rs",
"structopt",
"tokio",
"tokio-util",
"tracing",
"wintun",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.37" version = "1.0.37"
@ -1438,31 +1463,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sdlan-rs"
version = "0.1.0"
dependencies = [
"crc",
"crc32fast",
"dashmap 6.1.0",
"dns-lookup",
"etherparse",
"futures-util",
"local-ip-address",
"num_enum",
"once_cell",
"prost",
"prost-build",
"rand",
"rsa",
"sdlan-sn-rs",
"structopt",
"tokio",
"tokio-util",
"tracing",
"wintun",
]
[[package]] [[package]]
name = "sdlan-sn-rs" name = "sdlan-sn-rs"
version = "0.1.0" version = "0.1.0"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "sdlan-rs" name = "punchnet"
version = "0.1.0" version = "1.0.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
@ -18,6 +18,7 @@ prost-build = "0.12.6"
rand = "0.8.5" rand = "0.8.5"
rsa = "0.9.6" rsa = "0.9.6"
sdlan-sn-rs = { git = "ssh://git@git.asxalex.pw/sdlan-v2/sdlan-rs.git" } sdlan-sn-rs = { git = "ssh://git@git.asxalex.pw/sdlan-v2/sdlan-rs.git" }
# sdlan-sn-rs = {path = "../sdlan-rs"}
# sdlan-sn-rs = { git = "https://git.asxalex.pw/sdlan-v2/sdlan-rs.git" } # sdlan-sn-rs = { git = "https://git.asxalex.pw/sdlan-v2/sdlan-rs.git" }
structopt = "0.3.26" structopt = "0.3.26"
tokio = { version = "1.38.0", features = ["full"] } tokio = { version = "1.38.0", features = ["full"] }

View File

@ -25,4 +25,7 @@ libtun-so:
cd src/network && gcc -fPIC -shared -o libtuntap.so tuntap.c && cd - cd src/network && gcc -fPIC -shared -o libtuntap.so tuntap.c && cd -
libtun-a: libtun-a:
cd src/network && gcc -c tuntap.c && ar rcs libtuntap.a tuntap.o && cd - cd src/network && gcc -c tuntap.c && ar rcs libtuntap.a tuntap.o && cd -
pack:
tar -czvf punchnet.tar.gz punchnet punchnet.service libtuntap.so install.sh

13
install.sh Normal file
View File

@ -0,0 +1,13 @@
uid=`id -u`
if [ "$uid" != "0" ]; then
echo "need to be root"
exit -1
fi
mkdir -p /usr/local/punchnet
cp punchnet /usr/local/punchnet
cp libtuntap.so /usr/lib/
cp punchnet.service /etc/systemd/system
systemctl enable punchnet
systemctl start punchnet

12
punchnet.service Normal file
View File

@ -0,0 +1,12 @@
[Unit]
Description=punchnet client
Before=network.target network.service
Wants=network.target
[Service]
Type=simple
WorkingDirectory=/usr/local/punchnet
ExecStart=/usr/local/punchnet/punchnet
[Install]
WantedBy=multi-user.target

View File

@ -1,7 +1,7 @@
use sdlan_rs::get_edge; use punchnet::get_edge;
use sdlan_rs::run_sdlan; use punchnet::run_sdlan;
use sdlan_rs::CommandLine; use punchnet::CommandLine;
use sdlan_rs::CommandLineInput; use punchnet::CommandLineInput;
use sdlan_sn_rs::log; use sdlan_sn_rs::log;
use tracing::error; use tracing::error;
@ -23,14 +23,15 @@ async fn main() {
let cmd = CommandLineInput::from_args(); let cmd = CommandLineInput::from_args();
println!("port is {}", cmd.port); // println!("port is {}", cmd.port);
let (tx, rx) = std::sync::mpsc::channel(); let (tx, rx) = std::sync::mpsc::channel();
let server = "punchnet.aioe.tech".to_owned();
let _ = run_sdlan( let _ = run_sdlan(
CommandLine { CommandLine {
sn: "39.98.184.67:1265".to_owned(), sn: server.clone()+":1265",
tcp: "39.98.184.67:18083".to_owned(), tcp: server.clone()+":18083",
nat_server1: "39.98.184.67:1265".to_owned(), nat_server1: server.clone() +":1265",
nat_server2: "47.98.178.3:1265".to_owned(), nat_server2: "47.98.178.3:1265".to_owned(),
_allow_routing: true, _allow_routing: true,
_drop_multicast: true, _drop_multicast: true,
@ -43,7 +44,7 @@ async fn main() {
allow_p2p: true, allow_p2p: true,
}, },
tx, tx,
&sdlan_rs::get_install_channel(), &punchnet::get_install_channel(),
None, None,
) )
.await; .await;

View File

@ -18,7 +18,7 @@ use crate::ConnectionState;
use sdlan_sn_rs::config::AF_INET; use sdlan_sn_rs::config::AF_INET;
use sdlan_sn_rs::peer::{SdlanSock, V6Info}; use sdlan_sn_rs::peer::{SdlanSock, V6Info};
use sdlan_sn_rs::utils::{get_current_timestamp, ip_to_string, is_multi_broadcast, rsa_decrypt}; use sdlan_sn_rs::utils::{get_current_timestamp, ip_to_string, is_multi_broadcast, rsa_decrypt};
use sdlan_sn_rs::utils::{Mac, Result}; use sdlan_sn_rs::utils::{Mac, Result, gen_rsa_keys};
use tokio::io::AsyncWriteExt; use tokio::io::AsyncWriteExt;
use tokio::sync::mpsc::{channel, Receiver, Sender}; use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio_util::sync::CancellationToken; use tokio_util::sync::CancellationToken;
@ -85,7 +85,7 @@ async fn handle_tcp_message(msg: SdlanTcp) {
send_stun_request(edge).await; send_stun_request(edge).await;
tokio::spawn(async { tokio::spawn(async {
let nattype = edge.probe_nat_type().await; let nattype = edge.probe_nat_type().await;
println!("nat type is: {:?}", nattype); // println!("nat type is: {:?}", nattype);
}); });
} }
PacketType::RegisterSuperNAK => { PacketType::RegisterSuperNAK => {
@ -251,7 +251,7 @@ pub async fn async_main(
// let _ = PidRecorder::new(".pid"); // let _ = PidRecorder::new(".pid");
// // gen public key // // gen public key
// gen_rsa_keys(".client"); gen_rsa_keys(".client");
// let mut pubkey = String::new(); // let mut pubkey = String::new();
// File::open(".client/id_rsa.pub")?.read_to_string(&mut pubkey)?; // File::open(".client/id_rsa.pub")?.read_to_string(&mut pubkey)?;
// let privatekey = load_private_key_file(".client/id_rsa")?; // let privatekey = load_private_key_file(".client/id_rsa")?;

View File

@ -143,7 +143,7 @@ pub async fn handle_packet(eee: &'static Node, addr: SocketAddr, buf: &[u8]) ->
error!("failed to decode SdlStunReply"); error!("failed to decode SdlStunReply");
return Ok(()); return Ok(());
}; };
println!("got stun probe reply: {:?}", reply); // println!("got stun probe reply: {:?}", reply);
eee.send_nat_probe_reply(reply.cookie, reply).await; eee.send_nat_probe_reply(reply.cookie, reply).await;
} }
PacketType::StunReply => { PacketType::StunReply => {
@ -779,7 +779,7 @@ async fn send_register(
} }
if need_guess_port { if need_guess_port {
println!("need guess port"); // println!("need guess port");
} }
/* /*
@ -817,16 +817,6 @@ pub fn printHex(key: &[u8]) {
println!("[{}]", value.join(" ")) println!("[{}]", value.join(" "))
} }
fn test_aes(key: &[u8]) {
let content = (1..=10).map(|f| f as u8).collect::<Vec<u8>>();
print!("test aes origin: ");
printHex(&content);
if let Ok(encrypted) = aes_encrypt(key, &content) {
print!("test aes: ");
printHex(&encrypted);
}
}
async fn handle_tun_packet( async fn handle_tun_packet(
eee: &Node, eee: &Node,
_from_sock: &SdlanSock, _from_sock: &SdlanSock,
@ -841,7 +831,7 @@ async fn handle_tun_packet(
return; return;
} }
test_aes(key.as_slice()); // test_aes(key.as_slice());
let origin = aes_decrypt(key.as_slice(), &payload); let origin = aes_decrypt(key.as_slice(), &payload);
if let Err(_e) = origin { if let Err(_e) = origin {
error!("failed to decrypt original data"); error!("failed to decrypt original data");

View File

@ -3,6 +3,8 @@ use std::{net::Ipv4Addr, sync::RwLock};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use sdlan_sn_rs::utils::net_bit_len_to_mask; use sdlan_sn_rs::utils::net_bit_len_to_mask;
use tracing::{debug, error};
#[derive(Debug)] #[derive(Debug)]
pub struct RouteTable { pub struct RouteTable {
content: RwLock<Vec<RouteInfo>>, content: RwLock<Vec<RouteInfo>>,
@ -29,7 +31,7 @@ impl RouteTable {
pub fn get_gateway_ip(&self, net_ip: u32) -> Option<u32> { pub fn get_gateway_ip(&self, net_ip: u32) -> Option<u32> {
let routes = self.content.read().unwrap(); let routes = self.content.read().unwrap();
for route in &*routes { for route in &*routes {
println!("route: {:?}", route.to_string()); debug!("route: {:?}", route.to_string());
if (route.net_ip & route.net_mask) == (net_ip & route.net_mask) { if (route.net_ip & route.net_mask) == (net_ip & route.net_mask) {
// found // found
return Some(route.gateway_ip); return Some(route.gateway_ip);
@ -100,16 +102,17 @@ pub fn parse_route(route: String) -> Vec<(u32, u32, u32)> {
let routes: Vec<_> = route.split(",").collect(); let routes: Vec<_> = route.split(",").collect();
for route in routes { for route in routes {
let route_info: Vec<_> = route.split(";").collect(); let route_info: Vec<_> = route.split(";").collect();
println!("got route info: {:?}", route_info); debug!("got route info: {:?}", route_info);
if route_info.len() != 2 { if route_info.len() != 2 {
println!("route info format error");
error!("route info format error");
continue; continue;
} }
let cidr = route_info[0]; let cidr = route_info[0];
let gateway = route_info[1].parse::<Ipv4Addr>().unwrap(); let gateway = route_info[1].parse::<Ipv4Addr>().unwrap();
let ip_and_mask: Vec<_> = cidr.split("/").collect(); let ip_and_mask: Vec<_> = cidr.split("/").collect();
if ip_and_mask.len() != 2 { if ip_and_mask.len() != 2 {
println!("route info ip/bit error"); error!("route info ip/bit error");
continue; continue;
} }
let ip = ip_and_mask[0].parse::<Ipv4Addr>().unwrap(); let ip = ip_and_mask[0].parse::<Ipv4Addr>().unwrap();

View File

@ -30,7 +30,7 @@ use crate::utils::{caculate_crc, mac_to_string};
use super::device::{DeviceConfig, Mode}; use super::device::{DeviceConfig, Mode};
use super::TunTapPacketHandler; use super::TunTapPacketHandler;
#[link(name = "tuntap")] #[link(name = "tuntap", kind="static")]
extern "C" { extern "C" {
fn tuntap_setup(fd: c_int, name: *mut u8, mode: c_int, packet_info: c_int) -> c_int; fn tuntap_setup(fd: c_int, name: *mut u8, mode: c_int, packet_info: c_int) -> c_int;
} }
@ -117,7 +117,7 @@ impl Iface {
let netbit = ip_to_string(&net_bit_len_to_mask(netbit)); let netbit = ip_to_string(&net_bit_len_to_mask(netbit));
if cfg!(not(feature = "tun")) { if cfg!(not(feature = "tun")) {
println!("set tap device"); info!("set tap device");
let mac = device_config.get_mac(); let mac = device_config.get_mac();
let res = Command::new("ifconfig") let res = Command::new("ifconfig")
.arg(&self.name) .arg(&self.name)
@ -143,7 +143,7 @@ impl Iface {
} }
} }
} else { } else {
println!("set tun device"); info!("set tun device");
let res = Command::new("ifconfig") let res = Command::new("ifconfig")
.arg(&self.name) .arg(&self.name)
.arg(ip) .arg(ip)
@ -271,7 +271,7 @@ impl TunTapPacketHandler for Iface {
// handle ARP REQUEST // handle ARP REQUEST
debug!("got ARP REQUEST"); debug!("got ARP REQUEST");
if arp.ethhdr.dest != [0xff; 6] { if arp.ethhdr.dest != [0xff; 6] {
println!("ARP REQUEST not broadcast"); debug!("ARP REQUEST not broadcast");
return Ok(()); return Ok(());
} }
if dest_ip == self_ip { if dest_ip == self_ip {
@ -310,7 +310,7 @@ impl TunTapPacketHandler for Iface {
let v = encode_to_udp_message(Some(data), PacketType::Data as u8) let v = encode_to_udp_message(Some(data), PacketType::Data as u8)
.unwrap(); .unwrap();
println!( debug!(
"xxxx send arp reply to [{}], selfmac=[{}]", "xxxx send arp reply to [{}], selfmac=[{}]",
mac_to_string(&arp.dhwaddr), mac_to_string(&arp.dhwaddr),
mac_to_string(&self_mac) mac_to_string(&self_mac)
@ -321,9 +321,8 @@ impl TunTapPacketHandler for Iface {
} }
} }
ARP_REPLY => { ARP_REPLY => {
println!("got arp reply",);
println!("mac {:?} is at {:?}", arp.shwaddr, from_ip.to_be_bytes()); debug!("mac {:?} is at {:?}", arp.shwaddr, from_ip.to_be_bytes());
if dest_ip == self_ip { if dest_ip == self_ip {
send_arp_request(ArpRequestInfo::Set { send_arp_request(ArpRequestInfo::Set {
ip: from_ip, ip: from_ip,
@ -334,7 +333,7 @@ impl TunTapPacketHandler for Iface {
} }
} }
_other => { _other => {
println!("unknown arp type info"); error!("unknown arp type info");
} }
} }
} else { } else {
@ -415,7 +414,7 @@ impl TunTapPacketHandler for Iface {
} => { } => {
if do_arp_request { if do_arp_request {
add_to_arp_wait_list(dstip, data); add_to_arp_wait_list(dstip, data);
println!( debug!(
"find ip: {:?} => {:?}", "find ip: {:?} => {:?}",
src.to_be_bytes(), src.to_be_bytes(),
dstip.to_be_bytes() dstip.to_be_bytes()

View File

@ -152,18 +152,18 @@ impl TunTapPacketHandler for Iface {
let mut arp = ArpHdr::from_slice(&data); let mut arp = ArpHdr::from_slice(&data);
let self_ip = edge.device_config.get_ip(); let self_ip = edge.device_config.get_ip();
println!("self_ip: {:?}", self_ip.to_be_bytes()); debug!("self_ip: {:?}", self_ip.to_be_bytes());
let from_ip = ((arp.sipaddr[0] as u32) << 16) + arp.sipaddr[1] as u32; let from_ip = ((arp.sipaddr[0] as u32) << 16) + arp.sipaddr[1] as u32;
println!("from_ip: {:?}", from_ip.to_be_bytes()); debug!("from_ip: {:?}", from_ip.to_be_bytes());
let dest_ip = ((arp.dipaddr[0] as u32) << 16) + arp.dipaddr[1] as u32; let dest_ip = ((arp.dipaddr[0] as u32) << 16) + arp.dipaddr[1] as u32;
println!("dest_ip: {:?}", dest_ip.to_be_bytes()); debug!("dest_ip: {:?}", dest_ip.to_be_bytes());
match arp.opcode { match arp.opcode {
ARP_REQUEST => { ARP_REQUEST => {
// handle ARP REQUEST // handle ARP REQUEST
debug!("got ARP REQUEST"); debug!("got ARP REQUEST");
if arp.ethhdr.dest != [0xff; 6] { if arp.ethhdr.dest != [0xff; 6] {
println!("ARP REQUEST not broadcast"); debug!("ARP REQUEST not broadcast");
return Ok(()); return Ok(());
} }
if dest_ip == self_ip { if dest_ip == self_ip {
@ -201,7 +201,7 @@ impl TunTapPacketHandler for Iface {
let v = encode_to_udp_message(Some(data), PacketType::Data as u8) let v = encode_to_udp_message(Some(data), PacketType::Data as u8)
.unwrap(); .unwrap();
println!( debug!(
"xxxx send arp reply to [{}], selfmac=[{}]", "xxxx send arp reply to [{}], selfmac=[{}]",
mac_to_string(&arp.dhwaddr), mac_to_string(&arp.dhwaddr),
mac_to_string(&self_mac) mac_to_string(&self_mac)
@ -212,9 +212,8 @@ impl TunTapPacketHandler for Iface {
} }
} }
ARP_REPLY => { ARP_REPLY => {
println!("got arp reply",);
println!("mac {:?} is at {:?}", arp.shwaddr, from_ip.to_be_bytes()); debug!("mac {:?} is at {:?}", arp.shwaddr, from_ip.to_be_bytes());
if dest_ip == self_ip { if dest_ip == self_ip {
send_arp_request(ArpRequestInfo::Set { send_arp_request(ArpRequestInfo::Set {
ip: from_ip, ip: from_ip,
@ -225,7 +224,7 @@ impl TunTapPacketHandler for Iface {
} }
} }
_other => { _other => {
println!("unknown arp type info"); error!("unknown arp type info");
} }
} }
} else { } else {
@ -305,7 +304,7 @@ impl TunTapPacketHandler for Iface {
if do_arp_request { if do_arp_request {
add_to_arp_wait_list(dstip, data); add_to_arp_wait_list(dstip, data);
println!( info!(
"find ip: {:?} => {:?}", "find ip: {:?} => {:?}",
src.to_be_bytes(), src.to_be_bytes(),
dstip.to_be_bytes() dstip.to_be_bytes()

View File

@ -8,6 +8,8 @@ use sdlan_sn_rs::{
utils::{aes_encrypt, get_current_timestamp, ip_to_string, Mac}, utils::{aes_encrypt, get_current_timestamp, ip_to_string, Mac},
}; };
use tracing::debug;
use tracing::error; use tracing::error;
use crate::{ use crate::{
@ -59,7 +61,7 @@ impl ArpWaitList {
} }
async fn arp_arrived(&self, ip: u32, mac: Mac) { async fn arp_arrived(&self, ip: u32, mac: Mac) {
println!( debug!(
"arp for {} arrived: {}", "arp for {} arrived: {}",
ip_to_string(&ip), ip_to_string(&ip),
mac_to_string(&mac) mac_to_string(&mac)

View File

@ -297,7 +297,8 @@ impl ReadWriterHandle {
if let Some(msg) = data_from_tcp.recv().await { if let Some(msg) = data_from_tcp.recv().await {
on_message(msg).await; on_message(msg).await;
} else { } else {
eprintln!("data from tcp exited"); error!("data from tcp exited");
// eprintln!("data from tcp exited");
return; return;
} }
} }

View File

@ -2,10 +2,10 @@ use structopt::StructOpt;
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
pub struct CommandLineInput { pub struct CommandLineInput {
#[structopt(long = "token", default_value = "")] #[structopt(long = "token", default_value = "", help="specify a token")]
pub token: String, pub token: String,
#[structopt(short = "p", long = "port", default_value = "0")] #[structopt(short = "p", long = "port", default_value = "0", help="which port to use")]
pub port: u16, pub port: u16,
} }

View File

@ -2,6 +2,7 @@ use std::{
fs::{self, OpenOptions}, fs::{self, OpenOptions},
io::Write, io::Write,
}; };
use tracing::{debug, error};
pub struct PidRecorder(String); pub struct PidRecorder(String);
@ -19,7 +20,8 @@ impl PidRecorder {
.expect("failed to write"); .expect("failed to write");
} }
Err(e) => { Err(e) => {
eprintln!("failed to open pid file: {}", e); error!("failed to open pid file: {}", e);
// eprintln!("failed to open pid file: {}", e);
} }
} }
@ -30,7 +32,8 @@ impl PidRecorder {
impl Drop for PidRecorder { impl Drop for PidRecorder {
fn drop(&mut self) { fn drop(&mut self) {
if let Err(e) = fs::remove_file(&self.0) { if let Err(e) = fs::remove_file(&self.0) {
eprintln!("failed to remove pid file: {}", e); error!("failed to remove pid file: {}", e);
// eprintln!("failed to remove pid file: {}", e);
} }
} }
} }