Compare commits

...

2 Commits

Author SHA1 Message Date
372afd470b token login 2026-03-18 22:36:51 +08:00
c6df26ac85 fix some warnings 2026-03-18 16:37:40 +08:00
14 changed files with 99 additions and 36 deletions

View File

@ -1,4 +1,4 @@
{ {
"rust-analyzer.cargo.target": "x86_64-pc-windows-gnu", // "rust-analyzer.cargo.target": "x86_64-pc-windows-gnu",
// "rust-analyzer.cargo.features": ["tun"] // "rust-analyzer.cargo.features": ["tun"]
} }

3
Cargo.lock generated
View File

@ -2075,8 +2075,11 @@ dependencies = [
"dns-lookup", "dns-lookup",
"etherparse", "etherparse",
"futures-util", "futures-util",
"hex",
"hmac",
"libc", "libc",
"local-ip-address", "local-ip-address",
"md-5",
"myactor", "myactor",
"num_enum", "num_enum",
"once_cell", "once_cell",

View File

@ -36,6 +36,9 @@ clap = { version = "4.5.60", features = ["derive", "env"] }
rpassword = "7.4.0" rpassword = "7.4.0"
serde_json = "1.0.149" serde_json = "1.0.149"
chacha20poly1305 = "0.10.1" chacha20poly1305 = "0.10.1"
hmac = "0.12.1"
md-5 = "0.10.6"
hex = "0.4.3"
# rolling-file = { path = "../rolling-file" } # rolling-file = { path = "../rolling-file" }
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]

View File

