Compare commits

...
48 Commits
Author SHA1 Message Date
lubeilin d0b0c61a03 Merge remote-tracking branch 'origin/main' 2023-09-28 10:27:10 +08:00
lubeilin b0501db4e5 修改features说明 2023-09-28 10:26:38 +08:00
lubeilin 465a5c75ae 修改默认features 2023-09-28 10:05:52 +08:00
lbl8603 978460aca8 更新 README.md 2023-09-27 23:51:52 +08:00
lubeilin 4b86752c79 去除不必要的features 2023-09-27 19:59:50 +08:00
lubeilin bd61cad7b6 加密算法可选 2023-09-27 19:51:23 +08:00
lubeilin 40cbd2e26b 更新参数说明 2023-09-26 21:56:04 +08:00
lubeilin 2cab580b4e 更新版本 2023-09-26 21:53:55 +08:00
lubeilin 3d243fb01d 支持读取配置文件和自定义端口 2023-09-26 21:53:41 +08:00
lubeilin ca4e8d14f0 支持sm4-cbc加密 2023-09-26 21:53:07 +08:00
lubeilin 9c098c55c9 调整长度判断 2023-09-26 21:51:56 +08:00
lubeilin 707b07b8d3 ipv6改为完整地址 2023-09-24 15:42:19 +08:00
lubeilin de5a6971f0 更新读取时间不需要再插入 2023-09-24 14:58:03 +08:00
lubeilin 056036c4d2 减少注册和探测nat的频率 2023-09-24 14:53:37 +08:00
lubeilin 1cfb188845 去除多余依赖 2023-09-24 13:45:47 +08:00
lubeilin 73a2c31854 连接通过关闭同时关闭tap 2023-09-24 13:42:09 +08:00
lubeilin 92eea536f8 删除多余依赖 2023-09-24 12:57:49 +08:00
lubeilin 00936a923e 避免直接关闭网卡 2023-09-24 12:55:42 +08:00
lubeilin ba69ba78af 增加线程名称 2023-09-23 23:09:37 +08:00
lubeilin 17b206bace 1.2.4.3 2023-09-23 21:38:31 +08:00
lubeilin 58d5a4f5da 增加wintun日志 2023-09-23 21:38:20 +08:00
lubeilin 2438d14175 避免短时间重复上传服务端密钥 2023-09-23 21:33:00 +08:00
lubeilin 99f8526799 去除tap广播路由 2023-09-22 22:49:05 +08:00
lubeilin 56fcbd64ed 增加日志 2023-09-22 22:43:23 +08:00
lubeilin 3766b2b7c1 修改命令超时时间 2023-09-22 22:43:02 +08:00
lubeilin baf0698fe4 去除广播路由 2023-09-22 22:17:13 +08:00
lubeilin 301938b9fc 增加小版本 2023-09-22 18:19:13 +08:00
lubeilin 16a37c713a 增加日志 2023-09-22 18:18:29 +08:00
lubeilin d412a769dd fmt 2023-09-22 18:18:10 +08:00
lubeilin c8eecc87fd 调整心跳间隔,服务端和客户端心跳分离 2023-09-22 18:17:12 +08:00
lubeilin 6a11db70c8 调整代理超时时间 2023-09-22 18:16:06 +08:00
lubeilin d7c121a756 commit:
1.去除缓冲池
2.数据处理改为同步方法
3.fmt
2023-09-20 19:54:49 +08:00
lubeilin 3429ee8bd6 增加提示 2023-09-20 16:03:25 +08:00
lubeilin 4422f9f8b7 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	vnt/src/ip_proxy/tcp_proxy.rs
2023-09-20 15:39:54 +08:00
lubeilin 57ed454c93 修复内网ip断线问题 2023-09-20 11:11:31 +08:00
lubeilin 236205c0f3 修复内网ip断线问题 2023-09-19 18:25:14 +08:00
lubeilin 99b4bf0041 Merge remote-tracking branch 'origin/main' 2023-09-18 21:51:17 +08:00
lubeilin 9495e39700 优化nat校验 2023-09-18 21:51:08 +08:00
lbl8603 75e244e3a8 Update README.md 2023-09-18 11:17:21 +08:00
lubeilin bf8397e6e3 修复代理不正常关闭的问题 2023-09-17 20:28:59 +08:00
lubeilin 8cee974866 Merge remote-tracking branch 'origin/main' 2023-09-17 19:53:06 +08:00
lubeilin 5e018801db 增加代理超时时间 2023-09-17 19:52:54 +08:00
lbl8603 c4f7f4c19e Update README.md 2023-09-17 17:14:42 +08:00
lubeilin 29945eb3da 1.2.3
1.同步处理UDP,提升性能
2.加密引入openssl,提升性能
3.安卓支持ip代理
2023-09-17 12:54:15 +08:00
lubeilin 7db415d243 Merge remote-tracking branch 'origin/main' 2023-09-12 23:34:08 +08:00
lubeilin 808dcec795 Merge branch 'dev' 2023-09-12 23:28:49 +08:00
lbl8603 f4dda173c2 Update README.md 2023-08-30 22:31:20 +08:00
lubeilin 84e70149a1 增加参数说明 2023-08-29 22:02:55 +08:00
52 changed files with 2372 additions and 1123 deletions
+63 -49
View File
@@ -37,49 +37,41 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
# a list of all the targets # a list of all the targets
# 选择使用openssl或者ring,并不是所有平台都支持
include: include:
- TARGET: i686-unknown-linux-musl # test in an alpine container on a mac - TARGET: i686-unknown-linux-musl # test in an alpine container on a mac
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: normal FEATURES: default
- TARGET: x86_64-unknown-linux-gnu # tested in a debian container on a mac
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: x86_64-unknown-linux-musl # test in an alpine container on a mac - TARGET: x86_64-unknown-linux-musl # test in an alpine container on a mac
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: ring-cipher FEATURES: ring-cipher,openssl-vendored
- TARGET: aarch64-unknown-linux-gnu # tested on aws t4g.nano
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: aarch64-unknown-linux-musl # tested on aws t4g.nano in alpine container - TARGET: aarch64-unknown-linux-musl # tested on aws t4g.nano in alpine container
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: normal FEATURES: default
- TARGET: armv7-unknown-linux-gnueabihf # raspberry pi 2-3-4, not tested
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested - TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: normal FEATURES: openssl-vendored
- TARGET: arm-unknown-linux-gnueabihf # raspberry pi 0-1, not tested
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested - TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: normal FEATURES: openssl-vendored
- TARGET: x86_64-apple-darwin # tested on a mac, is not properly signed so there are security warnings - TARGET: x86_64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
OS: macos-latest OS: macos-latest
FEATURES: ring-cipher FEATURES: ring-cipher,openssl-vendored
- TARGET: aarch64-apple-darwin # tested on a mac, is not properly signed so there are security warnings - TARGET: aarch64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
OS: macos-latest OS: macos-latest
FEATURES: ring-cipher FEATURES: ring-cipher,openssl-vendored
- TARGET: i686-pc-windows-msvc # tested on a windows machine - TARGET: i686-pc-windows-msvc # tested on a windows machine
OS: windows-latest OS: windows-2019
FEATURES: ring-cipher FEATURES: ring-cipher,openssl-vendored
- TARGET: x86_64-pc-windows-msvc # tested on a windows machine - TARGET: x86_64-pc-windows-msvc # tested on a windows machine
OS: windows-latest OS: windows-latest
FEATURES: ring-cipher FEATURES: ring-cipher,openssl-vendored
- TARGET: mipsel-unknown-linux-musl # openwrt - TARGET: mipsel-unknown-linux-musl # openwrt
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: normal FEATURES: openssl-vendored
- TARGET: mips-unknown-linux-musl # openwrt
OS: ubuntu-latest
FEATURES: openssl-vendored
# needs: test # needs: test
runs-on: ${{ matrix.OS }} runs-on: ${{ matrix.OS }}
env: env:
@@ -98,6 +90,9 @@ jobs:
~/.cargo/registry ~/.cargo/registry
./target ./target
key: build-cargo-registry-${{matrix.TARGET}} key: build-cargo-registry-${{matrix.TARGET}}
- name: Use strawberry perl
if: startsWith(matrix.os, 'windows')
run: echo OPENSSL_SRC_PERL=C:/Strawberry/perl/bin/perl >> $GITHUB_ENV
- name: List - name: List
run: find ./ run: find ./
- name: Install and configure dependencies - name: Install and configure dependencies
@@ -105,45 +100,64 @@ jobs:
# dependencies are only needed on ubuntu as that's the only place where # dependencies are only needed on ubuntu as that's the only place where
# we make cross-compilation # we make cross-compilation
if [[ $OS =~ ^ubuntu.*$ ]]; then if [[ $OS =~ ^ubuntu.*$ ]]; then
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools gcc-mipsel-linux-gnu sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools
# curl -s musl.cc | grep mipsel
case $TARGET in
mipsel-unknown-linux-musl)
MUSL_URI=mipsel-linux-musl-cross
;;
aarch64-unknown-linux-musl)
MUSL_URI=aarch64-linux-musl-cross
;;
armv7-unknown-linux-musleabihf)
MUSL_URI=armv7l-linux-musleabihf-cross
;;
arm-unknown-linux-musleabihf)
MUSL_URI=arm-linux-musleabihf-cross
;;
mips-unknown-linux-musl)
MUSL_URI=mips-linux-musl-cross
;;
esac
if [ -n "$MUSL_URI" ]; then
mkdir -p ./musl_gcc
wget -c https://musl.cc/$MUSL_URI.tgz -P ./musl_gcc/
tar zxf ./musl_gcc/$MUSL_URI.tgz -C ./musl_gcc/
sudo ln -s $(pwd)/musl_gcc/$MUSL_URI/bin/*gcc /usr/bin/
fi
fi fi
# some additional configuration for cross-compilation on linux # some additional configuration for cross-compilation on linux
cat >>~/.cargo/config <<EOF cat >>~/.cargo/config <<EOF
[target.x86_64-unknown-linux-musl] [target.x86_64-unknown-linux-musl]
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"] rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
[target.aarch64-unknown-linux-musl] [target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-gnu-gcc" linker = "aarch64-linux-musl-gcc"
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"] rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
[target.armv7-unknown-linux-musleabihf] [target.armv7-unknown-linux-musleabihf]
linker = "arm-linux-gnueabihf-gcc" linker = "armv7l-linux-musleabihf-gcc"
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"] rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
[target.arm-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
[target.arm-unknown-linux-musleabihf] [target.arm-unknown-linux-musleabihf]
linker = "arm-linux-gnueabihf-gcc" linker = "arm-linux-musleabihf-gcc"
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"] rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
[target.mipsel-unknown-linux-musl] [target.mipsel-unknown-linux-musl]
linker = "mipsel-linux-gnu-gcc" linker = "mipsel-linux-musl-gcc"
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"] rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
[target.mips-unknown-linux-musl]
linker = "mips-linux-musl-gcc"
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
[target.x86_64-pc-windows-msvc] [target.x86_64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"] rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
[target.i686-pc-windows-msvc] [target.i686-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"] rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
[target.x86_64-apple-darwin] [target.x86_64-apple-darwin]
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"] rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
[target.aarch64-apple-darwin] [target.aarch64-apple-darwin]
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"] rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
[target.i686-unknown-linux-musl] [target.i686-unknown-linux-musl]
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"] rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
EOF EOF
- name: Install rust target - name: Install rust target
run: rustup target add $TARGET run: rustup target add $TARGET
+39 -6
View File
@@ -3,7 +3,9 @@
A virtual network tool (VPN) A virtual network tool (VPN)
将不同网络下的多个设备虚拟到一个局域网下 将不同网络下的多个设备虚拟到一个局域网下
### vnt-cli参数详解 [参数说明](https://github.com/lbl8603/vnt/blob/main/vnt-cli/README.md) ### vnt-cli参数详解 [参数说明](https://github.com/lbl8603/vnt/blob/main/vnt-cli/README.md)
### 快速使用: ### 快速使用:
1. 指定一个token,在多台设备上运行该程序,例如: 1. 指定一个token,在多台设备上运行该程序,例如:
@@ -61,17 +63,36 @@ A virtual network tool (VPN)
前提条件:安装rust编译环境([install rust](https://www.rust-lang.org/zh-CN/tools/install)) 前提条件:安装rust编译环境([install rust](https://www.rust-lang.org/zh-CN/tools/install))
```
到项目根目录下执行 cargo build -p vnt-cli 到项目根目录下执行 cargo build -p vnt-cli
也可按需编译,将得到更小的二进制文件,使用--no-default-features排除默认features
cargo build -p vnt-cli --no-default-features
```
features说明
| feature | 说明 | 是否默认 |
|------------------|----------------------|------|
| openssl | 使用openssl中的aes_ecb算法 | 否 |
| openssl-vendored | 从源码编译openssl | 否 |
| ring-cipher | 使用ring中的aes_gcm算法 | 否 |
| aes_cbc | 支持aes_cbc加密 | 是 |
| aes_ecb | 支持aes_ecb加密 | 是 |
| aes_gcm | 支持aes_gcm加密 | 是 |
| aes_ecb | 支持aes_ecb加密 | 是 |
| server_encrypt | 支持服务端加密 | 是 |
### 支持平台 ### 支持平台
- Mac - Mac
- Linux - Linux
- Windows - Windows
- 使用tun网卡 依赖wintun.dll([win-tun](https://www.wintun.net/))(将dll放到同目录下,建议使用版本0.14.1) - 默认使用tun网卡 依赖wintun.dll([win-tun](https://www.wintun.net/))(将dll放到同目录下,建议使用版本0.14.1)
- 使用tap网卡 依赖tap-windows([win-tap](https://build.openvpn.net/downloads/releases/))(建议使用版本9.24.7) - 使用tap网卡 依赖tap-windows([win-tap](https://build.openvpn.net/downloads/releases/))(建议使用版本9.24.7)
- Android - Android
- [SwitchApp](https://github.com/lbl8603/SwitchApp) - [VntApp](https://github.com/lbl8603/VntApp)
### 特性 ### 特性
@@ -86,9 +107,11 @@ A virtual network tool (VPN)
- p2p组播/广播 - p2p组播/广播
- 客户端数据加密 - 客户端数据加密
- 服务端数据加密 - 服务端数据加密
### 结构 ### 结构
<details> <summary>展开</summary> <details> <summary>展开</summary>
<pre> <pre>
0 15 31 0 15 31
@@ -121,8 +144,9 @@ A virtual network tool (VPN)
- 支持Ipv6(1.2.2已支持客户端之间的ipv6,待支持客户端和服务端之间的ipv6通信) - 支持Ipv6(1.2.2已支持客户端之间的ipv6,待支持客户端和服务端之间的ipv6通信)
### 常见问题 ### 常见问题
<details> <summary>展开</summary> <details> <summary>展开</summary>
#### 问题1: 设置网络地址失败 #### 问题1: 设置网络地址失败
##### 可能原因: ##### 可能原因:
@@ -138,26 +162,35 @@ vnt默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突
#### 问题2: windows系统上wintun.dll加载失败 #### 问题2: windows系统上wintun.dll加载失败
##### 可能原因: ##### 可能原因:
没有下载wintun.dll 或者使用的wintun.dll有问题 没有下载wintun.dll 或者使用的wintun.dll有问题
##### 解决方法: ##### 解决方法:
1. 下载最新版的wintun.dll [下载链接](https://www.wintun.net/builds/wintun-0.14.1.zip) 1. 下载最新版的wintun.dll [下载链接](https://www.wintun.net/builds/wintun-0.14.1.zip)
2. 解压后找到对应架构的目录,通常是amd64 2. 解压后找到对应架构的目录,通常是amd64
3. 将对应的wintun.dll放到和vnt-cli同目录下(或者放到C盘Windows目录下) 3. 将对应的wintun.dll放到和vnt-cli同目录下(或者放到C盘Windows目录下)
4. 再次启动vnt-cli 4. 再次启动vnt-cli
#### 问题3: 丢包严重,或是不能正常组网通信 #### 问题3: 丢包严重,或是不能正常组网通信
##### 可能原因: ##### 可能原因:
某些宽带下(比如广电宽带)UDP丢包严重 某些宽带下(比如广电宽带)UDP丢包严重
##### 解决方法: ##### 解决方法:
1. 使用TCP模式中继转发(vnt-cli增加--tcp参数) 1. 使用TCP模式中继转发(vnt-cli增加--tcp参数)
2. 如果p2p后效果很差,可以选择禁用p2p(vnt-cli增加--relay参数) 2. 如果p2p后效果很差,可以选择禁用p2p(vnt-cli增加--relay参数)
</details> </details>
### 交流群 ### 交流群
QQ:1034868233 QQ:1034868233
### 其他 ### 其他
可使用社区小伙伴搭建的中继服务器 可使用社区小伙伴搭建的中继服务器
1. -s vnt.8443.eu.org:29871 1. -s vnt.8443.eu.org:29871
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "common" name = "common"
version = "1.2.2" version = "1.2.5"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+3
View File
@@ -68,6 +68,9 @@ pub fn out_ips_parse(ips: &Vec<String>) -> Result<Vec<(u32, u32)>, String> {
pub fn to_ip(mask: &str) -> Result<u32, String> { pub fn to_ip(mask: &str) -> Result<u32, String> {
if let Ok(m) = mask.parse::<u32>() { if let Ok(m) = mask.parse::<u32>() {
if m >= 32 {
return Err("not netmask".to_string());
}
let mut mask = 0 as u32; let mut mask = 0 as u32;
for i in 0..m { for i in 0..m {
mask = mask | (1 << (31 - i)); mask = mask | (1 << (31 - i));
+3 -2
View File
@@ -1,8 +1,7 @@
use std::process::Command;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn get_unique_identifier() -> Option<String> { pub fn get_unique_identifier() -> Option<String> {
use std::os::windows::process::CommandExt; use std::os::windows::process::CommandExt;
use std::process::Command;
let output = match Command::new("wmic") let output = match Command::new("wmic")
.creation_flags(0x08000000) .creation_flags(0x08000000)
.args(&["csproduct", "get", "UUID"]) .args(&["csproduct", "get", "UUID"])
@@ -25,6 +24,7 @@ pub fn get_unique_identifier() -> Option<String> {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub fn get_unique_identifier() -> Option<String> { pub fn get_unique_identifier() -> Option<String> {
use std::process::Command;
let output = match Command::new("ioreg") let output = match Command::new("ioreg")
.args(&["-rd1", "-c", "IOPlatformExpertDevice"]) .args(&["-rd1", "-c", "IOPlatformExpertDevice"])
.output() .output()
@@ -50,6 +50,7 @@ pub fn get_unique_identifier() -> Option<String> {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub fn get_unique_identifier() -> Option<String> { pub fn get_unique_identifier() -> Option<String> {
use std::process::Command;
let output = match Command::new("dmidecode") let output = match Command::new("dmidecode")
.arg("-s") .arg("-s")
.arg("system-uuid") .arg("system-uuid")
+13 -7
View File
@@ -1,20 +1,21 @@
[package] [package]
name = "vnt-cli" name = "vnt-cli"
version = "1.2.2" version = "1.2.5"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
vnt = { path = "../vnt", package = "vnt", optional = true } vnt = { path = "../vnt", package = "vnt",default-features = false }
common = { path = "../common" } common = { path = "../common" }
tokio = { version = "1.28.1", features = ["full"] } tokio = { version = "1.32.0", features = ["full"] }
getopts = "0.2.21" getopts = "0.2.21"
console = "0.15.2" console = "0.15.2"
os_info = "3.7.0" os_info = "3.7.0"
dirs = "4.0.0" dirs = "5.0.1"
serde = "1.0" serde = "1.0"
serde_json = "1.0.94" serde_json = "1.0.94"
serde_yaml = "0.9.25"
log = "0.4.17" log = "0.4.17"
log4rs = "1.2.0" log4rs = "1.2.0"
[dependencies.uuid] [dependencies.uuid]
@@ -30,10 +31,15 @@ sudo = "0.6.0"
winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] } winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] }
[features] [features]
default = ["normal"] default = ["server_encrypt","aes_gcm","aes_cbc","aes_ecb","sm4_cbc"]
normal = ["vnt"] openssl = ["vnt/openssl"]
openssl-vendored = ["vnt/openssl-vendored"]
ring-cipher = ["vnt/ring-cipher"] ring-cipher = ["vnt/ring-cipher"]
aes_cbc=["vnt/aes_cbc"]
aes_ecb=["vnt/aes_ecb"]
sm4_cbc=["vnt/sm4_cbc"]
aes_gcm=["vnt/aes_gcm"]
server_encrypt=["vnt/server_encrypt"]
[build-dependencies] [build-dependencies]
embed-manifest = "1.4.0" embed-manifest = "1.4.0"
+69 -17
View File
@@ -19,21 +19,28 @@
配置点对网(IP代理)时使用,例如A(虚拟ip:10.26.0.2)通过B(虚拟ip:10.26.0.3,本地出口ip:192.168.0.10)访问C(目标网段192.168.0.0/24) 配置点对网(IP代理)时使用,例如A(虚拟ip:10.26.0.2)通过B(虚拟ip:10.26.0.3,本地出口ip:192.168.0.10)访问C(目标网段192.168.0.0/24)
则在A配置 **-i 192.168.0.0/24,10.26.0.3** ,表示将192.168.0.0/24网段的数据都转发到10.26.0.3节点 则在A配置 **'-i 192.168.0.0/24,10.26.0.3'** ,表示将192.168.0.0/24网段的数据都转发到10.26.0.3节点
在B配置 **-o 192.168.0.0/24** ,表示允许将数据转发到 192.168.0.0/24 在B配置 **'-o 192.168.0.0/24'** ,表示允许将数据转发到 192.168.0.0/24 ,允许转发所有网段可以使用 **'-o 0.0.0.0/0'**
-i和-o参数均可使用多次,来指定不同网段,例如 **'-o 192.168.1.0/24 -o 192.168.2.0/24'** 表示允许转发目标为192.168.1.0/24或192.168.2.0/24这两个网段的数据
### -w `<password>` ### -w `<password>`
提升通信安全性,使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密(包括中继数据)。使用相同密码的客户端才能通信 提升通信安全性,使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密(包括中继数据)。使用相同密码的客户端才能通信
| 密码位数 | 加密算法 | | 密码位数 | 加密算法 |
|---------|-------| |-------|------------|
| 小于8 | AES128-GCM | 小于8 | AES128-GCM |
| 大于等于8 | AES256-GCM | | 大于等于8 | AES256-GCM |
### -W ### -W
开启和服务端通信加密,可以避免中间人攻击 开启和服务端通信的数据加密,采用rsa+aes256gcm加密客户端和服务端之间通信的数据,可以避免token泄漏、中间人攻击
注意:
1. -w `<password>`是用于客户端-客户端之间的加密,password不会传递到服务端,只添加这个参数不会加密客户端-服务端通信的数据
2. -W 用于开启客户端-服务端之间的加密
### -m ### -m
模拟组播,高频使用组播通信时,可以尝试开启此参数,默认情况下会把组播当作广播发给所有节点 模拟组播,高频使用组播通信时,可以尝试开启此参数,默认情况下会把组播当作广播发给所有节点
@@ -43,7 +50,7 @@
### -u `<mtu>` ### -u `<mtu>`
设置虚拟网卡的mtu值,大多数情况下使用默认值效率会更高,也可根据实际情况微调这个值,不加密默认为1430,加密默认为1410 设置虚拟网卡的mtu值,大多数情况下使用默认值效率会更高,也可根据实际情况微调这个值,不加密默认为1450,加密默认为1410
### --tcp ### --tcp
和服务端使用tcp通信。有些网络提供商对UDP限制比较大,这个时候可以选择使用TCP模式,提高稳定性。一般来说udp延迟和消耗更低 和服务端使用tcp通信。有些网络提供商对UDP限制比较大,这个时候可以选择使用TCP模式,提高稳定性。一般来说udp延迟和消耗更低
@@ -51,20 +58,65 @@
指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配
### --par `<parallel>` ### --par `<parallel>`
任务并行度(必须为正整数),默认值为1,该值表示处理网卡读写的任务数,组网设备数较多、处理延迟较大时可适当调大此值 任务并行度(必须为正整数),默认值为1,该值表示处理网卡读写的任务数,组网设备数较多、处理延迟较大时可适当调大此值
### --thread `<thread>`
线程数(必须为正整数),默认为核心数乘2,该值表示处理网络读写、ip代理、打洞等用到的线程数,组网设备数较多、处理延迟较大时可适当调大此值
### --model `<model>` ### --model `<model>`
加密模式,可选值 aes_gcm/aes_cbc,默认使用aes_gcm,通常情况使用aes_cbc性能更好 加密模式,可选值 aes_gcm/aes_cbc/aes_ecb/sm4_cbc,默认使用aes_gcm,通常情况aes_gcm安全性高、aes_ecb性能更好,但是在低性能设备上sm4_cbc也许速度会更快;
| 密码位数 | model | 加密算法 |
|-------|--------|------------| | 密码位数 | model | 加密算法 |
| 1~8位 | aes_gcm | AES128-GCM | |-------|---------|------------|
| `>=`8 | aes_gcm | AES256-GCM | | 1~8位 | aes_gcm | AES128-GCM |
| 1~8位 | aes_cbc | AES128-CBC | | `>=`8 | aes_gcm | AES256-GCM |
| `>=`8 | aes_cbc | AES256-CBC | | 1~8位 | aes_cbc | AES128-CBC |
| `>=`8 | aes_cbc | AES256-CBC |
| 1~8位 | aes_ecb | AES128-ECB |
| `>=`8 | aes_ecb | AES256-ECB |
| `>0` | sm4_cbc | SM4-CBC |
### --finger ### --finger
开启数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启,开启会损耗一部分性能 开启数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启,开启会损耗一部分性能
注意:默认情况下服务端不会对中转的数据做校验,如果要对中转的数据做校验,则需要客户端、服务端都开启此参数
### --punch `<punch>`
取值ipv4/ipv6,选择只使用ipv4打洞或者只使用ipv6打洞,默认两则都会使用
### --port `<port>`
取值0~65535,指定本地监听的端口,默认取随机端口
### -f `<conf>`
指定配置文件
配置文件采用yaml格式,可参考:
```yaml
# 全部参数
tap: false #是否使用tap
token: xxx #组网token
device_id: xxx #当前设备id
name: windows 11 #当前设备名称
server_address: ip:port #注册和中继服务器
stun_server: #stun服务器
- stun1.l.google.com:19302
- stun2.l.google.com:19302
in_ips: #代理ip入站
- 192.168.1.0/24,10.26.0.3
out_ips: #代理ip出站
- 0.0.0.0/0
password: xxx #密码
simulate_multicast: false #模拟组播
mtu: 1420 #mtu
tcp: false #tcp模式
ip: 10.26.0.2 #指定虚拟ip
relay: false #中继模式
server_encrypt: true #服务端加密
parallel: 1 #任务并行度
cipher_model: aes_gcm #客户端加密算法
finger: false #关闭数据指纹
punch_model: ipv4 #打洞模式
port: 0 #使用随机端口
cmd: false #关闭控制台输入
```
或者需要哪个配置就加哪个,当然token是必须的
```yaml
# 部分参数
token: xxx #组网token
```
### --relay ### --relay
禁用p2p,在网络环境很差时,只使用服务器中转效果可能更好(可以配合--tcp参数一起使用) 禁用p2p,在网络环境很差时,只使用服务器中转效果可能更好(可以配合--tcp参数一起使用)
### --list ### --list
+1 -1
View File
@@ -26,7 +26,7 @@ impl CommandClient {
} }
}; };
let udp = UdpSocket::bind("127.0.0.1:0")?; let udp = UdpSocket::bind("127.0.0.1:0")?;
udp.set_read_timeout(Some(Duration::from_secs(2)))?; udp.set_read_timeout(Some(Duration::from_secs(5)))?;
udp.connect(SocketAddr::V4(SocketAddrV4::new( udp.connect(SocketAddr::V4(SocketAddrV4::new(
Ipv4Addr::new(127, 0, 0, 1), Ipv4Addr::new(127, 0, 0, 1),
port, port,
+1 -1
View File
@@ -17,7 +17,7 @@ pub enum CommandEnum {
pub fn command(cmd: CommandEnum) { pub fn command(cmd: CommandEnum) {
if let Err(e) = command_(cmd) { if let Err(e) = command_(cmd) {
println!("cmd: {}", e); println!("cmd: {:?}", e);
} }
} }
+7 -2
View File
@@ -17,15 +17,20 @@ impl CommandServer {
let udp = UdpSocket::bind("127.0.0.1:0").await?; let udp = UdpSocket::bind("127.0.0.1:0").await?;
let path_buf = crate::app_home()?.join("command-port"); let path_buf = crate::app_home()?.join("command-port");
let mut file = std::fs::File::create(path_buf)?; let mut file = std::fs::File::create(path_buf)?;
file.write_all(udp.local_addr()?.port().to_string().as_bytes())?; let addr = udp.local_addr()?;
file.write_all(addr.port().to_string().as_bytes())?;
file.sync_all()?; file.sync_all()?;
log::info!("启动后台cmd:{:?}", addr);
let mut buf = [0u8; 64]; let mut buf = [0u8; 64];
loop { loop {
let (len, addr) = udp.recv_from(&mut buf).await?; let (len, addr) = udp.recv_from(&mut buf).await?;
match std::str::from_utf8(&buf[..len]) { match std::str::from_utf8(&buf[..len]) {
Ok(cmd) => { Ok(cmd) => {
log::info!("收到cmd={:?}", cmd);
if let Ok(out) = command(cmd, &vnt) { if let Ok(out) = command(cmd, &vnt) {
let _ = udp.send_to(out.as_bytes(), addr).await; if let Err(e) = udp.send_to(out.as_bytes(), addr).await {
log::warn!("cmd={},err={:?}", cmd, e);
}
if "stopped" == &out { if "stopped" == &out {
break; break;
} }
+171
View File
@@ -0,0 +1,171 @@
use std::io;
use std::net::{Ipv4Addr, ToSocketAddrs};
use std::str::FromStr;
use serde::{Deserialize, Serialize};
use vnt::channel::punch::PunchModel;
use vnt::cipher::CipherModel;
use vnt::core::Config;
#[derive(Serialize, Deserialize, Debug)]
#[serde(default)]
pub struct FileConfig {
pub tap: bool,
pub token: String,
pub device_id: String,
pub name: String,
pub server_address: String,
pub stun_server: Vec<String>,
pub in_ips: Vec<String>,
pub out_ips: Vec<String>,
pub password: Option<String>,
pub simulate_multicast: bool,
pub mtu: Option<u16>,
pub tcp: bool,
pub ip: Option<String>,
pub relay: bool,
pub server_encrypt: bool,
pub parallel: usize,
pub cipher_model: String,
pub finger: bool,
pub punch_model: String,
pub port: u16,
pub cmd: bool,
}
impl Default for FileConfig {
fn default() -> Self {
Self {
tap: false,
token: "".to_string(),
device_id: get_device_id(),
name: os_info::get().to_string(),
server_address: "nat1.wherewego.top:29872".to_string(),
stun_server: vec![
"stun1.l.google.com:19302".to_string(),
"stun2.l.google.com:19302".to_string(),
"stun.qq.com:3478".to_string(),
],
in_ips: vec![],
out_ips: vec![],
password: None,
simulate_multicast: false,
mtu: None,
tcp: false,
ip: None,
relay: false,
server_encrypt: false,
parallel: 1,
cipher_model: "aes_gcm".to_string(),
finger: false,
punch_model: "".to_string(),
port: 0,
cmd: false,
}
}
}
pub fn read_config(file_path: &str) -> io::Result<(Config, bool)> {
let conf = std::fs::read_to_string(file_path)?;
let file_conf = match serde_yaml::from_str::<FileConfig>(&conf) {
Ok(val) => val,
Err(e) => {
log::error!("{:?}", e);
return Err(io::Error::new(io::ErrorKind::Other, format!("{}", e)));
}
};
if file_conf.token.is_empty() {
return Err(io::Error::new(io::ErrorKind::Other, "token is_empty"));
}
let server_address = match file_conf.server_address.to_socket_addrs() {
Ok(mut addr) => {
if let Some(addr) = addr.next() {
addr
} else {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("server_address {:?} error", &file_conf.server_address),
));
}
}
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("server_address {:?} error:{}", &file_conf.server_address, e),
));
}
};
let in_ips = match common::args_parse::ips_parse(&file_conf.in_ips) {
Ok(in_ips) => in_ips,
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("in_ips {:?} error:{}", &file_conf.in_ips, e),
));
}
};
let out_ips = match common::args_parse::out_ips_parse(&file_conf.out_ips) {
Ok(out_ips) => out_ips,
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("out_ips {:?} error:{}", &file_conf.out_ips, e),
));
}
};
let virtual_ip = match file_conf.ip.clone().map(|v| Ipv4Addr::from_str(&v)) {
None => None,
Some(r) => Some(r.map_err(|e| {
io::Error::new(
io::ErrorKind::Other,
format!("ip {:?} error:{}", &file_conf.ip, e),
)
})?),
};
let cipher_model = CipherModel::from_str(&file_conf.cipher_model)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
let punch_model = PunchModel::from_str(&file_conf.punch_model)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
let config = Config::new(
file_conf.tap,
file_conf.token,
file_conf.device_id,
file_conf.name,
server_address,
file_conf.server_address,
file_conf.stun_server,
in_ips,
out_ips,
file_conf.password,
file_conf.simulate_multicast,
file_conf.mtu,
file_conf.tcp,
virtual_ip,
file_conf.relay,
file_conf.server_encrypt,
file_conf.parallel,
cipher_model,
file_conf.finger,
punch_model,
file_conf.port,
);
Ok((config, file_conf.cmd))
}
pub fn get_device_id() -> String {
if let Some(id) = common::identifier::get_unique_identifier() {
id
} else {
let path_buf = crate::app_home().unwrap().join("device-id");
if let Ok(id) = std::fs::read_to_string(path_buf.as_path()) {
id
} else {
let id = uuid::Uuid::new_v4().to_string();
let _ = std::fs::write(path_buf, &id);
id
}
}
}
+204 -206
View File
@@ -7,8 +7,6 @@ use console::style;
use getopts::Options; use getopts::Options;
use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::io::{AsyncBufReadExt, BufReader};
use tokio::signal; use tokio::signal;
#[cfg(unix)]
use tokio::signal::unix::{signal, SignalKind};
use common::args_parse::{ips_parse, out_ips_parse}; use common::args_parse::{ips_parse, out_ips_parse};
use vnt::channel::punch::PunchModel; use vnt::channel::punch::PunchModel;
@@ -18,6 +16,7 @@ use vnt::handle::handshake_handler::HandshakeEnum;
use vnt::handle::registration_handler::ReqEnum; use vnt::handle::registration_handler::ReqEnum;
mod command; mod command;
mod config;
mod console_out; mod console_out;
mod root_check; mod root_check;
@@ -56,12 +55,10 @@ fn main() {
opts.optopt("", "thread", "线程数(必须为正整数)", "<thread>"); opts.optopt("", "thread", "线程数(必须为正整数)", "<thread>");
opts.optopt("", "model", "加密模式", "<model>"); opts.optopt("", "model", "加密模式", "<model>");
opts.optflag("", "finger", "指纹校验"); opts.optflag("", "finger", "指纹校验");
opts.optopt( opts.optopt("", "punch", "取值ipv4/ipv6", "<punch>");
"", opts.optopt("", "port", "监听的端口", "<port>");
"punch", opts.optflag("", "cmd", "开启窗口输入");
"取值ipv4/ipv6,表示仅使用ipv4或ipv6打洞", opts.optopt("f", "", "配置文件", "<conf>");
"<punch>",
);
//"后台运行时,查看其他设备列表" //"后台运行时,查看其他设备列表"
opts.optflag("", "list", "后台运行时,查看其他设备列表"); opts.optflag("", "list", "后台运行时,查看其他设备列表");
opts.optflag("", "all", "后台运行时,查看其他设备完整信息"); opts.optflag("", "all", "后台运行时,查看其他设备完整信息");
@@ -103,166 +100,196 @@ fn main() {
command::command(command::CommandEnum::All); command::command(command::CommandEnum::All);
return; return;
} }
if !matches.opt_present("k") { let conf = matches.opt_str("f");
print_usage(&program, opts); let (config, cmd) = if conf.is_some() {
println!("parameter -k not found ."); match config::read_config(&conf.unwrap()) {
return; Ok(c) => c,
} Err(e) => {
let tap = matches.opt_present("a"); println!("conf err {}", e);
let token: String = matches.opt_get("k").unwrap().unwrap();
let device_id = matches.opt_get_default("d", String::new()).unwrap();
let device_id = if device_id.is_empty() {
if let Some(id) = common::identifier::get_unique_identifier() {
id
} else {
let path_buf = app_home().unwrap().join("device-id");
if let Ok(id) = std::fs::read_to_string(path_buf.as_path()) {
id
} else {
let id = uuid::Uuid::new_v4().to_string();
let _ = std::fs::write(path_buf, &id);
id
}
}
} else {
device_id
};
if device_id.is_empty() {
print_usage(&program, opts);
println!("parameter -d not found .");
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:29872".to_string())
.unwrap();
let server_address = match server_address_str.to_socket_addrs() {
Ok(mut addr) => {
if let Some(addr) = addr.next() {
addr
} else {
println!("parameter -s error .");
return; return;
} }
} }
Err(e) => { } else {
println!("parameter -s error {}.", e); if !matches.opt_present("k") {
print_usage(&program, opts);
println!("parameter -k not found .");
return; return;
} }
}; let tap = matches.opt_present("a");
let mut stun_server = matches.opt_strs("e"); let token: String = matches.opt_get("k").unwrap().unwrap();
if stun_server.is_empty() { let device_id = matches.opt_get_default("d", String::new()).unwrap();
stun_server.push("stun1.l.google.com:19302".to_string()); let device_id = if device_id.is_empty() {
stun_server.push("stun2.l.google.com:19302".to_string()); config::get_device_id()
stun_server.push("stun.qq.com:3478".to_string()); } else {
} device_id
};
if device_id.is_empty() {
print_usage(&program, opts);
println!("parameter -d not found .");
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:29872".to_string())
.unwrap();
let server_address = match server_address_str.to_socket_addrs() {
Ok(mut addr) => {
if let Some(addr) = addr.next() {
addr
} else {
println!("parameter '-s {}' error .", server_address_str);
return;
}
}
Err(e) => {
println!("parameter '-s {}' error {}.", server_address_str, e);
return;
}
};
let mut stun_server = matches.opt_strs("e");
if stun_server.is_empty() {
stun_server.push("stun1.l.google.com:19302".to_string());
stun_server.push("stun2.l.google.com:19302".to_string());
stun_server.push("stun.qq.com:3478".to_string());
}
let in_ip = matches.opt_strs("i"); let in_ip = matches.opt_strs("i");
let in_ip = match ips_parse(&in_ip) { let in_ip = match ips_parse(&in_ip) {
Ok(in_ip) => in_ip, Ok(in_ip) => in_ip,
Err(e) => {
print_usage(&program, opts);
println!();
println!("-i {}", e);
println!("example: -i 192.168.0.0/24,10.26.0.3");
return;
}
};
let out_ip = matches.opt_strs("o");
let out_ip = match out_ips_parse(&out_ip) {
Ok(out_ip) => out_ip,
Err(e) => {
print_usage(&program, opts);
println!();
println!("-o {}", e);
println!("example: -o 0.0.0.0/0");
return;
}
};
let password: Option<String> = 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<String> = matches.opt_get("u").unwrap();
let mtu = if let Some(mtu) = mtu {
match u16::from_str(&mtu) {
Ok(mtu) => Some(mtu),
Err(e) => { Err(e) => {
print_usage(&program, opts); print_usage(&program, opts);
println!(); println!();
println!("-u {}", e); println!("-i: {:?} {}", in_ip, e);
println!("example: -i 192.168.0.0/24,10.26.0.3");
return;
}
};
let out_ip = matches.opt_strs("o");
let out_ip = match out_ips_parse(&out_ip) {
Ok(out_ip) => out_ip,
Err(e) => {
print_usage(&program, opts);
println!();
println!("-o: {:?} {}", out_ip, e);
println!("example: -o 0.0.0.0/0");
return;
}
};
let password: Option<String> = matches.opt_get("w").unwrap();
let server_encrypt = matches.opt_present("W");
#[cfg(not(feature = "server_encrypt"))]
{
if server_encrypt {
println!("Server encryption not supported");
return; return;
} }
} }
} else { let simulate_multicast = matches.opt_present("m");
None let mtu: Option<String> = matches.opt_get("u").unwrap();
}; let mtu = if let Some(mtu) = mtu {
let virtual_ip: Option<String> = matches.opt_get("ip").unwrap(); match u16::from_str(&mtu) {
let virtual_ip = virtual_ip.map(|v| Ipv4Addr::from_str(&v).expect("--ip error")); Ok(mtu) => Some(mtu),
if let Some(virtual_ip) = virtual_ip { Err(e) => {
if virtual_ip.is_unspecified() || virtual_ip.is_broadcast() || virtual_ip.is_multicast() { print_usage(&program, opts);
println!("--ip invalid"); println!();
println!("'-u {}' {}", mtu, e);
return;
}
}
} else {
None
};
let virtual_ip: Option<String> = matches.opt_get("ip").unwrap();
let virtual_ip =
virtual_ip.map(|v| Ipv4Addr::from_str(&v).expect(&format!("'--ip {}' error", v)));
if let Some(virtual_ip) = virtual_ip {
if virtual_ip.is_unspecified() || virtual_ip.is_broadcast() || virtual_ip.is_multicast()
{
println!("'--ip {}' invalid", virtual_ip);
return;
}
}
let tcp_channel = matches.opt_present("tcp");
let relay = matches.opt_present("relay");
let parallel = matches.opt_get::<usize>("par").unwrap().unwrap_or(1);
if parallel == 0 {
println!("'--par {}' invalid", parallel);
return; return;
} }
}
let tcp_channel = matches.opt_present("tcp"); let cipher_model = match matches.opt_get::<CipherModel>("model") {
let relay = matches.opt_present("relay"); Ok(model) => {
let parallel = matches.opt_get::<usize>("par").unwrap().unwrap_or(1); #[cfg(not(any(
if parallel == 0 { feature = "aes_gcm",
println!("--par invalid"); feature = "server_encrypt",
return; feature = "aes_cbc",
} feature = "aes_ecb",
let thread_num = matches feature = "sm4_cbc"
.opt_get::<usize>("thread") )))]
.unwrap() {
.unwrap_or(std::thread::available_parallelism().unwrap().get() * 2); if password.is_some() && model.is_none() {
let cipher_model = matches println!("Encryption not supported");
.opt_get::<CipherModel>("model") return;
.unwrap() }
.unwrap_or(CipherModel::AesGcm); }
if thread_num == 0 { #[cfg(not(any(feature = "aes_gcm", feature = "server_encrypt")))]
println!("--thread invalid"); {
return; if password.is_some() && model.is_none() {
} println!("'--model ' undefined");
let finger = matches.opt_present("finger"); return;
let punch_model = matches }
.opt_get::<PunchModel>("punch") model.unwrap_or(CipherModel::None)
.unwrap() }
.unwrap_or(PunchModel::All); #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
model.unwrap_or(CipherModel::AesGcm)
}
Err(e) => {
println!("'--model ' invalid,{}", e);
return;
}
};
let finger = matches.opt_present("finger");
let punch_model = matches
.opt_get::<PunchModel>("punch")
.unwrap()
.unwrap_or(PunchModel::All);
let port = matches.opt_get::<u16>("port").unwrap_or(None).unwrap_or(0);
let cmd = matches.opt_present("cmd");
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,
server_encrypt,
parallel,
cipher_model,
finger,
punch_model,
port,
);
(config, cmd)
};
println!("version {}", vnt::VNT_VERSION); println!("version {}", vnt::VNT_VERSION);
let config = Config::new(
tap, main0(config, cmd);
token,
device_id,
name,
server_address,
server_address_str,
stun_server,
in_ip,
out_ip,
password,
simulate_multicast,
mtu,
tcp_channel,
virtual_ip,
relay,
server_encrypt,
parallel,
cipher_model,
finger,
punch_model,
);
let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.worker_threads(thread_num)
.build()
.unwrap();
runtime.block_on(main0(config, !unused_cmd));
std::process::exit(0); std::process::exit(0);
} }
#[tokio::main]
async fn main0(config: Config, show_cmd: bool) { async fn main0(config: Config, show_cmd: bool) {
let server_encrypt = config.server_encrypt; let server_encrypt = config.server_encrypt;
let mut vnt_util = VntUtil::new(config).await.unwrap(); let mut vnt_util = VntUtil::new(config).await.unwrap();
@@ -370,11 +397,10 @@ async fn main0(config: Config, show_cmd: bool) {
let vnt_c = vnt.clone(); let vnt_c = vnt.clone();
tokio::spawn(async { tokio::spawn(async {
if let Err(e) = command::server::CommandServer::new().start(vnt_c).await { if let Err(e) = command::server::CommandServer::new().start(vnt_c).await {
log::warn!("cmd:{:?}", e);
println!("command error :{}", e); println!("command error :{}", e);
} }
}); });
#[cfg(unix)]
let mut sigterm = signal(SignalKind::terminate()).expect("Error setting SIGTERM handler");
if show_cmd { if show_cmd {
let stdin = tokio::io::stdin(); let stdin = tokio::io::stdin();
let mut cmd = String::new(); let mut cmd = String::new();
@@ -382,7 +408,6 @@ async fn main0(config: Config, show_cmd: bool) {
loop { loop {
cmd.clear(); cmd.clear();
println!("input:list,info,route,all,stop"); println!("input:list,info,route,all,stop");
#[cfg(unix)]
tokio::select! { tokio::select! {
_ = vnt.wait_stop()=>{ _ = vnt.wait_stop()=>{
return; return;
@@ -390,36 +415,7 @@ async fn main0(config: Config, show_cmd: bool) {
_ = signal::ctrl_c()=>{ _ = signal::ctrl_c()=>{
let _ = vnt.stop(); let _ = vnt.stop();
vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await; vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await;
return; std::process::exit(0);
}
_ = 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 !command(&cmd[..len],&vnt){
break;
}
}
Err(e) => {
println!("input err:{}",e);
break;
}
}
}
}
#[cfg(windows)]
tokio::select! {
_ = vnt.wait_stop()=>{
return;
}
_ = signal::ctrl_c()=>{
let _ = vnt.stop();
vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await;
return;
} }
rs = reader.read_line(&mut cmd)=>{ rs = reader.read_line(&mut cmd)=>{
match rs { match rs {
@@ -437,23 +433,6 @@ async fn main0(config: Config, show_cmd: bool) {
} }
} }
} }
#[cfg(unix)]
tokio::select! {
_ = vnt.wait_stop()=>{
return;
}
_ = 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;
}
}
#[cfg(windows)]
vnt.wait_stop().await; vnt.wait_stop().await;
} }
@@ -494,29 +473,48 @@ fn print_usage(program: &str, _opts: Options) {
println!("Options:"); println!("Options:");
println!( println!(
" -k <token> {}", " -k <token> {}",
green("必选,使用相同的token,就能组建一个局域网络".to_string()) green("使用相同的token,就能组建一个局域网络".to_string())
); );
println!(" -n <name> 给设备一个名字,便于区分不同设备,默认使用系统版本"); println!(" -n <name> 给设备一个名字,便于区分不同设备,默认使用系统版本");
println!(" -d <id> 设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip"); println!(" -d <id> 设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip");
println!(" -c 关闭交互式命令,使用此参数禁用控制台输入");
println!(" -s <server> 注册和中继服务器地址"); println!(" -s <server> 注册和中继服务器地址");
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可多次指定,如-e addr1 -e addr2"); println!(" -e <stun-server> stun服务器,用于探测NAT类型,可多次指定,如-e addr1 -e addr2");
println!(" -a 使用tap模式,默认使用tun模式"); println!(" -a 使用tap模式,默认使用tun模式");
println!(" -i <in-ip> 配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据"); println!(" -i <in-ip> 配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据");
println!(" 并转发到10.26.0.3,可指定多个网段"); println!(" 并转发到10.26.0.3,可指定多个网段");
println!(" -o <out-ip> 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段"); println!(" -o <out-ip> 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段");
println!(" -w <password> 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信"); let mut enums = String::new();
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
enums.push_str("/aes_gcm");
#[cfg(feature = "aes_cbc")]
enums.push_str("/aes_cbc");
#[cfg(feature = "aes_ecb")]
enums.push_str("/aes_ecb");
#[cfg(feature = "sm4_cbc")]
enums.push_str("/sm4_cbc");
if !enums.is_empty() {
println!(" -w <password> 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信");
}
#[cfg(feature = "server_encrypt")]
println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确"); println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确");
println!(" -m 模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送"); println!(" -m 模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送");
println!(" -u <mtu> 自定义mtu(不加密默认为1430,加密默认为1410)"); println!(" -u <mtu> 自定义mtu(不加密默认为1450,加密默认为1410)");
println!(" -f <conf_file> 读取配置文件中的配置");
println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp"); println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp");
println!(" --ip <ip> 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配"); println!(" --ip <ip> 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配");
println!(" --relay 仅使用服务器转发,不使用p2p,默认情况允许使用p2p"); println!(" --relay 仅使用服务器转发,不使用p2p,默认情况允许使用p2p");
println!(" --par <parallel> 任务并行度(必须为正整数),默认值为1"); println!(" --par <parallel> 任务并行度(必须为正整数),默认值为1");
println!(" --thread <thread> 线程数(必须为正整数),默认为核心数乘2"); if !enums.is_empty() {
println!(" --model <model> 加密模式(默认aes_gcm),可选值aes_gcm/aes_cbc/aes_ecb,通常性能aes_ecb>aes_cbc>aes_gcm,安全性则相反"); println!(
" --model <model> 加密模式(默认aes_gcm),可选值{}",
&enums[1..]
);
}
println!(" --finger 增加数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启"); println!(" --finger 增加数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启");
println!(" --punch <punch> 取值ipv4/ipv6ipv4表示仅使用ipv4打洞"); println!(" --punch <punch> 取值ipv4/ipv6ipv4表示仅使用ipv4打洞");
println!(" --port <port> 取值0~65535,指定本地监听的端口,默认取随机端口");
println!(" --cmd 开启交互式命令,使用此参数开启控制台输入");
println!(); println!();
println!( println!(
+2 -1
View File
@@ -1,11 +1,12 @@
[package] [package]
name = "vnt-jni" name = "vnt-jni"
version = "1.2.2" version = "1.2.5"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
common = { path = "../common" }
vnt = {path="../vnt"} vnt = {path="../vnt"}
jni = { version = "0.21.1", default-features = false } jni = { version = "0.21.1", default-features = false }
+34 -2
View File
@@ -66,6 +66,37 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
let cipher_model = to_string_not_null(env, &config, "cipherModel")?; let cipher_model = to_string_not_null(env, &config, "cipherModel")?;
let tcp = env.get_field(&config, "tcp", "Z")?.z()?; let tcp = env.get_field(&config, "tcp", "Z")?.z()?;
let finger = env.get_field(&config, "finger", "Z")?.z()?; let finger = env.get_field(&config, "finger", "Z")?.z()?;
let in_ips = to_string(env, &config, "inIps")?;
let out_ips = to_string(env, &config, "outIps")?;
let port = env.get_field(&config, "port", "I")?.i()? as u16;
let in_ips = if let Some(in_ips) = in_ips {
let in_ips: Vec<&str> = in_ips.split("\n").collect();
let in_ips = in_ips.iter().map(|v| v.to_string()).collect();
match common::args_parse::ips_parse(&in_ips) {
Ok(in_ips) => in_ips,
Err(e) => {
env.throw_new("java/lang/RuntimeException", format!("in_ips {}", e))
.expect("throw");
return Err(Error::JavaException);
}
}
} else {
vec![]
};
let out_ips = if let Some(out_ips) = out_ips {
let out_ips: Vec<&str> = out_ips.split("\n").collect();
let out_ips = out_ips.iter().map(|v| v.to_string()).collect();
match common::args_parse::out_ips_parse(&out_ips) {
Ok(out_ips) => out_ips,
Err(e) => {
env.throw_new("java/lang/RuntimeException", format!("out_ips {}", e))
.expect("throw");
return Err(Error::JavaException);
}
}
} else {
vec![]
};
let server_address = match server_address_str.to_socket_addrs() { let server_address = match server_address_str.to_socket_addrs() {
Ok(mut rs) => { Ok(mut rs) => {
@@ -106,8 +137,8 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
server_address, server_address,
server_address_str, server_address_str,
stun_server, stun_server,
vec![], in_ips,
vec![], out_ips,
password, password,
false, false,
None, None,
@@ -119,6 +150,7 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
cipher_model, cipher_model,
finger, finger,
PunchModel::All, PunchModel::All,
port,
); );
match VntUtilSync::new(config) { match VntUtilSync::new(config) {
Ok(vnt_util) => Ok(vnt_util), Ok(vnt_util) => Ok(vnt_util),
+25 -17
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "vnt" name = "vnt"
version = "1.2.2" version = "1.2.5"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -11,39 +11,47 @@ bytes = "1.3.0"
log = "0.4.17" log = "0.4.17"
libc = "0.2.137" libc = "0.2.137"
crossbeam-utils = "0.8" crossbeam-utils = "0.8"
crossbeam-epoch = "0.9.15"
dashmap = "5.5.1" dashmap = "5.5.1"
parking_lot = "0.12.1" parking_lot = "0.12.1"
byte-pool = "0.2.4"
lazy_static = "1.4.0"
rand = "0.8.5" rand = "0.8.5"
sha2 = { version = "0.10.6", features = ["oid"] } sha2 = { version = "0.10.6", features = ["oid"] }
thiserror = "1.0.37" thiserror = "1.0.37"
protobuf = "3.2.0" protobuf = "3.2.0"
socket2 ={ version = "0.5.2", features = ["all"] } socket2 = { version = "0.5.2", features = ["all"] }
tokio = { version = "1.28.1", features = ["full"] } tokio = { version = "1.32.0", features = ["full"] }
aes-gcm = {version="0.10.2", optional = true} aes-gcm = { version = "0.10.2",optional = true }
ring = {version="0.16.20", optional = true} ring = { version = "0.16.20", optional = true }
cbc = "0.1.2" cbc = {version = "0.1.2",optional = true}
ecb = "0.1.2" ecb = {version = "0.1.2",optional = true}
aes = "0.8.3" aes = "0.8.3"
stun-format = {version="1.0.1",features=["fmt","rfc3489"]} stun-format = { version = "1.0.1", features = ["fmt", "rfc3489"] }
rsa = {version="0.7.2", features = [] } rsa = { version = "0.7.2", features = [] ,optional = true}
spki = {version="0.6.0",features=["fingerprint","alloc"]} spki = { version = "0.6.0", features = ["fingerprint", "alloc"] ,optional = true}
openssl-sys = { git = "https://github.com/lbl8603/rust-openssl" ,optional = true}
libsm = {git="https://github.com/lbl8603/libsm" ,optional = true}
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies] [target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
tun = { path = "./rust-tun" } tun = { path = "./rust-tun" }
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]
win-tun-tap = { path = "./win-tun-tap" }
win-tun-tap = {path = "./win-tun-tap"}
libloading = "0.7.4" libloading = "0.7.4"
[build-dependencies] [build-dependencies]
protobuf-codegen = "3.2.0" protobuf-codegen = "3.2.0"
protoc-bin-vendored = "3.0.0" protoc-bin-vendored = "3.0.0"
[features] [features]
default=["aes-gcm"] default = ["server_encrypt","aes_gcm","aes_cbc","aes_ecb","sm4_cbc"]
ring-cipher=["ring"] openssl = ["openssl-sys"]
# 从源码编译
openssl-vendored = ["openssl-sys/vendored"]
ring-cipher = ["ring"]
aes_cbc=["cbc"]
aes_ecb=["ecb"]
sm4_cbc=["libsm"]
aes_gcm=["aes-gcm"]
server_encrypt =["rsa","spki"]
+461 -216
View File
@@ -1,36 +1,38 @@
use std::collections::HashMap;
use std::io; use std::io;
use std::net::{Ipv4Addr, SocketAddr}; use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
use std::ops::Sub;
use std::sync::atomic::Ordering;
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use byte_pool::{Block, BytePool}; use crossbeam_epoch::{Atomic, Owned};
use crossbeam_utils::atomic::AtomicCell; use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap; use dashmap::DashMap;
use std::net::UdpSocket as StdUdpSocket;
use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::tcp::OwnedReadHalf; use tokio::net::tcp::OwnedReadHalf;
use tokio::net::{TcpStream, UdpSocket}; use tokio::net::{TcpStream, UdpSocket};
use tokio::sync::watch::{channel, Receiver, Sender}; use tokio::sync::watch::{channel, Receiver, Sender};
use crate::channel::punch::NatType; use crate::channel::punch::NatType;
use crate::channel::{Route, RouteKey, Status}; use crate::channel::{Route, RouteKey, Status, TCP_ID, UDP_ID, UDP_V6_ID};
use crate::core::status::VntWorker; use crate::core::status::VntWorker;
use crate::handle::recv_handler::ChannelDataHandler; use crate::handle::recv_handler::ChannelDataHandler;
use crate::handle::CurrentDeviceInfo; use crate::handle::CurrentDeviceInfo;
use crate::ip_proxy::DashMapNew;
lazy_static::lazy_static! {
static ref POOL:BytePool = BytePool::new();
}
pub struct ContextInner { pub struct ContextInner {
//udp用于打洞、服务端通信(可选) //udp用于打洞、服务端通信(可选)
pub(crate) main_channel: Arc<UdpSocket>, pub(crate) main_channel: Arc<StdUdpSocket>,
pub(crate) main_channel_ipv6: Option<Arc<UdpSocket>>, pub(crate) main_channel_ipv6: Option<Arc<StdUdpSocket>>,
//在udp的基础上,可以选择使用tcp和服务端通信 //在udp的基础上,可以选择使用tcp和服务端通信
pub(crate) main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>, pub(crate) main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>,
pub(crate) route_table: DashMap<Ipv4Addr, Vec<Route>>, pub(crate) route_table: Atomic<HashMap<Ipv4Addr, Vec<Route>>>,
pub(crate) route_table_time: DashMap<(RouteKey, Ipv4Addr), Instant>, pub(crate) route_table_time: DashMap<(RouteKey, Ipv4Addr), Instant>,
pub(crate) status_receiver: Receiver<Status>, pub(crate) status_receiver: Receiver<Status>,
pub(crate) status_sender: Sender<Status>, pub(crate) status_sender: Sender<Status>,
pub(crate) udp_map: DashMap<usize, Arc<UdpSocket>>, pub(crate) udp_map: Atomic<HashMap<usize, Arc<UdpSocket>>>,
pub(crate) channel_num: usize, pub(crate) channel_num: usize,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
} }
@@ -42,8 +44,8 @@ pub struct Context {
impl Context { impl Context {
pub fn new( pub fn new(
main_channel: Arc<UdpSocket>, main_channel: Arc<StdUdpSocket>,
main_channel_ipv6: Option<Arc<UdpSocket>>, main_channel_ipv6: Option<Arc<StdUdpSocket>>,
main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>, main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
_channel_num: usize, _channel_num: usize,
@@ -55,11 +57,11 @@ impl Context {
main_channel, main_channel,
main_channel_ipv6, main_channel_ipv6,
main_tcp_channel, main_tcp_channel,
route_table: DashMap::with_capacity(16), route_table: Atomic::new(HashMap::with_capacity(16)),
route_table_time: DashMap::with_capacity(16), route_table_time: DashMap::new_cap(16),
status_receiver, status_receiver,
status_sender, status_sender,
udp_map: DashMap::new(), udp_map: Atomic::new(HashMap::with_capacity(16)),
channel_num, channel_num,
current_device, current_device,
}); });
@@ -74,8 +76,21 @@ impl Context {
pub fn is_cone(&self) -> bool { pub fn is_cone(&self) -> bool {
*self.inner.status_receiver.borrow() == Status::Cone *self.inner.status_receiver.borrow() == Status::Cone
} }
pub fn close(&self) { pub fn close(&self) -> io::Result<()> {
let _ = self.inner.status_sender.send(Status::Close); let _ = self.inner.status_sender.send(Status::Close);
if let Ok(port) = self.main_local_ipv4_port() {
let _ = StdUdpSocket::bind("127.0.0.1:0")?.send_to(
b"stop",
SocketAddr::V4(std::net::SocketAddrV4::new(Ipv4Addr::LOCALHOST, port)),
);
}
if let Ok(port) = self.main_local_ipv6_port() {
let _ = StdUdpSocket::bind("[::]:0")?.send_to(
b"stop",
SocketAddr::V6(std::net::SocketAddrV6::new(Ipv6Addr::LOCALHOST, port, 0, 0)),
);
}
Ok(())
} }
pub fn is_main_tcp(&self) -> bool { pub fn is_main_tcp(&self) -> bool {
self.inner.main_tcp_channel.is_some() self.inner.main_tcp_channel.is_some()
@@ -106,68 +121,112 @@ impl Context {
Err(io::Error::new(io::ErrorKind::Other, "not ipv6")) Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
} }
} }
pub async fn send_main_udp(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> { fn insert_udp(&self, id: usize, udp: Arc<UdpSocket>) {
self.insert_udp_(id, Some(udp))
}
fn remove_udp(&self, id: usize) {
self.insert_udp_(id, None)
}
fn insert_udp_(&self, id: usize, udp: Option<Arc<UdpSocket>>) {
let guard = &crossbeam_epoch::pin();
let udp_map = &self.inner.udp_map;
let mut udp_map_shared = self.inner.udp_map.load(Ordering::Relaxed, guard);
loop {
let mut map = unsafe { udp_map_shared.as_ref().unwrap().clone() };
match udp.clone() {
None => {
map.remove(&id);
}
Some(udp) => {
map.insert(id, udp);
}
}
match udp_map.compare_exchange(
udp_map_shared,
Owned::new(map),
Ordering::Relaxed,
Ordering::Relaxed,
guard,
) {
Ok(p) => unsafe {
guard.defer_destroy(p);
return;
},
Err(e) => {
udp_map_shared = e.current;
}
}
}
}
pub fn send_main_udp(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
if addr.is_ipv6() { if addr.is_ipv6() {
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 { if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
udp_ipv6.send_to(buf, addr).await udp_ipv6.send_to(buf, addr)
} else { } else {
Err(io::Error::new(io::ErrorKind::Other, "not ipv6")) Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
} }
} else { } else {
self.inner.main_channel.send_to(buf, addr).await self.inner.main_channel.send_to(buf, addr)
} }
} }
pub fn try_send_main_udp(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
if addr.is_ipv6() { pub fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
udp_ipv6.try_send_to(buf, addr)
} else {
Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
}
} else {
self.inner.main_channel.try_send_to(buf, addr)
}
}
pub async fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
if let Some(sender) = &self.inner.main_tcp_channel { if let Some(sender) = &self.inner.main_tcp_channel {
if sender.send(buf.to_vec()).await.is_ok() { if sender.try_send(buf.to_vec()).is_ok() {
Ok(buf.len()) Ok(buf.len())
} else { } else {
Err(io::Error::new(io::ErrorKind::Other, "send_main err")) Err(io::Error::new(io::ErrorKind::Other, "send_main err"))
} }
} else { } else {
self.send_main_udp(buf, addr).await self.send_main_udp(buf, addr)
}
}
pub fn try_send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
if let Some(sender) = &self.inner.main_tcp_channel {
if sender.try_send(buf.to_vec()).is_ok() {
Ok(buf.len())
} else {
Err(io::Error::new(io::ErrorKind::Other, "try_send_main err"))
}
} else {
self.try_send_main_udp(buf, addr)
} }
} }
pub(crate) async fn send_all(&self, buf: &[u8], addr: SocketAddr) -> io::Result<()> { pub(crate) fn try_send_all(&self, buf: &[u8], addr: SocketAddr) -> io::Result<()> {
for udp_ref in self.inner.udp_map.iter() { let table = unsafe {
let udp = udp_ref.clone(); let guard = &crossbeam_epoch::pin();
drop(udp_ref); self.inner
.udp_map
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
.clone()
};
if table.is_empty() {
log::error!("udp列表为空,addr={}", addr);
return Ok(());
}
for (_, udp) in table {
//使用ipv6的udp发送ipv4报文会出错 //使用ipv6的udp发送ipv4报文会出错
let _ = udp.send_to(buf, addr).await; if let Err(e) = udp.try_send_to(buf, addr) {
log::error!("{:?}", e);
}
} }
Ok(()) Ok(())
} }
pub async fn send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> { pub async fn send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> {
if let Some(v) = self.inner.route_table.get(id) { let route = self.get_route_by_id(id)?;
if v.value().is_empty() { self.send_by_key(buf, &route.route_key()).await
}
pub fn try_send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> {
let route = self.get_route_by_id(id)?;
self.try_send_by_key(buf, &route.route_key())
}
fn get_route_by_id(&self, id: &Ipv4Addr) -> io::Result<Route> {
let guard = &crossbeam_epoch::pin();
let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
if let Some(v) = table.get(id) {
if v.is_empty() {
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found")); return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
} }
let route = v.value()[0]; let route = v[0];
drop(v);
if route.rt == 199 { if route.rt == 199 {
//这通常是刚加入路由,直接放弃使用,避免抖动 //这通常是刚加入路由,直接放弃使用,避免抖动
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found")); return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
@@ -180,60 +239,81 @@ impl Context {
} }
} }
} }
return self.send_by_key(buf, &route.route_key()).await; return Ok(route);
} }
Err(io::Error::new(io::ErrorKind::NotFound, "route not found")) Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
} }
pub fn try_send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> {
if let Some(v) = self.inner.route_table.get(id) {
if v.value().is_empty() {
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
}
let route = v.value()[0];
drop(v);
if let Some(udp) = self.inner.udp_map.get(&route.index) {
return udp.value().try_send_to(buf, route.addr);
}
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub async fn send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> { pub async fn send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
if route_key.index == 0 { match route_key.index {
if let Some(sender) = &self.inner.main_tcp_channel { TCP_ID => {
let mut vec = vec![0; 4 + buf.len()]; if let Some(sender) = &self.inner.main_tcp_channel {
vec[4..].copy_from_slice(buf); if sender.send(buf.to_vec()).await.is_ok() {
return if sender.send(vec).await.is_ok() { Ok(buf.len())
Ok(buf.len()) } else {
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
}
} else { } else {
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err")) Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
}; }
}
UDP_ID => self.inner.main_channel.send_to(buf, route_key.addr),
UDP_V6_ID => {
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
udp_ipv6.send_to(buf, route_key.addr)
} else {
Err(io::Error::new(io::ErrorKind::Other, "not ipv6 udp"))
}
}
_ => {
if let Some(udp) = self.get_udp_by_route(route_key) {
return udp.send_to(buf, route_key.addr).await;
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
} }
} }
if let Some(udp_ref) = self.inner.udp_map.get(&route_key.index) {
let udp = udp_ref.value().clone();
drop(udp_ref);
return udp.send_to(buf, route_key.addr).await;
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
} }
pub fn try_send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> { pub fn try_send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
if route_key.index == 0 { match route_key.index {
if let Some(sender) = &self.inner.main_tcp_channel { TCP_ID => {
let mut vec = vec![0; 4 + buf.len()]; if let Some(sender) = &self.inner.main_tcp_channel {
vec[4..].copy_from_slice(buf); if sender.try_send(buf.to_vec()).is_ok() {
return if sender.try_send(vec).is_ok() { Ok(buf.len())
Ok(buf.len()) } else {
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
}
} else { } else {
Err(io::Error::new(io::ErrorKind::Other, "try_send_by_key err")) Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
}; }
}
UDP_ID => self.inner.main_channel.send_to(buf, route_key.addr),
UDP_V6_ID => {
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
udp_ipv6.send_to(buf, route_key.addr)
} else {
Err(io::Error::new(io::ErrorKind::Other, "not ipv6 udp"))
}
}
_ => {
if let Some(udp) = self.get_udp_by_route(route_key) {
return udp.try_send_to(buf, route_key.addr);
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
} }
} }
if let Some(udp) = self.inner.udp_map.get(&route_key.index) {
return udp.value().try_send_to(buf, route_key.addr);
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
} }
fn get_udp_by_route(&self, route_key: &RouteKey) -> Option<Arc<UdpSocket>> {
let guard = &crossbeam_epoch::pin();
let udp_map = unsafe {
self.inner
.udp_map
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
udp_map.get(&route_key.index).cloned()
}
pub fn add_route_if_absent(&self, id: Ipv4Addr, route: Route) { pub fn add_route_if_absent(&self, id: Ipv4Addr, route: Route) {
self.add_route_(id, route, true) self.add_route_(id, route, true)
} }
@@ -242,120 +322,203 @@ impl Context {
} }
fn add_route_(&self, id: Ipv4Addr, route: Route, only_if_absent: bool) { fn add_route_(&self, id: Ipv4Addr, route: Route, only_if_absent: bool) {
let key = route.route_key(); let key = route.route_key();
let mut list = self let guard = &crossbeam_epoch::pin();
.inner let route_table = &self.inner.route_table;
.route_table let mut table_share = route_table.load(Ordering::Relaxed, guard);
.entry(id) loop {
.or_insert_with(|| Vec::with_capacity(4)); let mut table = unsafe { table_share.as_ref().unwrap().clone() };
let mut exist = false;
for x in list.iter_mut() { let list = table.entry(id).or_insert_with(|| Vec::with_capacity(4));
if x.metric < route.metric { let mut exist = false;
//不能比当前的路径更长 for x in list.iter_mut() {
return; if x.metric < route.metric {
} //不能比当前的路径更长
if x.route_key() == key {
if only_if_absent {
return; return;
} }
x.metric = route.metric; if x.route_key() == key {
x.rt = route.rt; if only_if_absent {
exist = true; return;
break; }
x.metric = route.metric;
x.rt = route.rt;
exist = true;
break;
}
} }
} if exist {
if exist { list.sort_by_key(|k| k.sort_key());
list.sort_by_key(|k| k.sort_key()); } else {
} else { if route.metric == 1 {
if route.metric == 1 { //添加了直连的则排除非直连的
//添加了直连的则排除非直连的 list.retain(|k| k.metric == 1);
list.retain(|k| k.metric == 1); }
list.push(route);
list.sort_by_key(|k| k.sort_key());
let max_len = self.inner.channel_num + 1;
if list.len() > max_len {
list.truncate(max_len);
}
} }
list.push(route); match route_table.compare_exchange(
list.sort_by_key(|k| k.sort_key()); table_share,
let max_len = self.inner.channel_num + 1; Owned::new(table),
if list.len() > max_len { Ordering::Relaxed,
list.truncate(max_len); Ordering::Relaxed,
guard,
) {
Ok(p) => unsafe {
guard.defer_destroy(p);
break;
},
Err(e) => {
table_share = e.current;
}
} }
} }
self.inner self.inner
.route_table_time .route_table_time
.insert((key, id), Instant::now()); .insert((key, id), Instant::now().sub(Duration::from_secs(10)));
} }
pub fn route(&self, id: &Ipv4Addr) -> Option<Vec<Route>> { pub fn route(&self, id: &Ipv4Addr) -> Option<Vec<Route>> {
if let Some(v) = self.inner.route_table.get(id) { let guard = &crossbeam_epoch::pin();
Some(v.value().clone()) let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
if let Some(v) = table.get(id) {
Some(v.clone())
} else { } else {
None None
} }
} }
pub fn route_one(&self, id: &Ipv4Addr) -> Option<Route> { pub fn route_one(&self, id: &Ipv4Addr) -> Option<Route> {
if let Some(v) = self.inner.route_table.get(id) { let guard = &crossbeam_epoch::pin();
v.value().first().map(|v| *v) let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
if let Some(v) = table.get(id) {
v.first().map(|v| *v)
} else { } else {
None None
} }
} }
pub fn route_to_id(&self, route_key: &RouteKey) -> Option<Ipv4Addr> { pub fn route_to_id(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
for x in self.inner.route_table.iter() { let guard = &crossbeam_epoch::pin();
for route in x.value() { let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
for (k, v) in table.iter() {
for route in v {
if &route.route_key() == route_key && route.is_p2p() { if &route.route_key() == route_key && route.is_p2p() {
return Some(*x.key()); return Some(*k);
} }
} }
} }
None None
} }
pub fn need_punch(&self, id: &Ipv4Addr) -> bool { pub fn need_punch(&self, id: &Ipv4Addr) -> bool {
if let Some(v) = self.inner.route_table.get(id) { let guard = &crossbeam_epoch::pin();
if v.value().iter().filter(|k| k.is_p2p()).count() >= self.inner.channel_num { let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
if let Some(v) = table.get(id) {
if v.iter().filter(|k| k.is_p2p()).count() >= self.inner.channel_num {
return false; return false;
} }
} }
true true
} }
pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec<Route>)> { pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec<Route>)> {
self.inner let guard = &crossbeam_epoch::pin();
.route_table let table = unsafe {
.iter() self.inner
.map(|k| (k.key().clone(), k.value().clone())) .route_table
.collect() .load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
table.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
} }
pub fn route_table_one(&self) -> Vec<(Ipv4Addr, Route)> { pub fn route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
let mut v = Vec::with_capacity(8); let mut list = Vec::with_capacity(8);
for x in self.inner.route_table.iter() { let guard = &crossbeam_epoch::pin();
if let Some(route) = x.value().first() { let table = unsafe {
v.push((*x.key(), *route)); self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
for (k, v) in table {
if let Some(route) = v.first() {
list.push((*k, *route));
} }
} }
v list
} }
pub fn direct_route_table_one(&self) -> Vec<(Ipv4Addr, Route)> { pub fn direct_route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
let mut v = Vec::with_capacity(8); let mut list = Vec::with_capacity(8);
for x in self.inner.route_table.iter() { let guard = &crossbeam_epoch::pin();
if let Some(route) = x.value().first() { let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
for (k, v) in table {
if let Some(route) = v.first() {
if route.metric == 1 { if route.metric == 1 {
v.push((*x.key(), *route)); list.push((*k, *route));
} }
} }
} }
v list
} }
pub fn remove_route_all(&self, id: &Ipv4Addr) {
if let Some((_, routes)) = self.inner.route_table.remove(id) { pub fn remove_route(&self, id: &Ipv4Addr, route_key: RouteKey) {
for x in routes { let guard = &crossbeam_epoch::pin();
self.inner.route_table_time.remove(&(x.route_key(), *id)); let route_table = &self.inner.route_table;
let mut table_share = route_table.load(Ordering::Relaxed, guard);
loop {
let mut table = unsafe { table_share.as_ref().unwrap().clone() };
if let Some(routes) = table.get_mut(id) {
routes.retain(|x| x.route_key() != route_key);
match route_table.compare_exchange(
table_share,
Owned::new(table),
Ordering::Relaxed,
Ordering::Relaxed,
guard,
) {
Ok(p) => unsafe {
guard.defer_destroy(p);
self.inner.route_table_time.remove(&(route_key, *id));
return;
},
Err(e) => {
table_share = e.current;
}
}
} }
} }
} }
pub fn remove_route(&self, id: &Ipv4Addr, route_key: RouteKey) {
if let Some(v) = self.inner.route_table.get(id) {
let mut routes = v.value().clone();
drop(v);
routes.retain(|x| x.route_key() != route_key);
self.inner.route_table.insert(*id, routes);
}
self.inner.route_table_time.remove(&(route_key, *id));
}
pub fn update_read_time(&self, id: &Ipv4Addr, route_key: &RouteKey) { pub fn update_read_time(&self, id: &Ipv4Addr, route_key: &RouteKey) {
if let Some(mut time) = self.inner.route_table_time.get_mut(&(*route_key, *id)) { if let Some(mut time) = self.inner.route_table_time.get_mut(&(*route_key, *id)) {
*time.value_mut() = Instant::now(); *time.value_mut() = Instant::now();
@@ -377,16 +540,16 @@ impl Channel {
#[derive(Clone)] #[derive(Clone)]
struct BufSenderGroup( struct BufSenderGroup(
usize, usize,
Vec<tokio::sync::mpsc::Sender<(Block<'static>, usize, usize, RouteKey)>>, Vec<std::sync::mpsc::SyncSender<(Vec<u8>, usize, usize, RouteKey)>>,
); );
struct BufReceiverGroup(Vec<tokio::sync::mpsc::Receiver<(Block<'static>, usize, usize, RouteKey)>>); struct BufReceiverGroup(Vec<std::sync::mpsc::Receiver<(Vec<u8>, usize, usize, RouteKey)>>);
impl BufSenderGroup { impl BufSenderGroup {
pub async fn send(&mut self, val: (Block<'static>, usize, usize, RouteKey)) -> bool { pub fn send(&mut self, val: (Vec<u8>, usize, usize, RouteKey)) -> bool {
let index = self.0 % self.1.len(); let index = self.0 % self.1.len();
self.0 = self.0.wrapping_add(1); self.0 = self.0.wrapping_add(1);
self.1[index].send(val).await.is_ok() self.1[index].send(val).is_ok()
} }
} }
@@ -395,7 +558,7 @@ fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) {
let mut buf_receiver_group = Vec::with_capacity(size); let mut buf_receiver_group = Vec::with_capacity(size);
for _ in 0..size { for _ in 0..size {
let (buf_sender, buf_receiver) = let (buf_sender, buf_receiver) =
tokio::sync::mpsc::channel::<(Block<'static, Vec<u8>>, usize, usize, RouteKey)>(10); std::sync::mpsc::sync_channel::<(Vec<u8>, usize, usize, RouteKey)>(1);
buf_sender_group.push(buf_sender); buf_sender_group.push(buf_sender);
buf_receiver_group.push(buf_receiver); buf_receiver_group.push(buf_receiver);
} }
@@ -408,14 +571,15 @@ fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) {
impl Channel { impl Channel {
async fn tcp_handle( async fn tcp_handle(
mut tcp_r: OwnedReadHalf, mut tcp_r: OwnedReadHalf,
mut buf_sender: BufSenderGroup, context: Context,
handler: ChannelDataHandler,
head_reserve: usize, head_reserve: usize,
) -> io::Result<()> { ) -> io::Result<()> {
let mut head = [0; 4]; let mut head = [0; 4];
let addr = tcp_r.peer_addr()?; let addr = tcp_r.peer_addr()?;
let key = RouteKey::new(0, addr); let key = RouteKey::new(TCP_ID, addr);
loop { loop {
let mut buf = POOL.alloc(4096); let mut buf = [0; 4096];
tcp_r.read_exact(&mut head).await?; tcp_r.read_exact(&mut head).await?;
let len = (((head[2] as u16) << 8) | head[3] as u16) as usize; let len = (((head[2] as u16) << 8) | head[3] as u16) as usize;
if len < 12 || len > buf.len() { if len < 12 || len > buf.len() {
@@ -427,15 +591,7 @@ impl Channel {
tcp_r tcp_r
.read_exact(&mut buf[head_reserve..head_reserve + len]) .read_exact(&mut buf[head_reserve..head_reserve + len])
.await?; .await?;
if !buf_sender handler.handle(&mut buf, head_reserve, head_reserve + len, key, &context);
.send((buf, head_reserve, head_reserve + len, key))
.await
{
return Err(io::Error::new(
io::ErrorKind::Other,
"buf_sender发送数据失败",
));
}
} }
} }
async fn start_tcp( async fn start_tcp(
@@ -443,14 +599,16 @@ impl Channel {
tcp_stream: TcpStream, tcp_stream: TcpStream,
mut receiver: tokio::sync::mpsc::Receiver<Vec<u8>>, mut receiver: tokio::sync::mpsc::Receiver<Vec<u8>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
buf_sender: BufSenderGroup, context: Context,
handler: ChannelDataHandler,
head_reserve: usize, head_reserve: usize,
) { ) {
let (tcp_r, mut tcp_w) = tcp_stream.into_split(); let (tcp_r, mut tcp_w) = tcp_stream.into_split();
{ {
let buf_sender = buf_sender.clone(); let context = context.clone();
let handler = handler.clone();
tokio::spawn(async move { tokio::spawn(async move {
if let Err(e) = Self::tcp_handle(tcp_r, buf_sender, head_reserve).await { if let Err(e) = Self::tcp_handle(tcp_r, context, handler, head_reserve).await {
log::info!("tcp链接断开:{:?}", e); log::info!("tcp链接断开:{:?}", e);
} }
}); });
@@ -480,9 +638,10 @@ impl Channel {
Ok(tcp_stream) => { Ok(tcp_stream) => {
let (r, w) = tcp_stream.into_split(); let (r, w) = tcp_stream.into_split();
tcp_w = w; tcp_w = w;
let buf_sender = buf_sender.clone(); let context = context.clone();
let handler = handler.clone();
tokio::spawn(async move { tokio::spawn(async move {
if let Err(e) = Self::tcp_handle(r, buf_sender, head_reserve).await { if let Err(e) = Self::tcp_handle(r, context,handler, head_reserve).await {
log::info!("tcp 链接断开:{:?}",e); log::info!("tcp 链接断开:{:?}",e);
} }
}); });
@@ -513,18 +672,22 @@ impl Channel {
let handler = self.handler.clone(); let handler = self.handler.clone();
let context = self.context; let context = self.context;
let main_channel = context.inner.main_channel.clone(); let main_channel = context.inner.main_channel.clone();
let buf_sender = if parallel > 1 || tcp.is_some() { let buf_sender = if parallel > 1 {
let (buf_sender, buf_receiver) = buf_channel_group(parallel); let (buf_sender, buf_receiver) = buf_channel_group(parallel);
for mut buf_receiver in buf_receiver.0 { let mut num = 0;
for buf_receiver in buf_receiver.0 {
let context = context.clone(); let context = context.clone();
let handler = handler.clone(); let handler = handler.clone();
tokio::spawn(async move { std::thread::Builder::new()
while let Some((mut buf, start, end, route_key)) = buf_receiver.recv().await { .name(format!("recv-handler-{}", num))
handler .spawn(move || {
.handle(&mut buf, start, end, route_key, &context) while let Ok((mut buf, start, end, route_key)) = buf_receiver.recv() {
.await; handler.handle(&mut buf, start, end, route_key, &context);
} }
}); log::warn!("异步处理停止");
})
.unwrap();
num += 1;
} }
Some(buf_sender) Some(buf_sender)
} else { } else {
@@ -536,30 +699,55 @@ impl Channel {
tcp_stream, tcp_stream,
receiver, receiver,
context.inner.current_device.clone(), context.inner.current_device.clone(),
buf_sender.clone().unwrap(), context.clone(),
handler.clone(),
head_reserve, head_reserve,
)); ));
} }
if let Some(main_channel_ipv6) = &context.inner.main_channel_ipv6 { if let Some(main_channel_ipv6) = &context.inner.main_channel_ipv6 {
tokio::spawn(Self::start_( let worker = worker.worker("main_channel_ipv6");
worker.worker("main_channel_ipv6"), let context = context.clone();
context.clone(), let main_channel_ipv6 = main_channel_ipv6.clone();
main_channel_ipv6.clone(), let handler = handler.clone();
handler.clone(), let buf_sender = buf_sender.clone();
buf_sender.clone(), std::thread::Builder::new()
head_reserve, .name("ipv6-recv".into())
true, .spawn(move || {
)); log::info!("启动udp v6");
Self::main_start_(
worker,
context,
UDP_V6_ID,
main_channel_ipv6,
handler,
buf_sender,
head_reserve,
)
})
.unwrap();
}
{
let worker = worker.worker("main_channel_1");
let context = context.clone();
let main_channel = main_channel.clone();
let handler = handler.clone();
let buf_sender = buf_sender.clone();
std::thread::Builder::new()
.name("ipv4-recv".into())
.spawn(move || {
log::info!("启动udp v4");
Self::main_start_(
worker,
context,
UDP_ID,
main_channel,
handler,
buf_sender,
head_reserve,
)
})
.unwrap();
} }
tokio::spawn(Self::start_(
worker.worker("main_channel_1"),
context.clone(),
main_channel.clone(),
handler.clone(),
buf_sender.clone(),
head_reserve,
true,
));
if relay { if relay {
worker.stop_wait().await; worker.stop_wait().await;
return; return;
@@ -611,6 +799,62 @@ impl Channel {
} }
worker.stop_all(); worker.stop_all();
} }
fn main_start_(
worker: VntWorker,
context: Context,
id: usize,
udp: Arc<StdUdpSocket>,
handler: ChannelDataHandler,
buf_sender: Option<BufSenderGroup>,
head_reserve: usize,
) {
match buf_sender {
None => {
let mut buf = [0; 4096];
loop {
match udp.recv_from(&mut buf[head_reserve..]) {
Ok((len, addr)) => {
let end = head_reserve + len;
if &buf[head_reserve..end] == b"stop" {
if context.is_close() {
break;
}
}
handler.handle(
&mut buf,
head_reserve,
end,
RouteKey::new(id, addr),
&context,
);
}
Err(e) => {
log::error!("udp :{:?}", e);
}
}
}
}
Some(mut buf_sender) => loop {
let mut buf = vec![0; 4096];
match udp.recv_from(&mut buf[head_reserve..]) {
Ok((len, addr)) => {
let end = head_reserve + len;
if &buf[head_reserve..end] == b"stop" {
if context.is_close() {
break;
}
}
buf_sender.send((buf, head_reserve, end, RouteKey::new(id, addr)));
}
Err(e) => {
log::error!("udp :{:?}", e);
}
}
},
}
worker.stop_all();
}
async fn start_( async fn start_(
mut worker: VntWorker, mut worker: VntWorker,
context: Context, context: Context,
@@ -624,12 +868,13 @@ impl Channel {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use std::os::windows::io::AsRawSocket; use std::os::windows::io::AsRawSocket;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let id = 1 + udp.as_raw_socket() as usize; let id = 3 + udp.as_raw_socket() as usize;
#[cfg(any(unix))] #[cfg(any(unix))]
use std::os::fd::AsRawFd; use std::os::fd::AsRawFd;
#[cfg(any(unix))] #[cfg(any(unix))]
let id = 1 + udp.as_raw_fd() as usize; let id = 3 + udp.as_raw_fd() as usize;
context.inner.udp_map.insert(id, udp.clone());
context.insert_udp(id, udp.clone());
match buf_sender { match buf_sender {
None => { None => {
let mut buf = [0; 4096]; let mut buf = [0; 4096];
@@ -638,7 +883,7 @@ impl Channel {
rs=udp.recv_from(&mut buf[head_reserve..])=>{ rs=udp.recv_from(&mut buf[head_reserve..])=>{
match rs { match rs {
Ok((len, addr)) => { Ok((len, addr)) => {
handler.handle(&mut buf, head_reserve, head_reserve + len, RouteKey::new(id, addr), &context).await; handler.handle(&mut buf, head_reserve, head_reserve + len, RouteKey::new(id, addr), &context);
} }
Err(e) => { Err(e) => {
log::error!("{:?}",e) log::error!("{:?}",e)
@@ -672,12 +917,12 @@ impl Channel {
} }
} }
Some(mut buf_sender) => loop { Some(mut buf_sender) => loop {
let mut buf = POOL.alloc(4096); let mut buf = vec![0; 4096];
tokio::select! { tokio::select! {
rs=udp.recv_from(&mut buf[head_reserve..])=>{ rs=udp.recv_from(&mut buf[head_reserve..])=>{
match rs { match rs {
Ok((len, addr)) => { Ok((len, addr)) => {
if !buf_sender.send((buf,head_reserve,head_reserve+len,RouteKey::new(id, addr))).await{ if !buf_sender.send((buf,head_reserve,head_reserve+len,RouteKey::new(id, addr))){
log::error!("udp buf_sender发送数据失败"); log::error!("udp buf_sender发送数据失败");
break; break;
} }
@@ -713,7 +958,7 @@ impl Channel {
} }
}, },
} }
context.inner.udp_map.remove(&id); context.remove_udp(id);
if is_core { if is_core {
worker.stop_all(); worker.stop_all();
} }
+7
View File
@@ -5,6 +5,10 @@ pub mod idle;
pub mod punch; pub mod punch;
pub mod sender; pub mod sender;
const TCP_ID: usize = 0;
const UDP_ID: usize = 1;
const UDP_V6_ID: usize = 2;
#[derive(Copy, Clone, Eq, PartialEq)] #[derive(Copy, Clone, Eq, PartialEq)]
pub enum Status { pub enum Status {
Cone, Cone,
@@ -70,4 +74,7 @@ impl RouteKey {
pub(crate) fn new(index: usize, addr: SocketAddr) -> Self { pub(crate) fn new(index: usize, addr: SocketAddr) -> Self {
Self { index, addr } Self { index, addr }
} }
pub fn is_tcp(&self) -> bool {
self.index == TCP_ID
}
} }
+11 -11
View File
@@ -50,9 +50,12 @@ impl NatInfo {
public_port_range: u16, public_port_range: u16,
local_ipv4_addr: SocketAddrV4, local_ipv4_addr: SocketAddrV4,
ipv6_addr: SocketAddrV6, ipv6_addr: SocketAddrV6,
nat_type: NatType, mut nat_type: NatType,
) -> Self { ) -> Self {
public_ips.retain(|ip| !ip.is_loopback() && !ip.is_private()); public_ips.retain(|ip| !ip.is_loopback() && !ip.is_private() && !ip.is_unspecified());
if public_ips.len() > 1 {
nat_type = NatType::Symmetric;
}
Self { Self {
public_ips, public_ips,
public_port, public_port,
@@ -95,8 +98,7 @@ impl Punch {
if !nat_info.local_ipv4_addr.ip().is_unspecified() && nat_info.local_ipv4_addr.port() != 0 { if !nat_info.local_ipv4_addr.ip().is_unspecified() && nat_info.local_ipv4_addr.port() != 0 {
let _ = self let _ = self
.context .context
.send_main_udp(buf, SocketAddr::V4(nat_info.local_ipv4_addr)) .send_main_udp(buf, SocketAddr::V4(nat_info.local_ipv4_addr));
.await;
} }
if self.punch_model != PunchModel::IPv4 if self.punch_model != PunchModel::IPv4
&& !nat_info.ipv6_addr.ip().is_unspecified() && !nat_info.ipv6_addr.ip().is_unspecified()
@@ -104,8 +106,7 @@ impl Punch {
{ {
let rs = self let rs = self
.context .context
.send_main_udp(buf, SocketAddr::V6(nat_info.ipv6_addr)) .send_main_udp(buf, SocketAddr::V6(nat_info.ipv6_addr));
.await;
log::info!("发送到ipv6地址:{:?},rs={:?}", nat_info.ipv6_addr, rs); log::info!("发送到ipv6地址:{:?},rs={:?}", nat_info.ipv6_addr, rs);
if rs.is_ok() && self.punch_model == PunchModel::IPv6 { if rs.is_ok() && self.punch_model == PunchModel::IPv6 {
return Ok(()); return Ok(());
@@ -167,11 +168,10 @@ impl Punch {
let is_cone = self.context.is_cone(); let is_cone = self.context.is_cone();
for ip in nat_info.public_ips { for ip in nat_info.public_ips {
let addr = SocketAddr::V4(SocketAddrV4::new(ip, nat_info.public_port)); let addr = SocketAddr::V4(SocketAddrV4::new(ip, nat_info.public_port));
if is_cone { self.context.send_main_udp(buf, addr)?;
self.context.send_main_udp(buf, addr).await?; if !is_cone {
} else {
//只有一方是对称,则对称方要使用全部端口发送数据,符合上述计算的概率 //只有一方是对称,则对称方要使用全部端口发送数据,符合上述计算的概率
self.context.send_all(buf, addr).await?; self.context.try_send_all(buf, addr)?;
} }
tokio::time::sleep(Duration::from_millis(2)).await; tokio::time::sleep(Duration::from_millis(2)).await;
} }
@@ -195,7 +195,7 @@ impl Punch {
return Ok(()); return Ok(());
} }
let addr = SocketAddr::V4(SocketAddrV4::new(*pub_ip, *port)); let addr = SocketAddr::V4(SocketAddrV4::new(*pub_ip, *port));
self.context.send_main_udp(buf, addr).await?; self.context.send_main_udp(buf, addr)?;
tokio::time::sleep(Duration::from_millis(2)).await; tokio::time::sleep(Duration::from_millis(2)).await;
} }
} }
+90 -73
View File
@@ -1,8 +1,6 @@
use crate::cipher::Finger; use crate::cipher::Finger;
use crate::protocol::body::AesCbcSecretBody;
use crate::protocol::{NetPacket, HEAD_LEN}; use crate::protocol::{NetPacket, HEAD_LEN};
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyInit}; use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyInit};
use rand::RngCore;
use std::io; use std::io;
type Aes128EcbEnc = ecb::Encryptor<aes::Aes128>; type Aes128EcbEnc = ecb::Encryptor<aes::Aes128>;
@@ -12,11 +10,11 @@ type Aes256EcbDec = ecb::Decryptor<aes::Aes256>;
#[derive(Clone)] #[derive(Clone)]
pub struct AesEcbCipher { pub struct AesEcbCipher {
pub(crate) cipher: AesEcbEnum, key: AesEcbEnum,
pub(crate) finger: Option<Finger>, pub(crate) finger: Option<Finger>,
} }
#[derive(Clone)] #[derive(Clone, Copy)]
pub enum AesEcbEnum { pub enum AesEcbEnum {
AES128ECB([u8; 16]), AES128ECB([u8; 16]),
AES256ECB([u8; 32]), AES256ECB([u8; 32]),
@@ -24,7 +22,7 @@ pub enum AesEcbEnum {
impl AesEcbCipher { impl AesEcbCipher {
pub fn key(&self) -> &[u8] { pub fn key(&self) -> &[u8] {
match &self.cipher { match &self.key {
AesEcbEnum::AES128ECB(key) => key, AesEcbEnum::AES128ECB(key) => key,
AesEcbEnum::AES256ECB(key) => key, AesEcbEnum::AES256ECB(key) => key,
} }
@@ -34,13 +32,13 @@ impl AesEcbCipher {
impl AesEcbCipher { impl AesEcbCipher {
pub fn new_128(key: [u8; 16], finger: Option<Finger>) -> Self { pub fn new_128(key: [u8; 16], finger: Option<Finger>) -> Self {
Self { Self {
cipher: AesEcbEnum::AES128ECB(key), key: AesEcbEnum::AES128ECB(key),
finger, finger,
} }
} }
pub fn new_256(key: [u8; 32], finger: Option<Finger>) -> Self { pub fn new_256(key: [u8; 32], finger: Option<Finger>) -> Self {
Self { Self {
cipher: AesEcbEnum::AES256ECB(key), key: AesEcbEnum::AES256ECB(key),
finger, finger,
} }
} }
@@ -53,46 +51,67 @@ impl AesEcbCipher {
//未加密的数据直接丢弃 //未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
} }
if let Some(finger) = &self.finger {
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 len = net_packet.payload().len();
if len < 12 {
return Err(io::Error::new(io::ErrorKind::Other, "payload len <12"));
}
let secret_body = &net_packet.payload()[..len - 12];
let finger = finger.calculate_finger(&nonce_raw, secret_body);
if &finger != &net_packet.payload()[len - 12..] {
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
}
net_packet.set_data_len(net_packet.data_len() - finger.len())?;
}
if net_packet.payload().len() < 16 { if net_packet.payload().len() < 16 {
log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16); log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16);
return Err(io::Error::new(io::ErrorKind::Other, "data err")); return Err(io::Error::new(io::ErrorKind::Other, "data err"));
} }
let mut iv = [0; 16]; let mut out = [0u8; 1024 * 5];
iv[0..4].copy_from_slice(&net_packet.source().octets()); let rs = match self.key {
iv[4..8].copy_from_slice(&net_packet.destination().octets()); AesEcbEnum::AES128ECB(key) => Aes128EcbDec::new(&key.into())
iv[8] = net_packet.protocol().into(); .decrypt_padded_b2b_mut::<Pkcs7>(net_packet.payload(), &mut out),
iv[9] = net_packet.transport_protocol(); AesEcbEnum::AES256ECB(key) => Aes256EcbDec::new(&key.into())
iv[10] = net_packet.is_gateway() as u8; .decrypt_padded_b2b_mut::<Pkcs7>(net_packet.payload(), &mut out),
iv[11] = net_packet.source_ttl();
if let Some(finger) = &self.finger {
iv[12..16].copy_from_slice(&finger.hash[0..4]);
}
let mut secret_body =
AesCbcSecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
if let Some(finger) = &self.finger {
let finger = finger.calculate_finger(&iv[..12], secret_body.en_body());
if &finger != secret_body.finger() {
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
}
}
let rs = match &self.cipher {
AesEcbEnum::AES128ECB(key) => Aes128EcbDec::new(&(*key).into())
.decrypt_padded_mut::<Pkcs7>(secret_body.en_body_mut()),
AesEcbEnum::AES256ECB(key) => Aes256EcbDec::new(&(*key).into())
.decrypt_padded_mut::<Pkcs7>(secret_body.en_body_mut()),
}; };
match rs { match rs {
Ok(buf) => { Ok(buf) => {
let len = buf.len(); //校验头部
let src_net_packet = NetPacket::new(buf)?;
if src_net_packet.source() != net_packet.source() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.destination() != net_packet.destination() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.protocol() != net_packet.protocol() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.transport_protocol() != net_packet.transport_protocol() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.is_gateway() != net_packet.is_gateway() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.source_ttl() != net_packet.source_ttl() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
net_packet.set_data_len(buf.len())?;
net_packet.set_payload(src_net_packet.payload())?;
net_packet.set_encrypt_flag(false); net_packet.set_encrypt_flag(false);
//减去末尾的随机数
net_packet.set_data_len(HEAD_LEN + len - 4)?;
Ok(()) Ok(())
} }
Err(e) => Err(io::Error::new( Err(e) => Err(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
format!("解密失败:{}", e), format!("aes_ecb解密失败:{}", e),
)), )),
} }
} }
@@ -102,53 +121,51 @@ impl AesEcbCipher {
&self, &self,
net_packet: &mut NetPacket<B>, net_packet: &mut NetPacket<B>,
) -> io::Result<()> { ) -> io::Result<()> {
let data_len = net_packet.data_len(); let mut out = [0u8; 1024 * 5];
let mut iv = [0; 16]; let rs = match self.key {
iv[0..4].copy_from_slice(&net_packet.source().octets()); AesEcbEnum::AES128ECB(key) => Aes128EcbEnc::new(&key.into())
iv[4..8].copy_from_slice(&net_packet.destination().octets()); .encrypt_padded_b2b_mut::<Pkcs7>(net_packet.buffer(), &mut out),
iv[8] = net_packet.protocol().into(); AesEcbEnum::AES256ECB(key) => Aes256EcbEnc::new(&key.into())
iv[9] = net_packet.transport_protocol(); .encrypt_padded_b2b_mut::<Pkcs7>(net_packet.buffer(), &mut out),
iv[10] = net_packet.is_gateway() as u8;
iv[11] = net_packet.source_ttl();
if let Some(finger) = &self.finger {
iv[12..16].copy_from_slice(&finger.hash[0..4]);
net_packet.set_data_len(data_len + 16)?;
} else {
net_packet.set_data_len(data_len + 4)?;
}
//先扩充随机数
let mut secret_body =
AesCbcSecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
secret_body.set_random(rand::thread_rng().next_u32());
let p_len = secret_body.en_body().len();
net_packet.set_data_len_max();
let rs = match &self.cipher {
AesEcbEnum::AES128ECB(key) => Aes128EcbEnc::new(&(*key).into())
.encrypt_padded_mut::<Pkcs7>(net_packet.payload_mut(), p_len),
AesEcbEnum::AES256ECB(key) => Aes256EcbEnc::new(&(*key).into())
.encrypt_padded_mut::<Pkcs7>(net_packet.payload_mut(), p_len),
}; };
return match rs { return match rs {
Ok(buf) => { Ok(buf) => {
let len = buf.len(); net_packet.set_data_len(HEAD_LEN + buf.len())?;
if let Some(finger) = &self.finger { net_packet.set_payload(buf)?;
let finger = finger.calculate_finger(&iv[..12], buf);
//设置实际长度
net_packet.set_data_len(HEAD_LEN + len + finger.len())?;
let mut secret_body = AesCbcSecretBody::new(net_packet.payload_mut(), true)?;
secret_body.set_finger(&finger)?;
} else {
net_packet.set_data_len(HEAD_LEN + len)?;
}
net_packet.set_encrypt_flag(true); net_packet.set_encrypt_flag(true);
if let Some(finger) = &self.finger {
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 finger = finger.calculate_finger(&nonce_raw, buf);
let src_data_len = net_packet.data_len();
//设置实际长度
net_packet.set_data_len(src_data_len + finger.len())?;
net_packet.buffer_mut()[src_data_len..].copy_from_slice(&finger);
}
Ok(()) Ok(())
} }
Err(e) => Err(io::Error::new( Err(e) => Err(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
format!("加密失败:{}", e), format!("aes_ecb加密失败:{}", e),
)), )),
}; };
} }
} }
#[test]
fn test_aes_ecb() {
let d = AesEcbCipher::new_128([0; 16], Some(Finger::new("123")));
let mut p = NetPacket::new_encrypt([0; 100]).unwrap();
let src = p.buffer().to_vec();
d.encrypt_ipv4(&mut p).unwrap();
d.decrypt_ipv4(&mut p).unwrap();
assert_eq!(p.buffer(), &src)
}
+6 -6
View File
@@ -6,7 +6,7 @@ use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, KeyInit, Nonce, Tag};
use rand::RngCore; use rand::RngCore;
use crate::cipher::finger::Finger; use crate::cipher::finger::Finger;
use crate::protocol::{body::SecretBody, body::ENCRYPTION_RESERVED, NetPacket}; use crate::protocol::{body::SecretBody, body::AES_GCM_ENCRYPTION_RESERVED, NetPacket};
#[derive(Clone)] #[derive(Clone)]
pub struct AesGcmCipher { pub struct AesGcmCipher {
@@ -44,8 +44,8 @@ impl AesGcmCipher {
//未加密的数据直接丢弃 //未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
} }
if net_packet.payload().len() < ENCRYPTION_RESERVED { if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED {
log::error!("数据异常,长度小于{}", ENCRYPTION_RESERVED); log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED);
return Err(io::Error::new(io::ErrorKind::Other, "data err")); return Err(io::Error::new(io::ErrorKind::Other, "data err"));
} }
let mut nonce_raw = [0; 12]; let mut nonce_raw = [0; 12];
@@ -81,7 +81,7 @@ impl AesGcmCipher {
)); ));
} }
net_packet.set_encrypt_flag(false); net_packet.set_encrypt_flag(false);
net_packet.set_data_len(net_packet.data_len() - ENCRYPTION_RESERVED)?; net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?;
return Ok(()); return Ok(());
} }
/// net_packet 必须预留足够长度 /// net_packet 必须预留足够长度
@@ -90,7 +90,7 @@ impl AesGcmCipher {
&self, &self,
net_packet: &mut NetPacket<B>, net_packet: &mut NetPacket<B>,
) -> io::Result<()> { ) -> io::Result<()> {
if net_packet.reserve() < ENCRYPTION_RESERVED { if net_packet.reserve() < AES_GCM_ENCRYPTION_RESERVED {
return Err(io::Error::new(io::ErrorKind::Other, "too short")); return Err(io::Error::new(io::ErrorKind::Other, "too short"));
} }
let mut nonce_raw = [0; 12]; let mut nonce_raw = [0; 12];
@@ -101,7 +101,7 @@ impl AesGcmCipher {
nonce_raw[10] = net_packet.is_gateway() as u8; nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl(); nonce_raw[11] = net_packet.source_ttl();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw); let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
let data_len = net_packet.data_len() + ENCRYPTION_RESERVED; let data_len = net_packet.data_len() + AES_GCM_ENCRYPTION_RESERVED;
net_packet.set_data_len(data_len)?; net_packet.set_data_len(data_len)?;
let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
secret_body.set_random(rand::thread_rng().next_u32()); secret_body.set_random(rand::thread_rng().next_u32());
+98 -13
View File
@@ -1,20 +1,37 @@
#[cfg(feature = "aes_ecb")]
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
use crate::cipher::aes_ecb::AesEcbCipher; use crate::cipher::aes_ecb::AesEcbCipher;
#[cfg(feature = "aes_cbc")]
use crate::cipher::aes_cbc::AesCbcCipher;
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
#[cfg(not(feature = "ring-cipher"))] #[cfg(not(feature = "ring-cipher"))]
use crate::cipher::aes_gcm_cipher::AesGcmCipher; use crate::cipher::aes_gcm_cipher::AesGcmCipher;
#[cfg(feature = "aes_ecb")]
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
use crate::cipher::openssl_aes_ecb::AesEcbCipher;
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
#[cfg(feature = "ring-cipher")] #[cfg(feature = "ring-cipher")]
use crate::cipher::ring_aes_gcm_cipher::AesGcmCipher; use crate::cipher::ring_aes_gcm_cipher::AesGcmCipher;
use crate::cipher::{aes_cbc, Finger}; #[cfg(feature = "sm4_cbc")]
use crate::cipher::sm4_cbc::Sm4CbcCipher;
use crate::cipher::Finger;
use crate::protocol::NetPacket; use crate::protocol::NetPacket;
use aes_cbc::AesCbcCipher;
use sha2::Digest; use sha2::Digest;
use std::io; use std::io;
use std::str::FromStr; use std::str::FromStr;
#[derive(Copy, Clone, Eq, PartialEq, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum CipherModel { pub enum CipherModel {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
AesGcm, AesGcm,
#[cfg(feature = "aes_cbc")]
AesCbc, AesCbc,
#[cfg(feature = "aes_ecb")]
AesEcb, AesEcb,
#[cfg(feature = "sm4_cbc")]
Sm4Cbc,
None,
} }
impl FromStr for CipherModel { impl FromStr for CipherModel {
@@ -22,19 +39,45 @@ impl FromStr for CipherModel {
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().trim() { match s.to_lowercase().trim() {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
"aes_gcm" => Ok(CipherModel::AesGcm), "aes_gcm" => Ok(CipherModel::AesGcm),
#[cfg(feature = "aes_cbc")]
"aes_cbc" => Ok(CipherModel::AesCbc), "aes_cbc" => Ok(CipherModel::AesCbc),
#[cfg(feature = "aes_ecb")]
"aes_ecb" => Ok(CipherModel::AesEcb), "aes_ecb" => Ok(CipherModel::AesEcb),
_ => Err(format!("not match '{}'", s)), #[cfg(feature = "sm4_cbc")]
"sm4_cbc" => Ok(CipherModel::Sm4Cbc),
_ => {
let mut enums = String::new();
#[cfg(feature = "aes_gcm")]
enums.push_str("/aes_gcm");
#[cfg(feature = "aes_cbc")]
enums.push_str("/aes_cbc");
#[cfg(feature = "aes_ecb")]
enums.push_str("/aes_ecb");
#[cfg(feature = "sm4_cbc")]
enums.push_str("/sm4_cbc");
let str = if enums.is_empty() {
"no encrypt"
} else {
&enums[1..]
};
Err(format!("not match '{}', enum:{}", s, str))
}
} }
} }
} }
#[derive(Clone)] #[derive(Clone)]
pub enum Cipher { pub enum Cipher {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
AesGcm((AesGcmCipher, Vec<u8>)), AesGcm((AesGcmCipher, Vec<u8>)),
#[cfg(feature = "aes_cbc")]
AesCbc(AesCbcCipher), AesCbc(AesCbcCipher),
#[cfg(feature = "aes_ecb")]
AesEcb(AesEcbCipher), AesEcb(AesEcbCipher),
#[cfg(feature = "sm4_cbc")]
Sm4Cbc(Sm4CbcCipher),
None, None,
} }
@@ -50,6 +93,7 @@ impl Cipher {
hasher.update(password.as_bytes()); hasher.update(password.as_bytes());
let key: [u8; 32] = hasher.finalize().into(); let key: [u8; 32] = hasher.finalize().into();
match model { match model {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
CipherModel::AesGcm => { CipherModel::AesGcm => {
if password.len() < 8 { if password.len() < 8 {
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger); let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
@@ -59,6 +103,7 @@ impl Cipher {
Cipher::AesGcm((aes, key.to_vec())) Cipher::AesGcm((aes, key.to_vec()))
} }
} }
#[cfg(feature = "aes_cbc")]
CipherModel::AesCbc => { CipherModel::AesCbc => {
if password.len() < 8 { if password.len() < 8 {
let aes = AesCbcCipher::new_128(key[..16].try_into().unwrap(), finger); let aes = AesCbcCipher::new_128(key[..16].try_into().unwrap(), finger);
@@ -68,6 +113,7 @@ impl Cipher {
Cipher::AesCbc(aes) Cipher::AesCbc(aes)
} }
} }
#[cfg(feature = "aes_ecb")]
CipherModel::AesEcb => { CipherModel::AesEcb => {
if password.len() < 8 { if password.len() < 8 {
let aes = AesEcbCipher::new_128(key[..16].try_into().unwrap(), finger); let aes = AesEcbCipher::new_128(key[..16].try_into().unwrap(), finger);
@@ -77,6 +123,12 @@ impl Cipher {
Cipher::AesEcb(aes) Cipher::AesEcb(aes)
} }
} }
#[cfg(feature = "sm4_cbc")]
CipherModel::Sm4Cbc => {
let aes = Sm4CbcCipher::new_128(key[..16].try_into().unwrap(), finger);
Cipher::Sm4Cbc(aes)
}
CipherModel::None => Cipher::None,
} }
} else { } else {
Cipher::None Cipher::None
@@ -85,10 +137,12 @@ impl Cipher {
pub fn new_key(key: [u8; 32], token: String) -> io::Result<Self> { pub fn new_key(key: [u8; 32], token: String) -> io::Result<Self> {
let finger = Some(Finger::new(&token)); let finger = Some(Finger::new(&token));
match key.len() { match key.len() {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
16 => { 16 => {
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger); let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
Ok(Cipher::AesGcm((aes, key[..16].to_vec()))) Ok(Cipher::AesGcm((aes, key[..16].to_vec())))
} }
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
32 => { 32 => {
let aes = AesGcmCipher::new_256(key, finger); let aes = AesGcmCipher::new_256(key, finger);
Ok(Cipher::AesGcm((aes, key.to_vec()))) Ok(Cipher::AesGcm((aes, key.to_vec())))
@@ -101,9 +155,14 @@ impl Cipher {
net_packet: &mut NetPacket<B>, net_packet: &mut NetPacket<B>,
) -> io::Result<()> { ) -> io::Result<()> {
match self { match self {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.decrypt_ipv4(net_packet), Cipher::AesGcm((aes_gcm, _)) => aes_gcm.decrypt_ipv4(net_packet),
#[cfg(feature = "aes_cbc")]
Cipher::AesCbc(aes_cbc) => aes_cbc.decrypt_ipv4(net_packet), Cipher::AesCbc(aes_cbc) => aes_cbc.decrypt_ipv4(net_packet),
#[cfg(feature = "aes_ecb")]
Cipher::AesEcb(aes_ecb) => aes_ecb.decrypt_ipv4(net_packet), Cipher::AesEcb(aes_ecb) => aes_ecb.decrypt_ipv4(net_packet),
#[cfg(feature = "sm4_cbc")]
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.decrypt_ipv4(net_packet),
Cipher::None => { Cipher::None => {
if net_packet.is_encrypt() { if net_packet.is_encrypt() {
return Err(io::Error::new(io::ErrorKind::Other, "not key")); return Err(io::Error::new(io::ErrorKind::Other, "not key"));
@@ -117,30 +176,56 @@ impl Cipher {
net_packet: &mut NetPacket<B>, net_packet: &mut NetPacket<B>,
) -> io::Result<()> { ) -> io::Result<()> {
match self { match self {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.encrypt_ipv4(net_packet), Cipher::AesGcm((aes_gcm, _)) => aes_gcm.encrypt_ipv4(net_packet),
#[cfg(feature = "aes_cbc")]
Cipher::AesCbc(aes_cbc) => aes_cbc.encrypt_ipv4(net_packet), Cipher::AesCbc(aes_cbc) => aes_cbc.encrypt_ipv4(net_packet),
#[cfg(feature = "aes_ecb")]
Cipher::AesEcb(aes_ecb) => aes_ecb.encrypt_ipv4(net_packet), Cipher::AesEcb(aes_ecb) => aes_ecb.encrypt_ipv4(net_packet),
#[cfg(feature = "sm4_cbc")]
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.encrypt_ipv4(net_packet),
Cipher::None => Ok(()), Cipher::None => Ok(()),
} }
} }
pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> io::Result<()> { pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> io::Result<()> {
let finger = match self { match self {
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.finger.as_ref(), #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
Cipher::AesCbc(aes_cbc) => aes_cbc.finger.as_ref(), Cipher::AesGcm((aes_gcm, _)) => aes_gcm
Cipher::AesEcb(aes_ecb) => aes_ecb.finger.as_ref(), .finger
Cipher::None => None, .as_ref()
}; .map(|f| f.check_finger(net_packet))
if let Some(finger) = finger { .unwrap_or(Ok(())),
finger.check_finger(net_packet) #[cfg(feature = "aes_cbc")]
} else { Cipher::AesCbc(aes_cbc) => aes_cbc
Ok(()) .finger
.as_ref()
.map(|f| f.check_finger(net_packet))
.unwrap_or(Ok(())),
#[cfg(feature = "aes_ecb")]
Cipher::AesEcb(aes_ecb) => aes_ecb
.finger
.as_ref()
.map(|f| f.check_finger(net_packet))
.unwrap_or(Ok(())),
#[cfg(feature = "sm4_cbc")]
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc
.finger
.as_ref()
.map(|f| f.check_finger(net_packet))
.unwrap_or(Ok(())),
Cipher::None => Ok(()),
} }
} }
pub fn key(&self) -> Option<&[u8]> { pub fn key(&self) -> Option<&[u8]> {
match self { match self {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
Cipher::AesGcm((_, key)) => Some(key), Cipher::AesGcm((_, key)) => Some(key),
#[cfg(feature = "aes_cbc")]
Cipher::AesCbc(aes_cbc) => Some(aes_cbc.key()), Cipher::AesCbc(aes_cbc) => Some(aes_cbc.key()),
#[cfg(feature = "aes_ecb")]
Cipher::AesEcb(aes_ecb) => Some(aes_ecb.key()), Cipher::AesEcb(aes_ecb) => Some(aes_ecb.key()),
#[cfg(feature = "sm4_cbc")]
Cipher::Sm4Cbc(sm4_cbc) => Some(sm4_cbc.key()),
Cipher::None => None, Cipher::None => None,
} }
} }
+10 -1
View File
@@ -1,13 +1,22 @@
#[cfg(feature = "aes_cbc")]
mod aes_cbc; mod aes_cbc;
#[cfg(feature = "aes_ecb")]
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
mod aes_ecb; mod aes_ecb;
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
#[cfg(not(feature = "ring-cipher"))] #[cfg(not(feature = "ring-cipher"))]
mod aes_gcm_cipher; mod aes_gcm_cipher;
mod cipher; mod cipher;
mod finger; mod finger;
#[cfg(feature = "aes_ecb")]
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
mod openssl_aes_ecb;
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
#[cfg(feature = "ring-cipher")] #[cfg(feature = "ring-cipher")]
mod ring_aes_gcm_cipher; mod ring_aes_gcm_cipher;
mod rsa_cipher; mod rsa_cipher;
#[cfg(feature = "sm4_cbc")]
mod sm4_cbc;
pub use cipher::Cipher; pub use cipher::Cipher;
pub use cipher::CipherModel; pub use cipher::CipherModel;
pub use finger::Finger; pub use finger::Finger;
+226
View File
@@ -0,0 +1,226 @@
use crate::cipher::Finger;
use crate::protocol::{NetPacket, HEAD_LEN};
use libc::c_int;
use openssl_sys::EVP_CIPHER_CTX;
use std::{io, ptr};
pub struct AesEcbCipher {
key: Vec<u8>,
pub(crate) en_ctx: *mut EVP_CIPHER_CTX,
pub(crate) de_ctx: *mut EVP_CIPHER_CTX,
pub(crate) finger: Option<Finger>,
}
impl Drop for AesEcbCipher {
fn drop(&mut self) {
unsafe {
openssl_sys::EVP_CIPHER_CTX_free(self.de_ctx);
openssl_sys::EVP_CIPHER_CTX_free(self.en_ctx);
}
}
}
impl Clone for AesEcbCipher {
fn clone(&self) -> Self {
if self.key.len() == 16 {
AesEcbCipher::new_128(self.key.clone().try_into().unwrap(), self.finger.clone())
} else {
AesEcbCipher::new_256(self.key.clone().try_into().unwrap(), self.finger.clone())
}
}
}
unsafe impl Sync for AesEcbCipher {}
unsafe impl Send for AesEcbCipher {}
impl AesEcbCipher {
pub fn key(&self) -> &[u8] {
&self.key
}
}
impl AesEcbCipher {
pub fn new_128(key: [u8; 16], finger: Option<Finger>) -> Self {
unsafe {
let cipher = openssl_sys::EVP_aes_128_ecb();
let en_ctx = openssl_sys::EVP_CIPHER_CTX_new();
openssl_sys::EVP_EncryptInit_ex(
en_ctx,
cipher,
ptr::null_mut(),
key.as_ptr(),
ptr::null(),
);
let de_ctx = openssl_sys::EVP_CIPHER_CTX_new();
openssl_sys::EVP_DecryptInit_ex(
de_ctx,
cipher,
ptr::null_mut(),
key.as_ptr(),
ptr::null(),
);
Self {
key: key.to_vec(),
en_ctx,
de_ctx,
finger,
}
}
}
pub fn new_256(key: [u8; 32], finger: Option<Finger>) -> Self {
unsafe {
let cipher = openssl_sys::EVP_aes_256_ecb();
let en_ctx = openssl_sys::EVP_CIPHER_CTX_new();
openssl_sys::EVP_EncryptInit_ex(
en_ctx,
cipher,
ptr::null_mut(),
key.as_ptr(),
ptr::null(),
);
let de_ctx = openssl_sys::EVP_CIPHER_CTX_new();
openssl_sys::EVP_DecryptInit_ex(
de_ctx,
cipher,
ptr::null_mut(),
key.as_ptr(),
ptr::null(),
);
Self {
key: key.to_vec(),
en_ctx,
de_ctx,
finger,
}
}
}
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
net_packet: &mut NetPacket<B>,
) -> io::Result<()> {
if !net_packet.is_encrypt() {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if let Some(finger) = &self.finger {
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 len = net_packet.payload().len();
if len < 12 {
return Err(io::Error::new(io::ErrorKind::Other, "data len err"));
}
let secret_body = &net_packet.payload()[..len - 12];
let finger = finger.calculate_finger(&nonce_raw, secret_body);
if &finger != &net_packet.payload()[len - 12..] {
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
}
net_packet.set_data_len(net_packet.data_len() - finger.len())?;
}
if net_packet.payload().len() < 16 {
log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let input = net_packet.payload();
let mut out = [0u8; 1024 * 5];
let mut out_len = 0;
let ctx = self.de_ctx;
unsafe {
let out_ptr = out.as_mut_ptr();
let in_len = input.len() as c_int;
openssl_sys::EVP_DecryptUpdate(ctx, out_ptr, &mut out_len, input.as_ptr(), in_len);
let mut last_len = 0;
openssl_sys::EVP_DecryptFinal_ex(ctx, out_ptr.offset(out_len as isize), &mut last_len);
out_len += last_len;
}
let out_len = out_len as usize;
let text = &out[..out_len];
{
//校验头部
let src_net_packet = NetPacket::new(text)?;
if src_net_packet.source() != net_packet.source() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.destination() != net_packet.destination() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.protocol() != net_packet.protocol() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.transport_protocol() != net_packet.transport_protocol() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.is_gateway() != net_packet.is_gateway() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.source_ttl() != net_packet.source_ttl() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
}
net_packet.set_encrypt_flag(false);
net_packet.set_data_len(out_len)?;
net_packet.set_payload(&text[12..])?;
Ok(())
}
/// net_packet 必须预留足够长度 大于 12+16+16
/// data_len是有效载荷的长度
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
net_packet: &mut NetPacket<B>,
) -> io::Result<()> {
let input = net_packet.buffer();
let mut out = [0u8; 1024 * 5];
let mut out_len = 0;
let ctx = self.en_ctx;
//将头部也参与加密
unsafe {
let out_ptr = out.as_mut_ptr();
let in_len = input.len() as c_int;
openssl_sys::EVP_EncryptUpdate(ctx, out_ptr, &mut out_len, input.as_ptr(), in_len);
let mut last_len = 0;
openssl_sys::EVP_EncryptFinal_ex(ctx, out_ptr.offset(out_len as isize), &mut last_len);
out_len += last_len;
}
let out_len = out_len as usize;
if out_len == 0 {
return Err(io::Error::new(io::ErrorKind::Other, "ciphertext len err"));
}
//密文
let ciphertext = &out[..out_len];
net_packet.set_data_len(HEAD_LEN + out_len)?;
net_packet.payload_mut().copy_from_slice(ciphertext);
net_packet.set_encrypt_flag(true);
if let Some(finger) = &self.finger {
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 finger = finger.calculate_finger(&nonce_raw, ciphertext);
let src_data_len = net_packet.data_len();
//设置实际长度
net_packet.set_data_len(src_data_len + finger.len())?;
net_packet.buffer_mut()[src_data_len..].copy_from_slice(&finger);
}
Ok(())
}
}
#[test]
fn test_openssl_aes_ecb() {
let d = AesEcbCipher::new_128([0; 16], Some(Finger::new("123")));
let mut p = NetPacket::new_encrypt([0; 100]).unwrap();
d.encrypt_ipv4(&mut p).unwrap();
d.decrypt_ipv4(&mut p).unwrap();
}
+5 -5
View File
@@ -4,7 +4,7 @@ use ring::aead;
use ring::aead::{LessSafeKey, UnboundKey}; use ring::aead::{LessSafeKey, UnboundKey};
use std::io; use std::io;
use crate::protocol::body::{SecretBody, ENCRYPTION_RESERVED}; use crate::protocol::body::{SecretBody, AES_GCM_ENCRYPTION_RESERVED};
use crate::protocol::NetPacket; use crate::protocol::NetPacket;
#[derive(Clone)] #[derive(Clone)]
@@ -58,8 +58,8 @@ impl AesGcmCipher {
//未加密的数据直接丢弃 //未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
} }
if net_packet.payload().len() < ENCRYPTION_RESERVED { if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED {
log::error!("数据异常,长度小于{}", ENCRYPTION_RESERVED); log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED);
return Err(io::Error::new(io::ErrorKind::Other, "data err")); return Err(io::Error::new(io::ErrorKind::Other, "data err"));
} }
let mut nonce_raw = [0; 12]; let mut nonce_raw = [0; 12];
@@ -93,7 +93,7 @@ impl AesGcmCipher {
)); ));
} }
net_packet.set_encrypt_flag(false); net_packet.set_encrypt_flag(false);
net_packet.set_data_len(net_packet.data_len() - ENCRYPTION_RESERVED)?; net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?;
return Ok(()); return Ok(());
} }
/// net_packet 必须预留足够长度 /// net_packet 必须预留足够长度
@@ -111,7 +111,7 @@ impl AesGcmCipher {
nonce_raw[10] = net_packet.is_gateway() as u8; nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl(); nonce_raw[11] = net_packet.source_ttl();
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw); let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
let data_len = net_packet.data_len() + ENCRYPTION_RESERVED; let data_len = net_packet.data_len() + AES_GCM_ENCRYPTION_RESERVED;
net_packet.set_data_len(data_len)?; net_packet.set_data_len(data_len)?;
let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
secret_body.set_random(rand::thread_rng().next_u32()); secret_body.set_random(rand::thread_rng().next_u32());
+35 -9
View File
@@ -1,23 +1,32 @@
use crate::protocol::body::{RsaSecretBody, ENCRYPTION_RESERVED};
use crate::protocol::NetPacket; use crate::protocol::NetPacket;
use rand::Rng;
use rsa::pkcs8::der::Decode;
use rsa::{PublicKey, RsaPublicKey};
use sha2::Digest;
use spki::{DecodePublicKey, EncodePublicKey};
use std::io; use std::io;
#[cfg(feature = "server_encrypt")]
use crate::protocol::body::{RsaSecretBody, RSA_ENCRYPTION_RESERVED};
#[cfg(feature = "server_encrypt")]
use rand::Rng;
#[cfg(feature = "server_encrypt")]
use rsa::pkcs8::der::Decode;
#[cfg(feature = "server_encrypt")]
use rsa::{PublicKey, RsaPublicKey};
#[cfg(feature = "server_encrypt")]
use sha2::Digest;
#[cfg(feature = "server_encrypt")]
use spki::{DecodePublicKey, EncodePublicKey};
#[derive(Clone)] #[derive(Clone)]
pub struct RsaCipher { pub struct RsaCipher {
#[cfg(feature = "server_encrypt")]
inner: Inner, inner: Inner,
} }
#[cfg(feature = "server_encrypt")]
#[derive(Clone)] #[derive(Clone)]
struct Inner { struct Inner {
public_key: RsaPublicKey, public_key: RsaPublicKey,
} }
impl RsaCipher { impl RsaCipher {
#[cfg(feature = "server_encrypt")]
pub fn new(der: &[u8]) -> io::Result<Self> { pub fn new(der: &[u8]) -> io::Result<Self> {
match RsaPublicKey::from_public_key_der(der) { match RsaPublicKey::from_public_key_der(der) {
Ok(public_key) => { Ok(public_key) => {
@@ -30,6 +39,11 @@ impl RsaCipher {
)), )),
} }
} }
#[cfg(not(feature = "server_encrypt"))]
pub fn new(_der: &[u8]) -> io::Result<Self> {
unimplemented!()
}
#[cfg(feature = "server_encrypt")]
pub fn finger(&self) -> io::Result<String> { pub fn finger(&self) -> io::Result<String> {
match self.inner.public_key.to_public_key_der() { match self.inner.public_key.to_public_key_der() {
Ok(der) => match rsa::pkcs8::SubjectPublicKeyInfo::from_der(der.as_bytes()) { Ok(der) => match rsa::pkcs8::SubjectPublicKeyInfo::from_der(der.as_bytes()) {
@@ -51,18 +65,30 @@ impl RsaCipher {
)), )),
} }
} }
#[cfg(not(feature = "server_encrypt"))]
pub fn finger(&self) -> io::Result<String> {
unimplemented!()
}
} }
impl RsaCipher { impl RsaCipher {
#[cfg(not(feature = "server_encrypt"))]
pub fn encrypt<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
_net_packet: &mut NetPacket<B>,
) -> io::Result<NetPacket<Vec<u8>>> {
unimplemented!()
}
#[cfg(feature = "server_encrypt")]
/// net_packet 必须预留足够长度 /// net_packet 必须预留足够长度
pub fn encrypt<B: AsRef<[u8]> + AsMut<[u8]>>( pub fn encrypt<B: AsRef<[u8]> + AsMut<[u8]>>(
&self, &self,
net_packet: &mut NetPacket<B>, net_packet: &mut NetPacket<B>,
) -> io::Result<NetPacket<Vec<u8>>> { ) -> io::Result<NetPacket<Vec<u8>>> {
if net_packet.reserve() < ENCRYPTION_RESERVED { if net_packet.reserve() < RSA_ENCRYPTION_RESERVED {
return Err(io::Error::new(io::ErrorKind::Other, "too short")); return Err(io::Error::new(io::ErrorKind::Other, "too short"));
} }
let data_len = net_packet.data_len() + ENCRYPTION_RESERVED; let data_len = net_packet.data_len() + RSA_ENCRYPTION_RESERVED;
net_packet.set_data_len(data_len)?; net_packet.set_data_len(data_len)?;
let mut nonce_raw = [0; 12]; let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
+171
View File
@@ -0,0 +1,171 @@
use crate::cipher::Finger;
use crate::protocol::{NetPacket, HEAD_LEN};
use libsm::sm4::cipher_mode::CipherMode;
use libsm::sm4::Sm4CipherMode;
use rand::RngCore;
use std::io;
pub struct Sm4CbcCipher {
key: [u8; 16],
pub(crate) cipher: Sm4CipherMode,
pub(crate) finger: Option<Finger>,
}
impl Clone for Sm4CbcCipher {
fn clone(&self) -> Self {
let cipher = Sm4CipherMode::new(&self.key, CipherMode::Cbc).unwrap();
Self {
key: self.key,
cipher,
finger: self.finger.clone(),
}
}
}
impl Sm4CbcCipher {
pub fn key(&self) -> &[u8] {
&self.key
}
}
impl Sm4CbcCipher {
pub fn new_128(key: [u8; 16], finger: Option<Finger>) -> Self {
let cipher = Sm4CipherMode::new(&key, CipherMode::Cbc).unwrap();
Self {
key,
cipher,
finger,
}
}
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
net_packet: &mut NetPacket<B>,
) -> io::Result<()> {
if !net_packet.is_encrypt() {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if let Some(finger) = &self.finger {
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 len = net_packet.payload().len();
if len < 12 {
return Err(io::Error::new(io::ErrorKind::Other, "payload len <12"));
}
let secret_body = &net_packet.payload()[..len - 12];
let finger = finger.calculate_finger(&nonce_raw, secret_body);
if &finger != &net_packet.payload()[len - 12..] {
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
}
net_packet.set_data_len(net_packet.data_len() - finger.len())?;
}
let payload = net_packet.payload();
let len = payload.len();
if len < 16 || len > 1024 * 4 {
log::error!("数据异常,长度{}小于16或大于4096", len);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let mut out = [0u8; 1024 * 4];
let data = &payload[..len - 16];
let iv = &payload[len - 16..];
match self.cipher.decrypt(data, iv, &mut out) {
Ok(len) => {
let src_net_packet = NetPacket::new(&out[..len])?;
if src_net_packet.source() != net_packet.source() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.destination() != net_packet.destination() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.protocol() != net_packet.protocol() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.transport_protocol() != net_packet.transport_protocol() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.is_gateway() != net_packet.is_gateway() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.source_ttl() != net_packet.source_ttl() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
net_packet.set_data_len(len)?;
net_packet.set_payload(src_net_packet.payload())?;
net_packet.set_encrypt_flag(false);
Ok(())
}
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("sm4_cbc解密失败:{}", e),
)),
}
}
/// net_packet 必须预留足够长度
/// data_len是有效载荷的长度
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
net_packet: &mut NetPacket<B>,
) -> io::Result<()> {
let mut out = [0u8; 1024 * 4];
let mut iv = [0u8; 16];
rand::thread_rng().fill_bytes(&mut iv);
if net_packet.data_len() > 1024 * 4 - 32 {
log::error!(
"数据异常,长度{}大于1024 * 4 - 32",
net_packet.buffer().len()
);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
match self.cipher.encrypt(net_packet.buffer(), &iv, &mut out) {
Ok(len) => {
net_packet.set_data_len(HEAD_LEN + len + 16)?;
net_packet.payload_mut()[..len].copy_from_slice(&out[..len]);
net_packet.payload_mut()[len..].copy_from_slice(&iv);
if let Some(finger) = &self.finger {
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
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 finger = finger.calculate_finger(&nonce_raw, net_packet.payload());
let src_data_len = net_packet.data_len();
//设置实际长度
net_packet.set_data_len(src_data_len + finger.len())?;
net_packet.buffer_mut()[src_data_len..].copy_from_slice(&finger);
}
net_packet.set_encrypt_flag(true);
Ok(())
}
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("sm4_cbc加密失败:{}", e),
)),
}
}
}
#[test]
fn test_sm4_ecb() {
let d = Sm4CbcCipher::new_128([0; 16], Some(Finger::new("123")));
let mut p = NetPacket::new_encrypt([1; 1024]).unwrap();
let src = p.buffer().to_vec();
d.encrypt_ipv4(&mut p).unwrap();
d.decrypt_ipv4(&mut p).unwrap();
assert_eq!(p.buffer(), &src);
let d = Sm4CbcCipher::new_128([0; 16], None);
let mut p = NetPacket::new_encrypt([1; 102]).unwrap();
let src = p.buffer().to_vec();
d.encrypt_ipv4(&mut p).unwrap();
d.decrypt_ipv4(&mut p).unwrap();
assert_eq!(p.buffer(), &src)
}
+54 -26
View File
@@ -7,7 +7,8 @@ use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap; use dashmap::DashMap;
use parking_lot::Mutex; use parking_lot::Mutex;
use rand::Rng; use rand::Rng;
use tokio::net::{TcpStream, UdpSocket}; use std::net::UdpSocket;
use tokio::net::TcpStream;
use tokio::sync::mpsc::channel; use tokio::sync::mpsc::channel;
use crate::channel::channel::{Channel, Context}; use crate::channel::channel::{Channel, Context};
@@ -30,6 +31,7 @@ use crate::handle::{
CurrentDeviceInfo, PeerDeviceInfo, CurrentDeviceInfo, PeerDeviceInfo,
}; };
use crate::igmp_server::IgmpServer; use crate::igmp_server::IgmpServer;
use crate::ip_proxy::DashMapNew;
use crate::nat::NatTest; use crate::nat::NatTest;
use crate::tun_tap_device; use crate::tun_tap_device;
use crate::tun_tap_device::{DeviceReader, DeviceWriter}; use crate::tun_tap_device::{DeviceReader, DeviceWriter};
@@ -66,13 +68,23 @@ pub struct VntUtil {
impl VntUtil { impl VntUtil {
pub async fn new(config: Config) -> io::Result<VntUtil> { pub async fn new(config: Config) -> io::Result<VntUtil> {
let main_channel = UdpSocket::bind("0.0.0.0:0").await?; //单个udp用同步的性能更好,但是代理和多端口监听用异步更方便,这里将两者结合起来
let main_channel_ipv6 = match UdpSocket::bind("[::]:0").await { let main_channel = UdpSocket::bind(format!("0.0.0.0:{}", config.port))?;
Ok(main_channel_ipv6) => Some(main_channel_ipv6), main_channel.set_write_timeout(Some(Duration::from_secs(5)))?;
Err(e) => { main_channel.set_read_timeout(Some(Duration::from_secs(2)))?;
log::warn!("绑定ipv6地址失败:{}", e); let main_channel_ipv6 = if config.punch_model != PunchModel::IPv4 {
None match UdpSocket::bind(format!("[::]:{}", config.port)) {
Ok(main_channel_ipv6) => {
main_channel_ipv6.set_write_timeout(Some(Duration::from_secs(5)))?;
Some(main_channel_ipv6)
}
Err(e) => {
log::warn!("绑定ipv6地址失败:{}", e);
None
}
} }
} else {
None
}; };
let server_cipher = if config.server_encrypt { let server_cipher = if config.server_encrypt {
let mut key = [0 as u8; 32]; let mut key = [0 as u8; 32];
@@ -181,7 +193,7 @@ impl VntUtil {
if self.config.password.is_none() { if self.config.password.is_none() {
1450 1450
} else { } else {
1420 1410
} }
} }
Some(mtu) => mtu, Some(mtu) => mtu,
@@ -205,6 +217,8 @@ impl VntUtil {
Ok(driver_info) Ok(driver_info)
} }
pub async fn build(self) -> crate::Result<Vnt> { pub async fn build(self) -> crate::Result<Vnt> {
//将读的超时时间清空
self.main_channel.set_read_timeout(None)?;
let response = match self.response { let response = match self.response {
None => { None => {
return Err(Error::Stop("response None".to_string())); return Err(Error::Stop("response None".to_string()));
@@ -266,9 +280,10 @@ impl VntUtil {
)); ));
let device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>> = let device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>> =
Arc::new(Mutex::new((response.epoch, response.device_info_list))); Arc::new(Mutex::new((response.epoch, response.device_info_list)));
let peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>> = Arc::new(DashMap::new()); let peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>> = Arc::new(DashMap::new0());
let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected)); let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected));
let public_ip = response.public_ip;
let public_port = response.public_port;
let local_port = context.main_local_ipv4_port().unwrap_or(0); let local_port = context.main_local_ipv4_port().unwrap_or(0);
let local_ipv4_addr = crate::nat::local_ipv4_addr(local_port); let local_ipv4_addr = crate::nat::local_ipv4_addr(local_port);
@@ -277,12 +292,11 @@ impl VntUtil {
// NAT检测 // NAT检测
let nat_test = NatTest::new( let nat_test = NatTest::new(
config.stun_server.clone(), config.stun_server.clone(),
response.public_ip, public_ip,
response.public_port, public_port,
local_ipv4_addr, local_ipv4_addr,
ipv6_addr, ipv6_addr,
) );
.await;
let in_external_route = if config.in_ips.is_empty() { let in_external_route = if config.in_ips.is_empty() {
None None
} else { } else {
@@ -292,8 +306,11 @@ impl VntUtil {
(None, None, None) (None, None, None)
} else { } else {
let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy( let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(
#[cfg(not(target_os = "android"))]
channel_sender.clone(), channel_sender.clone(),
#[cfg(not(target_os = "android"))]
current_device.clone(), current_device.clone(),
#[cfg(not(target_os = "android"))]
client_cipher.clone(), client_cipher.clone(),
) )
.await?; .await?;
@@ -334,8 +351,7 @@ impl VntUtil {
client_cipher.clone(), client_cipher.clone(),
self.server_cipher.clone(), self.server_cipher.clone(),
config.parallel, config.parallel,
) );
.await;
} }
#[cfg(any(target_os = "android"))] #[cfg(any(target_os = "android"))]
tun_handler::start( tun_handler::start(
@@ -350,8 +366,7 @@ impl VntUtil {
client_cipher.clone(), client_cipher.clone(),
self.server_cipher.clone(), self.server_cipher.clone(),
config.parallel, config.parallel,
) );
.await;
//外部数据接收处理 //外部数据接收处理
let channel_recv_handler = ChannelDataHandler::new( let channel_recv_handler = ChannelDataHandler::new(
@@ -388,12 +403,20 @@ impl VntUtil {
let device_list = device_list.clone(); let device_list = device_list.clone();
let current_device = current_device.clone(); let current_device = current_device.clone();
// 定时心跳 // 定时心跳
heartbeat_handler::start_heartbeat_main(
vnt_status_manager.worker("main-heartbeat"),
channel_sender.clone(),
device_list.clone(),
current_device.clone(),
config.server_address_str,
client_cipher.clone(),
self.server_cipher.clone(),
);
heartbeat_handler::start_heartbeat( heartbeat_handler::start_heartbeat(
vnt_status_manager.worker("heartbeat"), vnt_status_manager.worker("heartbeat"),
channel_sender.clone(), channel_sender.clone(),
device_list.clone(), device_list.clone(),
current_device.clone(), current_device.clone(),
config.server_address_str,
client_cipher.clone(), client_cipher.clone(),
self.server_cipher.clone(), self.server_cipher.clone(),
); );
@@ -439,10 +462,11 @@ impl VntUtil {
} }
let context = context.clone(); let context = context.clone();
let nat_test = nat_test.clone(); let nat_test = nat_test.clone();
//延迟切换类型,避免无效流量
tokio::spawn(async move { tokio::spawn(async move {
tokio::time::sleep(Duration::from_secs(15)).await; let info = nat_test
context.switch(nat_test.nat_info().nat_type); .re_test(public_ip, public_port, local_ipv4_addr, ipv6_addr)
.await;
context.switch(info.nat_type);
}); });
} }
Ok(Vnt { Ok(Vnt {
@@ -497,14 +521,15 @@ impl Vnt {
self.context.route_table_one() self.context.route_table_one()
} }
pub fn stop(&self) -> io::Result<()> { pub fn stop(&self) -> io::Result<()> {
self.context.close(); let _ = self.context.close();
self.vnt_status_manager.stop_all(); self.vnt_status_manager.stop_all();
self.device_writer.close()?; let _ = self.device_writer.close();
let virtual_gateway = self.current_device.load().virtual_gateway; let virtual_gateway = self.current_device.load().virtual_gateway;
let _ = std::net::UdpSocket::bind("0.0.0.0:0")?.send_to( let _ = UdpSocket::bind("0.0.0.0:0")?.send_to(
&[0], b"stop",
SocketAddr::V4(SocketAddrV4::new(virtual_gateway, 10000)), SocketAddr::V4(SocketAddrV4::new(virtual_gateway, 10000)),
); );
Ok(()) Ok(())
} }
pub async fn wait_stop(&mut self) { pub async fn wait_stop(&mut self) {
@@ -552,6 +577,7 @@ pub struct Config {
pub cipher_model: CipherModel, pub cipher_model: CipherModel,
pub finger: bool, pub finger: bool,
pub punch_model: PunchModel, pub punch_model: PunchModel,
pub port: u16,
} }
impl Config { impl Config {
@@ -576,6 +602,7 @@ impl Config {
cipher_model: CipherModel, cipher_model: CipherModel,
finger: bool, finger: bool,
punch_model: PunchModel, punch_model: PunchModel,
port: u16,
) -> Self { ) -> Self {
for x in stun_server.iter_mut() { for x in stun_server.iter_mut() {
if !x.contains(":") { if !x.contains(":") {
@@ -603,6 +630,7 @@ impl Config {
cipher_model, cipher_model,
finger, finger,
punch_model, punch_model,
port,
} }
} }
} }
+21 -27
View File
@@ -1,14 +1,15 @@
use std::net::SocketAddr; use std::net::SocketAddr;
use std::time::Duration;
use protobuf::Message; use protobuf::Message;
use std::net::UdpSocket;
use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpStream, UdpSocket}; use tokio::net::TcpStream;
use crate::channel::channel::Context; use crate::channel::channel::Context;
use crate::channel::RouteKey;
use crate::cipher::{Cipher, RsaCipher}; use crate::cipher::{Cipher, RsaCipher};
use crate::proto::message::{HandshakeRequest, HandshakeResponse, SecretHandshakeRequest}; use crate::proto::message::{HandshakeRequest, HandshakeResponse, SecretHandshakeRequest};
use crate::protocol::body::ENCRYPTION_RESERVED; use crate::protocol::body::RSA_ENCRYPTION_RESERVED;
use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL}; use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL};
pub enum HandshakeEnum { pub enum HandshakeEnum {
@@ -44,7 +45,10 @@ fn secret_handshake_request_packet(
request.token = token; request.token = token;
request.key = key.to_vec(); request.key = key.to_vec();
let bytes = request.write_to_bytes()?; let bytes = request.write_to_bytes()?;
let mut net_packet = NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?; let mut net_packet = NetPacket::new0(
12 + bytes.len(),
vec![0u8; 12 + bytes.len() + RSA_ENCRYPTION_RESERVED],
)?;
net_packet.set_version(Version::V1); net_packet.set_version(Version::V1);
net_packet.set_gateway_flag(true); net_packet.set_gateway_flag(true);
net_packet.set_protocol(Protocol::Service); net_packet.set_protocol(Protocol::Service);
@@ -166,26 +170,18 @@ async fn send_recv(
} }
Ok(len) Ok(len)
} else { } else {
if let Err(e) = main_channel.send_to(send_buf, server_address).await { if let Err(e) = main_channel.send_to(send_buf, server_address) {
return Err(HandshakeEnum::Other(format!("send error:{}", e))); return Err(HandshakeEnum::Other(format!("send error:{}", e)));
} }
match tokio::time::timeout(Duration::from_millis(300), main_channel.recv_from(recv_buf)) match main_channel.recv_from(recv_buf) {
.await Ok((len, addr)) => {
{ if server_address != addr {
Ok(rs) => match rs { Err(HandshakeEnum::Other(format!("invalid data,from {}", addr)))
Ok((len, addr)) => { } else {
if server_address != addr {
return Err(HandshakeEnum::Other(format!("invalid data,from {}", addr)));
}
Ok(len) Ok(len)
} }
Err(e) => {
return Err(HandshakeEnum::Other(format!("receiver error:{}", e)));
}
},
Err(_) => {
return Err(HandshakeEnum::Timeout);
} }
Err(e) => Err(HandshakeEnum::Other(format!("receiver error:{}", e))),
} }
} }
} }
@@ -241,22 +237,20 @@ pub async fn secret_handshake(
} }
} }
pub async fn secret_handshake_req( pub fn secret_handshake_req(
context: &Context, context: &Context,
server_address: SocketAddr, server_address: SocketAddr,
rsa_cipher: &RsaCipher, rsa_cipher: &RsaCipher,
server_cipher: &Cipher, server_cipher: &Cipher,
token: String, token: String,
route_key: &RouteKey,
) -> crate::Result<()> { ) -> crate::Result<()> {
let secret_packet = let secret_packet =
secret_handshake_request_packet(rsa_cipher, token, server_cipher.key().unwrap())?; secret_handshake_request_packet(rsa_cipher, token, server_cipher.key().unwrap())?;
context if route_key.is_tcp() {
.send_main(secret_packet.buffer(), server_address) context.send_main(secret_packet.buffer(), server_address)?;
.await?; } else {
if context.is_main_tcp() { context.send_main_udp(secret_packet.buffer(), server_address)?;
context
.send_main_udp(secret_packet.buffer(), server_address)
.await?;
} }
Ok(()) Ok(())
} }
+73 -37
View File
@@ -43,6 +43,28 @@ async fn start_idle_(idle: Idle, sender: ChannelSender) -> io::Result<()> {
} }
pub fn start_heartbeat( pub fn start_heartbeat(
mut worker: VntWorker,
sender: ChannelSender,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
client_cipher: Cipher,
server_cipher: Cipher,
) {
tokio::spawn(async move {
tokio::select! {
_=worker.stop_wait()=>{
return;
}
rs=start_heartbeat_(sender, device_list, current_device,client_cipher,server_cipher)=>{
if let Err(e) = rs {
log::warn!("心跳任务停止:{:?}", e);
}
}
}
worker.stop_all();
});
}
pub fn start_heartbeat_main(
mut worker: VntWorker, mut worker: VntWorker,
sender: ChannelSender, sender: ChannelSender,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
@@ -56,11 +78,11 @@ pub fn start_heartbeat(
_=worker.stop_wait()=>{ _=worker.stop_wait()=>{
return; return;
} }
rs=start_heartbeat_(sender, device_list, current_device,server_address_str,client_cipher,server_cipher)=>{ rs=start_heartbeat_main_(sender, device_list, current_device,server_address_str,client_cipher,server_cipher)=>{
if let Err(e) = rs { if let Err(e) = rs {
log::warn!("心跳任务停止:{:?}", e); log::warn!("心跳任务停止:{:?}", e);
} }
} }
} }
worker.stop_all(); worker.stop_all();
}); });
@@ -74,7 +96,7 @@ fn heartbeat_packet(
gateway: bool, gateway: bool,
src: Ipv4Addr, src: Ipv4Addr,
dest: Ipv4Addr, dest: Ipv4Addr,
) -> NetPacket<[u8; 48]> { ) -> NetPacket<[u8; 12 + 4 + ENCRYPTION_RESERVED]> {
let mut net_packet = NetPacket::new_encrypt([0u8; 12 + 4 + ENCRYPTION_RESERVED]).unwrap(); let mut net_packet = NetPacket::new_encrypt([0u8; 12 + 4 + ENCRYPTION_RESERVED]).unwrap();
net_packet.set_version(Version::V1); net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Control); net_packet.set_protocol(Protocol::Control);
@@ -97,7 +119,7 @@ fn heartbeat_packet(
net_packet net_packet
} }
async fn start_heartbeat_( async fn start_heartbeat_main_(
sender: ChannelSender, sender: ChannelSender,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
@@ -106,28 +128,14 @@ async fn start_heartbeat_(
server_cipher: Cipher, server_cipher: Cipher,
) -> io::Result<()> { ) -> io::Result<()> {
let mut count = 0; let mut count = 0;
log::info!("启动心跳任务"); log::info!("启动心跳任务");
loop { loop {
if sender.is_close() { if sender.is_close() {
return Ok(()); return Ok(());
} }
let mut current_dev = current_device.load(); let mut current_dev = current_device.load();
//如果和服务端使用tcp连接,则维持udp洞的频率要更高些 let src = current_dev.virtual_ip();
if (sender.is_main_tcp() && count % 2 == 0) || (!sender.is_main_tcp() && count % 20 == 1) { if count % 40 == 19 {
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());
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 {
if let Ok(mut addr) = server_address_str.to_socket_addrs() { if let Ok(mut addr) = server_address_str.to_socket_addrs() {
if let Some(addr) = addr.next() { if let Some(addr) = addr.next() {
if addr != current_dev.connect_server { if addr != current_dev.connect_server {
@@ -145,7 +153,6 @@ async fn start_heartbeat_(
} }
} }
} }
let src = current_dev.virtual_ip();
let server_packet = heartbeat_packet( let server_packet = heartbeat_packet(
MAX_TTL, MAX_TTL,
&device_list, &device_list,
@@ -155,12 +162,44 @@ async fn start_heartbeat_(
src, src,
current_dev.virtual_gateway, current_dev.virtual_gateway,
); );
if let Err(e) = sender if let Err(e) = sender.send_main(server_packet.buffer(), current_dev.connect_server) {
.send_main(server_packet.buffer(), current_dev.connect_server)
.await
{
log::warn!("connect_server:{:?},e:{:?}", current_dev.connect_server, e); log::warn!("connect_server:{:?},e:{:?}", current_dev.connect_server, e);
} }
count += 1;
tokio::time::sleep(Duration::from_millis(3000)).await;
}
}
async fn start_heartbeat_(
sender: ChannelSender,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
client_cipher: Cipher,
server_cipher: Cipher,
) -> io::Result<()> {
let mut count = 0;
log::info!("启动心跳任务");
loop {
if sender.is_close() {
return Ok(());
}
let current_dev = current_device.load();
//如果和服务端使用tcp连接,则维持udp洞的频率要更高些
if (sender.is_main_tcp() && count % 4 == 0) || (!sender.is_main_tcp() && count % 40 == 1) {
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());
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);
}
let src = current_dev.virtual_ip();
if count < 7 || count % 7 == 0 { if count < 7 || count % 7 == 0 {
let mut route_list: Option<Vec<(Ipv4Addr, Vec<Route>)>> = None; let mut route_list: Option<Vec<(Ipv4Addr, Vec<Route>)>> = None;
let peer_list = { device_list.lock().1.clone() }; let peer_list = { device_list.lock().1.clone() };
@@ -178,9 +217,8 @@ async fn start_heartbeat_(
peer.virtual_ip, peer.virtual_ip,
); );
if let Some(route) = sender.route_one(&peer.virtual_ip) { if let Some(route) = sender.route_one(&peer.virtual_ip) {
if let Err(e) = sender if let Err(e) =
.send_by_key(client_packet.buffer(), &route.route_key()) sender.try_send_by_key(client_packet.buffer(), &route.route_key())
.await
{ {
log::warn!("virtual_ip:{},route:{:?},e:{:?}", peer.virtual_ip, route, e); log::warn!("virtual_ip:{},route:{:?},e:{:?}", peer.virtual_ip, route, e);
} }
@@ -189,9 +227,8 @@ async fn start_heartbeat_(
} }
} else { } else {
//没有直连路由则发送到网关 //没有直连路由则发送到网关
if let Err(e) = sender if let Err(e) =
.send_main(client_packet.buffer(), current_dev.connect_server) sender.send_main(client_packet.buffer(), current_dev.connect_server)
.await
{ {
log::warn!( log::warn!(
"virtual_ip:{},connect_server:{:?},e:{:?}", "virtual_ip:{},connect_server:{:?},e:{:?}",
@@ -247,9 +284,8 @@ async fn start_heartbeat_(
*peer_ip, *peer_ip,
); );
for route in route_list { for route in route_list {
if let Err(e) = sender if let Err(e) =
.send_by_key(client_packet.buffer(), &route.route_key()) sender.try_send_by_key(client_packet.buffer(), &route.route_key())
.await
{ {
log::warn!("peer_ip:{:?},route:{:?},e:{:?}", peer_ip, route, e); log::warn!("peer_ip:{:?},route:{:?},e:{:?}", peer_ip, route, e);
} }
@@ -259,6 +295,6 @@ async fn start_heartbeat_(
} }
count += 1; count += 1;
tokio::time::sleep(Duration::from_millis(5000)).await; tokio::time::sleep(Duration::from_millis(3000)).await;
} }
} }
+1 -3
View File
@@ -137,9 +137,7 @@ async fn start_punch_(
info.virtual_ip, info.virtual_ip,
) )
.unwrap(); .unwrap();
let _ = sender let _ = sender.send_main(packet.buffer(), current_device.connect_server);
.send_main(packet.buffer(), current_device.connect_server)
.await;
} }
tokio::time::sleep(sleep_time).await; tokio::time::sleep(sleep_time).await;
Ok(()) Ok(())
+98 -99
View File
@@ -1,5 +1,6 @@
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant};
use crossbeam_utils::atomic::AtomicCell; use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap; use dashmap::DashMap;
@@ -7,7 +8,6 @@ use parking_lot::Mutex;
use protobuf::Message; use protobuf::Message;
use tokio::sync::mpsc::Sender; use tokio::sync::mpsc::Sender;
use packet::icmp::icmp::HeaderOther;
use packet::icmp::{icmp, Kind}; use packet::icmp::{icmp, Kind};
use packet::ip::ipv4; use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet; use packet::ip::ipv4::packet::IpV4Packet;
@@ -54,6 +54,7 @@ pub struct ChannelDataHandler {
rsa_cipher: Option<RsaCipher>, rsa_cipher: Option<RsaCipher>,
relay: bool, relay: bool,
token: String, token: String,
time: Arc<AtomicCell<Instant>>,
} }
impl ChannelDataHandler { impl ChannelDataHandler {
@@ -94,12 +95,13 @@ impl ChannelDataHandler {
rsa_cipher, rsa_cipher,
relay, relay,
token, token,
time: Arc::new(AtomicCell::new(Instant::now())),
} }
} }
} }
impl ChannelDataHandler { impl ChannelDataHandler {
pub async fn handle( pub fn handle(
&self, &self,
buf: &mut [u8], buf: &mut [u8],
start: usize, start: usize,
@@ -108,14 +110,14 @@ impl ChannelDataHandler {
context: &Context, context: &Context,
) { ) {
assert_eq!(start, 14); assert_eq!(start, 14);
match self.handle0(&mut buf[..end], &route_key, context).await { match self.handle0(&mut buf[..end], &route_key, context) {
Ok(_) => {} Ok(_) => {}
Err(e) => { Err(e) => {
log::warn!("{:?}", e); log::warn!("{:?}", e);
} }
} }
} }
async fn handle0( fn handle0(
&self, &self,
buf: &mut [u8], buf: &mut [u8],
route_key: &RouteKey, route_key: &RouteKey,
@@ -133,6 +135,7 @@ impl ChannelDataHandler {
&& !destination.is_multicast() && !destination.is_multicast()
&& destination != current_device.broadcast_address; && destination != current_device.broadcast_address;
if current_device.virtual_ip() != destination if current_device.virtual_ip() != destination
&& !net_packet.is_gateway()
&& not_broadcast && not_broadcast
&& !destination.is_unspecified() && !destination.is_unspecified()
{ {
@@ -144,17 +147,13 @@ impl ChannelDataHandler {
// 转发 // 转发
if let Some(route) = context.route_one(&destination) { if let Some(route) = context.route_one(&destination) {
if route.metric <= net_packet.ttl() { if route.metric <= net_packet.ttl() {
context context.try_send_by_key(net_packet.buffer(), &route.route_key())?;
.send_by_key(net_packet.buffer(), &route.route_key())
.await?;
} }
} else if (ttl > 1 || destination == current_device.virtual_gateway()) } else if (ttl > 1 || destination == current_device.virtual_gateway())
&& source != current_device.virtual_gateway() && source != current_device.virtual_gateway()
{ {
//网关默认要转发一次,生存时间不够的发到网关也会被丢弃 //网关默认要转发一次,生存时间不够的发到网关也会被丢弃
context context.send_main(net_packet.buffer(), current_device.connect_server)?;
.send_main(net_packet.buffer(), current_device.connect_server)
.await?;
} }
} }
return Ok(()); return Ok(());
@@ -165,21 +164,28 @@ impl ChannelDataHandler {
== crate::protocol::error_packet::Protocol::NoKey.into() == crate::protocol::error_packet::Protocol::NoKey.into()
{ {
if let Some(rsa_cipher) = &self.rsa_cipher { if let Some(rsa_cipher) = &self.rsa_cipher {
let last = self.time.load();
if last.elapsed() < Duration::from_secs(3)
|| self.time.compare_exchange(last, Instant::now()).is_err()
{
//短时间不重复上传服务端密钥
return Ok(());
}
log::warn!("上传服务端密钥");
secret_handshake_req( secret_handshake_req(
context, context,
current_device.connect_server, current_device.connect_server,
rsa_cipher, rsa_cipher,
&self.server_cipher, &self.server_cipher,
self.token.clone(), self.token.clone(),
) route_key,
.await?; )?;
} }
} else { } else {
//服务端解密 //服务端解密
self.server_cipher.decrypt_ipv4(&mut net_packet)?; self.server_cipher.decrypt_ipv4(&mut net_packet)?;
let data_len = net_packet.data_len(); let data_len = net_packet.data_len();
self.server_packet_handle(context, current_device, buf, data_len, route_key) self.server_packet_handle(context, current_device, buf, data_len, route_key)?;
.await?;
} }
return Ok(()); return Ok(());
} }
@@ -211,7 +217,7 @@ impl ChannelDataHandler {
net_packet.set_destination(source); net_packet.set_destination(source);
//不管加不加密,和接收到的数据长度都一致 //不管加不加密,和接收到的数据长度都一致
self.client_cipher.encrypt_ipv4(&mut net_packet)?; self.client_cipher.encrypt_ipv4(&mut net_packet)?;
context.send_by_key(net_packet.buffer(), route_key).await?; context.try_send_by_key(net_packet.buffer(), route_key)?;
return Ok(()); return Ok(());
} }
} }
@@ -263,13 +269,14 @@ impl ChannelDataHandler {
.udp_proxy_map .udp_proxy_map
.insert(key, SocketAddrV4::new(dest_ip, dest_port)); .insert(key, SocketAddrV4::new(dest_ip, dest_port));
} }
#[cfg(not(target_os = "android"))]
ipv4::protocol::Protocol::Icmp => { ipv4::protocol::Protocol::Icmp => {
let dest_ip = ipv4.destination_ip(); let dest_ip = ipv4.destination_ip();
//转发到代理目标地址 //转发到代理目标地址
let icmp_packet = let icmp_packet =
icmp::IcmpPacket::new(ipv4.payload())?; icmp::IcmpPacket::new(ipv4.payload())?;
match icmp_packet.header_other() { match icmp_packet.header_other() {
HeaderOther::Identifier(id, seq) => { icmp::HeaderOther::Identifier(id, seq) => {
ip_proxy_map ip_proxy_map
.icmp_proxy_map .icmp_proxy_map
.insert((dest_ip, id, seq), source); .insert((dest_ip, id, seq), source);
@@ -278,8 +285,10 @@ impl ChannelDataHandler {
} }
_ => { _ => {
log::warn!( log::warn!(
"不支持的ip代理Icmp协议:{}", "不支持的ip代理Icmp协议:{}->{}->{}",
destination source,
destination,
dest_ip
); );
return Err(Error::Warn( return Err(Error::Warn(
"不支持的ip代理Icmp协议".to_string(), "不支持的ip代理Icmp协议".to_string(),
@@ -288,18 +297,36 @@ impl ChannelDataHandler {
} }
} }
_ => { _ => {
log::warn!("不支持的ip代理ipv4协议:{}", destination); log::warn!(
"不支持的ip代理ipv4协议{:?}:{}->{}->{}",
ipv4.protocol(),
source,
destination,
ipv4.destination_ip()
);
return Err(Error::Warn( return Err(Error::Warn(
"不支持的ip代理ipv4协议".to_string(), "不支持的ip代理ipv4协议".to_string(),
)); ));
} }
} }
} else { } else {
log::warn!("没有ip代理规则:{}", destination); log::warn!(
"没有ip代理规则{:?}:{}->{}->{}",
ipv4.protocol(),
source,
destination,
ipv4.destination_ip()
);
return Err(Error::Warn("没有ip代理规则".to_string())); return Err(Error::Warn("没有ip代理规则".to_string()));
} }
} else { } else {
log::warn!("不支持ip代理:{}", destination); log::warn!(
"不支持ip代理{:?}:{}->{}->{}",
ipv4.protocol(),
source,
destination,
ipv4.destination_ip()
);
return Err(Error::Warn("不支持ip代理".to_string())); return Err(Error::Warn("不支持ip代理".to_string()));
} }
} }
@@ -317,12 +344,10 @@ impl ChannelDataHandler {
Protocol::Service => {} Protocol::Service => {}
Protocol::Error => {} Protocol::Error => {}
Protocol::Control => { Protocol::Control => {
self.control(context, current_device, source, net_packet, route_key) self.control(context, current_device, source, net_packet, route_key)?;
.await?;
} }
Protocol::OtherTurn => { Protocol::OtherTurn => {
self.other_turn(context, current_device, source, net_packet, route_key) self.other_turn(context, current_device, source, net_packet, route_key)?;
.await?;
} }
Protocol::UnKnow(e) => { Protocol::UnKnow(e) => {
log::info!("不支持的协议:{}", e); log::info!("不支持的协议:{}", e);
@@ -331,7 +356,7 @@ impl ChannelDataHandler {
Ok(()) Ok(())
} }
async fn pong_packet( fn pong_packet(
&self, &self,
gateway: bool, gateway: bool,
metric: u8, metric: u8,
@@ -360,14 +385,12 @@ impl ChannelDataHandler {
poll_device.set_protocol(Protocol::Service); poll_device.set_protocol(Protocol::Service);
poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into()); poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into());
self.server_cipher.encrypt_ipv4(&mut poll_device)?; self.server_cipher.encrypt_ipv4(&mut poll_device)?;
context context.send_main(poll_device.buffer(), current_device.connect_server)?;
.send_main(poll_device.buffer(), current_device.connect_server)
.await?;
} }
} }
Ok(()) Ok(())
} }
async fn control( fn control(
&self, &self,
context: &Context, context: &Context,
current_device: CurrentDeviceInfo, current_device: CurrentDeviceInfo,
@@ -383,7 +406,7 @@ impl ChannelDataHandler {
net_packet.set_destination(source); net_packet.set_destination(source);
net_packet.first_set_ttl(MAX_TTL); net_packet.first_set_ttl(MAX_TTL);
self.client_cipher.encrypt_ipv4(&mut net_packet)?; self.client_cipher.encrypt_ipv4(&mut net_packet)?;
context.send_by_key(net_packet.buffer(), route_key).await?; context.try_send_by_key(net_packet.buffer(), route_key)?;
let route = Route::from(*route_key, metric, 199); let route = Route::from(*route_key, metric, 199);
context.add_route_if_absent(source, route); context.add_route_if_absent(source, route);
} }
@@ -396,8 +419,7 @@ impl ChannelDataHandler {
source, source,
pong_packet, pong_packet,
route_key, route_key,
) )?;
.await?;
} }
ControlPacket::PunchRequest => { ControlPacket::PunchRequest => {
if self.relay { if self.relay {
@@ -409,7 +431,7 @@ impl ChannelDataHandler {
net_packet.set_destination(source); net_packet.set_destination(source);
net_packet.first_set_ttl(1); net_packet.first_set_ttl(1);
self.client_cipher.encrypt_ipv4(&mut net_packet)?; self.client_cipher.encrypt_ipv4(&mut net_packet)?;
context.send_by_key(net_packet.buffer(), route_key).await?; context.try_send_by_key(net_packet.buffer(), route_key)?;
let route = Route::from(*route_key, 1, 199); let route = Route::from(*route_key, 1, 199);
context.add_route_if_absent(source, route); context.add_route_if_absent(source, route);
} }
@@ -433,26 +455,17 @@ impl ChannelDataHandler {
addr_packet.set_ipv4(ipv4); addr_packet.set_ipv4(ipv4);
addr_packet.set_port(route_key.addr.port()); addr_packet.set_port(route_key.addr.port());
self.client_cipher.encrypt_ipv4(&mut packet)?; self.client_cipher.encrypt_ipv4(&mut packet)?;
context.send_by_key(packet.buffer(), route_key).await?; context.try_send_by_key(packet.buffer(), route_key)?;
} }
std::net::IpAddr::V6(_) => {} std::net::IpAddr::V6(_) => {}
}, },
ControlPacket::AddrResponse(addr_packet) => { ControlPacket::AddrResponse(addr_packet) => self
if !addr_packet.ipv4().is_multicast() .nat_test
&& !addr_packet.ipv4().is_broadcast() .update_addr(addr_packet.ipv4(), addr_packet.port()),
&& !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(()) Ok(())
} }
async fn other_turn( fn other_turn(
&self, &self,
context: &Context, context: &Context,
current_device: CurrentDeviceInfo, current_device: CurrentDeviceInfo,
@@ -533,14 +546,12 @@ impl ChannelDataHandler {
// let _ = context.try_send_main_udp(packet.buffer(), // let _ = context.try_send_main_udp(packet.buffer(),
// SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port))); // SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port)));
// } // }
if self.punch(source, peer_nat_info).await { if self.punch(source, peer_nat_info) {
self.client_cipher.encrypt_ipv4(&mut punch_packet)?; self.client_cipher.encrypt_ipv4(&mut punch_packet)?;
context context.try_send_by_key(punch_packet.buffer(), route_key)?;
.send_by_key(punch_packet.buffer(), route_key)
.await?;
} }
} else { } else {
self.punch(source, peer_nat_info).await; self.punch(source, peer_nat_info);
} }
} }
other_turn_packet::Protocol::Unknown(e) => { other_turn_packet::Protocol::Unknown(e) => {
@@ -549,7 +560,7 @@ impl ChannelDataHandler {
} }
Ok(()) Ok(())
} }
async fn punch(&self, peer_ip: Ipv4Addr, peer_nat_info: NatInfo) -> bool { fn punch(&self, peer_ip: Ipv4Addr, peer_nat_info: NatInfo) -> bool {
match peer_nat_info.nat_type { match peer_nat_info.nat_type {
NatType::Symmetric => self NatType::Symmetric => self
.symmetric_sender .symmetric_sender
@@ -562,7 +573,7 @@ impl ChannelDataHandler {
/// 处理服务端数据 /// 处理服务端数据
impl ChannelDataHandler { impl ChannelDataHandler {
async fn server_packet_handle( fn server_packet_handle(
&self, &self,
context: &Context, context: &Context,
current_device: CurrentDeviceInfo, current_device: CurrentDeviceInfo,
@@ -574,16 +585,13 @@ impl ChannelDataHandler {
let source = net_packet.source(); let source = net_packet.source();
match net_packet.protocol() { match net_packet.protocol() {
Protocol::Service => { Protocol::Service => {
self.service(context, current_device, net_packet, route_key) self.service(context, current_device, net_packet, route_key)?;
.await?;
} }
Protocol::Error => { Protocol::Error => {
self.error(context, current_device, source, net_packet, route_key) self.error(context, current_device, source, net_packet, route_key)?;
.await?;
} }
Protocol::Control => { Protocol::Control => {
self.control_gateway(context, current_device, net_packet, route_key) self.control_gateway(context, current_device, net_packet, route_key)?;
.await?;
} }
Protocol::IpTurn => { Protocol::IpTurn => {
match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) { match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) {
@@ -617,16 +625,13 @@ impl ChannelDataHandler {
} }
return Ok(()); return Ok(());
} }
async fn control_gateway( fn control_gateway(
&self, &self,
context: &Context, context: &Context,
current_device: CurrentDeviceInfo, current_device: CurrentDeviceInfo,
net_packet: NetPacket<&[u8]>, net_packet: NetPacket<&[u8]>,
route_key: &RouteKey, route_key: &RouteKey,
) -> crate::Result<()> { ) -> crate::Result<()> {
if net_packet.source() != current_device.virtual_gateway {
return Ok(());
}
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? { match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
ControlPacket::PongPacket(pong_packet) => { ControlPacket::PongPacket(pong_packet) => {
let metric = net_packet.source_ttl() - net_packet.ttl() + 1; let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
@@ -638,26 +643,16 @@ impl ChannelDataHandler {
net_packet.source(), net_packet.source(),
pong_packet, pong_packet,
route_key, 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())
}
} }
ControlPacket::AddrResponse(addr_packet) => self
.nat_test
.update_addr(addr_packet.ipv4(), addr_packet.port()),
_ => {} _ => {}
} }
Ok(()) Ok(())
} }
async fn service( fn service(
&self, &self,
context: &Context, context: &Context,
current_device: CurrentDeviceInfo, current_device: CurrentDeviceInfo,
@@ -669,23 +664,29 @@ impl ChannelDataHandler {
service_packet::Protocol::RegistrationResponse => { service_packet::Protocol::RegistrationResponse => {
let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?; let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?;
{ if self.nat_test.can_update() {
let context = context.clone(); let context = context.clone();
let nat_test = self.nat_test.clone(); let nat_test = self.nat_test.clone();
tokio::spawn(async move { std::thread::spawn(move || {
let local_port = context.main_local_ipv4_port().unwrap_or(0); tokio::runtime::Builder::new_current_thread()
let local_ipv4_addr = nat::local_ipv4_addr(local_port); .enable_all()
let local_port = context.main_local_ipv6_port().unwrap_or(0); .build()
let ipv6_addr = nat::local_ipv6_addr(local_port); .unwrap()
let nat_info = nat_test .block_on(async move {
.re_test( let local_port = context.main_local_ipv4_port().unwrap_or(0);
Ipv4Addr::from(response.public_ip), let local_ipv4_addr = nat::local_ipv4_addr(local_port);
response.public_port as u16, let local_port = context.main_local_ipv6_port().unwrap_or(0);
local_ipv4_addr, let ipv6_addr = nat::local_ipv6_addr(local_port);
ipv6_addr, let nat_info = nat_test
) .re_test(
.await; Ipv4Addr::from(response.public_ip),
context.switch(nat_info.nat_type); response.public_port as u16,
local_ipv4_addr,
ipv6_addr,
)
.await;
context.switch(nat_info.nat_type);
})
}); });
} }
let new_ip = Ipv4Addr::from(response.virtual_ip); let new_ip = Ipv4Addr::from(response.virtual_ip);
@@ -757,7 +758,7 @@ impl ChannelDataHandler {
} }
Ok(()) Ok(())
} }
async fn error( fn error(
&self, &self,
_context: &Context, _context: &Context,
current_device: CurrentDeviceInfo, current_device: CurrentDeviceInfo,
@@ -778,9 +779,7 @@ impl ChannelDataHandler {
} }
self.connect_status.store(ConnectStatus::Connecting); self.connect_status.store(ConnectStatus::Connecting);
self.register self.register.fast_register(current_device.virtual_ip)?;
.fast_register(current_device.virtual_ip)
.await?;
} }
InErrorPacket::AddressExhausted => { InErrorPacket::AddressExhausted => {
//地址用尽 //地址用尽
+14 -23
View File
@@ -6,8 +6,9 @@ use crate::channel::sender::ChannelSender;
use crate::cipher::Cipher; use crate::cipher::Cipher;
use crate::handle::PeerDeviceInfo; use crate::handle::PeerDeviceInfo;
use protobuf::Message; use protobuf::Message;
use std::net::UdpSocket;
use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpStream, UdpSocket}; use tokio::net::TcpStream;
use crate::proto::message::{RegistrationRequest, RegistrationResponse}; use crate::proto::message::{RegistrationRequest, RegistrationResponse};
use crate::protocol::body::ENCRYPTION_RESERVED; use crate::protocol::body::ENCRYPTION_RESERVED;
@@ -81,28 +82,18 @@ pub async fn registration(
} }
&mut recv_buf[4..len] &mut recv_buf[4..len]
} else { } else {
if let Err(e) = main_channel.send_to(buf, server_address).await { if let Err(e) = main_channel.send_to(buf, server_address) {
return Err(ReqEnum::Other(format!("send error:{}", e))); return Err(ReqEnum::Other(format!("send error:{}", e)));
} }
match tokio::time::timeout( match main_channel.recv_from(&mut recv_buf) {
Duration::from_millis(300), Ok((len, addr)) => {
main_channel.recv_from(&mut recv_buf), if server_address != addr {
) return Err(ReqEnum::Other(format!("invalid data,from {}", addr)));
.await
{
Ok(rs) => match rs {
Ok((len, addr)) => {
if server_address != addr {
return Err(ReqEnum::Other(format!("invalid data,from {}", addr)));
}
&mut recv_buf[..len]
} }
Err(e) => { &mut recv_buf[..len]
return Err(ReqEnum::Other(format!("receiver error:{}", e))); }
} Err(e) => {
}, return Err(ReqEnum::Other(format!("receiver error:{}", e)));
Err(_) => {
return Err(ReqEnum::Timeout);
} }
} }
}; };
@@ -236,9 +227,9 @@ impl Register {
client_secret, client_secret,
} }
} }
pub async fn fast_register(&self, ip: Ipv4Addr) -> crate::Result<()> { pub fn fast_register(&self, ip: Ipv4Addr) -> crate::Result<()> {
let last = self.time.load(); let last = self.time.load();
if last.elapsed() < Duration::from_secs(2) if last.elapsed() < Duration::from_secs(3)
|| self.time.compare_exchange(last, Instant::now()).is_err() || self.time.compare_exchange(last, Instant::now()).is_err()
{ {
//短时间不重复注册 //短时间不重复注册
@@ -256,7 +247,7 @@ impl Register {
self.client_secret, self.client_secret,
)?; )?;
let buf = request_packet.buffer(); let buf = request_packet.buffer();
self.sender.send_main(buf, self.server_address).await?; self.sender.send_main(buf, self.server_address)?;
Ok(()) Ok(())
} }
} }
+5 -7
View File
@@ -1,18 +1,16 @@
use byte_pool::Block;
#[derive(Clone)] #[derive(Clone)]
pub struct BufSenderGroup( pub struct BufSenderGroup(
usize, usize,
Vec<tokio::sync::mpsc::Sender<(Block<'static>, usize, usize)>>, Vec<std::sync::mpsc::SyncSender<(Vec<u8>, usize, usize)>>,
); );
pub struct BufReceiverGroup(pub Vec<tokio::sync::mpsc::Receiver<(Block<'static>, usize, usize)>>); pub struct BufReceiverGroup(pub Vec<std::sync::mpsc::Receiver<(Vec<u8>, usize, usize)>>);
impl BufSenderGroup { impl BufSenderGroup {
pub async fn send(&mut self, val: (Block<'static>, usize, usize)) -> bool { pub fn send(&mut self, val: (Vec<u8>, usize, usize)) -> bool {
let index = self.0 % self.1.len(); let index = self.0 % self.1.len();
self.0 = self.0.wrapping_add(1); self.0 = self.0.wrapping_add(1);
self.1[index].send(val).await.is_ok() self.1[index].send(val).is_ok()
} }
} }
@@ -21,7 +19,7 @@ pub fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) {
let mut buf_receiver_group = Vec::with_capacity(size); let mut buf_receiver_group = Vec::with_capacity(size);
for _ in 0..size { for _ in 0..size {
let (buf_sender, buf_receiver) = let (buf_sender, buf_receiver) =
tokio::sync::mpsc::channel::<(Block<'static>, usize, usize)>(10); std::sync::mpsc::sync_channel::<(Vec<u8>, usize, usize)>(1);
buf_sender_group.push(buf_sender); buf_sender_group.push(buf_sender);
buf_receiver_group.push(buf_receiver); buf_receiver_group.push(buf_receiver);
} }
+12 -25
View File
@@ -17,12 +17,13 @@ use parking_lot::RwLock;
use std::io; use std::io;
use std::net::{Ipv4Addr, SocketAddrV4}; use std::net::{Ipv4Addr, SocketAddrV4};
use std::sync::Arc; use std::sync::Arc;
pub mod channel_group; pub mod channel_group;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
pub mod tap_handler; pub mod tap_handler;
pub mod tun_handler; pub mod tun_handler;
async fn broadcast( fn broadcast(
server_cipher: &Cipher, server_cipher: &Cipher,
multicast_members: Option<Arc<RwLock<Multicast>>>, multicast_members: Option<Arc<RwLock<Multicast>>>,
sender: &ChannelSender, sender: &ChannelSender,
@@ -47,8 +48,7 @@ async fn broadcast(
} }
if route.is_p2p() if route.is_p2p()
&& sender && sender
.send_by_key(net_packet.buffer(), &route.route_key()) .try_send_by_key(net_packet.buffer(), &route.route_key())
.await
.is_ok() .is_ok()
{ {
peer_ips.push(peer_ip); peer_ips.push(peer_ip);
@@ -62,9 +62,7 @@ async fn broadcast(
} }
//转发到服务端的可选择广播,还要进行服务端加密 //转发到服务端的可选择广播,还要进行服务端加密
if peer_ips.is_empty() { if peer_ips.is_empty() {
sender sender.send_main(net_packet.buffer(), current_device.connect_server)?;
.send_main(net_packet.buffer(), current_device.connect_server)
.await?;
} else { } else {
let buf = vec![ let buf = vec![
0 as u8; 0 as u8;
@@ -85,9 +83,7 @@ async fn broadcast(
broadcast.set_address(&peer_ips)?; broadcast.set_address(&peer_ips)?;
broadcast.set_data(net_packet.buffer())?; broadcast.set_data(net_packet.buffer())?;
server_cipher.encrypt_ipv4(&mut server_packet)?; server_cipher.encrypt_ipv4(&mut server_packet)?;
sender sender.send_main(server_packet.buffer(), current_device.connect_server)?;
.send_main(server_packet.buffer(), current_device.connect_server)
.await?;
} }
Ok(()) Ok(())
} }
@@ -96,7 +92,7 @@ async fn broadcast(
/// |12字节开头|ip报文|至少1024字节结尾| /// |12字节开头|ip报文|至少1024字节结尾|
/// ///
#[inline] #[inline]
pub async fn base_handle( pub fn base_handle(
sender: &ChannelSender, sender: &ChannelSender,
buf: &mut [u8], buf: &mut [u8],
data_len: usize, //数据总长度=12+ip包长度 data_len: usize, //数据总长度=12+ip包长度
@@ -126,9 +122,7 @@ pub async fn base_handle(
if protocol == Protocol::Icmp { if protocol == Protocol::Icmp {
net_packet.set_gateway_flag(true); net_packet.set_gateway_flag(true);
server_cipher.encrypt_ipv4(&mut net_packet)?; server_cipher.encrypt_ipv4(&mut net_packet)?;
sender sender.send_main(net_packet.buffer(), current_device.connect_server)?;
.send_main(net_packet.buffer(), current_device.connect_server)
.await?;
} }
return Ok(()); return Ok(());
} }
@@ -140,9 +134,7 @@ pub async fn base_handle(
net_packet.set_destination(current_device.virtual_gateway); net_packet.set_destination(current_device.virtual_gateway);
net_packet.set_gateway_flag(true); net_packet.set_gateway_flag(true);
server_cipher.encrypt_ipv4(&mut net_packet)?; server_cipher.encrypt_ipv4(&mut net_packet)?;
sender sender.send_main(net_packet.buffer(), current_device.connect_server)?;
.send_main(net_packet.buffer(), current_device.connect_server)
.await?;
} }
} }
Protocol::Udp => { Protocol::Udp => {
@@ -160,8 +152,7 @@ pub async fn base_handle(
sender, sender,
&mut net_packet, &mut net_packet,
&current_device, &current_device,
) )?;
.await?;
} }
_ => {} _ => {}
} }
@@ -176,8 +167,7 @@ pub async fn base_handle(
sender, sender,
&mut net_packet, &mut net_packet,
&current_device, &current_device,
) )?;
.await?;
return Ok(()); return Ok(());
} }
if !check_dest( if !check_dest(
@@ -256,13 +246,10 @@ pub async fn base_handle(
client_cipher.encrypt_ipv4(&mut net_packet)?; client_cipher.encrypt_ipv4(&mut net_packet)?;
//优先发到直连到地址 //优先发到直连到地址
if sender if sender
.send_by_id(net_packet.buffer(), &dest_ip) .try_send_by_id(net_packet.buffer(), &dest_ip)
.await
.is_err() .is_err()
{ {
sender sender.send_main(net_packet.buffer(), current_device.connect_server)?;
.send_main(net_packet.buffer(), current_device.connect_server)
.await?;
} }
return Ok(()); return Ok(());
} }
+43 -58
View File
@@ -1,9 +1,7 @@
use byte_pool::BytePool;
use std::sync::Arc; use std::sync::Arc;
use std::{io, thread}; use std::{io, thread};
use crossbeam_utils::atomic::AtomicCell; use crossbeam_utils::atomic::AtomicCell;
use lazy_static::lazy_static;
use packet::arp::arp::ArpPacket; use packet::arp::arp::ArpPacket;
use packet::ethernet; use packet::ethernet;
@@ -22,9 +20,6 @@ use crate::handle::CurrentDeviceInfo;
use crate::igmp_server::IgmpServer; use crate::igmp_server::IgmpServer;
use crate::ip_proxy::IpProxyMap; use crate::ip_proxy::IpProxyMap;
use crate::tun_tap_device::{DeviceReader, DeviceWriter}; use crate::tun_tap_device::{DeviceReader, DeviceWriter};
lazy_static! {
static ref POOL: BytePool<Vec<u8>> = BytePool::<Vec<u8>>::new();
}
pub fn start( pub fn start(
worker: VntWorker, worker: VntWorker,
@@ -43,33 +38,27 @@ pub fn start(
thread::Builder::new() thread::Builder::new()
.name("tap_handler".into()) .name("tap_handler".into())
.spawn(move || { .spawn(move || {
tokio::runtime::Builder::new_current_thread() if let Err(e) = start_simple(
.enable_all() &sender,
.build() device_reader,
.unwrap() &device_writer,
.block_on(async move { igmp_server,
if let Err(e) = start_simple( current_device,
sender, ip_route,
device_reader, ip_proxy_map,
device_writer, client_cipher,
igmp_server, server_cipher,
current_device, ) {
ip_route, log::warn!("tap:{:?}", e);
ip_proxy_map, }
client_cipher, let _ = sender.close();
server_cipher, let _ = device_writer.close();
) worker.stop_all();
.await
{
log::warn!("tap:{:?}", e);
}
worker.stop_all();
});
}) })
.unwrap(); .unwrap();
} else { } else {
let (buf_sender, buf_receiver) = buf_channel_group(parallel); let (buf_sender, buf_receiver) = buf_channel_group(parallel);
for mut buf_receiver in buf_receiver.0 { for buf_receiver in buf_receiver.0 {
let sender = sender.clone(); let sender = sender.clone();
let device_writer = device_writer.clone(); let device_writer = device_writer.clone();
let igmp_server = igmp_server.clone(); let igmp_server = igmp_server.clone();
@@ -78,8 +67,8 @@ pub fn start(
let ip_proxy_map = ip_proxy_map.clone(); let ip_proxy_map = ip_proxy_map.clone();
let client_cipher = client_cipher.clone(); let client_cipher = client_cipher.clone();
let server_cipher = server_cipher.clone(); let server_cipher = server_cipher.clone();
tokio::spawn(async move { thread::spawn(move || {
while let Some((mut buf, _, len)) = buf_receiver.recv().await { while let Ok((mut buf, _, len)) = buf_receiver.recv() {
match handle( match handle(
&mut buf, &mut buf,
len, len,
@@ -91,48 +80,44 @@ pub fn start(
&ip_proxy_map, &ip_proxy_map,
&client_cipher, &client_cipher,
&server_cipher, &server_cipher,
) ) {
.await
{
Ok(_) => {} Ok(_) => {}
Err(e) => { Err(e) => {
log::warn!("{:?}", e) log::warn!("{:?}", e)
} }
} }
} }
let _ = sender.close();
let _ = device_writer.close();
}); });
} }
thread::Builder::new() thread::Builder::new()
.name("tap_handler".into()) .name("tap_handler".into())
.spawn(move || { .spawn(move || {
tokio::runtime::Builder::new_current_thread() if let Err(e) = start_(&sender, device_reader, buf_sender) {
.enable_all() log::warn!("tap:{:?}", e);
.build() }
.unwrap() let _ = sender.close();
.block_on(async move { let _ = device_writer.close();
if let Err(e) = start_(sender, device_reader, buf_sender).await { worker.stop_all();
log::warn!("tap:{:?}", e);
}
worker.stop_all();
});
}) })
.unwrap(); .unwrap();
} }
} }
async fn start_( fn start_(
sender: ChannelSender, sender: &ChannelSender,
device_reader: DeviceReader, device_reader: DeviceReader,
mut buf_sender: BufSenderGroup, mut buf_sender: BufSenderGroup,
) -> io::Result<()> { ) -> io::Result<()> {
loop { loop {
let mut buf = POOL.alloc(4096); let mut buf = vec![0; 4096];
if sender.is_close() { if sender.is_close() {
return Ok(()); return Ok(());
} }
let start = 0; let start = 0;
let len = device_reader.read(&mut buf)?; let len = device_reader.read(&mut buf)?;
if !buf_sender.send((buf, start, len)).await { if !buf_sender.send((buf, start, len)) {
return Err(io::Error::new( return Err(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
"tap buf_sender发送失败", "tap buf_sender发送失败",
@@ -141,10 +126,10 @@ async fn start_(
} }
} }
async fn start_simple( fn start_simple(
sender: ChannelSender, sender: &ChannelSender,
device_reader: DeviceReader, device_reader: DeviceReader,
device_writer: DeviceWriter, device_writer: &DeviceWriter,
igmp_server: Option<IgmpServer>, igmp_server: Option<IgmpServer>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: Option<ExternalRoute>, ip_route: Option<ExternalRoute>,
@@ -154,27 +139,28 @@ async fn start_simple(
) -> io::Result<()> { ) -> io::Result<()> {
let mut buf = [0; 4096]; let mut buf = [0; 4096];
loop { loop {
if sender.is_close() {
return Ok(());
}
let len = device_reader.read(&mut buf)?; let len = device_reader.read(&mut buf)?;
if let Err(e) = handle( if let Err(e) = handle(
&mut buf, &mut buf,
len, len,
&igmp_server, &igmp_server,
&current_device, &current_device,
&device_writer, device_writer,
&sender, sender,
&ip_route, &ip_route,
&ip_proxy_map, &ip_proxy_map,
&client_cipher, &client_cipher,
&server_cipher, &server_cipher,
) ) {
.await
{
log::warn!("tap handle{:?}", e); log::warn!("tap handle{:?}", e);
} }
} }
} }
async fn handle( fn handle(
buf: &mut [u8], buf: &mut [u8],
len: usize, len: usize,
igmp_server: &Option<IgmpServer>, igmp_server: &Option<IgmpServer>,
@@ -261,8 +247,7 @@ async fn handle(
proxy_map, proxy_map,
client_cipher, client_cipher,
server_cipher, server_cipher,
) );
.await;
} }
_ => { _ => {
// log::warn!("不支持的二层协议:{:?}",p) // log::warn!("不支持的二层协议:{:?}",p)
+39 -58
View File
@@ -1,4 +1,3 @@
use byte_pool::BytePool;
use std::sync::Arc; use std::sync::Arc;
use std::{io, thread}; use std::{io, thread};
@@ -19,9 +18,6 @@ use crate::handle::CurrentDeviceInfo;
use crate::igmp_server::IgmpServer; use crate::igmp_server::IgmpServer;
use crate::ip_proxy::IpProxyMap; use crate::ip_proxy::IpProxyMap;
use crate::tun_tap_device::{DeviceReader, DeviceWriter}; use crate::tun_tap_device::{DeviceReader, DeviceWriter};
lazy_static::lazy_static! {
static ref POOL:BytePool<Vec<u8>> = BytePool::<Vec<u8>>::new();
}
fn icmp(device_writer: &DeviceWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Result<()> { fn icmp(device_writer: &DeviceWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Result<()> {
if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp { if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp {
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?; let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
@@ -40,7 +36,7 @@ fn icmp(device_writer: &DeviceWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) ->
/// 接收tun数据,并且转发到udp上 /// 接收tun数据,并且转发到udp上
#[inline] #[inline]
async fn handle( fn handle(
sender: &ChannelSender, sender: &ChannelSender,
data: &mut [u8], data: &mut [u8],
len: usize, len: usize,
@@ -75,11 +71,10 @@ async fn handle(
proxy_map, proxy_map,
client_cipher, client_cipher,
server_cipher, server_cipher,
) );
.await;
} }
pub async fn start( pub fn start(
worker: VntWorker, worker: VntWorker,
sender: ChannelSender, sender: ChannelSender,
device_reader: DeviceReader, device_reader: DeviceReader,
@@ -96,34 +91,27 @@ pub async fn start(
thread::Builder::new() thread::Builder::new()
.name("tun_handler".into()) .name("tun_handler".into())
.spawn(move || { .spawn(move || {
tokio::runtime::Builder::new_current_thread() if let Err(e) = start_simple(
.enable_all() &sender,
.build() device_reader,
.unwrap() &device_writer,
.block_on(async move { igmp_server,
if let Err(e) = start_simple( current_device,
sender, ip_route,
device_reader, ip_proxy_map,
&device_writer, client_cipher,
igmp_server, server_cipher,
current_device, ) {
ip_route, log::warn!("stop:{}", e);
ip_proxy_map, }
client_cipher, let _ = sender.close();
server_cipher, let _ = device_writer.close();
) worker.stop_all();
.await
{
log::warn!("stop:{}", e);
}
let _ = device_writer.close();
worker.stop_all();
})
}) })
.unwrap(); .unwrap();
} else { } else {
let (buf_sender, buf_receiver) = buf_channel_group(parallel); let (buf_sender, buf_receiver) = buf_channel_group(parallel);
for mut buf_receiver in buf_receiver.0 { for buf_receiver in buf_receiver.0 {
let sender = sender.clone(); let sender = sender.clone();
let device_writer = device_writer.clone(); let device_writer = device_writer.clone();
let igmp_server = igmp_server.clone(); let igmp_server = igmp_server.clone();
@@ -132,8 +120,8 @@ pub async fn start(
let ip_proxy_map = ip_proxy_map.clone(); let ip_proxy_map = ip_proxy_map.clone();
let client_cipher = client_cipher.clone(); let client_cipher = client_cipher.clone();
let server_cipher = server_cipher.clone(); let server_cipher = server_cipher.clone();
tokio::spawn(async move { thread::spawn(move || {
while let Some((mut buf, start, len)) = buf_receiver.recv().await { while let Ok((mut buf, start, len)) = buf_receiver.recv() {
match handle( match handle(
&sender, &sender,
&mut buf[start..], &mut buf[start..],
@@ -145,44 +133,39 @@ pub async fn start(
&ip_proxy_map, &ip_proxy_map,
&client_cipher, &client_cipher,
&server_cipher, &server_cipher,
) ) {
.await
{
Ok(_) => {} Ok(_) => {}
Err(e) => { Err(e) => {
log::warn!("{:?}", e) log::warn!("{:?}", e)
} }
} }
} }
let _ = sender.close();
let _ = device_writer.close();
}); });
} }
thread::Builder::new() thread::Builder::new()
.name("tun_handler".into()) .name("tun_handler".into())
.spawn(move || { .spawn(move || {
tokio::runtime::Builder::new_current_thread() if let Err(e) = start_(&sender, device_reader, buf_sender) {
.enable_all() log::warn!("stop:{}", e);
.build() }
.unwrap() let _ = sender.close();
.block_on(async move { let _ = device_writer.close();
if let Err(e) = start_(sender, device_reader, buf_sender).await { worker.stop_all();
log::warn!("stop:{}", e);
}
let _ = device_writer.close();
worker.stop_all();
})
}) })
.unwrap(); .unwrap();
} }
} }
async fn start_( fn start_(
sender: ChannelSender, sender: &ChannelSender,
device_reader: DeviceReader, device_reader: DeviceReader,
mut buf_sender: BufSenderGroup, mut buf_sender: BufSenderGroup,
) -> io::Result<()> { ) -> io::Result<()> {
loop { loop {
let mut buf = POOL.alloc(4096); let mut buf = vec![0; 4096];
buf[..12].fill(0); buf[..12].fill(0);
if sender.is_close() { if sender.is_close() {
return Ok(()); return Ok(());
@@ -191,7 +174,7 @@ async fn start_(
let len = device_reader.read(&mut buf[12..])? + 12; let len = device_reader.read(&mut buf[12..])? + 12;
#[cfg(any(target_os = "macos"))] #[cfg(any(target_os = "macos"))]
let start = 4; let start = 4;
if !buf_sender.send((buf, start, len)).await { if !buf_sender.send((buf, start, len)) {
return Err(io::Error::new( return Err(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
"tun buf_sender发送失败", "tun buf_sender发送失败",
@@ -200,8 +183,8 @@ async fn start_(
} }
} }
async fn start_simple( fn start_simple(
sender: ChannelSender, sender: &ChannelSender,
device_reader: DeviceReader, device_reader: DeviceReader,
device_writer: &DeviceWriter, device_writer: &DeviceWriter,
igmp_server: Option<IgmpServer>, igmp_server: Option<IgmpServer>,
@@ -221,7 +204,7 @@ async fn start_simple(
#[cfg(any(target_os = "macos"))] #[cfg(any(target_os = "macos"))]
let mut buf = &mut buf[4..]; let mut buf = &mut buf[4..];
match handle( match handle(
&sender, sender,
&mut buf, &mut buf,
len, len,
device_writer, device_writer,
@@ -231,9 +214,7 @@ async fn start_simple(
&ip_proxy_map, &ip_proxy_map,
&client_cipher, &client_cipher,
&server_cipher, &server_cipher,
) ) {
.await
{
Ok(_) => {} Ok(_) => {}
Err(e) => { Err(e) => {
log::warn!("{:?}", e) log::warn!("{:?}", e)
+12 -8
View File
@@ -1,15 +1,19 @@
use crate::tun_tap_device::DeviceWriter;
use dashmap::DashMap;
use packet::igmp::igmp_v2::IgmpV2Packet;
use packet::igmp::igmp_v3::{IgmpV3QueryPacket, IgmpV3RecordType, IgmpV3ReportPacket};
use packet::igmp::IgmpType;
use packet::ip::ipv4::protocol::Protocol;
use parking_lot::RwLock;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use dashmap::DashMap;
use parking_lot::RwLock;
use packet::igmp::igmp_v2::IgmpV2Packet;
use packet::igmp::igmp_v3::{IgmpV3QueryPacket, IgmpV3RecordType, IgmpV3ReportPacket};
use packet::igmp::IgmpType;
use packet::ip::ipv4::protocol::Protocol;
use crate::ip_proxy::DashMapNew;
use crate::tun_tap_device::DeviceWriter;
//1. 定时发送query,启动时20秒一次,连发3次,之后8分钟一次 //1. 定时发送query,启动时20秒一次,连发3次,之后8分钟一次
//2. 接收网关的igmp report 维护组播源信息 //2. 接收网关的igmp report 维护组播源信息
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@@ -52,7 +56,7 @@ pub struct IgmpServer {
impl IgmpServer { impl IgmpServer {
pub fn new(device_writer: DeviceWriter) -> Self { pub fn new(device_writer: DeviceWriter) -> Self {
let multicast: Arc<DashMap<Ipv4Addr, Arc<RwLock<Multicast>>>> = Arc::new(DashMap::new()); let multicast: Arc<DashMap<Ipv4Addr, Arc<RwLock<Multicast>>>> = Arc::new(DashMap::new0());
std::thread::spawn(move || { std::thread::spawn(move || {
//预留以太网帧头和ip头 //预留以太网帧头和ip头
let mut buf = [0; 14 + 24 + 12]; let mut buf = [0; 14 + 24 + 12];
+1 -1
View File
@@ -109,7 +109,7 @@ impl IcmpProxy {
) )
.is_err() .is_err()
{ {
let _ = self.sender.try_send_main( let _ = self.sender.send_main(
net_packet.buffer(), net_packet.buffer(),
connect_server, connect_server,
); );
+63 -24
View File
@@ -1,21 +1,48 @@
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; use crate::ip_proxy::tcp_proxy::TcpProxy;
use crate::ip_proxy::udp_proxy::UdpProxy; use crate::ip_proxy::udp_proxy::UdpProxy;
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap; use dashmap::DashMap;
#[cfg(not(target_os = "android"))]
use socket2::{SockAddr, Socket}; use socket2::{SockAddr, Socket};
use std::net::{Ipv4Addr, SocketAddrV4}; #[cfg(not(target_os = "android"))]
use std::net::Ipv4Addr;
use std::net::SocketAddrV4;
use std::sync::Arc; use std::sync::Arc;
use std::{io, thread}; use std::{io, thread};
use tokio::net::{TcpListener, UdpSocket}; use tokio::net::{TcpListener, UdpSocket};
#[cfg(not(target_os = "android"))]
pub mod icmp_proxy; pub mod icmp_proxy;
pub mod tcp_proxy; pub mod tcp_proxy;
pub mod udp_proxy; pub mod udp_proxy;
pub trait DashMapNew {
fn new0() -> Self;
fn new_cap(capacity: usize) -> Self;
}
impl<'a, K: 'a + Eq + std::hash::Hash, V: 'a> DashMapNew for DashMap<K, V> {
fn new0() -> Self {
Self::new_cap(0)
}
fn new_cap(capacity: usize) -> Self {
let shard_amount = (thread::available_parallelism().map_or(4, |v| {
// https://github.com/rust-lang/rust/issues/115868
let n: usize = v.get() * 4;
if n == 0 {
log::warn!("available_parallelism=0");
println!("warn available_parallelism=0");
}
if n < 4 {
return 4;
}
n
}))
.next_power_of_two();
DashMap::with_capacity_and_shard_amount(capacity, shard_amount)
}
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)] #[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)]
pub enum Protocol { pub enum Protocol {
Icmp, Icmp,
@@ -31,11 +58,14 @@ pub struct IpProxyMap {
pub(crate) tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>, pub(crate) tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
pub(crate) udp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>, pub(crate) udp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
// icmp用Identifier来区分,没有Identifier的一律不转发 // icmp用Identifier来区分,没有Identifier的一律不转发
#[cfg(not(target_os = "android"))]
pub(crate) icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>>, pub(crate) icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
#[cfg(not(target_os = "android"))]
icmp_socket: Arc<Socket>, icmp_socket: Arc<Socket>,
} }
impl IpProxyMap { impl IpProxyMap {
#[cfg(not(target_os = "android"))]
pub fn send_icmp(&self, buf: &[u8], dest: &Ipv4Addr) -> io::Result<usize> { pub fn send_icmp(&self, buf: &[u8], dest: &Ipv4Addr) -> io::Result<usize> {
self.icmp_socket self.icmp_socket
.send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0))) .send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0)))
@@ -43,31 +73,38 @@ impl IpProxyMap {
} }
pub async fn init_proxy( pub async fn init_proxy(
sender: ChannelSender, #[cfg(not(target_os = "android"))] sender: crate::channel::sender::ChannelSender,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, #[cfg(not(target_os = "android"))] current_device: Arc<
client_cipher: Cipher, crossbeam_utils::atomic::AtomicCell<crate::handle::CurrentDeviceInfo>,
>,
#[cfg(not(target_os = "android"))] client_cipher: crate::cipher::Cipher,
) -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> { ) -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> {
let tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new()); let tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new0());
let udp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new()); let udp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new0());
let icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>> = Arc::new(DashMap::new()); #[cfg(not(target_os = "android"))]
let icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>> = Arc::new(DashMap::new0());
let tcp_listener = TcpListener::bind("0.0.0.0:0").await?; let tcp_listener = TcpListener::bind("0.0.0.0:0").await?;
let udp_socket = UdpSocket::bind("0.0.0.0:0").await?; let udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
let tcp_proxy_port = tcp_listener.local_addr()?.port(); let tcp_proxy_port = tcp_listener.local_addr()?.port();
let udp_proxy_port = udp_socket.local_addr()?.port(); let udp_proxy_port = udp_socket.local_addr()?.port();
let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map.clone()); let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map.clone());
let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map.clone()); let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map.clone());
let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0); #[cfg(not(target_os = "android"))]
let icmp_proxy = IcmpProxy::new( let icmp_socket = {
addr, let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0);
icmp_proxy_map.clone(), let icmp_proxy = icmp_proxy::IcmpProxy::new(
sender.clone(), addr,
current_device.clone(), icmp_proxy_map.clone(),
client_cipher, sender.clone(),
)?; current_device.clone(),
let icmp_socket = icmp_proxy.icmp_socket(); client_cipher,
thread::spawn(move || { )?;
icmp_proxy.start(); let icmp_socket = icmp_proxy.icmp_socket();
}); thread::spawn(move || {
icmp_proxy.start();
});
icmp_socket
};
Ok(( Ok((
tcp_proxy, tcp_proxy,
@@ -77,7 +114,9 @@ pub async fn init_proxy(
udp_proxy_port, udp_proxy_port,
tcp_proxy_map, tcp_proxy_map,
udp_proxy_map, udp_proxy_map,
#[cfg(not(target_os = "android"))]
icmp_proxy_map, icmp_proxy_map,
#[cfg(not(target_os = "android"))]
icmp_socket, icmp_socket,
}, },
)) ))
+70 -22
View File
@@ -1,8 +1,12 @@
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap; use dashmap::DashMap;
use std::io; use std::io;
use std::net::{SocketAddr, SocketAddrV4}; use std::net::{SocketAddr, SocketAddrV4};
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::io::AsyncReadExt;
use tokio::io::AsyncWriteExt;
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
use tokio::net::{TcpListener, TcpStream}; use tokio::net::{TcpListener, TcpStream};
pub struct TcpProxy { pub struct TcpProxy {
@@ -30,19 +34,36 @@ impl TcpProxy {
if let Some(entry) = tcp_proxy_map.get(&sender_addr) { if let Some(entry) = tcp_proxy_map.get(&sender_addr) {
let dest_addr = *entry.value(); let dest_addr = *entry.value();
drop(entry); drop(entry);
let peer_tcp_stream = match TcpStream::connect(dest_addr).await {
Ok(peer_tcp_stream) => peer_tcp_stream,
Err(e) => {
log::warn!(
"tcp代理异常:{:?},来源:{},目标:{}",
e,
sender_addr,
dest_addr
);
continue;
}
};
tokio::spawn(async move { tokio::spawn(async move {
let peer_tcp_stream = match tokio::time::timeout(
Duration::from_secs(5),
TcpStream::connect(dest_addr),
)
.await
{
Ok(peer_tcp_stream) => match peer_tcp_stream {
Ok(peer_tcp_stream) => peer_tcp_stream,
Err(e) => {
log::warn!(
"tcp代理异常:{:?},来源:{},目标:{}",
e,
sender_addr,
dest_addr
);
return;
}
},
Err(e) => {
log::warn!(
"tcp代理异常:{:?},来源:{},目标:{}",
e,
sender_addr,
dest_addr
);
return;
}
};
if let Err(e) = proxy(tcp_stream, peer_tcp_stream).await { if let Err(e) = proxy(tcp_stream, peer_tcp_stream).await {
log::warn!("{}->{},{}", sender_addr, dest_addr, e); log::warn!("{}->{},{}", sender_addr, dest_addr, e);
} }
@@ -61,15 +82,42 @@ impl TcpProxy {
} }
} }
async fn proxy(mut client: TcpStream, mut server: TcpStream) -> io::Result<()> { async fn proxy(client: TcpStream, server: TcpStream) -> io::Result<()> {
let (mut client_reader, mut client_writer) = client.split(); let (client_read, client_write) = client.into_split();
let (mut server_reader, mut server_writer) = server.split(); let (server_read, server_write) = server.into_split();
let time = Arc::new(AtomicCell::new(Instant::now()));
let time1 = time.clone();
tokio::spawn(async move {
if let Err(e) = copy(client_read, server_write, &time1).await {
log::warn!("{:?}", e);
}
});
copy(server_read, client_write, &time).await
}
let client_to_server = tokio::io::copy(&mut client_reader, &mut server_writer); async fn copy(
let server_to_client = tokio::io::copy(&mut server_reader, &mut client_writer); mut read: OwnedReadHalf,
mut write: OwnedWriteHalf,
let (r1, r2) = tokio::join!(client_to_server, server_to_client); time: &AtomicCell<Instant>,
r1?; ) -> io::Result<()> {
r2?; let mut buf = [0; 10240];
loop {
tokio::select! {
result = read.read(&mut buf) =>{
let len = result?;
if len==0{
break;
}
write.write_all(&buf[..len]).await?;
time.store(Instant::now());
}
_ = tokio::time::sleep(Duration::from_secs(600)) =>{
if time.load().elapsed()>=Duration::from_secs(580){
//读写均超时再退出
break;
}
}
}
}
Ok(()) Ok(())
} }
+23 -9
View File
@@ -1,9 +1,12 @@
use crate::ip_proxy::DashMapNew;
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap; use dashmap::DashMap;
use std::io; use std::io;
use std::net::{SocketAddr, SocketAddrV4}; use std::net::{SocketAddr, SocketAddrV4};
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tokio::net::UdpSocket; use tokio::net::UdpSocket;
use tokio::time::Instant;
/// 一个udp代理,作用是利用系统协议栈,将udp数据报解析出来再转发到目的地址 /// 一个udp代理,作用是利用系统协议栈,将udp数据报解析出来再转发到目的地址
pub struct UdpProxy { pub struct UdpProxy {
@@ -20,7 +23,9 @@ impl UdpProxy {
let map = self.map; let map = self.map;
let udp_socket = self.udp_socket; let udp_socket = self.udp_socket;
let mut buf = [0u8; 65536]; let mut buf = [0u8; 65536];
let inner_map: Arc<DashMap<SocketAddrV4, Arc<UdpSocket>>> = Arc::new(DashMap::new());
let inner_map: Arc<DashMap<SocketAddrV4, (Arc<UdpSocket>, Arc<AtomicCell<Instant>>)>> =
Arc::new(DashMap::new0());
loop { loop {
match udp_socket.recv_from(&mut buf).await { match udp_socket.recv_from(&mut buf).await {
@@ -47,29 +52,36 @@ impl UdpProxy {
async fn start0( async fn start0(
buf: &[u8], buf: &[u8],
sender_addr: SocketAddrV4, sender_addr: SocketAddrV4,
inner_map: &Arc<DashMap<SocketAddrV4, Arc<UdpSocket>>>, inner_map: &Arc<DashMap<SocketAddrV4, (Arc<UdpSocket>, Arc<AtomicCell<Instant>>)>>,
map: &Arc<DashMap<SocketAddrV4, SocketAddrV4>>, map: &Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
udp_socket: &Arc<UdpSocket>, udp_socket: &Arc<UdpSocket>,
) -> io::Result<()> { ) -> io::Result<()> {
if let Some(entry) = inner_map.get(&sender_addr) { if let Some(entry) = inner_map.get(&sender_addr) {
let udp = entry.value().clone(); entry.value().1.store(Instant::now());
let udp = entry.value().0.clone();
drop(entry); drop(entry);
udp.send(buf).await?; udp.send(buf).await?;
} else if let Some(entry) = map.get(&sender_addr) { } else if let Some(entry) = map.get(&sender_addr) {
let dest_addr = *entry.value(); let dest_addr = *entry.value();
drop(entry); drop(entry);
let peer_udp_socket = UdpSocket::bind("0.0.0.0:0").await?; //先使用相同的端口,冲突了再随机端口
let peer_udp_socket = match UdpSocket::bind(format!("0.0.0.0:{}", sender_addr.port())).await
{
Ok(udp) => udp,
Err(_) => UdpSocket::bind("0.0.0.0:0").await?,
};
peer_udp_socket.connect(dest_addr).await?; peer_udp_socket.connect(dest_addr).await?;
peer_udp_socket.send(buf).await?; peer_udp_socket.send(buf).await?;
let peer_udp_socket = Arc::new(peer_udp_socket); let peer_udp_socket = Arc::new(peer_udp_socket);
let inner_map = inner_map.clone(); let inner_map = inner_map.clone();
inner_map.insert(sender_addr, peer_udp_socket.clone()); let time = Arc::new(AtomicCell::new(Instant::now()));
inner_map.insert(sender_addr, (peer_udp_socket.clone(), time.clone()));
let udp_socket = udp_socket.clone(); let udp_socket = udp_socket.clone();
let map = map.clone(); let map = map.clone();
tokio::spawn(async move { tokio::spawn(async move {
let mut buf = [0u8; 65536]; let mut buf = [0u8; 65536];
loop { loop {
match tokio::time::timeout(Duration::from_secs(300), peer_udp_socket.recv(&mut buf)) match tokio::time::timeout(Duration::from_secs(600), peer_udp_socket.recv(&mut buf))
.await .await
{ {
Ok(rs) => match rs { Ok(rs) => match rs {
@@ -96,9 +108,11 @@ async fn start0(
} }
}, },
Err(_) => { Err(_) => {
//超时关闭 if time.load().elapsed() > Duration::from_secs(580) {
log::warn!("udp代理超时关闭,来源:{},目标:{}", sender_addr, dest_addr); //超时关闭
break; log::warn!("udp代理超时关闭,来源:{},目标:{}", sender_addr, dest_addr);
break;
}
} }
} }
} }
+1 -1
View File
@@ -1,5 +1,5 @@
use crate::error::Error; use crate::error::Error;
pub const VNT_VERSION: &'static str = "1.2.2"; pub const VNT_VERSION: &'static str = "1.2.5";
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
pub mod channel; pub mod channel;
+36 -19
View File
@@ -1,7 +1,9 @@
use crossbeam_utils::atomic::AtomicCell;
use std::io; use std::io;
use std::net::UdpSocket; use std::net::UdpSocket;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant};
use parking_lot::Mutex; use parking_lot::Mutex;
@@ -22,7 +24,7 @@ pub fn local_ipv4() -> io::Result<Ipv4Addr> {
pub fn local_ipv6() -> io::Result<Ipv6Addr> { pub fn local_ipv6() -> io::Result<Ipv6Addr> {
let socket = UdpSocket::bind("[::]:0")?; let socket = UdpSocket::bind("[::]:0")?;
socket.connect("[2001:4860:4860::8888]:80")?; socket.connect("[2001:4860:4860:0000:0000:0000:0000:8888]:80")?;
let addr = socket.local_addr()?; let addr = socket.local_addr()?;
match addr.ip() { match addr.ip() {
IpAddr::V4(_) => Ok(Ipv6Addr::UNSPECIFIED), IpAddr::V4(_) => Ok(Ipv6Addr::UNSPECIFIED),
@@ -54,6 +56,7 @@ pub fn local_ipv6_addr(port: u16) -> SocketAddrV6 {
pub struct NatTest { pub struct NatTest {
stun_server: Vec<String>, stun_server: Vec<String>,
info: Arc<Mutex<NatInfo>>, info: Arc<Mutex<NatInfo>>,
time: Arc<AtomicCell<Instant>>,
} }
impl From<NatType> for PunchNatType { impl From<NatType> for PunchNatType {
@@ -75,7 +78,7 @@ impl Into<NatType> for PunchNatType {
} }
impl NatTest { impl NatTest {
pub async fn new( pub fn new(
mut stun_server: Vec<String>, mut stun_server: Vec<String>,
public_ip: Ipv4Addr, public_ip: Ipv4Addr,
public_port: u16, public_port: u16,
@@ -84,25 +87,42 @@ impl NatTest {
) -> NatTest { ) -> NatTest {
let server = stun_server[0].clone(); let server = stun_server[0].clone();
stun_server.resize(3, server); stun_server.resize(3, server);
let nat_info = Self::re_test_( let nat_info = NatInfo::new(
&stun_server, vec![public_ip],
public_ip,
public_port, public_port,
0,
local_ipv4_addr, local_ipv4_addr,
ipv6_addr, ipv6_addr,
) NatType::Cone,
.await; );
let info = Arc::new(Mutex::new(nat_info)); let info = Arc::new(Mutex::new(nat_info));
NatTest { stun_server, info } NatTest {
stun_server,
info,
time: Arc::new(AtomicCell::new(Instant::now())),
}
}
pub fn can_update(&self) -> bool {
let last = self.time.load();
last.elapsed() > Duration::from_secs(10)
&& self.time.compare_exchange(last, Instant::now()).is_ok()
} }
pub fn nat_info(&self) -> NatInfo { pub fn nat_info(&self) -> NatInfo {
self.info.lock().clone() self.info.lock().clone()
} }
pub fn update_addr(&self, ip: Ipv4Addr, port: u16) { pub fn update_addr(&self, ip: Ipv4Addr, port: u16) {
let mut guard = self.info.lock(); if !ip.is_multicast()
guard.public_port = port; && !ip.is_broadcast()
if !guard.public_ips.contains(&ip) { && !ip.is_unspecified()
guard.public_ips.push(ip); && !ip.is_loopback()
&& !ip.is_private()
&& port != 0
{
let mut guard = self.info.lock();
guard.public_port = port;
if !guard.public_ips.contains(&ip) {
guard.public_ips.push(ip);
}
} }
} }
pub async fn re_test( pub async fn re_test(
@@ -120,6 +140,7 @@ impl NatTest {
ipv6_addr, ipv6_addr,
) )
.await; .await;
log::info!("探测nat类型={:?}", info);
*self.info.lock() = info.clone(); *self.info.lock() = info.clone();
info info
} }
@@ -131,13 +152,9 @@ impl NatTest {
ipv6_addr: SocketAddrV6, ipv6_addr: SocketAddrV6,
) -> NatInfo { ) -> NatInfo {
return match stun_test::stun_test_nat(stun_server.clone()).await { return match stun_test::stun_test_nat(stun_server.clone()).await {
Ok((nat_type, ips, port_range)) => { Ok((nat_type, mut public_ips, port_range)) => {
let mut public_ips = Vec::new(); if !public_ips.contains(&public_ip) {
public_ips.push(Ipv4Addr::from(public_ip)); public_ips.push(public_ip)
for ip in ips {
if ip != public_ip {
public_ips.push(ip);
}
} }
NatInfo::new( NatInfo::new(
public_ips, public_ips,
+4 -1
View File
@@ -1,6 +1,9 @@
use std::{fmt, io}; use std::{fmt, io};
pub const ENCRYPTION_RESERVED: usize = 32; pub const ENCRYPTION_RESERVED: usize = 16 + 32 + 12;
pub const AES_GCM_ENCRYPTION_RESERVED: usize = 32;
pub const RSA_ENCRYPTION_RESERVED: usize = 32;
/* aes_gcm加密数据体 /* aes_gcm加密数据体
0 15 31 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 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
+4 -3
View File
@@ -111,7 +111,7 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
"length overflow", "length overflow",
)); ));
} }
//加密需要预留32字节 //加密需要预留ENCRYPTION_RESERVED字节
let data_len = buffer.as_ref().len() - ENCRYPTION_RESERVED; let data_len = buffer.as_ref().len() - ENCRYPTION_RESERVED;
Self::new0(data_len, buffer) Self::new0(data_len, buffer)
} }
@@ -155,7 +155,7 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
} }
/// 网关通信的标识 /// 网关通信的标识
pub fn is_gateway(&self) -> bool { pub fn is_gateway(&self) -> bool {
self.buffer.as_ref()[0] & 0x50 == 0x50 self.buffer.as_ref()[0] & 0x40 == 0x40
} }
pub fn version(&self) -> Version { pub fn version(&self) -> Version {
Version::from(self.buffer.as_ref()[0] & 0x0F) Version::from(self.buffer.as_ref()[0] & 0x0F)
@@ -187,7 +187,7 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> { impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
pub fn buffer_mut(&mut self) -> &mut [u8] { pub fn buffer_mut(&mut self) -> &mut [u8] {
self.buffer.as_mut() &mut self.buffer.as_mut()[..self.data_len]
} }
pub fn set_encrypt_flag(&mut self, is_encrypt: bool) { pub fn set_encrypt_flag(&mut self, is_encrypt: bool) {
if is_encrypt { if is_encrypt {
@@ -198,6 +198,7 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
} }
pub fn set_gateway_flag(&mut self, is_gateway: bool) { pub fn set_gateway_flag(&mut self, is_gateway: bool) {
if is_gateway { if is_gateway {
// 后面的版本再改为0x40,改了之后不兼容1.2.5之前的版本
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x50 self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x50
} else { } else {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF
+1 -1
View File
@@ -169,7 +169,7 @@ pub fn delete_device(_device_type: DeviceType) {
.output() .output()
.expect("sh exec error!"); .expect("sh exec error!");
if !delete_tun.status.success() { if !delete_tun.status.success() {
log::warn!("删除网卡失败:{:?}",delete_tun); log::warn!("删除网卡失败:{:?}", delete_tun);
} }
} }
} }
+21 -13
View File
@@ -5,7 +5,6 @@ use bytes::BufMut;
use packet::ethernet; use packet::ethernet;
use parking_lot::Mutex; use parking_lot::Mutex;
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use std::os::unix::io::AsRawFd;
#[cfg(any(target_os = "linux"))] #[cfg(any(target_os = "linux"))]
use tun::platform::linux::Device; use tun::platform::linux::Device;
#[cfg(any(target_os = "macos"))] #[cfg(any(target_os = "macos"))]
@@ -13,6 +12,7 @@ use tun::platform::macos::Device;
use tun::platform::posix::{Reader, Writer}; use tun::platform::posix::{Reader, Writer};
use packet::ethernet::packet::EthernetPacket; use packet::ethernet::packet::EthernetPacket;
#[derive(Clone)] #[derive(Clone)]
pub enum DeviceW { pub enum DeviceW {
Tun(Writer), Tun(Writer),
@@ -63,10 +63,17 @@ impl DeviceWriter {
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
buf.put_u16(libc::ETH_P_IP as u16); buf.put_u16(libc::ETH_P_IP as u16);
buf.extend_from_slice(packet); buf.extend_from_slice(packet);
writer.write_all(&buf) let len = writer.write(&buf)?;
if len != buf.len() {
log::error!("tun write error");
}
} else { } else {
writer.write_all(packet) let len = writer.write(packet)?;
if len != packet.len() {
log::error!("tun write error");
}
} }
Ok(())
} }
///tun网卡写入ipv4数据 ///tun网卡写入ipv4数据
pub fn write_ipv4_tun(&self, buf: &[u8]) -> io::Result<()> { pub fn write_ipv4_tun(&self, buf: &[u8]) -> io::Result<()> {
@@ -104,16 +111,17 @@ impl DeviceWriter {
} }
} }
pub fn close(&self) -> io::Result<()> { pub fn close(&self) -> io::Result<()> {
unsafe { //早期使用close直接切断网卡,现在并不需要这么做也能正常关闭
match &self.writer { // unsafe {
DeviceW::Tun(writer) => { // match &self.writer {
libc::close(writer.as_raw_fd()); // DeviceW::Tun(writer) => {
} // libc::close(writer.as_raw_fd());
DeviceW::Tap((writer, _)) => { // }
libc::close(writer.as_raw_fd()); // DeviceW::Tap((writer, _)) => {
} // libc::close(writer.as_raw_fd());
} // }
} // }
// }
Ok(()) Ok(())
} }
pub fn is_tun(&self) -> bool { pub fn is_tun(&self) -> bool {
+4 -4
View File
@@ -117,7 +117,7 @@ impl DeviceWriter {
// 当前网段路由 // 当前网段路由
dev.add_route(address, netmask, gateway, 1)?; dev.add_route(address, netmask, gateway, 1)?;
// 广播和组播路由 // 广播和组播路由
dev.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?; // dev.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
dev.add_route( dev.add_route(
Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([224, 0, 0, 0]),
Ipv4Addr::from([240, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]),
@@ -230,8 +230,8 @@ fn create_tun(
} }
// 当前网段路由 // 当前网段路由
tun_device.add_route(address, netmask, gateway, 1)?; tun_device.add_route(address, netmask, gateway, 1)?;
// 广播和组播路由 // 广播和组播路由 修改了广播路由会导致发不出广播
tun_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?; // tun_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
tun_device.add_route( tun_device.add_route(
Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([224, 0, 0, 0]),
Ipv4Addr::from([240, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]),
@@ -309,7 +309,7 @@ fn create_tap(
tap_device.add_route(*address, *netmask, gateway, 1)?; tap_device.add_route(*address, *netmask, gateway, 1)?;
} }
// 广播和组播路由 // 广播和组播路由
tap_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?; // tap_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
tap_device.add_route( tap_device.add_route(
Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([224, 0, 0, 0]),
Ipv4Addr::from([240, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]),
+2 -1
View File
@@ -29,5 +29,6 @@ features = [
"winerror", "winerror",
"ipexport", "ipexport",
"iphlpapi", "iphlpapi",
"handleapi" "handleapi",
"ifdef"
] ]
+2 -1
View File
@@ -119,7 +119,8 @@ impl TapDevice {
} }
pub fn delete(self) -> io::Result<()> { pub fn delete(self) -> io::Result<()> {
iface::delete_interface(&self.luid) // iface::delete_interface(&self.luid)
Ok(())
} }
} }
+12 -6
View File
@@ -1,12 +1,12 @@
use std::io; use std::io;
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use winapi::um::{handleapi, synchapi, winbase, winnt}; use winapi::um::{synchapi, winbase, winnt};
use crate::{decode_utf16, encode_utf16, ffi, netsh, route, IFace}; use crate::{decode_utf16, encode_utf16, ffi, netsh, route, IFace};
use rand::Rng; use rand::Rng;
mod log;
pub mod packet; pub mod packet;
mod wintun_log;
mod wintun_raw; mod wintun_raw;
/// The maximum size of wintun's internal ring buffer (in bytes) /// The maximum size of wintun's internal ring buffer (in bytes)
@@ -80,7 +80,7 @@ impl TunDevice {
let guid_struct: wintun_raw::GUID = unsafe { std::mem::transmute(guid) }; let guid_struct: wintun_raw::GUID = unsafe { std::mem::transmute(guid) };
let guid_ptr = &guid_struct as *const wintun_raw::GUID; let guid_ptr = &guid_struct as *const wintun_raw::GUID;
log::set_default_logger_if_unset(&win_tun); wintun_log::set_default_logger_if_unset(&win_tun);
//SAFETY: the function is loaded from the wintun dll properly, we are providing valid //SAFETY: the function is loaded from the wintun dll properly, we are providing valid
//pointers, and all the strings are correct null terminated UTF-16. This safety rationale //pointers, and all the strings are correct null terminated UTF-16. This safety rationale
@@ -88,6 +88,7 @@ impl TunDevice {
let adapter = let adapter =
win_tun.WintunCreateAdapter(pool_utf16.as_ptr(), name_utf16.as_ptr(), guid_ptr); win_tun.WintunCreateAdapter(pool_utf16.as_ptr(), name_utf16.as_ptr(), guid_ptr);
if adapter.is_null() { if adapter.is_null() {
log::error!("adapter.is_null {:?}", io::Error::last_os_error());
return Err(io::Error::new( return Err(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
"Failed to crate adapter", "Failed to crate adapter",
@@ -102,6 +103,7 @@ impl TunDevice {
// 开启session // 开启session
let session = win_tun.WintunStartSession(adapter, 128 * 1024); let session = win_tun.WintunStartSession(adapter, 128 * 1024);
if session.is_null() { if session.is_null() {
log::error!("session.is_null {:?}", io::Error::last_os_error());
return Err(io::Error::new( return Err(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
"WintunStartSession failed", "WintunStartSession failed",
@@ -138,10 +140,14 @@ impl TunDevice {
)); ));
} }
}; };
log::set_default_logger_if_unset(&win_tun); wintun_log::set_default_logger_if_unset(&win_tun);
let name_utf16 = encode_utf16(name); let name_utf16 = encode_utf16(name);
let adapter = win_tun.WintunOpenAdapter(name_utf16.as_ptr()); let adapter = win_tun.WintunOpenAdapter(name_utf16.as_ptr());
if adapter.is_null() { if adapter.is_null() {
log::error!(
"delete_for_name adapter.is_null {:?}",
io::Error::last_os_error()
);
return Err(io::Error::new( return Err(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
"Failed to open adapter", "Failed to open adapter",
@@ -187,8 +193,8 @@ pub struct Version {
impl IFace for TunDevice { impl IFace for TunDevice {
fn shutdown(&self) -> io::Result<()> { fn shutdown(&self) -> io::Result<()> {
let _ = unsafe { synchapi::SetEvent(self.shutdown_event) }; // let _ = unsafe { synchapi::SetEvent(self.shutdown_event) };
let _ = unsafe { handleapi::CloseHandle(self.shutdown_event) }; // let _ = unsafe { handleapi::CloseHandle(self.shutdown_event) };
Ok(()) Ok(())
} }