From 0472b1590ed0f35f560d98b09a57d9c4cdb22fa0 Mon Sep 17 00:00:00 2001 From: lubeilin <1791778603@qq.com> Date: Sun, 27 Aug 2023 11:58:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=9C=8D=E5=8A=A1=E7=AB=AF?= =?UTF-8?q?=E5=8A=A0=E5=AF=86=E3=80=81=E5=AE=8C=E5=96=84=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E7=AB=AF=E5=8A=A0=E5=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/rust.yml | 28 +- README.md | 2 +- common/Cargo.toml | 2 +- vnt-cli/Cargo.toml | 3 +- vnt-cli/README.md | 4 +- vnt-cli/src/command/entity.rs | 2 + vnt-cli/src/command/mod.rs | 4 + vnt-cli/src/command/server.rs | 26 +- vnt-cli/src/console_out/mod.rs | 31 +- vnt-cli/src/console_out/table.rs | 2 +- vnt-cli/src/main.rs | 245 ++++++++--- vnt/Cargo.toml | 6 +- vnt/proto/message.proto | 16 + vnt/src/channel/channel.rs | 144 +++--- vnt/src/cipher/aes_c.rs | 93 ++++ vnt/src/cipher/aes_gcm_cipher.rs | 156 +++---- vnt/src/cipher/finger.rs | 46 ++ vnt/src/cipher/mod.rs | 11 +- vnt/src/cipher/ring_cipher.rs | 157 +++---- vnt/src/cipher/rsa_cipher.rs | 99 +++++ vnt/src/core/mod.rs | 93 ++-- vnt/src/core/sync.rs | 13 +- vnt/src/handle/handshake_handler.rs | 211 +++++++++ vnt/src/handle/heartbeat_handler.rs | 78 ++-- vnt/src/handle/mod.rs | 5 +- vnt/src/handle/punch_handler.rs | 32 +- vnt/src/handle/recv_handler.rs | 528 +++++++++++++--------- vnt/src/handle/registration_handler.rs | 49 ++- vnt/src/handle/tun_tap/channel_group.rs | 23 + vnt/src/handle/tun_tap/mod.rs | 170 +++---- vnt/src/handle/tun_tap/tap_handler.rs | 52 ++- vnt/src/handle/tun_tap/tun_handler.rs | 72 +-- vnt/src/ip_proxy/icmp_proxy.rs | 53 +-- vnt/src/ip_proxy/mod.rs | 6 +- vnt/src/ip_proxy/tcp_proxy.rs | 35 +- vnt/src/proto/message.rs | 563 ++++++++++++++++++++++-- vnt/src/protocol/body.rs | 205 +++++++++ vnt/src/protocol/error_packet.rs | 5 + vnt/src/protocol/ip_turn_packet.rs | 62 +-- vnt/src/protocol/mod.rs | 79 +++- vnt/src/protocol/service_packet.rs | 13 + vnt/src/tun_tap_device/linux.rs | 9 +- 42 files changed, 2546 insertions(+), 887 deletions(-) create mode 100644 vnt/src/cipher/aes_c.rs create mode 100644 vnt/src/cipher/finger.rs create mode 100644 vnt/src/cipher/rsa_cipher.rs create mode 100644 vnt/src/handle/handshake_handler.rs create mode 100644 vnt/src/handle/tun_tap/channel_group.rs create mode 100644 vnt/src/protocol/body.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index bec3c97..4a9dd61 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -77,6 +77,9 @@ jobs: - TARGET: x86_64-pc-windows-msvc # tested on a windows machine OS: windows-latest FEATURES: ring-cipher + - TARGET: mipsel-unknown-linux-musl # openwrt + OS: ubuntu-latest + FEATURES: normal # needs: test runs-on: ${{ matrix.OS }} env: @@ -102,22 +105,45 @@ jobs: # dependencies are only needed on ubuntu as that's the only place where # we make cross-compilation if [[ $OS =~ ^ubuntu.*$ ]]; then - sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools + sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools gcc-mipsel-linux-gnu fi # some additional configuration for cross-compilation on linux cat >>~/.cargo/config <` -提升通信安全性,使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密。使用相同密码的客户端才能通信 +提升通信安全性,使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密(包括中继数据)。使用相同密码的客户端才能通信 | 密码位数 | 加密算法 | |---------|-------| | 小于8 | AES128-GCM | 大于等于8 | AES256-GCM | +### -W +开启和服务端通信加密,可以避免中间人攻击 ### -m 模拟组播,高频使用组播通信时,可以尝试开启此参数,默认情况下会把组播当作广播发给所有节点 diff --git a/vnt-cli/src/command/entity.rs b/vnt-cli/src/command/entity.rs index 9140522..2e6e555 100644 --- a/vnt-cli/src/command/entity.rs +++ b/vnt-cli/src/command/entity.rs @@ -31,4 +31,6 @@ pub struct DeviceItem { pub nat_traversal_type: String, pub rt: String, pub status: String, + pub client_secret: bool, + pub current_client_secret:bool, } \ No newline at end of file diff --git a/vnt-cli/src/command/mod.rs b/vnt-cli/src/command/mod.rs index 18f786d..db659f6 100644 --- a/vnt-cli/src/command/mod.rs +++ b/vnt-cli/src/command/mod.rs @@ -75,6 +75,7 @@ pub fn command_list(vnt: &Vnt) -> Vec { let info = vnt.current_device(); let device_list = vnt.device_list(); let mut list = Vec::new(); + let current_client_secret = vnt.client_encrypt(); for peer in device_list { let name = peer.name; let virtual_ip = peer.virtual_ip.to_string(); @@ -105,6 +106,7 @@ pub fn command_list(vnt: &Vnt) -> Vec { ("relay".to_string(), "".to_string()) }; let status = format!("{:?}", peer.status); + let client_secret = peer.client_secret; let item = DeviceItem { name, virtual_ip, @@ -114,6 +116,8 @@ pub fn command_list(vnt: &Vnt) -> Vec { nat_traversal_type, rt, status, + client_secret, + current_client_secret, }; list.push(item); } diff --git a/vnt-cli/src/command/server.rs b/vnt-cli/src/command/server.rs index 83eff1d..676caae 100644 --- a/vnt-cli/src/command/server.rs +++ b/vnt-cli/src/command/server.rs @@ -1,5 +1,5 @@ use std::io; -use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; +use std::io::Write; use tokio::net::UdpSocket; use vnt::core::Vnt; @@ -15,27 +15,11 @@ impl CommandServer { impl CommandServer { pub async fn start(self, vnt: Vnt) -> io::Result<()> { - let mut port = 21637 as u16; - let udp = loop { - match UdpSocket::bind(SocketAddr::V4(SocketAddrV4::new( - Ipv4Addr::new(127, 0, 0, 1), - port, - ))).await { - Ok(udp) => { - break udp; - } - Err(e) => { - if e.kind() == io::ErrorKind::AddrInUse { - port += 1; - } else { - log::error!("创建udp失败 {:?}", e); - return Err(e); - } - } - } - }; + let udp = UdpSocket::bind("127.0.0.1:0").await?; let path_buf = crate::app_home()?.join("command-port"); - std::fs::write(path_buf, udp.local_addr()?.port().to_string())?; + let mut file = std::fs::File::create(path_buf)?; + file.write_all(udp.local_addr()?.port().to_string().as_bytes())?; + file.sync_all()?; let mut buf = [0u8; 64]; loop { let (len, addr) = udp.recv_from(&mut buf).await?; diff --git a/vnt-cli/src/console_out/mod.rs b/vnt-cli/src/console_out/mod.rs index 38dc119..9069aa6 100644 --- a/vnt-cli/src/console_out/mod.rs +++ b/vnt-cli/src/console_out/mod.rs @@ -56,18 +56,27 @@ pub fn console_device_list(mut list: Vec) { ("Rt".to_string(), Style::new())]); for item in list { if &item.status == "Online" { - if &item.nat_traversal_type == "p2p" { - out_list.push(vec![(item.name, Style::new().green()), - (item.virtual_ip, Style::new().green()), - (item.status, Style::new().green()), - (item.nat_traversal_type, Style::new().green()), - (item.rt, Style::new().green())]); + if item.client_secret != item.current_client_secret { + //加密状态不一致,无法通信的 + out_list.push(vec![(item.name, Style::new().red()), + (item.virtual_ip, Style::new().red()), + (item.status, Style::new().red()), + ("".to_string(), Style::new().red()), + ("".to_string(), Style::new().red())]); } else { - out_list.push(vec![(item.name, Style::new().yellow()), - (item.virtual_ip, Style::new().yellow()), - (item.status, Style::new().yellow()), - (item.nat_traversal_type, Style::new().yellow()), - (item.rt, Style::new().yellow())]); + if &item.nat_traversal_type == "p2p" { + out_list.push(vec![(item.name, Style::new().green()), + (item.virtual_ip, Style::new().green()), + (item.status, Style::new().green()), + (item.nat_traversal_type, Style::new().green()), + (item.rt, Style::new().green())]); + } else { + out_list.push(vec![(item.name, Style::new().yellow()), + (item.virtual_ip, Style::new().yellow()), + (item.status, Style::new().yellow()), + (item.nat_traversal_type, Style::new().yellow()), + (item.rt, Style::new().yellow())]); + } } } else { out_list.push(vec![(item.name, Style::new().color256(102)), diff --git a/vnt-cli/src/console_out/table.rs b/vnt-cli/src/console_out/table.rs index c117b95..8d7d791 100644 --- a/vnt-cli/src/console_out/table.rs +++ b/vnt-cli/src/console_out/table.rs @@ -7,7 +7,7 @@ pub fn println_table(table: Vec>) { let mut width_list = vec![0; table[0].len()]; for in_list in table.iter() { for (index, (item, _)) in in_list.iter().enumerate() { - let width = console::measure_text_width(item) + 6; + let width = console::measure_text_width(item) + 4; if width_list[index] < width { width_list[index] = width; } diff --git a/vnt-cli/src/main.rs b/vnt-cli/src/main.rs index 3ee8c8f..babc697 100644 --- a/vnt-cli/src/main.rs +++ b/vnt-cli/src/main.rs @@ -2,11 +2,17 @@ use std::io; use std::net::{Ipv4Addr, ToSocketAddrs}; use std::path::PathBuf; use std::str::FromStr; + use console::style; use getopts::Options; use tokio::io::{AsyncBufReadExt, BufReader}; +use tokio::signal; +#[cfg(unix)] +use tokio::signal::unix::{signal, SignalKind}; + use common::args_parse::{ips_parse, out_ips_parse}; -use vnt::core::{Config, VntUtil}; +use vnt::core::{Config, Vnt, VntUtil}; +use vnt::handle::handshake_handler::HandshakeEnum; use vnt::handle::registration_handler::ReqEnum; mod command; @@ -28,24 +34,26 @@ async fn main() { } async fn main0() { + let _ = log4rs::init_file("log4rs.yaml", Default::default()); let args: Vec = std::env::args().collect(); let program = args[0].clone(); let mut opts = Options::new(); - opts.optopt("k", "", "必选,使用相同的token,就能组建一个局域网络", ""); - opts.optopt("n", "", "给设备一个名字,便于区分不同设备,默认使用系统版本", ""); - opts.optopt("d", "", "设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip", ""); - opts.optflag("c", "", "关闭交互式命令,使用此参数禁用控制台输入"); + opts.optopt("k", "", "组网标识", ""); + opts.optopt("n", "", "设备名称", ""); + opts.optopt("d", "", "设备标识", ""); + opts.optflag("c", "", "关闭交互式命令"); opts.optopt("s", "", "注册和中继服务器地址", ""); - opts.optmulti("e", "", "stun服务器,用于探测NAT类型,可多次指定,如-e addr1 -e addr2", ""); - opts.optflag("a", "", "使用tap模式,默认使用tun模式"); - opts.optmulti("i", "", "配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3 \n表示允许接收网段192.168.0.0/24的数据并转发到10.26.0.3,可指定多个网段", ""); - opts.optmulti("o", "", "配置点对网时使用,-o 192.168.0.0/24 \n表示允许将数据转发到192.168.0.0/24,可指定多个网段", ""); - opts.optopt("w", "", "使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信", ""); - opts.optflag("m", "", "模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送"); + opts.optmulti("e", "", "stun服务器", ""); + opts.optflag("a", "", "使用tap模式"); + opts.optmulti("i", "", "配置点对网(IP代理)入站时使用", ""); + opts.optmulti("o", "", "配置点对网出站时使用", ""); + opts.optopt("w", "", "客户端加密", ""); + opts.optflag("W", "", "服务端加密"); + opts.optflag("m", "", "模拟组播"); opts.optopt("u", "", "自定义mtu(默认为1430)", ""); - opts.optflag("", "tcp", "和服务端使用tcp通信,默认使用udp,一般来说udp延迟和消耗更低"); - opts.optopt("", "ip", "指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配", ""); - opts.optflag("", "relay", "仅使用服务器转发,不使用p2p,默认情况允许使用p2p"); + opts.optflag("", "tcp", "tcp"); + opts.optopt("", "ip", "指定虚拟ip", ""); + opts.optflag("", "relay", "仅使用服务器转发"); //"后台运行时,查看其他设备列表" opts.optflag("", "list", "后台运行时,查看其他设备列表"); opts.optflag("", "all", "后台运行时,查看其他设备完整信息"); @@ -117,7 +125,7 @@ async fn main0() { return; } let name = matches.opt_get_default("n", os_info::get().to_string()).unwrap(); - let server_address_str = matches.opt_get_default("s", "nat1.wherewego.top:29871".to_string()).unwrap(); + let server_address_str = matches.opt_get_default("s", "nat1.wherewego.top:29872".to_string()).unwrap(); let server_address = match server_address_str.to_socket_addrs() { Ok(mut addr) => { if let Some(addr) = addr.next() { @@ -162,6 +170,7 @@ async fn main0() { } }; let password: Option = matches.opt_get("w").unwrap(); + let server_encrypt = matches.opt_present("W"); let simulate_multicast = matches.opt_present("m"); let unused_cmd = matches.opt_present("c"); let mtu: Option = matches.opt_get("u").unwrap(); @@ -190,45 +199,101 @@ async fn main0() { } let tcp_channel = matches.opt_present("tcp"); let relay = matches.opt_present("relay"); + println!("version 1.2.0"); let config = Config::new(tap, token, device_id, name, server_address, server_address_str, stun_server, in_ip, - out_ip, password, simulate_multicast, mtu, tcp_channel, virtual_ip, relay); + out_ip, password, simulate_multicast, mtu, + tcp_channel, virtual_ip, relay, server_encrypt); let mut vnt_util = VntUtil::new(config).await.unwrap(); + let mut conn_count = 0; let response = loop { - match vnt_util.connect().await { + if conn_count > 0 { + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + } + conn_count += 1; + if let Err(e) = vnt_util.connect().await { + println!("connect server failed {}", e); + return; + } + match vnt_util.handshake().await { Ok(response) => { - break response; + if server_encrypt { + let finger = response.unwrap().finger().unwrap(); + println!("{}{}", green("server fingerprint:".to_string()), finger); + match vnt_util.secret_handshake().await { + Ok(_) => {} + Err(e) => { + match e { + HandshakeEnum::NotSecret => {} + HandshakeEnum::KeyError => {} + HandshakeEnum::Timeout => { + println!("handshake timeout") + } + HandshakeEnum::ServerError(str) => { + println!("error:{}", str); + } + HandshakeEnum::Other(str) => { + println!("error:{}", str); + } + } + continue; + } + } + } + match vnt_util.register().await { + Ok(response) => { + break response; + } + Err(e) => { + match e { + ReqEnum::TokenError => { + println!("token error"); + return; + } + ReqEnum::AddressExhausted => { + println!("address exhausted"); + return; + } + ReqEnum::Timeout => { + println!("timeout..."); + } + ReqEnum::ServerError(str) => { + println!("error:{}", str); + } + ReqEnum::Other(str) => { + println!("error:{}", str); + } + ReqEnum::IpAlreadyExists => { + println!("ip already exists"); + return; + } + ReqEnum::InvalidIp => { + println!("invalid ip"); + return; + } + } + } + } } Err(e) => { match e { - ReqEnum::TokenError => { - println!("token error"); + HandshakeEnum::NotSecret => { + println!("The server does not support encryption"); + return; } - ReqEnum::AddressExhausted => { - println!("address exhausted"); + HandshakeEnum::KeyError => {} + HandshakeEnum::Timeout => { + println!("handshake timeout") } - ReqEnum::Timeout => { - println!("timeout..."); - continue; - } - ReqEnum::ServerError(str) => { + HandshakeEnum::ServerError(str) => { println!("error:{}", str); - continue; } - ReqEnum::Other(str) => { + HandshakeEnum::Other(str) => { println!("error:{}", str); - continue; - } - ReqEnum::IpAlreadyExists => { - println!("ip already exists"); - } - ReqEnum::InvalidIp => { - println!("invalid ip"); } } - return; } } }; @@ -259,44 +324,56 @@ async fn main0() { let stdin = tokio::io::stdin(); let mut cmd = String::new(); let mut reader = BufReader::new(stdin); + #[cfg(unix)] + let mut sigterm = signal(SignalKind::terminate()).expect("Error setting SIGTERM handler"); loop { cmd.clear(); println!("input:list,info,route,all,stop"); + #[cfg(unix)] tokio::select! { _ = vnt.wait_stop()=>{ break; } + _ = signal::ctrl_c()=>{ + let _ = vnt.stop(); + vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await; + return; + } + _ = sigterm.recv()=>{ + let _ = vnt.stop(); + vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await; + return; + } rs = reader.read_line(&mut cmd)=>{ match rs { Ok(len) => { - if len ==0 { + if !command(&cmd[..len],&vnt){ break; } - match cmd[..len].to_lowercase().trim() { - "list" => { - let list = command::command_list(&vnt); - console_out::console_device_list(list); - } - "info"=>{ - let info = command::command_info(&vnt); - console_out::console_info(info); - } - "route" =>{ - let route = command::command_route(&vnt); - console_out::console_route_table(route); - } - "all" =>{ - let list = command::command_list(&vnt); - console_out::console_device_list_all(list); - } - "stop" =>{ - let _ = vnt.stop(); - break; - } - _ => { - } + } + Err(e) => { + println!("input err:{}",e); + break; + } + } + } + } + #[cfg(windows)] + tokio::select! { + _ = vnt.wait_stop()=>{ + break; + } + _ = signal::ctrl_c()=>{ + let _ = vnt.stop(); + vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await; + return; + } + rs = reader.read_line(&mut cmd)=>{ + match rs { + Ok(len) => { + if !command(&cmd[..len],&vnt){ + break; } - println!(); } Err(e) => { println!("input err:{}",e); @@ -310,9 +387,40 @@ async fn main0() { vnt.wait_stop().await; } +fn command(cmd: &str, vnt: &Vnt) -> bool { + if cmd.is_empty() { + return false; + } + match cmd.to_lowercase().trim() { + "list" => { + let list = command::command_list(&vnt); + console_out::console_device_list(list); + } + "info" => { + let info = command::command_info(&vnt); + console_out::console_info(info); + } + "route" => { + let route = command::command_route(&vnt); + console_out::console_route_table(route); + } + "all" => { + let list = command::command_list(&vnt); + console_out::console_device_list_all(list); + } + "stop" => { + let _ = vnt.stop(); + return false; + } + _ => {} + } + println!(); + return true; +} + fn print_usage(program: &str, _opts: Options) { println!("Usage: {} [options]", program); - println!("version:1.1.2"); + println!("version:1.2.0"); println!("Options:"); println!(" -k {}", green("必选,使用相同的token,就能组建一个局域网络".to_string())); println!(" -n 给设备一个名字,便于区分不同设备,默认使用系统版本"); @@ -325,17 +433,18 @@ fn print_usage(program: &str, _opts: Options) { println!(" 并转发到10.26.0.3,可指定多个网段"); println!(" -o 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段"); println!(" -w 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信"); + println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确"); println!(" -m 模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送"); println!(" -u 自定义mtu(默认为1430)"); println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp"); println!(" --ip 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配"); println!(" --relay 仅使用服务器转发,不使用p2p,默认情况允许使用p2p"); println!(); - println!(" --list {}",yellow("后台运行时,查看其他设备列表".to_string())); - println!(" --all {}",yellow("后台运行时,查看其他设备完整信息".to_string())); - println!(" --info {}",yellow("后台运行时,查看当前设备信息".to_string())); - println!(" --route {}",yellow("后台运行时,查看数据转发路径".to_string())); - println!(" --stop {}",yellow("停止后台运行".to_string())); + println!(" --list {}", yellow("后台运行时,查看其他设备列表".to_string())); + println!(" --all {}", yellow("后台运行时,查看其他设备完整信息".to_string())); + println!(" --info {}", yellow("后台运行时,查看当前设备信息".to_string())); + println!(" --route {}", yellow("后台运行时,查看数据转发路径".to_string())); + println!(" --stop {}", yellow("停止后台运行".to_string())); println!(" -h, --help 帮助"); } diff --git a/vnt/Cargo.toml b/vnt/Cargo.toml index 2e1abfe..91ebcc6 100644 --- a/vnt/Cargo.toml +++ b/vnt/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vnt" -version = "1.1.2" +version = "1.2.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -11,7 +11,7 @@ bytes = "1.3.0" log = "0.4.17" libc = "0.2.137" crossbeam-utils = "0.8" -crossbeam-skiplist = "0.1" +crossbeam-skiplist = "0.1.1" parking_lot = "0.12.1" rand = "0.8.5" sha2 = { version = "0.10.6", features = ["oid"] } @@ -22,6 +22,8 @@ tokio = { version = "1.28.1", features = ["full"] } aes-gcm = {version="0.10.2", optional = true} ring = {version="0.16.20", optional = true} stun-format = {version="1.0.1",features=["fmt","rfc3489"]} +rsa = {version="0.7.2", features = [] } +spki = {version="0.6.0",features=["fingerprint","alloc"]} [target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies] tun = { path = "./rust-tun" } diff --git a/vnt/proto/message.proto b/vnt/proto/message.proto index 969c908..99506ec 100644 --- a/vnt/proto/message.proto +++ b/vnt/proto/message.proto @@ -1,4 +1,18 @@ syntax = "proto3"; +message HandshakeRequest{ + string version = 1; + bool secret = 2; +} +message HandshakeResponse{ + string version = 1; + bool secret = 2; + bytes public_key = 3; + string key_finger = 4; +} +message SecretHandshakeRequest{ + string token = 1; + bytes key = 2; +} message RegistrationRequest{ string token = 1; string device_id = 2; @@ -7,6 +21,7 @@ message RegistrationRequest{ string version = 5; fixed32 virtual_ip = 6; bool allow_ip_change = 7; + bool client_secret = 8; } message RegistrationResponse{ @@ -23,6 +38,7 @@ message DeviceInfo{ string name = 1; fixed32 virtual_ip = 2; uint32 device_status = 3; + bool client_secret = 4; } message DeviceList{ diff --git a/vnt/src/channel/channel.rs b/vnt/src/channel/channel.rs index 6e2094d..ec8e7b7 100644 --- a/vnt/src/channel/channel.rs +++ b/vnt/src/channel/channel.rs @@ -92,9 +92,7 @@ impl Context { } pub async fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result { if let Some(sender) = &self.inner.main_tcp_channel { - let mut vec = vec![0; 4 + buf.len()]; - vec[4..].copy_from_slice(buf); - if sender.send(vec).await.is_ok() { + if sender.send(buf.to_vec()).await.is_ok() { Ok(buf.len()) } else { Err(io::Error::new(io::ErrorKind::Other, "send_main err")) @@ -105,9 +103,7 @@ impl Context { } pub fn try_send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result { if let Some(sender) = &self.inner.main_tcp_channel { - let mut vec = vec![0; 4 + buf.len()]; - vec[4..].copy_from_slice(buf); - if sender.try_send(vec).is_ok() { + if sender.try_send(buf.to_vec()).is_ok() { Ok(buf.len()) } else { Err(io::Error::new(io::ErrorKind::Other, "try_send_main err")) @@ -339,71 +335,91 @@ impl Channel { } } -impl Channel { - async fn handle(handler: &mut ChannelDataHandler, - context: &Context, - id: usize, - result: io::Result<(usize, SocketAddr)>, - buf: &mut [u8], start: usize) { - match result { - Ok((len, addr)) => { - handler.handle(buf, start, start + len, RouteKey::new(id, addr), context).await; - } - Err(e) => { - log::error!("{:?}",e) - } - } +#[derive(Clone)] +struct BufSenderGroup(usize, Vec, usize, usize, RouteKey)>>); + +struct BufReceiverGroup(Vec, usize, usize, RouteKey)>>); + +impl BufSenderGroup { + pub async fn send(&mut self, val: (Vec, usize, usize, RouteKey)) -> bool { + let index = self.0 % self.1.len(); + self.0 = self.0.wrapping_add(1); + self.1[index].send(val).await.is_ok() } - async fn tcp_handle(mut tcp_r: OwnedReadHalf, context: Context, - mut handler: ChannelDataHandler, head_reserve: usize, ) -> io::Result<()> { - let mut buf = [0; 4096]; +} + +fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) { + let mut buf_sender_group = Vec::with_capacity(size); + let mut buf_receiver_group = Vec::with_capacity(size); + for _ in 0..size { + let (buf_sender, buf_receiver) = tokio::sync::mpsc::channel::<(Vec, usize, usize, RouteKey)>(10); + buf_sender_group.push(buf_sender); + buf_receiver_group.push(buf_receiver); + } + (BufSenderGroup(0, buf_sender_group), BufReceiverGroup(buf_receiver_group)) +} + +impl Channel { + async fn tcp_handle(mut tcp_r: OwnedReadHalf, mut buf_sender: BufSenderGroup, head_reserve: usize) -> io::Result<()> { + let mut head = [0; 4]; let addr = tcp_r.peer_addr()?; let key = RouteKey::new(0, addr); loop { - tcp_r.read_exact(&mut buf[head_reserve..head_reserve + 4]).await?; - let len = 4 + (((buf[head_reserve + 2] as u16) << 8) | buf[head_reserve + 3] as u16) as usize; - tcp_r.read_exact(&mut buf[head_reserve + 4..head_reserve + len]).await?; - handler.handle(&mut buf[4..], head_reserve, head_reserve + len - 4, key, &context).await; + let mut buf = vec![0; 4096]; + tcp_r.read_exact(&mut head).await?; + let len = (((head[2] as u16) << 8) | head[3] as u16) as usize; + if len < 12 || len > buf.len() { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "length overflow", + )); + } + tcp_r.read_exact(&mut buf[head_reserve..head_reserve + len]).await?; + if !buf_sender.send((buf, head_reserve, head_reserve + len, key)).await { + return Err(io::Error::new(io::ErrorKind::Other, "buf_sender发送数据失败")); + } } } - async fn start_tcp(mut worker: VntWorker, tcp_stream: TcpStream, mut receiver: tokio::sync::mpsc::Receiver>, context: Context, handler: ChannelDataHandler, head_reserve: usize) { + async fn start_tcp(mut worker: VntWorker, tcp_stream: TcpStream, mut receiver: tokio::sync::mpsc::Receiver>, + current_device: Arc>, + buf_sender: BufSenderGroup, head_reserve: usize) { let (tcp_r, mut tcp_w) = tcp_stream.into_split(); { - let context = context.clone(); - let handler = handler.clone(); + let buf_sender = buf_sender.clone(); tokio::spawn(async move { - if let Err(e) = Self::tcp_handle(tcp_r, context, handler, head_reserve).await { + if let Err(e) = Self::tcp_handle(tcp_r, buf_sender, head_reserve).await { log::info!("tcp链接断开:{:?}",e); } }); } + let mut head = [0; 4]; loop { tokio::select! { _=worker.stop_wait()=>{ break; } rs=receiver.recv()=>{ - if let Some(mut data) = rs{ - if data.len()<4{ - continue - } - let len = data.len() - 4; - data[2] = (len >> 8) as u8; - data[3] = (len & 0xFF) as u8; - if let Err(e) = tcp_w.write_all(&data).await { - if context.is_close() { - break; - } + if let Some(data) = rs{ + let len = data.len(); + head[2] = (len >> 8) as u8; + head[3] = (len & 0xFF) as u8; + let mut err = false; + if let Err(e) = tcp_w.write_all(&head).await{ + err = true; log::info!("发送失败,需要重连:{:?}",e); + }else if let Err(e) = tcp_w.write_all(&data).await{ + err = true; + log::info!("发送失败,需要重连:{:?}",e); + } + if err { let _ = tcp_w.shutdown().await; - match TcpStream::connect(context.inner.current_device.load().connect_server).await { + match TcpStream::connect(current_device.load().connect_server).await { Ok(tcp_stream) => { let (r, w) = tcp_stream.into_split(); tcp_w = w; - let context = context.clone(); - let handler = handler.clone(); + let buf_sender = buf_sender.clone(); tokio::spawn(async move { - if let Err(e) = Self::tcp_handle(r, context, handler, head_reserve).await { + if let Err(e) = Self::tcp_handle(r, buf_sender, head_reserve).await { log::info!("tcp 链接断开:{:?}",e); } }); @@ -421,6 +437,7 @@ impl Channel { } worker.stop_all(); } + pub async fn start(self, mut worker: VntWorker, tcp: Option<(TcpStream, tokio::sync::mpsc::Receiver>)>, @@ -428,14 +445,22 @@ impl Channel { symmetric_channel_num: usize,//对称网络,则再加一组监听,提升打洞成功率 relay: bool, ) { + let (buf_sender, buf_receiver) = buf_channel_group(6); + for mut buf_receiver in buf_receiver.0 { + let context = self.context.clone(); + let handler = self.handler.clone(); + tokio::spawn(async move { + while let Some((mut buf, start, end, route_key)) = buf_receiver.recv().await { + handler.handle(&mut buf, start, end, route_key, &context).await; + } + }); + } let context = self.context; let main_channel = context.inner.main_channel.clone(); - let handler = self.handler.clone(); if let Some((tcp_stream, receiver)) = tcp { - tokio::spawn(Self::start_tcp(worker.worker("main_channel_tcp"), tcp_stream, receiver, context.clone(), handler.clone(), head_reserve)); + tokio::spawn(Self::start_tcp(worker.worker("main_channel_tcp"), tcp_stream, receiver, context.inner.current_device.clone(), buf_sender.clone(), head_reserve)); } - tokio::spawn(Self::start_(worker.worker("main_channel_1"), context.clone(), handler.clone(), main_channel.clone(), head_reserve, true)); - // tokio::spawn(Self::start_(worker.worker("main_channel_2"), context.clone(), handler, main_channel, head_reserve, true)); + tokio::spawn(Self::start_(worker.worker("main_channel_1"), context.clone(), main_channel.clone(), buf_sender.clone(), head_reserve, true)); if relay { worker.stop_wait().await; return; @@ -465,8 +490,7 @@ impl Channel { Ok(udp) => { let udp = Arc::new(udp); let context = context.clone(); - let handler = self.handler.clone(); - tokio::spawn(Self::start_(worker.worker("symmetric_channel"),context, handler, udp, head_reserve, false)); + tokio::spawn(Self::start_(worker.worker("symmetric_channel"),context, udp,buf_sender.clone(), head_reserve, false)); } Err(e) => { log::error!("{}",e); @@ -489,8 +513,8 @@ impl Channel { worker.stop_all(); } async fn start_(mut worker: VntWorker, context: Context, - mut handler: ChannelDataHandler, udp: Arc, + mut buf_sender: BufSenderGroup, head_reserve: usize, is_core: bool) { let mut status_receiver = context.inner.status_receiver.clone(); @@ -503,11 +527,21 @@ impl Channel { #[cfg(any(unix))] let id = 1 + udp.as_raw_fd() as usize; context.inner.udp_map.insert(id, udp.clone()); - let mut buf = [0; 4096]; loop { + let mut buf = vec![0; 4096]; tokio::select! { rs=udp.recv_from(&mut buf[head_reserve..])=>{ - Self::handle(&mut handler,&context,id,rs,&mut buf,head_reserve).await; + match rs { + Ok((len, addr)) => { + if !buf_sender.send((buf,head_reserve,head_reserve+len,RouteKey::new(id, addr))).await{ + log::error!("udp buf_sender发送数据失败"); + break; + } + } + Err(e) => { + log::error!("{:?}",e) + } + } } changed=status_receiver.changed()=>{ match changed { diff --git a/vnt/src/cipher/aes_c.rs b/vnt/src/cipher/aes_c.rs new file mode 100644 index 0000000..87262d4 --- /dev/null +++ b/vnt/src/cipher/aes_c.rs @@ -0,0 +1,93 @@ +use std::io; +use crate::cipher::Finger; +use crate::protocol::NetPacket; +use sha2::Digest; +#[cfg(feature = "ring-cipher")] +use crate::cipher::ring_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_gcm_cipher.rs b/vnt/src/cipher/aes_gcm_cipher.rs index f3d9f7d..4045e6c 100644 --- a/vnt/src/cipher/aes_gcm_cipher.rs +++ b/vnt/src/cipher/aes_gcm_cipher.rs @@ -1,111 +1,111 @@ use std::io; -use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, Nonce, Tag,KeyInit}; +use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, KeyInit, Nonce, Tag}; use aes_gcm::aead::consts::{U12, U16}; use aes_gcm::aead::generic_array::GenericArray; -use sha2::Digest; +use rand::RngCore; + +use crate::cipher::finger::Finger; +use crate::protocol::{body::ENCRYPTION_RESERVED, body::SecretBody, NetPacket}; + -use crate::protocol; -use crate::protocol::{ip_turn_packet, NetPacket}; #[derive(Clone)] -pub enum Cipher { - AesGCM128(Aes128Gcm), - AesGCM256(Aes256Gcm), - None, +pub struct AesGcmCipher { + pub(crate) cipher: AesGcmEnum, + pub(crate) finger: Finger, } -impl Cipher { - pub fn new(password: Option) -> Self { - 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 key: &Key = key[..16].into(); - Cipher::AesGCM128(Aes128Gcm::new(&key)) - } else { - let key: &Key = &key.into(); - Cipher::AesGCM256(Aes256Gcm::new(&key)) - } - } else { - Cipher::None +#[derive(Clone)] +pub enum AesGcmEnum { + AES128GCM(Aes128Gcm), + AES256GCM(Aes256Gcm), +} + +impl AesGcmCipher { + pub fn new_128(key: [u8; 16], finger: Finger) -> Self { + let key: &Key = &key.into(); + Self { + cipher: AesGcmEnum::AES128GCM(Aes128Gcm::new(key)), + finger, } } - pub fn decrypt_ipv4(&self, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result> { - match &self { - Cipher::None => { - return Ok(None); - } - _ => {} + pub fn new_256(key: [u8; 32], finger: Finger) -> Self { + let key: &Key = &key.into(); + Self { + cipher: AesGcmEnum::AES256GCM(Aes256Gcm::new(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() < 16 { - log::error!("数据异常,长度小于16"); + if net_packet.payload().len() < ENCRYPTION_RESERVED { + log::error!("数据异常,长度小于{}",ENCRYPTION_RESERVED); return Err(io::Error::new(io::ErrorKind::Other, "data err")); } - let mut nonce = [0; 12]; - nonce[0..4].copy_from_slice(&net_packet.source().octets()); - nonce[4..8].copy_from_slice(&net_packet.destination().octets()); - nonce[8] = protocol::Protocol::IpTurn.into(); - nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); - let nonce: &GenericArray = Nonce::from_slice(&nonce); - let payload_len = net_packet.payload().len() - 16; - let tag: GenericArray = Tag::clone_from_slice(&net_packet.payload()[payload_len..]); - let rs = match &self { - Cipher::AesGCM128(cipher) => { - cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len], &tag) - } - Cipher::AesGCM256(cipher) => { - cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len], &tag) - } - Cipher::None => { - return Ok(None); - } + let mut nonce_raw = [0; 12]; + nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); + nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce_raw[8] = net_packet.protocol().into(); + nonce_raw[9] = net_packet.transport_protocol(); + nonce_raw[10] = net_packet.is_gateway() as u8; + nonce_raw[11] = net_packet.source_ttl(); + let nonce: &GenericArray = Nonce::from_slice(&nonce_raw); + + let mut secret_body = SecretBody::new(net_packet.payload_mut())?; + let tag = secret_body.tag(); + if tag.len() != 16 { + return Err(io::Error::new(io::ErrorKind::Other, "tag err")); + } + let finger = self.finger.calculate_finger(&nonce_raw, &secret_body); + if &finger != secret_body.finger() { + return Err(io::Error::new(io::ErrorKind::Other, "finger err")); + } + let tag: GenericArray = Tag::clone_from_slice(tag); + let rs = match &self.cipher { + AesGcmEnum::AES128GCM(aes_gcm) => { aes_gcm.decrypt_in_place_detached(nonce, &[], secret_body.body_mut(), &tag) } + AesGcmEnum::AES256GCM(aes_gcm) => { aes_gcm.decrypt_in_place_detached(nonce, &[], secret_body.body_mut(), &tag) } }; if let Err(e) = rs { return Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e))); } - return Ok(Some(payload_len)); + net_packet.set_encrypt_flag(false); + net_packet.set_data_len(net_packet.data_len() - ENCRYPTION_RESERVED)?; + return Ok(()); } /// net_packet 必须预留足够长度 /// data_len是有效载荷的长度 - /// 返回加密后载荷的长度 - pub fn encrypt_ipv4(&self, payload_len: usize, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result> { - match &self { - Cipher::None => { - return Ok(None); - } - _ => {} + pub fn encrypt_ipv4 + AsMut<[u8]>>(&self, net_packet: &mut NetPacket) -> io::Result<()> { + if net_packet.reserve() < ENCRYPTION_RESERVED { + return Err(io::Error::new(io::ErrorKind::Other, "too short")); } - let mut nonce = [0; 12]; - nonce[0..4].copy_from_slice(&net_packet.source().octets()); - nonce[4..8].copy_from_slice(&net_packet.destination().octets()); - nonce[8] = protocol::Protocol::IpTurn.into(); - nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); - let nonce: &GenericArray = Nonce::from_slice(&nonce); - let rs = match &self { - Cipher::AesGCM128(cipher) => { - cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len]) - } - Cipher::AesGCM256(cipher) => { - cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len]) - } - Cipher::None => { - return Ok(None); - } + let mut nonce_raw = [0; 12]; + nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); + nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce_raw[8] = net_packet.protocol().into(); + nonce_raw[9] = net_packet.transport_protocol(); + nonce_raw[10] = net_packet.is_gateway() as u8; + nonce_raw[11] = net_packet.source_ttl(); + let nonce: &GenericArray = Nonce::from_slice(&nonce_raw); + let data_len = net_packet.data_len() + ENCRYPTION_RESERVED; + net_packet.set_data_len(data_len)?; + let mut secret_body = SecretBody::new(net_packet.payload_mut())?; + secret_body.set_random(rand::thread_rng().next_u32()); + let rs = match &self.cipher { + AesGcmEnum::AES128GCM(aes_gcm) => { aes_gcm.encrypt_in_place_detached(nonce, &[], secret_body.body_mut()) } + AesGcmEnum::AES256GCM(aes_gcm) => { aes_gcm.encrypt_in_place_detached(nonce, &[], secret_body.body_mut()) } }; return match rs { Ok(tag) => { - if tag.len() != 16 { - return Err(io::Error::new(io::ErrorKind::Other, format!("加密tag长度错误:{}", tag.len()))); - } + secret_body.set_tag(tag.as_slice())?; + let finger = self.finger.calculate_finger(&nonce_raw, &secret_body); + secret_body.set_finger(&finger)?; net_packet.set_encrypt_flag(true); - net_packet.payload_mut()[payload_len..payload_len + 16].copy_from_slice(tag.as_slice()); - Ok(Some(payload_len + 16)) + Ok(()) } Err(e) => { Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e))) diff --git a/vnt/src/cipher/finger.rs b/vnt/src/cipher/finger.rs new file mode 100644 index 0000000..612be75 --- /dev/null +++ b/vnt/src/cipher/finger.rs @@ -0,0 +1,46 @@ +use std::io; + +use sha2::Digest; + +use crate::protocol::{body::ENCRYPTION_RESERVED, body::SecretBody, NetPacket}; + +#[derive(Clone)] +pub struct Finger { + token: String, +} + +impl Finger { + pub fn new(token: String) -> Self { + Finger { token } + } + pub fn check_finger>(&self, net_packet: &NetPacket) -> io::Result<()> { + if !net_packet.is_encrypt() { + //未加密的数据直接丢弃 + return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); + } + if net_packet.payload().len() < ENCRYPTION_RESERVED { + log::error!("数据异常,长度小于{}",ENCRYPTION_RESERVED); + return Err(io::Error::new(io::ErrorKind::Other, "data err")); + } + let mut nonce_raw = [0; 12]; + nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); + nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce_raw[8] = net_packet.protocol().into(); + nonce_raw[9] = net_packet.transport_protocol(); + let secret_body = SecretBody::new(net_packet.payload())?; + let finger = self.calculate_finger(&nonce_raw, &secret_body); + if &finger != secret_body.finger() { + return Err(io::Error::new(io::ErrorKind::Other, "finger err")); + } + Ok(()) + } + pub fn calculate_finger>(&self, nonce_raw: &[u8; 12], secret_body: &SecretBody) -> [u8; 12] { + let mut hasher = sha2::Sha256::new(); + hasher.update(secret_body.body()); + hasher.update(nonce_raw); + hasher.update(secret_body.tag()); + hasher.update(&self.token); + let key: [u8; 32] = hasher.finalize().into(); + return key[20..].try_into().unwrap(); + } +} \ No newline at end of file diff --git a/vnt/src/cipher/mod.rs b/vnt/src/cipher/mod.rs index 21022de..e8a2b3a 100644 --- a/vnt/src/cipher/mod.rs +++ b/vnt/src/cipher/mod.rs @@ -1,8 +1,11 @@ #[cfg(feature = "ring-cipher")] mod ring_cipher; -#[cfg(feature = "ring-cipher")] -pub use ring_cipher::Cipher; #[cfg(not(feature = "ring-cipher"))] mod aes_gcm_cipher; -#[cfg(not(feature = "ring-cipher"))] -pub use aes_gcm_cipher::Cipher; \ No newline at end of file +mod rsa_cipher; +mod finger; +mod aes_c; + +pub use aes_c::Cipher; +pub use finger::Finger; +pub use rsa_cipher::RsaCipher; \ No newline at end of file diff --git a/vnt/src/cipher/ring_cipher.rs b/vnt/src/cipher/ring_cipher.rs index fc7abfc..c0404c4 100644 --- a/vnt/src/cipher/ring_cipher.rs +++ b/vnt/src/cipher/ring_cipher.rs @@ -1,117 +1,118 @@ - - use std::io; +use rand::RngCore; use ring::aead; use ring::aead::{LessSafeKey, UnboundKey}; -use sha2::Digest; +use crate::cipher::Finger; -use crate::protocol; -use crate::protocol::{ip_turn_packet, NetPacket}; +use crate::protocol::NetPacket; +use crate::protocol::body::{ENCRYPTION_RESERVED, SecretBody}; -pub enum Cipher { +#[derive(Clone)] +pub struct AesGcmCipher { + pub(crate) cipher: AesGcmEnum, + pub(crate) finger: Finger, +} + +pub enum AesGcmEnum { AesGCM128(LessSafeKey, [u8; 16]), AesGCM256(LessSafeKey, [u8; 32]), - None, } -impl Clone for Cipher { +impl Clone for AesGcmEnum { fn clone(&self) -> Self { match &self { - Cipher::AesGCM128(_, key) => { + AesGcmEnum::AesGCM128(_, key) => { let c = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, key.as_slice()).unwrap()); - Cipher::AesGCM128(c, *key) + AesGcmEnum::AesGCM128(c, *key) } - Cipher::AesGCM256(_, key) => { + AesGcmEnum::AesGCM256(_, key) => { let c = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, key.as_slice()).unwrap()); - Cipher::AesGCM256(c, *key) - } - Cipher::None => { - Cipher::None + AesGcmEnum::AesGCM256(c, *key) } } } } -impl Cipher { - pub fn new(password: Option) -> Self { - 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 c = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, &key[..16]).unwrap()); - Cipher::AesGCM128(c, key[..16].try_into().unwrap()) - } else { - let c = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, &key).unwrap()); - Cipher::AesGCM256(c, key) - } - } else { - Cipher::None +impl AesGcmCipher { + pub fn new_128(key: [u8; 16], finger: Finger) -> Self { + let cipher = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, &key).unwrap()); + Self { + cipher: AesGcmEnum::AesGCM128(cipher, key), + finger, } } - pub fn decrypt_ipv4(&self, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result> { - match &self { - Cipher::None => { - return Ok(None); - } - _ => {} + pub fn new_256(key: [u8; 32], finger: Finger) -> Self { + let cipher = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, &key).unwrap()); + Self { + cipher: AesGcmEnum::AesGCM256(cipher, 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() < 16 { - log::error!("数据异常,长度小于16"); + if net_packet.payload().len() < ENCRYPTION_RESERVED { + log::error!("数据异常,长度小于{}",ENCRYPTION_RESERVED); return Err(io::Error::new(io::ErrorKind::Other, "data err")); } - let mut nonce = [0; 12]; - nonce[0..4].copy_from_slice(&net_packet.source().octets()); - nonce[4..8].copy_from_slice(&net_packet.destination().octets()); - nonce[8] = protocol::Protocol::IpTurn.into(); - nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); - let nonce = aead::Nonce::assume_unique_for_key(nonce); - let payload_len = net_packet.payload().len() - 16; - let rs = match &self { - Cipher::AesGCM128(cipher, _) => { - cipher.open_in_place(nonce, aead::Aad::empty(), net_packet.payload_mut()) + let mut nonce_raw = [0; 12]; + nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); + nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce_raw[8] = net_packet.protocol().into(); + nonce_raw[9] = net_packet.transport_protocol(); + nonce_raw[10] = net_packet.is_gateway() as u8; + nonce_raw[11] = net_packet.source_ttl(); + let nonce = aead::Nonce::assume_unique_for_key(nonce_raw); + let mut secret_body = SecretBody::new(net_packet.payload_mut())?; + let tag = secret_body.tag(); + if tag.len() != 16 { + return Err(io::Error::new(io::ErrorKind::Other, "tag err")); + } + let finger = self.finger.calculate_finger(&nonce_raw, &secret_body); + if &finger != secret_body.finger() { + return Err(io::Error::new(io::ErrorKind::Other, "finger err")); + } + + let rs = match &self.cipher { + AesGcmEnum::AesGCM128(cipher, _) => { + cipher.open_in_place(nonce, aead::Aad::empty(), secret_body.en_body_mut()) } - Cipher::AesGCM256(cipher, _) => { - cipher.open_in_place(nonce, aead::Aad::empty(), net_packet.payload_mut()) - } - Cipher::None => { - return Ok(None); + AesGcmEnum::AesGCM256(cipher, _) => { + cipher.open_in_place(nonce, aead::Aad::empty(), secret_body.en_body_mut()) } }; if let Err(e) = rs { return Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e))); } - return Ok(Some(payload_len)); + net_packet.set_encrypt_flag(false); + net_packet.set_data_len(net_packet.data_len() - ENCRYPTION_RESERVED)?; + return Ok(()); } /// net_packet 必须预留足够长度 /// data_len是有效载荷的长度 /// 返回加密后载荷的长度 - pub fn encrypt_ipv4(&self, payload_len: usize, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result> { - match &self { - Cipher::None => { - return Ok(None); + pub fn encrypt_ipv4 + AsMut<[u8]>>(&self, net_packet: &mut NetPacket) -> io::Result<()> { + let mut nonce_raw = [0; 12]; + nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); + nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce_raw[8] = net_packet.protocol().into(); + nonce_raw[9] = net_packet.transport_protocol(); + nonce_raw[10] = net_packet.is_gateway() as u8; + nonce_raw[11] = net_packet.source_ttl(); + let nonce = aead::Nonce::assume_unique_for_key(nonce_raw); + let data_len = net_packet.data_len() + ENCRYPTION_RESERVED; + net_packet.set_data_len(data_len)?; + let mut secret_body = SecretBody::new(net_packet.payload_mut())?; + secret_body.set_random(rand::thread_rng().next_u32()); + + let rs = match &self.cipher { + AesGcmEnum::AesGCM128(cipher, _) => { + cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), secret_body.body_mut()) } - _ => {} - } - let mut nonce = [0; 12]; - nonce[0..4].copy_from_slice(&net_packet.source().octets()); - nonce[4..8].copy_from_slice(&net_packet.destination().octets()); - nonce[8] = protocol::Protocol::IpTurn.into(); - nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); - let nonce = aead::Nonce::assume_unique_for_key(nonce); - let rs = match &self { - Cipher::AesGCM128(cipher, _) => { - cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), &mut net_packet.payload_mut()[..payload_len]) - } - Cipher::AesGCM256(cipher, _) => { - cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), &mut net_packet.payload_mut()[..payload_len]) - } - Cipher::None => { - return Ok(None); + AesGcmEnum::AesGCM256(cipher, _) => { + cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), secret_body.body_mut()) } }; return match rs { @@ -120,9 +121,11 @@ impl Cipher { if tag.len() != 16 { return Err(io::Error::new(io::ErrorKind::Other, format!("加密tag长度错误:{}", tag.len()))); } + secret_body.set_tag(tag)?; + let finger = self.finger.calculate_finger(&nonce_raw, &secret_body); + secret_body.set_finger(&finger)?; net_packet.set_encrypt_flag(true); - net_packet.payload_mut()[payload_len..payload_len + 16].copy_from_slice(tag); - Ok(Some(payload_len + 16)) + Ok(()) } Err(e) => { Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e))) diff --git a/vnt/src/cipher/rsa_cipher.rs b/vnt/src/cipher/rsa_cipher.rs new file mode 100644 index 0000000..e5ef8ab --- /dev/null +++ b/vnt/src/cipher/rsa_cipher.rs @@ -0,0 +1,99 @@ +use std::io; +use rand::Rng; +use rsa::pkcs8::der::Decode; +use rsa::{PublicKey, RsaPublicKey}; +use spki::{DecodePublicKey, EncodePublicKey}; +use crate::protocol::body::{ENCRYPTION_RESERVED, RsaSecretBody}; +use crate::protocol::NetPacket; +use sha2::Digest; + +#[derive(Clone)] +pub struct RsaCipher { + inner: Inner, +} + +#[derive(Clone)] +struct Inner { + public_key: RsaPublicKey, +} + +impl RsaCipher { + pub fn new(der: &[u8]) -> io::Result { + match RsaPublicKey::from_public_key_der(der) { + Ok(public_key) => { + let inner = Inner { + public_key, + }; + Ok(Self { + inner + }) + } + Err(e) => { + Err(io::Error::new(io::ErrorKind::Other, format!("from_public_key_der failed {}", e))) + } + } + } + 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()) { + Ok(spki) => { + match spki.fingerprint_base64() { + Ok(finger) => { + Ok(finger) + } + Err(e) => { + Err(io::Error::new(io::ErrorKind::Other, format!("fingerprint_base64 error {}", e))) + } + } + } + Err(e) => { + Err(io::Error::new(io::ErrorKind::Other, format!("from_der error {}", e))) + } + } + } + Err(e) => { + Err(io::Error::new(io::ErrorKind::Other, format!("to_public_key_der error {}", e))) + } + } + } +} + +impl RsaCipher { + /// net_packet 必须预留足够长度 + pub fn encrypt + AsMut<[u8]>>(&self, net_packet: &mut NetPacket) -> io::Result>> { + if net_packet.reserve() < ENCRYPTION_RESERVED { + return Err(io::Error::new(io::ErrorKind::Other, "too short")); + } + let data_len = net_packet.data_len() + ENCRYPTION_RESERVED; + net_packet.set_data_len(data_len)?; + let mut nonce_raw = [0; 12]; + nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); + nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce_raw[8] = net_packet.protocol().into(); + nonce_raw[9] = net_packet.transport_protocol(); + nonce_raw[10] = net_packet.is_gateway() as u8; + nonce_raw[11] = net_packet.source_ttl(); + + let mut secret_body = RsaSecretBody::new(net_packet.payload_mut())?; + let mut rng = rand::thread_rng(); + rng.fill(secret_body.random_mut()); + + let mut hasher = sha2::Sha256::new(); + hasher.update(secret_body.body()); + hasher.update(nonce_raw); + let key: [u8; 32] = hasher.finalize().into(); + secret_body.set_finger(&key[16..])?; + match self.inner.public_key.encrypt(&mut rng, rsa::PaddingScheme::PKCS1v15Encrypt, secret_body.buffer()) { + Ok(enc_data) => { + let mut net_packet_e = NetPacket::new(vec![0; 12 + enc_data.len()])?; + net_packet_e.buffer_mut()[..12].copy_from_slice(&net_packet.buffer()[..12]); + net_packet_e.set_payload(&enc_data)?; + Ok(net_packet_e) + } + Err(e) => { + Err(io::Error::new(io::ErrorKind::Other, format!("encrypt failed {}", e))) + } + } + } +} \ No newline at end of file diff --git a/vnt/src/core/mod.rs b/vnt/src/core/mod.rs index 460c3dd..1b345fe 100644 --- a/vnt/src/core/mod.rs +++ b/vnt/src/core/mod.rs @@ -6,6 +6,7 @@ use std::time::Duration; use crossbeam_skiplist::SkipMap; use crossbeam_utils::atomic::AtomicCell; use parking_lot::Mutex; +use rand::Rng; use tokio::net::{TcpStream, UdpSocket}; use tokio::sync::mpsc::channel; @@ -14,11 +15,12 @@ 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; +use crate::cipher::{Cipher, RsaCipher}; use crate::core::status::VntStatusManger; use crate::error::Error; use crate::external_route::{AllowExternalRoute, ExternalRoute}; -use crate::handle::{ConnectStatus, CurrentDeviceInfo, heartbeat_handler, PeerDeviceInfo, punch_handler, registration_handler}; +use crate::handle::{ConnectStatus, CurrentDeviceInfo, handshake_handler, heartbeat_handler, PeerDeviceInfo, punch_handler, registration_handler}; +use crate::handle::handshake_handler::HandshakeEnum; use crate::handle::recv_handler::ChannelDataHandler; use crate::handle::registration_handler::{RegResponse, ReqEnum}; #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] @@ -35,7 +37,7 @@ pub mod sync; #[derive(Clone)] pub struct Vnt { - name: String, + config: Config, current_device: Arc>, context: Context, vnt_status_manager: VntStatusManger, @@ -55,33 +57,54 @@ pub struct VntUtil { main_tcp_channel: Option, response: Option, iface: Option<(DeviceWriter, DeviceReader)>, + server_cipher: Cipher, + rsa_cipher: Option, } impl VntUtil { pub async fn new(config: Config) -> io::Result { let main_channel = UdpSocket::bind("0.0.0.0:0").await?; + let server_cipher = if config.server_encrypt { + let mut key = [0 as u8; 32]; + rand::thread_rng().fill(&mut key); + Cipher::new_key(key, config.token.clone())? + } else { + Cipher::None + }; Ok(VntUtil { config, main_channel, main_tcp_channel: None, response: None, iface: None, + server_cipher, + rsa_cipher: None, }) } - pub async fn connect(&mut self) -> Result { + ///链接 + pub async fn connect(&mut self) -> io::Result<()> { if self.config.tcp { - match TcpStream::connect(self.config.server_address).await { - Ok(tcp) => { - let _ = self.main_tcp_channel.insert(tcp); - } - Err(e) => { - return Err(ReqEnum::Other(format!("connect error:{}", e))); - } - } + let tcp = TcpStream::connect(self.config.server_address).await?; + let _ = self.main_tcp_channel.insert(tcp); } - match registration_handler::registration(&self.main_channel, self.main_tcp_channel.as_mut(), self.config.server_address, + Ok(()) + } + + ///握手 用于获取公钥 + pub async fn handshake(&mut self) -> Result, HandshakeEnum> { + let rsa_cipher = handshake_handler::handshake(&self.main_channel, self.main_tcp_channel.as_mut(), self.config.server_address, self.config.server_encrypt).await?; + self.rsa_cipher = rsa_cipher.clone(); + Ok(rsa_cipher) + } + /// 加密握手 用于同步密钥 + pub async fn secret_handshake(&mut self) -> Result<(), HandshakeEnum> { + handshake_handler::secret_handshake(&self.main_channel, self.main_tcp_channel.as_mut(), self.config.server_address, self.rsa_cipher.as_ref().unwrap(), &self.server_cipher,self.config.token.clone()).await + } + /// 注册 + pub async fn register(&mut self) -> Result { + match registration_handler::registration(&self.main_channel, self.main_tcp_channel.as_mut(), &self.server_cipher, self.config.server_address, self.config.token.clone(), self.config.device_id.clone(), - self.config.name.clone(), self.config.ip.unwrap_or(Ipv4Addr::UNSPECIFIED)).await { + self.config.name.clone(), self.config.ip.unwrap_or(Ipv4Addr::UNSPECIFIED),self.config.password.is_some()).await { Ok(res) => { let _ = self.response.insert(res.clone()); Ok(res) @@ -149,9 +172,9 @@ impl VntUtil { res } }; - let config = self.config; + let config = self.config.clone(); let vnt_status_manager = VntStatusManger::new(); - let cipher = Cipher::new(config.password.clone()); + let client_cipher = Cipher::new_password(config.password.clone(), config.token.clone()); let virtual_ip = response.virtual_ip; let virtual_gateway = response.virtual_gateway; let virtual_netmask = response.virtual_netmask; @@ -170,9 +193,9 @@ impl VntUtil { let idle = Idle::new(Duration::from_secs(16), context.clone()); let channel_sender = ChannelSender::new(context.clone()); - let register = Arc::new(registration_handler::Register::new(channel_sender.clone(), + let register = Arc::new(registration_handler::Register::new(self.server_cipher.clone(), channel_sender.clone(), config.server_address, config.token.clone(), - config.device_id.clone(), config.name.clone())); + config.device_id.clone(), config.name.clone(),config.password.is_some())); let device_list: Arc)>> = Arc::new(Mutex::new((response.epoch, response.device_info_list))); let peer_nat_info_map: Arc> = Arc::new(SkipMap::new()); let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected)); @@ -190,7 +213,7 @@ impl VntUtil { let (tcp_proxy, udp_proxy, ip_proxy_map) = if config.out_ips.is_empty() { (None, None, None) } else { - let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(channel_sender.clone(), current_device.clone()).await?; + let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(channel_sender.clone(), current_device.clone(), client_cipher.clone()).await?; (Some(tcp_proxy), Some(udp_proxy), Some(ip_proxy_map)) }; let out_external_route = AllowExternalRoute::new(config.out_ips); @@ -203,21 +226,22 @@ impl VntUtil { #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] 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(), cipher.clone()); + igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), client_cipher.clone(), self.server_cipher.clone()); } 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(), cipher.clone()); + igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), client_cipher.clone(), self.server_cipher.clone()).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()); + igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone()).await; //外部数据接收处理 let channel_recv_handler = ChannelDataHandler::new(current_device.clone(), device_list.clone(), register.clone(), nat_test.clone(), igmp_server, device_writer.clone(), connect_status.clone(), peer_nat_info_map.clone(), ip_proxy_map, out_external_route, - cone_sender, symmetric_sender, cipher, config.relay); + cone_sender, symmetric_sender, client_cipher.clone(), + self.server_cipher.clone(), self.rsa_cipher.clone(), config.relay,config.token.clone()); { let channel = Channel::new(context.clone(), channel_recv_handler); let channel_worker = vnt_status_manager.worker("channel_worker"); @@ -238,20 +262,21 @@ impl VntUtil { let device_list = device_list.clone(); let current_device = current_device.clone(); // 定时心跳 - heartbeat_handler::start_heartbeat(other_worker.worker("heartbeat"), channel_sender.clone(), device_list.clone(), current_device.clone(), config.server_address_str); + heartbeat_handler::start_heartbeat(other_worker.worker("heartbeat"), channel_sender.clone(), device_list.clone(), + current_device.clone(), config.server_address_str, client_cipher.clone(), self.server_cipher.clone()); // 空闲检查 heartbeat_handler::start_idle(other_worker.worker("idle"), idle, channel_sender.clone()); if !config.relay { // 打洞处理 - punch_handler::start(other_worker.worker("cone_receiver"), cone_receiver, punch.clone(), current_device.clone()); - punch_handler::start(other_worker.worker("symmetric_receiver"), symmetric_receiver, punch, current_device.clone()); + punch_handler::start(other_worker.worker("cone_receiver"), cone_receiver, punch.clone(), current_device.clone(), client_cipher.clone()); + punch_handler::start(other_worker.worker("symmetric_receiver"), symmetric_receiver, punch, current_device.clone(), client_cipher.clone()); tokio::spawn(punch_handler::start_punch(other_worker, nat_test, - device_list, channel_sender, current_device)); + device_list, channel_sender, current_device, client_cipher.clone())); } } context.switch(nat_test.nat_info().nat_type); Ok(Vnt { - name: config.name, + config:self.config, current_device, context, vnt_status_manager, @@ -266,7 +291,13 @@ impl VntUtil { impl Vnt { pub fn name(&self) -> &str { - &self.name + &self.config.name + } + pub fn server_encrypt(&self) -> bool { + self.config.server_encrypt + } + pub fn client_encrypt(&self) -> bool { + self.config.password.is_some() } pub fn current_device(&self) -> CurrentDeviceInfo { self.current_device.load() @@ -344,6 +375,7 @@ pub struct Config { pub tcp: bool, pub ip: Option, pub relay: bool, + pub server_encrypt: bool, } @@ -357,7 +389,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, ) -> Self { + relay: bool, server_encrypt: bool, ) -> Self { for x in stun_server.iter_mut() { if !x.contains(":") { x.push_str(":3478"); @@ -379,6 +411,7 @@ impl Config { tcp, ip, relay, + server_encrypt, } } } \ No newline at end of file diff --git a/vnt/src/core/sync.rs b/vnt/src/core/sync.rs index 8d9c65c..a84173c 100644 --- a/vnt/src/core/sync.rs +++ b/vnt/src/core/sync.rs @@ -2,7 +2,9 @@ use std::io; use std::ops::Deref; use std::time::Duration; use tokio::runtime::Runtime; +use crate::cipher::RsaCipher; use crate::core::{Config, Vnt, VntUtil}; +use crate::handle::handshake_handler::HandshakeEnum; use crate::handle::registration_handler::{RegResponse, ReqEnum}; pub struct VntUtilSync { @@ -24,9 +26,18 @@ impl VntUtilSync { runtime, }) } - pub fn connect(&mut self) -> Result { + pub fn connect(&mut self) -> io::Result<()> { self.runtime.block_on(self.vnt_util.connect()) } + pub fn handshake(&mut self) -> Result, HandshakeEnum> { + self.runtime.block_on(self.vnt_util.handshake()) + } + pub fn secret_handshake(&mut self) -> Result<(), HandshakeEnum> { + self.runtime.block_on(self.vnt_util.secret_handshake()) + } + pub fn register(&mut self) -> Result { + self.runtime.block_on(self.vnt_util.register()) + } #[cfg(any(target_os = "android"))] pub fn create_iface(&mut self, vpn_fd: i32) { self.vnt_util.create_iface(vpn_fd) diff --git a/vnt/src/handle/handshake_handler.rs b/vnt/src/handle/handshake_handler.rs new file mode 100644 index 0000000..bd1ccea --- /dev/null +++ b/vnt/src/handle/handshake_handler.rs @@ -0,0 +1,211 @@ +use std::net::SocketAddr; +use std::time::Duration; + +use protobuf::Message; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::{TcpStream, UdpSocket}; + +use crate::channel::channel::Context; +use crate::cipher::{Cipher, RsaCipher}; +use crate::proto::message::{HandshakeRequest, HandshakeResponse, SecretHandshakeRequest}; +use crate::protocol::{MAX_TTL, NetPacket, Protocol, service_packet, Version}; +use crate::protocol::body::ENCRYPTION_RESERVED; + +const VERSION: &'static str = "1.2.0"; + +pub enum HandshakeEnum { + NotSecret, + KeyError, + Timeout, + ServerError(String), + Other(String), +} + +fn handshake_request_packet(secret: bool) -> crate::Result>> { + let mut request = HandshakeRequest::new(); + request.secret = secret; + request.version = VERSION.to_string(); + let bytes = request.write_to_bytes()?; + let buf = vec![0u8; 12 + bytes.len()]; + let mut net_packet = NetPacket::new(buf)?; + net_packet.set_version(Version::V1); + net_packet.set_gateway_flag(true); + net_packet.set_protocol(Protocol::Service); + net_packet.set_transport_protocol(service_packet::Protocol::HandshakeRequest.into()); + net_packet.first_set_ttl(MAX_TTL); + net_packet.set_payload(&bytes)?; + Ok(net_packet) +} + +fn secret_handshake_request_packet(rsa_cipher: &RsaCipher, token: String, key: &[u8]) -> crate::Result>> { + let mut request = SecretHandshakeRequest::new(); + request.token = token; + request.key = key.to_vec(); + let bytes = request.write_to_bytes()?; + let mut net_packet = NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?; + net_packet.set_version(Version::V1); + net_packet.set_gateway_flag(true); + net_packet.set_protocol(Protocol::Service); + net_packet.set_transport_protocol(service_packet::Protocol::SecretHandshakeRequest.into()); + net_packet.first_set_ttl(MAX_TTL); + net_packet.set_payload(&bytes)?; + Ok(rsa_cipher.encrypt(&mut net_packet)?) +} + +/// 第一次握手,拿到公钥 +pub async fn handshake(main_channel: &UdpSocket, main_tcp_channel: Option<&mut TcpStream>, + server_address: SocketAddr, secret: bool) -> Result, HandshakeEnum> { + let request_packet = handshake_request_packet(secret).unwrap(); + let send_buf = request_packet.buffer(); + let mut recv_buf = [0u8; 10240]; + let len = send_recv(main_channel, main_tcp_channel, server_address, send_buf, &mut recv_buf).await?; + let net_packet = match NetPacket::new(&recv_buf[..len]) { + Ok(net_packet) => { + net_packet + } + Err(e) => { + return Err(HandshakeEnum::Other(format!("net_packet {}", e))); + } + }; + match net_packet.protocol() { + Protocol::Service => { + match service_packet::Protocol::from(net_packet.transport_protocol()) { + service_packet::Protocol::HandshakeResponse => { + match HandshakeResponse::parse_from_bytes(net_packet.payload()) { + Ok(response) => { + if !response.secret && secret { + //客户端要加密,服务端不支持加密 + return Err(HandshakeEnum::NotSecret); + } + if secret { + //转换公钥 + match RsaCipher::new(&response.public_key) { + Ok(rsa) => { + match rsa.finger() { + Ok(finger) => { + if finger != response.key_finger { + return Err(HandshakeEnum::Other("finger error".to_string())); + } + } + Err(e) => { + return Err(HandshakeEnum::Other(format!("finger {}", e))); + } + } + Ok(Some(rsa)) + } + Err(e) => { + return Err(HandshakeEnum::Other(format!("RsaCipher {}", e))); + } + } + } else { + Ok(None) + } + } + Err(e) => { + return Err(HandshakeEnum::Other(format!("parse_from_bytes {}", e))); + } + } + } + _ => { + return Err(HandshakeEnum::Other("not match".to_string())); + } + } + } + _ => { + return Err(HandshakeEnum::Other("not match".to_string())); + } + } +} + +async fn send_recv(main_channel: &UdpSocket, main_tcp_channel: Option<&mut TcpStream>, + server_address: SocketAddr, send_buf: &[u8], recv_buf: &mut [u8]) -> Result { + if let Some(main_tcp_channel) = main_tcp_channel { + let mut head = [0; 4]; + let len = send_buf.len(); + head[2] = (len >> 8) as u8; + head[3] = (len & 0xFF) as u8; + if let Err(e) = main_tcp_channel.write_all(&head).await { + return Err(HandshakeEnum::Other(format!("send error:{}", e))); + } + if let Err(e) = main_tcp_channel.write_all(send_buf).await { + return Err(HandshakeEnum::Other(format!("send error:{}", e))); + } + if let Err(e) = main_tcp_channel.read_exact(&mut head).await { + return Err(HandshakeEnum::Other(format!("read error:{}", e))); + } + let len = (((head[2] as u16) << 8) | head[3] as u16) as usize; + if len > recv_buf.len() { + return Err(HandshakeEnum::Other("too long".to_string())); + } + if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[..len]).await { + return Err(HandshakeEnum::Other(format!("read error:{}", e))); + } + Ok(len) + } else { + if let Err(e) = main_channel.send_to(send_buf, server_address).await { + return Err(HandshakeEnum::Other(format!("send error:{}", e))); + } + match tokio::time::timeout(Duration::from_millis(300), main_channel.recv_from(recv_buf)).await { + Ok(rs) => { + match rs { + Ok((len, addr)) => { + if server_address != addr { + return Err(HandshakeEnum::Other(format!("invalid data,from {}", addr))); + } + Ok(len) + } + Err(e) => { + return Err(HandshakeEnum::Other(format!("receiver error:{}", e))); + } + } + } + Err(_) => { + return Err(HandshakeEnum::Timeout); + } + } + } +} + +/// 第二次握手,同步对称密钥,后续将使用对称加密 +pub async fn secret_handshake(main_channel: &UdpSocket, main_tcp_channel: Option<&mut TcpStream>, + server_address: SocketAddr, rsa_cipher: &RsaCipher, server_cipher: &Cipher, token: String) + -> Result<(), HandshakeEnum> { + let secret_packet = match secret_handshake_request_packet(rsa_cipher, token, server_cipher.key().unwrap()) { + Ok(secret_packet) => { + secret_packet + } + Err(e) => { + return Err(HandshakeEnum::Other(format!("secret_handshake_request_packet {}", e))); + } + }; + let send_buf = secret_packet.buffer(); + let mut recv_buf = [0u8; 10240]; + let len = send_recv(main_channel, main_tcp_channel, server_address, send_buf, &mut recv_buf).await?; + let mut net_packet = match NetPacket::new(&mut recv_buf[..len]) { + Ok(net_packet) => { net_packet } + Err(e) => { + return Err(HandshakeEnum::Other(format!("secret_net_packet {}", e))); + } + }; + match server_cipher.decrypt_ipv4(&mut net_packet) { + Ok(_) => { + if net_packet.is_gateway() && net_packet.protocol() == Protocol::Service + && service_packet::Protocol::from(net_packet.transport_protocol()) == + service_packet::Protocol::SecretHandshakeResponse { + Ok(()) + } else { + Err(HandshakeEnum::Other("not match".to_string())) + } + } + Err(e) => { + Err(HandshakeEnum::Other(format!("decrypt_ipv4 {}", e))) + } + } +} + +pub async fn secret_handshake_req(context: &Context, + server_address: SocketAddr, rsa_cipher: &RsaCipher, server_cipher: &Cipher, token: String, ) -> crate::Result<()> { + let secret_packet = secret_handshake_request_packet(rsa_cipher, token, server_cipher.key().unwrap())?; + context.send_main(secret_packet.buffer(), server_address).await?; + Ok(()) +} diff --git a/vnt/src/handle/heartbeat_handler.rs b/vnt/src/handle/heartbeat_handler.rs index 2315c2a..ae805da 100644 --- a/vnt/src/handle/heartbeat_handler.rs +++ b/vnt/src/handle/heartbeat_handler.rs @@ -9,12 +9,14 @@ use rand::prelude::SliceRandom; use crate::channel::idle::Idle; use crate::channel::Route; use crate::channel::sender::ChannelSender; +use crate::cipher::Cipher; use crate::core::status::VntWorker; use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo}; use crate::protocol::control_packet::PingPacket; use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, Version}; +use crate::protocol::body::ENCRYPTION_RESERVED; pub fn start_idle(mut worker: VntWorker, idle: Idle, sender: ChannelSender) { tokio::spawn(async move { @@ -50,13 +52,15 @@ pub fn start_heartbeat( device_list: Arc)>>, current_device: Arc>, server_address_str: String, + client_cipher: Cipher, + server_cipher: Cipher, ) { tokio::spawn(async move { tokio::select! { _=worker.stop_wait()=>{ return; } - rs=start_heartbeat_(sender, device_list, current_device,server_address_str)=>{ + rs=start_heartbeat_(sender, device_list, current_device,server_address_str,client_cipher,server_cipher)=>{ if let Err(e) = rs { log::warn!("心跳任务停止:{:?}", e); } @@ -66,11 +70,29 @@ pub fn start_heartbeat( }); } -fn set_now_time(packet: &mut NetPacket<[u8; 16]>) -> io::Result<()> { - let current_time = crate::handle::now_time() as u16; - let mut ping = PingPacket::new(packet.payload_mut())?; - ping.set_time(current_time); - Ok(()) + +fn heartbeat_packet( device_list: &Mutex<(u16, Vec)>,client_cipher: &Cipher, server_cipher: &Cipher, gateway: bool, src: Ipv4Addr, dest: Ipv4Addr) -> NetPacket<[u8; 48]> { + let mut net_packet = NetPacket::new_encrypt([0u8; 12 + 4 + ENCRYPTION_RESERVED]).unwrap(); + net_packet.set_version(Version::V1); + net_packet.set_protocol(Protocol::Control); + net_packet.set_transport_protocol(control_packet::Protocol::Ping.into()); + //只寻找两跳以内能到的目标 + net_packet.first_set_ttl(2); + net_packet.set_source(src); + net_packet.set_destination(dest); + { + let mut ping = PingPacket::new(net_packet.payload_mut()).unwrap(); + let epoch = { device_list.lock().0 }; + ping.set_epoch(epoch); + ping.set_time( crate::handle::now_time() as u16); + } + if gateway { + net_packet.set_gateway_flag(true); + server_cipher.encrypt_ipv4(&mut net_packet).unwrap(); + } else { + client_cipher.encrypt_ipv4(&mut net_packet).unwrap(); + } + net_packet } async fn start_heartbeat_( @@ -78,22 +100,19 @@ async fn start_heartbeat_( device_list: Arc)>>, current_device: Arc>, server_address_str: String, + client_cipher: Cipher, + server_cipher: Cipher, ) -> io::Result<()> { - let mut net_packet = NetPacket::new([0u8; 16])?; - net_packet.set_version(Version::V1); - net_packet.set_protocol(Protocol::Control); - net_packet.set_transport_protocol(control_packet::Protocol::Ping.into()); - //只寻找两跳以内能到的目标 - net_packet.first_set_ttl(2); let mut count = 0; loop { if sender.is_close() { return Ok(()); } let mut current_dev = current_device.load(); - if count % 10 == 0 { - let mut packet = NetPacket::new([0; 12])?; + if count % 20 == 2 { + let mut packet = NetPacket::new_encrypt([0; 12 + ENCRYPTION_RESERVED])?; packet.set_version(Version::V1); + packet.set_gateway_flag(true); packet.set_protocol(Protocol::Control); packet.set_transport_protocol( control_packet::Protocol::AddrRequest.into(), @@ -101,6 +120,7 @@ async fn start_heartbeat_( packet.first_set_ttl(MAX_TTL); packet.set_source(current_dev.virtual_ip()); packet.set_destination(current_dev.virtual_gateway); + server_cipher.encrypt_ipv4(&mut packet)?; let _ = sender.send_main_udp(packet.buffer(), current_dev.connect_server).await; } if count % 20 == 19 { @@ -116,15 +136,9 @@ async fn start_heartbeat_( } } } - net_packet.set_source(current_dev.virtual_ip()); - { - let mut ping = PingPacket::new(net_packet.payload_mut())?; - let epoch = { device_list.lock().0 }; - ping.set_epoch(epoch); - } - set_now_time(&mut net_packet)?; - net_packet.set_destination(current_dev.virtual_gateway()); - if let Err(e) = sender.send_main(net_packet.buffer(), current_dev.connect_server).await + let src = current_dev.virtual_ip(); + let server_packet = heartbeat_packet(&device_list,&client_cipher, &server_cipher, true, src, current_dev.virtual_gateway); + if let Err(e) = sender.send_main(server_packet.buffer(), current_dev.connect_server).await { log::warn!( "connect_server:{:?},e:{:?}", @@ -139,16 +153,15 @@ async fn start_heartbeat_( if peer.virtual_ip == current_dev.virtual_ip { continue; } - set_now_time(&mut net_packet)?; - net_packet.set_destination(peer.virtual_ip); + let client_packet = heartbeat_packet(&device_list,&client_cipher, &server_cipher, false, src, peer.virtual_ip); if let Some(route) = sender.route_one(&peer.virtual_ip) { - let _ = sender.send_by_key(net_packet.buffer(), &route.route_key()).await; + let _ = sender.send_by_key(client_packet.buffer(), &route.route_key()).await; if route.is_p2p() { continue; } } else { //没有直连路由则发送到网关 - let _ = sender.send_main(net_packet.buffer(), current_dev.connect_server).await; + let _ = sender.send_main(client_packet.buffer(), current_dev.connect_server).await; } //再随机发送到其他地址,看有没有客户端符合转发条件 @@ -161,8 +174,7 @@ async fn start_heartbeat_( 'a: for (peer_ip, route_list) in route_list.iter() { for route in route_list { if peer_ip != &peer.virtual_ip && route.is_p2p() { - set_now_time(&mut net_packet)?; - let _ = sender.try_send_by_key(net_packet.buffer(), &route.route_key()); + let _ = sender.try_send_by_key(client_packet.buffer(), &route.route_key()); num += 1; break; } @@ -175,10 +187,12 @@ async fn start_heartbeat_( } } else { for (peer_ip, route_list) in sender.route_table().iter() { - net_packet.set_destination(*peer_ip); + if peer_ip == ¤t_dev.virtual_gateway { + continue; + } + let client_packet = heartbeat_packet(&device_list,&client_cipher, &server_cipher, false, src, *peer_ip); for route in route_list { - set_now_time(&mut net_packet)?; - if let Err(e) = sender.send_by_key(net_packet.buffer(), &route.route_key()).await { + if let Err(e) = sender.send_by_key(client_packet.buffer(), &route.route_key()).await { log::warn!("peer_ip:{:?},route:{:?},e:{:?}", peer_ip, route, e); } tokio::time::sleep(Duration::from_millis(2)).await; diff --git a/vnt/src/handle/mod.rs b/vnt/src/handle/mod.rs index d4359eb..af90d88 100644 --- a/vnt/src/handle/mod.rs +++ b/vnt/src/handle/mod.rs @@ -1,5 +1,6 @@ use std::net::{Ipv4Addr, SocketAddr}; +pub mod handshake_handler; pub mod heartbeat_handler; pub mod punch_handler; pub mod recv_handler; @@ -26,14 +27,16 @@ pub struct PeerDeviceInfo { pub virtual_ip: Ipv4Addr, pub name: String, pub status: PeerDeviceStatus, + pub client_secret: bool, } impl PeerDeviceInfo { - pub fn new(virtual_ip: Ipv4Addr, name: String, status: u8) -> Self { + pub fn new(virtual_ip: Ipv4Addr, name: String, status: u8,client_secret: bool) -> Self { Self { virtual_ip, name, status: PeerDeviceStatus::from(status), + client_secret } } } diff --git a/vnt/src/handle/punch_handler.rs b/vnt/src/handle/punch_handler.rs index 8d71bd6..b287681 100644 --- a/vnt/src/handle/punch_handler.rs +++ b/vnt/src/handle/punch_handler.rs @@ -13,12 +13,16 @@ use std::io; use tokio::sync::mpsc::Receiver; use crate::channel::punch::{NatInfo, Punch}; use crate::channel::sender::ChannelSender; +use crate::cipher::Cipher; use crate::core::status::VntWorker; +use crate::protocol::body::ENCRYPTION_RESERVED; -pub fn start(mut worker: VntWorker, receiver: Receiver<(Ipv4Addr, NatInfo)>, punch: Punch, current_device: Arc>) { +pub fn start(mut worker: VntWorker, receiver: Receiver<(Ipv4Addr, NatInfo)>, + punch: Punch, current_device: Arc>, + client_cipher: Cipher, ) { tokio::spawn(async move { tokio::select! { - _=start0(receiver, punch, current_device)=>{} + _=start0(receiver, punch, current_device,client_cipher)=>{} _=worker.stop_wait()=>{ return; } @@ -27,21 +31,24 @@ pub fn start(mut worker: VntWorker, receiver: Receiver<(Ipv4Addr, NatInfo)>, pun }); } -pub async fn start0(mut receiver: Receiver<(Ipv4Addr, NatInfo)>, mut punch: Punch, current_device: Arc>) { +pub async fn start0(mut receiver: Receiver<(Ipv4Addr, NatInfo)>, + mut punch: Punch, current_device: Arc>, + client_cipher: Cipher, ) { while let Some((peer_ip, nat_info)) = receiver.recv().await { - if let Err(e) = start_(&mut punch, ¤t_device, peer_ip, nat_info).await { + if let Err(e) = start_(&client_cipher, &mut punch, ¤t_device, peer_ip, nat_info).await { log::warn!("网络打洞异常 {:?}", e); } } } async fn start_( + client_cipher: &Cipher, punch: &mut Punch, current_device: &Arc>, peer_ip: Ipv4Addr, nat_info: NatInfo, ) -> io::Result<()> { - let mut packet = NetPacket::new([0u8; 12])?; + let mut packet = NetPacket::new_encrypt([0u8; 12 + ENCRYPTION_RESERVED])?; packet.set_version(Version::V1); packet.first_set_ttl(1); packet.set_protocol(Protocol::Control); @@ -49,7 +56,7 @@ async fn start_( packet.set_source(current_device.load().virtual_ip()); packet.set_destination(peer_ip); log::info!("发起打洞,目标:{:?},{:?}", peer_ip, nat_info); - + client_cipher.encrypt_ipv4(&mut packet)?; punch.punch(packet.buffer(), peer_ip, nat_info).await } @@ -59,6 +66,7 @@ pub async fn start_punch( device_list: Arc)>>, sender: ChannelSender, current_device: Arc>, + client_cipher: Cipher, ) { let mut num = 0; let sleep_time = [3, 5, 7, 11, 13, 17, 19, 23, 29]; @@ -67,7 +75,8 @@ pub async fn start_punch( break; } tokio::select! { - rs= start_punch_(Duration::from_secs(sleep_time[num % sleep_time.len()]),&nat_test, &device_list, &sender, ¤t_device)=>{ + rs= start_punch_(Duration::from_secs(sleep_time[num % sleep_time.len()]),&nat_test, &device_list, + &sender, ¤t_device,&client_cipher)=>{ if let Err(e) = rs { log::warn!("打洞处理任务异常 {:?}", e); } @@ -86,6 +95,7 @@ async fn start_punch_( device_list: &Arc)>>, sender: &ChannelSender, current_device: &Arc>, + client_cipher: &Cipher, ) -> crate::Result<()> { let current_device = current_device.load(); let nat_info = nat_test.nat_info(); @@ -103,7 +113,7 @@ async fn start_punch_( if count > 2 { break; } - let buf = punch_packet(current_device.virtual_ip(), &nat_info, info.virtual_ip)?; + let buf = punch_packet(client_cipher, current_device.virtual_ip(), &nat_info, info.virtual_ip)?; let _ = sender.send_main(&buf, current_device.connect_server).await; } tokio::time::sleep(sleep_time).await; @@ -111,6 +121,7 @@ async fn start_punch_( } pub fn punch_packet( + client_cipher: &Cipher, virtual_ip: Ipv4Addr, nat_info: &NatInfo, dest: Ipv4Addr, @@ -128,13 +139,14 @@ pub fn punch_packet( punch_reply.local_port = nat_info.local_port as u32; punch_reply.nat_type = protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type)); let bytes = punch_reply.write_to_bytes()?; - let mut net_packet = NetPacket::new(vec![0u8; 12 + bytes.len()])?; + let mut net_packet = NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?; net_packet.set_version(Version::V1); net_packet.set_protocol(Protocol::OtherTurn); net_packet.set_transport_protocol(other_turn_packet::Protocol::Punch.into()); net_packet.first_set_ttl(MAX_TTL); net_packet.set_source(virtual_ip); net_packet.set_destination(dest); - net_packet.set_payload(&bytes); + net_packet.set_payload(&bytes)?; + client_cipher.encrypt_ipv4(&mut net_packet)?; Ok(net_packet.into_buffer()) } diff --git a/vnt/src/handle/recv_handler.rs b/vnt/src/handle/recv_handler.rs index 7ea44dd..82725e8 100644 --- a/vnt/src/handle/recv_handler.rs +++ b/vnt/src/handle/recv_handler.rs @@ -1,8 +1,8 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use std::sync::Arc; -use crossbeam_utils::atomic::AtomicCell; use crossbeam_skiplist::SkipMap; +use crossbeam_utils::atomic::AtomicCell; use parking_lot::Mutex; use protobuf::Message; use tokio::sync::mpsc::Sender; @@ -11,21 +11,23 @@ use packet::icmp::{icmp, Kind}; use packet::icmp::icmp::HeaderOther; use packet::ip::ipv4; use packet::ip::ipv4::packet::IpV4Packet; + +use crate::channel::{Route, RouteKey}; use crate::channel::channel::Context; use crate::channel::punch::{NatInfo, NatType}; -use crate::channel::{Route, RouteKey}; -use crate::cipher::Cipher; - +use crate::cipher::{Cipher, RsaCipher}; use crate::error::Error; use crate::external_route::AllowExternalRoute; -use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo, PeerDeviceStatus}; +use crate::handle::{ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo, PeerDeviceStatus}; +use crate::handle::handshake_handler::secret_handshake_req; use crate::handle::registration_handler::Register; use crate::igmp_server::IgmpServer; use crate::ip_proxy::IpProxyMap; use crate::nat; use crate::nat::NatTest; use crate::proto::message::{DeviceList, PunchInfo, PunchNatType, RegistrationResponse}; -use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, service_packet, other_turn_packet, Version, ip_turn_packet}; +use crate::protocol::{control_packet, ip_turn_packet, MAX_TTL, NetPacket, other_turn_packet, Protocol, service_packet, Version}; +use crate::protocol::body::ENCRYPTION_RESERVED; use crate::protocol::control_packet::ControlPacket; use crate::protocol::error_packet::InErrorPacket; use crate::tun_tap_device::DeviceWriter; @@ -44,8 +46,11 @@ pub struct ChannelDataHandler { out_external_route: AllowExternalRoute, cone_sender: Sender<(Ipv4Addr, NatInfo)>, symmetric_sender: Sender<(Ipv4Addr, NatInfo)>, - cipher: Cipher, + client_cipher: Cipher, + server_cipher: Cipher, + rsa_cipher: Option, relay: bool, + token: String, } impl ChannelDataHandler { @@ -61,8 +66,10 @@ impl ChannelDataHandler { out_external_route: AllowExternalRoute, cone_sender: Sender<(Ipv4Addr, NatInfo)>, symmetric_sender: Sender<(Ipv4Addr, NatInfo)>, - cipher: Cipher, - relay: bool, ) -> Self { + client_cipher: Cipher, + server_cipher: Cipher, + rsa_cipher: Option, + relay: bool, token: String, ) -> Self { Self { current_device, device_list, @@ -76,26 +83,29 @@ impl ChannelDataHandler { out_external_route, cone_sender, symmetric_sender, - cipher, + client_cipher, + server_cipher, + rsa_cipher, relay, + token, } } } impl ChannelDataHandler { - pub async fn handle(&mut self, buf: &mut [u8], start: usize, end: usize, route_key: RouteKey, context: &Context) { + pub async fn handle(&self, buf: &mut [u8], start: usize, end: usize, route_key: RouteKey, context: &Context) { assert_eq!(start, 14); match self.handle0(&mut buf[..end], &route_key, context).await { Ok(_) => {} Err(e) => { - log::error!("{:?}",e); + log::warn!("{:?}",e); } } } async fn handle0(&self, buf: &mut [u8], route_key: &RouteKey, context: &Context) -> crate::Result<()> { let mut net_packet = NetPacket::new(&mut buf[14..])?; - if net_packet.ttl() == 0 { + if net_packet.ttl() == 0 || net_packet.source_ttl() < net_packet.ttl() { return Ok(()); } let source = net_packet.source(); @@ -104,16 +114,9 @@ impl ChannelDataHandler { let destination = net_packet.destination(); let not_broadcast = !destination.is_broadcast() && !destination.is_multicast() && destination != current_device.broadcast_address; if current_device.virtual_ip() != destination - && not_broadcast && !destination.is_unspecified() - && self.connect_status.load() == ConnectStatus::Connected { - if !check_dest(source, current_device.virtual_netmask, current_device.virtual_network) { - log::warn!("转发数据,源地址错误:{:?},当前网络:{:?},route_key:{:?}",source,current_device.virtual_network,route_key); - return Ok(()); - } - if !check_dest(destination, current_device.virtual_netmask, current_device.virtual_network) { - log::warn!("转发数据,目的地址错误:{:?},当前网络:{:?},route_key:{:?}",destination,current_device.virtual_network,route_key); - return Ok(()); - } + && not_broadcast && !destination.is_unspecified() { + //校验指纹,不需要解密 + self.client_cipher.check_finger(&net_packet)?; net_packet.set_ttl(net_packet.ttl() - 1); let ttl = net_packet.ttl(); if ttl > 0 { @@ -130,32 +133,25 @@ impl ChannelDataHandler { } return Ok(()); } + if net_packet.is_gateway() { + if net_packet.protocol() == Protocol::Error && net_packet.transport_protocol() == crate::protocol::error_packet::Protocol::NoKey.into() { + if let Some(rsa_cipher) = &self.rsa_cipher { + secret_handshake_req(context, current_device.connect_server, rsa_cipher, &self.server_cipher, self.token.clone()).await?; + } + } else { + //服务端解密 + self.server_cipher.decrypt_ipv4(&mut net_packet)?; + let data_len = net_packet.data_len(); + self.server_packet_handle(context, current_device, buf, data_len, route_key).await?; + } + return Ok(()); + } + self.client_cipher.decrypt_ipv4(&mut net_packet)?; match net_packet.protocol() { Protocol::IpTurn => { match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) { - ip_turn_packet::Protocol::Icmp => { - let ipv4 = IpV4Packet::new(net_packet.payload())?; - if ipv4.protocol() == ipv4::protocol::Protocol::Icmp { - self.device_writer.write_ipv4(&mut buf[12..])?; - return Ok(()); - } - } - ip_turn_packet::Protocol::Igmp => { - if let Some(igmp_server) = &self.igmp_server { - let ipv4 = IpV4Packet::new(net_packet.payload())?; - if ipv4.protocol() == ipv4::protocol::Protocol::Igmp { - igmp_server.handle(ipv4.payload(), source)?; - } - } - return Ok(()); - } ip_turn_packet::Protocol::Ipv4 => { - let data = if let Some(payload_len) = self.cipher.decrypt_ipv4(&mut net_packet)? { - &mut net_packet.payload_mut()[..payload_len] - } else { - net_packet.payload_mut() - }; - let mut ipv4 = IpV4Packet::new(data)?; + let mut ipv4 = IpV4Packet::new(net_packet.payload_mut())?; match ipv4.protocol() { ipv4::protocol::Protocol::Igmp => { if let Some(igmp_server) = &self.igmp_server { @@ -176,7 +172,7 @@ impl ChannelDataHandler { net_packet.set_source(destination); net_packet.set_destination(source); //不管加不加密,和接收到的数据长度都一致 - let _ = self.cipher.encrypt_ipv4(net_packet.payload().len() - 16, &mut net_packet)?; + self.client_cipher.encrypt_ipv4(&mut net_packet)?; context.send_by_key(net_packet.buffer(), route_key).await?; return Ok(()); } @@ -198,7 +194,11 @@ impl ChannelDataHandler { tcp_packet.update_checksum(); ipv4.set_destination_ip(destination); ipv4.update_checksum(); - ip_proxy_map.tcp_proxy_map.insert(SocketAddrV4::new(source, source_port), SocketAddrV4::new(dest_ip, dest_port)); + let key = SocketAddrV4::new(source, source_port); + //https://github.com/crossbeam-rs/crossbeam/issues/1023 + if !ip_proxy_map.tcp_proxy_map.contains_key(&key){ + ip_proxy_map.tcp_proxy_map.insert(key, SocketAddrV4::new(dest_ip, dest_port)); + } } ipv4::protocol::Protocol::Udp => { let dest_ip = ipv4.destination_ip(); @@ -210,7 +210,10 @@ impl ChannelDataHandler { udp_packet.update_checksum(); ipv4.set_destination_ip(destination); ipv4.update_checksum(); - ip_proxy_map.udp_proxy_map.insert(SocketAddrV4::new(source, source_port), SocketAddrV4::new(dest_ip, dest_port)); + let key = SocketAddrV4::new(source, source_port); + if !ip_proxy_map.udp_proxy_map.contains_key(&key){ + ip_proxy_map.udp_proxy_map.insert(key, SocketAddrV4::new(dest_ip, dest_port)); + } } ipv4::protocol::Protocol::Icmp => { let dest_ip = ipv4.destination_ip(); @@ -222,15 +225,23 @@ impl ChannelDataHandler { ip_proxy_map.send_icmp(ipv4.payload(), &dest_ip)?; } _ => { - return Ok(()); + log::warn!("不支持的ip代理Icmp协议:{}",destination); + return Err(Error::Warn("不支持的ip代理Icmp协议".to_string())); } } } _ => { - return Ok(()); + log::warn!("不支持的ip代理ipv4协议:{}",destination); + return Err(Error::Warn("不支持的ip代理ipv4协议".to_string())); } } + } else { + log::warn!("没有ip代理规则:{}",destination); + return Err(Error::Warn("没有ip代理规则".to_string())); } + } else { + log::warn!("不支持ip代理:{}",destination); + return Err(Error::Warn("不支持ip代理".to_string())); } } @@ -244,12 +255,8 @@ impl ChannelDataHandler { ip_turn_packet::Protocol::Unknown(_) => {} } } - Protocol::Service => { - self.service(context, current_device, source, net_packet, route_key).await?; - } - Protocol::Error => { - self.error(context, current_device, source, net_packet, route_key).await?; - } + Protocol::Service => {} + Protocol::Error => {} Protocol::Control => { self.control(context, current_device, source, net_packet, route_key).await?; } @@ -262,7 +269,249 @@ impl ChannelDataHandler { } Ok(()) } - async fn service(&self, context: &Context, current_device: CurrentDeviceInfo, _source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> { + + async fn pong_packet(&self, gateway: bool, metric: u8, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, pong_packet: control_packet::PongPacket<&[u8]>, route_key: &RouteKey) -> crate::Result<()> { + let current_time = crate::handle::now_time() as u16; + if current_time < pong_packet.time() { + return Ok(()); + } + let rt = (current_time - pong_packet.time()) as i64; + let route = Route::from(*route_key, metric, rt); + context.add_route(source, route); + if gateway { + let epoch = self.device_list.lock().0; + if pong_packet.epoch() != epoch { + let mut poll_device = NetPacket::new_encrypt([0; 12 + ENCRYPTION_RESERVED])?; + poll_device.set_source(current_device.virtual_ip()); + poll_device.set_destination(source); + poll_device.set_version(Version::V1); + poll_device.set_gateway_flag(true); + poll_device.first_set_ttl(MAX_TTL); + poll_device.set_protocol(Protocol::Service); + poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into()); + self.server_cipher.encrypt_ipv4(&mut poll_device)?; + context.send_main(poll_device.buffer(), current_device.connect_server).await?; + } + } + Ok(()) + } + async fn control(&self, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, mut net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> { + let metric = net_packet.source_ttl() - net_packet.ttl() + 1; + match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? { + ControlPacket::PingPacket(_) => { + net_packet.set_transport_protocol(control_packet::Protocol::Pong.into()); + net_packet.set_source(current_device.virtual_ip()); + net_packet.set_destination(source); + net_packet.first_set_ttl(MAX_TTL); + self.client_cipher.encrypt_ipv4(&mut net_packet)?; + context.send_by_key(net_packet.buffer(), route_key).await?; + let route = Route::from(*route_key, metric, 199); + context.add_route_if_absent(source, route); + } + ControlPacket::PongPacket(pong_packet) => { + self.pong_packet(false, metric, context, current_device, source, pong_packet, route_key).await?; + } + ControlPacket::PunchRequest => { + if self.relay { + return Ok(()); + } + //回应 + net_packet.set_transport_protocol(control_packet::Protocol::PunchResponse.into()); + net_packet.set_source(current_device.virtual_ip()); + net_packet.set_destination(source); + net_packet.first_set_ttl(1); + self.client_cipher.encrypt_ipv4(&mut net_packet)?; + context.send_by_key(net_packet.buffer(), route_key).await?; + let route = Route::from(*route_key, 1, 199); + context.add_route_if_absent(source, route); + } + ControlPacket::PunchResponse => { + if self.relay { + return Ok(()); + } + let route = Route::from(*route_key, 1, 199); + context.add_route_if_absent(source, route); + } + ControlPacket::AddrRequest => { + match route_key.addr.ip() { + std::net::IpAddr::V4(ipv4) => { + let mut packet = NetPacket::new_encrypt([0; 12 + 6 + ENCRYPTION_RESERVED])?; + packet.set_version(Version::V1); + packet.set_protocol(Protocol::Control); + packet.set_transport_protocol( + control_packet::Protocol::AddrResponse.into(), + ); + packet.first_set_ttl(MAX_TTL); + packet.set_source(current_device.virtual_ip()); + packet.set_destination(source); + let mut addr_packet = control_packet::AddrPacket::new(packet.payload_mut())?; + addr_packet.set_ipv4(ipv4); + addr_packet.set_port(route_key.addr.port()); + self.client_cipher.encrypt_ipv4(&mut packet)?; + context.send_by_key(packet.buffer(), route_key).await?; + } + std::net::IpAddr::V6(_) => {} + } + } + ControlPacket::AddrResponse(addr_packet) => { + if !addr_packet.ipv4().is_multicast() + && !addr_packet.ipv4().is_broadcast() + && !addr_packet.ipv4().is_unspecified() + && !addr_packet.ipv4().is_loopback() + && !addr_packet.ipv4().is_private() && addr_packet.port() != 0 { + self.nat_test.update_addr(addr_packet.ipv4(), addr_packet.port()) + } + } + } + Ok(()) + } + async fn other_turn(&self, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> { + if self.relay { + return Ok(()); + } + match other_turn_packet::Protocol::from(net_packet.transport_protocol()) { + other_turn_packet::Protocol::Punch => { + let punch_info = PunchInfo::parse_from_bytes(net_packet.payload())?; + let public_ips = punch_info.public_ip_list. + iter().map(|v| { Ipv4Addr::from(v.to_be_bytes()) }).collect(); + let peer_nat_info = NatInfo::new(public_ips, + punch_info.public_port as u16, + punch_info.public_port_range as u16, + Ipv4Addr::from(punch_info.local_ip.to_be_bytes()), + punch_info.local_port as u16, + punch_info.nat_type.enum_value_or_default().into()); + self.peer_nat_info_map.insert(source, peer_nat_info.clone()); + if !punch_info.reply { + let mut punch_reply = PunchInfo::new(); + punch_reply.reply = true; + let nat_info = self.nat_test.nat_info(); + punch_reply.public_ip_list = nat_info.public_ips.iter().map(|ip| u32::from_be_bytes(ip.octets())).collect(); + punch_reply.public_port = nat_info.public_port as u32; + punch_reply.public_port_range = nat_info.public_port_range as u32; + punch_reply.nat_type = + protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type)); + punch_reply.local_ip = u32::from_be_bytes(nat_info.local_ip.octets()); + punch_reply.local_port = nat_info.local_port as u32; + let bytes = punch_reply.write_to_bytes()?; + let mut punch_packet = + NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?; + punch_packet.set_version(Version::V1); + punch_packet.set_protocol(Protocol::OtherTurn); + punch_packet.set_transport_protocol( + other_turn_packet::Protocol::Punch.into(), + ); + punch_packet.first_set_ttl(MAX_TTL); + punch_packet.set_source(current_device.virtual_ip()); + punch_packet.set_destination(source); + punch_packet.set_payload(&bytes)?; + if !peer_nat_info.local_ip.is_unspecified() && peer_nat_info.local_port != 0 { + let mut packet = NetPacket::new_encrypt([0u8; 12 + ENCRYPTION_RESERVED])?; + packet.set_version(Version::V1); + packet.first_set_ttl(1); + packet.set_protocol(Protocol::Control); + packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into()); + packet.set_source(current_device.virtual_ip()); + packet.set_destination(source); + self.client_cipher.encrypt_ipv4(&mut packet)?; + let _ = context.send_main(packet.buffer(), SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port))).await; + } + if self.punch(source, peer_nat_info).await { + self.client_cipher.encrypt_ipv4(&mut punch_packet)?; + context.send_by_key(punch_packet.buffer(), route_key).await?; + } + } else { + self.punch(source, peer_nat_info).await; + } + } + other_turn_packet::Protocol::Unknown(e) => { + log::warn!("不支持的转发协议 {:?},source:{:?}",e,source); + } + } + Ok(()) + } + async fn punch(&self, peer_ip: Ipv4Addr, peer_nat_info: NatInfo) -> bool { + match peer_nat_info.nat_type { + NatType::Symmetric => { + self.symmetric_sender.try_send((peer_ip, peer_nat_info)).is_ok() + } + NatType::Cone => { + self.cone_sender.try_send((peer_ip, peer_nat_info)).is_ok() + } + } + } +} + +/// 处理服务端数据 +impl ChannelDataHandler { + async fn server_packet_handle(&self, context: &Context, current_device: CurrentDeviceInfo, buf: &mut [u8], data_len: usize, route_key: &RouteKey) -> crate::Result<()> { + let net_packet = NetPacket::new0(data_len, &buf[14..])?; + let source = net_packet.source(); + match net_packet.protocol() { + Protocol::Service => { + self.service(context, current_device, net_packet, route_key).await?; + } + Protocol::Error => { + self.error(context, current_device, source, net_packet, route_key).await?; + } + Protocol::Control => { + self.control_gateway(context, current_device, net_packet, route_key).await?; + } + Protocol::IpTurn => { + match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) { + ip_turn_packet::Protocol::Ipv4 => { + let ipv4 = IpV4Packet::new(net_packet.payload())?; + match ipv4.protocol() { + ipv4::protocol::Protocol::Igmp => { + if let Some(igmp_server) = &self.igmp_server { + igmp_server.handle(ipv4.payload(), source)?; + } + return Ok(()); + } + ipv4::protocol::Protocol::Icmp => { + if ipv4.destination_ip() == current_device.virtual_ip { + let icmp_packet = icmp::IcmpPacket::new(ipv4.payload())?; + if icmp_packet.kind() == Kind::EchoReply { + self.device_writer.write_ipv4(&mut buf[12..])?; + return Ok(()); + } + } + } + _ => {} + } + } + ip_turn_packet::Protocol::Ipv4Broadcast => {} + ip_turn_packet::Protocol::Unknown(_) => {} + } + } + Protocol::OtherTurn => {} + Protocol::UnKnow(_) => {} + } + return Ok(()); + } + async fn control_gateway(&self, context: &Context, current_device: CurrentDeviceInfo, net_packet: NetPacket<&[u8]>, route_key: &RouteKey) -> crate::Result<()> { + if net_packet.source() != current_device.virtual_gateway { + return Ok(()); + } + match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? { + ControlPacket::PongPacket(pong_packet) => { + let metric = net_packet.source_ttl() - net_packet.ttl() + 1; + self.pong_packet(true, metric, context, current_device, net_packet.source(), pong_packet, route_key).await?; + } + ControlPacket::AddrResponse(addr_packet) => { + if addr_packet.port() != 0 + && !addr_packet.ipv4().is_multicast() + && !addr_packet.ipv4().is_broadcast() + && !addr_packet.ipv4().is_unspecified() + && !addr_packet.ipv4().is_loopback() + && !addr_packet.ipv4().is_private() { + self.nat_test.update_addr(addr_packet.ipv4(), addr_packet.port()) + } + } + _ => {} + } + Ok(()) + } + async fn service(&self, context: &Context, current_device: CurrentDeviceInfo, net_packet: NetPacket<&[u8]>, route_key: &RouteKey) -> crate::Result<()> { match service_packet::Protocol::from(net_packet.transport_protocol()) { service_packet::Protocol::RegistrationRequest => {} service_packet::Protocol::RegistrationResponse => { @@ -305,6 +554,7 @@ impl ChannelDataHandler { Ipv4Addr::from(info.virtual_ip), info.name, info.device_status as u8, + info.client_secret, ) }) .collect(); @@ -323,10 +573,11 @@ impl ChannelDataHandler { service_packet::Protocol::Unknown(u) => { log::warn!("未知服务协议:{}",u); } + _ => {} } Ok(()) } - async fn error(&self, _context: &Context, current_device: CurrentDeviceInfo, _source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, _route_key: &RouteKey) -> crate::Result<()> { + async fn error(&self, _context: &Context, current_device: CurrentDeviceInfo, _source: Ipv4Addr, net_packet: NetPacket<&[u8]>, _route_key: &RouteKey) -> crate::Result<()> { log::info!("current_device:{:?}",current_device); match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload())? { InErrorPacket::TokenError => { @@ -355,167 +606,8 @@ impl ChannelDataHandler { InErrorPacket::InvalidIp => { log::error!("InvalidIp"); } + InErrorPacket::NoKey => {} } Ok(()) } - async fn control(&self, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, mut net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> { - let metric = net_packet.source_ttl() - net_packet.ttl() + 1; - match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? { - ControlPacket::PingPacket(_) => { - net_packet.set_transport_protocol(control_packet::Protocol::Pong.into()); - net_packet.set_source(current_device.virtual_ip()); - net_packet.set_destination(source); - net_packet.first_set_ttl(MAX_TTL); - context.send_by_key(net_packet.buffer(), route_key).await?; - let route = Route::from(*route_key, metric, 199); - context.add_route_if_absent(source, route); - } - ControlPacket::PongPacket(pong_packet) => { - let current_time = crate::handle::now_time() as u16; - if current_time < pong_packet.time() { - return Ok(()); - } - let rt = (current_time - pong_packet.time()) as i64; - let route = Route::from(*route_key, metric, rt); - context.add_route(source, route); - if source == current_device.virtual_gateway() { - let epoch = self.device_list.lock().0; - if pong_packet.epoch() != epoch { - let mut poll_device = NetPacket::new([0; 12])?; - poll_device.set_source(current_device.virtual_ip()); - poll_device.set_destination(source); - poll_device.set_version(Version::V1); - poll_device.first_set_ttl(MAX_TTL); - poll_device.set_protocol(Protocol::Service); - poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into()); - context.send_main(poll_device.buffer(), current_device.connect_server).await?; - } - } - } - ControlPacket::PunchRequest => { - if self.relay { - return Ok(()); - } - //回应 - net_packet.set_transport_protocol(control_packet::Protocol::PunchResponse.into()); - net_packet.set_source(current_device.virtual_ip()); - net_packet.set_destination(source); - net_packet.first_set_ttl(1); - context.send_by_key(net_packet.buffer(), route_key).await?; - let route = Route::from(*route_key, metric, 199); - context.add_route_if_absent(source, route); - } - ControlPacket::PunchResponse => { - if self.relay { - return Ok(()); - } - // log::info!("PunchResponse route_key:{:?}",route_key); - let route = Route::from(*route_key, metric, 199); - context.add_route_if_absent(source, route); - } - ControlPacket::AddrRequest => { - match route_key.addr.ip() { - std::net::IpAddr::V4(ipv4) => { - let mut packet = NetPacket::new([0; 12 + 6])?; - packet.set_version(Version::V1); - packet.set_protocol(Protocol::Control); - packet.set_transport_protocol( - control_packet::Protocol::AddrResponse.into(), - ); - packet.first_set_ttl(MAX_TTL); - packet.set_source(current_device.virtual_ip()); - packet.set_destination(source); - let mut addr_packet = control_packet::AddrPacket::new(packet.payload_mut())?; - addr_packet.set_ipv4(ipv4); - addr_packet.set_port(route_key.addr.port()); - context.send_by_key(packet.buffer(), route_key).await?; - } - std::net::IpAddr::V6(_) => {} - } - } - ControlPacket::AddrResponse(addr_packet) => { - if addr_packet.port() != 0 - && !addr_packet.ipv4().is_multicast() - && !addr_packet.ipv4().is_broadcast() - && !addr_packet.ipv4().is_unspecified() - && !addr_packet.ipv4().is_loopback() - && !addr_packet.ipv4().is_private() { - self.nat_test.update_addr(addr_packet.ipv4(), addr_packet.port()) - } - } - } - Ok(()) - } - async fn other_turn(&self, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> { - if self.relay { - return Ok(()); - } - match other_turn_packet::Protocol::from(net_packet.transport_protocol()) { - other_turn_packet::Protocol::Punch => { - let punch_info = PunchInfo::parse_from_bytes(net_packet.payload())?; - let public_ips = punch_info.public_ip_list. - iter().map(|v| { Ipv4Addr::from(v.to_be_bytes()) }).collect(); - let peer_nat_info = NatInfo::new(public_ips, - punch_info.public_port as u16, - punch_info.public_port_range as u16, - Ipv4Addr::from(punch_info.local_ip.to_be_bytes()), - punch_info.local_port as u16, - punch_info.nat_type.enum_value_or_default().into()); - self.peer_nat_info_map.insert(source, peer_nat_info.clone()); - if !punch_info.reply { - let mut punch_reply = PunchInfo::new(); - punch_reply.reply = true; - let nat_info = self.nat_test.nat_info(); - punch_reply.public_ip_list = nat_info.public_ips.iter().map(|ip| u32::from_be_bytes(ip.octets())).collect(); - punch_reply.public_port = nat_info.public_port as u32; - punch_reply.public_port_range = nat_info.public_port_range as u32; - punch_reply.nat_type = - protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type)); - punch_reply.local_ip = u32::from_be_bytes(nat_info.local_ip.octets()); - punch_reply.local_port = nat_info.local_port as u32; - let bytes = punch_reply.write_to_bytes()?; - let mut net_packet = - NetPacket::new(vec![0u8; 12 + bytes.len()])?; - net_packet.set_version(Version::V1); - net_packet.set_protocol(Protocol::OtherTurn); - net_packet.set_transport_protocol( - other_turn_packet::Protocol::Punch.into(), - ); - net_packet.first_set_ttl(MAX_TTL); - net_packet.set_source(current_device.virtual_ip()); - net_packet.set_destination(source); - net_packet.set_payload(&bytes); - if !peer_nat_info.local_ip.is_unspecified() && peer_nat_info.local_port != 0 { - let mut packet = NetPacket::new([0u8; 12])?; - packet.set_version(Version::V1); - packet.first_set_ttl(1); - packet.set_protocol(Protocol::Control); - packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into()); - packet.set_source(current_device.virtual_ip()); - packet.set_destination(source); - let _ = context.send_main(packet.buffer(), SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port))).await; - } - if self.punch(source, peer_nat_info).await { - context.send_by_key(net_packet.buffer(), route_key).await?; - } - } else { - self.punch(source, peer_nat_info).await; - } - } - other_turn_packet::Protocol::Unknown(e) => { - log::warn!("不支持的转发协议 {:?},source:{:?}",e,source); - } - } - Ok(()) - } - async fn punch(&self, peer_ip: Ipv4Addr, peer_nat_info: NatInfo) -> bool { - match peer_nat_info.nat_type { - NatType::Symmetric => { - self.symmetric_sender.try_send((peer_ip, peer_nat_info)).is_ok() - } - NatType::Cone => { - self.cone_sender.try_send((peer_ip, peer_nat_info)).is_ok() - } - } - } } \ No newline at end of file diff --git a/vnt/src/handle/registration_handler.rs b/vnt/src/handle/registration_handler.rs index df9f162..14d1131 100644 --- a/vnt/src/handle/registration_handler.rs +++ b/vnt/src/handle/registration_handler.rs @@ -1,4 +1,3 @@ -use std::io; use std::net::{Ipv4Addr, SocketAddr}; use std::time::{Duration, Instant}; use crossbeam_utils::atomic::AtomicCell; @@ -7,11 +6,13 @@ use protobuf::Message; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::{TcpStream, UdpSocket}; use crate::channel::sender::ChannelSender; +use crate::cipher::Cipher; use crate::handle::PeerDeviceInfo; use crate::proto::message::{RegistrationRequest, RegistrationResponse}; use crate::protocol::error_packet::InErrorPacket; use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL}; +use crate::protocol::body::ENCRYPTION_RESERVED; pub enum ReqEnum { TokenError, @@ -38,14 +39,16 @@ pub struct RegResponse { pub async fn registration( main_channel: &UdpSocket, main_tcp_channel: Option<&mut TcpStream>, + server_cipher: &Cipher, server_address: SocketAddr, token: String, device_id: String, name: String, ip: Ipv4Addr, + client_secret: bool, ) -> Result { let request_packet = - registration_request_packet(token.clone(), device_id.clone(), name.clone(), ip, false, false).unwrap(); + registration_request_packet(server_cipher, token.clone(), device_id.clone(), name.clone(), ip, false, false, client_secret).unwrap(); let buf = request_packet.buffer(); let mut recv_buf = [0u8; 10240]; let recv_buf = if let Some(main_tcp_channel) = main_tcp_channel { @@ -61,10 +64,13 @@ pub async fn registration( return Err(ReqEnum::Other(format!("read error:{}", e))); } let len = 4 + (((recv_buf[2] as u16) << 8) | recv_buf[3] as u16) as usize; + if len > recv_buf.len() { + return Err(ReqEnum::Other("too long".to_string())); + } if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[4..len]).await { return Err(ReqEnum::Other(format!("read error:{}", e))); } - &recv_buf[4..len] + &mut recv_buf[4..len] } else { if let Err(e) = main_channel.send_to(buf, server_address).await { return Err(ReqEnum::Other(format!("send error:{}", e))); @@ -76,7 +82,7 @@ pub async fn registration( if server_address != addr { return Err(ReqEnum::Other(format!("invalid data,from {}", addr))); } - &recv_buf[..len] + &mut recv_buf[..len] } Err(e) => { return Err(ReqEnum::Other(format!("receiver error:{}", e))); @@ -88,7 +94,7 @@ pub async fn registration( } } }; - let net_packet = match NetPacket::new(recv_buf) { + let mut net_packet = match NetPacket::new(recv_buf) { Ok(net_packet) => { net_packet } @@ -96,6 +102,9 @@ pub async fn registration( return Err(ReqEnum::ServerError(format!("{}", e))); } }; + if let Err(e) = server_cipher.decrypt_ipv4(&mut net_packet) { + return Err(ReqEnum::ServerError(format!("decrypt_ipv4 {}", e))); + } match net_packet.protocol() { Protocol::Service => { match service_packet::Protocol::from(net_packet.transport_protocol()) { @@ -110,6 +119,7 @@ pub async fn registration( Ipv4Addr::from(info.virtual_ip), info.name, info.device_status as u8, + info.client_secret, ) }) .collect(); @@ -155,6 +165,9 @@ pub async fn registration( InErrorPacket::InvalidIp => { Err(ReqEnum::InvalidIp) } + InErrorPacket::NoKey => { + Err(ReqEnum::ServerError("no key".to_string())) + } }, Err(e) => Err(ReqEnum::Other(format!("{}", e))), } @@ -164,12 +177,14 @@ pub async fn registration( } fn registration_request_packet( + server_cipher: &Cipher, token: String, device_id: String, name: String, ip: Ipv4Addr, is_fast: bool, allow_ip_change: bool, + client_secret: bool, ) -> crate::Result>> { let mut request = RegistrationRequest::new(); request.token = token; @@ -178,45 +193,54 @@ fn registration_request_packet( request.virtual_ip = ip.into(); request.allow_ip_change = allow_ip_change; request.is_fast = is_fast; - request.version = "1.1.2".to_string(); + request.version = "1.2.0".to_string(); + request.client_secret = client_secret; let bytes = request.write_to_bytes()?; - let buf = vec![0u8; 12 + bytes.len()]; - let mut net_packet = NetPacket::new(buf)?; + let buf = vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED]; + let mut net_packet = NetPacket::new_encrypt(buf)?; net_packet.set_version(Version::V1); + net_packet.set_gateway_flag(true); net_packet.set_protocol(Protocol::Service); net_packet.set_transport_protocol(service_packet::Protocol::RegistrationRequest.into()); net_packet.first_set_ttl(MAX_TTL); - net_packet.set_payload(&bytes); + net_packet.set_payload(&bytes)?; + server_cipher.encrypt_ipv4(&mut net_packet)?; Ok(net_packet) } pub struct Register { + server_cipher: Cipher, sender: ChannelSender, server_address: SocketAddr, token: String, device_id: String, name: String, time: AtomicCell, + client_secret: bool, } impl Register { pub fn new( + server_cipher: Cipher, sender: ChannelSender, server_address: SocketAddr, token: String, device_id: String, name: String, + client_secret: bool, ) -> Self { Self { + server_cipher, sender, server_address, token, device_id, name, time: AtomicCell::new(Instant::now()), + client_secret, } } - pub async fn fast_register(&self, ip: Ipv4Addr) -> io::Result<()> { + pub async fn fast_register(&self, ip: Ipv4Addr) -> crate::Result<()> { let last = self.time.load(); if last.elapsed() < Duration::from_secs(2) || self @@ -229,14 +253,15 @@ impl Register { } log::info!("重新连接"); let request_packet = registration_request_packet( + &self.server_cipher, self.token.clone(), self.device_id.clone(), self.name.clone(), ip, false, true, - ) - .unwrap(); + self.client_secret, + )?; let buf = request_packet.buffer(); self.sender.send_main(buf, self.server_address).await?; Ok(()) diff --git a/vnt/src/handle/tun_tap/channel_group.rs b/vnt/src/handle/tun_tap/channel_group.rs new file mode 100644 index 0000000..9d896bc --- /dev/null +++ b/vnt/src/handle/tun_tap/channel_group.rs @@ -0,0 +1,23 @@ +#[derive(Clone)] +pub struct BufSenderGroup(usize, Vec, usize, usize)>>); + +pub struct BufReceiverGroup(pub Vec, usize, usize)>>); + +impl BufSenderGroup { + pub async fn send(&mut self, val: (Vec, usize, usize)) -> bool { + let index = self.0 % self.1.len(); + self.0 = self.0.wrapping_add(1); + self.1[index].send(val).await.is_ok() + } +} + +pub fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) { + let mut buf_sender_group = Vec::with_capacity(size); + let mut buf_receiver_group = Vec::with_capacity(size); + for _ in 0..size { + let (buf_sender, buf_receiver) = tokio::sync::mpsc::channel::<(Vec, usize, usize)>(10); + buf_sender_group.push(buf_sender); + buf_receiver_group.push(buf_receiver); + } + (BufSenderGroup(0, buf_sender_group), BufReceiverGroup(buf_receiver_group)) +} \ No newline at end of file diff --git a/vnt/src/handle/tun_tap/mod.rs b/vnt/src/handle/tun_tap/mod.rs index aa59b65..fa37b8e 100644 --- a/vnt/src/handle/tun_tap/mod.rs +++ b/vnt/src/handle/tun_tap/mod.rs @@ -1,4 +1,7 @@ -use std::net::{Ipv4Addr, SocketAddrV4}; +use std::io; +use std::net::SocketAddrV4; +use std::sync::Arc; +use parking_lot::RwLock; use packet::ip::ipv4::packet::IpV4Packet; use packet::ip::ipv4::protocol::Protocol; use packet::tcp::tcp::TcpPacket; @@ -8,21 +11,22 @@ use crate::cipher::Cipher; use crate::external_route::ExternalRoute; use crate::handle::{check_dest, CurrentDeviceInfo}; use crate::ip_proxy::IpProxyMap; -use crate::protocol::{ip_turn_packet, NetPacket, Version}; +use crate::protocol::{ip_turn_packet, MAX_TTL, NetPacket, Version}; use crate::error::*; -use crate::igmp_server::IgmpServer; +use crate::igmp_server::{IgmpServer, Multicast}; use crate::protocol; -use crate::protocol::ip_turn_packet::BroadcastPacketEnd; - +use crate::protocol::body::ENCRYPTION_RESERVED; +use crate::protocol::ip_turn_packet::BroadcastPacket; +pub mod channel_group; pub mod tun_handler; #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] pub mod tap_handler; -async fn broadcast(sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]>, data_len: usize, current_device: &CurrentDeviceInfo) -> Result<()> { +async fn broadcast(server_cipher: &Cipher, multicast_members: Option>>, sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]>, current_device: &CurrentDeviceInfo) -> Result<()> { let mut peer_ips = Vec::with_capacity(8); let vec = sender.route_table_one(); let mut relay_count = 0; - const MAX_COUNT: usize = u8::MAX as usize; + const MAX_COUNT: usize = 8; for (peer_ip, route) in vec { if peer_ip == current_device.virtual_gateway { continue; @@ -30,8 +34,13 @@ async fn broadcast(sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]> if peer_ips.len() == MAX_COUNT { break; } + if let Some(members) = &multicast_members { + if !members.read().is_send(&peer_ip) { + continue; + } + } if route.is_p2p() - && sender.send_by_key(&net_packet.buffer()[..data_len], &route.route_key()).await.is_ok() { + && sender.send_by_key(net_packet.buffer(), &route.route_key()).await.is_ok() { peer_ips.push(peer_ip); } else { relay_count += 1; @@ -41,78 +50,51 @@ async fn broadcast(sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]> //不需要转发 return Ok(()); } - + //转发到服务端的可选择广播,还要进行服务端加密 if peer_ips.is_empty() { - sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?; + sender.send_main(net_packet.buffer(), current_device.connect_server).await?; } else { - let end_len = 1 + peer_ips.len() * 4; + let buf = vec![0 as u8; 12 + 1 + peer_ips.len() * 4 + net_packet.data_len() + ENCRYPTION_RESERVED]; //剩余的发送到服务端,需要告知哪些已发送过 - //放在末尾可以减少复制次数 - let mut broadcast = BroadcastPacketEnd::unchecked(&mut net_packet.buffer_mut()[data_len..data_len + end_len]); - broadcast.set_address(&peer_ips)?; - net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4Broadcast.into()); - sender.send_main(&net_packet.buffer()[..(data_len + end_len)], current_device.connect_server).await?; - } - Ok(()) -} + let mut server_packet = NetPacket::new_encrypt(buf)?; + server_packet.set_version(Version::V1); + server_packet.set_gateway_flag(true); + server_packet.first_set_ttl(MAX_TTL); + server_packet.set_source(net_packet.source()); + server_packet.set_destination(current_device.virtual_gateway); + server_packet.set_protocol(protocol::Protocol::IpTurn); + server_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4Broadcast.into()); -async fn multicast(igmp_server: &IgmpServer, multicast_addr: Ipv4Addr, sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]>, data_len: usize, current_device: &CurrentDeviceInfo) -> Result<()> { - let mut peer_ips = Vec::with_capacity(8); - let vec = sender.route_table_one(); - let mut relay_count = 0; - const MAX_COUNT: usize = u8::MAX as usize; - if let Some(members) = igmp_server.load(&multicast_addr) { - for (peer_ip, route) in vec { - if peer_ip == current_device.virtual_gateway { - continue; - } - let is_send = { members.read().is_send(&peer_ip) }; - if is_send { - if peer_ips.len() == MAX_COUNT { - break; - } - if route.is_p2p() - && sender.send_by_key(&net_packet.buffer()[..data_len], &route.route_key()).await.is_ok() { - peer_ips.push(peer_ip); - } else { - relay_count += 1; - } - } - } - } - if relay_count == 0 && !peer_ips.is_empty() && peer_ips.len() != MAX_COUNT { - //不需要转发 - return Ok(()); - } - if peer_ips.is_empty() { - sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?; - } else { - let end_len = 1 + peer_ips.len() * 4; - //剩余的发送到服务端,需要告知哪些已发送过 - //放在末尾可以减少复制次数 - let mut broadcast = BroadcastPacketEnd::unchecked(&mut net_packet.buffer_mut()[data_len..data_len + end_len]); + let mut broadcast = BroadcastPacket::unchecked(server_packet.payload_mut()); broadcast.set_address(&peer_ips)?; - net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4Broadcast.into()); - sender.send_main(&net_packet.buffer()[..(data_len + end_len)], current_device.connect_server).await?; + broadcast.set_data(net_packet.buffer())?; + server_cipher.encrypt_ipv4(&mut server_packet)?; + sender.send_main(server_packet.buffer(), current_device.connect_server).await?; } Ok(()) } /// 实现一个原地发送,必须保证是如下结构 -/// |12字节开头|ip报文|至少1024字节+12字节结尾| +/// |12字节开头|ip报文|至少1024字节结尾| /// #[inline] pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8], - mut data_len: usize,//数据总长度=ip长度+12 + data_len: usize,//数据总长度=12+ip包长度 igmp_server: &Option, current_device: CurrentDeviceInfo, - ip_route: &Option, proxy_map: &Option, cipher: &Cipher) -> Result<()> { + ip_route: &Option, + proxy_map: &Option, + client_cipher: &Cipher, + server_cipher: &Cipher) -> Result<()> { let ipv4_packet = IpV4Packet::new(&buf[12..data_len])?; let protocol = ipv4_packet.protocol(); let ip_head_len = ipv4_packet.header_len() as usize * 4; + if 12 + ip_head_len >= data_len { + Err(io::Error::new(io::ErrorKind::Other, "ip_head_len err"))? + } let src_ip = ipv4_packet.source_ip(); let mut dest_ip = ipv4_packet.destination_ip(); - let mut net_packet = NetPacket::new(buf)?; + let mut net_packet = NetPacket::new0(data_len, buf)?; net_packet.set_version(Version::V1); net_packet.set_protocol(protocol::Protocol::IpTurn); net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4.into()); @@ -121,9 +103,9 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8], net_packet.set_destination(dest_ip); if dest_ip == current_device.virtual_gateway { if protocol == Protocol::Icmp { - net_packet.set_transport_protocol(ip_turn_packet::Protocol::Icmp.into()); - //发送到服务端的不加密 - sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?; + net_packet.set_gateway_flag(true); + server_cipher.encrypt_ipv4(&mut net_packet)?; + sender.send_main(net_packet.buffer(), current_device.connect_server).await?; } return Ok(()); } @@ -131,39 +113,30 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8], match protocol { Protocol::Igmp => { if igmp_server.is_some() { - net_packet.set_transport_protocol(ip_turn_packet::Protocol::Igmp.into()); //发送到服务端 net_packet.set_destination(current_device.virtual_gateway); - sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?; + net_packet.set_gateway_flag(true); + server_cipher.encrypt_ipv4(&mut net_packet)?; + sender.send_main(net_packet.buffer(), current_device.connect_server).await?; } - return Ok(()); } Protocol::Udp => { - if let Some(igmp_server) = igmp_server { - if let Some(len) = cipher.encrypt_ipv4(data_len - 12, &mut net_packet)? { - data_len = 12 + len; - } - multicast(igmp_server, dest_ip, sender, &mut net_packet, data_len, ¤t_device).await?; - return Ok(()); + client_cipher.encrypt_ipv4(&mut net_packet)?; + let multicast_members = if let Some(igmp_server) = igmp_server { + igmp_server.load(&dest_ip) } else { - //当广播 - dest_ip = Ipv4Addr::BROADCAST; - net_packet.set_destination(dest_ip); - } - } - _ => { - return Ok(()); + None + }; + broadcast(server_cipher, multicast_members, sender, &mut net_packet, ¤t_device).await?; } + _ => {} } + return Ok(()); } if dest_ip.is_broadcast() || current_device.broadcast_address == dest_ip { // 广播 发送到直连目标 - if Protocol::Udp == protocol { - if let Some(len) = cipher.encrypt_ipv4(data_len - 12, &mut net_packet)? { - data_len = 12 + len; - } - broadcast(sender, &mut net_packet, data_len, ¤t_device).await?; - } + client_cipher.encrypt_ipv4(&mut net_packet)?; + broadcast(server_cipher, None, sender, &mut net_packet, ¤t_device).await?; return Ok(()); } if !check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) { @@ -186,32 +159,38 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8], match protocol { Protocol::Tcp => { let dest_addr = { - let tcp_packet = TcpPacket::new(src_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?; + let tcp_packet = TcpPacket::new(src_ip, dest_ip, + &mut net_packet.payload_mut()[ip_head_len..])?; SocketAddrV4::new(dest_ip, tcp_packet.destination_port()) }; if let Some(entry) = proxy_map.tcp_proxy_map.get(&dest_addr) { let source_addr = entry.value(); let source_ip = *source_addr.ip(); - let mut tcp_packet = TcpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?; + let mut tcp_packet = TcpPacket::new(source_ip, dest_ip, + &mut net_packet.payload_mut()[ip_head_len..])?; tcp_packet.set_source_port(source_addr.port()); tcp_packet.update_checksum(); - let mut ipv4_packet = IpV4Packet::new(&mut net_packet.buffer_mut()[12..data_len])?; + let mut ipv4_packet = IpV4Packet::new(net_packet.payload_mut())?; ipv4_packet.set_source_ip(source_ip); ipv4_packet.update_checksum(); + }else{ + log::warn!("不存在接口 {:?}",dest_addr); } } Protocol::Udp => { let dest_addr = { - let udp_packet = UdpPacket::new(src_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?; + let udp_packet = UdpPacket::new(src_ip, dest_ip, + &mut net_packet.payload_mut()[ip_head_len..])?; SocketAddrV4::new(dest_ip, udp_packet.destination_port()) }; if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) { let source_addr = entry.value(); let source_ip = *source_addr.ip(); - let mut udp_packet = UdpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?; + let mut udp_packet = UdpPacket::new(source_ip, dest_ip, + &mut net_packet.payload_mut()[ip_head_len..])?; udp_packet.set_source_port(source_addr.port()); udp_packet.update_checksum(); - let mut ipv4_packet = IpV4Packet::new(&mut net_packet.buffer_mut()[12..data_len])?; + let mut ipv4_packet = IpV4Packet::new(net_packet.payload_mut())?; ipv4_packet.set_source_ip(source_ip); ipv4_packet.update_checksum(); } @@ -219,13 +198,10 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8], _ => {} } } - if let Some(len) = cipher.encrypt_ipv4(data_len - 12, &mut net_packet)? { - data_len = 12 + len; - } - + client_cipher.encrypt_ipv4(&mut net_packet)?; //优先发到直连到地址 - if sender.send_by_id(&net_packet.buffer()[..data_len], &dest_ip).await.is_err() { - sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?; + if sender.send_by_id(net_packet.buffer(), &dest_ip).await.is_err() { + sender.send_main(net_packet.buffer(), current_device.connect_server).await?; } return Ok(()); } diff --git a/vnt/src/handle/tun_tap/tap_handler.rs b/vnt/src/handle/tun_tap/tap_handler.rs index 4ea5771..4cf2c26 100644 --- a/vnt/src/handle/tun_tap/tap_handler.rs +++ b/vnt/src/handle/tun_tap/tap_handler.rs @@ -16,6 +16,7 @@ use crate::cipher::Cipher; use crate::core::status::VntWorker; use crate::external_route::ExternalRoute; use crate::handle::CurrentDeviceInfo; +use crate::handle::tun_tap::channel_group::{buf_channel_group, BufSenderGroup}; use crate::igmp_server::IgmpServer; use crate::ip_proxy::IpProxyMap; use crate::tun_tap_device::{DeviceReader, DeviceWriter}; @@ -27,14 +28,34 @@ pub fn start(worker: VntWorker, sender: ChannelSender, current_device: Arc>, ip_route: Option, ip_proxy_map: Option, - cipher: Cipher) { + client_cipher: Cipher, server_cipher: Cipher) { + let (buf_sender, buf_receiver) = buf_channel_group(6); + for mut buf_receiver in buf_receiver.0 { + let sender = sender.clone(); + let device_writer = device_writer.clone(); + let igmp_server = igmp_server.clone(); + let current_device = current_device.clone(); + let ip_route = ip_route.clone(); + let ip_proxy_map = ip_proxy_map.clone(); + let client_cipher = client_cipher.clone(); + let server_cipher = server_cipher.clone(); + tokio::spawn(async move { + while let Some((mut buf, _, len)) = buf_receiver.recv().await { + match handle(&mut buf, len, &igmp_server, ¤t_device, &device_writer, &sender, + &ip_route, &ip_proxy_map, &client_cipher, &server_cipher).await { + Ok(_) => {} + Err(e) => { + log::warn!("{:?}", e) + } + } + } + }); + } thread::Builder::new().name("tap_handler".into()).spawn(move || { tokio::runtime::Builder::new_current_thread() .enable_all().build().unwrap() .block_on(async move { - if let Err(e) = start_(sender, device_reader, - device_writer, igmp_server, - current_device, ip_route, ip_proxy_map, cipher).await { + if let Err(e) = start_(sender, device_reader, buf_sender).await { log::warn!("tap:{:?}",e); } worker.stop_all(); @@ -44,24 +65,23 @@ pub fn start(worker: VntWorker, sender: ChannelSender, async fn start_(sender: ChannelSender, device_reader: DeviceReader, - device_writer: DeviceWriter, - igmp_server: Option, - current_device: Arc>, - ip_route: Option, - ip_proxy_map: Option, - cipher: Cipher) -> io::Result<()> { - let mut buf = [0; 4096]; + mut buf_sender: BufSenderGroup) -> io::Result<()> { loop { - //ip拆包了会直接丢弃? + let mut buf = vec![0; 4096]; + if sender.is_close() { + return Ok(()); + } + let start = 0; let len = device_reader.read(&mut buf)?; - if let Err(e) = handle(&mut buf, len, &igmp_server, ¤t_device, &device_writer, &sender, &ip_route, &ip_proxy_map, &cipher).await { - log::warn!("tap handle{:?}",e); + if !buf_sender.send((buf, start, len)).await { + return Err(io::Error::new(io::ErrorKind::Other, "tap buf_sender发送失败")); } } } async fn handle(buf: &mut [u8], len: usize, igmp_server: &Option, current_device: &AtomicCell, - device_writer: &DeviceWriter, sender: &ChannelSender, ip_route: &Option, proxy_map: &Option, cipher: &Cipher) -> crate::Result<()> { + device_writer: &DeviceWriter, sender: &ChannelSender, ip_route: &Option, + proxy_map: &Option, client_cipher: &Cipher, server_cipher: &Cipher) -> crate::Result<()> { let mut ethernet_packet = EthernetPacket::new(&mut buf[..len])?; let current_device = current_device.load(); match ethernet_packet.protocol() { @@ -113,7 +133,7 @@ async fn handle(buf: &mut [u8], len: usize, igmp_server: &Option, cu } // 以太网帧头部14字节,预留12字节 return crate::handle::tun_tap::base_handle(sender, &mut buf[2..], len - 2, igmp_server, current_device, - ip_route, proxy_map, cipher).await; + ip_route, proxy_map, client_cipher, server_cipher).await; } _ => { // log::warn!("不支持的二层协议:{:?}",p) diff --git a/vnt/src/handle/tun_tap/tun_handler.rs b/vnt/src/handle/tun_tap/tun_handler.rs index 895e2ae..7d9b177 100644 --- a/vnt/src/handle/tun_tap/tun_handler.rs +++ b/vnt/src/handle/tun_tap/tun_handler.rs @@ -14,6 +14,7 @@ use crate::core::status::VntWorker; use crate::error::*; use crate::external_route::ExternalRoute; use crate::handle::CurrentDeviceInfo; +use crate::handle::tun_tap::channel_group::{buf_channel_group, BufSenderGroup}; use crate::igmp_server::IgmpServer; use crate::ip_proxy::IpProxyMap; use crate::tun_tap_device::{DeviceReader, DeviceWriter}; @@ -36,8 +37,10 @@ fn icmp(device_writer: &DeviceWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> /// 接收tun数据,并且转发到udp上 #[inline] -async fn handle(sender: &ChannelSender, data: &mut [u8], len: usize, device_writer: &DeviceWriter, igmp_server: &Option, current_device: CurrentDeviceInfo, - ip_route: &Option, proxy_map: &Option, cipher: &Cipher) -> Result<()> { +async fn handle(sender: &ChannelSender, data: &mut [u8], len: usize, device_writer: &DeviceWriter, + igmp_server: &Option, current_device: CurrentDeviceInfo, + ip_route: &Option, proxy_map: &Option, + client_cipher: &Cipher, server_cipher: &Cipher) -> Result<()> { let ipv4_packet = if let Ok(ipv4_packet) = IpV4Packet::new(&mut data[12..len]) { ipv4_packet } else { @@ -51,22 +54,46 @@ async fn handle(sender: &ChannelSender, data: &mut [u8], len: usize, device_writ if src_ip == dest_ip { return icmp(&device_writer, ipv4_packet); } - return crate::handle::tun_tap::base_handle(sender, data, len, igmp_server, current_device, ip_route, proxy_map, cipher).await; + return crate::handle::tun_tap::base_handle(sender, data, len, igmp_server, + current_device, ip_route, proxy_map, client_cipher, server_cipher).await; } -pub fn start(worker: VntWorker, sender: ChannelSender, - device_reader: DeviceReader, - device_writer: DeviceWriter, - igmp_server: Option, - current_device: Arc>, - ip_route: Option, - ip_proxy_map: Option, - cipher: Cipher) { +pub async fn start(worker: VntWorker, sender: ChannelSender, + device_reader: DeviceReader, + device_writer: DeviceWriter, + igmp_server: Option, + current_device: Arc>, + ip_route: Option, + ip_proxy_map: Option, + client_cipher: Cipher, server_cipher: Cipher) { + let (buf_sender, buf_receiver) = buf_channel_group(6); + for mut buf_receiver in buf_receiver.0 { + let sender = sender.clone(); + let device_writer = device_writer.clone(); + let igmp_server = igmp_server.clone(); + let current_device = current_device.clone(); + let ip_route = ip_route.clone(); + let ip_proxy_map = ip_proxy_map.clone(); + let client_cipher = client_cipher.clone(); + let server_cipher = server_cipher.clone(); + tokio::spawn(async move { + while let Some((mut buf, start, len)) = buf_receiver.recv().await { + match handle(&sender, &mut buf[start..], len, &device_writer, &igmp_server, current_device.load(), + &ip_route, &ip_proxy_map, &client_cipher, &server_cipher).await { + Ok(_) => {} + Err(e) => { + log::warn!("{:?}", e) + } + } + } + }); + } + thread::Builder::new().name("tun_handler".into()).spawn(move || { tokio::runtime::Builder::new_current_thread() .enable_all().build().unwrap() .block_on(async move { - if let Err(e) = start_(sender, device_reader, &device_writer, igmp_server, current_device, ip_route, ip_proxy_map, cipher).await { + if let Err(e) = start_(sender, device_reader, buf_sender).await { log::warn!("stop:{}",e); } let _ = device_writer.close(); @@ -75,27 +102,18 @@ pub fn start(worker: VntWorker, sender: ChannelSender, }).unwrap(); } -async fn start_(sender: ChannelSender, - device_reader: DeviceReader, - device_writer: &DeviceWriter, - igmp_server: Option, - current_device: Arc>, - ip_route: Option, - ip_proxy_map: Option, - cipher: Cipher) -> io::Result<()> { - let mut buf = [0; 4096]; +async fn start_(sender: ChannelSender, device_reader: DeviceReader, mut buf_sender: BufSenderGroup) -> io::Result<()> { loop { + let mut buf = vec![0; 4096]; if sender.is_close() { return Ok(()); } + let start = 0; let len = device_reader.read(&mut buf[12..])? + 12; #[cfg(any(target_os = "macos"))] - let mut buf = &mut buf[4..]; - match handle(&sender, &mut buf, len, device_writer, &igmp_server, current_device.load(), &ip_route, &ip_proxy_map, &cipher).await { - Ok(_) => {} - Err(e) => { - log::warn!("{:?}", e) - } + let start = 4; + if !buf_sender.send((buf, start, len)).await { + return Err(io::Error::new(io::ErrorKind::Other, "tun buf_sender发送失败")); } } } diff --git a/vnt/src/ip_proxy/icmp_proxy.rs b/vnt/src/ip_proxy/icmp_proxy.rs index df36c74..cf32767 100644 --- a/vnt/src/ip_proxy/icmp_proxy.rs +++ b/vnt/src/ip_proxy/icmp_proxy.rs @@ -11,8 +11,10 @@ use packet::icmp::icmp; use packet::icmp::icmp::HeaderOther; use packet::ip::ipv4; use crate::channel::sender::ChannelSender; +use crate::cipher::Cipher; use crate::handle::CurrentDeviceInfo; use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version}; +use crate::protocol::body::ENCRYPTION_RESERVED; pub struct IcmpProxy { icmp_socket: Arc, @@ -20,41 +22,20 @@ pub struct IcmpProxy { icmp_proxy_map: Arc>, sender: ChannelSender, current_device: Arc>, + client_cipher: Cipher, } impl IcmpProxy { - pub fn new(addr: SocketAddrV4, icmp_proxy_map: Arc>, sender: ChannelSender, current_device: Arc>) -> io::Result { + pub fn new(addr: SocketAddrV4, icmp_proxy_map: Arc>, + sender: ChannelSender, current_device: Arc>, client_cipher: Cipher) -> io::Result { let icmp_socket = Arc::new(Socket::new(Domain::IPV4, Type::RAW, Some(socket2::Protocol::ICMPV4))?); icmp_socket.bind(&SockAddr::from(addr))?; - // // 设置 SIO_RCVALL 参数 - // #[cfg(windows)] - // { - // use std::os::windows::io::AsRawSocket; - // let raw_fd = icmp_socket.as_raw_socket(); - // let mut rcvall: winapi::shared::minwindef::DWORD = 1; - // let mut bytes_returned: winapi::shared::minwindef::DWORD = 0; - // let result = unsafe { - // winapi::um::winsock2::WSAIoctl( - // raw_fd as _, - // winapi::shared::mstcpip::SIO_RCVALL, - // &mut rcvall as *mut winapi::shared::minwindef::DWORD as *mut std::ffi::c_void, - // std::mem::size_of::() as winapi::shared::minwindef::DWORD, - // std::ptr::null_mut(), - // 0, - // &mut bytes_returned as winapi::shared::minwindef::LPDWORD, - // std::ptr::null_mut(), - // None, - // ) - // }; - // if result != 0 { - // return Err(io::Error::from_raw_os_error(unsafe { winapi::um::winsock2::WSAGetLastError() })); - // } - // } Ok(IcmpProxy { icmp_socket, icmp_proxy_map, sender, current_device, + client_cipher, }) } pub fn icmp_socket(&self) -> Arc { @@ -64,11 +45,7 @@ impl IcmpProxy { let mut buf = [0 as u8; 1500]; let data: &mut [MaybeUninit] = unsafe { std::mem::transmute(&mut buf[..]) }; - let mut net_packet = NetPacket::new([0u8; 4 + 8 + 1500]).unwrap(); - net_packet.set_version(Version::V1); - net_packet.set_protocol(Protocol::IpTurn); - net_packet.set_transport_protocol(ipv4::protocol::Protocol::Icmp.into()); - net_packet.first_set_ttl(MAX_TTL); + loop { match self.recv(data) { Ok((len, peer_ip)) => { @@ -88,12 +65,20 @@ impl IcmpProxy { let current_device = self.current_device.load(); let virtual_ip = current_device.virtual_ip(); let connect_server = current_device.connect_server; + let mut net_packet = NetPacket::new_encrypt(vec![0u8; 12 + len + ENCRYPTION_RESERVED]).unwrap(); + net_packet.set_version(Version::V1); + net_packet.set_protocol(Protocol::IpTurn); + net_packet.set_transport_protocol(crate::protocol::ip_turn_packet::Protocol::Ipv4.into()); + net_packet.first_set_ttl(MAX_TTL); net_packet.set_source(virtual_ip); net_packet.set_destination(dest_ip); - let data_len = ipv4_packet.buffer.len(); - net_packet.set_payload(ipv4_packet.buffer); - if self.sender.try_send_by_id(&net_packet.buffer()[..(12 + data_len)], &dest_ip).is_err() { - let _ = self.sender.try_send_main(&net_packet.buffer()[..(12 + data_len)], connect_server); + net_packet.set_payload(ipv4_packet.buffer).unwrap(); + if let Err(e) = self.client_cipher.encrypt_ipv4(&mut net_packet) { + log::warn!("加密失败:{}",e); + continue; + } + if self.sender.try_send_by_id(net_packet.buffer(), &dest_ip).is_err() { + let _ = self.sender.try_send_main(net_packet.buffer(), connect_server); } } } diff --git a/vnt/src/ip_proxy/mod.rs b/vnt/src/ip_proxy/mod.rs index 3a4b6b1..8497272 100644 --- a/vnt/src/ip_proxy/mod.rs +++ b/vnt/src/ip_proxy/mod.rs @@ -6,6 +6,7 @@ use crossbeam_skiplist::SkipMap; use socket2::{SockAddr, Socket}; use tokio::net::{TcpListener, UdpSocket}; use crate::channel::sender::ChannelSender; +use crate::cipher::Cipher; use crate::handle::CurrentDeviceInfo; use crate::ip_proxy::icmp_proxy::IcmpProxy; use crate::ip_proxy::tcp_proxy::TcpProxy; @@ -40,7 +41,7 @@ impl IpProxyMap { } } -pub async fn init_proxy(sender: ChannelSender, current_device: Arc>) -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> { +pub async fn init_proxy(sender: ChannelSender, current_device: Arc>, client_cipher: Cipher,) -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> { let tcp_proxy_map: Arc> = Arc::new(SkipMap::new()); let udp_proxy_map: Arc> = Arc::new(SkipMap::new()); let icmp_proxy_map: Arc> = Arc::new(SkipMap::new()); @@ -51,7 +52,8 @@ pub async fn init_proxy(sender: ChannelSender, current_device: Arc>, + tcp_proxy_map: Arc>, } impl TcpProxy { - pub fn new(tcp_listener: TcpListener, map: Arc>) -> Self { + pub fn new(tcp_listener: TcpListener, tcp_proxy_map: Arc>) -> Self { Self { tcp_listener, - map, + tcp_proxy_map, } } - pub async fn start(self) { + pub async fn start(self) { let tcp_listener = self.tcp_listener; - let map = self.map; + let tcp_proxy_map = self.tcp_proxy_map; loop { match tcp_listener.accept().await { Ok((tcp_stream, sender_addr)) => { match sender_addr { SocketAddr::V4(sender_addr) => { - if let Some(entry) = map.get(&sender_addr) { + if let Some(entry) = tcp_proxy_map.get(&sender_addr) { let dest_addr = *entry.value(); let peer_tcp_stream = match TcpStream::connect(dest_addr).await { - Ok(peer_tcp_stream) => {peer_tcp_stream} + Ok(peer_tcp_stream) => { peer_tcp_stream } Err(e) => { log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,sender_addr,dest_addr); continue; } }; - let map = map.clone(); + let tcp_proxy_map = tcp_proxy_map.clone(); tokio::spawn(async move { - match proxy(tcp_stream, peer_tcp_stream).await { - Ok(_) => {} - Err(e) => { - log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,sender_addr,dest_addr); - } + if let Err(e) = proxy(tcp_stream, peer_tcp_stream).await { + log::warn!("{}->{},{}",sender_addr,dest_addr,e); } - map.remove(&sender_addr); + tcp_proxy_map.remove(&sender_addr); }); } } SocketAddr::V6(_) => {} } - } Err(e) => { log::warn!("tcp代理监听:{:?}",e); } } - } } } @@ -65,7 +61,8 @@ async fn proxy(mut client: TcpStream, mut server: TcpStream) -> io::Result<()> { let client_to_server = tokio::io::copy(&mut client_reader, &mut server_writer); let server_to_client = tokio::io::copy(&mut server_reader, &mut client_writer); - tokio::try_join!(client_to_server, server_to_client)?; - + let (r1, r2) = tokio::join!(client_to_server, server_to_client); + r1?; + r2?; Ok(()) -} \ No newline at end of file +} diff --git a/vnt/src/proto/message.rs b/vnt/src/proto/message.rs index 2827aaf..99be211 100644 --- a/vnt/src/proto/message.rs +++ b/vnt/src/proto/message.rs @@ -25,6 +25,462 @@ /// of protobuf runtime. const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_2_0; +#[derive(PartialEq,Clone,Default,Debug)] +// @@protoc_insertion_point(message:HandshakeRequest) +pub struct HandshakeRequest { + // message fields + // @@protoc_insertion_point(field:HandshakeRequest.version) + pub version: ::std::string::String, + // @@protoc_insertion_point(field:HandshakeRequest.secret) + pub secret: bool, + // special fields + // @@protoc_insertion_point(special_field:HandshakeRequest.special_fields) + pub special_fields: ::protobuf::SpecialFields, +} + +impl<'a> ::std::default::Default for &'a HandshakeRequest { + fn default() -> &'a HandshakeRequest { + ::default_instance() + } +} + +impl HandshakeRequest { + pub fn new() -> HandshakeRequest { + ::std::default::Default::default() + } + + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { + let mut fields = ::std::vec::Vec::with_capacity(2); + let mut oneofs = ::std::vec::Vec::with_capacity(0); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "version", + |m: &HandshakeRequest| { &m.version }, + |m: &mut HandshakeRequest| { &mut m.version }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "secret", + |m: &HandshakeRequest| { &m.secret }, + |m: &mut HandshakeRequest| { &mut m.secret }, + )); + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "HandshakeRequest", + fields, + oneofs, + ) + } +} + +impl ::protobuf::Message for HandshakeRequest { + const NAME: &'static str = "HandshakeRequest"; + + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { + while let Some(tag) = is.read_raw_tag_or_eof()? { + match tag { + 10 => { + self.version = is.read_string()?; + }, + 16 => { + self.secret = is.read_bool()?; + }, + tag => { + ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u64 { + let mut my_size = 0; + if !self.version.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.version); + } + if self.secret != false { + my_size += 1 + 1; + } + my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); + self.special_fields.cached_size().set(my_size as u32); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { + if !self.version.is_empty() { + os.write_string(1, &self.version)?; + } + if self.secret != false { + os.write_bool(2, self.secret)?; + } + os.write_unknown_fields(self.special_fields.unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn special_fields(&self) -> &::protobuf::SpecialFields { + &self.special_fields + } + + fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { + &mut self.special_fields + } + + fn new() -> HandshakeRequest { + HandshakeRequest::new() + } + + fn clear(&mut self) { + self.version.clear(); + self.secret = false; + self.special_fields.clear(); + } + + fn default_instance() -> &'static HandshakeRequest { + static instance: HandshakeRequest = HandshakeRequest { + version: ::std::string::String::new(), + secret: false, + special_fields: ::protobuf::SpecialFields::new(), + }; + &instance + } +} + +impl ::protobuf::MessageFull for HandshakeRequest { + fn descriptor() -> ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); + descriptor.get(|| file_descriptor().message_by_package_relative_name("HandshakeRequest").unwrap()).clone() + } +} + +impl ::std::fmt::Display for HandshakeRequest { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for HandshakeRequest { + type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; +} + +#[derive(PartialEq,Clone,Default,Debug)] +// @@protoc_insertion_point(message:HandshakeResponse) +pub struct HandshakeResponse { + // message fields + // @@protoc_insertion_point(field:HandshakeResponse.version) + pub version: ::std::string::String, + // @@protoc_insertion_point(field:HandshakeResponse.secret) + pub secret: bool, + // @@protoc_insertion_point(field:HandshakeResponse.public_key) + pub public_key: ::std::vec::Vec, + // @@protoc_insertion_point(field:HandshakeResponse.key_finger) + pub key_finger: ::std::string::String, + // special fields + // @@protoc_insertion_point(special_field:HandshakeResponse.special_fields) + pub special_fields: ::protobuf::SpecialFields, +} + +impl<'a> ::std::default::Default for &'a HandshakeResponse { + fn default() -> &'a HandshakeResponse { + ::default_instance() + } +} + +impl HandshakeResponse { + pub fn new() -> HandshakeResponse { + ::std::default::Default::default() + } + + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { + let mut fields = ::std::vec::Vec::with_capacity(4); + let mut oneofs = ::std::vec::Vec::with_capacity(0); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "version", + |m: &HandshakeResponse| { &m.version }, + |m: &mut HandshakeResponse| { &mut m.version }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "secret", + |m: &HandshakeResponse| { &m.secret }, + |m: &mut HandshakeResponse| { &mut m.secret }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "public_key", + |m: &HandshakeResponse| { &m.public_key }, + |m: &mut HandshakeResponse| { &mut m.public_key }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "key_finger", + |m: &HandshakeResponse| { &m.key_finger }, + |m: &mut HandshakeResponse| { &mut m.key_finger }, + )); + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "HandshakeResponse", + fields, + oneofs, + ) + } +} + +impl ::protobuf::Message for HandshakeResponse { + const NAME: &'static str = "HandshakeResponse"; + + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { + while let Some(tag) = is.read_raw_tag_or_eof()? { + match tag { + 10 => { + self.version = is.read_string()?; + }, + 16 => { + self.secret = is.read_bool()?; + }, + 26 => { + self.public_key = is.read_bytes()?; + }, + 34 => { + self.key_finger = is.read_string()?; + }, + tag => { + ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u64 { + let mut my_size = 0; + if !self.version.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.version); + } + if self.secret != false { + my_size += 1 + 1; + } + if !self.public_key.is_empty() { + my_size += ::protobuf::rt::bytes_size(3, &self.public_key); + } + if !self.key_finger.is_empty() { + my_size += ::protobuf::rt::string_size(4, &self.key_finger); + } + my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); + self.special_fields.cached_size().set(my_size as u32); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { + if !self.version.is_empty() { + os.write_string(1, &self.version)?; + } + if self.secret != false { + os.write_bool(2, self.secret)?; + } + if !self.public_key.is_empty() { + os.write_bytes(3, &self.public_key)?; + } + if !self.key_finger.is_empty() { + os.write_string(4, &self.key_finger)?; + } + os.write_unknown_fields(self.special_fields.unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn special_fields(&self) -> &::protobuf::SpecialFields { + &self.special_fields + } + + fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { + &mut self.special_fields + } + + fn new() -> HandshakeResponse { + HandshakeResponse::new() + } + + fn clear(&mut self) { + self.version.clear(); + self.secret = false; + self.public_key.clear(); + self.key_finger.clear(); + self.special_fields.clear(); + } + + fn default_instance() -> &'static HandshakeResponse { + static instance: HandshakeResponse = HandshakeResponse { + version: ::std::string::String::new(), + secret: false, + public_key: ::std::vec::Vec::new(), + key_finger: ::std::string::String::new(), + special_fields: ::protobuf::SpecialFields::new(), + }; + &instance + } +} + +impl ::protobuf::MessageFull for HandshakeResponse { + fn descriptor() -> ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); + descriptor.get(|| file_descriptor().message_by_package_relative_name("HandshakeResponse").unwrap()).clone() + } +} + +impl ::std::fmt::Display for HandshakeResponse { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for HandshakeResponse { + type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; +} + +#[derive(PartialEq,Clone,Default,Debug)] +// @@protoc_insertion_point(message:SecretHandshakeRequest) +pub struct SecretHandshakeRequest { + // message fields + // @@protoc_insertion_point(field:SecretHandshakeRequest.token) + pub token: ::std::string::String, + // @@protoc_insertion_point(field:SecretHandshakeRequest.key) + pub key: ::std::vec::Vec, + // special fields + // @@protoc_insertion_point(special_field:SecretHandshakeRequest.special_fields) + pub special_fields: ::protobuf::SpecialFields, +} + +impl<'a> ::std::default::Default for &'a SecretHandshakeRequest { + fn default() -> &'a SecretHandshakeRequest { + ::default_instance() + } +} + +impl SecretHandshakeRequest { + pub fn new() -> SecretHandshakeRequest { + ::std::default::Default::default() + } + + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { + let mut fields = ::std::vec::Vec::with_capacity(2); + let mut oneofs = ::std::vec::Vec::with_capacity(0); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "token", + |m: &SecretHandshakeRequest| { &m.token }, + |m: &mut SecretHandshakeRequest| { &mut m.token }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "key", + |m: &SecretHandshakeRequest| { &m.key }, + |m: &mut SecretHandshakeRequest| { &mut m.key }, + )); + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "SecretHandshakeRequest", + fields, + oneofs, + ) + } +} + +impl ::protobuf::Message for SecretHandshakeRequest { + const NAME: &'static str = "SecretHandshakeRequest"; + + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { + while let Some(tag) = is.read_raw_tag_or_eof()? { + match tag { + 10 => { + self.token = is.read_string()?; + }, + 18 => { + self.key = is.read_bytes()?; + }, + tag => { + ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u64 { + let mut my_size = 0; + if !self.token.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.token); + } + if !self.key.is_empty() { + my_size += ::protobuf::rt::bytes_size(2, &self.key); + } + my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); + self.special_fields.cached_size().set(my_size as u32); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { + if !self.token.is_empty() { + os.write_string(1, &self.token)?; + } + if !self.key.is_empty() { + os.write_bytes(2, &self.key)?; + } + os.write_unknown_fields(self.special_fields.unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn special_fields(&self) -> &::protobuf::SpecialFields { + &self.special_fields + } + + fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { + &mut self.special_fields + } + + fn new() -> SecretHandshakeRequest { + SecretHandshakeRequest::new() + } + + fn clear(&mut self) { + self.token.clear(); + self.key.clear(); + self.special_fields.clear(); + } + + fn default_instance() -> &'static SecretHandshakeRequest { + static instance: SecretHandshakeRequest = SecretHandshakeRequest { + token: ::std::string::String::new(), + key: ::std::vec::Vec::new(), + special_fields: ::protobuf::SpecialFields::new(), + }; + &instance + } +} + +impl ::protobuf::MessageFull for SecretHandshakeRequest { + fn descriptor() -> ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); + descriptor.get(|| file_descriptor().message_by_package_relative_name("SecretHandshakeRequest").unwrap()).clone() + } +} + +impl ::std::fmt::Display for SecretHandshakeRequest { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for SecretHandshakeRequest { + type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; +} + #[derive(PartialEq,Clone,Default,Debug)] // @@protoc_insertion_point(message:RegistrationRequest) pub struct RegistrationRequest { @@ -43,6 +499,8 @@ pub struct RegistrationRequest { pub virtual_ip: u32, // @@protoc_insertion_point(field:RegistrationRequest.allow_ip_change) pub allow_ip_change: bool, + // @@protoc_insertion_point(field:RegistrationRequest.client_secret) + pub client_secret: bool, // special fields // @@protoc_insertion_point(special_field:RegistrationRequest.special_fields) pub special_fields: ::protobuf::SpecialFields, @@ -60,7 +518,7 @@ impl RegistrationRequest { } fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(7); + let mut fields = ::std::vec::Vec::with_capacity(8); let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( "token", @@ -97,6 +555,11 @@ impl RegistrationRequest { |m: &RegistrationRequest| { &m.allow_ip_change }, |m: &mut RegistrationRequest| { &mut m.allow_ip_change }, )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "client_secret", + |m: &RegistrationRequest| { &m.client_secret }, + |m: &mut RegistrationRequest| { &mut m.client_secret }, + )); ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( "RegistrationRequest", fields, @@ -136,6 +599,9 @@ impl ::protobuf::Message for RegistrationRequest { 56 => { self.allow_ip_change = is.read_bool()?; }, + 64 => { + self.client_secret = is.read_bool()?; + }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; }, @@ -169,6 +635,9 @@ impl ::protobuf::Message for RegistrationRequest { if self.allow_ip_change != false { my_size += 1 + 1; } + if self.client_secret != false { + my_size += 1 + 1; + } my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); self.special_fields.cached_size().set(my_size as u32); my_size @@ -196,6 +665,9 @@ impl ::protobuf::Message for RegistrationRequest { if self.allow_ip_change != false { os.write_bool(7, self.allow_ip_change)?; } + if self.client_secret != false { + os.write_bool(8, self.client_secret)?; + } os.write_unknown_fields(self.special_fields.unknown_fields())?; ::std::result::Result::Ok(()) } @@ -220,6 +692,7 @@ impl ::protobuf::Message for RegistrationRequest { self.version.clear(); self.virtual_ip = 0; self.allow_ip_change = false; + self.client_secret = false; self.special_fields.clear(); } @@ -232,6 +705,7 @@ impl ::protobuf::Message for RegistrationRequest { version: ::std::string::String::new(), virtual_ip: 0, allow_ip_change: false, + client_secret: false, special_fields: ::protobuf::SpecialFields::new(), }; &instance @@ -514,6 +988,8 @@ pub struct DeviceInfo { pub virtual_ip: u32, // @@protoc_insertion_point(field:DeviceInfo.device_status) pub device_status: u32, + // @@protoc_insertion_point(field:DeviceInfo.client_secret) + pub client_secret: bool, // special fields // @@protoc_insertion_point(special_field:DeviceInfo.special_fields) pub special_fields: ::protobuf::SpecialFields, @@ -531,7 +1007,7 @@ impl DeviceInfo { } fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(3); + let mut fields = ::std::vec::Vec::with_capacity(4); let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( "name", @@ -548,6 +1024,11 @@ impl DeviceInfo { |m: &DeviceInfo| { &m.device_status }, |m: &mut DeviceInfo| { &mut m.device_status }, )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "client_secret", + |m: &DeviceInfo| { &m.client_secret }, + |m: &mut DeviceInfo| { &mut m.client_secret }, + )); ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( "DeviceInfo", fields, @@ -575,6 +1056,9 @@ impl ::protobuf::Message for DeviceInfo { 24 => { self.device_status = is.read_uint32()?; }, + 32 => { + self.client_secret = is.read_bool()?; + }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; }, @@ -596,6 +1080,9 @@ impl ::protobuf::Message for DeviceInfo { if self.device_status != 0 { my_size += ::protobuf::rt::uint32_size(3, self.device_status); } + if self.client_secret != false { + my_size += 1 + 1; + } my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); self.special_fields.cached_size().set(my_size as u32); my_size @@ -611,6 +1098,9 @@ impl ::protobuf::Message for DeviceInfo { if self.device_status != 0 { os.write_uint32(3, self.device_status)?; } + if self.client_secret != false { + os.write_bool(4, self.client_secret)?; + } os.write_unknown_fields(self.special_fields.unknown_fields())?; ::std::result::Result::Ok(()) } @@ -631,6 +1121,7 @@ impl ::protobuf::Message for DeviceInfo { self.name.clear(); self.virtual_ip = 0; self.device_status = 0; + self.client_secret = false; self.special_fields.clear(); } @@ -639,6 +1130,7 @@ impl ::protobuf::Message for DeviceInfo { name: ::std::string::String::new(), virtual_ip: 0, device_status: 0, + client_secret: false, special_fields: ::protobuf::SpecialFields::new(), }; &instance @@ -1107,33 +1599,41 @@ impl PunchNatType { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\rmessage.proto\"\xd6\x01\n\x13RegistrationRequest\x12\x14\n\x05token\ - \x18\x01\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\tR\ - \x08deviceId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\x07\ - is_fast\x18\x04\x20\x01(\x08R\x06isFast\x12\x18\n\x07version\x18\x05\x20\ - \x01(\tR\x07version\x12\x1d\n\nvirtual_ip\x18\x06\x20\x01(\x07R\tvirtual\ - Ip\x12&\n\x0fallow_ip_change\x18\x07\x20\x01(\x08R\rallowIpChange\"\xb3\ - \x02\n\x14RegistrationResponse\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\ - \x07R\tvirtualIp\x12'\n\x0fvirtual_gateway\x18\x02\x20\x01(\x07R\x0evirt\ - ualGateway\x12'\n\x0fvirtual_netmask\x18\x03\x20\x01(\x07R\x0evirtualNet\ - mask\x12\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05epoch\x125\n\x10device_in\ - fo_list\x18\x05\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\x12\x1b\ - \n\tpublic_ip\x18\x06\x20\x01(\x07R\x08publicIp\x12\x1f\n\x0bpublic_port\ - \x18\x07\x20\x01(\rR\npublicPort\x12\x1f\n\x0bpublic_ipv6\x18\x08\x20\ - \x01(\x0cR\npublicIpv6\"d\n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\ - \x01(\tR\x04name\x12\x1d\n\nvirtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\ - \x12#\n\rdevice_status\x18\x03\x20\x01(\rR\x0cdeviceStatus\"Y\n\nDeviceL\ - ist\x12\x14\n\x05epoch\x18\x01\x20\x01(\rR\x05epoch\x125\n\x10device_inf\ - o_list\x18\x02\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xa2\x02\ - \n\tPunchInfo\x12$\n\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIp\ - List\x12\x1f\n\x0bpublic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11\ - public_port_range\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12(\n\x08nat_t\ - ype\x18\x05\x20\x01(\x0e2\r.PunchNatTypeR\x07natType\x12\x14\n\x05reply\ - \x18\x06\x20\x01(\x08R\x05reply\x12\x19\n\x08local_ip\x18\x07\x20\x01(\ - \x07R\x07localIp\x12\x1d\n\nlocal_port\x18\x08\x20\x01(\rR\tlocalPort\ - \x12(\n\x10public_ipv6_list\x18\t\x20\x03(\x0cR\x0epublicIpv6List*'\n\ - \x0cPunchNatType\x12\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\x10\x01b\x06\ - proto3\ + \n\rmessage.proto\"D\n\x10HandshakeRequest\x12\x18\n\x07version\x18\x01\ + \x20\x01(\tR\x07version\x12\x16\n\x06secret\x18\x02\x20\x01(\x08R\x06sec\ + ret\"\x83\x01\n\x11HandshakeResponse\x12\x18\n\x07version\x18\x01\x20\ + \x01(\tR\x07version\x12\x16\n\x06secret\x18\x02\x20\x01(\x08R\x06secret\ + \x12\x1d\n\npublic_key\x18\x03\x20\x01(\x0cR\tpublicKey\x12\x1d\n\nkey_f\ + inger\x18\x04\x20\x01(\tR\tkeyFinger\"@\n\x16SecretHandshakeRequest\x12\ + \x14\n\x05token\x18\x01\x20\x01(\tR\x05token\x12\x10\n\x03key\x18\x02\ + \x20\x01(\x0cR\x03key\"\xfb\x01\n\x13RegistrationRequest\x12\x14\n\x05to\ + ken\x18\x01\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\t\ + R\x08deviceId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\ + \x07is_fast\x18\x04\x20\x01(\x08R\x06isFast\x12\x18\n\x07version\x18\x05\ + \x20\x01(\tR\x07version\x12\x1d\n\nvirtual_ip\x18\x06\x20\x01(\x07R\tvir\ + tualIp\x12&\n\x0fallow_ip_change\x18\x07\x20\x01(\x08R\rallowIpChange\ + \x12#\n\rclient_secret\x18\x08\x20\x01(\x08R\x0cclientSecret\"\xb3\x02\n\ + \x14RegistrationResponse\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tvi\ + rtualIp\x12'\n\x0fvirtual_gateway\x18\x02\x20\x01(\x07R\x0evirtualGatewa\ + y\x12'\n\x0fvirtual_netmask\x18\x03\x20\x01(\x07R\x0evirtualNetmask\x12\ + \x14\n\x05epoch\x18\x04\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\ + \x18\x05\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\x12\x1b\n\tpubl\ + ic_ip\x18\x06\x20\x01(\x07R\x08publicIp\x12\x1f\n\x0bpublic_port\x18\x07\ + \x20\x01(\rR\npublicPort\x12\x1f\n\x0bpublic_ipv6\x18\x08\x20\x01(\x0cR\ + \npublicIpv6\"\x89\x01\n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\x01(\ + \tR\x04name\x12\x1d\n\nvirtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\x12#\ + \n\rdevice_status\x18\x03\x20\x01(\rR\x0cdeviceStatus\x12#\n\rclient_sec\ + ret\x18\x04\x20\x01(\x08R\x0cclientSecret\"Y\n\nDeviceList\x12\x14\n\x05\ + epoch\x18\x01\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x02\ + \x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xa2\x02\n\tPunchInfo\ + \x12$\n\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIpList\x12\x1f\ + \n\x0bpublic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11public_port_\ + range\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12(\n\x08nat_type\x18\x05\ + \x20\x01(\x0e2\r.PunchNatTypeR\x07natType\x12\x14\n\x05reply\x18\x06\x20\ + \x01(\x08R\x05reply\x12\x19\n\x08local_ip\x18\x07\x20\x01(\x07R\x07local\ + Ip\x12\x1d\n\nlocal_port\x18\x08\x20\x01(\rR\tlocalPort\x12(\n\x10public\ + _ipv6_list\x18\t\x20\x03(\x0cR\x0epublicIpv6List*'\n\x0cPunchNatType\x12\ + \r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\x10\x01b\x06proto3\ "; /// `FileDescriptorProto` object which was a source for this generated file @@ -1151,7 +1651,10 @@ pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor { file_descriptor.get(|| { let generated_file_descriptor = generated_file_descriptor_lazy.get(|| { let mut deps = ::std::vec::Vec::with_capacity(0); - let mut messages = ::std::vec::Vec::with_capacity(5); + let mut messages = ::std::vec::Vec::with_capacity(8); + messages.push(HandshakeRequest::generated_message_descriptor_data()); + messages.push(HandshakeResponse::generated_message_descriptor_data()); + messages.push(SecretHandshakeRequest::generated_message_descriptor_data()); messages.push(RegistrationRequest::generated_message_descriptor_data()); messages.push(RegistrationResponse::generated_message_descriptor_data()); messages.push(DeviceInfo::generated_message_descriptor_data()); diff --git a/vnt/src/protocol/body.rs b/vnt/src/protocol/body.rs new file mode 100644 index 0000000..215bdb7 --- /dev/null +++ b/vnt/src/protocol/body.rs @@ -0,0 +1,205 @@ +use std::{fmt, io}; + +pub const ENCRYPTION_RESERVED: usize = 32; +/* aes_gcm加密数据体 + 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) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | tag(32) | + | tag(32) | + | tag(32) | + | tag(32) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | finger(32) | + | finger(32) | + | finger(32) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + 注:finger用于快速校验数据是否被修改,上层可使用token、协议头参与计算finger, + 确保服务端和客户端都能感知修改(服务端不能解密也能校验指纹) + */ +pub struct SecretBody { + buffer: B, +} + +impl> SecretBody { + pub fn new(buffer: B) -> io::Result> { + let len = buffer.as_ref().len(); + // 不能大于udp最大载荷长度 + if len < 32 || len > 65535 - 20 - 8 - 12 { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "length overflow", + )); + } + Ok(SecretBody { buffer }) + } + pub fn data(&self) -> &[u8] { + let end = self.buffer.as_ref().len() - 32; + &self.buffer.as_ref()[..end] + } + pub fn random(&self) -> u32 { + let end = self.buffer.as_ref().len() - 16 - 12; + u32::from_be_bytes(self.buffer.as_ref()[end - 4..end].try_into().unwrap()) + } + pub fn body(&self) -> &[u8] { + let end = self.buffer.as_ref().len() - 16 - 12; + &self.buffer.as_ref()[..end] + } + pub fn tag(&self) -> &[u8] { + let end = self.buffer.as_ref().len() - 12; + &self.buffer.as_ref()[end - 16..end] + } + pub fn finger(&self) -> &[u8] { + let end = self.buffer.as_ref().len(); + &self.buffer.as_ref()[end - 12..end] + } + pub fn buffer(&self) -> &[u8] { + self.buffer.as_ref() + } +} + +impl + AsMut<[u8]>> SecretBody { + pub fn set_data(&mut self, data: &[u8]) -> io::Result<()> { + let end = self.buffer.as_ref().len() - 32; + if end - 4 != data.len() { + return Err(io::Error::new(io::ErrorKind::InvalidData, "end-4 != data.len")); + } + self.buffer.as_mut()[..end].copy_from_slice(data); + Ok(()) + } + pub fn set_random(&mut self, random: u32) { + let end = self.buffer.as_ref().len() - 16 - 12; + self.buffer.as_mut()[end - 4..end].copy_from_slice(&random.to_be_bytes()); + } + + pub fn set_tag(&mut self, tag: &[u8]) -> io::Result<()> { + if tag.len() != 16 { + return Err(io::Error::new(io::ErrorKind::InvalidData, "tag.len != 16")); + } + let end = self.buffer.as_ref().len() - 12; + self.buffer.as_mut()[end - 16..end].copy_from_slice(tag); + Ok(()) + } + 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 data_mut(&mut self) -> &mut [u8] { + let end = self.buffer.as_ref().len() - 32; + &mut self.buffer.as_mut()[..end] + } + /// 数据部分 + pub fn body_mut(&mut self) -> &mut [u8] { + let end = self.buffer.as_ref().len() - 12 - 16; + &mut self.buffer.as_mut()[..end] + } + pub fn tag_mut(&mut self) -> &mut [u8] { + let end = self.buffer.as_ref().len() - 12; + &mut self.buffer.as_mut()[end - 16..end] + } + /// 数据部分+tag部分 + pub fn en_body_mut(&mut self) -> &mut [u8] { + let end = self.buffer.as_ref().len() - 12; + &mut self.buffer.as_mut()[..end] + } + pub fn buffer_mut(&mut self) -> &mut [u8] { + self.buffer.as_mut() + } +} + +impl> fmt::Debug for SecretBody { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SecretBody") + .field("random", &self.random()) + .field("body", &self.body()) + .field("tag", &self.tag()) + .finish() + } +} + +/* rsa加密数据体 + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 数据体(n) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | random(32) | + | random(32) | + | random(32) | + | random(32) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | finger(32) | + | finger(32) | + | finger(32) | + | finger(32) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +pub struct RsaSecretBody { + buffer: B, +} + +impl> RsaSecretBody { + pub fn new(buffer: B) -> io::Result> { + let len = buffer.as_ref().len(); + // 不能大于udp最大载荷长度 + if len < 32 || len > 65535 - 20 - 8 - 12 { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "length overflow", + )); + } + Ok(RsaSecretBody { buffer }) + } + pub fn data(&self) -> &[u8] { + let end = self.buffer.as_ref().len() - 32; + &self.buffer.as_ref()[..end] + } + pub fn random(&self) -> &[u8] { + let end = self.buffer.as_ref().len() - 16; + &self.buffer.as_ref()[end - 16..end] + } + pub fn body(&self) -> &[u8] { + let end = self.buffer.as_ref().len() - 16; + &self.buffer.as_ref()[..end] + } + pub fn finger(&self) -> &[u8] { + let end = self.buffer.as_ref().len() - 16; + &self.buffer.as_ref()[end..] + } + pub fn buffer(&self) -> &[u8] { + &self.buffer.as_ref() + } +} + +impl + AsMut<[u8]>> RsaSecretBody { + pub fn set_random(&mut self, random: &[u8]) -> io::Result<()> { + if random.len() != 16 { + return Err(io::Error::new(io::ErrorKind::InvalidData, "random.len != 16")); + } + let end = self.buffer.as_ref().len() - 16; + self.buffer.as_mut()[end - 16..end].copy_from_slice(random); + Ok(()) + } + pub fn random_mut(&mut self) -> &mut [u8] { + let end = self.buffer.as_ref().len() - 16; + &mut self.buffer.as_mut()[end - 16..end] + } + pub fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> { + if finger.len() != 16 { + return Err(io::Error::new(io::ErrorKind::InvalidData, "finger.len != 16")); + } + let end = self.buffer.as_ref().len(); + self.buffer.as_mut()[end - 16..end].copy_from_slice(finger); + Ok(()) + } +} \ No newline at end of file diff --git a/vnt/src/protocol/error_packet.rs b/vnt/src/protocol/error_packet.rs index 45be4bc..64971a0 100644 --- a/vnt/src/protocol/error_packet.rs +++ b/vnt/src/protocol/error_packet.rs @@ -7,6 +7,7 @@ pub enum Protocol { AddressExhausted, IpAlreadyExists, InvalidIp, + NoKey, Other(u8), } @@ -18,6 +19,7 @@ impl From for Protocol { 3 => Self::AddressExhausted, 4 => Self::IpAlreadyExists, 5 => Self::InvalidIp, + 6 => Self::NoKey, val => Self::Other(val), } } @@ -31,6 +33,7 @@ impl Into for Protocol { Protocol::AddressExhausted => 3, Protocol::IpAlreadyExists => 4, Protocol::InvalidIp => 5, + Protocol::NoKey => 6, Protocol::Other(val) => val, } } @@ -42,6 +45,7 @@ pub enum InErrorPacket { AddressExhausted, IpAlreadyExists, InvalidIp, + NoKey, OtherError(ErrorPacket), } @@ -53,6 +57,7 @@ impl> InErrorPacket { Protocol::AddressExhausted => Ok(InErrorPacket::AddressExhausted), Protocol::IpAlreadyExists => Ok(InErrorPacket::IpAlreadyExists), Protocol::InvalidIp => Ok(InErrorPacket::InvalidIp), + Protocol::NoKey => Ok(InErrorPacket::NoKey), Protocol::Other(_) => Ok(InErrorPacket::OtherError(ErrorPacket::new(buffer)?)), } } diff --git a/vnt/src/protocol/ip_turn_packet.rs b/vnt/src/protocol/ip_turn_packet.rs index c2c5a86..667a44f 100644 --- a/vnt/src/protocol/ip_turn_packet.rs +++ b/vnt/src/protocol/ip_turn_packet.rs @@ -3,8 +3,6 @@ use std::net::Ipv4Addr; #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum Protocol { - Icmp, - Igmp, Ipv4, Ipv4Broadcast, Unknown(u8), @@ -13,8 +11,6 @@ pub enum Protocol { impl From for Protocol { fn from(value: u8) -> Self { match value { - 1 => Protocol::Icmp, - 2 => Protocol::Igmp, 4 => Protocol::Ipv4, 201 => Protocol::Ipv4Broadcast, val => Protocol::Unknown(val), @@ -25,8 +21,6 @@ impl From for Protocol { impl Into for Protocol { fn into(self) -> u8 { match self { - Protocol::Icmp => 1, - Protocol::Igmp => 2, Protocol::Ipv4 => 4, Protocol::Ipv4Broadcast => 201, Protocol::Unknown(val) => val, @@ -34,18 +28,18 @@ impl Into for Protocol { } } -pub struct BroadcastPacketEnd { +pub struct BroadcastPacket { buffer: B, } -impl> BroadcastPacketEnd { +impl> BroadcastPacket { pub fn unchecked(buffer: B) -> Self { Self { buffer } } pub fn new(buffer: B) -> io::Result { let len = buffer.as_ref().len(); let packet = Self::unchecked(buffer); - if len < 1 || packet.len() != len { + if len < 2 + 4 || packet.addr_num() == 0 { Err(io::Error::new( io::ErrorKind::InvalidData, "InvalidData", @@ -56,31 +50,36 @@ impl> BroadcastPacketEnd { } } -impl> BroadcastPacketEnd { - pub fn len(&self) -> usize { - 1 + self.num() as usize * 4 - } - pub fn num(&self) -> u8 { - let len = self.buffer.as_ref().len(); - self.buffer.as_ref()[len - 1] +impl> BroadcastPacket { + pub fn addr_num(&self) -> u8 { + self.buffer.as_ref()[1] } /// 已经发送给了这些地址 - /// 从尾往头拿 pub fn addresses(&self) -> Vec { - let num = self.num() as usize; + let num = self.addr_num() as usize; let mut list = Vec::with_capacity(num); let buf = self.buffer.as_ref(); - let mut offset = buf.len() + 4 - 2; + let mut offset = 1; for _ in 0..num { - offset -= 4; - list.push(Ipv4Addr::new(buf[offset - 3], buf[offset - 2], buf[offset - 1], buf[offset])); + list.push(Ipv4Addr::new(buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3])); + offset += 4; } list } + pub fn data(&self) -> io::Result<&[u8]> { + let start = 1 + self.addr_num() as usize * 4; + if start > self.buffer.as_ref().len() { + Err(io::Error::new( + io::ErrorKind::InvalidData, + "InvalidData", + )) + } else { + Ok(&self.buffer.as_ref()[start..]) + } + } } -impl + AsMut<[u8]>> BroadcastPacketEnd { - /// 从头往尾放 +impl + AsMut<[u8]>> BroadcastPacket { pub fn set_address(&mut self, addr: &[Ipv4Addr]) -> io::Result<()> { let buf = self.buffer.as_mut(); if buf.len() < 1 + addr.len() * 4 || addr.len() > u8::MAX as usize { @@ -89,15 +88,28 @@ impl + AsMut<[u8]>> BroadcastPacketEnd { "InvalidData", )) } else { - let mut offset = 0; + buf[0] = addr.len() as u8; + let mut offset = 1; for ip in addr { buf[offset..offset + 4].copy_from_slice(&ip.octets()); offset += 4; } - self.buffer.as_mut()[offset] = addr.len() as u8; Ok(()) } } + pub fn set_data(&mut self, data: &[u8]) -> io::Result<()> { + let num = self.addr_num() as usize; + let start = 1 + 4 * num; + let buf = self.buffer.as_mut(); + if start > buf.len() || start + data.len() != buf.len() { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "InvalidData", + )); + } + buf[start..].copy_from_slice(data); + Ok(()) + } } diff --git a/vnt/src/protocol/mod.rs b/vnt/src/protocol/mod.rs index 96f4a7a..e6afa7d 100644 --- a/vnt/src/protocol/mod.rs +++ b/vnt/src/protocol/mod.rs @@ -1,11 +1,12 @@ -use std::net::Ipv4Addr; use std::{fmt, io}; +use std::net::Ipv4Addr; +use crate::protocol::body::ENCRYPTION_RESERVED; /* 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | p|unused| 版本(4) | 协议(8) | 上层协议(8) | 初始ttl(4) | 生存时间(4) | + |e|s|unused| 版本(4) | 协议(8) | 上层协议(8) | 初始ttl(4) | 生存时间(4) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 源ip地址(32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -13,8 +14,11 @@ use std::{fmt, io}; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 数据体 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 注:e为是否加密标志,s为服务端通信包标志 */ + +pub mod body; pub mod control_packet; pub mod error_packet; pub mod service_packet; @@ -91,33 +95,68 @@ pub const MAX_SOURCE: u8 = 0b11110000; #[derive(Copy, Clone)] pub struct NetPacket { + data_len: usize, buffer: B, } impl> NetPacket { pub fn new(buffer: B) -> io::Result> { - let len = buffer.as_ref().len(); - // 不能大于udp最大载荷长度 - if len < 12 || len > 65535 - 20 - 8 { + let data_len = buffer.as_ref().len(); + Self::new0(data_len, buffer) + } + pub fn new_encrypt(buffer: B) -> io::Result> { + if 12 + ENCRYPTION_RESERVED > buffer.as_ref().len() { return Err(io::Error::new( io::ErrorKind::InvalidData, "length overflow", )); } - Ok(NetPacket { buffer }) + //加密需要预留32字节 + let data_len = buffer.as_ref().len() - ENCRYPTION_RESERVED; + Self::new0(data_len, buffer) + } + pub fn new0(data_len: usize, buffer: B) -> io::Result> { + if data_len > buffer.as_ref().len() { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "length overflow", + )); + } + // 不能大于udp最大载荷长度 + if data_len < 12 || buffer.as_ref().len() > 65535 - 20 - 8 { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "length overflow", + )); + } + Ok(NetPacket { data_len, buffer }) } pub fn buffer(&self) -> &[u8] { + &self.buffer.as_ref()[..self.data_len] + } + pub fn raw_buffer(&self) -> &[u8] { self.buffer.as_ref() } + pub fn data_len(&self) -> usize { + self.data_len + } + pub fn reserve(&self) -> usize { + self.buffer.as_ref().len() - self.data_len + } pub fn into_buffer(self) -> B { self.buffer } } impl> NetPacket { + /// 数据加密 pub fn is_encrypt(&self) -> bool { self.buffer.as_ref()[0] & 0x80 == 0x80 } + /// 网关通信的标识 + pub fn is_gateway(&self) -> bool { + self.buffer.as_ref()[0] & 0x50 == 0x50 + } pub fn version(&self) -> Version { Version::from(self.buffer.as_ref()[0] & 0x0F) } @@ -142,7 +181,7 @@ impl> NetPacket { Ipv4Addr::from(tmp) } pub fn payload(&self) -> &[u8] { - &self.buffer.as_ref()[12..] + &self.buffer.as_ref()[12..self.data_len] } } @@ -157,6 +196,13 @@ impl + AsMut<[u8]>> NetPacket { self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0x7F }; } + pub fn set_gateway_flag(&mut self, is_gateway: bool) { + if is_gateway { + self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x50 + } else { + self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF + }; + } pub fn set_version(&mut self, version: Version) { let v: u8 = version.into(); self.buffer.as_mut()[0] = (self.buffer.as_ref()[0] & 0xF0) | (0x0F & v); @@ -182,11 +228,22 @@ impl + AsMut<[u8]>> NetPacket { pub fn set_destination(&mut self, destination: Ipv4Addr) { self.buffer.as_mut()[8..12].copy_from_slice(&destination.octets()); } - pub fn set_payload(&mut self, payload: &[u8]) { - self.buffer.as_mut()[12..payload.len() + 12].copy_from_slice(payload); + pub fn set_payload(&mut self, payload: &[u8]) -> io::Result<()> { + if self.data_len - 12 != payload.len() { + return Err(io::Error::new(io::ErrorKind::InvalidData, "data_len - 12 != payload.len")); + } + self.buffer.as_mut()[12..self.data_len].copy_from_slice(payload); + Ok(()) } pub fn payload_mut(&mut self) -> &mut [u8] { - &mut self.buffer.as_mut()[12..] + &mut self.buffer.as_mut()[12..self.data_len] + } + pub fn set_data_len(&mut self, data_len: usize) -> io::Result<()> { + if data_len > self.buffer.as_ref().len() || data_len < 12 { + return Err(io::Error::new(io::ErrorKind::InvalidData, "data_len invalid")); + } + self.data_len = data_len; + Ok(()) } } @@ -194,6 +251,8 @@ impl> fmt::Debug for NetPacket { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("NetPacket") .field("version", &self.version()) + .field("gateway", &self.is_gateway()) + .field("encrypt", &self.is_encrypt()) .field("protocol", &self.protocol()) .field("transport_protocol", &self.transport_protocol()) .field("ttl", &self.ttl()) diff --git a/vnt/src/protocol/service_packet.rs b/vnt/src/protocol/service_packet.rs index d17a149..0b34699 100644 --- a/vnt/src/protocol/service_packet.rs +++ b/vnt/src/protocol/service_packet.rs @@ -8,6 +8,11 @@ pub enum Protocol { PollDeviceList, /// 推送设备列表 PushDeviceList, + /// 和服务端握手 + HandshakeRequest, + HandshakeResponse, + SecretHandshakeRequest, + SecretHandshakeResponse, Unknown(u8), } @@ -18,6 +23,10 @@ impl From for Protocol { 2 => Self::RegistrationResponse, 3 => Self::PollDeviceList, 4 => Self::PushDeviceList, + 5 => Self::HandshakeRequest, + 6 => Self::HandshakeResponse, + 7 => Self::SecretHandshakeRequest, + 8 => Self::SecretHandshakeResponse, val => Self::Unknown(val), } } @@ -30,6 +39,10 @@ impl Into for Protocol { Self::RegistrationResponse => 2, Self::PollDeviceList => 3, Self::PushDeviceList => 4, + Self::HandshakeRequest => 5, + Self::HandshakeResponse => 6, + Self::SecretHandshakeRequest => 7, + Self::SecretHandshakeResponse => 8, Self::Unknown(val) => val, } } diff --git a/vnt/src/tun_tap_device/linux.rs b/vnt/src/tun_tap_device/linux.rs index de319b8..c0bdd6e 100644 --- a/vnt/src/tun_tap_device/linux.rs +++ b/vnt/src/tun_tap_device/linux.rs @@ -11,10 +11,14 @@ impl DeviceWriter { pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> { let mut config = tun::Configuration::default(); + let broadcast_address = (!u32::from_be_bytes(netmask.octets())) + | u32::from_be_bytes(gateway.octets()); + let broadcast_address = Ipv4Addr::from(broadcast_address); config .destination(gateway) .address(address) .netmask(netmask) + .broadcast(broadcast_address) // .queues(2) .up(); let mut dev = self.lock.lock(); @@ -58,12 +62,15 @@ pub fn create_device(device_type: DeviceType, mtu: u16, ) -> io::Result<(DeviceWriter, DeviceReader,DriverInfo)> { let mut config = tun::Configuration::default(); - + let broadcast_address = (!u32::from_be_bytes(netmask.octets())) + | u32::from_be_bytes(gateway.octets()); + let broadcast_address = Ipv4Addr::from(broadcast_address); config .destination(gateway) .address(address) .netmask(netmask) .mtu(mtu.into()) + .broadcast(broadcast_address) // .queues(2) 用多个队列有兼容性问题 .up(); match device_type {