@ -1,9 +1,22 @@
use hmac::{Hmac, Mac as HamcMac};
use punchnet::TokenLogin;
use reqwest::Client; use reqwest::Client;
use sdlan_sn_rs::utils::{Mac, Result, SDLanError}; use sdlan_sn_rs::utils::{Mac, Result, SDLanError};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use md5::Md5;
pub const TEST_PREFIX: &'static str = "https://punchnet.s5s8.com/api"; pub const TEST_PREFIX: &'static str = "https://punchnet.s5s8.com/api";
const DIGEST_KEY: &'static str = "H6p*2RfEu4ITcL";
type HmacMd5 = Hmac<Md5>;
trait HMacCalculator {
fn calculate_hmac(&self) -> Result<String>;
}
fn calculate_hmac<T: HMacCalculator>(cal: T) -> Result<String> {
cal.calculate_hmac()
}
#[derive(Serialize)] #[derive(Serialize)]
struct TokenLoginData<'a> { struct TokenLoginData<'a> {
@ -14,6 +27,29 @@ struct TokenLoginData<'a> {
version: &'a str, version: &'a str,
} }
fn do_calculate(data: &[u8]) -> Result<String>{
let Ok(mut mac) = HmacMd5::new_from_slice(DIGEST_KEY.as_bytes()) else {
return Err(SDLanError::IOError("failed to new hmac".to_owned()));
};
mac.update(data);
let result = mac.finalize().into_bytes();
Ok(hex::encode(result))
}
impl <'a> HMacCalculator for TokenLoginData<'a> {
fn calculate_hmac(&self) -> Result<String> {
let data = format!("client_id={}&mac={}&system={}&token={}&version={}",
self.client_id,
self.mac,
self.system,
self.token,
self.version,
);
do_calculate(data.as_bytes())
}
}
#[derive(Serialize)] #[derive(Serialize)]
struct UserPassLoginData<'a> { struct UserPassLoginData<'a> {
client_id: &'a str, client_id: &'a str,
@ -24,6 +60,20 @@ struct UserPassLoginData<'a> {
version: &'a str, version: &'a str,
} }
impl HMacCalculator for UserPassLoginData<'_> {
fn calculate_hmac(&self) -> Result<String> {
let data = format!("client_id={}&mac={}&password={}&system={}&username={}&version={}",
self.client_id,
self.mac,
self.password,
self.system,
self.username,
self.version,
);
do_calculate(data.as_bytes())
}
}
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct LoginResponse { pub struct LoginResponse {
pub code: i32, pub code: i32,
@ -54,14 +104,18 @@ async fn post_with_data<T, R>(
url: &str, url: &str,
data: T, data: T,
) -> Result<R> ) -> Result<R>
where T: Serialize, where T: Serialize + HMacCalculator,
R: for<'de> Deserialize<'de> R: for<'de> Deserialize<'de>
{ {
let client = Client::new(); let client = Client::new();
let Ok(hmac) = data.calculate_hmac() else {
return Err(SDLanError::IOError("failed to calculate hmac".to_owned()));
};
let Ok(response) = client let Ok(response) = client
.post(url) .post(url)
.header("X-sign", hmac)
.json(&data) .json(&data)
.send() .send()
.await else { .await else {
@ -70,7 +124,6 @@ where T: Serialize,
// println!("status: {}", response.status()); // println!("status: {}", response.status());
let text = response.text().await.unwrap(); let text = response.text().await.unwrap();
// println!("text = {}", text);
let data = serde_json::from_str(&text).unwrap(); let data = serde_json::from_str(&text).unwrap();
@ -137,6 +190,16 @@ struct ConnectDisconnectRequest<'a> {
access_token: &'a str, access_token: &'a str,
} }
impl HMacCalculator for ConnectDisconnectRequest<'_> {
fn calculate_hmac(&self) -> Result<String> {
let data = format!("access_token={}&client_id={}",
self.access_token,
self.client_id
);
do_calculate(data.as_bytes())
}
}
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct ConnectResponse { pub struct ConnectResponse {
pub code: i32, pub code: i32,
@ -210,6 +273,17 @@ struct GetResourceRequest<'a> {
id: i32, id: i32,
} }
impl HMacCalculator for GetResourceRequest<'_> {
fn calculate_hmac(&self) -> Result<String> {
let data = format!("access_token={}&client_id={}&id={}",
self.access_token,
self.client_id,
self.id,
);
do_calculate(data.as_bytes())
}
}
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct GetResourceResponse { pub struct GetResourceResponse {
pub code: i32, pub code: i32,

View File

@ -354,7 +354,7 @@ fn main() {
} }
} }
let should_daemonize = true; let should_daemonize = false;
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
if should_daemonize { if should_daemonize {

View File

@ -1,4 +1,4 @@
use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::atomic::{Ordering};
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
@ -15,7 +15,6 @@ use sdlan_sn_rs::utils::{get_current_timestamp, is_multi_broadcast};
use sdlan_sn_rs::utils::{Mac, Result}; use sdlan_sn_rs::utils::{Mac, Result};
use tokio::net::{UdpSocket}; use tokio::net::{UdpSocket};
use tokio::sync::mpsc::{channel, Receiver, Sender}; use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio::time::sleep;
use tokio_util::sync::CancellationToken; use tokio_util::sync::CancellationToken;
use super::{Node, StartStopInfo}; use super::{Node, StartStopInfo};
@ -118,17 +117,6 @@ pub async fn async_main(
Ok(()) Ok(())
} }
async fn run_quic_loop(
edge: &Node,
quic_addr: &str,
pong_time: Arc<AtomicU64>,
start_stop_chan: Receiver<StartStopInfo>,
connecting_chan: Sender<ConnectionInfo>,
ipv6_ntework_restarter: Option<Sender<bool>>
) {
}
async fn run_edge_loop(eee: &'static Node, cancel: CancellationToken) { async fn run_edge_loop(eee: &'static Node, cancel: CancellationToken) {
ping_to_sn().await; ping_to_sn().await;
{ {
@ -251,7 +239,7 @@ async fn loop_tap(eee: &'static Node, cancel: CancellationToken) {
packet.push(0x00); packet.push(0x00);
packet.extend_from_slice(&reply); packet.extend_from_slice(&reply);
/// TODO: check the packet should // TODO: check the packet should
if let Err(_e) = eee.device.handle_packet_from_net(&packet).await { if let Err(_e) = eee.device.handle_packet_from_net(&packet).await {
error!("failed to write dns packet to device"); error!("failed to write dns packet to device");
} }

View File

@ -1,5 +1,3 @@
use std::sync::RwLock;
use crate::utils::mac_to_string; use crate::utils::mac_to_string;
use sdlan_sn_rs::{peer::IpSubnet, utils::Mac}; use sdlan_sn_rs::{peer::IpSubnet, utils::Mac};
use tracing::debug; use tracing::debug;

View File

@ -13,12 +13,12 @@ use tokio::sync::oneshot;
use tracing::{debug, error}; use tracing::{debug, error};
use crate::quic::quic_init; use crate::quic::quic_init;
use crate::{ConnectionInfo, Encryptor, MyEncryptor, get_base_dir}; use crate::{ConnectionInfo, MyEncryptor, get_base_dir};
use crate::pb::{ use crate::pb::{
encode_to_tcp_message, encode_to_udp_message, SdlEmpty, SdlStunProbe, SdlStunProbeReply, encode_to_tcp_message, encode_to_udp_message, SdlEmpty, SdlStunProbe, SdlStunProbeReply,
}; };
use crate::tcp::{NatType, PacketType, StunProbeAttr, get_quic_write_conn}; use crate::tcp::{NatType, PacketType, StunProbeAttr, get_quic_write_conn};
use crate::utils::{Socket, create_or_load_mac}; use crate::utils::{Socket};
use sdlan_sn_rs::peer::{IpSubnet, V6Info}; use sdlan_sn_rs::peer::{IpSubnet, V6Info};

View File

@ -1,6 +1,5 @@
use std::{net::SocketAddr, sync::atomic::Ordering, time::Duration}; use std::{net::SocketAddr, sync::atomic::Ordering, time::Duration};
use crate::network::IdentityID;
use crate::pb::SdlPolicyRequest; use crate::pb::SdlPolicyRequest;
use crate::tcp::{NatType, get_quic_write_conn, is_identity_ok}; use crate::tcp::{NatType, get_quic_write_conn, is_identity_ok};
use crate::{network::TunTapPacketHandler, utils::mac_to_string}; use crate::{network::TunTapPacketHandler, utils::mac_to_string};

View File

@ -1,7 +1,7 @@
use etherparse::{Ethernet2Header}; use etherparse::{Ethernet2Header};
use sdlan_sn_rs::config::SDLAN_DEFAULT_TTL; use sdlan_sn_rs::config::SDLAN_DEFAULT_TTL;
use sdlan_sn_rs::utils::{ use sdlan_sn_rs::utils::{
aes_encrypt, ip_to_string, is_ipv6_multicast, net_bit_len_to_mask, ip_to_string, is_ipv6_multicast, net_bit_len_to_mask,
SDLanError, SDLanError,
}; };
use std::ffi::CStr; use std::ffi::CStr;

View File

@ -5,7 +5,7 @@ use dashmap::DashMap;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use sdlan_sn_rs::{ use sdlan_sn_rs::{
config::SDLAN_DEFAULT_TTL, config::SDLAN_DEFAULT_TTL,
utils::{aes_encrypt, get_current_timestamp, ip_to_string, Mac}, utils::{get_current_timestamp, ip_to_string, Mac},
}; };
use tracing::debug; use tracing::debug;

View File

@ -1,6 +1,6 @@
use std::{collections::{HashMap, HashSet}, sync::{OnceLock, atomic::{AtomicU64, Ordering}}, time::{SystemTime, UNIX_EPOCH}}; use std::{collections::{HashMap, HashSet}, sync::{OnceLock}, time::{SystemTime, UNIX_EPOCH}};
use dashmap::{DashMap, DashSet}; use dashmap::{DashMap};
use tracing::debug; use tracing::debug;
type IdentityID = u32; type IdentityID = u32;

View File

@ -225,7 +225,7 @@ async fn handle_tcp_message(msg: SdlanTcp) {
}; };
let data = hdr.marshal_to_bytes(); let data = hdr.marshal_to_bytes();
if let Err(e) = edge.device.send(&data) { if let Err(_e) = edge.device.send(&data) {
error!("failed to write arp response to device"); error!("failed to write arp response to device");
} }
} }
@ -692,7 +692,7 @@ async fn on_disconnected_callback() {
*edge.encryptor.write().unwrap() = MyEncryptor::Invalid; *edge.encryptor.write().unwrap() = MyEncryptor::Invalid;
} }
async fn on_connected_callback(local_ip: Option<IpAddr>, stream: &mut SendStream, pkt_id: Option<u32>) { async fn on_connected_callback(local_ip: Option<IpAddr>, stream: &mut SendStream, _pkt_id: Option<u32>) {
let edge = get_edge(); let edge = get_edge();
// let installed_channel = install_channel.to_owned(); // let installed_channel = install_channel.to_owned();

View File

@ -1,12 +1,10 @@
use std::{sync::{Arc, OnceLock, RwLock, atomic::{AtomicBool, AtomicU32, Ordering}}, time::{SystemTime, UNIX_EPOCH}}; use std::{sync::atomic::{AtomicU32, Ordering}, time::{SystemTime, UNIX_EPOCH}};
use tracing::debug;
use chacha20poly1305::{KeyInit, aead::Aead}; use chacha20poly1305::{KeyInit, aead::Aead};
use dashmap::DashSet;
use sdlan_sn_rs::utils::{Result, SDLanError, aes_decrypt, aes_encrypt}; use sdlan_sn_rs::utils::{Result, SDLanError, aes_decrypt, aes_encrypt};
const CounterMask: u32 = (1<<24) - 1; const COUNTER_MASK: u32 = (1<<24) - 1;
pub trait Encryptor { pub trait Encryptor {
fn is_setted(&self) -> bool; fn is_setted(&self) -> bool;
@ -107,7 +105,7 @@ impl Encryptor for Chacha20Encryptor {
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() as u64; let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() as u64;
let next_counter = self.next_counter.fetch_update(Ordering::Release, Ordering::Acquire, |current| { let next_counter = self.next_counter.fetch_update(Ordering::Release, Ordering::Acquire, |current| {
Some((current + 1) & CounterMask) Some((current + 1) & COUNTER_MASK)
}).unwrap() as u64; }).unwrap() as u64;
let mut nonce = Vec::new(); let mut nonce = Vec::new();