From b9fe5e0fe25af24d3269ffed506e51ea6897e387 Mon Sep 17 00:00:00 2001 From: lubeilin <1791778603@qq.com> Date: Mon, 28 Aug 2023 23:13:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81aes=5Fcbc=E5=8A=A0=E5=AF=86?= =?UTF-8?q?=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnt-cli/src/main.rs | 6 +- vnt-jni/src/vnt_util.rs | 3 +- vnt/Cargo.toml | 2 + vnt/src/cipher/aes_c.rs | 93 ----------------- vnt/src/cipher/aes_cbc.rs | 128 +++++++++++++++++++++++ vnt/src/cipher/cipher.rs | 145 ++++++++++++++++++++++++++ vnt/src/cipher/finger.rs | 12 +-- vnt/src/cipher/mod.rs | 9 +- vnt/src/core/mod.rs | 16 +-- vnt/src/handle/tun_tap/tun_handler.rs | 2 + vnt/src/protocol/body.rs | 58 +++++++++++ vnt/src/protocol/mod.rs | 5 +- 12 files changed, 367 insertions(+), 112 deletions(-) delete mode 100644 vnt/src/cipher/aes_c.rs create mode 100644 vnt/src/cipher/aes_cbc.rs create mode 100644 vnt/src/cipher/cipher.rs diff --git a/vnt-cli/src/main.rs b/vnt-cli/src/main.rs index 47177d59..cbe2f78d 100644 --- a/vnt-cli/src/main.rs +++ b/vnt-cli/src/main.rs @@ -11,6 +11,7 @@ use tokio::signal; use tokio::signal::unix::{signal, SignalKind}; use common::args_parse::{ips_parse, out_ips_parse}; +use vnt::cipher::CipherModel; use vnt::core::{Config, Vnt, VntUtil}; use vnt::handle::handshake_handler::HandshakeEnum; use vnt::handle::registration_handler::ReqEnum; @@ -50,6 +51,7 @@ fn main() { opts.optflag("", "relay", "仅使用服务器转发"); opts.optopt("", "par", "任务并行度(必须为正整数)", ""); opts.optopt("", "thread", "线程数(必须为正整数)", ""); + opts.optopt("", "model", "加密模式", ""); //"后台运行时,查看其他设备列表" opts.optflag("", "list", "后台运行时,查看其他设备列表"); opts.optflag("", "all", "后台运行时,查看其他设备完整信息"); @@ -201,6 +203,7 @@ fn main() { return; } let thread_num = matches.opt_get::("thread").unwrap().unwrap_or(std::thread::available_parallelism().unwrap().get() * 2); + let cipher_model = matches.opt_get::("model").unwrap().unwrap_or(CipherModel::AesGcm); if thread_num == 0 { println!("--thread invalid"); return; @@ -211,7 +214,7 @@ fn main() { server_address, server_address_str, stun_server, in_ip, out_ip, password, simulate_multicast, mtu, - tcp_channel, virtual_ip, relay, server_encrypt, parallel); + tcp_channel, virtual_ip, relay, server_encrypt, parallel, cipher_model); let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().worker_threads(thread_num).build().unwrap(); runtime.block_on(main0(config, !unused_cmd)); std::process::exit(0); @@ -454,6 +457,7 @@ fn print_usage(program: &str, _opts: Options) { println!(" --relay 仅使用服务器转发,不使用p2p,默认情况允许使用p2p"); println!(" --par 任务并行度(必须为正整数),默认值为1"); println!(" --thread 线程数(必须为正整数),默认为核心数乘2"); + println!(" --model 加密模式,可选值 aes_gcm/aes_cbc,默认使用aes_gcm,通常情况使用aes_cbc性能更好"); println!(); println!(" --list {}", yellow("后台运行时,查看其他设备列表".to_string())); println!(" --all {}", yellow("后台运行时,查看其他设备完整信息".to_string())); diff --git a/vnt-jni/src/vnt_util.rs b/vnt-jni/src/vnt_util.rs index 00528616..4b1bc667 100644 --- a/vnt-jni/src/vnt_util.rs +++ b/vnt-jni/src/vnt_util.rs @@ -7,6 +7,7 @@ use jni::objects::{JClass, JObject, JString, JValue}; use jni::sys::jboolean; use jni::sys::{jint, jlong, jobject}; use jni::JNIEnv; +use vnt::cipher::CipherModel; use vnt::core::Config; use vnt::core::sync::VntUtilSync; use vnt::handle::registration_handler::{RegResponse, ReqEnum}; @@ -80,7 +81,7 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result { token, device_id, name, server_address, server_address_str, stun_server, vec![], - vec![], password, false, None, false, None, false,false,1); + vec![], password, false, None, false, None, false,false,1,CipherModel::AesGcm); match VntUtilSync::new(config) { Ok(vnt_util) => { Ok(vnt_util) diff --git a/vnt/Cargo.toml b/vnt/Cargo.toml index 35ba07dd..5f25604b 100644 --- a/vnt/Cargo.toml +++ b/vnt/Cargo.toml @@ -23,6 +23,8 @@ socket2 ={ version = "0.5.2", features = ["all"] } tokio = { version = "1.28.1", features = ["full"] } aes-gcm = {version="0.10.2", optional = true} ring = {version="0.16.20", optional = true} +cbc = "0.1.2" +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"]} diff --git a/vnt/src/cipher/aes_c.rs b/vnt/src/cipher/aes_c.rs deleted file mode 100644 index d317c21f..00000000 --- a/vnt/src/cipher/aes_c.rs +++ /dev/null @@ -1,93 +0,0 @@ -use std::io; -use crate::cipher::Finger; -use crate::protocol::NetPacket; -use sha2::Digest; -#[cfg(feature = "ring-cipher")] -use crate::cipher::ring_aes_gcm_cipher::AesGcmCipher; -#[cfg(not(feature = "ring-cipher"))] -use crate::cipher::aes_gcm_cipher::AesGcmCipher; - -#[derive(Clone)] -pub enum Cipher { - Aes((AesGcmCipher, Vec)), - None, -} - -impl Cipher { - pub fn new_password(password: Option, token: String) -> Self { - let finger = Finger::new(&token); - if let Some(password) = password { - let mut hasher = sha2::Sha256::new(); - hasher.update(password.as_bytes()); - let key: [u8; 32] = hasher.finalize().into(); - if password.len() < 8 { - let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger); - Cipher::Aes((aes, key[..16].to_vec())) - } else { - let aes = AesGcmCipher::new_256(key, finger); - Cipher::Aes((aes, key.to_vec())) - } - } else { - Cipher::None - } - } - pub fn new_key(key: [u8; 32], token: String) -> io::Result { - let finger = Finger::new(&token); - match key.len() { - 16 => { - let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger); - Ok(Cipher::Aes((aes, key[..16].to_vec()))) - } - 32 => { - let aes = AesGcmCipher::new_256(key, finger); - Ok(Cipher::Aes((aes, key.to_vec()))) - } - _ => { - Err(io::Error::new(io::ErrorKind::Other, "key error")) - } - } - } - pub fn decrypt_ipv4 + AsMut<[u8]>>(&self, net_packet: &mut NetPacket) -> io::Result<()> { - match self { - Cipher::Aes((aes_gcm, _)) => { - aes_gcm.decrypt_ipv4(net_packet) - } - Cipher::None => { - if net_packet.is_encrypt() { - return Err(io::Error::new(io::ErrorKind::Other, "not key")); - } - Ok(()) - } - } - } - pub fn encrypt_ipv4 + AsMut<[u8]>>(&self, net_packet: &mut NetPacket) -> io::Result<()> { - match self { - Cipher::Aes((aes_gcm, _)) => { - aes_gcm.encrypt_ipv4(net_packet) - } - Cipher::None => { - Ok(()) - } - } - } - pub fn check_finger>(&self, net_packet: &NetPacket) -> io::Result<()> { - match self { - Cipher::Aes((aes_gcm, _)) => { - aes_gcm.finger.check_finger(net_packet) - } - Cipher::None => { - Ok(()) - } - } - } - pub fn key(&self) -> Option<&[u8]> { - match self { - Cipher::Aes((_, key)) => { - Some(key) - } - Cipher::None => { - None - } - } - } -} \ No newline at end of file diff --git a/vnt/src/cipher/aes_cbc.rs b/vnt/src/cipher/aes_cbc.rs new file mode 100644 index 00000000..b91fc4dd --- /dev/null +++ b/vnt/src/cipher/aes_cbc.rs @@ -0,0 +1,128 @@ +use std::io; + +use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyIvInit}; +use rand::RngCore; + +use crate::cipher::Finger; +use crate::protocol::body::AesCbcSecretBody; +use crate::protocol::{HEAD_LEN, NetPacket}; + +type Aes128CbcEnc = cbc::Encryptor; +type Aes128CbcDec = cbc::Decryptor; +type Aes256CbcEnc = cbc::Encryptor; +type Aes256CbcDec = cbc::Decryptor; + +#[derive(Clone)] +pub struct AesCbcCipher { + pub(crate) cipher: AesCbcEnum, + pub(crate) finger: Finger, +} + +#[derive(Clone)] +pub enum AesCbcEnum { + AES128CBC([u8; 16]), + AES256CBC([u8; 32]), +} + +impl AesCbcCipher { + pub fn key(&self) -> &[u8] { + match &self.cipher { + AesCbcEnum::AES128CBC(key) => { key } + AesCbcEnum::AES256CBC(key) => { key } + } + } +} + +impl AesCbcCipher { + pub fn new_128(key: [u8; 16], finger: Finger) -> Self { + Self { + cipher: AesCbcEnum::AES128CBC(key), + finger, + } + } + pub fn new_256(key: [u8; 32], finger: Finger) -> Self { + Self { + cipher: AesCbcEnum::AES256CBC(key), + finger, + } + } + + pub fn decrypt_ipv4 + AsMut<[u8]>>(&self, net_packet: &mut NetPacket) -> io::Result<()> { + if !net_packet.is_encrypt() { + //未加密的数据直接丢弃 + return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); + } + if net_packet.payload().len() < 12 + 16 { + log::error!("数据异常,长度{}小于{}",net_packet.payload().len(),12+16); + return Err(io::Error::new(io::ErrorKind::Other, "data err")); + } + let mut iv = [0; 16]; + iv[0..4].copy_from_slice(&net_packet.source().octets()); + iv[4..8].copy_from_slice(&net_packet.destination().octets()); + iv[8] = net_packet.protocol().into(); + iv[9] = net_packet.transport_protocol(); + iv[10] = net_packet.is_gateway() as u8; + iv[11] = net_packet.source_ttl(); + iv[12..16].copy_from_slice(&self.finger.hash[0..4]); + + let mut secret_body = AesCbcSecretBody::new(net_packet.payload_mut())?; + let finger = self.finger.calculate_finger(&iv[..12], secret_body.en_body()); + if &finger != secret_body.finger() { + return Err(io::Error::new(io::ErrorKind::Other, "finger err")); + } + let rs = match &self.cipher { + AesCbcEnum::AES128CBC(key) => { Aes128CbcDec::new(&(*key).into(), &iv.into()).decrypt_padded_mut::(secret_body.en_body_mut()) } + AesCbcEnum::AES256CBC(key) => { Aes256CbcDec::new(&(*key).into(), &iv.into()).decrypt_padded_mut::(secret_body.en_body_mut()) } + }; + match rs { + Ok(buf) => { + let len = buf.len(); + net_packet.set_encrypt_flag(false); + //减去末尾的随机数 + net_packet.set_data_len(HEAD_LEN + len - 4)?; + Ok(()) + } + Err(e) => { + Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e))) + } + } + } + /// net_packet 必须预留足够长度 + /// data_len是有效载荷的长度 + pub fn encrypt_ipv4 + AsMut<[u8]>>(&self, net_packet: &mut NetPacket) -> io::Result<()> { + let mut iv = [0; 16]; + iv[0..4].copy_from_slice(&net_packet.source().octets()); + iv[4..8].copy_from_slice(&net_packet.destination().octets()); + iv[8] = net_packet.protocol().into(); + iv[9] = net_packet.transport_protocol(); + iv[10] = net_packet.is_gateway() as u8; + iv[11] = net_packet.source_ttl(); + iv[12..16].copy_from_slice(&self.finger.hash[0..4]); + //先扩充随机数 + let data_len = net_packet.data_len(); + net_packet.set_data_len(data_len + 16)?; + let mut secret_body = AesCbcSecretBody::new(net_packet.payload_mut())?; + secret_body.set_random(rand::thread_rng().next_u32()); + let p_len = secret_body.en_body().len(); + net_packet.set_data_len_max(); + let rs = match &self.cipher { + AesCbcEnum::AES128CBC(key) => { Aes128CbcEnc::new(&(*key).into(), &iv.into()).encrypt_padded_mut::(net_packet.payload_mut(), p_len) } + AesCbcEnum::AES256CBC(key) => { Aes256CbcEnc::new(&(*key).into(), &iv.into()).encrypt_padded_mut::(net_packet.payload_mut(), p_len) } + }; + return match rs { + Ok(buf) => { + let len = buf.len(); + let finger = self.finger.calculate_finger(&iv[..12], buf); + //设置实际长度 + net_packet.set_data_len(HEAD_LEN + len + finger.len())?; + let mut secret_body = AesCbcSecretBody::new(net_packet.payload_mut())?; + secret_body.set_finger(&finger)?; + net_packet.set_encrypt_flag(true); + Ok(()) + } + Err(e) => { + Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e))) + } + }; + } +} \ No newline at end of file diff --git a/vnt/src/cipher/cipher.rs b/vnt/src/cipher/cipher.rs new file mode 100644 index 00000000..cd7cc1d6 --- /dev/null +++ b/vnt/src/cipher/cipher.rs @@ -0,0 +1,145 @@ +use std::io; +use std::str::FromStr; +use crate::cipher::{aes_cbc, Finger}; +use crate::protocol::NetPacket; +use sha2::Digest; +#[cfg(feature = "ring-cipher")] +use crate::cipher::ring_aes_gcm_cipher::AesGcmCipher; +#[cfg(not(feature = "ring-cipher"))] +use crate::cipher::aes_gcm_cipher::AesGcmCipher; +use aes_cbc::AesCbcCipher; + +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum CipherModel { + AesGcm, + AesCbc, +} + +impl FromStr for CipherModel { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "aes_gcm" => { + Ok(CipherModel::AesGcm) + } + "aes_cbc" => { Ok(CipherModel::AesCbc) } + _ => { + Err(format!("not match '{}'", s)) + } + } + } +} + +#[derive(Clone)] +pub enum Cipher { + AesGcm((AesGcmCipher, Vec)), + AesCbc(AesCbcCipher), + None, +} + +impl Cipher { + pub fn new_password(model: CipherModel, password: Option, token: String) -> Self { + let finger = Finger::new(&token); + if let Some(password) = password { + let mut hasher = sha2::Sha256::new(); + hasher.update(password.as_bytes()); + let key: [u8; 32] = hasher.finalize().into(); + match model { + CipherModel::AesGcm => { + if password.len() < 8 { + let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger); + Cipher::AesGcm((aes, key[..16].to_vec())) + } else { + let aes = AesGcmCipher::new_256(key, finger); + Cipher::AesGcm((aes, key.to_vec())) + } + } + CipherModel::AesCbc => { + if password.len() < 8 { + let aes = AesCbcCipher::new_128(key[..16].try_into().unwrap(), finger); + Cipher::AesCbc(aes) + } else { + let aes = AesCbcCipher::new_256(key, finger); + Cipher::AesCbc(aes) + } + } + } + } else { + Cipher::None + } + } + pub fn new_key(key: [u8; 32], token: String) -> io::Result { + let finger = Finger::new(&token); + match key.len() { + 16 => { + let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger); + Ok(Cipher::AesGcm((aes, key[..16].to_vec()))) + } + 32 => { + let aes = AesGcmCipher::new_256(key, finger); + Ok(Cipher::AesGcm((aes, key.to_vec()))) + } + _ => { + Err(io::Error::new(io::ErrorKind::Other, "key error")) + } + } + } + pub fn decrypt_ipv4 + AsMut<[u8]>>(&self, net_packet: &mut NetPacket) -> io::Result<()> { + match self { + Cipher::AesGcm((aes_gcm, _)) => { + aes_gcm.decrypt_ipv4(net_packet) + } + Cipher::AesCbc(aes_cbc) => { + aes_cbc.decrypt_ipv4(net_packet).unwrap(); + Ok(()) + } + Cipher::None => { + if net_packet.is_encrypt() { + return Err(io::Error::new(io::ErrorKind::Other, "not key")); + } + Ok(()) + } + } + } + pub fn encrypt_ipv4 + AsMut<[u8]>>(&self, net_packet: &mut NetPacket) -> io::Result<()> { + match self { + Cipher::AesGcm((aes_gcm, _)) => { + aes_gcm.encrypt_ipv4(net_packet) + } + Cipher::AesCbc(aes_cbc) => { + aes_cbc.encrypt_ipv4(net_packet).unwrap(); + Ok(()) + } + Cipher::None => { + Ok(()) + } + } + } + pub fn check_finger>(&self, net_packet: &NetPacket) -> io::Result<()> { + match self { + Cipher::AesGcm((aes_gcm, _)) => { + aes_gcm.finger.check_finger(net_packet) + } + Cipher::AesCbc(aes_cbc) => { + aes_cbc.finger.check_finger(net_packet) + } + Cipher::None => { + Ok(()) + } + } + } + pub fn key(&self) -> Option<&[u8]> { + match self { + Cipher::AesGcm((_, key)) => { + Some(key) + } + Cipher::AesCbc(aes_cbc) => { + Some(aes_cbc.key()) + } + Cipher::None => { + None + } + } + } +} \ No newline at end of file diff --git a/vnt/src/cipher/finger.rs b/vnt/src/cipher/finger.rs index 431c996c..77ca91b1 100644 --- a/vnt/src/cipher/finger.rs +++ b/vnt/src/cipher/finger.rs @@ -2,11 +2,11 @@ use std::io; use sha2::Digest; -use crate::protocol::{body::ENCRYPTION_RESERVED, NetPacket}; +use crate::protocol::NetPacket; #[derive(Clone)] pub struct Finger { - hash: [u8; 32], + pub(crate) hash: [u8; 32], } impl Finger { @@ -22,8 +22,8 @@ impl Finger { return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); } let payload_len = net_packet.payload().len(); - if payload_len < ENCRYPTION_RESERVED { - log::error!("数据异常,长度小于{}",ENCRYPTION_RESERVED); + if payload_len < 12 { + log::error!("数据异常,长度小于{}",12); return Err(io::Error::new(io::ErrorKind::Other, "data err")); } let mut nonce_raw = [0; 12]; @@ -40,9 +40,9 @@ impl Finger { } Ok(()) } - pub fn calculate_finger(&self, nonce_raw: &[u8; 12], secret_body: &[u8]) -> [u8; 12] { + pub fn calculate_finger(&self, nonce: &[u8], secret_body: &[u8]) -> [u8; 12] { let mut hasher = sha2::Sha256::new(); - hasher.update(nonce_raw); + hasher.update(nonce); hasher.update(secret_body); hasher.update(&self.hash); let key: [u8; 32] = hasher.finalize().into(); diff --git a/vnt/src/cipher/mod.rs b/vnt/src/cipher/mod.rs index d3881aaa..2b64eefb 100644 --- a/vnt/src/cipher/mod.rs +++ b/vnt/src/cipher/mod.rs @@ -3,9 +3,12 @@ mod ring_aes_gcm_cipher; #[cfg(not(feature = "ring-cipher"))] mod aes_gcm_cipher; mod rsa_cipher; +mod aes_cbc; mod finger; -mod aes_c; +mod cipher; -pub use aes_c::Cipher; +pub use cipher::Cipher; pub use finger::Finger; -pub use rsa_cipher::RsaCipher; \ No newline at end of file +pub use rsa_cipher::RsaCipher; +pub use cipher::CipherModel; + diff --git a/vnt/src/core/mod.rs b/vnt/src/core/mod.rs index baa73f85..0289cee9 100644 --- a/vnt/src/core/mod.rs +++ b/vnt/src/core/mod.rs @@ -15,7 +15,7 @@ use crate::channel::channel::{Channel, Context}; use crate::channel::idle::Idle; use crate::channel::punch::{NatInfo, Punch}; use crate::channel::sender::ChannelSender; -use crate::cipher::{Cipher, RsaCipher}; +use crate::cipher::{Cipher, CipherModel, RsaCipher}; use crate::core::status::VntStatusManger; use crate::error::Error; use crate::external_route::{AllowExternalRoute, ExternalRoute}; @@ -185,7 +185,7 @@ impl VntUtil { }; let config = self.config.clone(); let vnt_status_manager = VntStatusManger::new(); - let client_cipher = Cipher::new_password(config.password.clone(), config.token.clone()); + let client_cipher = Cipher::new_password(config.cipher_model, config.password.clone(), config.token.clone()); let virtual_ip = response.virtual_ip; let virtual_gateway = response.virtual_gateway; let virtual_netmask = response.virtual_netmask; @@ -238,15 +238,15 @@ impl VntUtil { if config.tap { tap_handler::start(vnt_status_manager.worker("tap_handler"), channel_sender.clone(), device_reader, device_writer.clone(), igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), - client_cipher.clone(), self.server_cipher.clone(),config.parallel); + client_cipher.clone(), self.server_cipher.clone(), config.parallel); } else { tun_handler::start(vnt_status_manager.worker("tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(), igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), - client_cipher.clone(), self.server_cipher.clone(),config.parallel).await; + client_cipher.clone(), self.server_cipher.clone(), config.parallel).await; } #[cfg(any(target_os = "android"))] tun_handler::start(vnt_status_manager.worker("android tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(), - igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone(),config.parallel).await; + igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone(), config.parallel).await; //外部数据接收处理 let channel_recv_handler = ChannelDataHandler::new(current_device.clone(), device_list.clone(), @@ -266,7 +266,7 @@ impl VntUtil { tokio::spawn(udp_proxy.start()); } tokio::spawn(async move { - channel.start(channel_worker, tcp, 14, 65, relay,config.parallel).await + channel.start(channel_worker, tcp, 14, 65, relay, config.parallel).await }); } { @@ -390,6 +390,7 @@ pub struct Config { pub relay: bool, pub server_encrypt: bool, pub parallel: usize, + pub cipher_model: CipherModel, } @@ -403,7 +404,7 @@ impl Config { in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32)>, password: Option, simulate_multicast: bool, mtu: Option, tcp: bool, ip: Option, - relay: bool, server_encrypt: bool, parallel: usize, ) -> Self { + relay: bool, server_encrypt: bool, parallel: usize, cipher_model: CipherModel) -> Self { for x in stun_server.iter_mut() { if !x.contains(":") { x.push_str(":3478"); @@ -427,6 +428,7 @@ impl Config { relay, server_encrypt, parallel, + cipher_model, } } } \ No newline at end of file diff --git a/vnt/src/handle/tun_tap/tun_handler.rs b/vnt/src/handle/tun_tap/tun_handler.rs index b69d7527..c127a10d 100644 --- a/vnt/src/handle/tun_tap/tun_handler.rs +++ b/vnt/src/handle/tun_tap/tun_handler.rs @@ -122,6 +122,7 @@ pub async fn start(worker: VntWorker, sender: ChannelSender, async fn start_(sender: ChannelSender, device_reader: DeviceReader, mut buf_sender: BufSenderGroup) -> io::Result<()> { loop { let mut buf = POOL.alloc(4096); + buf[..12].fill(0); if sender.is_close() { return Ok(()); } @@ -148,6 +149,7 @@ async fn start_simple(sender: ChannelSender, if sender.is_close() { return Ok(()); } + buf[..12].fill(0); let len = device_reader.read(&mut buf[12..])? + 12; #[cfg(any(target_os = "macos"))] let mut buf = &mut buf[4..]; diff --git a/vnt/src/protocol/body.rs b/vnt/src/protocol/body.rs index ad9a54c3..4914bf79 100644 --- a/vnt/src/protocol/body.rs +++ b/vnt/src/protocol/body.rs @@ -131,6 +131,64 @@ impl> fmt::Debug for SecretBody { .finish() } } +/* aes_cbc加密数据体 + 0 15 31 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 数据体 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | random(32) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | finger(32) | + | finger(32) | + | finger(32) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + 注:finger用于快速校验数据是否被修改,上层可使用token、协议头参与计算finger, + 确保服务端和客户端都能感知修改(服务端不能解密也能校验指纹) + */ +pub struct AesCbcSecretBody { + buffer: B, +} +impl> AesCbcSecretBody { + pub fn new(buffer: B) -> io::Result> { + let len = buffer.as_ref().len(); + // 不能大于udp最大载荷长度 + if len < 16 || len > 65535 - 20 - 8 - 12 { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "length overflow", + )); + } + Ok(AesCbcSecretBody { buffer }) + } + pub fn en_body(&self) -> &[u8] { + let end = self.buffer.as_ref().len() - 12; + &self.buffer.as_ref()[..end] + } + pub fn finger(&self) -> &[u8] { + let end = self.buffer.as_ref().len(); + &self.buffer.as_ref()[end - 12..end] + } +} +impl + AsMut<[u8]>> AesCbcSecretBody { + pub fn set_random(&mut self, random: u32) { + let end = self.buffer.as_ref().len() - 12; + self.buffer.as_mut()[end - 4..end].copy_from_slice(&random.to_be_bytes()); + } + pub fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> { + if finger.len() != 12 { + return Err(io::Error::new(io::ErrorKind::InvalidData, "finger.len != 12")); + } + let end = self.buffer.as_ref().len(); + self.buffer.as_mut()[end - 12..end].copy_from_slice(finger); + Ok(()) + } + pub fn en_body_mut(&mut self) -> &mut [u8] { + let end = self.buffer.as_ref().len() - 12; + &mut self.buffer.as_mut()[..end] + } +} /* rsa加密数据体 0 15 31 diff --git a/vnt/src/protocol/mod.rs b/vnt/src/protocol/mod.rs index 592972b0..ea87e9e1 100644 --- a/vnt/src/protocol/mod.rs +++ b/vnt/src/protocol/mod.rs @@ -16,7 +16,7 @@ use crate::protocol::body::ENCRYPTION_RESERVED; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 注:e为是否加密标志,s为服务端通信包标志,u未使用 */ - +pub const HEAD_LEN: usize = 12; pub mod body; pub mod control_packet; @@ -245,6 +245,9 @@ impl + AsMut<[u8]>> NetPacket { self.data_len = data_len; Ok(()) } + pub fn set_data_len_max(&mut self) { + self.data_len = self.buffer.as_ref().len(); + } } impl> fmt::Debug for NetPacket {