支持aes_cbc加密算法
This commit is contained in:
+5
-1
@@ -11,6 +11,7 @@ use tokio::signal;
|
|||||||
use tokio::signal::unix::{signal, SignalKind};
|
use tokio::signal::unix::{signal, SignalKind};
|
||||||
|
|
||||||
use common::args_parse::{ips_parse, out_ips_parse};
|
use common::args_parse::{ips_parse, out_ips_parse};
|
||||||
|
use vnt::cipher::CipherModel;
|
||||||
use vnt::core::{Config, Vnt, VntUtil};
|
use vnt::core::{Config, Vnt, VntUtil};
|
||||||
use vnt::handle::handshake_handler::HandshakeEnum;
|
use vnt::handle::handshake_handler::HandshakeEnum;
|
||||||
use vnt::handle::registration_handler::ReqEnum;
|
use vnt::handle::registration_handler::ReqEnum;
|
||||||
@@ -50,6 +51,7 @@ fn main() {
|
|||||||
opts.optflag("", "relay", "仅使用服务器转发");
|
opts.optflag("", "relay", "仅使用服务器转发");
|
||||||
opts.optopt("", "par", "任务并行度(必须为正整数)", "<parallel>");
|
opts.optopt("", "par", "任务并行度(必须为正整数)", "<parallel>");
|
||||||
opts.optopt("", "thread", "线程数(必须为正整数)", "<thread>");
|
opts.optopt("", "thread", "线程数(必须为正整数)", "<thread>");
|
||||||
|
opts.optopt("", "model", "加密模式", "<model>");
|
||||||
//"后台运行时,查看其他设备列表"
|
//"后台运行时,查看其他设备列表"
|
||||||
opts.optflag("", "list", "后台运行时,查看其他设备列表");
|
opts.optflag("", "list", "后台运行时,查看其他设备列表");
|
||||||
opts.optflag("", "all", "后台运行时,查看其他设备完整信息");
|
opts.optflag("", "all", "后台运行时,查看其他设备完整信息");
|
||||||
@@ -201,6 +203,7 @@ fn main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let thread_num = matches.opt_get::<usize>("thread").unwrap().unwrap_or(std::thread::available_parallelism().unwrap().get() * 2);
|
let thread_num = matches.opt_get::<usize>("thread").unwrap().unwrap_or(std::thread::available_parallelism().unwrap().get() * 2);
|
||||||
|
let cipher_model = matches.opt_get::<CipherModel>("model").unwrap().unwrap_or(CipherModel::AesGcm);
|
||||||
if thread_num == 0 {
|
if thread_num == 0 {
|
||||||
println!("--thread invalid");
|
println!("--thread invalid");
|
||||||
return;
|
return;
|
||||||
@@ -211,7 +214,7 @@ fn main() {
|
|||||||
server_address, server_address_str,
|
server_address, server_address_str,
|
||||||
stun_server, in_ip,
|
stun_server, in_ip,
|
||||||
out_ip, password, simulate_multicast, mtu,
|
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();
|
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().worker_threads(thread_num).build().unwrap();
|
||||||
runtime.block_on(main0(config, !unused_cmd));
|
runtime.block_on(main0(config, !unused_cmd));
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
@@ -454,6 +457,7 @@ fn print_usage(program: &str, _opts: Options) {
|
|||||||
println!(" --relay 仅使用服务器转发,不使用p2p,默认情况允许使用p2p");
|
println!(" --relay 仅使用服务器转发,不使用p2p,默认情况允许使用p2p");
|
||||||
println!(" --par <parallel> 任务并行度(必须为正整数),默认值为1");
|
println!(" --par <parallel> 任务并行度(必须为正整数),默认值为1");
|
||||||
println!(" --thread <thread> 线程数(必须为正整数),默认为核心数乘2");
|
println!(" --thread <thread> 线程数(必须为正整数),默认为核心数乘2");
|
||||||
|
println!(" --model <model> 加密模式,可选值 aes_gcm/aes_cbc,默认使用aes_gcm,通常情况使用aes_cbc性能更好");
|
||||||
println!();
|
println!();
|
||||||
println!(" --list {}", yellow("后台运行时,查看其他设备列表".to_string()));
|
println!(" --list {}", yellow("后台运行时,查看其他设备列表".to_string()));
|
||||||
println!(" --all {}", yellow("后台运行时,查看其他设备完整信息".to_string()));
|
println!(" --all {}", yellow("后台运行时,查看其他设备完整信息".to_string()));
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use jni::objects::{JClass, JObject, JString, JValue};
|
|||||||
use jni::sys::jboolean;
|
use jni::sys::jboolean;
|
||||||
use jni::sys::{jint, jlong, jobject};
|
use jni::sys::{jint, jlong, jobject};
|
||||||
use jni::JNIEnv;
|
use jni::JNIEnv;
|
||||||
|
use vnt::cipher::CipherModel;
|
||||||
use vnt::core::Config;
|
use vnt::core::Config;
|
||||||
use vnt::core::sync::VntUtilSync;
|
use vnt::core::sync::VntUtilSync;
|
||||||
use vnt::handle::registration_handler::{RegResponse, ReqEnum};
|
use vnt::handle::registration_handler::{RegResponse, ReqEnum};
|
||||||
@@ -80,7 +81,7 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
|
|||||||
token, device_id, name,
|
token, device_id, name,
|
||||||
server_address, server_address_str,
|
server_address, server_address_str,
|
||||||
stun_server, vec![],
|
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) {
|
match VntUtilSync::new(config) {
|
||||||
Ok(vnt_util) => {
|
Ok(vnt_util) => {
|
||||||
Ok(vnt_util)
|
Ok(vnt_util)
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ socket2 ={ version = "0.5.2", features = ["all"] }
|
|||||||
tokio = { version = "1.28.1", features = ["full"] }
|
tokio = { version = "1.28.1", features = ["full"] }
|
||||||
aes-gcm = {version="0.10.2", optional = true}
|
aes-gcm = {version="0.10.2", optional = true}
|
||||||
ring = {version="0.16.20", 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"]}
|
stun-format = {version="1.0.1",features=["fmt","rfc3489"]}
|
||||||
rsa = {version="0.7.2", features = [] }
|
rsa = {version="0.7.2", features = [] }
|
||||||
spki = {version="0.6.0",features=["fingerprint","alloc"]}
|
spki = {version="0.6.0",features=["fingerprint","alloc"]}
|
||||||
|
|||||||
@@ -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<u8>)),
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Cipher {
|
|
||||||
pub fn new_password(password: Option<String>, 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<Self> {
|
|
||||||
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<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> 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<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> io::Result<()> {
|
|
||||||
match self {
|
|
||||||
Cipher::Aes((aes_gcm, _)) => {
|
|
||||||
aes_gcm.encrypt_ipv4(net_packet)
|
|
||||||
}
|
|
||||||
Cipher::None => {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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<aes::Aes128>;
|
||||||
|
type Aes128CbcDec = cbc::Decryptor<aes::Aes128>;
|
||||||
|
type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
|
||||||
|
type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
|
||||||
|
|
||||||
|
#[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<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> 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::<Pkcs7>(secret_body.en_body_mut()) }
|
||||||
|
AesCbcEnum::AES256CBC(key) => { Aes256CbcDec::new(&(*key).into(), &iv.into()).decrypt_padded_mut::<Pkcs7>(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<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> 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::<Pkcs7>(net_packet.payload_mut(), p_len) }
|
||||||
|
AesCbcEnum::AES256CBC(key) => { Aes256CbcEnc::new(&(*key).into(), &iv.into()).encrypt_padded_mut::<Pkcs7>(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)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Self, Self::Err> {
|
||||||
|
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<u8>)),
|
||||||
|
AesCbc(AesCbcCipher),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cipher {
|
||||||
|
pub fn new_password(model: CipherModel, password: Option<String>, 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<Self> {
|
||||||
|
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<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> 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<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> 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<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,11 +2,11 @@ use std::io;
|
|||||||
|
|
||||||
use sha2::Digest;
|
use sha2::Digest;
|
||||||
|
|
||||||
use crate::protocol::{body::ENCRYPTION_RESERVED, NetPacket};
|
use crate::protocol::NetPacket;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Finger {
|
pub struct Finger {
|
||||||
hash: [u8; 32],
|
pub(crate) hash: [u8; 32],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Finger {
|
impl Finger {
|
||||||
@@ -22,8 +22,8 @@ impl Finger {
|
|||||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||||
}
|
}
|
||||||
let payload_len = net_packet.payload().len();
|
let payload_len = net_packet.payload().len();
|
||||||
if payload_len < ENCRYPTION_RESERVED {
|
if payload_len < 12 {
|
||||||
log::error!("数据异常,长度小于{}",ENCRYPTION_RESERVED);
|
log::error!("数据异常,长度小于{}",12);
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
}
|
}
|
||||||
let mut nonce_raw = [0; 12];
|
let mut nonce_raw = [0; 12];
|
||||||
@@ -40,9 +40,9 @@ impl Finger {
|
|||||||
}
|
}
|
||||||
Ok(())
|
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();
|
let mut hasher = sha2::Sha256::new();
|
||||||
hasher.update(nonce_raw);
|
hasher.update(nonce);
|
||||||
hasher.update(secret_body);
|
hasher.update(secret_body);
|
||||||
hasher.update(&self.hash);
|
hasher.update(&self.hash);
|
||||||
let key: [u8; 32] = hasher.finalize().into();
|
let key: [u8; 32] = hasher.finalize().into();
|
||||||
|
|||||||
@@ -3,9 +3,12 @@ mod ring_aes_gcm_cipher;
|
|||||||
#[cfg(not(feature = "ring-cipher"))]
|
#[cfg(not(feature = "ring-cipher"))]
|
||||||
mod aes_gcm_cipher;
|
mod aes_gcm_cipher;
|
||||||
mod rsa_cipher;
|
mod rsa_cipher;
|
||||||
|
mod aes_cbc;
|
||||||
mod finger;
|
mod finger;
|
||||||
mod aes_c;
|
mod cipher;
|
||||||
|
|
||||||
pub use aes_c::Cipher;
|
pub use cipher::Cipher;
|
||||||
pub use finger::Finger;
|
pub use finger::Finger;
|
||||||
pub use rsa_cipher::RsaCipher;
|
pub use rsa_cipher::RsaCipher;
|
||||||
|
pub use cipher::CipherModel;
|
||||||
|
|
||||||
|
|||||||
+9
-7
@@ -15,7 +15,7 @@ use crate::channel::channel::{Channel, Context};
|
|||||||
use crate::channel::idle::Idle;
|
use crate::channel::idle::Idle;
|
||||||
use crate::channel::punch::{NatInfo, Punch};
|
use crate::channel::punch::{NatInfo, Punch};
|
||||||
use crate::channel::sender::ChannelSender;
|
use crate::channel::sender::ChannelSender;
|
||||||
use crate::cipher::{Cipher, RsaCipher};
|
use crate::cipher::{Cipher, CipherModel, RsaCipher};
|
||||||
use crate::core::status::VntStatusManger;
|
use crate::core::status::VntStatusManger;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::external_route::{AllowExternalRoute, ExternalRoute};
|
use crate::external_route::{AllowExternalRoute, ExternalRoute};
|
||||||
@@ -185,7 +185,7 @@ impl VntUtil {
|
|||||||
};
|
};
|
||||||
let config = self.config.clone();
|
let config = self.config.clone();
|
||||||
let vnt_status_manager = VntStatusManger::new();
|
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_ip = response.virtual_ip;
|
||||||
let virtual_gateway = response.virtual_gateway;
|
let virtual_gateway = response.virtual_gateway;
|
||||||
let virtual_netmask = response.virtual_netmask;
|
let virtual_netmask = response.virtual_netmask;
|
||||||
@@ -238,15 +238,15 @@ impl VntUtil {
|
|||||||
if config.tap {
|
if config.tap {
|
||||||
tap_handler::start(vnt_status_manager.worker("tap_handler"), channel_sender.clone(), device_reader, device_writer.clone(),
|
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(),
|
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 {
|
} else {
|
||||||
tun_handler::start(vnt_status_manager.worker("tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(),
|
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(),
|
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"))]
|
#[cfg(any(target_os = "android"))]
|
||||||
tun_handler::start(vnt_status_manager.worker("android tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(),
|
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(),
|
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(udp_proxy.start());
|
||||||
}
|
}
|
||||||
tokio::spawn(async move {
|
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 relay: bool,
|
||||||
pub server_encrypt: bool,
|
pub server_encrypt: bool,
|
||||||
pub parallel: usize,
|
pub parallel: usize,
|
||||||
|
pub cipher_model: CipherModel,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -403,7 +404,7 @@ impl Config {
|
|||||||
in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32)>,
|
in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32)>,
|
||||||
password: Option<String>, simulate_multicast: bool, mtu: Option<u16>, tcp: bool,
|
password: Option<String>, simulate_multicast: bool, mtu: Option<u16>, tcp: bool,
|
||||||
ip: Option<Ipv4Addr>,
|
ip: Option<Ipv4Addr>,
|
||||||
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() {
|
for x in stun_server.iter_mut() {
|
||||||
if !x.contains(":") {
|
if !x.contains(":") {
|
||||||
x.push_str(":3478");
|
x.push_str(":3478");
|
||||||
@@ -427,6 +428,7 @@ impl Config {
|
|||||||
relay,
|
relay,
|
||||||
server_encrypt,
|
server_encrypt,
|
||||||
parallel,
|
parallel,
|
||||||
|
cipher_model,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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<()> {
|
async fn start_(sender: ChannelSender, device_reader: DeviceReader, mut buf_sender: BufSenderGroup) -> io::Result<()> {
|
||||||
loop {
|
loop {
|
||||||
let mut buf = POOL.alloc(4096);
|
let mut buf = POOL.alloc(4096);
|
||||||
|
buf[..12].fill(0);
|
||||||
if sender.is_close() {
|
if sender.is_close() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -148,6 +149,7 @@ async fn start_simple(sender: ChannelSender,
|
|||||||
if sender.is_close() {
|
if sender.is_close() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
buf[..12].fill(0);
|
||||||
let len = device_reader.read(&mut buf[12..])? + 12;
|
let len = device_reader.read(&mut buf[12..])? + 12;
|
||||||
#[cfg(any(target_os = "macos"))]
|
#[cfg(any(target_os = "macos"))]
|
||||||
let mut buf = &mut buf[4..];
|
let mut buf = &mut buf[4..];
|
||||||
|
|||||||
@@ -131,6 +131,64 @@ impl<B: AsRef<[u8]>> fmt::Debug for SecretBody<B> {
|
|||||||
.finish()
|
.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<B> {
|
||||||
|
buffer: B,
|
||||||
|
}
|
||||||
|
impl<B: AsRef<[u8]>> AesCbcSecretBody<B> {
|
||||||
|
pub fn new(buffer: B) -> io::Result<AesCbcSecretBody<B>> {
|
||||||
|
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<B: AsRef<[u8]> + AsMut<[u8]>> AesCbcSecretBody<B> {
|
||||||
|
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加密数据体
|
/* rsa加密数据体
|
||||||
0 15 31
|
0 15 31
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use crate::protocol::body::ENCRYPTION_RESERVED;
|
|||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
注:e为是否加密标志,s为服务端通信包标志,u未使用
|
注:e为是否加密标志,s为服务端通信包标志,u未使用
|
||||||
*/
|
*/
|
||||||
|
pub const HEAD_LEN: usize = 12;
|
||||||
|
|
||||||
pub mod body;
|
pub mod body;
|
||||||
pub mod control_packet;
|
pub mod control_packet;
|
||||||
@@ -245,6 +245,9 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
|||||||
self.data_len = data_len;
|
self.data_len = data_len;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
pub fn set_data_len_max(&mut self) {
|
||||||
|
self.data_len = self.buffer.as_ref().len();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: AsRef<[u8]>> fmt::Debug for NetPacket<B> {
|
impl<B: AsRef<[u8]>> fmt::Debug for NetPacket<B> {
|
||||||
|
|||||||
Reference in New Issue
Block a user