diff --git a/README.md b/README.md index 9558e4e..0af6246 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,9 @@ A virtual network tool (VPN) 将不同网络下的多个设备虚拟到一个局域网下 + ### vnt-cli参数详解 [参数说明](https://github.com/lbl8603/vnt/blob/main/vnt-cli/README.md) + ### 快速使用: 1. 指定一个token,在多台设备上运行该程序,例如: @@ -61,8 +63,28 @@ A virtual network tool (VPN) 前提条件:安装rust编译环境([install rust](https://www.rust-lang.org/zh-CN/tools/install)) +``` 到项目根目录下执行 cargo build -p vnt-cli +也可按需编译,将得到更小的二进制文件,使用--no-default-features排除默认features + +cargo build -p vnt-cli --no-default-features --features raw +``` + +features说明 + +| feature | 说明 | +|------------------|----------------------| +| raw | 默认 | +| openssl | 使用openssl中的aes_ecb算法 | +| openssl-vendored | 从源码编译openssl | +| ring-cipher | 使用ring中的aes_gcm算法 | +| aes_cbc | 支持aes_cbc加密 | +| aes_ecb | 支持aes_ecb加密 | +| aes_gcm | 支持aes_gcm加密 | +| aes_ecb | 支持aes_ecb加密 | +| server_encrypt | 支持服务端加密 | + ### 支持平台 - Mac @@ -86,9 +108,11 @@ A virtual network tool (VPN) - p2p组播/广播 - 客户端数据加密 - 服务端数据加密 + ### 结构 +
展开 - +
     
    0                                            15                                              31
@@ -121,8 +145,9 @@ A virtual network tool (VPN)
 - 支持Ipv6(1.2.2已支持客户端之间的ipv6,待支持客户端和服务端之间的ipv6通信)
 
 ### 常见问题
+
 
