From 6f895c3404712a6c0b2f56673c16a483b4d08c4c Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 25 Feb 2026 15:30:26 +0800 Subject: [PATCH] changed to new message.proto, and use Bytes for SDLData's data --- Cargo.lock | 5 +- Cargo.toml | 1 + message.proto | 171 ++++++++++++++++++------------ src/bin/build_pb/main.rs | 1 + src/bin/punchnet/main.rs | 10 +- src/network/node.rs | 117 ++++++++++++++++++--- src/network/packet.rs | 1 + src/network/tun_linux.rs | 7 +- src/network/tuntap.rs | 6 +- src/pb/message.rs | 220 ++++++++++++++++++++++++--------------- src/tcp/tcp_conn.rs | 39 ++++--- src/utils/mod.rs | 36 ++++++- 12 files changed, 423 insertions(+), 191 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9fa481..eb7219c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -224,9 +224,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "c2rust-bitfields" @@ -1868,6 +1868,7 @@ dependencies = [ name = "punchnet" version = "1.0.0" dependencies = [ + "bytes", "cargo-deb", "crc", "crc32fast", diff --git a/Cargo.toml b/Cargo.toml index 713bbda..5d1f483 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ tokio = { version = "1.38.0", features = ["full"] } tokio-util = "0.7.11" tracing = "0.1.40" myactor = { git = "https://gitea.s5s8.com/rust/actor-rs.git" } +bytes = "1.11.1" # rolling-file = { path = "../rolling-file" } [target.'cfg(unix)'.dependencies] diff --git a/message.proto b/message.proto index 96eb93c..6fe18eb 100644 --- a/message.proto +++ b/message.proto @@ -1,5 +1,7 @@ syntax = "proto3"; +package message; + // 基础公共类型定义 message SDLV4Info { @@ -13,54 +15,101 @@ message SDLV6Info { bytes v6 = 2; } -// 设备网络地址信息 -message SDLDevAddr { - uint32 network_id = 1; - bytes mac = 2; - uint32 net_addr = 3; - uint32 net_bit_len = 4; - string network_domain = 5; -} +// 和super之间采用了quic协议通讯 +// 传输层采用: <> -// tcp通讯消息 -message SDLEmpty { - -} - -message SDLRegisterSuper { +message SDLWelcome { uint32 version = 1; - string installed_channel = 2; - string client_id = 3; - SDLDevAddr dev_addr = 4; - string pub_key = 5; - string token = 6; - string network_code = 7; - string hostname = 8; + // 服务器允许的最大双向流 + uint32 max_bidi_streams = 2; + // 服务器允许的最大包 + uint32 max_packet_size = 3; + // 心跳包的间隔 + uint32 heartbeat_sec = 4; } +// quic 通讯消息 +message SDLEmpty { + uint32 pkt_id = 1; +} + +// 这里修改成了扁平的结构, 否则有些字段不好找放的位置 +message SDLRegisterSuper { + uint32 pkt_id = 1; + string client_id = 2; + // 网络地址信息已经有https请求分配了 + // 注册的时候需要带上(network_id, mac, ip, mask_len, hostname) + uint32 network_id = 3; + bytes mac = 4; + uint32 ip = 5; + uint32 mask_len = 6; + string hostname = 7; + + string pub_key = 8; + // 客户端使用http协议请求后端,通过token或者账号密码登录时, 统一返回一个access_token; + // RegisterSuper的时候,验证凭证是否合法 (access_token) + string access_token = 9; +} + +// 客户端的升级逻辑,在https的接口里面去完成 +// 部分逻辑会脱离quic去通讯,增加session_token校验 message SDLRegisterSuperAck { - SDLDevAddr dev_addr = 1; + uint32 pkt_id = 1; bytes aes_key = 2; - uint32 upgrade_type = 3; - optional string upgrade_prompt = 4; - optional string upgrade_address = 5; + bytes session_token = 3; } message SDLRegisterSuperNak { - uint32 error_code = 1; - string error_message = 2; + uint32 pkt_id = 1; + uint32 error_code = 2; + string error_message = 3; } // 网络地址查询 message SDLQueryInfo { - bytes dst_mac = 1; + uint32 pkt_id = 1; + bytes dst_mac = 2; } message SDLPeerInfo { - bytes dst_mac = 1; - SDLV4Info v4_info = 2; - optional SDLV6Info v6_info = 3; + uint32 pkt_id = 1; + bytes dst_mac = 2; + SDLV4Info v4_info = 3; + optional SDLV6Info v6_info = 4; +} + +// ARP查询相关 +// 真实的arp请求是通过广播的形式获取到的,但是针对于macos这种tun的实现;是能够分析出arp请求包的; +// 对于当前网络来说,服务端是知道mac对应的ip地址的,因此没有必要广播;直接通过服务器端返回 +message SDLArpRequest { + uint32 pkt_id = 1; + uint32 target_ip = 2; +} + +message SDLArpResponse { + uint32 pkt_id = 1; + uint32 target_ip = 2; + bytes target_mac = 3; +} + +// 权限请求查询相关 +message SDLPolicyRequest { + uint32 pkt_id = 1; + uint32 src_identity_id = 2; + uint32 dst_identity_id = 3; + uint32 version = 4; +} + +// 基于quic通讯,rules部分已经没有了长度限制 +message SDLPolicyResponse { + uint32 pkt_id = 1; + uint32 src_identity_id = 2; + uint32 dst_identity_id = 3; + // 版本号,客户端需要比较版本号确定是否覆盖; 请求端自己去管理版本号,服务端只是原样回写 + uint32 version = 4; + // 4+1+2 的稀疏序列化规则 + bytes rules = 5; } // 事件定义 @@ -82,30 +131,9 @@ message SDLNetworkShutdownEvent { string message = 1; } -// 命令定义 - -message SDLChangeNetworkCommand { - SDLDevAddr dev_addr = 1; - bytes aes_key = 2; -} - -message SDLCommandAck { - // status = true, 表示成功;status = false 表示失败,message是失败原因描述 - bool status = 1; - optional string message = 2; -} - -message SDLFlows { - // 服务器转发流量 - uint32 forward_num = 1; - // p2p直接流量 - uint32 p2p_num = 2; - // 接收的流量 - uint32 inbound_num = 3; -} - // UDP通讯消息 +// client和stun之间的心跳包,客户端需要和super的udp之间的存活逻辑 message SDLStunRequest { uint32 cookie = 1; string client_id = 2; @@ -114,6 +142,7 @@ message SDLStunRequest { uint32 ip = 5; uint32 nat_type = 6; optional SDLV6Info v6_info = 7; + bytes session_token = 8; } message SDLStunReply { @@ -127,8 +156,31 @@ message SDLData { bool is_p2p = 4; uint32 ttl = 5; bytes data = 6; + bytes session_token = 7; + // 端通过https登录的时候,服务端会分配该端对应的权限标识 + // 后续的请求过程中需要带上这个值,对端通过这个值要判断对数据包是否放行 + uint32 identity_id = 8; } +// 网络类型探测 + +message SDLStunProbe { + uint32 cookie = 1; + uint32 attr = 2; + // 增加step是为了方便端上判断,收到的请求和响应之间的映射关系;服务器端原样返回 + uint32 step = 3; +} + +message SDLStunProbeReply { + uint32 cookie = 1; + // 增加step是为了方便端上判断,收到的请求和响应之间的映射关系;服务器端原样返回 + uint32 step = 2; + uint32 port = 3; + uint32 ip = 4; +} + +// Node-Node之间的握手逻辑, 是基于udp传输的 + message SDLRegister { uint32 network_id = 1; bytes src_mac = 2; @@ -139,17 +191,4 @@ message SDLRegisterAck { uint32 network_id = 1; bytes src_mac = 2; bytes dst_mac = 3; -} - -// 网络类型探测 - -message SDLStunProbe { - uint32 cookie = 1; - uint32 attr = 2; -} - -message SDLStunProbeReply { - uint32 cookie = 1; - uint32 port = 2; - uint32 ip = 3; } \ No newline at end of file diff --git a/src/bin/build_pb/main.rs b/src/bin/build_pb/main.rs index 67a37a4..c5d8c2b 100755 --- a/src/bin/build_pb/main.rs +++ b/src/bin/build_pb/main.rs @@ -1,6 +1,7 @@ fn main() { prost_build::Config::new() .out_dir("src/pb") + .bytes(&[".message.SDLData.data"]) // .out_dir("../tcp_mock/pb") .protoc_arg("--experimental_allow_proto3_optional") .compile_protos(&["message.proto"], &["."]) diff --git a/src/bin/punchnet/main.rs b/src/bin/punchnet/main.rs index 1055941..cbc754b 100755 --- a/src/bin/punchnet/main.rs +++ b/src/bin/punchnet/main.rs @@ -109,7 +109,15 @@ async fn main() { // exit(0); } */ - if let Err(e) = edge.start_without_feedback(cmd.token, cmd.network_code, None).await { + if let Err(e) = edge.start_without_feedback( + String::new(), + 0, + &"".to_owned(), + 0, + 24, + 0, + Some("".to_owned()) + ).await { error!("failed to start: {:?}", e); } diff --git a/src/network/node.rs b/src/network/node.rs index a8cae53..38ba667 100755 --- a/src/network/node.rs +++ b/src/network/node.rs @@ -16,7 +16,7 @@ use crate::pb::{ encode_to_tcp_message, encode_to_udp_message, SdlEmpty, SdlStunProbe, SdlStunProbeReply, }; use crate::tcp::{get_tcp_conn, NatType, PacketType, StunProbeAttr}; -use crate::utils::{Socket}; +use crate::utils::{Socket, create_or_load_mac}; use sdlan_sn_rs::peer::{IpSubnet, V6Info}; @@ -79,8 +79,8 @@ pub async fn init_edge( node_conf, sock_v4, sock_multicast, - token, - network_code, + // token, + // network_code, privatekey, tcp_pong.clone(), start_stop, @@ -123,10 +123,48 @@ pub struct StartStopInfo { pub pkt_id: Option, } +pub struct StringToken(RwLock); + +impl StringToken { + pub fn new(value: T) -> Self { + Self(RwLock::new(value)) + } + + pub fn get(&self) -> T { + self.0.read().unwrap().clone() + } + + pub fn set(&self, token: T) { + *self.0.write().unwrap() = token; + } +} + +pub struct IdentityID(AtomicU32); + +impl IdentityID { + pub fn new(id: u32) -> Self { + Self(AtomicU32::new(id)) + } + + pub fn load(&self) -> u32 { + self.0.load(Ordering::Relaxed) + } + + pub fn store(&self, id: u32) { + self.0.store(id, Ordering::Relaxed); + } +} + pub struct Node { packet_id: AtomicU32, pub network_id: AtomicU32, + pub network_domain: RwLock, + + pub identity_id: IdentityID, + + pub access_token: StringToken, + pub session_token: StringToken>, pub hostname: RwLock, @@ -139,8 +177,8 @@ pub struct Node { pub connection_chan: Option>, // user token info - pub _token: Mutex, - pub network_code: Mutex, + // pub _token: Mutex, + // pub network_code: Mutex, pub device_config: DeviceConfig, pub device: Iface, @@ -205,14 +243,33 @@ impl Node { self.nat_type.lock().unwrap().clone() } - pub async fn start_without_feedback(&self, token: String, network_code: String, hostname: Option) -> Result<()> { + pub async fn start_without_feedback( + &self, + access_token: String, + network_id: u32, + network_domain: &String, + ip_net: u32, + ip_net_bit_len: u8, + identity_id: u32, + hostname: Option + ) -> Result<()> { if let Some(host) = hostname { let idfile = format!("{}/.host", get_base_dir()); let _ = save_to_file(&idfile, &host); *self.hostname.write().unwrap() = host; } - *self._token.lock().unwrap() = token; - *self.network_code.lock().unwrap() = network_code; + + self.access_token.set(access_token); + self.device_config.ip.net_addr.store(ip_net, Ordering::Relaxed); + self.device_config.ip.net_bit_len.store(ip_net_bit_len, Ordering::Relaxed); + *self.device_config.mac.write().unwrap() = create_or_load_mac(); + self.network_id.store(network_id, Ordering::Relaxed); + self.network_domain.write().unwrap().clone_from(network_domain); + // self.network_domain = network_domain; + + self.identity_id.store(identity_id); + // *self._token.lock().unwrap() = token; + // *self.network_code.lock().unwrap() = network_code; let _ = self .start_stop_sender .send(StartStopInfo { @@ -225,8 +282,17 @@ impl Node { pub async fn start_with_feedback( &self, - token: String, - network_code: String, + + access_token: String, + + network_id: u32, + network_domain: &String, + + ip_net: u32, + ip_net_bit_len: u8, + identity_id: u32, + // token: String, + // network_code: String, hostname: Option, timeout: Duration, ) -> Result { @@ -235,8 +301,17 @@ impl Node { let _ = save_to_file(&idfile, &host); *self.hostname.write().unwrap() = host; } - *self._token.lock().unwrap() = token; - *self.network_code.lock().unwrap() = network_code; + + self.access_token.set(access_token); + self.device_config.ip.net_addr.store(ip_net, Ordering::Relaxed); + self.device_config.ip.net_bit_len.store(ip_net_bit_len, Ordering::Relaxed); + *self.device_config.mac.write().unwrap() = create_or_load_mac(); + self.network_id.store(network_id, Ordering::Relaxed); + self.network_domain.write().unwrap().clone_from(network_domain); + + self.identity_id.store(identity_id); + // *self._token.lock().unwrap() = token; + // *self.network_code.lock().unwrap() = network_code; let (tx, rx) = oneshot::channel(); let id = self.get_next_packet_id(); self.packet_id_match.insert(id, tx); @@ -265,7 +340,8 @@ impl Node { } pub async fn stop(&self) { - *self._token.lock().unwrap() = "".to_owned(); + // *self._token.lock().unwrap() = "".to_owned(); + self.session_token.set(vec![]); let _ = self .start_stop_sender .send(StartStopInfo { @@ -281,8 +357,8 @@ impl Node { sock: Socket, multicast_sock: Option, // tcpsock: TCPSocket, - token: &str, - network_code: &str, + // token: &str, + // network_code: &str, private: RsaPrivateKey, tcp_pong: Arc, start_stop: Sender, @@ -304,10 +380,16 @@ impl Node { network_id: AtomicU32::new(0), hostname: RwLock::new(hostname), + network_domain: RwLock::new(String::new()), + udp_sock_for_dns: udpsock_for_dns, - _token: Mutex::new(token.to_owned()), - network_code: Mutex::new(network_code.to_owned()), + identity_id: IdentityID::new(0), + access_token: StringToken::new(String::new()), + session_token: StringToken::new(Vec::new()), + + // _token: Mutex::new(token.to_owned()), + // network_code: Mutex::new(network_code.to_owned()), start_stop_sender: start_stop, connection_chan: connecting_chan, @@ -515,6 +597,7 @@ impl Node { let probe = SdlStunProbe { attr: msgattr as u32, cookie, + step: 0, }; // println!("==> sending probe request: {:?}", probe); diff --git a/src/network/packet.rs b/src/network/packet.rs index 3970281..2fb3368 100755 --- a/src/network/packet.rs +++ b/src/network/packet.rs @@ -1132,6 +1132,7 @@ async fn send_query_peer(eee: &Node, dst_mac: Mac) -> Result<()> { } let query = SdlQueryInfo { dst_mac: Vec::from(dst_mac), + pkt_id: 0, }; let Ok(content) = encode_to_tcp_message( diff --git a/src/network/tun_linux.rs b/src/network/tun_linux.rs index 38d0967..f8585fc 100755 --- a/src/network/tun_linux.rs +++ b/src/network/tun_linux.rs @@ -221,6 +221,8 @@ impl TunTapPacketHandler for Iface { if let Some(eth) = headers.link { if let Some(hdr) = eth.ethernet2() { + use bytes::Bytes; + if let Some(ip) = headers.net { match ip { etherparse::NetHeaders::Ipv4(ipv4, _) => { @@ -251,13 +253,16 @@ impl TunTapPacketHandler for Iface { 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: Vec::from(encrypted), + 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(); diff --git a/src/network/tuntap.rs b/src/network/tuntap.rs index dc4f779..ee5aba9 100755 --- a/src/network/tuntap.rs +++ b/src/network/tuntap.rs @@ -1,5 +1,6 @@ use std::sync::atomic::Ordering; +use bytes::Bytes; use dashmap::DashMap; use once_cell::sync::OnceCell; use sdlan_sn_rs::{ @@ -91,13 +92,16 @@ impl ArpWaitList { error!("failed to encrypt packet request"); return; }; + let data_bytes = Bytes::from(encrypted); let data = SdlData { is_p2p: true, network_id, ttl: SDLAN_DEFAULT_TTL as u32, src_mac: Vec::from(src_mac), dst_mac: Vec::from(mac), - data: Vec::from(encrypted), + 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, mac, &msg, pkt_size as u64).await; diff --git a/src/pb/message.rs b/src/pb/message.rs index d30d486..65c4587 100644 --- a/src/pb/message.rs +++ b/src/pb/message.rs @@ -17,83 +17,148 @@ pub struct Sdlv6Info { #[prost(bytes = "vec", tag = "2")] pub v6: ::prost::alloc::vec::Vec, } -/// 设备网络地址信息 #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct SdlDevAddr { +pub struct SdlWelcome { #[prost(uint32, tag = "1")] - pub network_id: u32, - #[prost(bytes = "vec", tag = "2")] - pub mac: ::prost::alloc::vec::Vec, + pub version: u32, + /// 服务器允许的最大双向流 + #[prost(uint32, tag = "2")] + pub max_bidi_streams: u32, + /// 服务器允许的最大包 #[prost(uint32, tag = "3")] - pub net_addr: u32, + pub max_packet_size: u32, + /// 心跳包的间隔 #[prost(uint32, tag = "4")] - pub net_bit_len: u32, - #[prost(string, tag = "5")] - pub network_domain: ::prost::alloc::string::String, + pub heartbeat_sec: u32, } -/// tcp通讯消息 +/// quic 通讯消息 #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct SdlEmpty {} +pub struct SdlEmpty { + #[prost(uint32, tag = "1")] + pub pkt_id: u32, +} +/// 这里修改成了扁平的结构, 否则有些字段不好找放的位置 #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct SdlRegisterSuper { #[prost(uint32, tag = "1")] - pub version: u32, + pub pkt_id: u32, #[prost(string, tag = "2")] - pub installed_channel: ::prost::alloc::string::String, - #[prost(string, tag = "3")] pub client_id: ::prost::alloc::string::String, - #[prost(message, optional, tag = "4")] - pub dev_addr: ::core::option::Option, - #[prost(string, tag = "5")] - pub pub_key: ::prost::alloc::string::String, - #[prost(string, tag = "6")] - pub token: ::prost::alloc::string::String, + /// 网络地址信息已经有https请求分配了 + /// 注册的时候需要带上(network_id, mac, ip, mask_len, hostname) + #[prost(uint32, tag = "3")] + pub network_id: u32, + #[prost(bytes = "vec", tag = "4")] + pub mac: ::prost::alloc::vec::Vec, + #[prost(uint32, tag = "5")] + pub ip: u32, + #[prost(uint32, tag = "6")] + pub mask_len: u32, #[prost(string, tag = "7")] - pub network_code: ::prost::alloc::string::String, - #[prost(string, tag = "8")] pub hostname: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub pub_key: ::prost::alloc::string::String, + /// 客户端使用http协议请求后端,通过token或者账号密码登录时, 统一返回一个access_token; + /// RegisterSuper的时候,验证凭证是否合法 (access_token) + #[prost(string, tag = "9")] + pub access_token: ::prost::alloc::string::String, } +/// 客户端的升级逻辑,在https的接口里面去完成 +/// 部分逻辑会脱离quic去通讯,增加session_token校验 #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct SdlRegisterSuperAck { - #[prost(message, optional, tag = "1")] - pub dev_addr: ::core::option::Option, + #[prost(uint32, tag = "1")] + pub pkt_id: u32, #[prost(bytes = "vec", tag = "2")] pub aes_key: ::prost::alloc::vec::Vec, - #[prost(uint32, tag = "3")] - pub upgrade_type: u32, - #[prost(string, optional, tag = "4")] - pub upgrade_prompt: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag = "5")] - pub upgrade_address: ::core::option::Option<::prost::alloc::string::String>, + #[prost(bytes = "vec", tag = "3")] + pub session_token: ::prost::alloc::vec::Vec, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct SdlRegisterSuperNak { #[prost(uint32, tag = "1")] + pub pkt_id: u32, + #[prost(uint32, tag = "2")] pub error_code: u32, - #[prost(string, tag = "2")] + #[prost(string, tag = "3")] pub error_message: ::prost::alloc::string::String, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct SdlQueryInfo { - #[prost(bytes = "vec", tag = "1")] + #[prost(uint32, tag = "1")] + pub pkt_id: u32, + #[prost(bytes = "vec", tag = "2")] pub dst_mac: ::prost::alloc::vec::Vec, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct SdlPeerInfo { - #[prost(bytes = "vec", tag = "1")] + #[prost(uint32, tag = "1")] + pub pkt_id: u32, + #[prost(bytes = "vec", tag = "2")] pub dst_mac: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag = "2")] - pub v4_info: ::core::option::Option, #[prost(message, optional, tag = "3")] + pub v4_info: ::core::option::Option, + #[prost(message, optional, tag = "4")] pub v6_info: ::core::option::Option, } +/// ARP查询相关 +/// 真实的arp请求是通过广播的形式获取到的,但是针对于macos这种tun的实现;是能够分析出arp请求包的; +/// 对于当前网络来说,服务端是知道mac对应的ip地址的,因此没有必要广播;直接通过服务器端返回 +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SdlArpRequest { + #[prost(uint32, tag = "1")] + pub pkt_id: u32, + #[prost(uint32, tag = "2")] + pub target_ip: u32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SdlArpResponse { + #[prost(uint32, tag = "1")] + pub pkt_id: u32, + #[prost(uint32, tag = "2")] + pub target_ip: u32, + #[prost(bytes = "vec", tag = "3")] + pub target_mac: ::prost::alloc::vec::Vec, +} +/// 权限请求查询相关 +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SdlPolicyRequest { + #[prost(uint32, tag = "1")] + pub pkt_id: u32, + #[prost(uint32, tag = "2")] + pub src_identity_id: u32, + #[prost(uint32, tag = "3")] + pub dst_identity_id: u32, + #[prost(uint32, tag = "4")] + pub version: u32, +} +/// 基于quic通讯,rules部分已经没有了长度限制 +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SdlPolicyResponse { + #[prost(uint32, tag = "1")] + pub pkt_id: u32, + #[prost(uint32, tag = "2")] + pub src_identity_id: u32, + #[prost(uint32, tag = "3")] + pub dst_identity_id: u32, + /// 版本号,客户端需要比较版本号确定是否覆盖; 请求端自己去管理版本号,服务端只是原样回写 + #[prost(uint32, tag = "4")] + pub version: u32, + /// 4+1+2 的稀疏序列化规则 + #[prost(bytes = "vec", tag = "5")] + pub rules: ::prost::alloc::vec::Vec, +} #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct SdlNatChangedEvent { @@ -122,36 +187,7 @@ pub struct SdlNetworkShutdownEvent { #[prost(string, tag = "1")] pub message: ::prost::alloc::string::String, } -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SdlChangeNetworkCommand { - #[prost(message, optional, tag = "1")] - pub dev_addr: ::core::option::Option, - #[prost(bytes = "vec", tag = "2")] - pub aes_key: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SdlCommandAck { - /// status = true, 表示成功;status = false 表示失败,message是失败原因描述 - #[prost(bool, tag = "1")] - pub status: bool, - #[prost(string, optional, tag = "2")] - pub message: ::core::option::Option<::prost::alloc::string::String>, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SdlFlows { - /// 服务器转发流量 - #[prost(uint32, tag = "1")] - pub forward_num: u32, - /// p2p直接流量 - #[prost(uint32, tag = "2")] - pub p2p_num: u32, - /// 接收的流量 - #[prost(uint32, tag = "3")] - pub inbound_num: u32, -} +/// client和stun之间的心跳包,客户端需要和super的udp之间的存活逻辑 #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct SdlStunRequest { @@ -169,6 +205,8 @@ pub struct SdlStunRequest { pub nat_type: u32, #[prost(message, optional, tag = "7")] pub v6_info: ::core::option::Option, + #[prost(bytes = "vec", tag = "8")] + pub session_token: ::prost::alloc::vec::Vec, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -189,8 +227,38 @@ pub struct SdlData { pub is_p2p: bool, #[prost(uint32, tag = "5")] pub ttl: u32, - #[prost(bytes = "vec", tag = "6")] - pub data: ::prost::alloc::vec::Vec, + #[prost(bytes = "bytes", tag = "6")] + pub data: ::prost::bytes::Bytes, + #[prost(bytes = "vec", tag = "7")] + pub session_token: ::prost::alloc::vec::Vec, + /// 端通过https登录的时候,服务端会分配该端对应的权限标识 + /// 后续的请求过程中需要带上这个值,对端通过这个值要判断对数据包是否放行 + #[prost(uint32, tag = "8")] + pub identity_id: u32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SdlStunProbe { + #[prost(uint32, tag = "1")] + pub cookie: u32, + #[prost(uint32, tag = "2")] + pub attr: u32, + /// 增加step是为了方便端上判断,收到的请求和响应之间的映射关系;服务器端原样返回 + #[prost(uint32, tag = "3")] + pub step: u32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SdlStunProbeReply { + #[prost(uint32, tag = "1")] + pub cookie: u32, + /// 增加step是为了方便端上判断,收到的请求和响应之间的映射关系;服务器端原样返回 + #[prost(uint32, tag = "2")] + pub step: u32, + #[prost(uint32, tag = "3")] + pub port: u32, + #[prost(uint32, tag = "4")] + pub ip: u32, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -212,21 +280,3 @@ pub struct SdlRegisterAck { #[prost(bytes = "vec", tag = "3")] pub dst_mac: ::prost::alloc::vec::Vec, } -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SdlStunProbe { - #[prost(uint32, tag = "1")] - pub cookie: u32, - #[prost(uint32, tag = "2")] - pub attr: u32, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SdlStunProbeReply { - #[prost(uint32, tag = "1")] - pub cookie: u32, - #[prost(uint32, tag = "2")] - pub port: u32, - #[prost(uint32, tag = "3")] - pub ip: u32, -} diff --git a/src/tcp/tcp_conn.rs b/src/tcp/tcp_conn.rs index b09fde4..3d8439c 100755 --- a/src/tcp/tcp_conn.rs +++ b/src/tcp/tcp_conn.rs @@ -25,7 +25,7 @@ use tracing::error; use crate::config::{NULL_MAC, TCP_PING_TIME}; use crate::network::{Node, RegisterSuperFeedback, StartStopInfo, check_peer_registration_needed, handle_packet_peer_info}; -use crate::pb::{SdlDevAddr, SdlRegisterSuper, SdlRegisterSuperAck, SdlRegisterSuperNak, SdlSendRegisterEvent, SdlStunRequest, Sdlv6Info, encode_to_tcp_message, encode_to_udp_message}; +use crate::pb::{SdlRegisterSuper, SdlRegisterSuperAck, SdlRegisterSuperNak, SdlSendRegisterEvent, SdlStunRequest, Sdlv6Info, encode_to_tcp_message, encode_to_udp_message}; use crate::tcp::{EventType, NakMsgCode, NatType, PacketType, read_a_packet}; use crate::utils::send_to_sock; use crate::{ConnectionInfo, ConnectionState, get_edge}; @@ -61,20 +61,24 @@ async fn handle_tcp_message(msg: SdlanTcp) { error!("failed to rsa decrypt aes key"); return; }; + /* let Some(dev) = ack.dev_addr else { error!("no dev_addr is specified"); return; }; + */ - let ip = ip_to_string(&dev.net_addr); + let ip = ip_to_string(&edge.device_config.get_ip()); // debug!("aes key is {:?}, ip is {}/{}", aes, ip, dev.net_bit_len,); println!("assigned ip: {}", ip); let hostname = edge.hostname.read().unwrap().clone(); - println!("network is: {}.{}", hostname, dev.network_domain); + // println!("network is: {}.{}", hostname, dev.network_domain); + /* edge.device_config .ip .net_addr .store(dev.net_addr, Ordering::Relaxed); + */ if let Some(ref chan) = edge.connection_chan { let _ = chan.send(ConnectionInfo::IPInfo(ip)).await; } @@ -85,12 +89,15 @@ async fn handle_tcp_message(msg: SdlanTcp) { }; */ // *edge.device_config.mac.write().unwrap() = mac; + /* edge.device_config .ip .net_bit_len .store(dev.net_bit_len as u8, Ordering::Relaxed); - edge.device.reload_config(&edge.device_config, &dev.network_domain); edge.network_id.store(dev.network_id, Ordering::Relaxed); + */ + // edge.device.reload_config(&edge.device_config, &dev.network_domain); + edge.device.reload_config(&edge.device_config, &edge.network_domain.read().unwrap().clone()); edge.set_authorized(true, aes); send_stun_request(edge).await; @@ -263,6 +270,7 @@ pub async fn send_stun_request(eee: &Node) { None => None, }; let req = SdlStunRequest { + session_token: Vec::from(eee.session_token.get()), cookie: 0, client_id: eee.config.node_uuid.clone(), network_id: eee.network_id.load(Ordering::Relaxed), @@ -293,8 +301,9 @@ async fn on_connected_callback<'a>(stream: &'a mut tokio::net::TcpStream, pkt_id let edge = get_edge(); // let installed_channel = install_channel.to_owned(); - let token = edge._token.lock().unwrap().clone(); - let code = edge.network_code.lock().unwrap().clone(); + // let token = edge._token.lock().unwrap().clone(); + // let code = edge.network_code.lock().unwrap().clone(); + // let edge = get_edge(); // let edge = get_edge(); // let token = args.token.clone(); @@ -309,20 +318,16 @@ async fn on_connected_callback<'a>(stream: &'a mut tokio::net::TcpStream, pkt_id } } let register_super = SdlRegisterSuper { - version: 1, - installed_channel: edge.install_channel.clone(), + mac: Vec::from(edge.device_config.get_mac()), + pkt_id: edge.get_next_packet_id(), + network_id: edge.network_id.load(Ordering::Relaxed), + ip: edge.device_config.get_ip(), + mask_len: edge.device_config.get_net_bit() as u32, + access_token: edge.access_token.get(), + // installed_channel, client_id: edge.config.node_uuid.clone(), - dev_addr: Some(SdlDevAddr { - mac: Vec::from(edge.device_config.get_mac()), - net_addr: 0, - network_id: 0, - net_bit_len: 0, - network_domain: "".to_owned(), - }), pub_key: edge.rsa_pubkey.clone(), - token, - network_code: code, hostname: edge.hostname.read().unwrap().clone(), }; // debug!("send register super: {:?}", register_super); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 42ceef5..251258e 100755 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,12 +1,16 @@ mod command; +use std::{fs::OpenOptions, io::Write, path::Path}; + pub use command::*; mod socks; use rand::Rng; -use sdlan_sn_rs::utils::Mac; +use sdlan_sn_rs::utils::{Mac, Result, SDLanError, save_to_file}; pub use socks::*; +use crate::get_base_dir; + mod pid_recorder; // pub const CRC_HASH: crc::Crc = crc::Crc::::new(&crc::CRC_32_XFER); @@ -17,6 +21,36 @@ pub fn caculate_crc(data: &[u8]) -> u32 { res } +pub fn create_or_load_mac() -> Mac { + let path = format!("{}/.mac", get_base_dir()); + if let Ok(content) = std::fs::read(&path) { + if content.len() == 6 { + let mut mac = [0; 6]; + mac.copy_from_slice(&content); + return mac; + } + } + let mac = generate_mac_address(); + let _ = save_to_file_binary(&path, &mac); + mac +} + + +pub fn save_to_file_binary(idfile: &str, content: &[u8]) -> Result<()> { + if idfile.len() == 0 { + return Err(SDLanError::IOError("file is empty".to_owned())); + } + + let filepath = Path::new(idfile); + OpenOptions::new() + .create(true) + .write(true) + .truncate(true) + .open(filepath)? + .write_all(content)?; + Ok(()) +} + pub fn mac_to_string(mac: &Mac) -> String { format!( "[{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}]",