展开 - + #### 问题1: 设置网络地址失败 ##### 可能原因: @@ -138,26 +163,35 @@ vnt默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突 #### 问题2: windows系统上wintun.dll加载失败 ##### 可能原因: + 没有下载wintun.dll 或者使用的wintun.dll有问题 + ##### 解决方法: + 1. 下载最新版的wintun.dll [下载链接](https://www.wintun.net/builds/wintun-0.14.1.zip) 2. 解压后找到对应架构的目录,通常是amd64 3. 将对应的wintun.dll放到和vnt-cli同目录下(或者放到C盘Windows目录下) 4. 再次启动vnt-cli - + #### 问题3: 丢包严重,或是不能正常组网通信 + ##### 可能原因: + 某些宽带下(比如广电宽带)UDP丢包严重 + ##### 解决方法: + 1. 使用TCP模式中继转发(vnt-cli增加--tcp参数) 2. 如果p2p后效果很差,可以选择禁用p2p(vnt-cli增加--relay参数) -
### 交流群 QQ:1034868233 + ### 其他 + 可使用社区小伙伴搭建的中继服务器 + 1. -s vnt.8443.eu.org:29871 diff --git a/vnt-cli/Cargo.toml b/vnt-cli/Cargo.toml index 9f63d60..5609b40 100644 --- a/vnt-cli/Cargo.toml +++ b/vnt-cli/Cargo.toml @@ -6,13 +6,13 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -vnt = { path = "../vnt", package = "vnt", optional = true } +vnt = { path = "../vnt", package = "vnt",default-features = false, optional = true } common = { path = "../common" } tokio = { version = "1.32.0", features = ["full"] } getopts = "0.2.21" console = "0.15.2" os_info = "3.7.0" -dirs = "4.0.0" +dirs = "5.0.1" serde = "1.0" serde_json = "1.0.94" serde_yaml = "0.9.25" @@ -31,11 +31,16 @@ sudo = "0.6.0" winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] } [features] -default = ["vnt"] +default = ["server_encrypt","aes_gcm","aes_cbc","aes_ecb","sm4_cbc"] +raw=["vnt"] openssl = ["vnt/openssl"] openssl-vendored = ["vnt/openssl-vendored"] ring-cipher = ["vnt/ring-cipher"] - +aes_cbc=["vnt/aes_cbc"] +aes_ecb=["vnt/aes_ecb"] +sm4_cbc=["vnt/sm4_cbc"] +aes_gcm=["vnt/aes_gcm"] +server_encrypt=["vnt/server_encrypt"] [build-dependencies] embed-manifest = "1.4.0" \ No newline at end of file diff --git a/vnt-cli/src/main.rs b/vnt-cli/src/main.rs index c4515f2..938f61c 100644 --- a/vnt-cli/src/main.rs +++ b/vnt-cli/src/main.rs @@ -179,6 +179,13 @@ fn main() { }; let password: Option = matches.opt_get("w").unwrap(); let server_encrypt = matches.opt_present("W"); + #[cfg(not(feature = "server_encrypt"))] + { + if server_encrypt { + println!("Server encryption not supported"); + return; + } + } let simulate_multicast = matches.opt_present("m"); let mtu: Option = matches.opt_get("u").unwrap(); let mtu = if let Some(mtu) = mtu { @@ -213,7 +220,31 @@ fn main() { } let cipher_model = match matches.opt_get::("model") { - Ok(model) => model.unwrap_or(CipherModel::AesGcm), + Ok(model) => { + #[cfg(not(any( + feature = "aes_gcm", + feature = "server_encrypt", + feature = "aes_cbc", + feature = "aes_ecb", + feature = "sm4_cbc" + )))] + { + if password.is_some() && model.is_none() { + println!("Encryption not supported"); + return; + } + } + #[cfg(not(any(feature = "aes_gcm", feature = "server_encrypt")))] + { + if password.is_some() && model.is_none() { + println!("'--model ' undefined"); + return; + } + model.unwrap_or(CipherModel::None) + } + #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] + model.unwrap_or(CipherModel::AesGcm) + } Err(e) => { println!("'--model ' invalid,{}", e); return; @@ -452,7 +483,19 @@ fn print_usage(program: &str, _opts: Options) { println!(" -i 配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据"); println!(" 并转发到10.26.0.3,可指定多个网段"); println!(" -o 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段"); - println!(" -w 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信"); + let mut enums = String::new(); + #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] + enums.push_str("/aes_gcm"); + #[cfg(feature = "aes_cbc")] + enums.push_str("/aes_cbc"); + #[cfg(feature = "aes_ecb")] + enums.push_str("/aes_ecb"); + #[cfg(feature = "sm4_cbc")] + enums.push_str("/sm4_cbc"); + if !enums.is_empty() { + println!(" -w 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信"); + } + #[cfg(feature = "server_encrypt")] println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确"); println!(" -m 模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送"); println!(" -u 自定义mtu(不加密默认为1450,加密默认为1410)"); @@ -462,7 +505,12 @@ fn print_usage(program: &str, _opts: Options) { println!(" --ip 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配"); println!(" --relay 仅使用服务器转发,不使用p2p,默认情况允许使用p2p"); println!(" --par 任务并行度(必须为正整数),默认值为1"); - println!(" --model 加密模式(默认aes_gcm),可选值aes_gcm/aes_cbc/aes_ecb/sm4_cbc"); + if !enums.is_empty() { + println!( + " --model 加密模式(默认aes_gcm),可选值{}", + &enums[1..] + ); + } println!(" --finger 增加数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启"); println!(" --punch 取值ipv4/ipv6,ipv4表示仅使用ipv4打洞"); println!(" --port 取值0~65535,指定本地监听的端口,默认取随机端口"); diff --git a/vnt/Cargo.toml b/vnt/Cargo.toml index 07fbc14..ee12417 100644 --- a/vnt/Cargo.toml +++ b/vnt/Cargo.toml @@ -20,16 +20,16 @@ thiserror = "1.0.37" protobuf = "3.2.0" socket2 = { version = "0.5.2", features = ["all"] } tokio = { version = "1.32.0", features = ["full"] } -aes-gcm = { version = "0.10.2" } +aes-gcm = { version = "0.10.2",optional = true } ring = { version = "0.16.20", optional = true } -cbc = "0.1.2" -ecb = "0.1.2" +cbc = {version = "0.1.2",optional = true} +ecb = {version = "0.1.2",optional = true} aes = "0.8.3" stun-format = { version = "1.0.1", features = ["fmt", "rfc3489"] } -rsa = { version = "0.7.2", features = [] } -spki = { version = "0.6.0", features = ["fingerprint", "alloc"] } +rsa = { version = "0.7.2", features = [] ,optional = true} +spki = { version = "0.6.0", features = ["fingerprint", "alloc"] ,optional = true} openssl-sys = { git = "https://github.com/lbl8603/rust-openssl" ,optional = true} -libsm = {git="https://github.com/lbl8603/libsm"} +libsm = {git="https://github.com/lbl8603/libsm" ,optional = true} [target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies] tun = { path = "./rust-tun" } @@ -44,10 +44,14 @@ protobuf-codegen = "3.2.0" protoc-bin-vendored = "3.0.0" [features] -default = [] +default = ["server_encrypt","aes_gcm","aes_cbc","aes_ecb","sm4_cbc"] openssl = ["openssl-sys"] # 从源码编译 openssl-vendored = ["openssl-sys/vendored"] ring-cipher = ["ring"] - +aes_cbc=["cbc"] +aes_ecb=["ecb"] +sm4_cbc=["libsm"] +aes_gcm=["aes-gcm","ring"] +server_encrypt =["rsa","spki"] diff --git a/vnt/src/cipher/cipher.rs b/vnt/src/cipher/cipher.rs index 780934c..ba77d08 100644 --- a/vnt/src/cipher/cipher.rs +++ b/vnt/src/cipher/cipher.rs @@ -1,25 +1,37 @@ +#[cfg(feature = "aes_ecb")] #[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))] use crate::cipher::aes_ecb::AesEcbCipher; + +#[cfg(feature = "aes_cbc")] +use crate::cipher::aes_cbc::AesCbcCipher; +#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] #[cfg(not(feature = "ring-cipher"))] use crate::cipher::aes_gcm_cipher::AesGcmCipher; +#[cfg(feature = "aes_ecb")] #[cfg(any(feature = "openssl-vendored", feature = "openssl"))] use crate::cipher::openssl_aes_ecb::AesEcbCipher; +#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] #[cfg(feature = "ring-cipher")] use crate::cipher::ring_aes_gcm_cipher::AesGcmCipher; +#[cfg(feature = "sm4_cbc")] use crate::cipher::sm4_cbc::Sm4CbcCipher; -use crate::cipher::{aes_cbc, Finger}; +use crate::cipher::Finger; use crate::protocol::NetPacket; -use aes_cbc::AesCbcCipher; use sha2::Digest; use std::io; use std::str::FromStr; #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum CipherModel { + #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] AesGcm, + #[cfg(feature = "aes_cbc")] AesCbc, + #[cfg(feature = "aes_ecb")] AesEcb, + #[cfg(feature = "sm4_cbc")] Sm4Cbc, + None, } impl FromStr for CipherModel { @@ -27,20 +39,44 @@ impl FromStr for CipherModel { fn from_str(s: &str) -> Result { match s.to_lowercase().trim() { + #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] "aes_gcm" => Ok(CipherModel::AesGcm), + #[cfg(feature = "aes_cbc")] "aes_cbc" => Ok(CipherModel::AesCbc), + #[cfg(feature = "aes_ecb")] "aes_ecb" => Ok(CipherModel::AesEcb), + #[cfg(feature = "sm4_cbc")] "sm4_cbc" => Ok(CipherModel::Sm4Cbc), - _ => Err(format!("not match '{}', enum:aes_gcm/aes_cbc/aes_ecb", s)), + _ => { + let mut enums = String::new(); + #[cfg(feature = "aes_gcm")] + enums.push_str("/aes_gcm"); + #[cfg(feature = "aes_cbc")] + enums.push_str("/aes_cbc"); + #[cfg(feature = "aes_ecb")] + enums.push_str("/aes_ecb"); + #[cfg(feature = "sm4_cbc")] + enums.push_str("/sm4_cbc"); + let str = if enums.is_empty() { + "no encrypt" + } else { + &enums[1..] + }; + Err(format!("not match '{}', enum:{}", s, str)) + } } } } #[derive(Clone)] pub enum Cipher { + #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] AesGcm((AesGcmCipher, Vec)), + #[cfg(feature = "aes_cbc")] AesCbc(AesCbcCipher), + #[cfg(feature = "aes_ecb")] AesEcb(AesEcbCipher), + #[cfg(feature = "sm4_cbc")] Sm4Cbc(Sm4CbcCipher), None, } @@ -57,6 +93,7 @@ impl Cipher { hasher.update(password.as_bytes()); let key: [u8; 32] = hasher.finalize().into(); match model { + #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] CipherModel::AesGcm => { if password.len() < 8 { let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger); @@ -66,6 +103,7 @@ impl Cipher { Cipher::AesGcm((aes, key.to_vec())) } } + #[cfg(feature = "aes_cbc")] CipherModel::AesCbc => { if password.len() < 8 { let aes = AesCbcCipher::new_128(key[..16].try_into().unwrap(), finger); @@ -75,6 +113,7 @@ impl Cipher { Cipher::AesCbc(aes) } } + #[cfg(feature = "aes_ecb")] CipherModel::AesEcb => { if password.len() < 8 { let aes = AesEcbCipher::new_128(key[..16].try_into().unwrap(), finger); @@ -84,10 +123,12 @@ impl Cipher { Cipher::AesEcb(aes) } } + #[cfg(feature = "sm4_cbc")] CipherModel::Sm4Cbc => { let aes = Sm4CbcCipher::new_128(key[..16].try_into().unwrap(), finger); Cipher::Sm4Cbc(aes) } + CipherModel::None => Cipher::None, } } else { Cipher::None @@ -96,10 +137,12 @@ impl Cipher { pub fn new_key(key: [u8; 32], token: String) -> io::Result { let finger = Some(Finger::new(&token)); match key.len() { + #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] 16 => { let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger); Ok(Cipher::AesGcm((aes, key[..16].to_vec()))) } + #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] 32 => { let aes = AesGcmCipher::new_256(key, finger); Ok(Cipher::AesGcm((aes, key.to_vec()))) @@ -112,9 +155,13 @@ impl Cipher { net_packet: &mut NetPacket, ) -> io::Result<()> { match self { + #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] Cipher::AesGcm((aes_gcm, _)) => aes_gcm.decrypt_ipv4(net_packet), + #[cfg(feature = "aes_cbc")] Cipher::AesCbc(aes_cbc) => aes_cbc.decrypt_ipv4(net_packet), + #[cfg(feature = "aes_ecb")] Cipher::AesEcb(aes_ecb) => aes_ecb.decrypt_ipv4(net_packet), + #[cfg(feature = "sm4_cbc")] Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.decrypt_ipv4(net_packet), Cipher::None => { if net_packet.is_encrypt() { @@ -129,32 +176,55 @@ impl Cipher { net_packet: &mut NetPacket, ) -> io::Result<()> { match self { + #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] Cipher::AesGcm((aes_gcm, _)) => aes_gcm.encrypt_ipv4(net_packet), + #[cfg(feature = "aes_cbc")] Cipher::AesCbc(aes_cbc) => aes_cbc.encrypt_ipv4(net_packet), + #[cfg(feature = "aes_ecb")] Cipher::AesEcb(aes_ecb) => aes_ecb.encrypt_ipv4(net_packet), + #[cfg(feature = "sm4_cbc")] Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.encrypt_ipv4(net_packet), Cipher::None => Ok(()), } } pub fn check_finger>(&self, net_packet: &NetPacket) -> io::Result<()> { - let finger = match self { - Cipher::AesGcm((aes_gcm, _)) => aes_gcm.finger.as_ref(), - Cipher::AesCbc(aes_cbc) => aes_cbc.finger.as_ref(), - Cipher::AesEcb(aes_ecb) => aes_ecb.finger.as_ref(), - Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.finger.as_ref(), - Cipher::None => None, - }; - if let Some(finger) = finger { - finger.check_finger(net_packet) - } else { - Ok(()) + match self { + #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] + Cipher::AesGcm((aes_gcm, _)) => aes_gcm + .finger + .as_ref() + .map(|f| f.check_finger(net_packet)) + .unwrap_or(Ok(())), + #[cfg(feature = "aes_cbc")] + Cipher::AesCbc(aes_cbc) => aes_cbc + .finger + .as_ref() + .map(|f| f.check_finger(net_packet)) + .unwrap_or(Ok(())), + #[cfg(feature = "aes_ecb")] + Cipher::AesEcb(aes_ecb) => aes_ecb + .finger + .as_ref() + .map(|f| f.check_finger(net_packet)) + .unwrap_or(Ok(())), + #[cfg(feature = "sm4_cbc")] + Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc + .finger + .as_ref() + .map(|f| f.check_finger(net_packet)) + .unwrap_or(Ok(())), + Cipher::None => Ok(()), } } pub fn key(&self) -> Option<&[u8]> { match self { + #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] Cipher::AesGcm((_, key)) => Some(key), + #[cfg(feature = "aes_cbc")] Cipher::AesCbc(aes_cbc) => Some(aes_cbc.key()), + #[cfg(feature = "aes_ecb")] Cipher::AesEcb(aes_ecb) => Some(aes_ecb.key()), + #[cfg(feature = "sm4_cbc")] Cipher::Sm4Cbc(sm4_cbc) => Some(sm4_cbc.key()), Cipher::None => None, } diff --git a/vnt/src/cipher/mod.rs b/vnt/src/cipher/mod.rs index 99fe605..c75834c 100644 --- a/vnt/src/cipher/mod.rs +++ b/vnt/src/cipher/mod.rs @@ -1,16 +1,21 @@ +#[cfg(feature = "aes_cbc")] mod aes_cbc; +#[cfg(feature = "aes_ecb")] #[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))] mod aes_ecb; +#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] #[cfg(not(feature = "ring-cipher"))] mod aes_gcm_cipher; mod cipher; mod finger; +#[cfg(feature = "aes_ecb")] +#[cfg(any(feature = "openssl-vendored", feature = "openssl"))] +mod openssl_aes_ecb; +#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] #[cfg(feature = "ring-cipher")] mod ring_aes_gcm_cipher; mod rsa_cipher; - -#[cfg(any(feature = "openssl-vendored", feature = "openssl"))] -mod openssl_aes_ecb; +#[cfg(feature = "sm4_cbc")] mod sm4_cbc; pub use cipher::Cipher; pub use cipher::CipherModel; diff --git a/vnt/src/cipher/rsa_cipher.rs b/vnt/src/cipher/rsa_cipher.rs index 3b52c05..d6d7f55 100644 --- a/vnt/src/cipher/rsa_cipher.rs +++ b/vnt/src/cipher/rsa_cipher.rs @@ -1,23 +1,32 @@ -use crate::protocol::body::{RsaSecretBody, RSA_ENCRYPTION_RESERVED}; use crate::protocol::NetPacket; -use rand::Rng; -use rsa::pkcs8::der::Decode; -use rsa::{PublicKey, RsaPublicKey}; -use sha2::Digest; -use spki::{DecodePublicKey, EncodePublicKey}; use std::io; +#[cfg(feature = "server_encrypt")] +use crate::protocol::body::{RsaSecretBody, RSA_ENCRYPTION_RESERVED}; +#[cfg(feature = "server_encrypt")] +use rand::Rng; +#[cfg(feature = "server_encrypt")] +use rsa::pkcs8::der::Decode; +#[cfg(feature = "server_encrypt")] +use rsa::{PublicKey, RsaPublicKey}; +#[cfg(feature = "server_encrypt")] +use sha2::Digest; +#[cfg(feature = "server_encrypt")] +use spki::{DecodePublicKey, EncodePublicKey}; + #[derive(Clone)] pub struct RsaCipher { + #[cfg(feature = "server_encrypt")] inner: Inner, } - +#[cfg(feature = "server_encrypt")] #[derive(Clone)] struct Inner { public_key: RsaPublicKey, } impl RsaCipher { + #[cfg(feature = "server_encrypt")] pub fn new(der: &[u8]) -> io::Result { match RsaPublicKey::from_public_key_der(der) { Ok(public_key) => { @@ -30,6 +39,11 @@ impl RsaCipher { )), } } + #[cfg(not(feature = "server_encrypt"))] + pub fn new(_der: &[u8]) -> io::Result { + unimplemented!() + } + #[cfg(feature = "server_encrypt")] pub fn finger(&self) -> io::Result { match self.inner.public_key.to_public_key_der() { Ok(der) => match rsa::pkcs8::SubjectPublicKeyInfo::from_der(der.as_bytes()) { @@ -51,9 +65,21 @@ impl RsaCipher { )), } } + #[cfg(not(feature = "server_encrypt"))] + pub fn finger(&self) -> io::Result { + unimplemented!() + } } impl RsaCipher { + #[cfg(not(feature = "server_encrypt"))] + pub fn encrypt + AsMut<[u8]>>( + &self, + _net_packet: &mut NetPacket, + ) -> io::Result>> { + unimplemented!() + } + #[cfg(feature = "server_encrypt")] /// net_packet 必须预留足够长度 pub fn encrypt + AsMut<[u8]>>( &self, diff --git a/vnt/src/cipher/sm4_cbc.rs b/vnt/src/cipher/sm4_cbc.rs index 9b89680..0c302a5 100644 --- a/vnt/src/cipher/sm4_cbc.rs +++ b/vnt/src/cipher/sm4_cbc.rs @@ -116,7 +116,7 @@ impl Sm4CbcCipher { let mut out = [0u8; 1024 * 4]; let mut iv = [0u8; 16]; rand::thread_rng().fill_bytes(&mut iv); - if net_packet.buffer().len() > 1024 * 4 - 32 { + if net_packet.data_len() > 1024 * 4 - 32 { log::error!( "数据异常,长度{}大于1024 * 4 - 32", net_packet.buffer().len() @@ -125,10 +125,9 @@ impl Sm4CbcCipher { } match self.cipher.encrypt(net_packet.buffer(), &iv, &mut out) { Ok(len) => { - out[len..len + 16].copy_from_slice(&iv); net_packet.set_data_len(HEAD_LEN + len + 16)?; - net_packet.set_payload(&out[..len + 16])?; - net_packet.set_encrypt_flag(true); + net_packet.payload_mut()[..len].copy_from_slice(&out[..len]); + net_packet.payload_mut()[len..].copy_from_slice(&iv); if let Some(finger) = &self.finger { let mut nonce_raw = [0; 12]; nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); @@ -144,6 +143,7 @@ impl Sm4CbcCipher { net_packet.buffer_mut()[src_data_len..].copy_from_slice(&finger); } + net_packet.set_encrypt_flag(true); Ok(()) } Err(e) => Err(io::Error::new( diff --git a/vnt/src/protocol/mod.rs b/vnt/src/protocol/mod.rs index e1db894..f5bfc54 100644 --- a/vnt/src/protocol/mod.rs +++ b/vnt/src/protocol/mod.rs @@ -155,7 +155,7 @@ impl> NetPacket { } /// 网关通信的标识 pub fn is_gateway(&self) -> bool { - self.buffer.as_ref()[0] & 0x50 == 0x50 + self.buffer.as_ref()[0] & 0x40 == 0x40 } pub fn version(&self) -> Version { Version::from(self.buffer.as_ref()[0] & 0x0F) @@ -198,6 +198,7 @@ impl + AsMut<[u8]>> NetPacket { } pub fn set_gateway_flag(&mut self, is_gateway: bool) { if is_gateway { + // 后面的版本再改为0x40,改了之后不兼容1.2.5之前的版本 self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x50 } else { self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF