Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf8397e6e3 | ||
|
|
8cee974866 | ||
|
|
5e018801db | ||
|
|
c4f7f4c19e | ||
|
|
29945eb3da | ||
|
|
7db415d243 | ||
|
|
808dcec795 | ||
|
|
ad8fecc319 | ||
|
|
27ae9a89da | ||
|
|
b3a4a4de5e | ||
|
|
ca76c35f6a | ||
|
|
073c820da6 | ||
|
|
954f0d2d05 | ||
|
|
a943f5bffc | ||
|
|
c3cff7c5b5 | ||
|
|
acb5a8a325 | ||
|
|
1a4e375dbf | ||
|
|
eec7d73ebe | ||
|
|
f4dda173c2 | ||
|
|
96fb8c881d | ||
|
|
aeebbd18fd | ||
|
|
baa71a51eb | ||
|
|
84e70149a1 | ||
|
|
959f2aa783 | ||
|
|
99b2aa9522 | ||
|
|
561fa9f8fe | ||
|
|
ad9dd6a7f7 | ||
|
|
65758eb94c | ||
|
|
fb7ccf4d11 | ||
|
|
b9fe5e0fe2 | ||
|
|
c3368481ad | ||
|
|
cdf5c3a508 | ||
|
|
f9217625e1 | ||
|
|
323f6c9221 | ||
|
|
2e507f1a9d | ||
|
|
e611d69a25 | ||
|
|
45d8c6717d | ||
|
|
756539c3bd | ||
|
|
3d4fcdbc96 | ||
|
|
3cd19dbc1f | ||
|
|
7b770a1bb0 | ||
|
|
0472b1590e | ||
|
|
81764433d8 | ||
|
|
9ee6e101c4 | ||
|
|
565e80b994 | ||
|
|
7ccc4535e4 | ||
|
|
d1bde297d6 | ||
|
|
c5398a51e8 | ||
|
|
fddb59992b | ||
|
|
665e25b1a3 | ||
|
|
fdb4bb1155 | ||
|
|
f104e191ed | ||
|
|
6311d75ac0 | ||
|
|
c3f134e332 | ||
|
|
5bccdf3bbe | ||
|
|
9e881eeecd | ||
|
|
fbe01d8cbf | ||
|
|
d336d938a9 | ||
|
|
598923c95a | ||
|
|
0afe4c4417 | ||
|
|
dff51caf35 | ||
|
|
7c30f2691a | ||
|
|
c6aca2c2dc | ||
|
|
28ac8cf88e | ||
|
|
62b2af54a2 | ||
|
|
a2d45da44d | ||
|
|
d937f392d3 | ||
|
|
2c9abf314a | ||
|
|
ab7abd0c1f |
+74
-20
@@ -37,39 +37,48 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# a list of all the targets
|
||||
# 选择使用openssl或者ring,并不是所有平台都支持
|
||||
include:
|
||||
- TARGET: i686-unknown-linux-musl # test in an alpine container on a mac
|
||||
OS: ubuntu-latest
|
||||
- TARGET: x86_64-unknown-linux-gnu # tested in a debian container on a mac
|
||||
OS: ubuntu-latest
|
||||
FEATURES: default
|
||||
- TARGET: x86_64-unknown-linux-musl # test in an alpine container on a mac
|
||||
OS: ubuntu-latest
|
||||
- TARGET: aarch64-unknown-linux-gnu # tested on aws t4g.nano
|
||||
OS: ubuntu-latest
|
||||
FEATURES: ring-cipher,openssl-vendored
|
||||
- TARGET: aarch64-unknown-linux-musl # tested on aws t4g.nano in alpine container
|
||||
OS: ubuntu-latest
|
||||
- TARGET: armv7-unknown-linux-gnueabihf # raspberry pi 2-3-4, not tested
|
||||
OS: ubuntu-latest
|
||||
FEATURES: default
|
||||
- TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested
|
||||
OS: ubuntu-latest
|
||||
- TARGET: arm-unknown-linux-gnueabihf # raspberry pi 0-1, not tested
|
||||
OS: ubuntu-latest
|
||||
FEATURES: openssl-vendored
|
||||
- TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested
|
||||
OS: ubuntu-latest
|
||||
FEATURES: openssl-vendored
|
||||
- TARGET: x86_64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
|
||||
OS: macos-latest
|
||||
FEATURES: ring-cipher,openssl-vendored
|
||||
- TARGET: aarch64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
|
||||
OS: macos-latest
|
||||
FEATURES: ring-cipher,openssl-vendored
|
||||
- TARGET: i686-pc-windows-msvc # tested on a windows machine
|
||||
OS: windows-latest
|
||||
OS: windows-2019
|
||||
FEATURES: ring-cipher,openssl-vendored
|
||||
- TARGET: x86_64-pc-windows-msvc # tested on a windows machine
|
||||
OS: windows-latest
|
||||
FEATURES: ring-cipher,openssl-vendored
|
||||
- TARGET: mipsel-unknown-linux-musl # openwrt
|
||||
OS: ubuntu-latest
|
||||
FEATURES: openssl-vendored
|
||||
- TARGET: mips-unknown-linux-musl # openwrt
|
||||
OS: ubuntu-latest
|
||||
FEATURES: openssl-vendored
|
||||
# needs: test
|
||||
runs-on: ${{ matrix.OS }}
|
||||
env:
|
||||
NAME: vnt-cli # change with the name of your project
|
||||
TARGET: ${{ matrix.TARGET }}
|
||||
OS: ${{ matrix.OS }}
|
||||
FEATURES: ${{ matrix.FEATURES }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Init submodules
|
||||
@@ -81,6 +90,9 @@ jobs:
|
||||
~/.cargo/registry
|
||||
./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
|
||||
run: find ./
|
||||
- name: Install and configure dependencies
|
||||
@@ -88,27 +100,69 @@ jobs:
|
||||
# dependencies are only needed on ubuntu as that's the only place where
|
||||
# we make cross-compilation
|
||||
if [[ $OS =~ ^ubuntu.*$ ]]; then
|
||||
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf
|
||||
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
|
||||
|
||||
|
||||
# some additional configuration for cross-compilation on linux
|
||||
cat >>~/.cargo/config <<EOF
|
||||
[target.aarch64-unknown-linux-gnu]
|
||||
linker = "aarch64-linux-gnu-gcc"
|
||||
[target.x86_64-unknown-linux-musl]
|
||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||
[target.aarch64-unknown-linux-musl]
|
||||
linker = "aarch64-linux-gnu-gcc"
|
||||
[target.armv7-unknown-linux-gnueabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
linker = "aarch64-linux-musl-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||
[target.armv7-unknown-linux-musleabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
[target.arm-unknown-linux-gnueabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
linker = "armv7l-linux-musleabihf-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||
[target.arm-unknown-linux-musleabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
linker = "arm-linux-musleabihf-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||
[target.mipsel-unknown-linux-musl]
|
||||
linker = "mipsel-linux-musl-gcc"
|
||||
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]
|
||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||
[target.i686-pc-windows-msvc]
|
||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||
[target.x86_64-apple-darwin]
|
||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||
[target.aarch64-apple-darwin]
|
||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||
[target.i686-unknown-linux-musl]
|
||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||
EOF
|
||||
- name: Install rust target
|
||||
run: rustup target add $TARGET
|
||||
- name: Run build
|
||||
run: cargo build --package vnt-cli --release --verbose --target $TARGET
|
||||
run: cargo build --package vnt-cli --release --verbose --target $TARGET --features $FEATURES
|
||||
- name: List target
|
||||
run: find ./target
|
||||
- name: Compress
|
||||
|
||||
@@ -50,11 +50,12 @@ A virtual network tool (VPN)
|
||||
### 使用须知
|
||||
|
||||
- token的作用是标识一个虚拟局域网,当使用公共服务器时,建议使用一个唯一值当token(比如uuid),否则有可能连接到其他人创建的虚拟局域网中
|
||||
- 默认使用公共服务器,目前的配置是2核4G 4Mbps,有需要再扩展~
|
||||
- 默认使用公共服务器做注册和中继,目前的配置是2核4G 4Mbps,有需要再扩展~
|
||||
- 需要root/管理员权限
|
||||
- vnt-cli需要使用命令行运行
|
||||
- Mac和Linux下需要加可执行权限(例如:chmod +x ./vnt-cli)
|
||||
- 可以自己搭注册和中继服务器([server](https://github.com/lbl8603/vnts))
|
||||
- vnt使用stun服务器探测网络NAT类型,默认使用谷歌和腾讯的stun服务器,也可自己搭建(-e参数指定)
|
||||
|
||||
### 编译
|
||||
|
||||
@@ -70,7 +71,7 @@ A virtual network tool (VPN)
|
||||
- 使用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)
|
||||
- Android
|
||||
- [SwitchApp](https://github.com/lbl8603/SwitchApp)
|
||||
- [VntApp](https://github.com/lbl8603/VntApp)
|
||||
|
||||
### 特性
|
||||
|
||||
@@ -84,12 +85,40 @@ A virtual network tool (VPN)
|
||||
- IP代理
|
||||
- p2p组播/广播
|
||||
- 客户端数据加密
|
||||
- 服务端数据加密
|
||||
### 结构
|
||||
<details> <summary>展开</summary>
|
||||
|
||||
<pre>
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|e |s |unused| 版本(4) | 协议(8) | 上层协议(8) |初始ttl(4)|生存时间(4) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 源ip地址(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 目的ip地址(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 数据体(n) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| 指纹(96) |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
注:
|
||||
1. e为是否加密标志,s为服务端通信包标志,unused占两位未使用;
|
||||
2. 开启加密时,数据体为加密后的密文(加密方式取决于密码长度和加密模式),
|
||||
且会存在指纹,指纹使用sha256生成,用于对数据包完整性和真实性的校验
|
||||
</pre>
|
||||
|
||||
|
||||
</details>
|
||||
|
||||
### Todo
|
||||
|
||||
- 桌面UI(测试中)
|
||||
- 服务端数据加密
|
||||
- 支持Ipv6
|
||||
- 支持Ipv6(1.2.2已支持客户端之间的ipv6,待支持客户端和服务端之间的ipv6通信)
|
||||
|
||||
### 常见问题
|
||||
<details> <summary>展开</summary>
|
||||
@@ -115,6 +144,13 @@ vnt默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突
|
||||
2. 解压后找到对应架构的目录,通常是amd64
|
||||
3. 将对应的wintun.dll放到和vnt-cli同目录下(或者放到C盘Windows目录下)
|
||||
4. 再次启动vnt-cli
|
||||
|
||||
#### 问题3: 丢包严重,或是不能正常组网通信
|
||||
##### 可能原因:
|
||||
某些宽带下(比如广电宽带)UDP丢包严重
|
||||
##### 解决方法:
|
||||
1. 使用TCP模式中继转发(vnt-cli增加--tcp参数)
|
||||
2. 如果p2p后效果很差,可以选择禁用p2p(vnt-cli增加--relay参数)
|
||||
|
||||
|
||||
</details>
|
||||
@@ -122,3 +158,6 @@ vnt默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突
|
||||
### 交流群
|
||||
|
||||
QQ:1034868233
|
||||
### 其他
|
||||
可使用社区小伙伴搭建的中继服务器
|
||||
1. -s vnt.8443.eu.org:29871
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "common"
|
||||
version = "1.1.1"
|
||||
version = "1.2.3"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
+42
-10
@@ -35,16 +35,48 @@ pub fn ips_parse(ips: &Vec<String>) -> Result<Vec<(u32, u32, Ipv4Addr)>, String>
|
||||
} else {
|
||||
return Err("not ipv4".to_string());
|
||||
};
|
||||
let mask = if let Ok(m) = mask.parse::<u32>() {
|
||||
let mut mask = 0 as u32;
|
||||
for i in 0..m {
|
||||
mask = mask | (1 << (31 - i));
|
||||
}
|
||||
mask
|
||||
} else {
|
||||
return Err("not netmask".to_string());
|
||||
};
|
||||
let mask = to_ip(mask)?;
|
||||
in_ips_c.push((u32::from_be_bytes(dest.octets()), mask, ip));
|
||||
}
|
||||
Ok(in_ips_c)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn out_ips_parse(ips: &Vec<String>) -> Result<Vec<(u32, u32)>, String> {
|
||||
let mut in_ips_c = vec![];
|
||||
for x in ips {
|
||||
let mut split = x.split("/");
|
||||
let dest = if let Some(dest) = split.next() {
|
||||
dest
|
||||
} else {
|
||||
return Err("no ipv4/mask".to_string());
|
||||
};
|
||||
let mask = if let Some(mask) = split.next() {
|
||||
mask
|
||||
} else {
|
||||
return Err("no netmask".to_string());
|
||||
};
|
||||
let dest = if let Ok(dest) = dest.parse::<Ipv4Addr>() {
|
||||
dest
|
||||
} else {
|
||||
return Err("not ipv4".to_string());
|
||||
};
|
||||
let mask = to_ip(mask)?;
|
||||
in_ips_c.push((u32::from_be_bytes(dest.octets()), mask));
|
||||
}
|
||||
Ok(in_ips_c)
|
||||
}
|
||||
|
||||
pub fn to_ip(mask: &str) -> Result<u32, String> {
|
||||
if let Ok(m) = mask.parse::<u32>() {
|
||||
if m >= 32 {
|
||||
return Err("not netmask".to_string());
|
||||
}
|
||||
let mut mask = 0 as u32;
|
||||
for i in 0..m {
|
||||
mask = mask | (1 << (31 - i));
|
||||
}
|
||||
Ok(mask)
|
||||
} else {
|
||||
Err("not netmask".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
+15
-11
@@ -1,14 +1,13 @@
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn get_unique_identifier() -> Option<String> {
|
||||
use std::os::windows::process::CommandExt;
|
||||
use std::process::Command;
|
||||
let output = match Command::new("wmic")
|
||||
.creation_flags(0x08000000)
|
||||
.args(&["csproduct", "get", "UUID"])
|
||||
.output() {
|
||||
Ok(output) => { output }
|
||||
.output()
|
||||
{
|
||||
Ok(output) => output,
|
||||
Err(_) => {
|
||||
return None;
|
||||
}
|
||||
@@ -25,10 +24,12 @@ pub fn get_unique_identifier() -> Option<String> {
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn get_unique_identifier() -> Option<String> {
|
||||
use std::process::Command;
|
||||
let output = match Command::new("ioreg")
|
||||
.args(&["-rd1", "-c", "IOPlatformExpertDevice"])
|
||||
.output() {
|
||||
Ok(output) => { output }
|
||||
.output()
|
||||
{
|
||||
Ok(output) => output,
|
||||
Err(_) => {
|
||||
return None;
|
||||
}
|
||||
@@ -38,7 +39,8 @@ pub fn get_unique_identifier() -> Option<String> {
|
||||
let identifier = result
|
||||
.lines()
|
||||
.find(|line| line.contains("IOPlatformUUID"))
|
||||
.unwrap_or("").trim();
|
||||
.unwrap_or("")
|
||||
.trim();
|
||||
if identifier.is_empty() {
|
||||
None
|
||||
} else {
|
||||
@@ -48,11 +50,13 @@ pub fn get_unique_identifier() -> Option<String> {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn get_unique_identifier() -> Option<String> {
|
||||
use std::process::Command;
|
||||
let output = match Command::new("dmidecode")
|
||||
.arg("-s")
|
||||
.arg("system-uuid")
|
||||
.output() {
|
||||
Ok(output) => { output }
|
||||
.output()
|
||||
{
|
||||
Ok(output) => output,
|
||||
Err(_) => {
|
||||
return None;
|
||||
}
|
||||
@@ -65,4 +69,4 @@ pub fn get_unique_identifier() -> Option<String> {
|
||||
} else {
|
||||
Some(identifier.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
pub mod identifier;
|
||||
pub mod args_parse;
|
||||
pub mod identifier;
|
||||
|
||||
+12
-7
@@ -1,14 +1,14 @@
|
||||
[package]
|
||||
name = "vnt-cli"
|
||||
version = "1.1.1"
|
||||
version = "1.2.3"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
vnt = {path="../vnt"}
|
||||
common = {path="../common"}
|
||||
tokio = { version = "1.28.1", features = ["full"] }
|
||||
vnt = { path = "../vnt", package = "vnt", optional = true }
|
||||
common = { path = "../common" }
|
||||
tokio = { version = "1.32.0", features = ["full"] }
|
||||
getopts = "0.2.21"
|
||||
console = "0.15.2"
|
||||
os_info = "3.7.0"
|
||||
@@ -16,10 +16,11 @@ dirs = "4.0.0"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0.94"
|
||||
log = "0.4.17"
|
||||
log4rs = "1.2.0"
|
||||
[dependencies.uuid]
|
||||
version = "1.4.1"
|
||||
features = [
|
||||
"v4", # Lets you generate random UUIDs
|
||||
"v4", # Lets you generate random UUIDs
|
||||
]
|
||||
|
||||
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
|
||||
@@ -27,9 +28,13 @@ sudo = "0.6.0"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
mini = []
|
||||
default = ["vnt"]
|
||||
openssl = ["vnt/openssl"]
|
||||
openssl-vendored = ["vnt/openssl-vendored"]
|
||||
ring-cipher = ["vnt/ring-cipher"]
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
embed-manifest = "1.4.0"
|
||||
+54
-13
@@ -1,31 +1,41 @@
|
||||
## 模块介绍
|
||||
体积小,可以在服务器、路由器等环境使用
|
||||
## 详细参数说明
|
||||
### -k
|
||||
### -k `<token>`
|
||||
一个虚拟局域网的标识,在同一服务器下,相同token的设备会组建一个局域网
|
||||
### -n
|
||||
### -n `<name>`
|
||||
设备名称,方便区分不同设备
|
||||
### -d
|
||||
### -d `<id>`
|
||||
设备id,每台设备的唯一标识,注意不要重复
|
||||
### -c
|
||||
关闭控制台交互式命令,后台运行时可以加此参数
|
||||
### -s
|
||||
### -s `<server>`
|
||||
注册和中继服务器地址,注册和转发数据
|
||||
### -e
|
||||
探测客户端NAT类型,不同类型有不同的打洞策略
|
||||
### -e `<stun-server>`
|
||||
使用stun服务探测客户端NAT类型,不同类型有不同的打洞策略
|
||||
### -a
|
||||
加了此参数表示使用tap网卡,默认使用tun网卡,tun网卡效率更高
|
||||
### -i、-o
|
||||
### -i `<in-ip>`、-o `<out-ip>`
|
||||
|
||||
配置点对网(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.10** ,表示允许将192.168.0.0/24的数据从网卡192.168.0.10转发出去
|
||||
在B配置 **'-o 192.168.0.0/24'** ,表示允许将数据转发到 192.168.0.0/24 ,允许转发所有网段可以使用 **'-o 0.0.0.0/0'**
|
||||
|
||||
### -w
|
||||
提升通信安全性,使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密。使用相同密码的客户端才能通信
|
||||
-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>`
|
||||
|
||||
提升通信安全性,使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密(包括中继数据)。使用相同密码的客户端才能通信
|
||||
|
||||
| 密码位数 | 加密算法 |
|
||||
|---------|-------|
|
||||
| 小于8 | AES128-GCM
|
||||
| 大于等于8 | AES256-GCM |
|
||||
|
||||
### -W
|
||||
开启和服务端通信的数据加密,采用rsa+aes256gcm加密客户端和服务端之间通信的数据,可以避免token泄漏、中间人攻击
|
||||
### -m
|
||||
模拟组播,高频使用组播通信时,可以尝试开启此参数,默认情况下会把组播当作广播发给所有节点
|
||||
|
||||
@@ -33,8 +43,39 @@
|
||||
|
||||
模拟组播:高频使用组播时防止广播泛洪,客户端和中继服务器会维护组播成员等信息,注意使用此选项时,虚拟网内所有成员都需要开启此选项
|
||||
|
||||
### -u
|
||||
### -u `<mtu>`
|
||||
|
||||
设置虚拟网卡的mtu值,大多数情况下使用默认值效率会更高,也可根据实际情况微调这个值,默认值为1430
|
||||
设置虚拟网卡的mtu值,大多数情况下使用默认值效率会更高,也可根据实际情况微调这个值,不加密默认为1450,加密默认为1410
|
||||
|
||||
### --tcp
|
||||
和服务端使用tcp通信。有些网络提供商对UDP限制比较大,这个时候可以选择使用TCP模式,提高稳定性。一般来说udp延迟和消耗更低
|
||||
### --ip `<IP>`
|
||||
指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配
|
||||
### --par `<parallel>`
|
||||
任务并行度(必须为正整数),默认值为1,该值表示处理网卡读写的任务数,组网设备数较多、处理延迟较大时可适当调大此值
|
||||
### --model `<model>`
|
||||
加密模式,可选值 aes_gcm/aes_cbc/aes_ecb,默认使用aes_gcm,通常情况aes_gcm安全性高、aes_ecb性能更好
|
||||
|
||||
| 密码位数 | model | 加密算法 |
|
||||
|-------|---------|------------|
|
||||
| 1~8位 | aes_gcm | AES128-GCM |
|
||||
| `>=`8 | aes_gcm | AES256-GCM |
|
||||
| 1~8位 | aes_cbc | AES128-CBC |
|
||||
| `>=`8 | aes_cbc | AES256-CBC |
|
||||
| 1~8位 | aes_ecb | AES128-ECB |
|
||||
| `>=`8 | aes_ecb | AES256-ECB |
|
||||
### --finger
|
||||
开启数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启,开启会损耗一部分性能
|
||||
|
||||
### --relay
|
||||
禁用p2p,在网络环境很差时,只使用服务器中转效果可能更好(可以配合--tcp参数一起使用)
|
||||
### --list
|
||||
在后台运行时,查看其他设备列表
|
||||
### --all
|
||||
在后台运行时,查看其他设备完整信息
|
||||
### --info
|
||||
在后台运行时,查看当前设备信息
|
||||
### --route
|
||||
在后台运行时,查看数据转发路径
|
||||
### --stop
|
||||
停止后台运行
|
||||
|
||||
+1
-1
@@ -7,4 +7,4 @@ fn main() {
|
||||
// embed_manifest(new_manifest("vnt")
|
||||
// .requested_execution_level(ExecutionLevel::RequireAdministrator)).expect("unable to embed manifest file");
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::command::entity::{DeviceItem, RouteItem, Info};
|
||||
use crate::command::entity::{DeviceItem, Info, RouteItem};
|
||||
|
||||
pub struct CommandClient {
|
||||
udp: UdpSocket,
|
||||
@@ -17,9 +17,12 @@ impl CommandClient {
|
||||
}
|
||||
let port = std::fs::read_to_string(path_buf)?;
|
||||
let port = match u16::from_str(&port) {
|
||||
Ok(port) => { port }
|
||||
Ok(port) => port,
|
||||
Err(_) => {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "'command-port' file error"));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"'command-port' file error",
|
||||
));
|
||||
}
|
||||
};
|
||||
let udp = UdpSocket::bind("127.0.0.1:0")?;
|
||||
@@ -38,11 +41,9 @@ impl CommandClient {
|
||||
let mut buf = [0; 10240];
|
||||
let len = self.udp.recv(&mut buf)?;
|
||||
match serde_json::from_slice::<Vec<DeviceItem>>(&buf[..len]) {
|
||||
Ok(val) => {
|
||||
Ok(val)
|
||||
}
|
||||
Ok(val) => Ok(val),
|
||||
Err(e) => {
|
||||
log::error!("{:?}",e);
|
||||
log::error!("{:?}", e);
|
||||
Err(io::Error::new(io::ErrorKind::Other, "data error"))
|
||||
}
|
||||
}
|
||||
@@ -52,11 +53,9 @@ impl CommandClient {
|
||||
let mut buf = [0; 10240];
|
||||
let len = self.udp.recv(&mut buf)?;
|
||||
match serde_json::from_slice::<Vec<RouteItem>>(&buf[..len]) {
|
||||
Ok(val) => {
|
||||
Ok(val)
|
||||
}
|
||||
Ok(val) => Ok(val),
|
||||
Err(e) => {
|
||||
log::error!("{:?}",e);
|
||||
log::error!("{:?}", e);
|
||||
Err(io::Error::new(io::ErrorKind::Other, "data error"))
|
||||
}
|
||||
}
|
||||
@@ -66,11 +65,9 @@ impl CommandClient {
|
||||
let mut buf = [0; 10240];
|
||||
let len = self.udp.recv(&mut buf)?;
|
||||
match serde_json::from_slice::<Info>(&buf[..len]) {
|
||||
Ok(val) => {
|
||||
Ok(val)
|
||||
}
|
||||
Ok(val) => Ok(val),
|
||||
Err(e) => {
|
||||
log::error!("{:?},{:?}",&buf[..len],e);
|
||||
log::error!("{:?},{:?}", &buf[..len], e);
|
||||
Err(io::Error::new(io::ErrorKind::Other, "data error"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ pub struct Info {
|
||||
pub relay_server: String,
|
||||
pub nat_type: String,
|
||||
pub public_ips: String,
|
||||
pub local_ip: String,
|
||||
pub local_addr: String,
|
||||
pub ipv6_addr: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
@@ -28,7 +29,10 @@ pub struct DeviceItem {
|
||||
pub nat_type: String,
|
||||
pub public_ips: String,
|
||||
pub local_ip: String,
|
||||
pub ipv6: String,
|
||||
pub nat_traversal_type: String,
|
||||
pub rt: String,
|
||||
pub status: String,
|
||||
}
|
||||
pub client_secret: bool,
|
||||
pub current_client_secret: bool,
|
||||
}
|
||||
|
||||
+45
-17
@@ -1,11 +1,11 @@
|
||||
use crate::command::entity::{DeviceItem, Info, RouteItem};
|
||||
use crate::console_out;
|
||||
use std::io;
|
||||
use vnt::core::Vnt;
|
||||
use crate::command::entity::{DeviceItem, RouteItem, Info};
|
||||
use crate::console_out;
|
||||
|
||||
pub mod client;
|
||||
pub mod server;
|
||||
pub mod entity;
|
||||
pub mod server;
|
||||
|
||||
pub enum CommandEnum {
|
||||
Route,
|
||||
@@ -51,7 +51,9 @@ pub fn command_route(vnt: &Vnt) -> Vec<RouteItem> {
|
||||
let route_table = vnt.route_table();
|
||||
let mut route_list = Vec::with_capacity(route_table.len());
|
||||
for (destination, route) in route_table {
|
||||
let next_hop = vnt.route_key(&route.route_key()).map_or(String::new(), |v| v.to_string());
|
||||
let next_hop = vnt
|
||||
.route_key(&route.route_key())
|
||||
.map_or(String::new(), |v| v.to_string());
|
||||
let metric = route.metric.to_string();
|
||||
let rt = if route.rt < 0 {
|
||||
"".to_string()
|
||||
@@ -72,22 +74,39 @@ pub fn command_route(vnt: &Vnt) -> Vec<RouteItem> {
|
||||
}
|
||||
|
||||
pub fn command_list(vnt: &Vnt) -> Vec<DeviceItem> {
|
||||
let info = vnt.current_device();
|
||||
let device_list = vnt.device_list();
|
||||
let mut list = Vec::new();
|
||||
let current_client_secret = vnt.client_encrypt();
|
||||
for peer in device_list {
|
||||
let name = peer.name;
|
||||
let virtual_ip = peer.virtual_ip.to_string();
|
||||
let (nat_type, public_ips, local_ip) = if let Some(nat_info) = vnt.peer_nat_info(&peer.virtual_ip) {
|
||||
let nat_type = format!("{:?}", nat_info.nat_type);
|
||||
let public_ips: Vec<String> = nat_info.public_ips.iter().map(|v| v.to_string()).collect();
|
||||
let public_ips = public_ips.join(",");
|
||||
let local_ip = nat_info.local_ip.to_string();
|
||||
(nat_type, public_ips, local_ip)
|
||||
} else {
|
||||
("".to_string(), "".to_string(), "".to_string())
|
||||
};
|
||||
let (nat_type, public_ips, local_ip, ipv6) =
|
||||
if let Some(nat_info) = vnt.peer_nat_info(&peer.virtual_ip) {
|
||||
let nat_type = format!("{:?}", nat_info.nat_type);
|
||||
let public_ips: Vec<String> =
|
||||
nat_info.public_ips.iter().map(|v| v.to_string()).collect();
|
||||
let public_ips = public_ips.join(",");
|
||||
let local_ip = nat_info.local_ipv4_addr.ip().to_string();
|
||||
let ipv6 = nat_info.ipv6_addr.ip().to_string();
|
||||
(nat_type, public_ips, local_ip, ipv6)
|
||||
} else {
|
||||
(
|
||||
"".to_string(),
|
||||
"".to_string(),
|
||||
"".to_string(),
|
||||
"".to_string(),
|
||||
)
|
||||
};
|
||||
let (nat_traversal_type, rt) = if let Some(route) = vnt.route(&peer.virtual_ip) {
|
||||
let nat_traversal_type = if route.metric == 1 { "p2p" } else { "relay" }.to_string();
|
||||
let nat_traversal_type = if route.metric == 1 {
|
||||
"p2p"
|
||||
} else if route.addr == info.connect_server {
|
||||
"server-relay"
|
||||
} else {
|
||||
"client-relay"
|
||||
}
|
||||
.to_string();
|
||||
let rt = if route.rt < 0 {
|
||||
"".to_string()
|
||||
} else {
|
||||
@@ -98,15 +117,19 @@ pub fn command_list(vnt: &Vnt) -> Vec<DeviceItem> {
|
||||
("relay".to_string(), "".to_string())
|
||||
};
|
||||
let status = format!("{:?}", peer.status);
|
||||
let client_secret = peer.client_secret;
|
||||
let item = DeviceItem {
|
||||
name,
|
||||
virtual_ip,
|
||||
nat_type,
|
||||
public_ips,
|
||||
local_ip,
|
||||
ipv6,
|
||||
nat_traversal_type,
|
||||
rt,
|
||||
status,
|
||||
client_secret,
|
||||
current_client_secret,
|
||||
};
|
||||
list.push(item);
|
||||
}
|
||||
@@ -125,7 +148,12 @@ pub fn command_info(vnt: &Vnt) -> Info {
|
||||
let nat_type = format!("{:?}", nat_info.nat_type);
|
||||
let public_ips: Vec<String> = nat_info.public_ips.iter().map(|v| v.to_string()).collect();
|
||||
let public_ips = public_ips.join(",");
|
||||
let local_ip = nat_info.local_ip.to_string();
|
||||
let local_addr = nat_info.local_ipv4_addr.to_string();
|
||||
let ipv6_addr = if nat_info.ipv6_addr.ip().is_unspecified() {
|
||||
"None".to_string()
|
||||
} else {
|
||||
nat_info.ipv6_addr.ip().to_string()
|
||||
};
|
||||
Info {
|
||||
name,
|
||||
virtual_ip,
|
||||
@@ -135,7 +163,7 @@ pub fn command_info(vnt: &Vnt) -> Info {
|
||||
relay_server,
|
||||
nat_type,
|
||||
public_ips,
|
||||
local_ip,
|
||||
local_addr,
|
||||
ipv6_addr,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
use std::io;
|
||||
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||
use std::io::Write;
|
||||
use tokio::net::UdpSocket;
|
||||
|
||||
use vnt::core::Vnt;
|
||||
|
||||
|
||||
pub struct CommandServer {}
|
||||
|
||||
impl CommandServer {
|
||||
@@ -15,27 +14,11 @@ impl CommandServer {
|
||||
|
||||
impl CommandServer {
|
||||
pub async fn start(self, vnt: Vnt) -> io::Result<()> {
|
||||
let mut port = 21637 as u16;
|
||||
let udp = loop {
|
||||
match UdpSocket::bind(SocketAddr::V4(SocketAddrV4::new(
|
||||
Ipv4Addr::new(127, 0, 0, 1),
|
||||
port,
|
||||
))).await {
|
||||
Ok(udp) => {
|
||||
break udp;
|
||||
}
|
||||
Err(e) => {
|
||||
if e.kind() == io::ErrorKind::AddrInUse {
|
||||
port += 1;
|
||||
} else {
|
||||
log::error!("创建udp失败 {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let udp = UdpSocket::bind("127.0.0.1:0").await?;
|
||||
let path_buf = crate::app_home()?.join("command-port");
|
||||
std::fs::write(path_buf, udp.local_addr()?.port().to_string())?;
|
||||
let mut file = std::fs::File::create(path_buf)?;
|
||||
file.write_all(udp.local_addr()?.port().to_string().as_bytes())?;
|
||||
file.sync_all()?;
|
||||
let mut buf = [0u8; 64];
|
||||
loop {
|
||||
let (len, addr) = udp.recv_from(&mut buf).await?;
|
||||
@@ -57,39 +40,26 @@ impl CommandServer {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn command(cmd: &str, vnt: &Vnt) -> io::Result<String> {
|
||||
let out_str = match cmd {
|
||||
"route" => {
|
||||
match serde_json::to_string(&crate::command::command_route(vnt)) {
|
||||
Ok(str) => {
|
||||
str
|
||||
}
|
||||
Err(e) => {
|
||||
format!("{:?}", e)
|
||||
}
|
||||
"route" => match serde_json::to_string(&crate::command::command_route(vnt)) {
|
||||
Ok(str) => str,
|
||||
Err(e) => {
|
||||
format!("{:?}", e)
|
||||
}
|
||||
}
|
||||
"list" => {
|
||||
match serde_json::to_string(&crate::command::command_list(vnt)) {
|
||||
Ok(str) => {
|
||||
str
|
||||
}
|
||||
Err(e) => {
|
||||
format!("{:?}", e)
|
||||
}
|
||||
},
|
||||
"list" => match serde_json::to_string(&crate::command::command_list(vnt)) {
|
||||
Ok(str) => str,
|
||||
Err(e) => {
|
||||
format!("{:?}", e)
|
||||
}
|
||||
}
|
||||
"info" => {
|
||||
match serde_json::to_string(&crate::command::command_info(vnt)) {
|
||||
Ok(str) => {
|
||||
str
|
||||
}
|
||||
Err(e) => {
|
||||
format!("{:?}", e)
|
||||
}
|
||||
},
|
||||
"info" => match serde_json::to_string(&crate::command::command_info(vnt)) {
|
||||
Ok(str) => str,
|
||||
Err(e) => {
|
||||
format!("{:?}", e)
|
||||
}
|
||||
}
|
||||
},
|
||||
"stop" => {
|
||||
vnt.stop()?;
|
||||
"stopped".to_string()
|
||||
|
||||
+106
-67
@@ -1,6 +1,6 @@
|
||||
use console::{style, Style};
|
||||
|
||||
use crate::command::entity::{DeviceItem, RouteItem, Info};
|
||||
use crate::command::entity::{DeviceItem, Info, RouteItem};
|
||||
|
||||
pub mod table;
|
||||
|
||||
@@ -9,11 +9,15 @@ pub fn console_info(status: Info) {
|
||||
println!("Virtual ip: {}", style(status.virtual_ip).green());
|
||||
println!("Virtual gateway: {}", style(status.virtual_gateway).green());
|
||||
println!("Virtual netmask: {}", style(status.virtual_netmask).green());
|
||||
println!("Connection status: {}", style(status.connect_status).green());
|
||||
println!(
|
||||
"Connection status: {}",
|
||||
style(status.connect_status).green()
|
||||
);
|
||||
println!("NAT type: {}", style(status.nat_type).green());
|
||||
println!("Relay server: {}", style(status.relay_server).green());
|
||||
println!("Public ips: {}", style(status.public_ips).green());
|
||||
println!("Local ip: {}", style(status.local_ip).green());
|
||||
println!("Local addr: {}", style(status.local_addr).green());
|
||||
println!("IPv6: {}", style(status.ipv6_addr).green());
|
||||
}
|
||||
|
||||
pub fn console_route_table(mut list: Vec<RouteItem>) {
|
||||
@@ -24,17 +28,21 @@ pub fn console_route_table(mut list: Vec<RouteItem>) {
|
||||
list.sort_by(|t1, t2| t1.destination.cmp(&t2.destination));
|
||||
let mut out_list = Vec::with_capacity(list.len());
|
||||
|
||||
out_list.push(vec![("Destination".to_string(), Style::new()),
|
||||
("Next Hop".to_string(), Style::new()),
|
||||
("Metric".to_string(), Style::new()),
|
||||
("Rt".to_string(), Style::new()),
|
||||
("Interface".to_string(), Style::new()), ]);
|
||||
out_list.push(vec![
|
||||
("Destination".to_string(), Style::new()),
|
||||
("Next Hop".to_string(), Style::new()),
|
||||
("Metric".to_string(), Style::new()),
|
||||
("Rt".to_string(), Style::new()),
|
||||
("Interface".to_string(), Style::new()),
|
||||
]);
|
||||
for item in list {
|
||||
out_list.push(vec![(item.destination, Style::new().green()),
|
||||
(item.next_hop, Style::new().green()),
|
||||
(item.metric, Style::new().green()),
|
||||
(item.rt, Style::new().green()),
|
||||
(item.interface, Style::new().green())]);
|
||||
out_list.push(vec![
|
||||
(item.destination, Style::new().green()),
|
||||
(item.next_hop, Style::new().green()),
|
||||
(item.metric, Style::new().green()),
|
||||
(item.rt, Style::new().green()),
|
||||
(item.interface, Style::new().green()),
|
||||
]);
|
||||
}
|
||||
|
||||
table::println_table(out_list)
|
||||
@@ -49,32 +57,51 @@ pub fn console_device_list(mut list: Vec<DeviceItem>) {
|
||||
list.sort_by(|t1, t2| t1.status.cmp(&t2.status));
|
||||
let mut out_list = Vec::with_capacity(list.len());
|
||||
//表头
|
||||
out_list.push(vec![("Name".to_string(), Style::new()),
|
||||
("Virtual Ip".to_string(), Style::new()),
|
||||
("Status".to_string(), Style::new()),
|
||||
("P2P/Relay".to_string(), Style::new()),
|
||||
("Rt".to_string(), Style::new())]);
|
||||
out_list.push(vec![
|
||||
("Name".to_string(), Style::new()),
|
||||
("Virtual Ip".to_string(), Style::new()),
|
||||
("Status".to_string(), Style::new()),
|
||||
("P2P/Relay".to_string(), Style::new()),
|
||||
("Rt".to_string(), Style::new()),
|
||||
]);
|
||||
for item in list {
|
||||
if &item.status == "Online" {
|
||||
if &item.nat_traversal_type == "p2p" {
|
||||
out_list.push(vec![(item.name, Style::new().green()),
|
||||
(item.virtual_ip, Style::new().green()),
|
||||
(item.status, Style::new().green()),
|
||||
(item.nat_traversal_type, Style::new().green()),
|
||||
(item.rt, Style::new().green())]);
|
||||
if item.client_secret != item.current_client_secret {
|
||||
//加密状态不一致,无法通信的
|
||||
out_list.push(vec![
|
||||
(item.name, Style::new().red()),
|
||||
(item.virtual_ip, Style::new().red()),
|
||||
(item.status, Style::new().red()),
|
||||
("".to_string(), Style::new().red()),
|
||||
("".to_string(), Style::new().red()),
|
||||
]);
|
||||
} else {
|
||||
out_list.push(vec![(item.name, Style::new().yellow()),
|
||||
(item.virtual_ip, Style::new().yellow()),
|
||||
(item.status, Style::new().yellow()),
|
||||
(item.nat_traversal_type, Style::new().yellow()),
|
||||
(item.rt, Style::new().yellow())]);
|
||||
if &item.nat_traversal_type == "p2p" {
|
||||
out_list.push(vec![
|
||||
(item.name, Style::new().green()),
|
||||
(item.virtual_ip, Style::new().green()),
|
||||
(item.status, Style::new().green()),
|
||||
(item.nat_traversal_type, Style::new().green()),
|
||||
(item.rt, Style::new().green()),
|
||||
]);
|
||||
} else {
|
||||
out_list.push(vec![
|
||||
(item.name, Style::new().yellow()),
|
||||
(item.virtual_ip, Style::new().yellow()),
|
||||
(item.status, Style::new().yellow()),
|
||||
(item.nat_traversal_type, Style::new().yellow()),
|
||||
(item.rt, Style::new().yellow()),
|
||||
]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out_list.push(vec![(item.name, Style::new().color256(102)),
|
||||
(item.virtual_ip, Style::new().color256(102)),
|
||||
(item.status, Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102))]);
|
||||
out_list.push(vec![
|
||||
(item.name, Style::new().color256(102)),
|
||||
(item.virtual_ip, Style::new().color256(102)),
|
||||
(item.status, Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)),
|
||||
]);
|
||||
}
|
||||
}
|
||||
table::println_table(out_list)
|
||||
@@ -89,45 +116,57 @@ pub fn console_device_list_all(mut list: Vec<DeviceItem>) {
|
||||
list.sort_by(|t1, t2| t1.status.cmp(&t2.status));
|
||||
let mut out_list = Vec::with_capacity(list.len());
|
||||
//表头
|
||||
out_list.push(vec![("Name".to_string(), Style::new()),
|
||||
("Virtual Ip".to_string(), Style::new()),
|
||||
("Status".to_string(), Style::new()),
|
||||
("NAT Type".to_string(), Style::new()),
|
||||
("Public Ips".to_string(), Style::new()),
|
||||
("Local Ip".to_string(), Style::new()),
|
||||
("P2P/Relay".to_string(), Style::new()),
|
||||
("Rt".to_string(), Style::new())]);
|
||||
out_list.push(vec![
|
||||
("Name".to_string(), Style::new()),
|
||||
("Virtual Ip".to_string(), Style::new()),
|
||||
("Status".to_string(), Style::new()),
|
||||
("P2P/Relay".to_string(), Style::new()),
|
||||
("Rt".to_string(), Style::new()),
|
||||
("NAT Type".to_string(), Style::new()),
|
||||
("Public Ips".to_string(), Style::new()),
|
||||
("Local Ip".to_string(), Style::new()),
|
||||
("IPv6".to_string(), Style::new()),
|
||||
]);
|
||||
for item in list {
|
||||
if &item.status == "Online" {
|
||||
if &item.nat_traversal_type == "p2p" {
|
||||
out_list.push(vec![(item.name, Style::new().green()),
|
||||
(item.virtual_ip, Style::new().green()),
|
||||
(item.status, Style::new().green()),
|
||||
(item.nat_traversal_type, Style::new().green()),
|
||||
(item.rt, Style::new().green()),
|
||||
(item.nat_type, Style::new().green()),
|
||||
(item.public_ips, Style::new().green()),
|
||||
(item.local_ip, Style::new().green())]);
|
||||
out_list.push(vec![
|
||||
(item.name, Style::new().green()),
|
||||
(item.virtual_ip, Style::new().green()),
|
||||
(item.status, Style::new().green()),
|
||||
(item.nat_traversal_type, Style::new().green()),
|
||||
(item.rt, Style::new().green()),
|
||||
(item.nat_type, Style::new().green()),
|
||||
(item.public_ips, Style::new().green()),
|
||||
(item.local_ip, Style::new().green()),
|
||||
(item.ipv6, Style::new().green()),
|
||||
]);
|
||||
} else {
|
||||
out_list.push(vec![(item.name, Style::new().yellow()),
|
||||
(item.virtual_ip, Style::new().yellow()),
|
||||
(item.status, Style::new().yellow()),
|
||||
(item.nat_traversal_type, Style::new().yellow()),
|
||||
(item.rt, Style::new().yellow()),
|
||||
(item.nat_type, Style::new().yellow()),
|
||||
(item.public_ips, Style::new().yellow()),
|
||||
(item.local_ip, Style::new().yellow()), ]);
|
||||
out_list.push(vec![
|
||||
(item.name, Style::new().yellow()),
|
||||
(item.virtual_ip, Style::new().yellow()),
|
||||
(item.status, Style::new().yellow()),
|
||||
(item.nat_traversal_type, Style::new().yellow()),
|
||||
(item.rt, Style::new().yellow()),
|
||||
(item.nat_type, Style::new().yellow()),
|
||||
(item.public_ips, Style::new().yellow()),
|
||||
(item.local_ip, Style::new().yellow()),
|
||||
(item.ipv6, Style::new().yellow()),
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
out_list.push(vec![(item.name, Style::new().color256(102)),
|
||||
(item.virtual_ip, Style::new().color256(102)),
|
||||
(item.status, Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)), ]);
|
||||
out_list.push(vec![
|
||||
(item.name, Style::new().color256(102)),
|
||||
(item.virtual_ip, Style::new().color256(102)),
|
||||
(item.status, Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)),
|
||||
("".to_string(), Style::new().color256(102)),
|
||||
]);
|
||||
}
|
||||
}
|
||||
table::println_table(out_list)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ pub fn println_table(table: Vec<Vec<(String, Style)>>) {
|
||||
let mut width_list = vec![0; table[0].len()];
|
||||
for in_list in table.iter() {
|
||||
for (index, (item, _)) in in_list.iter().enumerate() {
|
||||
let width = console::measure_text_width(item) + 6;
|
||||
let width = console::measure_text_width(item) + 4;
|
||||
if width_list[index] < width {
|
||||
width_list[index] = width;
|
||||
}
|
||||
@@ -20,4 +20,4 @@ pub fn println_table(table: Vec<Vec<(String, Style)>>) {
|
||||
}
|
||||
println!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+286
-121
@@ -2,11 +2,17 @@ use std::io;
|
||||
use std::net::{Ipv4Addr, ToSocketAddrs};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
use console::style;
|
||||
use getopts::Options;
|
||||
use tokio::io::{AsyncBufReadExt, BufReader};
|
||||
use common::args_parse::ips_parse;
|
||||
use vnt::core::{Config, VntUtil};
|
||||
use tokio::signal;
|
||||
|
||||
use common::args_parse::{ips_parse, out_ips_parse};
|
||||
use vnt::channel::punch::PunchModel;
|
||||
use vnt::cipher::CipherModel;
|
||||
use vnt::core::{Config, Vnt, VntUtil};
|
||||
use vnt::handle::handshake_handler::HandshakeEnum;
|
||||
use vnt::handle::registration_handler::ReqEnum;
|
||||
|
||||
mod command;
|
||||
@@ -14,48 +20,55 @@ mod console_out;
|
||||
mod root_check;
|
||||
|
||||
pub fn app_home() -> io::Result<PathBuf> {
|
||||
let path = dirs::home_dir().ok_or(io::Error::new(io::ErrorKind::Other, "not home"))?.join(".vnt-cli");
|
||||
let path = dirs::home_dir()
|
||||
.ok_or(io::Error::new(io::ErrorKind::Other, "not home"))?
|
||||
.join(".vnt-cli");
|
||||
if !path.exists() {
|
||||
std::fs::create_dir_all(&path)?;
|
||||
}
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
main0().await;
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
async fn main0() {
|
||||
fn main() {
|
||||
let _ = log4rs::init_file("log4rs.yaml", Default::default());
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let program = args[0].clone();
|
||||
let mut opts = Options::new();
|
||||
opts.long_only(false);
|
||||
opts.optopt("k", "", &format!("{}", green("必选,使用相同的token,就能组建一个局域网络".to_string())), "<token>");
|
||||
opts.optopt("n", "", "给设备一个名字,默认使用系统版本", "<name>");
|
||||
opts.optopt("d", "", "设备唯一标识符,不使用--ip参数时,服务端凭此参数分配ip", "<id>");
|
||||
opts.optflag("c", "", "关闭交互式命令,使用此参数禁用控制台输入");
|
||||
opts.optopt("k", "", "组网标识", "<token>");
|
||||
opts.optopt("n", "", "设备名称", "<name>");
|
||||
opts.optopt("d", "", "设备标识", "<id>");
|
||||
opts.optflag("c", "", "关闭交互式命令");
|
||||
opts.optopt("s", "", "注册和中继服务器地址", "<server>");
|
||||
opts.optopt("e", "", "NAT探测服务器地址,使用逗号分隔", "<addr1,addr2>");
|
||||
opts.optflag("a", "", "使用tap模式,默认使用tun模式");
|
||||
opts.optmulti("i", "", "配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3,表示允许接收网段192.168.0.0/24的数据并转发到10.26.0.3", "<in-ip>");
|
||||
opts.optmulti("o", "", "配置点对网时使用,-o 192.168.0.0/24,192.168.0.10,表示允许目标为192.168.0.0/24的数据从网卡192.168.0.10转发出去", "<out-ip>");
|
||||
opts.optopt("w", "", "使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信", "<password>");
|
||||
opts.optflag("m", "", "模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送");
|
||||
opts.optopt("u", "", "虚拟网卡mtu值", "<mtu>");
|
||||
opts.optflag("", "tcp", "和服务端使用tcp通信,默认使用udp,一般来说udp延迟和消耗更低");
|
||||
opts.optopt("", "ip", "指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配", "<IP>");
|
||||
opts.optflag("", "relay", "仅使用服务器转发,不使用p2p,默认情况允许使用p2p");
|
||||
opts.optmulti("e", "", "stun服务器", "<stun-server>");
|
||||
opts.optflag("a", "", "使用tap模式");
|
||||
opts.optmulti("i", "", "配置点对网(IP代理)入站时使用", "<in-ip>");
|
||||
opts.optmulti("o", "", "配置点对网出站时使用", "<out-ip>");
|
||||
opts.optopt("w", "", "客户端加密", "<password>");
|
||||
opts.optflag("W", "", "服务端加密");
|
||||
opts.optflag("m", "", "模拟组播");
|
||||
opts.optopt("u", "", "自定义mtu(默认为1430)", "<mtu>");
|
||||
opts.optflag("", "tcp", "tcp");
|
||||
opts.optopt("", "ip", "指定虚拟ip", "<ip>");
|
||||
opts.optflag("", "relay", "仅使用服务器转发");
|
||||
opts.optopt("", "par", "任务并行度(必须为正整数)", "<parallel>");
|
||||
opts.optopt("", "thread", "线程数(必须为正整数)", "<thread>");
|
||||
opts.optopt("", "model", "加密模式", "<model>");
|
||||
opts.optflag("", "finger", "指纹校验");
|
||||
opts.optopt(
|
||||
"",
|
||||
"punch",
|
||||
"取值ipv4/ipv6,表示仅使用ipv4或ipv6打洞",
|
||||
"<punch>",
|
||||
);
|
||||
//"后台运行时,查看其他设备列表"
|
||||
opts.optflag("", "list", &format!("{}", yellow("后台运行时,查看其他设备列表".to_string())));
|
||||
opts.optflag("", "all", &format!("{}", yellow("后台运行时,查看其他设备完整信息".to_string())));
|
||||
opts.optflag("", "info", &format!("{}", yellow("后台运行时,查看当前设备信息".to_string())));
|
||||
opts.optflag("", "route", &format!("{}", yellow("后台运行时,查看数据转发路径".to_string())));
|
||||
opts.optflag("", "stop", &format!("{}", yellow("停止后台运行".to_string())));
|
||||
opts.optflag("", "list", "后台运行时,查看其他设备列表");
|
||||
opts.optflag("", "all", "后台运行时,查看其他设备完整信息");
|
||||
opts.optflag("", "info", "后台运行时,查看当前设备信息");
|
||||
opts.optflag("", "route", "后台运行时,查看数据转发路径");
|
||||
opts.optflag("", "stop", "停止后台运行");
|
||||
opts.optflag("h", "help", "帮助");
|
||||
let matches = match opts.parse(&args[1..]) {
|
||||
Ok(m) => { m }
|
||||
Ok(m) => m,
|
||||
Err(f) => {
|
||||
print_usage(&program, opts);
|
||||
println!("{}", f.to_string());
|
||||
@@ -117,61 +130,67 @@ async fn main0() {
|
||||
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:29871".to_string()).unwrap();
|
||||
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 .");
|
||||
println!("parameter '-s {}' error .", server_address_str);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("parameter -s error {}.", e);
|
||||
println!("parameter '-s {}' error {}.", server_address_str, e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let nat_test_server = matches.opt_get_default("e",
|
||||
"nat1.wherewego.top:35061,nat1.wherewego.top:35062,nat2.wherewego.top:35061,nat2.wherewego.top:35062".to_string()).unwrap();
|
||||
|
||||
let nat_test_server = nat_test_server.split(",").flat_map(|a| a.to_socket_addrs()).flatten()
|
||||
.collect::<Vec<_>>();
|
||||
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 = 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!("-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 ips_parse(&out_ip) {
|
||||
Ok(out_ip) => { out_ip }
|
||||
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!("-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");
|
||||
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)
|
||||
}
|
||||
Ok(mtu) => Some(mtu),
|
||||
Err(e) => {
|
||||
print_usage(&program, opts);
|
||||
println!();
|
||||
println!("-u {}", e);
|
||||
println!("'-u {}' {}", mtu, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -179,55 +198,146 @@ async fn main0() {
|
||||
None
|
||||
};
|
||||
let virtual_ip: Option<String> = matches.opt_get("ip").unwrap();
|
||||
let virtual_ip = virtual_ip.map(|v| Ipv4Addr::from_str(&v).expect("--ip error"));
|
||||
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");
|
||||
println!("'--ip {}' invalid", virtual_ip);
|
||||
return;
|
||||
}
|
||||
}
|
||||
let tcp_channel = matches.opt_present("tcp");
|
||||
let relay = matches.opt_present("relay");
|
||||
let config = Config::new(tap,
|
||||
token, device_id, name,
|
||||
server_address, server_address_str,
|
||||
nat_test_server, in_ip,
|
||||
out_ip, password, simulate_multicast, mtu, tcp_channel, virtual_ip, relay);
|
||||
let parallel = matches.opt_get::<usize>("par").unwrap().unwrap_or(1);
|
||||
if parallel == 0 {
|
||||
println!("'--par {}' invalid", parallel);
|
||||
return;
|
||||
}
|
||||
|
||||
let cipher_model = matches
|
||||
.opt_get::<CipherModel>("model")
|
||||
.unwrap()
|
||||
.unwrap_or(CipherModel::AesGcm);
|
||||
|
||||
let finger = matches.opt_present("finger");
|
||||
let punch_model = matches
|
||||
.opt_get::<PunchModel>("punch")
|
||||
.unwrap()
|
||||
.unwrap_or(PunchModel::All);
|
||||
println!("version {}", vnt::VNT_VERSION);
|
||||
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,
|
||||
);
|
||||
main0(config, !unused_cmd);
|
||||
std::process::exit(0);
|
||||
}
|
||||
#[tokio::main]
|
||||
async fn main0(config: Config, show_cmd: bool) {
|
||||
let server_encrypt = config.server_encrypt;
|
||||
let mut vnt_util = VntUtil::new(config).await.unwrap();
|
||||
let mut conn_count = 0;
|
||||
let response = loop {
|
||||
match vnt_util.connect().await {
|
||||
if conn_count > 0 {
|
||||
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
|
||||
}
|
||||
conn_count += 1;
|
||||
if let Err(e) = vnt_util.connect().await {
|
||||
println!("connect server failed {}", e);
|
||||
return;
|
||||
}
|
||||
match vnt_util.handshake().await {
|
||||
Ok(response) => {
|
||||
break response;
|
||||
}
|
||||
Err(e) => {
|
||||
match e {
|
||||
ReqEnum::TokenError => {
|
||||
println!("token error");
|
||||
}
|
||||
ReqEnum::AddressExhausted => {
|
||||
println!("address exhausted");
|
||||
}
|
||||
ReqEnum::Timeout => {
|
||||
println!("timeout...");
|
||||
continue;
|
||||
}
|
||||
ReqEnum::ServerError(str) => {
|
||||
println!("error:{}", str);
|
||||
continue;
|
||||
}
|
||||
ReqEnum::Other(str) => {
|
||||
println!("error:{}", str);
|
||||
continue;
|
||||
}
|
||||
ReqEnum::IpAlreadyExists => {
|
||||
println!("ip already exists");
|
||||
}
|
||||
ReqEnum::InvalidIp => {
|
||||
println!("invalid ip");
|
||||
if server_encrypt {
|
||||
let finger = response.unwrap().finger().unwrap();
|
||||
println!("{}{}", green("server fingerprint:".to_string()), finger);
|
||||
match vnt_util.secret_handshake().await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
match e {
|
||||
HandshakeEnum::NotSecret => {}
|
||||
HandshakeEnum::KeyError => {}
|
||||
HandshakeEnum::Timeout => {
|
||||
println!("handshake timeout")
|
||||
}
|
||||
HandshakeEnum::ServerError(str) => {
|
||||
println!("error:{}", str);
|
||||
}
|
||||
HandshakeEnum::Other(str) => {
|
||||
println!("error:{}", str);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
match vnt_util.register().await {
|
||||
Ok(response) => {
|
||||
break response;
|
||||
}
|
||||
Err(e) => match e {
|
||||
ReqEnum::TokenError => {
|
||||
println!("token error");
|
||||
return;
|
||||
}
|
||||
ReqEnum::AddressExhausted => {
|
||||
println!("address exhausted");
|
||||
return;
|
||||
}
|
||||
ReqEnum::Timeout => {
|
||||
println!("timeout...");
|
||||
}
|
||||
ReqEnum::ServerError(str) => {
|
||||
println!("error:{}", str);
|
||||
}
|
||||
ReqEnum::Other(str) => {
|
||||
println!("error:{}", str);
|
||||
}
|
||||
ReqEnum::IpAlreadyExists => {
|
||||
println!("ip already exists");
|
||||
return;
|
||||
}
|
||||
ReqEnum::InvalidIp => {
|
||||
println!("invalid ip");
|
||||
return;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
Err(e) => match e {
|
||||
HandshakeEnum::NotSecret => {
|
||||
println!("The server does not support encryption");
|
||||
return;
|
||||
}
|
||||
HandshakeEnum::KeyError => {}
|
||||
HandshakeEnum::Timeout => {
|
||||
println!("handshake timeout")
|
||||
}
|
||||
HandshakeEnum::ServerError(str) => {
|
||||
println!("error:{}", str);
|
||||
}
|
||||
HandshakeEnum::Other(str) => {
|
||||
println!("error:{}", str);
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
println!(" ====== Connect Successfully ====== ");
|
||||
@@ -238,9 +348,7 @@ async fn main0() {
|
||||
println!("name:{}", driver_info.name);
|
||||
println!("version:{}", driver_info.version);
|
||||
let mut vnt = match vnt_util.build().await {
|
||||
Ok(vnt) => {
|
||||
vnt
|
||||
}
|
||||
Ok(vnt) => vnt,
|
||||
Err(e) => {
|
||||
println!("error:{}", e);
|
||||
return;
|
||||
@@ -253,7 +361,7 @@ async fn main0() {
|
||||
println!("command error :{}", e);
|
||||
}
|
||||
});
|
||||
if !unused_cmd {
|
||||
if show_cmd {
|
||||
let stdin = tokio::io::stdin();
|
||||
let mut cmd = String::new();
|
||||
let mut reader = BufReader::new(stdin);
|
||||
@@ -262,39 +370,19 @@ async fn main0() {
|
||||
println!("input:list,info,route,all,stop");
|
||||
tokio::select! {
|
||||
_ = vnt.wait_stop()=>{
|
||||
break;
|
||||
return;
|
||||
}
|
||||
_ = signal::ctrl_c()=>{
|
||||
let _ = vnt.stop();
|
||||
vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await;
|
||||
std::process::exit(0);
|
||||
}
|
||||
rs = reader.read_line(&mut cmd)=>{
|
||||
match rs {
|
||||
Ok(len) => {
|
||||
if len ==0 {
|
||||
if !command(&cmd[..len],&vnt){
|
||||
break;
|
||||
}
|
||||
match cmd[..len].to_lowercase().trim() {
|
||||
"list" => {
|
||||
let list = command::command_list(&vnt);
|
||||
console_out::console_device_list(list);
|
||||
}
|
||||
"info"=>{
|
||||
let info = command::command_info(&vnt);
|
||||
console_out::console_info(info);
|
||||
}
|
||||
"route" =>{
|
||||
let route = command::command_route(&vnt);
|
||||
console_out::console_route_table(route);
|
||||
}
|
||||
"all" =>{
|
||||
let list = command::command_list(&vnt);
|
||||
console_out::console_device_list_all(list);
|
||||
}
|
||||
"stop" =>{
|
||||
let _ = vnt.stop();
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
Err(e) => {
|
||||
println!("input err:{}",e);
|
||||
@@ -308,10 +396,88 @@ async fn main0() {
|
||||
vnt.wait_stop().await;
|
||||
}
|
||||
|
||||
fn print_usage(program: &str, opts: Options) {
|
||||
let brief = format!("Usage: {} [options]", program);
|
||||
println!("version:1.1.1");
|
||||
println!("{}", opts.usage(&brief));
|
||||
fn command(cmd: &str, vnt: &Vnt) -> bool {
|
||||
if cmd.is_empty() {
|
||||
return false;
|
||||
}
|
||||
match cmd.to_lowercase().trim() {
|
||||
"list" => {
|
||||
let list = command::command_list(&vnt);
|
||||
console_out::console_device_list(list);
|
||||
}
|
||||
"info" => {
|
||||
let info = command::command_info(&vnt);
|
||||
console_out::console_info(info);
|
||||
}
|
||||
"route" => {
|
||||
let route = command::command_route(&vnt);
|
||||
console_out::console_route_table(route);
|
||||
}
|
||||
"all" => {
|
||||
let list = command::command_list(&vnt);
|
||||
console_out::console_device_list_all(list);
|
||||
}
|
||||
"stop" => {
|
||||
let _ = vnt.stop();
|
||||
return false;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
println!();
|
||||
return true;
|
||||
}
|
||||
|
||||
fn print_usage(program: &str, _opts: Options) {
|
||||
println!("Usage: {} [options]", program);
|
||||
println!("version:{}", vnt::VNT_VERSION);
|
||||
println!("Options:");
|
||||
println!(
|
||||
" -k <token> {}",
|
||||
green("必选,使用相同的token,就能组建一个局域网络".to_string())
|
||||
);
|
||||
println!(" -n <name> 给设备一个名字,便于区分不同设备,默认使用系统版本");
|
||||
println!(" -d <id> 设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip");
|
||||
println!(" -c 关闭交互式命令,使用此参数禁用控制台输入");
|
||||
println!(" -s <server> 注册和中继服务器地址");
|
||||
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可多次指定,如-e addr1 -e addr2");
|
||||
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!(" 并转发到10.26.0.3,可指定多个网段");
|
||||
println!(" -o <out-ip> 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段");
|
||||
println!(" -w <password> 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信");
|
||||
println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确");
|
||||
println!(" -m 模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送");
|
||||
println!(" -u <mtu> 自定义mtu(不加密默认为1450,加密默认为1410)");
|
||||
println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp");
|
||||
println!(" --ip <ip> 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配");
|
||||
println!(" --relay 仅使用服务器转发,不使用p2p,默认情况允许使用p2p");
|
||||
println!(" --par <parallel> 任务并行度(必须为正整数),默认值为1");
|
||||
println!(" --model <model> 加密模式(默认aes_gcm),可选值aes_gcm/aes_cbc/aes_ecb,一般来说性能:aes_ecb>aes_cbc>aes_gcm");
|
||||
println!(" --finger 增加数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启");
|
||||
println!(" --punch <punch> 取值ipv4/ipv6,ipv4表示仅使用ipv4打洞");
|
||||
|
||||
println!();
|
||||
println!(
|
||||
" --list {}",
|
||||
yellow("后台运行时,查看其他设备列表".to_string())
|
||||
);
|
||||
println!(
|
||||
" --all {}",
|
||||
yellow("后台运行时,查看其他设备完整信息".to_string())
|
||||
);
|
||||
println!(
|
||||
" --info {}",
|
||||
yellow("后台运行时,查看当前设备信息".to_string())
|
||||
);
|
||||
println!(
|
||||
" --route {}",
|
||||
yellow("后台运行时,查看数据转发路径".to_string())
|
||||
);
|
||||
println!(
|
||||
" --stop {}",
|
||||
yellow("停止后台运行".to_string())
|
||||
);
|
||||
println!(" -h, --help 帮助");
|
||||
}
|
||||
|
||||
fn green(str: String) -> impl std::fmt::Display {
|
||||
@@ -321,4 +487,3 @@ fn green(str: String) -> impl std::fmt::Display {
|
||||
fn yellow(str: String) -> impl std::fmt::Display {
|
||||
style(str).yellow()
|
||||
}
|
||||
|
||||
|
||||
@@ -8,4 +8,4 @@ pub use windows::is_app_elevated;
|
||||
mod unix;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
pub use unix::is_app_elevated;
|
||||
pub use unix::is_app_elevated;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
pub fn is_app_elevated() -> bool {
|
||||
sudo::RunningAs::Root == sudo::check()
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,11 +1,12 @@
|
||||
[package]
|
||||
name = "vnt-jni"
|
||||
version = "0.1.0"
|
||||
version = "1.2.3"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
common = { path = "../common" }
|
||||
vnt = {path="../vnt"}
|
||||
|
||||
jni = { version = "0.21.1", default-features = false }
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
pub mod vnt;
|
||||
pub mod vnt_util;
|
||||
pub mod vnt;
|
||||
+19
-15
@@ -1,8 +1,8 @@
|
||||
use std::ptr;
|
||||
use jni::errors::Error;
|
||||
use jni::JNIEnv;
|
||||
use jni::objects::{JClass, JObject, JValue};
|
||||
use jni::sys::{jboolean, jbyte, jint, jlong, jobject, jobjectArray, jsize};
|
||||
use jni::JNIEnv;
|
||||
use std::ptr;
|
||||
use vnt::channel::Route;
|
||||
use vnt::core::sync::VntSync;
|
||||
use vnt::handle::PeerDeviceInfo;
|
||||
@@ -67,7 +67,7 @@ pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_list0(
|
||||
"top/wherewego/vnt/jni/PeerDeviceInfo",
|
||||
JObject::null(),
|
||||
) {
|
||||
Ok(arr) => { arr }
|
||||
Ok(arr) => arr,
|
||||
Err(e) => {
|
||||
env.throw_new("java/lang/RuntimeException", format!("error:{:?}", e))
|
||||
.expect("throw");
|
||||
@@ -77,12 +77,8 @@ pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_list0(
|
||||
for (index, peer) in list.into_iter().enumerate() {
|
||||
let route = if let Some(route) = vnt.route(&peer.virtual_ip) {
|
||||
match route_parse(&mut env, route) {
|
||||
Ok(route) => {
|
||||
JObject::from_raw(route)
|
||||
}
|
||||
Err(_) => {
|
||||
JObject::null()
|
||||
}
|
||||
Ok(route) => JObject::from_raw(route),
|
||||
Err(_) => JObject::null(),
|
||||
}
|
||||
} else {
|
||||
JObject::null()
|
||||
@@ -115,24 +111,32 @@ fn route_parse(env: &mut JNIEnv, route: Route) -> Result<jobject, Error> {
|
||||
let rs = env.new_object(
|
||||
"top/wherewego/vnt/jni/Route",
|
||||
"(Ljava/lang/String;BI)V",
|
||||
&[JValue::Object(&env.new_string(address)?.into()),
|
||||
&[
|
||||
JValue::Object(&env.new_string(address)?.into()),
|
||||
JValue::Byte(metric as jbyte),
|
||||
JValue::Int(rt as jint)],
|
||||
JValue::Int(rt as jint),
|
||||
],
|
||||
)?;
|
||||
Ok(rs.as_raw())
|
||||
}
|
||||
|
||||
fn peer_device_info_parse(env: &mut JNIEnv, peer: PeerDeviceInfo, route: JObject) -> Result<jobject, Error> {
|
||||
fn peer_device_info_parse(
|
||||
env: &mut JNIEnv,
|
||||
peer: PeerDeviceInfo,
|
||||
route: JObject,
|
||||
) -> Result<jobject, Error> {
|
||||
let virtual_ip = u32::from(peer.virtual_ip);
|
||||
let name = peer.name.to_string();
|
||||
let status = format!("{:?}", peer.status);
|
||||
let rs = env.new_object(
|
||||
"top/wherewego/vnt/jni/PeerDeviceInfo",
|
||||
"(ILjava/lang/String;Ljava/lang/String;Ltop/wherewego/vnt/jni/Route;)V",
|
||||
&[JValue::Int(virtual_ip as jint),
|
||||
&[
|
||||
JValue::Int(virtual_ip as jint),
|
||||
JValue::Object(&env.new_string(name)?.into()),
|
||||
JValue::Object(&env.new_string(status)?.into()),
|
||||
JValue::Object(&route)],
|
||||
JValue::Object(&route),
|
||||
],
|
||||
)?;
|
||||
Ok(rs.as_raw())
|
||||
}
|
||||
}
|
||||
|
||||
+196
-78
@@ -1,5 +1,6 @@
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::ptr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use jni::errors::Error;
|
||||
use jni::objects::{JClass, JObject, JString, JValue};
|
||||
@@ -7,16 +8,22 @@ use jni::objects::{JClass, JObject, JString, JValue};
|
||||
use jni::sys::jboolean;
|
||||
use jni::sys::{jint, jlong, jobject};
|
||||
use jni::JNIEnv;
|
||||
use vnt::core::Config;
|
||||
use vnt::channel::punch::PunchModel;
|
||||
use vnt::cipher::CipherModel;
|
||||
use vnt::core::sync::VntUtilSync;
|
||||
use vnt::core::Config;
|
||||
use vnt::handle::registration_handler::{RegResponse, ReqEnum};
|
||||
#[cfg(not(target_os = "android"))]
|
||||
use vnt::tun_tap_device::DriverInfo;
|
||||
|
||||
fn to_string_not_null(env: &mut JNIEnv, config: &JObject, name: &'static str) -> Result<String, Error> {
|
||||
fn to_string_not_null(
|
||||
env: &mut JNIEnv,
|
||||
config: &JObject,
|
||||
name: &'static str,
|
||||
) -> Result<String, Error> {
|
||||
let value = env.get_field(config, name, "Ljava/lang/String;")?.l()?;
|
||||
if value.is_null() {
|
||||
env.throw_new("Ljava/lang/NullPointerException", name)
|
||||
env.throw_new("java/lang/NullPointerException", name)
|
||||
.expect("throw");
|
||||
return Err(Error::NullPtr(name));
|
||||
}
|
||||
@@ -25,7 +32,7 @@ fn to_string_not_null(env: &mut JNIEnv, config: &JObject, name: &'static str) ->
|
||||
match value.to_str() {
|
||||
Ok(value) => Ok(value.to_string()),
|
||||
Err(_) => {
|
||||
env.throw_new("Ljava/lang/RuntimeException", "not utf-8")
|
||||
env.throw_new("java/lang/RuntimeException", "not utf-8")
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
@@ -42,7 +49,7 @@ fn to_string(env: &mut JNIEnv, config: &JObject, name: &str) -> Result<Option<St
|
||||
match value.to_str() {
|
||||
Ok(value) => Ok(Some(value.to_string())),
|
||||
Err(_) => {
|
||||
env.throw_new("Ljava/lang/RuntimeException", "not utf-8")
|
||||
env.throw_new("java/lang/RuntimeException", "not utf-8")
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
@@ -55,37 +62,102 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
|
||||
let device_id = to_string_not_null(env, &config, "deviceId")?;
|
||||
let password = to_string(env, &config, "password")?;
|
||||
let server_address_str = to_string_not_null(env, &config, "server")?;
|
||||
let nat_test_server = to_string_not_null(env, &config, "natTestServer")?;
|
||||
let stun_server_str = to_string_not_null(env, &config, "stunServer")?;
|
||||
let cipher_model = to_string_not_null(env, &config, "cipherModel")?;
|
||||
let tcp = env.get_field(&config, "tcp", "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 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() {
|
||||
Ok(mut rs) => {
|
||||
if let Some(addr) = rs.next() {
|
||||
addr
|
||||
} else {
|
||||
env.throw_new("Ljava/lang/RuntimeException", "server address err")
|
||||
env.throw_new("java/lang/RuntimeException", "server address err")
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
env.throw_new("Ljava/lang/RuntimeException", format!("server address {}", e))
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("server address {}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
};
|
||||
let cipher_model = match CipherModel::from_str(&cipher_model) {
|
||||
Ok(cipher_model) => cipher_model,
|
||||
Err(e) => {
|
||||
env.throw_new("java/lang/RuntimeException", format!("cipher_model {}", e))
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
};
|
||||
let nat_test_server = nat_test_server.split(",").flat_map(|a| a.trim().to_socket_addrs()).flatten()
|
||||
.collect::<Vec<_>>();
|
||||
let config = Config::new(false,
|
||||
token, device_id, name,
|
||||
server_address, server_address_str,
|
||||
nat_test_server, vec![],
|
||||
vec![], password, false, None, false, None, false);
|
||||
let mut stun_server = Vec::new();
|
||||
for addr in stun_server_str.split(",") {
|
||||
stun_server.push(addr.trim().to_string());
|
||||
}
|
||||
let config = Config::new(
|
||||
false,
|
||||
token,
|
||||
device_id,
|
||||
name,
|
||||
server_address,
|
||||
server_address_str,
|
||||
stun_server,
|
||||
in_ips,
|
||||
out_ips,
|
||||
password,
|
||||
false,
|
||||
None,
|
||||
tcp,
|
||||
None,
|
||||
false,
|
||||
false,
|
||||
1,
|
||||
cipher_model,
|
||||
finger,
|
||||
PunchModel::All,
|
||||
);
|
||||
match VntUtilSync::new(config) {
|
||||
Ok(vnt_util) => {
|
||||
Ok(vnt_util)
|
||||
}
|
||||
Ok(vnt_util) => Ok(vnt_util),
|
||||
Err(e) => {
|
||||
env.throw_new("Ljava/lang/RuntimeException", format!("vnt start error {}", e))
|
||||
.expect("throw");
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt start error {}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
@@ -112,52 +184,89 @@ pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_connect0(
|
||||
mut env: JNIEnv,
|
||||
_class: JClass,
|
||||
raw_vnt_util: jlong,
|
||||
) -> jobject {
|
||||
) {
|
||||
let raw_vnt_util = raw_vnt_util as *mut VntUtilSync;
|
||||
match (&mut *raw_vnt_util).connect() {
|
||||
Ok(response) => {
|
||||
match reg_response(&mut env, response) {
|
||||
Ok(res) => {
|
||||
return res;
|
||||
}
|
||||
Err(e) => {
|
||||
env.throw(format!("vnt connect error {}", e)).expect("throw");
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
match e {
|
||||
ReqEnum::TokenError => {
|
||||
env.throw_new("top/wherewego/vnt/jni/exception/TokenErrorException", "TokenError")
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::AddressExhausted => {
|
||||
env.throw_new("top/wherewego/vnt/jni/exception/AddressExhaustedException", "AddressExhausted")
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::Timeout => {
|
||||
env.throw_new("top/wherewego/vnt/jni/exception/TimeoutException", "Timeout")
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::ServerError(str) => {
|
||||
env.throw_new("java/lang/RuntimeException", format!("vnt connect error {}", str))
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::Other(str) => {
|
||||
env.throw_new("java/lang/RuntimeException", format!("vnt connect error {}", str))
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::IpAlreadyExists => {
|
||||
env.throw_new("top/wherewego/vnt/jni/exception/IpAlreadyExistsException", "IpAlreadyExists")
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::InvalidIp => {
|
||||
env.throw_new("top/wherewego/vnt/jni/exception/InvalidIpException", "InvalidIp")
|
||||
.expect("throw");
|
||||
}
|
||||
}
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt connect error {}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_register0(
|
||||
mut env: JNIEnv,
|
||||
_class: JClass,
|
||||
raw_vnt_util: jlong,
|
||||
) -> jobject {
|
||||
let raw_vnt_util = raw_vnt_util as *mut VntUtilSync;
|
||||
match (&mut *raw_vnt_util).register() {
|
||||
Ok(response) => match reg_response(&mut env, response) {
|
||||
Ok(res) => {
|
||||
return res;
|
||||
}
|
||||
Err(e) => {
|
||||
env.throw(format!("vnt register error {}", e))
|
||||
.expect("throw");
|
||||
}
|
||||
},
|
||||
Err(e) => match e {
|
||||
ReqEnum::TokenError => {
|
||||
env.throw_new(
|
||||
"top/wherewego/vnt/jni/exception/TokenErrorException",
|
||||
"TokenError",
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::AddressExhausted => {
|
||||
env.throw_new(
|
||||
"top/wherewego/vnt/jni/exception/AddressExhaustedException",
|
||||
"AddressExhausted",
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::Timeout => {
|
||||
env.throw_new(
|
||||
"top/wherewego/vnt/jni/exception/TimeoutException",
|
||||
"Timeout",
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::ServerError(str) => {
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt register error {}", str),
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::Other(str) => {
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt register error {}", str),
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::IpAlreadyExists => {
|
||||
env.throw_new(
|
||||
"top/wherewego/vnt/jni/exception/IpAlreadyExistsException",
|
||||
"IpAlreadyExists",
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::InvalidIp => {
|
||||
env.throw_new(
|
||||
"top/wherewego/vnt/jni/exception/InvalidIpException",
|
||||
"InvalidIp",
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
},
|
||||
}
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
@@ -184,19 +293,21 @@ pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_createIface0(
|
||||
let raw_vnt_util = raw_vnt_util as *mut VntUtilSync;
|
||||
let rs = (&mut *raw_vnt_util).create_iface();
|
||||
match rs {
|
||||
Ok(driver_info) => {
|
||||
match driver_info_e(&mut env, driver_info) {
|
||||
Ok(res) => {
|
||||
return res;
|
||||
}
|
||||
Err(e) => {
|
||||
env.throw(format!("vnt create iface error {}", e)).expect("throw");
|
||||
}
|
||||
Ok(driver_info) => match driver_info_e(&mut env, driver_info) {
|
||||
Ok(res) => {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
env.throw(format!("vnt create iface error {}", e))
|
||||
.expect("throw");
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
env.throw_new("java/lang/RuntimeException", format!("vnt create iface error {}", e))
|
||||
.expect("throw");
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt create iface error {}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
}
|
||||
return ptr::null_mut();
|
||||
@@ -214,8 +325,11 @@ pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_build0(
|
||||
return Box::into_raw(Box::new(rs)) as jlong;
|
||||
}
|
||||
Err(e) => {
|
||||
env.throw_new("java/lang/RuntimeException", format!("vnt start error:{:?}", e))
|
||||
.expect("throw");
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt start error:{:?}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -228,9 +342,11 @@ fn reg_response(env: &mut JNIEnv, response: RegResponse) -> Result<jobject, Erro
|
||||
let response = env.new_object(
|
||||
"top/wherewego/vnt/jni/RegResponse",
|
||||
"(III)V",
|
||||
&[JValue::Int(virtual_ip as jint),
|
||||
&[
|
||||
JValue::Int(virtual_ip as jint),
|
||||
JValue::Int(virtual_gateway as jint),
|
||||
JValue::Int(virtual_netmask as jint)],
|
||||
JValue::Int(virtual_netmask as jint),
|
||||
],
|
||||
)?;
|
||||
Ok(response.into_raw())
|
||||
}
|
||||
@@ -244,10 +360,12 @@ fn driver_info_e(env: &mut JNIEnv, driver_info: DriverInfo) -> Result<jobject, E
|
||||
let response = env.new_object(
|
||||
"top/wherewego/vnt/jni/DriverInfo",
|
||||
"(ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
|
||||
&[JValue::Bool(is_tun as jboolean),
|
||||
&[
|
||||
JValue::Bool(is_tun as jboolean),
|
||||
JValue::Object(&env.new_string(name)?.into()),
|
||||
JValue::Object(&env.new_string(version)?.into()),
|
||||
JValue::Object(&env.new_string(mac)?.into()), ],
|
||||
JValue::Object(&env.new_string(mac)?.into()),
|
||||
],
|
||||
)?;
|
||||
Ok(response.into_raw())
|
||||
}
|
||||
|
||||
+28
-8
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "vnt"
|
||||
version = "1.1.1"
|
||||
version = "1.2.3"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
@@ -11,25 +11,45 @@ bytes = "1.3.0"
|
||||
log = "0.4.17"
|
||||
libc = "0.2.137"
|
||||
crossbeam-utils = "0.8"
|
||||
crossbeam-skiplist = "0.1"
|
||||
crossbeam-epoch = "0.9.15"
|
||||
dashmap = "5.5.1"
|
||||
parking_lot = "0.12.1"
|
||||
byte-pool = "0.2.4"
|
||||
lazy_static = "1.4.0"
|
||||
rand = "0.8.5"
|
||||
sha2 = { version = "0.10.6", features = ["oid"] }
|
||||
aes-gcm = "0.10.2"
|
||||
|
||||
thiserror = "1.0.37"
|
||||
protobuf = "3.2.0"
|
||||
socket2 ={ version = "0.5.2", features = ["all"] }
|
||||
tokio = { version = "1.28.1", features = ["full"] }
|
||||
socket2 = { version = "0.5.2", features = ["all"] }
|
||||
tokio = { version = "1.32.0", features = ["full"] }
|
||||
aes-gcm = { version = "0.10.2" }
|
||||
ring = { version = "0.16.20", optional = true }
|
||||
cbc = "0.1.2"
|
||||
ecb = "0.1.2"
|
||||
aes = "0.8.3"
|
||||
stun-format = { version = "1.0.1", features = ["fmt", "rfc3489"] }
|
||||
rsa = { version = "0.7.2", features = [] }
|
||||
spki = { version = "0.6.0", features = ["fingerprint", "alloc"] }
|
||||
openssl-sys = { git = "https://github.com/lbl8603/rust-openssl" ,optional = true}
|
||||
|
||||
|
||||
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
|
||||
tun = { path = "./rust-tun" }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
|
||||
win-tun-tap = {path = "./win-tun-tap"}
|
||||
win-tun-tap = { path = "./win-tun-tap" }
|
||||
libloading = "0.7.4"
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
protobuf-codegen = "3.2.0"
|
||||
protoc-bin-vendored = "3.0.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
openssl = ["openssl-sys"]
|
||||
# 从源码编译
|
||||
openssl-vendored = ["openssl-sys/vendored"]
|
||||
ring-cipher = ["ring"]
|
||||
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ use std::{fmt, io};
|
||||
/// 地址解析协议,由IP地址找到MAC地址
|
||||
/// https://www.ietf.org/rfc/rfc6747.txt
|
||||
/*
|
||||
0 2 4 5 6 8 10 (字节)
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 硬件类型|协议类型|硬件地址长度|协议地址长度|操作类型|
|
||||
| 源MAC地址 | 源ip地址 |
|
||||
| 目的MAC地址 | 目的ip地址 |
|
||||
*/
|
||||
0 2 4 5 6 8 10 (字节)
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 硬件类型|协议类型|硬件地址长度|协议地址长度|操作类型|
|
||||
| 源MAC地址 | 源ip地址 |
|
||||
| 目的MAC地址 | 目的ip地址 |
|
||||
*/
|
||||
|
||||
pub struct ArpPacket<B> {
|
||||
buffer: B,
|
||||
@@ -119,4 +119,4 @@ impl<B: AsRef<[u8]>> fmt::Debug for ArpPacket<B> {
|
||||
.field("target_protocol_addr", &self.target_protocol_addr())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
pub mod arp;
|
||||
pub mod arp;
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
pub mod packet;
|
||||
pub mod protocol;
|
||||
pub mod protocol;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use std::{fmt, io};
|
||||
use crate::ethernet::protocol::Protocol;
|
||||
use std::{fmt, io};
|
||||
|
||||
/// 以太网帧协议
|
||||
/// https://www.ietf.org/rfc/rfc894.txt
|
||||
/*
|
||||
0 6 12 14 (字节)
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 目的地址 | 源地址 | 类型 |
|
||||
*/
|
||||
0 6 12 14 (字节)
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 目的地址 | 源地址 | 类型 |
|
||||
*/
|
||||
pub struct EthernetPacket<B> {
|
||||
pub buffer: B,
|
||||
}
|
||||
@@ -74,4 +74,4 @@ impl<B: AsRef<[u8]>> fmt::Debug for EthernetPacket<B> {
|
||||
.field("payload", &self.payload())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ impl From<u16> for Protocol {
|
||||
0x88f7 => Ptp,
|
||||
0x8902 => Cfm,
|
||||
0x9100 => QinQ,
|
||||
n => Unknown(n),
|
||||
n => Unknown(n),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,30 +112,30 @@ impl Into<u16> for Protocol {
|
||||
use self::Protocol::*;
|
||||
|
||||
match self {
|
||||
Ipv4 => 0x0800,
|
||||
Arp => 0x0806,
|
||||
WakeOnLan => 0x0842,
|
||||
Trill => 0x22f3,
|
||||
DecNet => 0x6003,
|
||||
Rarp => 0x8035,
|
||||
AppleTalk => 0x809b,
|
||||
Aarp => 0x80f3,
|
||||
Ipx => 0x8137,
|
||||
Qnx => 0x8204,
|
||||
Ipv6 => 0x86dd,
|
||||
FlowControl => 0x8808,
|
||||
CobraNet => 0x8819,
|
||||
Mpls => 0x8847,
|
||||
MplsMulticast => 0x8848,
|
||||
Ipv4 => 0x0800,
|
||||
Arp => 0x0806,
|
||||
WakeOnLan => 0x0842,
|
||||
Trill => 0x22f3,
|
||||
DecNet => 0x6003,
|
||||
Rarp => 0x8035,
|
||||
AppleTalk => 0x809b,
|
||||
Aarp => 0x80f3,
|
||||
Ipx => 0x8137,
|
||||
Qnx => 0x8204,
|
||||
Ipv6 => 0x86dd,
|
||||
FlowControl => 0x8808,
|
||||
CobraNet => 0x8819,
|
||||
Mpls => 0x8847,
|
||||
MplsMulticast => 0x8848,
|
||||
PppoeDiscovery => 0x8863,
|
||||
PppoeSession => 0x8864,
|
||||
Vlan => 0x8100,
|
||||
PBridge => 0x88a8,
|
||||
Lldp => 0x88cc,
|
||||
Ptp => 0x88f7,
|
||||
Cfm => 0x8902,
|
||||
QinQ => 0x9100,
|
||||
Unknown(n) => n,
|
||||
PppoeSession => 0x8864,
|
||||
Vlan => 0x8100,
|
||||
PBridge => 0x88a8,
|
||||
Lldp => 0x88cc,
|
||||
Ptp => 0x88f7,
|
||||
Cfm => 0x8902,
|
||||
QinQ => 0x9100,
|
||||
Unknown(n) => n,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::{fmt, io};
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use crate::cal_checksum;
|
||||
use crate::icmp::{Code, Kind};
|
||||
use crate::ip::ipv4::packet::IpV4Packet;
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use std::{fmt, io};
|
||||
|
||||
/// icmp 协议
|
||||
/* https://www.rfc-editor.org/rfc/rfc792
|
||||
@@ -67,7 +67,7 @@ impl<B: AsRef<[u8]>> IcmpPacket<B> {
|
||||
| Kind::TimestampReply
|
||||
| Kind::InformationRequest
|
||||
| Kind::InformationReply => {
|
||||
let ide =u16::from_be_bytes(self.buffer.as_ref()[4..6].try_into().unwrap());
|
||||
let ide = u16::from_be_bytes(self.buffer.as_ref()[4..6].try_into().unwrap());
|
||||
let seq = u16::from_be_bytes(self.buffer.as_ref()[6..8].try_into().unwrap());
|
||||
HeaderOther::Identifier(ide, seq)
|
||||
}
|
||||
@@ -121,11 +121,11 @@ impl<B: AsRef<[u8]>> fmt::Debug for IcmpPacket<B> {
|
||||
} else {
|
||||
"icmp::Packet!"
|
||||
})
|
||||
.field("kind", &self.kind())
|
||||
.field("code", &self.code())
|
||||
.field("checksum", &self.checksum())
|
||||
.field("payload", &self.payload())
|
||||
.finish()
|
||||
.field("kind", &self.kind())
|
||||
.field("code", &self.code())
|
||||
.field("checksum", &self.checksum())
|
||||
.field("payload", &self.payload())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
use crate::cal_checksum;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{fmt, io};
|
||||
|
||||
/// igmp v1
|
||||
/* https://datatracker.ietf.org/doc/html/rfc1112
|
||||
0 1 2 3
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|Version| Type | Unused | Checksum |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Group Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
0 1 2 3
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|Version| Type | Unused | Checksum |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Group Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
/// v1版本的报文
|
||||
pub struct IgmpV1Packet<B> {
|
||||
pub buffer: B,
|
||||
@@ -43,7 +43,7 @@ impl Into<u8> for IgmpV1Type {
|
||||
match self {
|
||||
IgmpV1Type::Query => 0x11,
|
||||
IgmpV1Type::ReportV1 => 0x12,
|
||||
IgmpV1Type::Unknown(v) => v
|
||||
IgmpV1Type::Unknown(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,4 +114,4 @@ impl<B: AsRef<[u8]>> fmt::Debug for IgmpV1Packet<B> {
|
||||
.field("group_address", &self.group_address())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
use crate::cal_checksum;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{fmt, io};
|
||||
|
||||
/// igmp v2
|
||||
/* https://www.rfc-editor.org/rfc/rfc2236.html
|
||||
|
||||
0 1 2 3
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type | Max Resp Time | Checksum |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Group Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
0 1 2 3
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type | Max Resp Time | Checksum |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Group Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
/// v2版本的报文
|
||||
pub struct IgmpV2Packet<B> {
|
||||
@@ -48,7 +48,7 @@ impl Into<u8> for IgmpV2Type {
|
||||
IgmpV2Type::Query => 0x11,
|
||||
IgmpV2Type::ReportV2 => 0x16,
|
||||
IgmpV2Type::LeaveV2 => 0x17,
|
||||
IgmpV2Type::Unknown(v) => v
|
||||
IgmpV2Type::Unknown(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::cal_checksum;
|
||||
|
||||
@@ -116,7 +116,7 @@ impl Into<u8> for IgmpV3Type {
|
||||
match self {
|
||||
IgmpV3Type::Query => 0x11,
|
||||
IgmpV3Type::ReportV3 => 0x22,
|
||||
IgmpV3Type::Unknown(v) => v
|
||||
IgmpV3Type::Unknown(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,7 +203,7 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> IgmpV3QueryPacket<B> {
|
||||
self.buffer.as_mut()[2..4].copy_from_slice(&checksum.to_be_bytes())
|
||||
}
|
||||
pub fn set_qrv(&mut self, qrv: u8) {
|
||||
self.buffer.as_mut()[8] = (self.buffer.as_ref()[8]&(!0x07)) | (qrv & 0x07)
|
||||
self.buffer.as_mut()[8] = (self.buffer.as_ref()[8] & (!0x07)) | (qrv & 0x07)
|
||||
}
|
||||
pub fn set_qqic(&mut self, qqic: u8) {
|
||||
self.buffer.as_mut()[9] = qqic
|
||||
@@ -349,7 +349,10 @@ impl<B: AsRef<[u8]>> IgmpV3ReportPacket<B> {
|
||||
return None;
|
||||
}
|
||||
if let Ok(record) = IgmpV3RecordPacket::new(&buf[start..]) {
|
||||
let end = start + 8 + record.aux_data_len() as usize * 4 + record.source_number() as usize * 4;
|
||||
let end = start
|
||||
+ 8
|
||||
+ record.aux_data_len() as usize * 4
|
||||
+ record.source_number() as usize * 4;
|
||||
if end > len {
|
||||
return None;
|
||||
}
|
||||
@@ -364,7 +367,6 @@ impl<B: AsRef<[u8]>> IgmpV3ReportPacket<B> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// group record
|
||||
pub struct IgmpV3RecordPacket<B> {
|
||||
pub buffer: B,
|
||||
@@ -488,4 +490,4 @@ impl<B: AsRef<[u8]>> fmt::Debug for IgmpV3RecordPacket<B> {
|
||||
.field("auxiliary_data", &self.auxiliary_data())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ pub mod igmp_v1;
|
||||
pub mod igmp_v2;
|
||||
pub mod igmp_v3;
|
||||
|
||||
#[derive(Debug,Copy, Clone,Eq, PartialEq)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum IgmpType {
|
||||
/// 0x11 所有组224.0.0.1或者特定组
|
||||
Query,
|
||||
@@ -40,7 +40,7 @@ impl Into<u8> for IgmpType {
|
||||
IgmpType::ReportV2 => 0x16,
|
||||
IgmpType::ReportV3 => 0x22,
|
||||
IgmpType::LeaveV2 => 0x17,
|
||||
IgmpType::Unknown(v) => v
|
||||
IgmpType::Unknown(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::cal_checksum;
|
||||
use crate::ip::ipv4::protocol::Protocol;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#[derive(Eq, PartialEq,Ord, PartialOrd, Copy, Clone, Debug)]
|
||||
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)]
|
||||
pub enum Protocol {
|
||||
///
|
||||
Hopopt,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::io;
|
||||
use ipv4::packet::IpV4Packet;
|
||||
use std::io;
|
||||
|
||||
pub mod ipv4;
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@ use std::net::Ipv4Addr;
|
||||
use byteorder::BigEndian;
|
||||
use byteorder::ReadBytesExt;
|
||||
|
||||
pub mod arp;
|
||||
pub mod ethernet;
|
||||
pub mod icmp;
|
||||
pub mod igmp;
|
||||
pub mod ip;
|
||||
pub mod tcp;
|
||||
pub mod udp;
|
||||
pub mod ethernet;
|
||||
pub mod arp;
|
||||
// pub enum IpUpperLayer<B> {
|
||||
// UDP(UdpPacket<B>),
|
||||
// Unknown(B),
|
||||
@@ -103,9 +103,9 @@ pub fn ipv4_cal_checksum(
|
||||
src_ip: &Ipv4Addr,
|
||||
dest_ip: &Ipv4Addr,
|
||||
protocol: u8,
|
||||
length: u16,
|
||||
) -> u16 {
|
||||
use std::io::Cursor;
|
||||
let length = buffer.len();
|
||||
let mut sum = 0;
|
||||
let src_ip = src_ip.octets();
|
||||
sum += u32c(src_ip[0], src_ip[1]);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::tcp::Flags;
|
||||
|
||||
@@ -58,7 +58,11 @@ impl<B: AsRef<[u8]>> TcpPacket<B> {
|
||||
buffer,
|
||||
}
|
||||
}
|
||||
pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> io::Result<TcpPacket<B>> {
|
||||
pub fn new(
|
||||
source_ip: Ipv4Addr,
|
||||
destination_ip: Ipv4Addr,
|
||||
buffer: B,
|
||||
) -> io::Result<TcpPacket<B>> {
|
||||
let packet = TcpPacket::unchecked(source_ip, destination_ip, buffer);
|
||||
|
||||
if packet.buffer.as_ref().len() < 20 {
|
||||
@@ -134,7 +138,6 @@ impl<B: AsRef<[u8]>> TcpPacket<B> {
|
||||
&self.source_ip,
|
||||
&self.destination_ip,
|
||||
6,
|
||||
self.buffer.as_ref().len() as u16,
|
||||
)
|
||||
}
|
||||
pub fn urgent_pointer(&self) -> u16 {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{fmt, io};
|
||||
|
||||
/// udp协议
|
||||
///
|
||||
@@ -60,7 +60,11 @@ impl<B: AsRef<[u8]>> UdpPacket<B> {
|
||||
buffer,
|
||||
}
|
||||
}
|
||||
pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> io::Result<UdpPacket<B>> {
|
||||
pub fn new(
|
||||
source_ip: Ipv4Addr,
|
||||
destination_ip: Ipv4Addr,
|
||||
buffer: B,
|
||||
) -> io::Result<UdpPacket<B>> {
|
||||
if buffer.as_ref().len() < 8 {
|
||||
Err(io::Error::from(io::ErrorKind::InvalidData))?;
|
||||
}
|
||||
@@ -102,7 +106,6 @@ impl<B: AsRef<[u8]>> UdpPacket<B> {
|
||||
&self.source_ip,
|
||||
&self.destination_ip,
|
||||
17,
|
||||
self.length(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+18
-1
@@ -1,4 +1,18 @@
|
||||
syntax = "proto3";
|
||||
message HandshakeRequest{
|
||||
string version = 1;
|
||||
bool secret = 2;
|
||||
}
|
||||
message HandshakeResponse{
|
||||
string version = 1;
|
||||
bool secret = 2;
|
||||
bytes public_key = 3;
|
||||
string key_finger = 4;
|
||||
}
|
||||
message SecretHandshakeRequest{
|
||||
string token = 1;
|
||||
bytes key = 2;
|
||||
}
|
||||
message RegistrationRequest{
|
||||
string token = 1;
|
||||
string device_id = 2;
|
||||
@@ -7,6 +21,7 @@ message RegistrationRequest{
|
||||
string version = 5;
|
||||
fixed32 virtual_ip = 6;
|
||||
bool allow_ip_change = 7;
|
||||
bool client_secret = 8;
|
||||
}
|
||||
|
||||
message RegistrationResponse{
|
||||
@@ -23,6 +38,7 @@ message DeviceInfo{
|
||||
string name = 1;
|
||||
fixed32 virtual_ip = 2;
|
||||
uint32 device_status = 3;
|
||||
bool client_secret = 4;
|
||||
}
|
||||
|
||||
message DeviceList{
|
||||
@@ -38,7 +54,8 @@ message PunchInfo{
|
||||
bool reply = 6;
|
||||
fixed32 local_ip = 7;
|
||||
uint32 local_port = 8;
|
||||
repeated bytes public_ipv6_list = 9;
|
||||
bytes ipv6 = 9;
|
||||
uint32 ipv6_port = 10;
|
||||
}
|
||||
enum PunchNatType{
|
||||
Symmetric = 0;
|
||||
|
||||
@@ -19,7 +19,7 @@ use crate::error::*;
|
||||
|
||||
/// A TUN device.
|
||||
pub trait Device {
|
||||
type Queue ;
|
||||
type Queue;
|
||||
|
||||
/// Reconfigure the device.
|
||||
fn configure(&mut self, config: &Configuration) -> Result<()> {
|
||||
|
||||
@@ -77,10 +77,10 @@ impl Device {
|
||||
|
||||
req.ifru.flags = device_type
|
||||
| if config.platform.packet_information {
|
||||
0
|
||||
} else {
|
||||
IFF_NO_PI
|
||||
}
|
||||
0
|
||||
} else {
|
||||
IFF_NO_PI
|
||||
}
|
||||
| if queues_num > 1 { IFF_MULTI_QUEUE } else { 0 };
|
||||
|
||||
for _ in 0..queues_num {
|
||||
|
||||
@@ -22,7 +22,7 @@ use std::ptr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use libc;
|
||||
use libc::{AF_INET, c_char, c_uint, c_void, SOCK_DGRAM, sockaddr, socklen_t};
|
||||
use libc::{c_char, c_uint, c_void, sockaddr, socklen_t, AF_INET, SOCK_DGRAM};
|
||||
|
||||
use crate::configuration::{Configuration, Layer};
|
||||
use crate::device::Device as D;
|
||||
|
||||
@@ -27,7 +27,6 @@ pub mod macos;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use self::macos::{create, Configuration, Device, Queue};
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::configuration::Configuration;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::os::unix::io::{AsRawFd,RawFd};
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::platform::posix::Fd;
|
||||
@@ -72,7 +72,6 @@ impl Writer {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn write_vectored(&self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
|
||||
unsafe {
|
||||
let mut msg: libc::msghdr = mem::zeroed();
|
||||
|
||||
+699
-259
@@ -1,31 +1,42 @@
|
||||
use std::collections::HashMap;
|
||||
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::time::{Duration, Instant};
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use parking_lot::Mutex;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::{TcpStream, UdpSocket};
|
||||
use tokio::net::tcp::OwnedReadHalf;
|
||||
use tokio::sync::watch::{channel, Receiver, Sender};
|
||||
use crate::channel::{Route, RouteKey, Status};
|
||||
use crate::channel::punch::NatType;
|
||||
use crate::core::status::VntWorker;
|
||||
use crate::handle::CurrentDeviceInfo;
|
||||
use crate::handle::recv_handler::ChannelDataHandler;
|
||||
|
||||
use byte_pool::{Block, BytePool};
|
||||
use crossbeam_epoch::{Atomic, Owned};
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use dashmap::DashMap;
|
||||
use std::net::UdpSocket as StdUdpSocket;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::tcp::OwnedReadHalf;
|
||||
use tokio::net::{TcpStream, UdpSocket};
|
||||
use tokio::sync::watch::{channel, Receiver, Sender};
|
||||
|
||||
use crate::channel::punch::NatType;
|
||||
use crate::channel::{Route, RouteKey, Status, TCP_ID, UDP_ID, UDP_V6_ID};
|
||||
use crate::core::status::VntWorker;
|
||||
use crate::handle::recv_handler::ChannelDataHandler;
|
||||
use crate::handle::CurrentDeviceInfo;
|
||||
use crate::ip_proxy::DashMapNew;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref POOL:BytePool = BytePool::new();
|
||||
}
|
||||
pub struct ContextInner {
|
||||
pub(crate) lock: Mutex<()>,
|
||||
//udp用于打洞、服务端通信(可选)
|
||||
pub(crate) main_channel: Arc<UdpSocket>,
|
||||
pub(crate) main_channel: Arc<StdUdpSocket>,
|
||||
pub(crate) main_channel_ipv6: Option<Arc<StdUdpSocket>>,
|
||||
//在udp的基础上,可以选择使用tcp和服务端通信
|
||||
pub(crate) main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>,
|
||||
pub(crate) route_table: SkipMap<Ipv4Addr, Vec<Route>>,
|
||||
pub(crate) route_table_time: SkipMap<(RouteKey, Ipv4Addr), AtomicCell<Instant>>,
|
||||
pub(crate) route_table: Atomic<HashMap<Ipv4Addr, Vec<Route>>>,
|
||||
pub(crate) route_table_time: DashMap<(RouteKey, Ipv4Addr), Instant>,
|
||||
pub(crate) status_receiver: Receiver<Status>,
|
||||
pub(crate) status_sender: Sender<Status>,
|
||||
pub(crate) udp_map: SkipMap<usize, Arc<UdpSocket>>,
|
||||
pub(crate) udp_map: Atomic<HashMap<usize, Arc<UdpSocket>>>,
|
||||
pub(crate) channel_num: usize,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
}
|
||||
@@ -36,25 +47,29 @@ pub struct Context {
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new(main_channel: Arc<UdpSocket>, main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>, _channel_num: usize) -> Self {
|
||||
pub fn new(
|
||||
main_channel: Arc<StdUdpSocket>,
|
||||
main_channel_ipv6: Option<Arc<StdUdpSocket>>,
|
||||
main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
_channel_num: usize,
|
||||
) -> Self {
|
||||
//当前版本只支持一个通道
|
||||
let channel_num = 1;
|
||||
let (status_sender, status_receiver) = channel(Status::Cone);
|
||||
let inner = Arc::new(ContextInner {
|
||||
lock: Mutex::new(()),
|
||||
main_channel,
|
||||
main_channel_ipv6,
|
||||
main_tcp_channel,
|
||||
route_table: SkipMap::new(),
|
||||
route_table_time: SkipMap::new(),
|
||||
route_table: Atomic::new(HashMap::with_capacity(16)),
|
||||
route_table_time: DashMap::new_cap(16),
|
||||
status_receiver,
|
||||
status_sender,
|
||||
udp_map: SkipMap::new(),
|
||||
udp_map: Atomic::new(HashMap::with_capacity(16)),
|
||||
channel_num,
|
||||
current_device,
|
||||
});
|
||||
Self {
|
||||
inner
|
||||
}
|
||||
Self { inner }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,8 +80,24 @@ impl Context {
|
||||
pub fn is_cone(&self) -> bool {
|
||||
*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);
|
||||
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 {
|
||||
self.inner.main_tcp_channel.is_some()
|
||||
}
|
||||
pub fn switch(&self, nat_type: NatType) {
|
||||
match nat_type {
|
||||
@@ -84,116 +115,209 @@ impl Context {
|
||||
pub fn switch_to_symmetric(&self) {
|
||||
let _ = self.inner.status_sender.send(Status::Symmetric);
|
||||
}
|
||||
pub fn main_local_port(&self) -> io::Result<u16> {
|
||||
pub fn main_local_ipv4_port(&self) -> io::Result<u16> {
|
||||
self.inner.main_channel.local_addr().map(|k| k.port())
|
||||
}
|
||||
pub async fn send_main_udp(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
|
||||
self.inner.main_channel.send_to(buf, addr).await
|
||||
pub fn main_local_ipv6_port(&self) -> io::Result<u16> {
|
||||
if let Some(ipv6) = &self.inner.main_channel_ipv6 {
|
||||
ipv6.local_addr().map(|k| k.port())
|
||||
} else {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
|
||||
}
|
||||
}
|
||||
pub async fn send_main(&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 let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
|
||||
udp_ipv6.send_to(buf, addr)
|
||||
} else {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
|
||||
}
|
||||
} else {
|
||||
self.inner.main_channel.send_to(buf, addr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
|
||||
if let Some(sender) = &self.inner.main_tcp_channel {
|
||||
let mut vec = vec![0; 4 + buf.len()];
|
||||
vec[4..].copy_from_slice(buf);
|
||||
if sender.send(vec).await.is_ok() {
|
||||
if sender.try_send(buf.to_vec()).is_ok() {
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "send_main err"))
|
||||
}
|
||||
} else {
|
||||
self.inner.main_channel.send_to(buf, addr).await
|
||||
}
|
||||
}
|
||||
pub fn try_send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
|
||||
if let Some(sender) = &self.inner.main_tcp_channel {
|
||||
let mut vec = vec![0; 4 + buf.len()];
|
||||
vec[4..].copy_from_slice(buf);
|
||||
if sender.try_send(vec).is_ok() {
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "try_send_main err"))
|
||||
}
|
||||
} else {
|
||||
self.inner.main_channel.try_send_to(buf, addr)
|
||||
self.send_main_udp(buf, addr)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn send_all(&self, buf: &[u8], addr: SocketAddr) -> io::Result<()> {
|
||||
for udp in self.inner.udp_map.iter() {
|
||||
udp.value().send_to(buf, addr).await?;
|
||||
pub(crate) fn try_send_all(&self, buf: &[u8], addr: SocketAddr) -> io::Result<()> {
|
||||
let table = unsafe {
|
||||
let guard = &crossbeam_epoch::pin();
|
||||
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报文会出错
|
||||
if let Err(e) = udp.try_send_to(buf, addr) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn 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() {
|
||||
let route = self.get_route_by_id(id)?;
|
||||
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"));
|
||||
}
|
||||
let route = v[0];
|
||||
if route.rt == 199 {
|
||||
//这通常是刚加入路由,直接放弃使用,避免抖动
|
||||
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
|
||||
}
|
||||
let route = v.value()[0];
|
||||
drop(v);
|
||||
if !route.is_p2p() {
|
||||
if let Some(time) = self.inner.route_table_time.get(&(route.route_key(), *id)) {
|
||||
//借道传输时,长时间不通信的通道不使用
|
||||
if time.value().load().elapsed() > Duration::from_secs(3) {
|
||||
if time.value().elapsed() > Duration::from_secs(6) {
|
||||
return Err(io::Error::new(io::ErrorKind::NotFound, "route time out"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(udp) = self.inner.udp_map.get(&route.index) {
|
||||
return udp.value().send_to(buf, route.addr).await;
|
||||
}
|
||||
return Ok(route);
|
||||
}
|
||||
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> {
|
||||
if route_key.index == 0 {
|
||||
if let Some(sender) = &self.inner.main_tcp_channel {
|
||||
let mut vec = vec![0; 4 + buf.len()];
|
||||
vec[4..].copy_from_slice(buf);
|
||||
return if sender.send(vec).await.is_ok() {
|
||||
Ok(buf.len())
|
||||
match route_key.index {
|
||||
TCP_ID => {
|
||||
if let Some(sender) = &self.inner.main_tcp_channel {
|
||||
if sender.send(buf.to_vec()).await.is_ok() {
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
|
||||
}
|
||||
} else {
|
||||
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) = self.inner.udp_map.get(&route_key.index) {
|
||||
return udp.value().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> {
|
||||
if route_key.index == 0 {
|
||||
if let Some(sender) = &self.inner.main_tcp_channel {
|
||||
let mut vec = vec![0; 4 + buf.len()];
|
||||
vec[4..].copy_from_slice(buf);
|
||||
return if sender.try_send(vec).is_ok() {
|
||||
Ok(buf.len())
|
||||
match route_key.index {
|
||||
TCP_ID => {
|
||||
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, "send_by_key err"))
|
||||
}
|
||||
} 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) {
|
||||
self.add_route_(id, route, true)
|
||||
}
|
||||
@@ -202,122 +326,206 @@ impl Context {
|
||||
}
|
||||
fn add_route_(&self, id: Ipv4Addr, route: Route, only_if_absent: bool) {
|
||||
let key = route.route_key();
|
||||
let guard = self.inner.lock.lock();
|
||||
let mut list = if let Some(entry) = self.inner.route_table.get(&id) {
|
||||
entry.value().clone()
|
||||
} else {
|
||||
Vec::with_capacity(4)
|
||||
};
|
||||
let mut exist = false;
|
||||
for x in list.iter_mut() {
|
||||
if x.metric < route.metric {
|
||||
//不能比当前的路径更长
|
||||
return;
|
||||
}
|
||||
if x.route_key() == key {
|
||||
if only_if_absent {
|
||||
let guard = &crossbeam_epoch::pin();
|
||||
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() };
|
||||
|
||||
let list = table.entry(id).or_insert_with(|| Vec::with_capacity(4));
|
||||
let mut exist = false;
|
||||
for x in list.iter_mut() {
|
||||
if x.metric < route.metric {
|
||||
//不能比当前的路径更长
|
||||
return;
|
||||
}
|
||||
x.metric = route.metric;
|
||||
x.rt = route.rt;
|
||||
exist = true;
|
||||
break;
|
||||
if x.route_key() == key {
|
||||
if only_if_absent {
|
||||
return;
|
||||
}
|
||||
x.metric = route.metric;
|
||||
x.rt = route.rt;
|
||||
exist = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if exist {
|
||||
list.sort_by_key(|k| k.sort_key());
|
||||
} else {
|
||||
if route.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);
|
||||
}
|
||||
}
|
||||
match route_table.compare_exchange(
|
||||
table_share,
|
||||
Owned::new(table),
|
||||
Ordering::Relaxed,
|
||||
Ordering::Relaxed,
|
||||
guard,
|
||||
) {
|
||||
Ok(p) => unsafe {
|
||||
guard.defer_destroy(p);
|
||||
break;
|
||||
},
|
||||
Err(e) => {
|
||||
table_share = e.current;
|
||||
}
|
||||
}
|
||||
}
|
||||
if exist {
|
||||
list.sort_by_key(|k| k.sort_key());
|
||||
} else {
|
||||
if route.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);
|
||||
}
|
||||
}
|
||||
self.inner.route_table.insert(id, list);
|
||||
self.inner.route_table_time.insert((key, id), AtomicCell::new(Instant::now()));
|
||||
drop(guard);
|
||||
|
||||
self.inner
|
||||
.route_table_time
|
||||
.insert((key, id), Instant::now().sub(Duration::from_secs(10)));
|
||||
}
|
||||
pub fn route(&self, id: &Ipv4Addr) -> Option<Vec<Route>> {
|
||||
if let Some(v) = self.inner.route_table.get(id) {
|
||||
Some(v.value().clone())
|
||||
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) {
|
||||
Some(v.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
pub fn route_one(&self, id: &Ipv4Addr) -> Option<Route> {
|
||||
if let Some(v) = self.inner.route_table.get(id) {
|
||||
v.value().iter().max_by_key(|k| k.sort_key()).map(|k| *k)
|
||||
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) {
|
||||
v.first().map(|v| *v)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
pub fn route_to_id(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
|
||||
for x in self.inner.route_table_time.iter() {
|
||||
if &x.key().0 == route_key {
|
||||
return Some(x.key().1);
|
||||
let guard = &crossbeam_epoch::pin();
|
||||
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() {
|
||||
return Some(*k);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
pub fn need_punch(&self, id: &Ipv4Addr) -> bool {
|
||||
if let Some(v) = self.inner.route_table.get(id) {
|
||||
if v.value().iter().filter(|k| k.is_p2p()).count() >= self.inner.channel_num {
|
||||
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.iter().filter(|k| k.is_p2p()).count() >= self.inner.channel_num {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec<Route>)> {
|
||||
self.inner.route_table.iter().map(|k| (k.key().clone(), k.value().clone())).collect()
|
||||
let guard = &crossbeam_epoch::pin();
|
||||
let table = unsafe {
|
||||
self.inner
|
||||
.route_table
|
||||
.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)> {
|
||||
let mut v = Vec::with_capacity(8);
|
||||
for x in self.inner.route_table.iter() {
|
||||
if let Some(route) = x.value().first() {
|
||||
v.push((*x.key(), *route));
|
||||
let mut list = Vec::with_capacity(8);
|
||||
let guard = &crossbeam_epoch::pin();
|
||||
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() {
|
||||
list.push((*k, *route));
|
||||
}
|
||||
}
|
||||
v
|
||||
list
|
||||
}
|
||||
pub fn direct_route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
|
||||
let mut v = Vec::with_capacity(8);
|
||||
for x in self.inner.route_table.iter() {
|
||||
if let Some(route) = x.value().first() {
|
||||
let mut list = Vec::with_capacity(8);
|
||||
let guard = &crossbeam_epoch::pin();
|
||||
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 {
|
||||
v.push((*x.key(), *route));
|
||||
list.push((*k, *route));
|
||||
}
|
||||
}
|
||||
}
|
||||
v
|
||||
list
|
||||
}
|
||||
pub fn remove_route_all(&self, id: &Ipv4Addr) {
|
||||
let guard = self.inner.lock.lock();
|
||||
if let Some(v) = self.inner.route_table.remove(id) {
|
||||
for x in v.value() {
|
||||
self.inner.route_table_time.remove(&(x.route_key(), *id));
|
||||
|
||||
pub fn remove_route(&self, id: &Ipv4Addr, route_key: RouteKey) {
|
||||
let guard = &crossbeam_epoch::pin();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
drop(guard);
|
||||
}
|
||||
pub fn remove_route(&self, id: &Ipv4Addr, route_key: RouteKey) {
|
||||
let guard = self.inner.lock.lock();
|
||||
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));
|
||||
}
|
||||
drop(guard);
|
||||
}
|
||||
pub fn update_read_time(&self, id: &Ipv4Addr, route_key: &RouteKey) {
|
||||
if let Some(time) = self.inner.route_table_time.get(&(*route_key, *id)) {
|
||||
time.value().store(Instant::now());
|
||||
if let Some(mut time) = self.inner.route_table_time.get_mut(&(*route_key, *id)) {
|
||||
*time.value_mut() = Instant::now();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -328,80 +536,118 @@ pub struct Channel {
|
||||
}
|
||||
|
||||
impl Channel {
|
||||
pub fn new(context: Context,
|
||||
handler: ChannelDataHandler, ) -> Self {
|
||||
Self {
|
||||
context,
|
||||
handler,
|
||||
}
|
||||
pub fn new(context: Context, handler: ChannelDataHandler) -> Self {
|
||||
Self { context, handler }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct BufSenderGroup(
|
||||
usize,
|
||||
Vec<std::sync::mpsc::SyncSender<(Block<'static>, usize, usize, RouteKey)>>,
|
||||
);
|
||||
|
||||
struct BufReceiverGroup(Vec<std::sync::mpsc::Receiver<(Block<'static>, usize, usize, RouteKey)>>);
|
||||
|
||||
impl BufSenderGroup {
|
||||
pub fn send(&mut self, val: (Block<'static>, usize, usize, RouteKey)) -> bool {
|
||||
let index = self.0 % self.1.len();
|
||||
self.0 = self.0.wrapping_add(1);
|
||||
self.1[index].send(val).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) {
|
||||
let mut buf_sender_group = Vec::with_capacity(size);
|
||||
let mut buf_receiver_group = Vec::with_capacity(size);
|
||||
for _ in 0..size {
|
||||
let (buf_sender, buf_receiver) =
|
||||
std::sync::mpsc::sync_channel::<(Block<'static, Vec<u8>>, usize, usize, RouteKey)>(1);
|
||||
buf_sender_group.push(buf_sender);
|
||||
buf_receiver_group.push(buf_receiver);
|
||||
}
|
||||
(
|
||||
BufSenderGroup(0, buf_sender_group),
|
||||
BufReceiverGroup(buf_receiver_group),
|
||||
)
|
||||
}
|
||||
|
||||
impl Channel {
|
||||
async fn handle(handler: &mut ChannelDataHandler,
|
||||
context: &Context,
|
||||
id: usize,
|
||||
result: io::Result<(usize, SocketAddr)>,
|
||||
buf: &mut [u8], start: usize) {
|
||||
match result {
|
||||
Ok((len, addr)) => {
|
||||
handler.handle(buf, start, start + len, RouteKey::new(id, addr), context).await;
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}",e)
|
||||
}
|
||||
}
|
||||
}
|
||||
async fn tcp_handle(mut tcp_r: OwnedReadHalf, context: Context,
|
||||
mut handler: ChannelDataHandler, head_reserve: usize, ) -> io::Result<()> {
|
||||
let mut buf = [0; 4096];
|
||||
async fn tcp_handle(
|
||||
mut tcp_r: OwnedReadHalf,
|
||||
context: Context,
|
||||
handler: ChannelDataHandler,
|
||||
head_reserve: usize,
|
||||
) -> io::Result<()> {
|
||||
let mut head = [0; 4];
|
||||
let addr = tcp_r.peer_addr()?;
|
||||
let key = RouteKey::new(0, addr);
|
||||
let key = RouteKey::new(TCP_ID, addr);
|
||||
loop {
|
||||
tcp_r.read_exact(&mut buf[head_reserve..head_reserve + 4]).await?;
|
||||
let len = 4 + (((buf[head_reserve + 2] as u16) << 8) | buf[head_reserve + 3] as u16) as usize;
|
||||
tcp_r.read_exact(&mut buf[head_reserve + 4..head_reserve + len]).await?;
|
||||
handler.handle(&mut buf[4..], head_reserve, head_reserve + len - 4, key, &context).await;
|
||||
let mut buf = [0; 4096];
|
||||
tcp_r.read_exact(&mut head).await?;
|
||||
let len = (((head[2] as u16) << 8) | head[3] as u16) as usize;
|
||||
if len < 12 || len > buf.len() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"length overflow",
|
||||
));
|
||||
}
|
||||
tcp_r
|
||||
.read_exact(&mut buf[head_reserve..head_reserve + len])
|
||||
.await?;
|
||||
handler
|
||||
.handle(&mut buf, head_reserve, head_reserve + len, key, &context)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
async fn start_tcp(mut worker: VntWorker, tcp_stream: TcpStream, mut receiver: tokio::sync::mpsc::Receiver<Vec<u8>>, context: Context, handler: ChannelDataHandler, head_reserve: usize) {
|
||||
async fn start_tcp(
|
||||
mut worker: VntWorker,
|
||||
tcp_stream: TcpStream,
|
||||
mut receiver: tokio::sync::mpsc::Receiver<Vec<u8>>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
context: Context,
|
||||
handler: ChannelDataHandler,
|
||||
head_reserve: usize,
|
||||
) {
|
||||
let (tcp_r, mut tcp_w) = tcp_stream.into_split();
|
||||
{
|
||||
let context = context.clone();
|
||||
let handler = handler.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = Self::tcp_handle(tcp_r, context, handler, head_reserve).await {
|
||||
log::info!("tcp链接断开:{:?}",e);
|
||||
log::info!("tcp链接断开:{:?}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
let mut head = [0; 4];
|
||||
loop {
|
||||
tokio::select! {
|
||||
_=worker.stop_wait()=>{
|
||||
break;
|
||||
}
|
||||
rs=receiver.recv()=>{
|
||||
if let Some(mut data) = rs{
|
||||
if data.len()<4{
|
||||
continue
|
||||
}
|
||||
let len = data.len() - 4;
|
||||
data[2] = (len >> 8) as u8;
|
||||
data[3] = (len & 0xFF) as u8;
|
||||
if let Err(e) = tcp_w.write_all(&data).await {
|
||||
if context.is_close() {
|
||||
break;
|
||||
}
|
||||
if let Some(data) = rs{
|
||||
let len = data.len();
|
||||
head[2] = (len >> 8) as u8;
|
||||
head[3] = (len & 0xFF) as u8;
|
||||
let mut err = false;
|
||||
if let Err(e) = tcp_w.write_all(&head).await{
|
||||
err = true;
|
||||
log::info!("发送失败,需要重连:{:?}",e);
|
||||
}else if let Err(e) = tcp_w.write_all(&data).await{
|
||||
err = true;
|
||||
log::info!("发送失败,需要重连:{:?}",e);
|
||||
}
|
||||
if err {
|
||||
let _ = tcp_w.shutdown().await;
|
||||
match TcpStream::connect(context.inner.current_device.load().connect_server).await {
|
||||
match TcpStream::connect(current_device.load().connect_server).await {
|
||||
Ok(tcp_stream) => {
|
||||
let (r, w) = tcp_stream.into_split();
|
||||
tcp_w = w;
|
||||
let context = context.clone();
|
||||
let handler = handler.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = Self::tcp_handle(r, context, handler, head_reserve).await {
|
||||
if let Err(e) = Self::tcp_handle(r, context,handler, head_reserve).await {
|
||||
log::info!("tcp 链接断开:{:?}",e);
|
||||
}
|
||||
});
|
||||
@@ -419,21 +665,101 @@ impl Channel {
|
||||
}
|
||||
worker.stop_all();
|
||||
}
|
||||
pub async fn start(self,
|
||||
mut worker: VntWorker,
|
||||
tcp: Option<(TcpStream, tokio::sync::mpsc::Receiver<Vec<u8>>)>,
|
||||
head_reserve: usize,//头部预留字节
|
||||
symmetric_channel_num: usize,//对称网络,则再加一组监听,提升打洞成功率
|
||||
relay: bool,
|
||||
|
||||
pub async fn start(
|
||||
self,
|
||||
mut worker: VntWorker,
|
||||
tcp: Option<(TcpStream, tokio::sync::mpsc::Receiver<Vec<u8>>)>,
|
||||
head_reserve: usize, //头部预留字节
|
||||
symmetric_channel_num: usize, //对称网络,则再加一组监听,提升打洞成功率
|
||||
relay: bool,
|
||||
parallel: usize,
|
||||
) {
|
||||
let handler = self.handler.clone();
|
||||
let context = self.context;
|
||||
let main_channel = context.inner.main_channel.clone();
|
||||
let handler = self.handler.clone();
|
||||
let buf_sender = if parallel > 1 {
|
||||
let (buf_sender, buf_receiver) = buf_channel_group(parallel);
|
||||
for buf_receiver in buf_receiver.0 {
|
||||
let context = context.clone();
|
||||
let handler = handler.clone();
|
||||
std::thread::spawn(move || {
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
log::info!("启动异步处理");
|
||||
runtime.block_on(async move {
|
||||
while let Ok((mut buf, start, end, route_key)) = buf_receiver.recv() {
|
||||
handler
|
||||
.handle(&mut buf, start, end, route_key, &context)
|
||||
.await;
|
||||
}
|
||||
log::warn!("异步处理停止");
|
||||
});
|
||||
});
|
||||
}
|
||||
Some(buf_sender)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some((tcp_stream, receiver)) = tcp {
|
||||
tokio::spawn(Self::start_tcp(worker.worker("main_channel_tcp"), tcp_stream, receiver, context.clone(), handler.clone(), head_reserve));
|
||||
tokio::spawn(Self::start_tcp(
|
||||
worker.worker("main_channel_tcp"),
|
||||
tcp_stream,
|
||||
receiver,
|
||||
context.inner.current_device.clone(),
|
||||
context.clone(),
|
||||
handler.clone(),
|
||||
head_reserve,
|
||||
));
|
||||
}
|
||||
if let Some(main_channel_ipv6) = &context.inner.main_channel_ipv6 {
|
||||
let worker = worker.worker("main_channel_ipv6");
|
||||
let context = context.clone();
|
||||
let main_channel_ipv6 = main_channel_ipv6.clone();
|
||||
let handler = handler.clone();
|
||||
let buf_sender = buf_sender.clone();
|
||||
std::thread::spawn(move || {
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
log::info!("启动udp v6");
|
||||
runtime.block_on(Self::main_start_(
|
||||
worker,
|
||||
context,
|
||||
UDP_V6_ID,
|
||||
main_channel_ipv6,
|
||||
handler,
|
||||
buf_sender,
|
||||
head_reserve,
|
||||
));
|
||||
});
|
||||
}
|
||||
{
|
||||
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::spawn(move || {
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
log::info!("启动udp v4");
|
||||
runtime.block_on(Self::main_start_(
|
||||
worker,
|
||||
context,
|
||||
UDP_ID,
|
||||
main_channel,
|
||||
handler,
|
||||
buf_sender,
|
||||
head_reserve,
|
||||
));
|
||||
});
|
||||
}
|
||||
tokio::spawn(Self::start_(worker.worker("main_channel_1"), context.clone(), handler.clone(), main_channel.clone(), head_reserve, true));
|
||||
// tokio::spawn(Self::start_(worker.worker("main_channel_2"), context.clone(), handler, main_channel, head_reserve, true));
|
||||
if relay {
|
||||
worker.stop_wait().await;
|
||||
return;
|
||||
@@ -463,8 +789,7 @@ impl Channel {
|
||||
Ok(udp) => {
|
||||
let udp = Arc::new(udp);
|
||||
let context = context.clone();
|
||||
let handler = self.handler.clone();
|
||||
tokio::spawn(Self::start_(worker.worker("symmetric_channel"),context, handler, udp, head_reserve, false));
|
||||
tokio::spawn(Self::start_(worker.worker("symmetric_channel"),context, udp,handler.clone(),buf_sender.clone(), head_reserve, false));
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{}",e);
|
||||
@@ -486,53 +811,168 @@ impl Channel {
|
||||
}
|
||||
worker.stop_all();
|
||||
}
|
||||
async fn start_(mut worker: VntWorker, context: Context,
|
||||
mut handler: ChannelDataHandler,
|
||||
udp: Arc<UdpSocket>,
|
||||
head_reserve: usize,
|
||||
is_core: bool) {
|
||||
async 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,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("udp :{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(mut buf_sender) => loop {
|
||||
let mut buf = POOL.alloc(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_(
|
||||
mut worker: VntWorker,
|
||||
context: Context,
|
||||
udp: Arc<UdpSocket>,
|
||||
handler: ChannelDataHandler,
|
||||
buf_sender: Option<BufSenderGroup>,
|
||||
head_reserve: usize,
|
||||
is_core: bool,
|
||||
) {
|
||||
let mut status_receiver = context.inner.status_receiver.clone();
|
||||
#[cfg(target_os = "windows")]
|
||||
use std::os::windows::io::AsRawSocket;
|
||||
#[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))]
|
||||
use std::os::fd::AsRawFd;
|
||||
#[cfg(any(unix))]
|
||||
let id = 1 + udp.as_raw_fd() as usize;
|
||||
context.inner.udp_map.insert(id, udp.clone());
|
||||
let mut buf = [0; 4096];
|
||||
loop {
|
||||
tokio::select! {
|
||||
rs=udp.recv_from(&mut buf[head_reserve..])=>{
|
||||
Self::handle(&mut handler,&context,id,rs,&mut buf,head_reserve).await;
|
||||
}
|
||||
changed=status_receiver.changed()=>{
|
||||
match changed {
|
||||
Ok(_) => {
|
||||
match *status_receiver.borrow() {
|
||||
Status::Cone => {
|
||||
if !is_core{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Status::Close=>{
|
||||
break;
|
||||
}
|
||||
Status::Symmetric => {}
|
||||
let id = 3 + udp.as_raw_fd() as usize;
|
||||
|
||||
context.insert_udp(id, udp.clone());
|
||||
match buf_sender {
|
||||
None => {
|
||||
let mut buf = [0; 4096];
|
||||
loop {
|
||||
tokio::select! {
|
||||
rs=udp.recv_from(&mut buf[head_reserve..])=>{
|
||||
match rs {
|
||||
Ok((len, addr)) => {
|
||||
handler.handle(&mut buf, head_reserve, head_reserve + len, RouteKey::new(id, addr), &context).await;
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}",e)
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_=worker.stop_wait()=>{
|
||||
break;
|
||||
changed=status_receiver.changed()=>{
|
||||
match changed {
|
||||
Ok(_) => {
|
||||
match *status_receiver.borrow() {
|
||||
Status::Cone => {
|
||||
if !is_core{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Status::Close=>{
|
||||
break;
|
||||
}
|
||||
Status::Symmetric => {}
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_=worker.stop_wait()=>{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(mut buf_sender) => loop {
|
||||
let mut buf = POOL.alloc(4096);
|
||||
tokio::select! {
|
||||
rs=udp.recv_from(&mut buf[head_reserve..])=>{
|
||||
match rs {
|
||||
Ok((len, addr)) => {
|
||||
if !buf_sender.send((buf,head_reserve,head_reserve+len,RouteKey::new(id, addr))){
|
||||
log::error!("udp buf_sender发送数据失败");
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}",e)
|
||||
}
|
||||
}
|
||||
}
|
||||
changed=status_receiver.changed()=>{
|
||||
match changed {
|
||||
Ok(_) => {
|
||||
match *status_receiver.borrow() {
|
||||
Status::Cone => {
|
||||
if !is_core{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Status::Close=>{
|
||||
break;
|
||||
}
|
||||
Status::Symmetric => {}
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_=worker.stop_wait()=>{
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
context.inner.udp_map.remove(&id);
|
||||
context.remove_udp(id);
|
||||
if is_core {
|
||||
worker.stop_all();
|
||||
}
|
||||
|
||||
+6
-11
@@ -1,10 +1,9 @@
|
||||
use crate::channel::channel::Context;
|
||||
use crate::channel::RouteKey;
|
||||
use std::io;
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::time::Duration;
|
||||
use crate::channel::channel::Context;
|
||||
use crate::channel::RouteKey;
|
||||
|
||||
|
||||
pub struct Idle {
|
||||
read_idle: Duration,
|
||||
@@ -12,12 +11,8 @@ pub struct Idle {
|
||||
}
|
||||
|
||||
impl Idle {
|
||||
pub fn new(read_idle: Duration,
|
||||
context: Context, ) -> Self {
|
||||
Self {
|
||||
read_idle,
|
||||
context,
|
||||
}
|
||||
pub fn new(read_idle: Duration, context: Context) -> Self {
|
||||
Self { read_idle, context }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +22,7 @@ impl Idle {
|
||||
loop {
|
||||
let mut max = Duration::from_secs(0);
|
||||
for entry in self.context.inner.route_table_time.iter() {
|
||||
let last_read = entry.value().load().elapsed();
|
||||
let last_read = entry.value().elapsed();
|
||||
if last_read >= self.read_idle {
|
||||
return Ok((entry.key().1.clone(), entry.key().0.clone()));
|
||||
} else {
|
||||
@@ -45,4 +40,4 @@ impl Idle {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-10
@@ -1,10 +1,14 @@
|
||||
use std::net::SocketAddr;
|
||||
|
||||
pub mod channel;
|
||||
pub mod punch;
|
||||
pub mod idle;
|
||||
pub mod punch;
|
||||
pub mod sender;
|
||||
|
||||
const TCP_ID: usize = 0;
|
||||
const UDP_ID: usize = 1;
|
||||
const UDP_V6_ID: usize = 2;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub enum Status {
|
||||
Cone,
|
||||
@@ -27,8 +31,7 @@ pub struct RouteSortKey {
|
||||
}
|
||||
|
||||
impl Route {
|
||||
pub fn new(index: usize,
|
||||
addr: SocketAddr, metric: u8, rt: i64, ) -> Self {
|
||||
pub fn new(index: usize, addr: SocketAddr, metric: u8, rt: i64) -> Self {
|
||||
Self {
|
||||
index,
|
||||
addr,
|
||||
@@ -68,11 +71,10 @@ pub struct RouteKey {
|
||||
}
|
||||
|
||||
impl RouteKey {
|
||||
pub(crate) fn new(index: usize,
|
||||
addr: SocketAddr, ) -> Self {
|
||||
Self {
|
||||
index,
|
||||
addr,
|
||||
}
|
||||
pub(crate) fn new(index: usize, addr: SocketAddr) -> Self {
|
||||
Self { index, addr }
|
||||
}
|
||||
}
|
||||
pub fn is_tcp(&self) -> bool {
|
||||
self.index == TCP_ID
|
||||
}
|
||||
}
|
||||
|
||||
+77
-31
@@ -1,19 +1,39 @@
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use rand::prelude::SliceRandom;
|
||||
|
||||
use crate::channel::channel::Context;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum PunchModel {
|
||||
IPv4,
|
||||
IPv6,
|
||||
All,
|
||||
}
|
||||
|
||||
impl FromStr for PunchModel {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s.to_lowercase().trim() {
|
||||
"ipv4" => Ok(PunchModel::IPv4),
|
||||
"ipv6" => Ok(PunchModel::IPv6),
|
||||
_ => Ok(PunchModel::All),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct NatInfo {
|
||||
pub public_ips: Vec<Ipv4Addr>,
|
||||
pub public_port: u16,
|
||||
pub public_port_range: u16,
|
||||
pub local_ip: Ipv4Addr,
|
||||
pub local_port: u16,
|
||||
pub local_ipv4_addr: SocketAddrV4,
|
||||
pub ipv6_addr: SocketAddrV6,
|
||||
pub nat_type: NatType,
|
||||
}
|
||||
|
||||
@@ -24,21 +44,21 @@ pub enum NatType {
|
||||
}
|
||||
|
||||
impl NatInfo {
|
||||
pub fn new(mut public_ips: Vec<Ipv4Addr>,
|
||||
public_port: u16,
|
||||
public_port_range: u16,
|
||||
local_ip: Ipv4Addr,
|
||||
local_port: u16,
|
||||
nat_type: NatType, ) -> Self {
|
||||
public_ips.retain(|ip| {
|
||||
!ip.is_loopback() && !ip.is_private()
|
||||
});
|
||||
pub fn new(
|
||||
mut public_ips: Vec<Ipv4Addr>,
|
||||
public_port: u16,
|
||||
public_port_range: u16,
|
||||
local_ipv4_addr: SocketAddrV4,
|
||||
ipv6_addr: SocketAddrV6,
|
||||
nat_type: NatType,
|
||||
) -> Self {
|
||||
public_ips.retain(|ip| !ip.is_loopback() && !ip.is_private());
|
||||
Self {
|
||||
public_ips,
|
||||
public_port,
|
||||
public_port_range,
|
||||
local_ip,
|
||||
local_port,
|
||||
local_ipv4_addr,
|
||||
ipv6_addr,
|
||||
nat_type,
|
||||
}
|
||||
}
|
||||
@@ -49,10 +69,11 @@ pub struct Punch {
|
||||
context: Context,
|
||||
port_vec: Vec<u16>,
|
||||
port_index: HashMap<Ipv4Addr, usize>,
|
||||
punch_model: PunchModel,
|
||||
}
|
||||
|
||||
impl Punch {
|
||||
pub fn new(context: Context) -> Self {
|
||||
pub fn new(context: Context, punch_model: PunchModel) -> Self {
|
||||
let mut port_vec: Vec<u16> = (1..65535).collect();
|
||||
port_vec.push(65535);
|
||||
let mut rng = rand::thread_rng();
|
||||
@@ -61,6 +82,7 @@ impl Punch {
|
||||
context,
|
||||
port_vec,
|
||||
port_index: HashMap::new(),
|
||||
punch_model,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,8 +92,22 @@ impl Punch {
|
||||
if !self.context.need_punch(&id) {
|
||||
return Ok(());
|
||||
}
|
||||
if !nat_info.local_ip.is_unspecified() || nat_info.local_port != 0 {
|
||||
let _ = self.context.send_main_udp(buf, SocketAddr::V4(SocketAddrV4::new(nat_info.local_ip, nat_info.local_port))).await;
|
||||
if !nat_info.local_ipv4_addr.ip().is_unspecified() && nat_info.local_ipv4_addr.port() != 0 {
|
||||
let _ = self
|
||||
.context
|
||||
.send_main_udp(buf, SocketAddr::V4(nat_info.local_ipv4_addr));
|
||||
}
|
||||
if self.punch_model != PunchModel::IPv4
|
||||
&& !nat_info.ipv6_addr.ip().is_unspecified()
|
||||
&& nat_info.ipv6_addr.port() != 0
|
||||
{
|
||||
let rs = self
|
||||
.context
|
||||
.send_main_udp(buf, SocketAddr::V6(nat_info.ipv6_addr));
|
||||
log::info!("发送到ipv6地址:{:?},rs={:?}", nat_info.ipv6_addr, rs);
|
||||
if rs.is_ok() && self.punch_model == PunchModel::IPv6 {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
match nat_info.nat_type {
|
||||
NatType::Symmetric => {
|
||||
@@ -91,12 +127,10 @@ impl Punch {
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let (max_port, overflow) = nat_info.public_port.overflowing_add(nat_info.public_port_range);
|
||||
let max_port = if overflow {
|
||||
65535
|
||||
} else {
|
||||
max_port
|
||||
};
|
||||
let (max_port, overflow) = nat_info
|
||||
.public_port
|
||||
.overflowing_add(nat_info.public_port_range);
|
||||
let max_port = if overflow { 65535 } else { max_port };
|
||||
let k = if max_port - min_port + 1 > max_k1 {
|
||||
max_k1 as usize
|
||||
} else {
|
||||
@@ -108,7 +142,8 @@ impl Punch {
|
||||
let mut rng = rand::thread_rng();
|
||||
nums.shuffle(&mut rng);
|
||||
}
|
||||
self.punch_symmetric(&nums[..k], buf, &nat_info.public_ips, max_k1 as usize).await?;
|
||||
self.punch_symmetric(&nums[..k], buf, &nat_info.public_ips, max_k1 as usize)
|
||||
.await?;
|
||||
}
|
||||
let start = *self.port_index.entry(id.clone()).or_insert(0);
|
||||
let mut end = start + max_k2;
|
||||
@@ -117,18 +152,23 @@ impl Punch {
|
||||
end = self.port_vec.len();
|
||||
index = 0
|
||||
}
|
||||
self.punch_symmetric(&self.port_vec[start..end], buf, &nat_info.public_ips, max_k2).await?;
|
||||
self.punch_symmetric(
|
||||
&self.port_vec[start..end],
|
||||
buf,
|
||||
&nat_info.public_ips,
|
||||
max_k2,
|
||||
)
|
||||
.await?;
|
||||
self.port_index.insert(id, index);
|
||||
}
|
||||
NatType::Cone => {
|
||||
let is_cone = self.context.is_cone();
|
||||
for ip in nat_info.public_ips {
|
||||
let addr = SocketAddr::V4(SocketAddrV4::new(ip, nat_info.public_port));
|
||||
if is_cone {
|
||||
self.context.send_main_udp(buf, addr).await?;
|
||||
} else {
|
||||
self.context.send_main_udp(buf, addr)?;
|
||||
if !is_cone {
|
||||
//只有一方是对称,则对称方要使用全部端口发送数据,符合上述计算的概率
|
||||
self.context.send_all(buf, addr).await?;
|
||||
self.context.try_send_all(buf, addr)?;
|
||||
}
|
||||
tokio::time::sleep(Duration::from_millis(2)).await;
|
||||
}
|
||||
@@ -137,7 +177,13 @@ impl Punch {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn punch_symmetric(&self, ports: &[u16], buf: &[u8], ips: &Vec<Ipv4Addr>, max: usize) -> io::Result<()> {
|
||||
async fn punch_symmetric(
|
||||
&self,
|
||||
ports: &[u16],
|
||||
buf: &[u8],
|
||||
ips: &Vec<Ipv4Addr>,
|
||||
max: usize,
|
||||
) -> io::Result<()> {
|
||||
let mut count = 0;
|
||||
for port in ports {
|
||||
for pub_ip in ips {
|
||||
@@ -146,7 +192,7 @@ impl Punch {
|
||||
return Ok(());
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::ops::Deref;
|
||||
use crate::channel::channel::Context;
|
||||
use std::ops::Deref;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ChannelSender {
|
||||
@@ -8,9 +8,7 @@ pub struct ChannelSender {
|
||||
|
||||
impl ChannelSender {
|
||||
pub fn new(context: Context) -> Self {
|
||||
Self {
|
||||
context,
|
||||
}
|
||||
Self { context }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
use std::io;
|
||||
|
||||
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyIvInit};
|
||||
use rand::RngCore;
|
||||
|
||||
use crate::cipher::Finger;
|
||||
use crate::protocol::body::AesCbcSecretBody;
|
||||
use crate::protocol::{NetPacket, HEAD_LEN};
|
||||
|
||||
type Aes128CbcEnc = cbc::Encryptor<aes::Aes128>;
|
||||
type Aes128CbcDec = cbc::Decryptor<aes::Aes128>;
|
||||
type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
|
||||
type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AesCbcCipher {
|
||||
pub(crate) cipher: AesCbcEnum,
|
||||
pub(crate) finger: Option<Finger>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum AesCbcEnum {
|
||||
AES128CBC([u8; 16]),
|
||||
AES256CBC([u8; 32]),
|
||||
}
|
||||
|
||||
impl AesCbcCipher {
|
||||
pub fn key(&self) -> &[u8] {
|
||||
match &self.cipher {
|
||||
AesCbcEnum::AES128CBC(key) => key,
|
||||
AesCbcEnum::AES256CBC(key) => key,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AesCbcCipher {
|
||||
pub fn new_128(key: [u8; 16], finger: Option<Finger>) -> Self {
|
||||
Self {
|
||||
cipher: AesCbcEnum::AES128CBC(key),
|
||||
finger,
|
||||
}
|
||||
}
|
||||
pub fn new_256(key: [u8; 32], finger: Option<Finger>) -> Self {
|
||||
Self {
|
||||
cipher: AesCbcEnum::AES256CBC(key),
|
||||
finger,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
if !net_packet.is_encrypt() {
|
||||
//未加密的数据直接丢弃
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||
}
|
||||
if net_packet.payload().len() < 16 {
|
||||
log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||
}
|
||||
let mut iv = [0; 16];
|
||||
iv[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
iv[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
iv[8] = net_packet.protocol().into();
|
||||
iv[9] = net_packet.transport_protocol();
|
||||
iv[10] = net_packet.is_gateway() as u8;
|
||||
iv[11] = net_packet.source_ttl();
|
||||
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 {
|
||||
AesCbcEnum::AES128CBC(key) => Aes128CbcDec::new(&(*key).into(), &iv.into())
|
||||
.decrypt_padded_mut::<Pkcs7>(secret_body.en_body_mut()),
|
||||
AesCbcEnum::AES256CBC(key) => Aes256CbcDec::new(&(*key).into(), &iv.into())
|
||||
.decrypt_padded_mut::<Pkcs7>(secret_body.en_body_mut()),
|
||||
};
|
||||
match rs {
|
||||
Ok(buf) => {
|
||||
let len = buf.len();
|
||||
net_packet.set_encrypt_flag(false);
|
||||
//减去末尾的随机数
|
||||
net_packet.set_data_len(HEAD_LEN + len - 4)?;
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("解密失败:{}", e),
|
||||
)),
|
||||
}
|
||||
}
|
||||
/// net_packet 必须预留足够长度
|
||||
/// data_len是有效载荷的长度
|
||||
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
let data_len = net_packet.data_len();
|
||||
let mut iv = [0; 16];
|
||||
iv[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
iv[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
iv[8] = net_packet.protocol().into();
|
||||
iv[9] = net_packet.transport_protocol();
|
||||
iv[10] = net_packet.is_gateway() as u8;
|
||||
iv[11] = net_packet.source_ttl();
|
||||
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 {
|
||||
AesCbcEnum::AES128CBC(key) => Aes128CbcEnc::new(&(*key).into(), &iv.into())
|
||||
.encrypt_padded_mut::<Pkcs7>(net_packet.payload_mut(), p_len),
|
||||
AesCbcEnum::AES256CBC(key) => Aes256CbcEnc::new(&(*key).into(), &iv.into())
|
||||
.encrypt_padded_mut::<Pkcs7>(net_packet.payload_mut(), p_len),
|
||||
};
|
||||
return match rs {
|
||||
Ok(buf) => {
|
||||
let len = buf.len();
|
||||
if let Some(finger) = &self.finger {
|
||||
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);
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("加密失败:{}", e),
|
||||
)),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
use crate::cipher::Finger;
|
||||
use crate::protocol::{NetPacket, HEAD_LEN};
|
||||
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyInit};
|
||||
use std::io;
|
||||
|
||||
type Aes128EcbEnc = ecb::Encryptor<aes::Aes128>;
|
||||
type Aes128EcbDec = ecb::Decryptor<aes::Aes128>;
|
||||
type Aes256EcbEnc = ecb::Encryptor<aes::Aes256>;
|
||||
type Aes256EcbDec = ecb::Decryptor<aes::Aes256>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AesEcbCipher {
|
||||
key: AesEcbEnum,
|
||||
pub(crate) finger: Option<Finger>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum AesEcbEnum {
|
||||
AES128ECB([u8; 16]),
|
||||
AES256ECB([u8; 32]),
|
||||
}
|
||||
|
||||
impl AesEcbCipher {
|
||||
pub fn key(&self) -> &[u8] {
|
||||
match &self.key {
|
||||
AesEcbEnum::AES128ECB(key) => key,
|
||||
AesEcbEnum::AES256ECB(key) => key,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AesEcbCipher {
|
||||
pub fn new_128(key: [u8; 16], finger: Option<Finger>) -> Self {
|
||||
Self {
|
||||
key: AesEcbEnum::AES128ECB(key),
|
||||
finger,
|
||||
}
|
||||
}
|
||||
pub fn new_256(key: [u8; 32], finger: Option<Finger>) -> Self {
|
||||
Self {
|
||||
key: AesEcbEnum::AES256ECB(key),
|
||||
finger,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
if !net_packet.is_encrypt() {
|
||||
//未加密的数据直接丢弃
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||
}
|
||||
if net_packet.payload().len() < 16 {
|
||||
log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||
}
|
||||
|
||||
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 mut out = [0u8; 1024 * 5];
|
||||
let rs = match self.key {
|
||||
AesEcbEnum::AES128ECB(key) => Aes128EcbDec::new(&key.into())
|
||||
.decrypt_padded_b2b_mut::<Pkcs7>(net_packet.payload(), &mut out),
|
||||
AesEcbEnum::AES256ECB(key) => Aes256EcbDec::new(&key.into())
|
||||
.decrypt_padded_b2b_mut::<Pkcs7>(net_packet.payload(), &mut out),
|
||||
};
|
||||
match rs {
|
||||
Ok(buf) => {
|
||||
//校验头部
|
||||
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);
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("解密失败:{}", e),
|
||||
)),
|
||||
}
|
||||
}
|
||||
/// net_packet 必须预留足够长度
|
||||
/// data_len是有效载荷的长度
|
||||
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
let mut out = [0u8; 1024 * 5];
|
||||
let rs = match self.key {
|
||||
AesEcbEnum::AES128ECB(key) => Aes128EcbEnc::new(&key.into())
|
||||
.encrypt_padded_b2b_mut::<Pkcs7>(net_packet.buffer(), &mut out),
|
||||
AesEcbEnum::AES256ECB(key) => Aes256EcbEnc::new(&key.into())
|
||||
.encrypt_padded_b2b_mut::<Pkcs7>(net_packet.buffer(), &mut out),
|
||||
};
|
||||
|
||||
return match rs {
|
||||
Ok(buf) => {
|
||||
net_packet.set_data_len(HEAD_LEN + buf.len())?;
|
||||
net_packet.set_payload(buf)?;
|
||||
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(())
|
||||
}
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("加密失败:{}", 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();
|
||||
d.encrypt_ipv4(&mut p).unwrap();
|
||||
d.decrypt_ipv4(&mut p).unwrap();
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
use std::io;
|
||||
|
||||
use aes_gcm::aead::consts::{U12, U16};
|
||||
use aes_gcm::aead::generic_array::GenericArray;
|
||||
use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, KeyInit, Nonce, Tag};
|
||||
use rand::RngCore;
|
||||
|
||||
use crate::cipher::finger::Finger;
|
||||
use crate::protocol::{body::SecretBody, body::AES_GCM_ENCRYPTION_RESERVED, NetPacket};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AesGcmCipher {
|
||||
pub(crate) cipher: AesGcmEnum,
|
||||
pub(crate) finger: Option<Finger>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum AesGcmEnum {
|
||||
AES128GCM(Aes128Gcm),
|
||||
AES256GCM(Aes256Gcm),
|
||||
}
|
||||
|
||||
impl AesGcmCipher {
|
||||
pub fn new_128(key: [u8; 16], finger: Option<Finger>) -> Self {
|
||||
let key: &Key<Aes128Gcm> = &key.into();
|
||||
Self {
|
||||
cipher: AesGcmEnum::AES128GCM(Aes128Gcm::new(key)),
|
||||
finger,
|
||||
}
|
||||
}
|
||||
pub fn new_256(key: [u8; 32], finger: Option<Finger>) -> Self {
|
||||
let key: &Key<Aes256Gcm> = &key.into();
|
||||
Self {
|
||||
cipher: AesGcmEnum::AES256GCM(Aes256Gcm::new(key)),
|
||||
finger,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
if !net_packet.is_encrypt() {
|
||||
//未加密的数据直接丢弃
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||
}
|
||||
if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED {
|
||||
log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||
}
|
||||
let mut nonce_raw = [0; 12];
|
||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce_raw[8] = net_packet.protocol().into();
|
||||
nonce_raw[9] = net_packet.transport_protocol();
|
||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||
nonce_raw[11] = net_packet.source_ttl();
|
||||
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
|
||||
|
||||
let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
||||
let tag = secret_body.tag();
|
||||
if let Some(finger) = &self.finger {
|
||||
let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body());
|
||||
if &finger != secret_body.finger() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
||||
}
|
||||
}
|
||||
let tag: GenericArray<u8, U16> = Tag::clone_from_slice(tag);
|
||||
let rs = match &self.cipher {
|
||||
AesGcmEnum::AES128GCM(aes_gcm) => {
|
||||
aes_gcm.decrypt_in_place_detached(nonce, &[], secret_body.body_mut(), &tag)
|
||||
}
|
||||
AesGcmEnum::AES256GCM(aes_gcm) => {
|
||||
aes_gcm.decrypt_in_place_detached(nonce, &[], secret_body.body_mut(), &tag)
|
||||
}
|
||||
};
|
||||
if let Err(e) = rs {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("解密失败:{}", e),
|
||||
));
|
||||
}
|
||||
net_packet.set_encrypt_flag(false);
|
||||
net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?;
|
||||
return Ok(());
|
||||
}
|
||||
/// net_packet 必须预留足够长度
|
||||
/// data_len是有效载荷的长度
|
||||
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
if net_packet.reserve() < AES_GCM_ENCRYPTION_RESERVED {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "too short"));
|
||||
}
|
||||
let mut nonce_raw = [0; 12];
|
||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce_raw[8] = net_packet.protocol().into();
|
||||
nonce_raw[9] = net_packet.transport_protocol();
|
||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||
nonce_raw[11] = net_packet.source_ttl();
|
||||
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
|
||||
let data_len = net_packet.data_len() + AES_GCM_ENCRYPTION_RESERVED;
|
||||
net_packet.set_data_len(data_len)?;
|
||||
let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
||||
secret_body.set_random(rand::thread_rng().next_u32());
|
||||
let rs = match &self.cipher {
|
||||
AesGcmEnum::AES128GCM(aes_gcm) => {
|
||||
aes_gcm.encrypt_in_place_detached(nonce, &[], secret_body.body_mut())
|
||||
}
|
||||
AesGcmEnum::AES256GCM(aes_gcm) => {
|
||||
aes_gcm.encrypt_in_place_detached(nonce, &[], secret_body.body_mut())
|
||||
}
|
||||
};
|
||||
return match rs {
|
||||
Ok(tag) => {
|
||||
secret_body.set_tag(tag.as_slice())?;
|
||||
if let Some(finger) = &self.finger {
|
||||
let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body());
|
||||
secret_body.set_finger(&finger)?;
|
||||
}
|
||||
net_packet.set_encrypt_flag(true);
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("加密失败:{}", e),
|
||||
)),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
|
||||
use crate::cipher::aes_ecb::AesEcbCipher;
|
||||
#[cfg(not(feature = "ring-cipher"))]
|
||||
use crate::cipher::aes_gcm_cipher::AesGcmCipher;
|
||||
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
|
||||
use crate::cipher::openssl_aes_ecb::AesEcbCipher;
|
||||
#[cfg(feature = "ring-cipher")]
|
||||
use crate::cipher::ring_aes_gcm_cipher::AesGcmCipher;
|
||||
use crate::cipher::{aes_cbc, Finger};
|
||||
use crate::protocol::NetPacket;
|
||||
use aes_cbc::AesCbcCipher;
|
||||
use sha2::Digest;
|
||||
use std::io;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum CipherModel {
|
||||
AesGcm,
|
||||
AesCbc,
|
||||
AesEcb,
|
||||
}
|
||||
|
||||
impl FromStr for CipherModel {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s.to_lowercase().trim() {
|
||||
"aes_gcm" => Ok(CipherModel::AesGcm),
|
||||
"aes_cbc" => Ok(CipherModel::AesCbc),
|
||||
"aes_ecb" => Ok(CipherModel::AesEcb),
|
||||
_ => Err(format!("not match '{}'", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Cipher {
|
||||
AesGcm((AesGcmCipher, Vec<u8>)),
|
||||
AesCbc(AesCbcCipher),
|
||||
AesEcb(AesEcbCipher),
|
||||
None,
|
||||
}
|
||||
|
||||
impl Cipher {
|
||||
pub fn new_password(
|
||||
model: CipherModel,
|
||||
password: Option<String>,
|
||||
token: Option<String>,
|
||||
) -> Self {
|
||||
let finger = token.map(|token| Finger::new(&token));
|
||||
if let Some(password) = password {
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(password.as_bytes());
|
||||
let key: [u8; 32] = hasher.finalize().into();
|
||||
match model {
|
||||
CipherModel::AesGcm => {
|
||||
if password.len() < 8 {
|
||||
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||
Cipher::AesGcm((aes, key[..16].to_vec()))
|
||||
} else {
|
||||
let aes = AesGcmCipher::new_256(key, finger);
|
||||
Cipher::AesGcm((aes, key.to_vec()))
|
||||
}
|
||||
}
|
||||
CipherModel::AesCbc => {
|
||||
if password.len() < 8 {
|
||||
let aes = AesCbcCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||
Cipher::AesCbc(aes)
|
||||
} else {
|
||||
let aes = AesCbcCipher::new_256(key, finger);
|
||||
Cipher::AesCbc(aes)
|
||||
}
|
||||
}
|
||||
CipherModel::AesEcb => {
|
||||
if password.len() < 8 {
|
||||
let aes = AesEcbCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||
Cipher::AesEcb(aes)
|
||||
} else {
|
||||
let aes = AesEcbCipher::new_256(key, finger);
|
||||
Cipher::AesEcb(aes)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Cipher::None
|
||||
}
|
||||
}
|
||||
pub fn new_key(key: [u8; 32], token: String) -> io::Result<Self> {
|
||||
let finger = Some(Finger::new(&token));
|
||||
match key.len() {
|
||||
16 => {
|
||||
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||
Ok(Cipher::AesGcm((aes, key[..16].to_vec())))
|
||||
}
|
||||
32 => {
|
||||
let aes = AesGcmCipher::new_256(key, finger);
|
||||
Ok(Cipher::AesGcm((aes, key.to_vec())))
|
||||
}
|
||||
_ => Err(io::Error::new(io::ErrorKind::Other, "key error")),
|
||||
}
|
||||
}
|
||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
match self {
|
||||
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.decrypt_ipv4(net_packet),
|
||||
Cipher::AesCbc(aes_cbc) => aes_cbc.decrypt_ipv4(net_packet),
|
||||
Cipher::AesEcb(aes_ecb) => aes_ecb.decrypt_ipv4(net_packet),
|
||||
Cipher::None => {
|
||||
if net_packet.is_encrypt() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not key"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
match self {
|
||||
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.encrypt_ipv4(net_packet),
|
||||
Cipher::AesCbc(aes_cbc) => aes_cbc.encrypt_ipv4(net_packet),
|
||||
Cipher::AesEcb(aes_ecb) => aes_ecb.encrypt_ipv4(net_packet),
|
||||
Cipher::None => Ok(()),
|
||||
}
|
||||
}
|
||||
pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> io::Result<()> {
|
||||
let finger = match self {
|
||||
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.finger.as_ref(),
|
||||
Cipher::AesCbc(aes_cbc) => aes_cbc.finger.as_ref(),
|
||||
Cipher::AesEcb(aes_ecb) => aes_ecb.finger.as_ref(),
|
||||
Cipher::None => None,
|
||||
};
|
||||
if let Some(finger) = finger {
|
||||
finger.check_finger(net_packet)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
pub fn key(&self) -> Option<&[u8]> {
|
||||
match self {
|
||||
Cipher::AesGcm((_, key)) => Some(key),
|
||||
Cipher::AesCbc(aes_cbc) => Some(aes_cbc.key()),
|
||||
Cipher::AesEcb(aes_ecb) => Some(aes_ecb.key()),
|
||||
Cipher::None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
use std::io;
|
||||
|
||||
use sha2::Digest;
|
||||
|
||||
use crate::protocol::NetPacket;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Finger {
|
||||
pub(crate) hash: [u8; 32],
|
||||
}
|
||||
|
||||
impl Finger {
|
||||
pub fn new(str: &str) -> Self {
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(str.as_bytes());
|
||||
let hash: [u8; 32] = hasher.finalize().into();
|
||||
Finger { hash }
|
||||
}
|
||||
pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> io::Result<()> {
|
||||
if !net_packet.is_encrypt() {
|
||||
//未加密的数据直接丢弃
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||
}
|
||||
let payload_len = net_packet.payload().len();
|
||||
if payload_len < 12 {
|
||||
log::error!("数据异常,长度小于{}", 12);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||
}
|
||||
let mut nonce_raw = [0; 12];
|
||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce_raw[8] = net_packet.protocol().into();
|
||||
nonce_raw[9] = net_packet.transport_protocol();
|
||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||
nonce_raw[11] = net_packet.source_ttl();
|
||||
let payload = net_packet.payload();
|
||||
let finger = self.calculate_finger(&nonce_raw, &payload[..payload_len - 12]);
|
||||
if &finger[..] != &payload[payload_len - 12..] {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn calculate_finger(&self, nonce: &[u8], secret_body: &[u8]) -> [u8; 12] {
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(nonce);
|
||||
hasher.update(secret_body);
|
||||
hasher.update(&self.hash);
|
||||
let key: [u8; 32] = hasher.finalize().into();
|
||||
return key[20..].try_into().unwrap();
|
||||
}
|
||||
}
|
||||
+16
-113
@@ -1,115 +1,18 @@
|
||||
use std::io;
|
||||
mod aes_cbc;
|
||||
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
|
||||
mod aes_ecb;
|
||||
#[cfg(not(feature = "ring-cipher"))]
|
||||
mod aes_gcm_cipher;
|
||||
mod cipher;
|
||||
mod finger;
|
||||
#[cfg(feature = "ring-cipher")]
|
||||
mod ring_aes_gcm_cipher;
|
||||
mod rsa_cipher;
|
||||
|
||||
use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, Nonce, Tag,KeyInit};
|
||||
use aes_gcm::aead::consts::{U12, U16};
|
||||
use aes_gcm::aead::generic_array::GenericArray;
|
||||
use sha2::Digest;
|
||||
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
|
||||
mod openssl_aes_ecb;
|
||||
|
||||
use crate::protocol;
|
||||
use crate::protocol::{ip_turn_packet, NetPacket};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Cipher {
|
||||
AesGCM128(Aes128Gcm),
|
||||
AesGCM256(Aes256Gcm),
|
||||
None,
|
||||
}
|
||||
|
||||
impl Cipher {
|
||||
pub fn new(password: Option<String>) -> Self {
|
||||
if let Some(password) = password {
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(password.as_bytes());
|
||||
let key: [u8; 32] = hasher.finalize().into();
|
||||
if password.len() < 8 {
|
||||
let key: &Key<Aes128Gcm> = key[..16].into();
|
||||
Cipher::AesGCM128(Aes128Gcm::new(&key))
|
||||
} else {
|
||||
let key: &Key<Aes256Gcm> = &key.into();
|
||||
Cipher::AesGCM256(Aes256Gcm::new(&key))
|
||||
}
|
||||
} else {
|
||||
Cipher::None
|
||||
}
|
||||
}
|
||||
pub fn decrypt_ipv4(&self, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result<Option<usize>> {
|
||||
match &self {
|
||||
Cipher::None => {
|
||||
return Ok(None);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if !net_packet.is_encrypt() {
|
||||
//未加密的数据直接丢弃
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||
}
|
||||
if net_packet.payload().len() < 16 {
|
||||
log::error!("数据异常,长度小于16");
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||
}
|
||||
let mut nonce = [0; 12];
|
||||
nonce[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce[8] = protocol::Protocol::IpTurn.into();
|
||||
nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
|
||||
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce);
|
||||
let payload_len = net_packet.payload().len() - 16;
|
||||
let tag: GenericArray<u8, U16> = Tag::clone_from_slice(&net_packet.payload()[payload_len..]);
|
||||
let rs = match &self {
|
||||
Cipher::AesGCM128(cipher) => {
|
||||
cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len], &tag)
|
||||
}
|
||||
Cipher::AesGCM256(cipher) => {
|
||||
cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len], &tag)
|
||||
}
|
||||
Cipher::None => {
|
||||
return Ok(None);
|
||||
}
|
||||
};
|
||||
if let Err(e) = rs {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e)));
|
||||
}
|
||||
return Ok(Some(payload_len));
|
||||
}
|
||||
/// net_packet 必须预留足够长度
|
||||
/// data_len是有效载荷的长度
|
||||
/// 返回加密后载荷的长度
|
||||
pub fn encrypt_ipv4(&self, payload_len: usize, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result<Option<usize>> {
|
||||
match &self {
|
||||
Cipher::None => {
|
||||
return Ok(None);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let mut nonce = [0; 12];
|
||||
nonce[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce[8] = protocol::Protocol::IpTurn.into();
|
||||
nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
|
||||
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce);
|
||||
let rs = match &self {
|
||||
Cipher::AesGCM128(cipher) => {
|
||||
cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len])
|
||||
}
|
||||
Cipher::AesGCM256(cipher) => {
|
||||
cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len])
|
||||
}
|
||||
Cipher::None => {
|
||||
return Ok(None);
|
||||
}
|
||||
};
|
||||
return match rs {
|
||||
Ok(tag) => {
|
||||
if tag.len() != 16 {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("加密tag长度错误:{}", tag.len())));
|
||||
}
|
||||
net_packet.set_encrypt_flag(true);
|
||||
net_packet.payload_mut()[payload_len..payload_len + 16].copy_from_slice(tag.as_slice());
|
||||
Ok(Some(payload_len + 16))
|
||||
}
|
||||
Err(e) => {
|
||||
Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e)))
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
pub use cipher::Cipher;
|
||||
pub use cipher::CipherModel;
|
||||
pub use finger::Finger;
|
||||
pub use rsa_cipher::RsaCipher;
|
||||
|
||||
@@ -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 net_packet.payload().len() < 16 {
|
||||
log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||
}
|
||||
|
||||
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())?;
|
||||
}
|
||||
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();
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
use crate::cipher::Finger;
|
||||
use rand::RngCore;
|
||||
use ring::aead;
|
||||
use ring::aead::{LessSafeKey, UnboundKey};
|
||||
use std::io;
|
||||
|
||||
use crate::protocol::body::{SecretBody, AES_GCM_ENCRYPTION_RESERVED};
|
||||
use crate::protocol::NetPacket;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AesGcmCipher {
|
||||
pub(crate) cipher: AesGcmEnum,
|
||||
pub(crate) finger: Option<Finger>,
|
||||
}
|
||||
|
||||
pub enum AesGcmEnum {
|
||||
AesGCM128(LessSafeKey, [u8; 16]),
|
||||
AesGCM256(LessSafeKey, [u8; 32]),
|
||||
}
|
||||
|
||||
impl Clone for AesGcmEnum {
|
||||
fn clone(&self) -> Self {
|
||||
match &self {
|
||||
AesGcmEnum::AesGCM128(_, key) => {
|
||||
let c =
|
||||
LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, key.as_slice()).unwrap());
|
||||
AesGcmEnum::AesGCM128(c, *key)
|
||||
}
|
||||
AesGcmEnum::AesGCM256(_, key) => {
|
||||
let c =
|
||||
LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, key.as_slice()).unwrap());
|
||||
AesGcmEnum::AesGCM256(c, *key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AesGcmCipher {
|
||||
pub fn new_128(key: [u8; 16], finger: Option<Finger>) -> Self {
|
||||
let cipher = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, &key).unwrap());
|
||||
Self {
|
||||
cipher: AesGcmEnum::AesGCM128(cipher, key),
|
||||
finger,
|
||||
}
|
||||
}
|
||||
pub fn new_256(key: [u8; 32], finger: Option<Finger>) -> Self {
|
||||
let cipher = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, &key).unwrap());
|
||||
Self {
|
||||
cipher: AesGcmEnum::AesGCM256(cipher, key),
|
||||
finger,
|
||||
}
|
||||
}
|
||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
if !net_packet.is_encrypt() {
|
||||
//未加密的数据直接丢弃
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||
}
|
||||
if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED {
|
||||
log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||
}
|
||||
let mut nonce_raw = [0; 12];
|
||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce_raw[8] = net_packet.protocol().into();
|
||||
nonce_raw[9] = net_packet.transport_protocol();
|
||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||
nonce_raw[11] = net_packet.source_ttl();
|
||||
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
|
||||
let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
||||
if let Some(finger) = &self.finger {
|
||||
let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body());
|
||||
if &finger != secret_body.finger() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "ring aes finger err"));
|
||||
}
|
||||
}
|
||||
|
||||
let rs = match &self.cipher {
|
||||
AesGcmEnum::AesGCM128(cipher, _) => {
|
||||
cipher.open_in_place(nonce, aead::Aad::empty(), secret_body.en_body_mut())
|
||||
}
|
||||
AesGcmEnum::AesGCM256(cipher, _) => {
|
||||
cipher.open_in_place(nonce, aead::Aad::empty(), secret_body.en_body_mut())
|
||||
}
|
||||
};
|
||||
if let Err(e) = rs {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("解密失败:{}", e),
|
||||
));
|
||||
}
|
||||
net_packet.set_encrypt_flag(false);
|
||||
net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?;
|
||||
return Ok(());
|
||||
}
|
||||
/// net_packet 必须预留足够长度
|
||||
/// data_len是有效载荷的长度
|
||||
/// 返回加密后载荷的长度
|
||||
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
let mut nonce_raw = [0; 12];
|
||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce_raw[8] = net_packet.protocol().into();
|
||||
nonce_raw[9] = net_packet.transport_protocol();
|
||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||
nonce_raw[11] = net_packet.source_ttl();
|
||||
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
|
||||
let data_len = net_packet.data_len() + AES_GCM_ENCRYPTION_RESERVED;
|
||||
net_packet.set_data_len(data_len)?;
|
||||
let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
||||
secret_body.set_random(rand::thread_rng().next_u32());
|
||||
|
||||
let rs = match &self.cipher {
|
||||
AesGcmEnum::AesGCM128(cipher, _) => {
|
||||
cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), secret_body.body_mut())
|
||||
}
|
||||
AesGcmEnum::AesGCM256(cipher, _) => {
|
||||
cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), secret_body.body_mut())
|
||||
}
|
||||
};
|
||||
return match rs {
|
||||
Ok(tag) => {
|
||||
let tag = tag.as_ref();
|
||||
if tag.len() != 16 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("加密tag长度错误:{}", tag.len()),
|
||||
));
|
||||
}
|
||||
secret_body.set_tag(tag)?;
|
||||
if let Some(finger) = &self.finger {
|
||||
let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body());
|
||||
secret_body.set_finger(&finger)?;
|
||||
}
|
||||
net_packet.set_encrypt_flag(true);
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("加密失败:{}", e),
|
||||
)),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
use crate::protocol::body::{RsaSecretBody, RSA_ENCRYPTION_RESERVED};
|
||||
use crate::protocol::NetPacket;
|
||||
use rand::Rng;
|
||||
use rsa::pkcs8::der::Decode;
|
||||
use rsa::{PublicKey, RsaPublicKey};
|
||||
use sha2::Digest;
|
||||
use spki::{DecodePublicKey, EncodePublicKey};
|
||||
use std::io;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RsaCipher {
|
||||
inner: Inner,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Inner {
|
||||
public_key: RsaPublicKey,
|
||||
}
|
||||
|
||||
impl RsaCipher {
|
||||
pub fn new(der: &[u8]) -> io::Result<Self> {
|
||||
match RsaPublicKey::from_public_key_der(der) {
|
||||
Ok(public_key) => {
|
||||
let inner = Inner { public_key };
|
||||
Ok(Self { inner })
|
||||
}
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("from_public_key_der failed {}", e),
|
||||
)),
|
||||
}
|
||||
}
|
||||
pub fn finger(&self) -> io::Result<String> {
|
||||
match self.inner.public_key.to_public_key_der() {
|
||||
Ok(der) => match rsa::pkcs8::SubjectPublicKeyInfo::from_der(der.as_bytes()) {
|
||||
Ok(spki) => match spki.fingerprint_base64() {
|
||||
Ok(finger) => Ok(finger),
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("fingerprint_base64 error {}", e),
|
||||
)),
|
||||
},
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("from_der error {}", e),
|
||||
)),
|
||||
},
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("to_public_key_der error {}", e),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RsaCipher {
|
||||
/// net_packet 必须预留足够长度
|
||||
pub fn encrypt<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<NetPacket<Vec<u8>>> {
|
||||
if net_packet.reserve() < RSA_ENCRYPTION_RESERVED {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "too short"));
|
||||
}
|
||||
let data_len = net_packet.data_len() + RSA_ENCRYPTION_RESERVED;
|
||||
net_packet.set_data_len(data_len)?;
|
||||
let mut nonce_raw = [0; 12];
|
||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||
nonce_raw[8] = net_packet.protocol().into();
|
||||
nonce_raw[9] = net_packet.transport_protocol();
|
||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||
nonce_raw[11] = net_packet.source_ttl();
|
||||
|
||||
let mut secret_body = RsaSecretBody::new(net_packet.payload_mut())?;
|
||||
let mut rng = rand::thread_rng();
|
||||
rng.fill(secret_body.random_mut());
|
||||
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(secret_body.body());
|
||||
hasher.update(nonce_raw);
|
||||
let key: [u8; 32] = hasher.finalize().into();
|
||||
secret_body.set_finger(&key[16..])?;
|
||||
match self.inner.public_key.encrypt(
|
||||
&mut rng,
|
||||
rsa::PaddingScheme::PKCS1v15Encrypt,
|
||||
secret_body.buffer(),
|
||||
) {
|
||||
Ok(enc_data) => {
|
||||
let mut net_packet_e = NetPacket::new(vec![0; 12 + enc_data.len()])?;
|
||||
net_packet_e.buffer_mut()[..12].copy_from_slice(&net_packet.buffer()[..12]);
|
||||
net_packet_e.set_payload(&enc_data)?;
|
||||
Ok(net_packet_e)
|
||||
}
|
||||
Err(e) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("encrypt failed {}", e),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
+355
-111
@@ -3,28 +3,35 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use dashmap::DashMap;
|
||||
use parking_lot::Mutex;
|
||||
use tokio::net::{TcpStream, UdpSocket};
|
||||
use rand::Rng;
|
||||
use std::net::UdpSocket;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::sync::mpsc::channel;
|
||||
|
||||
use crate::channel::{Route, RouteKey};
|
||||
use crate::channel::channel::{Channel, Context};
|
||||
use crate::channel::idle::Idle;
|
||||
use crate::channel::punch::{NatInfo, Punch};
|
||||
use crate::channel::punch::{NatInfo, Punch, PunchModel};
|
||||
use crate::channel::sender::ChannelSender;
|
||||
use crate::cipher::Cipher;
|
||||
use crate::channel::{Route, RouteKey};
|
||||
use crate::cipher::{Cipher, CipherModel, RsaCipher};
|
||||
use crate::core::status::VntStatusManger;
|
||||
use crate::error::Error;
|
||||
use crate::external_route::ExternalRoute;
|
||||
use crate::handle::{ConnectStatus, CurrentDeviceInfo, heartbeat_handler, PeerDeviceInfo, punch_handler, registration_handler};
|
||||
use crate::external_route::{AllowExternalRoute, ExternalRoute};
|
||||
use crate::handle::handshake_handler::HandshakeEnum;
|
||||
use crate::handle::recv_handler::ChannelDataHandler;
|
||||
use crate::handle::registration_handler::{RegResponse, ReqEnum};
|
||||
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
|
||||
use crate::handle::tun_tap::tap_handler;
|
||||
use crate::handle::tun_tap::tun_handler;
|
||||
use crate::handle::{
|
||||
handshake_handler, heartbeat_handler, punch_handler, registration_handler, ConnectStatus,
|
||||
CurrentDeviceInfo, PeerDeviceInfo,
|
||||
};
|
||||
use crate::igmp_server::IgmpServer;
|
||||
use crate::ip_proxy::DashMapNew;
|
||||
use crate::nat::NatTest;
|
||||
use crate::tun_tap_device;
|
||||
use crate::tun_tap_device::{DeviceReader, DeviceWriter};
|
||||
@@ -32,10 +39,9 @@ use crate::tun_tap_device::{DeviceReader, DeviceWriter};
|
||||
pub mod status;
|
||||
pub mod sync;
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vnt {
|
||||
name: String,
|
||||
config: Config,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
context: Context,
|
||||
vnt_status_manager: VntStatusManger,
|
||||
@@ -46,49 +52,111 @@ pub struct Vnt {
|
||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||
nat_test: NatTest,
|
||||
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
||||
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
|
||||
peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>>,
|
||||
}
|
||||
|
||||
pub struct VntUtil {
|
||||
config: Config,
|
||||
main_channel: UdpSocket,
|
||||
main_channel_ipv6: Option<UdpSocket>,
|
||||
main_tcp_channel: Option<TcpStream>,
|
||||
response: Option<RegResponse>,
|
||||
iface: Option<(DeviceWriter, DeviceReader)>,
|
||||
server_cipher: Cipher,
|
||||
rsa_cipher: Option<RsaCipher>,
|
||||
}
|
||||
|
||||
impl 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 = UdpSocket::bind("0.0.0.0:0")?;
|
||||
main_channel.set_write_timeout(Some(Duration::from_secs(5)))?;
|
||||
main_channel.set_read_timeout(Some(Duration::from_secs(2)))?;
|
||||
let main_channel_ipv6 = if config.punch_model != PunchModel::IPv4 {
|
||||
match UdpSocket::bind("[::]:0") {
|
||||
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 mut key = [0 as u8; 32];
|
||||
rand::thread_rng().fill(&mut key);
|
||||
Cipher::new_key(key, config.token.clone())?
|
||||
} else {
|
||||
Cipher::None
|
||||
};
|
||||
Ok(VntUtil {
|
||||
config,
|
||||
main_channel,
|
||||
main_channel_ipv6,
|
||||
main_tcp_channel: None,
|
||||
response: None,
|
||||
iface: None,
|
||||
server_cipher,
|
||||
rsa_cipher: None,
|
||||
})
|
||||
}
|
||||
pub async fn connect(&mut self) -> Result<RegResponse, ReqEnum> {
|
||||
///链接
|
||||
pub async fn connect(&mut self) -> io::Result<()> {
|
||||
if self.config.tcp {
|
||||
match TcpStream::connect(self.config.server_address).await {
|
||||
Ok(tcp) => {
|
||||
let _ = self.main_tcp_channel.insert(tcp);
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(ReqEnum::Other(format!("connect error:{}", e)));
|
||||
}
|
||||
}
|
||||
let tcp = TcpStream::connect(self.config.server_address).await?;
|
||||
let _ = self.main_tcp_channel.insert(tcp);
|
||||
}
|
||||
match registration_handler::registration(&self.main_channel, self.main_tcp_channel.as_mut(), self.config.server_address,
|
||||
self.config.token.clone(), self.config.device_id.clone(),
|
||||
self.config.name.clone(), self.config.ip.unwrap_or(Ipv4Addr::UNSPECIFIED)).await {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
///握手 用于获取公钥
|
||||
pub async fn handshake(&mut self) -> Result<Option<RsaCipher>, HandshakeEnum> {
|
||||
let rsa_cipher = handshake_handler::handshake(
|
||||
&self.main_channel,
|
||||
self.main_tcp_channel.as_mut(),
|
||||
self.config.server_address,
|
||||
self.config.server_encrypt,
|
||||
)
|
||||
.await?;
|
||||
self.rsa_cipher = rsa_cipher.clone();
|
||||
Ok(rsa_cipher)
|
||||
}
|
||||
/// 加密握手 用于同步密钥
|
||||
pub async fn secret_handshake(&mut self) -> Result<(), HandshakeEnum> {
|
||||
handshake_handler::secret_handshake(
|
||||
&self.main_channel,
|
||||
self.main_tcp_channel.as_mut(),
|
||||
self.config.server_address,
|
||||
self.rsa_cipher.as_ref().unwrap(),
|
||||
&self.server_cipher,
|
||||
self.config.token.clone(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
/// 注册
|
||||
pub async fn register(&mut self) -> Result<RegResponse, ReqEnum> {
|
||||
match registration_handler::registration(
|
||||
&self.main_channel,
|
||||
self.main_tcp_channel.as_mut(),
|
||||
&self.server_cipher,
|
||||
self.config.server_address,
|
||||
self.config.token.clone(),
|
||||
self.config.device_id.clone(),
|
||||
self.config.name.clone(),
|
||||
self.config.ip.unwrap_or(Ipv4Addr::UNSPECIFIED),
|
||||
self.config.password.is_some(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(res) => {
|
||||
let _ = self.response.insert(res.clone());
|
||||
Ok(res)
|
||||
}
|
||||
Err(e) => {
|
||||
Err(e)
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
#[cfg(any(target_os = "android"))]
|
||||
@@ -105,57 +173,82 @@ impl VntUtil {
|
||||
None => {
|
||||
return Err(io::Error::from(io::ErrorKind::AlreadyExists));
|
||||
}
|
||||
Some(res) => {
|
||||
res
|
||||
}
|
||||
Some(res) => res,
|
||||
};
|
||||
let device_type = if self.config.tap {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
//删除tun网卡避免ip冲突,因为非正常退出会保留网卡
|
||||
tun_tap_device::delete_device(tun_tap_device::DeviceType::Tun);
|
||||
}
|
||||
tun_tap_device::DeviceType::Tap
|
||||
} else {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
//删除tap网卡避免ip冲突,非正常退出会保留网卡
|
||||
tun_tap_device::delete_device(tun_tap_device::DeviceType::Tap);
|
||||
}
|
||||
tun_tap_device::DeviceType::Tun
|
||||
};
|
||||
let mtu = self.config.mtu.unwrap_or(1430);
|
||||
let in_ips = self.config.in_ips.iter().map(|(dest, mask, _)| { (Ipv4Addr::from(*dest & *mask), Ipv4Addr::from(*mask)) }).collect::<Vec<(Ipv4Addr, Ipv4Addr)>>();
|
||||
let mtu = match self.config.mtu {
|
||||
None => {
|
||||
if self.config.password.is_none() {
|
||||
1450
|
||||
} else {
|
||||
1410
|
||||
}
|
||||
}
|
||||
Some(mtu) => mtu,
|
||||
};
|
||||
let in_ips = self
|
||||
.config
|
||||
.in_ips
|
||||
.iter()
|
||||
.map(|(dest, mask, _)| (Ipv4Addr::from(*dest & *mask), Ipv4Addr::from(*mask)))
|
||||
.collect::<Vec<(Ipv4Addr, Ipv4Addr)>>();
|
||||
|
||||
let (device_writer, device_reader, driver_info) = tun_tap_device::create_device(device_type, response.virtual_ip,
|
||||
response.virtual_netmask, response.virtual_gateway, in_ips, mtu)?;
|
||||
let (device_writer, device_reader, driver_info) = tun_tap_device::create_device(
|
||||
device_type,
|
||||
response.virtual_ip,
|
||||
response.virtual_netmask,
|
||||
response.virtual_gateway,
|
||||
in_ips,
|
||||
mtu,
|
||||
)?;
|
||||
let _ = self.iface.insert((device_writer, device_reader));
|
||||
Ok(driver_info)
|
||||
}
|
||||
pub async fn build(self) -> crate::Result<Vnt> {
|
||||
//将读的超时时间清空
|
||||
self.main_channel.set_read_timeout(None)?;
|
||||
let response = match self.response {
|
||||
None => {
|
||||
return Err(Error::Stop("response None".to_string()));
|
||||
}
|
||||
Some(res) => {
|
||||
res
|
||||
}
|
||||
Some(res) => res,
|
||||
};
|
||||
let (device_writer, device_reader) = match self.iface {
|
||||
None => {
|
||||
return Err(Error::Stop("iface None".to_string()));
|
||||
}
|
||||
Some(res) => {
|
||||
res
|
||||
}
|
||||
Some(res) => res,
|
||||
};
|
||||
let config = self.config;
|
||||
let config = self.config.clone();
|
||||
let vnt_status_manager = VntStatusManger::new();
|
||||
let cipher = Cipher::new(config.password.clone());
|
||||
let finger = if config.finger {
|
||||
Some(config.token.clone())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let client_cipher =
|
||||
Cipher::new_password(config.cipher_model, config.password.clone(), finger);
|
||||
let virtual_ip = response.virtual_ip;
|
||||
let virtual_gateway = response.virtual_gateway;
|
||||
let virtual_netmask = response.virtual_netmask;
|
||||
let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, config.server_address)));
|
||||
let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(
|
||||
virtual_ip,
|
||||
virtual_gateway,
|
||||
virtual_netmask,
|
||||
config.server_address,
|
||||
)));
|
||||
|
||||
let (cone_sender, cone_receiver) = channel(3);
|
||||
let (symmetric_sender, symmetric_receiver) = channel(2);
|
||||
@@ -165,37 +258,65 @@ impl VntUtil {
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
let context = Context::new(Arc::new(self.main_channel), tcp_sender, current_device.clone(), 1);
|
||||
let punch = Punch::new(context.clone());
|
||||
let context = Context::new(
|
||||
Arc::new(self.main_channel),
|
||||
self.main_channel_ipv6.map(|v| Arc::new(v)),
|
||||
tcp_sender,
|
||||
current_device.clone(),
|
||||
1,
|
||||
);
|
||||
let punch = Punch::new(context.clone(), config.punch_model);
|
||||
let idle = Idle::new(Duration::from_secs(16), context.clone());
|
||||
let channel_sender = ChannelSender::new(context.clone());
|
||||
|
||||
let register = Arc::new(registration_handler::Register::new(channel_sender.clone(),
|
||||
config.server_address, config.token.clone(),
|
||||
config.device_id.clone(), config.name.clone()));
|
||||
let device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>> = Arc::new(Mutex::new((response.epoch, response.device_info_list)));
|
||||
let peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>> = Arc::new(SkipMap::new());
|
||||
let register = Arc::new(registration_handler::Register::new(
|
||||
self.server_cipher.clone(),
|
||||
channel_sender.clone(),
|
||||
config.server_address,
|
||||
config.token.clone(),
|
||||
config.device_id.clone(),
|
||||
config.name.clone(),
|
||||
config.password.is_some(),
|
||||
));
|
||||
let device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>> =
|
||||
Arc::new(Mutex::new((response.epoch, response.device_info_list)));
|
||||
let peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>> = Arc::new(DashMap::new0());
|
||||
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_ip = crate::nat::local_ip()?;
|
||||
let local_port = context.main_local_port()?;
|
||||
let local_ipv4_addr = crate::nat::local_ipv4_addr(local_port);
|
||||
let ipv6_port = context.main_local_ipv6_port().unwrap_or(0);
|
||||
let ipv6_addr = crate::nat::local_ipv6_addr(ipv6_port);
|
||||
// NAT检测
|
||||
let nat_test = NatTest::new(config.nat_test_server.clone(), response.public_ip, response.public_port, local_ip, local_port);
|
||||
|
||||
let out_ips = config.out_ips.iter().map(|(_, _, ip)| *ip).collect::<Vec<Ipv4Addr>>();
|
||||
let out_external_route = ExternalRoute::new(config.out_ips);
|
||||
let nat_test = NatTest::new(
|
||||
config.stun_server.clone(),
|
||||
public_ip,
|
||||
public_port,
|
||||
local_ipv4_addr,
|
||||
ipv6_addr,
|
||||
);
|
||||
let in_external_route = if config.in_ips.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(ExternalRoute::new(config.in_ips))
|
||||
};
|
||||
let (tcp_proxy, udp_proxy, ip_proxy_map) = if out_ips.is_empty() {
|
||||
let (tcp_proxy, udp_proxy, ip_proxy_map) = if config.out_ips.is_empty() {
|
||||
(None, None, None)
|
||||
} else {
|
||||
let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(channel_sender.clone(), out_ips, current_device.clone()).await?;
|
||||
let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(
|
||||
#[cfg(not(target_os = "android"))]
|
||||
channel_sender.clone(),
|
||||
#[cfg(not(target_os = "android"))]
|
||||
current_device.clone(),
|
||||
#[cfg(not(target_os = "android"))]
|
||||
client_cipher.clone(),
|
||||
)
|
||||
.await?;
|
||||
(Some(tcp_proxy), Some(udp_proxy), Some(ip_proxy_map))
|
||||
};
|
||||
let out_external_route = AllowExternalRoute::new(config.out_ips);
|
||||
|
||||
let igmp_server = if config.simulate_multicast {
|
||||
Some(IgmpServer::new(device_writer.clone()))
|
||||
@@ -204,56 +325,144 @@ impl VntUtil {
|
||||
};
|
||||
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
|
||||
if config.tap {
|
||||
tap_handler::start(vnt_status_manager.worker("tap_handler"), channel_sender.clone(), device_reader, device_writer.clone(),
|
||||
igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone());
|
||||
tap_handler::start(
|
||||
vnt_status_manager.worker("tap_handler"),
|
||||
channel_sender.clone(),
|
||||
device_reader,
|
||||
device_writer.clone(),
|
||||
igmp_server.clone(),
|
||||
current_device.clone(),
|
||||
in_external_route,
|
||||
ip_proxy_map.clone(),
|
||||
client_cipher.clone(),
|
||||
self.server_cipher.clone(),
|
||||
config.parallel,
|
||||
);
|
||||
} else {
|
||||
tun_handler::start(vnt_status_manager.worker("tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(),
|
||||
igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone());
|
||||
tun_handler::start(
|
||||
vnt_status_manager.worker("tun_handler"),
|
||||
channel_sender.clone(),
|
||||
device_reader,
|
||||
device_writer.clone(),
|
||||
igmp_server.clone(),
|
||||
current_device.clone(),
|
||||
in_external_route,
|
||||
ip_proxy_map.clone(),
|
||||
client_cipher.clone(),
|
||||
self.server_cipher.clone(),
|
||||
config.parallel,
|
||||
);
|
||||
}
|
||||
#[cfg(any(target_os = "android"))]
|
||||
tun_handler::start(vnt_status_manager.worker("android tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(),
|
||||
igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone());
|
||||
tun_handler::start(
|
||||
vnt_status_manager.worker("android tun_handler"),
|
||||
channel_sender.clone(),
|
||||
device_reader,
|
||||
device_writer.clone(),
|
||||
igmp_server.clone(),
|
||||
current_device.clone(),
|
||||
in_external_route,
|
||||
ip_proxy_map.clone(),
|
||||
client_cipher.clone(),
|
||||
self.server_cipher.clone(),
|
||||
config.parallel,
|
||||
);
|
||||
|
||||
//外部数据接收处理
|
||||
let channel_recv_handler = ChannelDataHandler::new(current_device.clone(), device_list.clone(),
|
||||
register.clone(), nat_test.clone(), igmp_server,
|
||||
device_writer.clone(), connect_status.clone(),
|
||||
peer_nat_info_map.clone(), ip_proxy_map, out_external_route,
|
||||
cone_sender, symmetric_sender, cipher, config.relay);
|
||||
let channel_recv_handler = ChannelDataHandler::new(
|
||||
current_device.clone(),
|
||||
device_list.clone(),
|
||||
register.clone(),
|
||||
nat_test.clone(),
|
||||
igmp_server,
|
||||
device_writer.clone(),
|
||||
connect_status.clone(),
|
||||
peer_nat_info_map.clone(),
|
||||
ip_proxy_map,
|
||||
out_external_route,
|
||||
cone_sender,
|
||||
symmetric_sender,
|
||||
client_cipher.clone(),
|
||||
self.server_cipher.clone(),
|
||||
self.rsa_cipher.clone(),
|
||||
config.relay,
|
||||
config.token.clone(),
|
||||
);
|
||||
{
|
||||
let channel = Channel::new(context.clone(), channel_recv_handler);
|
||||
let channel_worker = vnt_status_manager.worker("channel_worker");
|
||||
let relay = config.relay;
|
||||
tokio::spawn(async move {
|
||||
channel
|
||||
.start(channel_worker, tcp, 14, 65, relay, config.parallel)
|
||||
.await
|
||||
});
|
||||
}
|
||||
{
|
||||
let nat_test = nat_test.clone();
|
||||
let device_list = device_list.clone();
|
||||
let current_device = current_device.clone();
|
||||
// 定时心跳
|
||||
heartbeat_handler::start_heartbeat(
|
||||
vnt_status_manager.worker("heartbeat"),
|
||||
channel_sender.clone(),
|
||||
device_list.clone(),
|
||||
current_device.clone(),
|
||||
config.server_address_str,
|
||||
client_cipher.clone(),
|
||||
self.server_cipher.clone(),
|
||||
);
|
||||
// 空闲检查
|
||||
heartbeat_handler::start_idle(
|
||||
vnt_status_manager.worker("idle"),
|
||||
idle,
|
||||
channel_sender.clone(),
|
||||
);
|
||||
if !config.relay {
|
||||
// 打洞处理
|
||||
punch_handler::start(
|
||||
vnt_status_manager.worker("cone_receiver"),
|
||||
cone_receiver,
|
||||
punch.clone(),
|
||||
current_device.clone(),
|
||||
client_cipher.clone(),
|
||||
);
|
||||
punch_handler::start(
|
||||
vnt_status_manager.worker("symmetric_receiver"),
|
||||
symmetric_receiver,
|
||||
punch,
|
||||
current_device.clone(),
|
||||
client_cipher.clone(),
|
||||
);
|
||||
tokio::spawn(punch_handler::start_punch(
|
||||
vnt_status_manager.worker("punch_handler"),
|
||||
nat_test,
|
||||
device_list,
|
||||
channel_sender,
|
||||
current_device,
|
||||
client_cipher.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
{
|
||||
//代理
|
||||
if let Some(tcp_proxy) = tcp_proxy {
|
||||
tokio::spawn(tcp_proxy.start());
|
||||
}
|
||||
if let Some(udp_proxy) = udp_proxy {
|
||||
tokio::spawn(udp_proxy.start());
|
||||
}
|
||||
let context = context.clone();
|
||||
let nat_test = nat_test.clone();
|
||||
tokio::spawn(async move {
|
||||
channel.start(channel_worker, tcp, 14, 65, relay).await
|
||||
let info = nat_test
|
||||
.re_test(public_ip, public_port, local_ipv4_addr, ipv6_addr)
|
||||
.await;
|
||||
context.switch(info.nat_type);
|
||||
});
|
||||
}
|
||||
{
|
||||
let other_worker = vnt_status_manager.worker("punch_handler");
|
||||
let nat_test = nat_test.clone();
|
||||
let device_list = device_list.clone();
|
||||
let current_device = current_device.clone();
|
||||
// 定时心跳
|
||||
heartbeat_handler::start_heartbeat(other_worker.worker("heartbeat"), channel_sender.clone(), device_list.clone(), current_device.clone(), config.server_address_str);
|
||||
// 空闲检查
|
||||
heartbeat_handler::start_idle(other_worker.worker("idle"), idle, channel_sender.clone());
|
||||
if !config.relay {
|
||||
// 打洞处理
|
||||
punch_handler::start(other_worker.worker("cone_receiver"), cone_receiver, punch.clone(), current_device.clone());
|
||||
punch_handler::start(other_worker.worker("symmetric_receiver"), symmetric_receiver, punch, current_device.clone());
|
||||
tokio::spawn(punch_handler::start_punch(other_worker, nat_test,
|
||||
device_list, channel_sender, current_device));
|
||||
}
|
||||
}
|
||||
context.switch(nat_test.nat_info().nat_type);
|
||||
Ok(Vnt {
|
||||
name: config.name,
|
||||
config: self.config,
|
||||
current_device,
|
||||
context,
|
||||
vnt_status_manager,
|
||||
@@ -268,7 +477,13 @@ impl VntUtil {
|
||||
|
||||
impl Vnt {
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
&self.config.name
|
||||
}
|
||||
pub fn server_encrypt(&self) -> bool {
|
||||
self.config.server_encrypt
|
||||
}
|
||||
pub fn client_encrypt(&self) -> bool {
|
||||
self.config.password.is_some()
|
||||
}
|
||||
pub fn current_device(&self) -> CurrentDeviceInfo {
|
||||
self.current_device.load()
|
||||
@@ -298,12 +513,15 @@ impl Vnt {
|
||||
self.context.route_table_one()
|
||||
}
|
||||
pub fn stop(&self) -> io::Result<()> {
|
||||
self.context.close();
|
||||
let _ = self.context.close();
|
||||
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 _ = std::net::UdpSocket::bind("0.0.0.0:0")?.send_to(&[0],
|
||||
SocketAddr::V4(SocketAddrV4::new(virtual_gateway, 10000)));
|
||||
let _ = UdpSocket::bind("0.0.0.0:0")?.send_to(
|
||||
b"stop",
|
||||
SocketAddr::V4(SocketAddrV4::new(virtual_gateway, 10000)),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub async fn wait_stop(&mut self) {
|
||||
@@ -337,29 +555,50 @@ pub struct Config {
|
||||
pub name: String,
|
||||
pub server_address: SocketAddr,
|
||||
pub server_address_str: String,
|
||||
pub nat_test_server: Vec<SocketAddr>,
|
||||
pub stun_server: Vec<String>,
|
||||
pub in_ips: Vec<(u32, u32, Ipv4Addr)>,
|
||||
pub out_ips: Vec<(u32, u32, Ipv4Addr)>,
|
||||
pub out_ips: Vec<(u32, u32)>,
|
||||
pub password: Option<String>,
|
||||
pub simulate_multicast: bool,
|
||||
pub mtu: Option<u16>,
|
||||
pub tcp: bool,
|
||||
pub ip: Option<Ipv4Addr>,
|
||||
pub relay: bool,
|
||||
pub server_encrypt: bool,
|
||||
pub parallel: usize,
|
||||
pub cipher_model: CipherModel,
|
||||
pub finger: bool,
|
||||
pub punch_model: PunchModel,
|
||||
}
|
||||
|
||||
|
||||
impl Config {
|
||||
pub fn new(tap: bool, token: String,
|
||||
device_id: String,
|
||||
name: String,
|
||||
server_address: SocketAddr,
|
||||
server_address_str: String,
|
||||
nat_test_server: Vec<SocketAddr>,
|
||||
in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32, Ipv4Addr)>,
|
||||
password: Option<String>, simulate_multicast: bool, mtu: Option<u16>, tcp: bool,
|
||||
ip: Option<Ipv4Addr>,
|
||||
relay: bool, ) -> Self {
|
||||
pub fn new(
|
||||
tap: bool,
|
||||
token: String,
|
||||
device_id: String,
|
||||
name: String,
|
||||
server_address: SocketAddr,
|
||||
server_address_str: String,
|
||||
mut stun_server: Vec<String>,
|
||||
in_ips: Vec<(u32, u32, Ipv4Addr)>,
|
||||
out_ips: Vec<(u32, u32)>,
|
||||
password: Option<String>,
|
||||
simulate_multicast: bool,
|
||||
mtu: Option<u16>,
|
||||
tcp: bool,
|
||||
ip: Option<Ipv4Addr>,
|
||||
relay: bool,
|
||||
server_encrypt: bool,
|
||||
parallel: usize,
|
||||
cipher_model: CipherModel,
|
||||
finger: bool,
|
||||
punch_model: PunchModel,
|
||||
) -> Self {
|
||||
for x in stun_server.iter_mut() {
|
||||
if !x.contains(":") {
|
||||
x.push_str(":3478");
|
||||
}
|
||||
}
|
||||
Self {
|
||||
tap,
|
||||
token,
|
||||
@@ -367,7 +606,7 @@ impl Config {
|
||||
name,
|
||||
server_address,
|
||||
server_address_str,
|
||||
nat_test_server,
|
||||
stun_server,
|
||||
in_ips,
|
||||
out_ips,
|
||||
password,
|
||||
@@ -376,6 +615,11 @@ impl Config {
|
||||
tcp,
|
||||
ip,
|
||||
relay,
|
||||
server_encrypt,
|
||||
parallel,
|
||||
cipher_model,
|
||||
finger,
|
||||
punch_model,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::util::wait::WaitGroup;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::watch;
|
||||
use tokio::sync::watch::{Receiver, Sender};
|
||||
use crate::util::wait::WaitGroup;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub enum VntStatus {
|
||||
@@ -10,7 +10,7 @@ pub enum VntStatus {
|
||||
}
|
||||
|
||||
pub struct VntWorker {
|
||||
_name: String,
|
||||
name: String,
|
||||
wg: WaitGroup,
|
||||
status_s: Arc<Sender<VntStatus>>,
|
||||
status_r: Receiver<VntStatus>,
|
||||
@@ -20,7 +20,7 @@ impl VntWorker {
|
||||
pub fn worker(&self, name: &str) -> Self {
|
||||
self.wg.add();
|
||||
VntWorker {
|
||||
_name: name.to_string(),
|
||||
name: name.to_string(),
|
||||
wg: self.wg.clone(),
|
||||
status_s: self.status_s.clone(),
|
||||
status_r: self.status_r.clone(),
|
||||
@@ -30,6 +30,7 @@ impl VntWorker {
|
||||
|
||||
impl Drop for VntWorker {
|
||||
fn drop(&mut self) {
|
||||
log::info!("任务停止:{}", self.name);
|
||||
self.wg.done();
|
||||
}
|
||||
}
|
||||
@@ -49,7 +50,9 @@ impl VntWorker {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Err(_) => { return; }
|
||||
Err(_) => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +83,7 @@ impl VntStatusManger {
|
||||
pub fn worker(&self, name: &str) -> VntWorker {
|
||||
self.wg.add();
|
||||
VntWorker {
|
||||
_name: name.to_string(),
|
||||
name: name.to_string(),
|
||||
wg: self.wg.clone(),
|
||||
status_s: self.status_s.clone(),
|
||||
status_r: self.status_r.clone(),
|
||||
|
||||
+26
-14
@@ -1,9 +1,11 @@
|
||||
use crate::cipher::RsaCipher;
|
||||
use crate::core::{Config, Vnt, VntUtil};
|
||||
use crate::handle::handshake_handler::HandshakeEnum;
|
||||
use crate::handle::registration_handler::{RegResponse, ReqEnum};
|
||||
use std::io;
|
||||
use std::ops::Deref;
|
||||
use std::time::Duration;
|
||||
use tokio::runtime::Runtime;
|
||||
use crate::core::{Config, Vnt, VntUtil};
|
||||
use crate::handle::registration_handler::{RegResponse, ReqEnum};
|
||||
|
||||
pub struct VntUtilSync {
|
||||
vnt_util: VntUtil,
|
||||
@@ -17,16 +19,24 @@ pub struct VntSync {
|
||||
|
||||
impl VntUtilSync {
|
||||
pub fn new(config: Config) -> io::Result<VntUtilSync> {
|
||||
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();
|
||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()?;
|
||||
let vnt_util = runtime.block_on(VntUtil::new(config))?;
|
||||
Ok(VntUtilSync {
|
||||
vnt_util,
|
||||
runtime,
|
||||
})
|
||||
Ok(VntUtilSync { vnt_util, runtime })
|
||||
}
|
||||
pub fn connect(&mut self) -> Result<RegResponse, ReqEnum> {
|
||||
pub fn connect(&mut self) -> io::Result<()> {
|
||||
self.runtime.block_on(self.vnt_util.connect())
|
||||
}
|
||||
pub fn handshake(&mut self) -> Result<Option<RsaCipher>, HandshakeEnum> {
|
||||
self.runtime.block_on(self.vnt_util.handshake())
|
||||
}
|
||||
pub fn secret_handshake(&mut self) -> Result<(), HandshakeEnum> {
|
||||
self.runtime.block_on(self.vnt_util.secret_handshake())
|
||||
}
|
||||
pub fn register(&mut self) -> Result<RegResponse, ReqEnum> {
|
||||
self.runtime.block_on(self.vnt_util.register())
|
||||
}
|
||||
#[cfg(any(target_os = "android"))]
|
||||
pub fn create_iface(&mut self, vpn_fd: i32) {
|
||||
self.vnt_util.create_iface(vpn_fd)
|
||||
@@ -40,13 +50,14 @@ impl VntUtilSync {
|
||||
let vnt = runtime.block_on(self.vnt_util.build())?;
|
||||
{
|
||||
let mut vnt = vnt.clone();
|
||||
std::thread::spawn(move || {
|
||||
runtime.block_on(vnt.wait_stop())
|
||||
});
|
||||
std::thread::spawn(move || runtime.block_on(vnt.wait_stop()));
|
||||
}
|
||||
Ok(VntSync {
|
||||
vnt,
|
||||
runtime: tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(),
|
||||
runtime: tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -56,7 +67,8 @@ impl VntSync {
|
||||
self.runtime.block_on(self.vnt.wait_stop())
|
||||
}
|
||||
pub fn wait_stop_ms(&mut self, ms: u64) -> bool {
|
||||
self.runtime.block_on(self.vnt.wait_stop_ms(Duration::from_millis(ms)))
|
||||
self.runtime
|
||||
.block_on(self.vnt.wait_stop_ms(Duration::from_millis(ms)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,4 +78,4 @@ impl Deref for VntSync {
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.vnt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ pub struct ExternalRoute {
|
||||
impl ExternalRoute {
|
||||
pub fn new(route_table: Vec<(u32, u32, Ipv4Addr)>) -> Self {
|
||||
Self {
|
||||
route_table:Arc::new(route_table)
|
||||
route_table: Arc::new(route_table),
|
||||
}
|
||||
}
|
||||
pub fn route(&self, ip: &Ipv4Addr) -> Option<Ipv4Addr> {
|
||||
@@ -23,4 +23,26 @@ impl ExternalRoute {
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AllowExternalRoute {
|
||||
route_table: Arc<Vec<(u32, u32)>>,
|
||||
}
|
||||
|
||||
impl AllowExternalRoute {
|
||||
pub fn new(route_table: Vec<(u32, u32)>) -> Self {
|
||||
Self {
|
||||
route_table: Arc::new(route_table),
|
||||
}
|
||||
}
|
||||
pub fn allow(&self, ip: &Ipv4Addr) -> bool {
|
||||
let ip = u32::from_be_bytes(ip.octets());
|
||||
for (dest, mask) in self.route_table.iter() {
|
||||
if *mask & ip == *mask & *dest {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use protobuf::Message;
|
||||
use std::net::UdpSocket;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
|
||||
use crate::channel::channel::Context;
|
||||
use crate::channel::RouteKey;
|
||||
use crate::cipher::{Cipher, RsaCipher};
|
||||
use crate::proto::message::{HandshakeRequest, HandshakeResponse, SecretHandshakeRequest};
|
||||
use crate::protocol::body::RSA_ENCRYPTION_RESERVED;
|
||||
use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL};
|
||||
|
||||
pub enum HandshakeEnum {
|
||||
NotSecret,
|
||||
KeyError,
|
||||
Timeout,
|
||||
ServerError(String),
|
||||
Other(String),
|
||||
}
|
||||
|
||||
fn handshake_request_packet(secret: bool) -> crate::Result<NetPacket<Vec<u8>>> {
|
||||
let mut request = HandshakeRequest::new();
|
||||
request.secret = secret;
|
||||
request.version = crate::VNT_VERSION.to_string();
|
||||
let bytes = request.write_to_bytes()?;
|
||||
let buf = vec![0u8; 12 + bytes.len()];
|
||||
let mut net_packet = NetPacket::new(buf)?;
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_gateway_flag(true);
|
||||
net_packet.set_protocol(Protocol::Service);
|
||||
net_packet.set_transport_protocol(service_packet::Protocol::HandshakeRequest.into());
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
net_packet.set_payload(&bytes)?;
|
||||
Ok(net_packet)
|
||||
}
|
||||
|
||||
fn secret_handshake_request_packet(
|
||||
rsa_cipher: &RsaCipher,
|
||||
token: String,
|
||||
key: &[u8],
|
||||
) -> crate::Result<NetPacket<Vec<u8>>> {
|
||||
let mut request = SecretHandshakeRequest::new();
|
||||
request.token = token;
|
||||
request.key = key.to_vec();
|
||||
let bytes = request.write_to_bytes()?;
|
||||
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_gateway_flag(true);
|
||||
net_packet.set_protocol(Protocol::Service);
|
||||
net_packet.set_transport_protocol(service_packet::Protocol::SecretHandshakeRequest.into());
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
net_packet.set_payload(&bytes)?;
|
||||
Ok(rsa_cipher.encrypt(&mut net_packet)?)
|
||||
}
|
||||
|
||||
/// 第一次握手,拿到公钥
|
||||
pub async fn handshake(
|
||||
main_channel: &UdpSocket,
|
||||
main_tcp_channel: Option<&mut TcpStream>,
|
||||
server_address: SocketAddr,
|
||||
secret: bool,
|
||||
) -> Result<Option<RsaCipher>, HandshakeEnum> {
|
||||
let request_packet = handshake_request_packet(secret).unwrap();
|
||||
let send_buf = request_packet.buffer();
|
||||
let mut recv_buf = [0u8; 10240];
|
||||
let len = send_recv(
|
||||
main_channel,
|
||||
main_tcp_channel,
|
||||
server_address,
|
||||
send_buf,
|
||||
&mut recv_buf,
|
||||
)
|
||||
.await?;
|
||||
let net_packet = match NetPacket::new(&recv_buf[..len]) {
|
||||
Ok(net_packet) => net_packet,
|
||||
Err(e) => {
|
||||
return Err(HandshakeEnum::Other(format!("net_packet {}", e)));
|
||||
}
|
||||
};
|
||||
match net_packet.protocol() {
|
||||
Protocol::Service => {
|
||||
match service_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||
service_packet::Protocol::HandshakeResponse => {
|
||||
match HandshakeResponse::parse_from_bytes(net_packet.payload()) {
|
||||
Ok(response) => {
|
||||
if !response.secret && secret {
|
||||
//客户端要加密,服务端不支持加密
|
||||
return Err(HandshakeEnum::NotSecret);
|
||||
}
|
||||
if secret {
|
||||
//转换公钥
|
||||
match RsaCipher::new(&response.public_key) {
|
||||
Ok(rsa) => {
|
||||
match rsa.finger() {
|
||||
Ok(finger) => {
|
||||
if finger != response.key_finger {
|
||||
return Err(HandshakeEnum::Other(
|
||||
"finger error".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(HandshakeEnum::Other(format!(
|
||||
"finger {}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
Ok(Some(rsa))
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(HandshakeEnum::Other(format!(
|
||||
"RsaCipher {}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(HandshakeEnum::Other(format!("parse_from_bytes {}", e)));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(HandshakeEnum::Other("not match".to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(HandshakeEnum::Other("not match".to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn send_recv(
|
||||
main_channel: &UdpSocket,
|
||||
main_tcp_channel: Option<&mut TcpStream>,
|
||||
server_address: SocketAddr,
|
||||
send_buf: &[u8],
|
||||
recv_buf: &mut [u8],
|
||||
) -> Result<usize, HandshakeEnum> {
|
||||
if let Some(main_tcp_channel) = main_tcp_channel {
|
||||
let mut head = [0; 4];
|
||||
let len = send_buf.len();
|
||||
head[2] = (len >> 8) as u8;
|
||||
head[3] = (len & 0xFF) as u8;
|
||||
if let Err(e) = main_tcp_channel.write_all(&head).await {
|
||||
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
|
||||
}
|
||||
if let Err(e) = main_tcp_channel.write_all(send_buf).await {
|
||||
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
|
||||
}
|
||||
if let Err(e) = main_tcp_channel.read_exact(&mut head).await {
|
||||
return Err(HandshakeEnum::Other(format!("read error:{}", e)));
|
||||
}
|
||||
let len = (((head[2] as u16) << 8) | head[3] as u16) as usize;
|
||||
if len > recv_buf.len() {
|
||||
return Err(HandshakeEnum::Other("too long".to_string()));
|
||||
}
|
||||
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[..len]).await {
|
||||
return Err(HandshakeEnum::Other(format!("read error:{}", e)));
|
||||
}
|
||||
Ok(len)
|
||||
} else {
|
||||
if let Err(e) = main_channel.send_to(send_buf, server_address) {
|
||||
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
|
||||
}
|
||||
match main_channel.recv_from(recv_buf) {
|
||||
Ok((len, addr)) => {
|
||||
if server_address != addr {
|
||||
Err(HandshakeEnum::Other(format!("invalid data,from {}", addr)))
|
||||
} else {
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
Err(e) => Err(HandshakeEnum::Other(format!("receiver error:{}", e))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 第二次握手,同步对称密钥,后续将使用对称加密
|
||||
pub async fn secret_handshake(
|
||||
main_channel: &UdpSocket,
|
||||
main_tcp_channel: Option<&mut TcpStream>,
|
||||
server_address: SocketAddr,
|
||||
rsa_cipher: &RsaCipher,
|
||||
server_cipher: &Cipher,
|
||||
token: String,
|
||||
) -> Result<(), HandshakeEnum> {
|
||||
let secret_packet =
|
||||
match secret_handshake_request_packet(rsa_cipher, token, server_cipher.key().unwrap()) {
|
||||
Ok(secret_packet) => secret_packet,
|
||||
Err(e) => {
|
||||
return Err(HandshakeEnum::Other(format!(
|
||||
"secret_handshake_request_packet {}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
};
|
||||
let send_buf = secret_packet.buffer();
|
||||
let mut recv_buf = [0u8; 10240];
|
||||
let len = send_recv(
|
||||
main_channel,
|
||||
main_tcp_channel,
|
||||
server_address,
|
||||
send_buf,
|
||||
&mut recv_buf,
|
||||
)
|
||||
.await?;
|
||||
let mut net_packet = match NetPacket::new(&mut recv_buf[..len]) {
|
||||
Ok(net_packet) => net_packet,
|
||||
Err(e) => {
|
||||
return Err(HandshakeEnum::Other(format!("secret_net_packet {}", e)));
|
||||
}
|
||||
};
|
||||
match server_cipher.decrypt_ipv4(&mut net_packet) {
|
||||
Ok(_) => {
|
||||
if net_packet.is_gateway()
|
||||
&& net_packet.protocol() == Protocol::Service
|
||||
&& service_packet::Protocol::from(net_packet.transport_protocol())
|
||||
== service_packet::Protocol::SecretHandshakeResponse
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
Err(HandshakeEnum::Other("not match".to_string()))
|
||||
}
|
||||
}
|
||||
Err(e) => Err(HandshakeEnum::Other(format!("decrypt_ipv4 {}", e))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn secret_handshake_req(
|
||||
context: &Context,
|
||||
server_address: SocketAddr,
|
||||
rsa_cipher: &RsaCipher,
|
||||
server_cipher: &Cipher,
|
||||
token: String,
|
||||
route_key: &RouteKey,
|
||||
) -> crate::Result<()> {
|
||||
let secret_packet =
|
||||
secret_handshake_request_packet(rsa_cipher, token, server_cipher.key().unwrap())?;
|
||||
if route_key.is_tcp() {
|
||||
context.send_main(secret_packet.buffer(), server_address)?;
|
||||
} else {
|
||||
context.send_main_udp(secret_packet.buffer(), server_address)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,20 +1,21 @@
|
||||
use std::io;
|
||||
use std::net::{Ipv4Addr, ToSocketAddrs};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use std::io;
|
||||
|
||||
use crate::channel::idle::Idle;
|
||||
use crate::channel::sender::ChannelSender;
|
||||
use crate::channel::Route;
|
||||
use crate::cipher::Cipher;
|
||||
use crate::core::status::VntWorker;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use parking_lot::Mutex;
|
||||
use rand::prelude::SliceRandom;
|
||||
use crate::channel::idle::Idle;
|
||||
use crate::channel::Route;
|
||||
use crate::channel::sender::ChannelSender;
|
||||
use crate::core::status::VntWorker;
|
||||
|
||||
|
||||
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
|
||||
use crate::protocol::body::ENCRYPTION_RESERVED;
|
||||
use crate::protocol::control_packet::PingPacket;
|
||||
use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, Version};
|
||||
use crate::protocol::{control_packet, NetPacket, Protocol, Version, MAX_TTL};
|
||||
|
||||
pub fn start_idle(mut worker: VntWorker, idle: Idle, sender: ChannelSender) {
|
||||
tokio::spawn(async move {
|
||||
@@ -33,13 +34,10 @@ pub fn start_idle(mut worker: VntWorker, idle: Idle, sender: ChannelSender) {
|
||||
}
|
||||
|
||||
async fn start_idle_(idle: Idle, sender: ChannelSender) -> io::Result<()> {
|
||||
log::info!("启动空闲检查任务");
|
||||
loop {
|
||||
let (peer_ip, route) = idle.next_idle().await?;
|
||||
log::info!(
|
||||
"peer_ip:{:?},route:{:?}",
|
||||
peer_ip,
|
||||
route
|
||||
);
|
||||
log::info!("路由空闲 peer_ip:{:?},route:{:?}", peer_ip, route);
|
||||
sender.remove_route(&peer_ip, route);
|
||||
}
|
||||
}
|
||||
@@ -50,13 +48,15 @@ pub fn start_heartbeat(
|
||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
server_address_str: String,
|
||||
client_cipher: Cipher,
|
||||
server_cipher: Cipher,
|
||||
) {
|
||||
tokio::spawn(async move {
|
||||
tokio::select! {
|
||||
_=worker.stop_wait()=>{
|
||||
return;
|
||||
}
|
||||
rs=start_heartbeat_(sender, device_list, current_device,server_address_str)=>{
|
||||
rs=start_heartbeat_(sender, device_list, current_device,server_address_str,client_cipher,server_cipher)=>{
|
||||
if let Err(e) = rs {
|
||||
log::warn!("心跳任务停止:{:?}", e);
|
||||
}
|
||||
@@ -66,11 +66,35 @@ pub fn start_heartbeat(
|
||||
});
|
||||
}
|
||||
|
||||
fn set_now_time(packet: &mut NetPacket<[u8; 16]>) -> io::Result<()> {
|
||||
let current_time = crate::handle::now_time() as u16;
|
||||
let mut ping = PingPacket::new(packet.payload_mut())?;
|
||||
ping.set_time(current_time);
|
||||
Ok(())
|
||||
fn heartbeat_packet(
|
||||
ttl: u8,
|
||||
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
|
||||
client_cipher: &Cipher,
|
||||
server_cipher: &Cipher,
|
||||
gateway: bool,
|
||||
src: Ipv4Addr,
|
||||
dest: Ipv4Addr,
|
||||
) -> NetPacket<[u8; 12 + 4 + ENCRYPTION_RESERVED]> {
|
||||
let mut net_packet = NetPacket::new_encrypt([0u8; 12 + 4 + ENCRYPTION_RESERVED]).unwrap();
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_protocol(Protocol::Control);
|
||||
net_packet.set_transport_protocol(control_packet::Protocol::Ping.into());
|
||||
net_packet.first_set_ttl(ttl);
|
||||
net_packet.set_source(src);
|
||||
net_packet.set_destination(dest);
|
||||
{
|
||||
let mut ping = PingPacket::new(net_packet.payload_mut()).unwrap();
|
||||
let epoch = { device_list.lock().0 };
|
||||
ping.set_epoch(epoch);
|
||||
ping.set_time(crate::handle::now_time() as u16);
|
||||
}
|
||||
if gateway {
|
||||
net_packet.set_gateway_flag(true);
|
||||
server_cipher.encrypt_ipv4(&mut net_packet).unwrap();
|
||||
} else {
|
||||
client_cipher.encrypt_ipv4(&mut net_packet).unwrap();
|
||||
}
|
||||
net_packet
|
||||
}
|
||||
|
||||
async fn start_heartbeat_(
|
||||
@@ -78,30 +102,28 @@ async fn start_heartbeat_(
|
||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
server_address_str: String,
|
||||
client_cipher: Cipher,
|
||||
server_cipher: Cipher,
|
||||
) -> io::Result<()> {
|
||||
let mut net_packet = NetPacket::new([0u8; 16])?;
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_protocol(Protocol::Control);
|
||||
net_packet.set_transport_protocol(control_packet::Protocol::Ping.into());
|
||||
//只寻找两跳以内能到的目标
|
||||
net_packet.first_set_ttl(2);
|
||||
let mut count = 0;
|
||||
log::info!("启动心跳任务");
|
||||
loop {
|
||||
if sender.is_close() {
|
||||
return Ok(());
|
||||
}
|
||||
let mut current_dev = current_device.load();
|
||||
if count % 10 == 0 {
|
||||
let mut packet = NetPacket::new([0; 12])?;
|
||||
//如果和服务端使用tcp连接,则维持udp洞的频率要更高些
|
||||
if (sender.is_main_tcp() && count % 2 == 0) || (!sender.is_main_tcp() && count % 20 == 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.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);
|
||||
let _ = sender.send_main_udp(packet.buffer(), current_dev.connect_server).await;
|
||||
server_cipher.encrypt_ipv4(&mut packet)?;
|
||||
let _ = sender.send_main_udp(packet.buffer(), current_dev.connect_server);
|
||||
}
|
||||
if count % 20 == 19 {
|
||||
if let Ok(mut addr) = server_address_str.to_socket_addrs() {
|
||||
@@ -109,6 +131,11 @@ async fn start_heartbeat_(
|
||||
if addr != current_dev.connect_server {
|
||||
let mut tmp = current_dev.clone();
|
||||
tmp.connect_server = addr;
|
||||
log::info!(
|
||||
"服务端地址变化,旧地址:{},新地址:{}",
|
||||
current_dev.connect_server,
|
||||
addr
|
||||
);
|
||||
if current_device.compare_exchange(current_dev, tmp).is_ok() {
|
||||
current_dev.connect_server = addr;
|
||||
}
|
||||
@@ -116,21 +143,18 @@ async fn start_heartbeat_(
|
||||
}
|
||||
}
|
||||
}
|
||||
net_packet.set_source(current_dev.virtual_ip());
|
||||
{
|
||||
let mut ping = PingPacket::new(net_packet.payload_mut())?;
|
||||
let epoch = { device_list.lock().0 };
|
||||
ping.set_epoch(epoch);
|
||||
}
|
||||
set_now_time(&mut net_packet)?;
|
||||
net_packet.set_destination(current_dev.virtual_gateway());
|
||||
if let Err(e) = sender.send_main(net_packet.buffer(), current_dev.connect_server).await
|
||||
{
|
||||
log::warn!(
|
||||
"connect_server:{:?},e:{:?}",
|
||||
current_dev.connect_server,
|
||||
e
|
||||
);
|
||||
let src = current_dev.virtual_ip();
|
||||
let server_packet = heartbeat_packet(
|
||||
MAX_TTL,
|
||||
&device_list,
|
||||
&client_cipher,
|
||||
&server_cipher,
|
||||
true,
|
||||
src,
|
||||
current_dev.virtual_gateway,
|
||||
);
|
||||
if let Err(e) = sender.send_main(server_packet.buffer(), current_dev.connect_server) {
|
||||
log::warn!("connect_server:{:?},e:{:?}", current_dev.connect_server, e);
|
||||
}
|
||||
if count < 7 || count % 7 == 0 {
|
||||
let mut route_list: Option<Vec<(Ipv4Addr, Vec<Route>)>> = None;
|
||||
@@ -139,17 +163,36 @@ async fn start_heartbeat_(
|
||||
if peer.virtual_ip == current_dev.virtual_ip {
|
||||
continue;
|
||||
}
|
||||
set_now_time(&mut net_packet)?;
|
||||
net_packet.set_destination(peer.virtual_ip);
|
||||
let client_packet = heartbeat_packet(
|
||||
MAX_TTL,
|
||||
&device_list,
|
||||
&client_cipher,
|
||||
&server_cipher,
|
||||
false,
|
||||
src,
|
||||
peer.virtual_ip,
|
||||
);
|
||||
if let Some(route) = sender.route_one(&peer.virtual_ip) {
|
||||
let _ = sender.send_by_key(net_packet.buffer(), &route.route_key()).await;
|
||||
if let Err(e) =
|
||||
sender.try_send_by_key(client_packet.buffer(), &route.route_key())
|
||||
{
|
||||
log::warn!("virtual_ip:{},route:{:?},e:{:?}", peer.virtual_ip, route, e);
|
||||
}
|
||||
if route.is_p2p() {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
//没有直连路由则发送到网关
|
||||
let _ = sender.send_main(net_packet.buffer(), current_dev.connect_server).await;
|
||||
continue;
|
||||
if let Err(e) =
|
||||
sender.send_main(client_packet.buffer(), current_dev.connect_server)
|
||||
{
|
||||
log::warn!(
|
||||
"virtual_ip:{},connect_server:{:?},e:{:?}",
|
||||
peer.virtual_ip,
|
||||
current_dev.connect_server,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//再随机发送到其他地址,看有没有客户端符合转发条件
|
||||
@@ -162,12 +205,20 @@ async fn start_heartbeat_(
|
||||
'a: for (peer_ip, route_list) in route_list.iter() {
|
||||
for route in route_list {
|
||||
if peer_ip != &peer.virtual_ip && route.is_p2p() {
|
||||
set_now_time(&mut net_packet)?;
|
||||
let _ = sender.try_send_by_key(net_packet.buffer(), &route.route_key());
|
||||
if let Err(e) =
|
||||
sender.try_send_by_key(client_packet.buffer(), &route.route_key())
|
||||
{
|
||||
log::warn!(
|
||||
"virtual_ip:{},route:{:?},e:{:?}",
|
||||
peer.virtual_ip,
|
||||
route,
|
||||
e
|
||||
);
|
||||
}
|
||||
num += 1;
|
||||
break;
|
||||
}
|
||||
if num >= 3 {
|
||||
if num >= 2 {
|
||||
break 'a;
|
||||
}
|
||||
}
|
||||
@@ -176,10 +227,22 @@ async fn start_heartbeat_(
|
||||
}
|
||||
} else {
|
||||
for (peer_ip, route_list) in sender.route_table().iter() {
|
||||
net_packet.set_destination(*peer_ip);
|
||||
if peer_ip == ¤t_dev.virtual_gateway {
|
||||
continue;
|
||||
}
|
||||
let client_packet = heartbeat_packet(
|
||||
MAX_TTL,
|
||||
&device_list,
|
||||
&client_cipher,
|
||||
&server_cipher,
|
||||
false,
|
||||
src,
|
||||
*peer_ip,
|
||||
);
|
||||
for route in route_list {
|
||||
set_now_time(&mut net_packet)?;
|
||||
if let Err(e) = sender.send_by_key(net_packet.buffer(), &route.route_key()).await {
|
||||
if let Err(e) =
|
||||
sender.try_send_by_key(client_packet.buffer(), &route.route_key())
|
||||
{
|
||||
log::warn!("peer_ip:{:?},route:{:?},e:{:?}", peer_ip, route, e);
|
||||
}
|
||||
tokio::time::sleep(Duration::from_millis(2)).await;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
|
||||
pub mod handshake_handler;
|
||||
pub mod heartbeat_handler;
|
||||
pub mod punch_handler;
|
||||
pub mod recv_handler;
|
||||
@@ -26,19 +27,21 @@ pub struct PeerDeviceInfo {
|
||||
pub virtual_ip: Ipv4Addr,
|
||||
pub name: String,
|
||||
pub status: PeerDeviceStatus,
|
||||
pub client_secret: bool,
|
||||
}
|
||||
|
||||
impl PeerDeviceInfo {
|
||||
pub fn new(virtual_ip: Ipv4Addr, name: String, status: u8) -> Self {
|
||||
pub fn new(virtual_ip: Ipv4Addr, name: String, status: u8, client_secret: bool) -> Self {
|
||||
Self {
|
||||
virtual_ip,
|
||||
name,
|
||||
status: PeerDeviceStatus::from(status),
|
||||
client_secret,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq,Ord, PartialOrd)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum PeerDeviceStatus {
|
||||
Online,
|
||||
Offline,
|
||||
@@ -79,7 +82,6 @@ pub struct CurrentDeviceInfo {
|
||||
pub broadcast_address: Ipv4Addr,
|
||||
//链接的服务器地址
|
||||
pub connect_server: SocketAddr,
|
||||
|
||||
}
|
||||
|
||||
impl CurrentDeviceInfo {
|
||||
|
||||
@@ -1,24 +1,32 @@
|
||||
use crate::channel::punch::{NatInfo, Punch};
|
||||
use crate::channel::sender::ChannelSender;
|
||||
use crate::cipher::Cipher;
|
||||
use crate::core::status::VntWorker;
|
||||
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
|
||||
use crate::nat::NatTest;
|
||||
use crate::proto::message::{PunchInfo, PunchNatType};
|
||||
use crate::protocol::body::ENCRYPTION_RESERVED;
|
||||
use crate::protocol::{control_packet, other_turn_packet, NetPacket, Protocol, Version, MAX_TTL};
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use parking_lot::Mutex;
|
||||
use protobuf::Message;
|
||||
use rand::prelude::SliceRandom;
|
||||
use std::io;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use std::io;
|
||||
use tokio::sync::mpsc::Receiver;
|
||||
use crate::channel::punch::{NatInfo, Punch};
|
||||
use crate::channel::sender::ChannelSender;
|
||||
use crate::core::status::VntWorker;
|
||||
|
||||
pub fn start(mut worker: VntWorker, receiver: Receiver<(Ipv4Addr, NatInfo)>, punch: Punch, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
|
||||
pub fn start(
|
||||
mut worker: VntWorker,
|
||||
receiver: Receiver<(Ipv4Addr, NatInfo)>,
|
||||
punch: Punch,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
client_cipher: Cipher,
|
||||
) {
|
||||
tokio::spawn(async move {
|
||||
tokio::select! {
|
||||
_=start0(receiver, punch, current_device)=>{}
|
||||
_=start0(receiver, punch, current_device,client_cipher)=>{}
|
||||
_=worker.stop_wait()=>{
|
||||
return;
|
||||
}
|
||||
@@ -27,21 +35,36 @@ pub fn start(mut worker: VntWorker, receiver: Receiver<(Ipv4Addr, NatInfo)>, pun
|
||||
});
|
||||
}
|
||||
|
||||
pub async fn start0(mut receiver: Receiver<(Ipv4Addr, NatInfo)>, mut punch: Punch, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
|
||||
pub async fn start0(
|
||||
mut receiver: Receiver<(Ipv4Addr, NatInfo)>,
|
||||
mut punch: Punch,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
client_cipher: Cipher,
|
||||
) {
|
||||
log::info!("启动打洞任务");
|
||||
while let Some((peer_ip, nat_info)) = receiver.recv().await {
|
||||
if let Err(e) = start_(&mut punch, ¤t_device, peer_ip, nat_info).await {
|
||||
if let Err(e) = start_(
|
||||
&client_cipher,
|
||||
&mut punch,
|
||||
¤t_device,
|
||||
peer_ip,
|
||||
nat_info,
|
||||
)
|
||||
.await
|
||||
{
|
||||
log::warn!("网络打洞异常 {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn start_(
|
||||
client_cipher: &Cipher,
|
||||
punch: &mut Punch,
|
||||
current_device: &Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
peer_ip: Ipv4Addr,
|
||||
nat_info: NatInfo,
|
||||
) -> io::Result<()> {
|
||||
let mut packet = NetPacket::new([0u8; 12])?;
|
||||
let mut packet = NetPacket::new_encrypt([0u8; 12 + ENCRYPTION_RESERVED])?;
|
||||
packet.set_version(Version::V1);
|
||||
packet.first_set_ttl(1);
|
||||
packet.set_protocol(Protocol::Control);
|
||||
@@ -49,7 +72,7 @@ async fn start_(
|
||||
packet.set_source(current_device.load().virtual_ip());
|
||||
packet.set_destination(peer_ip);
|
||||
log::info!("发起打洞,目标:{:?},{:?}", peer_ip, nat_info);
|
||||
|
||||
client_cipher.encrypt_ipv4(&mut packet)?;
|
||||
punch.punch(packet.buffer(), peer_ip, nat_info).await
|
||||
}
|
||||
|
||||
@@ -59,15 +82,18 @@ pub async fn start_punch(
|
||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||
sender: ChannelSender,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
client_cipher: Cipher,
|
||||
) {
|
||||
let mut num = 0;
|
||||
let sleep_time = [3, 5, 7, 11, 13, 17, 19, 23, 29];
|
||||
log::info!("启动发起打洞请求任务");
|
||||
loop {
|
||||
if sender.is_close() {
|
||||
break;
|
||||
}
|
||||
tokio::select! {
|
||||
rs= start_punch_(Duration::from_secs(sleep_time[num % sleep_time.len()]),&nat_test, &device_list, &sender, ¤t_device)=>{
|
||||
rs= start_punch_(Duration::from_secs(sleep_time[num % sleep_time.len()]),&nat_test, &device_list,
|
||||
&sender, ¤t_device,&client_cipher)=>{
|
||||
if let Err(e) = rs {
|
||||
log::warn!("打洞处理任务异常 {:?}", e);
|
||||
}
|
||||
@@ -86,6 +112,7 @@ async fn start_punch_(
|
||||
device_list: &Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||
sender: &ChannelSender,
|
||||
current_device: &Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
client_cipher: &Cipher,
|
||||
) -> crate::Result<()> {
|
||||
let current_device = current_device.load();
|
||||
let nat_info = nat_test.nat_info();
|
||||
@@ -103,18 +130,25 @@ async fn start_punch_(
|
||||
if count > 2 {
|
||||
break;
|
||||
}
|
||||
let buf = punch_packet(current_device.virtual_ip(), &nat_info, info.virtual_ip)?;
|
||||
let _ = sender.send_main(&buf, current_device.connect_server).await;
|
||||
let packet = punch_packet(
|
||||
client_cipher,
|
||||
current_device.virtual_ip(),
|
||||
&nat_info,
|
||||
info.virtual_ip,
|
||||
)
|
||||
.unwrap();
|
||||
let _ = sender.send_main(packet.buffer(), current_device.connect_server);
|
||||
}
|
||||
tokio::time::sleep(sleep_time).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn punch_packet(
|
||||
client_cipher: &Cipher,
|
||||
virtual_ip: Ipv4Addr,
|
||||
nat_info: &NatInfo,
|
||||
dest: Ipv4Addr,
|
||||
) -> crate::Result<Vec<u8>> {
|
||||
) -> crate::Result<NetPacket<Vec<u8>>> {
|
||||
let mut punch_reply = PunchInfo::new();
|
||||
punch_reply.reply = false;
|
||||
punch_reply.public_ip_list = nat_info
|
||||
@@ -124,17 +158,22 @@ pub fn punch_packet(
|
||||
.collect();
|
||||
punch_reply.public_port = nat_info.public_port as u32;
|
||||
punch_reply.public_port_range = nat_info.public_port_range as u32;
|
||||
punch_reply.local_ip = u32::from_be_bytes(nat_info.local_ip.octets());
|
||||
punch_reply.local_port = nat_info.local_port as u32;
|
||||
punch_reply.local_ip = u32::from_be_bytes(nat_info.local_ipv4_addr.ip().octets());
|
||||
punch_reply.local_port = nat_info.local_ipv4_addr.port() as u32;
|
||||
if !nat_info.ipv6_addr.ip().is_unspecified() {
|
||||
punch_reply.ipv6_port = nat_info.ipv6_addr.port() as u32;
|
||||
punch_reply.ipv6 = nat_info.ipv6_addr.ip().octets().to_vec();
|
||||
}
|
||||
punch_reply.nat_type = protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type));
|
||||
let bytes = punch_reply.write_to_bytes()?;
|
||||
let mut net_packet = NetPacket::new(vec![0u8; 12 + bytes.len()])?;
|
||||
let mut net_packet = NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?;
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_protocol(Protocol::OtherTurn);
|
||||
net_packet.set_transport_protocol(other_turn_packet::Protocol::Punch.into());
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
net_packet.set_source(virtual_ip);
|
||||
net_packet.set_destination(dest);
|
||||
net_packet.set_payload(&bytes);
|
||||
Ok(net_packet.into_buffer())
|
||||
net_packet.set_payload(&bytes)?;
|
||||
client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||
Ok(net_packet)
|
||||
}
|
||||
|
||||
+541
-276
@@ -1,33 +1,37 @@
|
||||
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use dashmap::DashMap;
|
||||
use parking_lot::Mutex;
|
||||
use protobuf::Message;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
||||
use packet::icmp::{icmp, Kind};
|
||||
use packet::icmp::icmp::HeaderOther;
|
||||
use packet::ip::ipv4;
|
||||
use packet::ip::ipv4::packet::IpV4Packet;
|
||||
|
||||
use crate::channel::channel::Context;
|
||||
use crate::channel::punch::{NatInfo, NatType};
|
||||
use crate::channel::{Route, RouteKey};
|
||||
use crate::cipher::Cipher;
|
||||
|
||||
use crate::cipher::{Cipher, RsaCipher};
|
||||
use crate::error::Error;
|
||||
use crate::external_route::ExternalRoute;
|
||||
use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo, PeerDeviceStatus};
|
||||
use crate::external_route::AllowExternalRoute;
|
||||
use crate::handle::handshake_handler::secret_handshake_req;
|
||||
use crate::handle::registration_handler::Register;
|
||||
use crate::handle::{ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo, PeerDeviceStatus};
|
||||
use crate::igmp_server::IgmpServer;
|
||||
use crate::ip_proxy::IpProxyMap;
|
||||
use crate::nat;
|
||||
use crate::nat::NatTest;
|
||||
use crate::proto::message::{DeviceList, PunchInfo, PunchNatType, RegistrationResponse};
|
||||
use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, service_packet, other_turn_packet, Version, ip_turn_packet};
|
||||
use crate::protocol::body::ENCRYPTION_RESERVED;
|
||||
use crate::protocol::control_packet::ControlPacket;
|
||||
use crate::protocol::error_packet::InErrorPacket;
|
||||
use crate::protocol::{
|
||||
control_packet, ip_turn_packet, other_turn_packet, service_packet, NetPacket, Protocol,
|
||||
Version, MAX_TTL,
|
||||
};
|
||||
use crate::tun_tap_device::DeviceWriter;
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -39,30 +43,38 @@ pub struct ChannelDataHandler {
|
||||
igmp_server: Option<IgmpServer>,
|
||||
device_writer: DeviceWriter,
|
||||
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
||||
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
|
||||
peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>>,
|
||||
ip_proxy_map: Option<IpProxyMap>,
|
||||
out_external_route: ExternalRoute,
|
||||
out_external_route: AllowExternalRoute,
|
||||
cone_sender: Sender<(Ipv4Addr, NatInfo)>,
|
||||
symmetric_sender: Sender<(Ipv4Addr, NatInfo)>,
|
||||
cipher: Cipher,
|
||||
client_cipher: Cipher,
|
||||
server_cipher: Cipher,
|
||||
rsa_cipher: Option<RsaCipher>,
|
||||
relay: bool,
|
||||
token: String,
|
||||
}
|
||||
|
||||
impl ChannelDataHandler {
|
||||
pub fn new(current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||
register: Arc<Register>,
|
||||
nat_test: NatTest,
|
||||
igmp_server: Option<IgmpServer>,
|
||||
device_writer: DeviceWriter,
|
||||
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
||||
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
|
||||
ip_proxy_map: Option<IpProxyMap>,
|
||||
out_external_route: ExternalRoute,
|
||||
cone_sender: Sender<(Ipv4Addr, NatInfo)>,
|
||||
symmetric_sender: Sender<(Ipv4Addr, NatInfo)>,
|
||||
cipher: Cipher,
|
||||
relay: bool, ) -> Self {
|
||||
pub fn new(
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||
register: Arc<Register>,
|
||||
nat_test: NatTest,
|
||||
igmp_server: Option<IgmpServer>,
|
||||
device_writer: DeviceWriter,
|
||||
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
||||
peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>>,
|
||||
ip_proxy_map: Option<IpProxyMap>,
|
||||
out_external_route: AllowExternalRoute,
|
||||
cone_sender: Sender<(Ipv4Addr, NatInfo)>,
|
||||
symmetric_sender: Sender<(Ipv4Addr, NatInfo)>,
|
||||
client_cipher: Cipher,
|
||||
server_cipher: Cipher,
|
||||
rsa_cipher: Option<RsaCipher>,
|
||||
relay: bool,
|
||||
token: String,
|
||||
) -> Self {
|
||||
Self {
|
||||
current_device,
|
||||
device_list,
|
||||
@@ -76,85 +88,102 @@ impl ChannelDataHandler {
|
||||
out_external_route,
|
||||
cone_sender,
|
||||
symmetric_sender,
|
||||
cipher,
|
||||
client_cipher,
|
||||
server_cipher,
|
||||
rsa_cipher,
|
||||
relay,
|
||||
token,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl ChannelDataHandler {
|
||||
pub async fn handle(&mut self, buf: &mut [u8], start: usize, end: usize, route_key: RouteKey, context: &Context) {
|
||||
pub async fn handle(
|
||||
&self,
|
||||
buf: &mut [u8],
|
||||
start: usize,
|
||||
end: usize,
|
||||
route_key: RouteKey,
|
||||
context: &Context,
|
||||
) {
|
||||
assert_eq!(start, 14);
|
||||
match self.handle0(&mut buf[..end], &route_key, context).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::error!("{:?}",e);
|
||||
log::warn!("{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
async fn handle0(&self, buf: &mut [u8], route_key: &RouteKey, context: &Context) -> crate::Result<()> {
|
||||
async fn handle0(
|
||||
&self,
|
||||
buf: &mut [u8],
|
||||
route_key: &RouteKey,
|
||||
context: &Context,
|
||||
) -> crate::Result<()> {
|
||||
let mut net_packet = NetPacket::new(&mut buf[14..])?;
|
||||
if net_packet.ttl() == 0 {
|
||||
if net_packet.ttl() == 0 || net_packet.source_ttl() < net_packet.ttl() {
|
||||
return Ok(());
|
||||
}
|
||||
let source = net_packet.source();
|
||||
context.update_read_time(&source, route_key);
|
||||
let current_device = self.current_device.load();
|
||||
let destination = net_packet.destination();
|
||||
let not_broadcast = !destination.is_broadcast() && !destination.is_multicast() && destination != current_device.broadcast_address;
|
||||
let not_broadcast = !destination.is_broadcast()
|
||||
&& !destination.is_multicast()
|
||||
&& destination != current_device.broadcast_address;
|
||||
if current_device.virtual_ip() != destination
|
||||
&& not_broadcast && !destination.is_unspecified()
|
||||
&& self.connect_status.load() == ConnectStatus::Connected {
|
||||
if !check_dest(source, current_device.virtual_netmask, current_device.virtual_network) {
|
||||
log::warn!("转发数据,源地址错误:{:?},当前网络:{:?},route_key:{:?}",source,current_device.virtual_network,route_key);
|
||||
return Ok(());
|
||||
}
|
||||
if !check_dest(destination, current_device.virtual_netmask, current_device.virtual_network) {
|
||||
log::warn!("转发数据,目的地址错误:{:?},当前网络:{:?},route_key:{:?}",destination,current_device.virtual_network,route_key);
|
||||
return Ok(());
|
||||
}
|
||||
&& not_broadcast
|
||||
&& !destination.is_unspecified()
|
||||
{
|
||||
//校验指纹,不需要解密
|
||||
self.client_cipher.check_finger(&net_packet)?;
|
||||
net_packet.set_ttl(net_packet.ttl() - 1);
|
||||
let ttl = net_packet.ttl();
|
||||
if ttl > 0 {
|
||||
// 转发
|
||||
if let Some(route) = context.route_one(&destination) {
|
||||
if route.metric <= net_packet.ttl() {
|
||||
context.send_by_key(net_packet.buffer(), &route.route_key()).await?;
|
||||
context.try_send_by_key(net_packet.buffer(), &route.route_key())?;
|
||||
}
|
||||
} else if (ttl > 1 || destination == current_device.virtual_gateway())
|
||||
&& source != current_device.virtual_gateway() {
|
||||
&& source != current_device.virtual_gateway()
|
||||
{
|
||||
//网关默认要转发一次,生存时间不够的发到网关也会被丢弃
|
||||
context.send_main(net_packet.buffer(), current_device.connect_server).await?;
|
||||
context.send_main(net_packet.buffer(), current_device.connect_server)?;
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
if net_packet.is_gateway() {
|
||||
if net_packet.protocol() == Protocol::Error
|
||||
&& net_packet.transport_protocol()
|
||||
== crate::protocol::error_packet::Protocol::NoKey.into()
|
||||
{
|
||||
if let Some(rsa_cipher) = &self.rsa_cipher {
|
||||
secret_handshake_req(
|
||||
context,
|
||||
current_device.connect_server,
|
||||
rsa_cipher,
|
||||
&self.server_cipher,
|
||||
self.token.clone(),
|
||||
route_key,
|
||||
)?;
|
||||
}
|
||||
} else {
|
||||
//服务端解密
|
||||
self.server_cipher.decrypt_ipv4(&mut net_packet)?;
|
||||
let data_len = net_packet.data_len();
|
||||
self.server_packet_handle(context, current_device, buf, data_len, route_key)
|
||||
.await?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
self.client_cipher.decrypt_ipv4(&mut net_packet)?;
|
||||
match net_packet.protocol() {
|
||||
Protocol::IpTurn => {
|
||||
match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||
ip_turn_packet::Protocol::Icmp => {
|
||||
let ipv4 = IpV4Packet::new(net_packet.payload())?;
|
||||
if ipv4.protocol() == ipv4::protocol::Protocol::Icmp {
|
||||
self.device_writer.write_ipv4(&mut buf[12..])?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
ip_turn_packet::Protocol::Igmp => {
|
||||
if let Some(igmp_server) = &self.igmp_server {
|
||||
let ipv4 = IpV4Packet::new(net_packet.payload())?;
|
||||
if ipv4.protocol() == ipv4::protocol::Protocol::Igmp {
|
||||
igmp_server.handle(ipv4.payload(), source)?;
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
ip_turn_packet::Protocol::Ipv4 => {
|
||||
let data = if let Some(payload_len) = self.cipher.decrypt_ipv4(&mut net_packet)? {
|
||||
&mut net_packet.payload_mut()[..payload_len]
|
||||
} else {
|
||||
net_packet.payload_mut()
|
||||
};
|
||||
let mut ipv4 = IpV4Packet::new(data)?;
|
||||
let mut ipv4 = IpV4Packet::new(net_packet.payload_mut())?;
|
||||
match ipv4.protocol() {
|
||||
ipv4::protocol::Protocol::Igmp => {
|
||||
if let Some(igmp_server) = &self.igmp_server {
|
||||
@@ -164,7 +193,8 @@ impl ChannelDataHandler {
|
||||
}
|
||||
ipv4::protocol::Protocol::Icmp => {
|
||||
if ipv4.destination_ip() == destination {
|
||||
let mut icmp_packet = icmp::IcmpPacket::new(ipv4.payload_mut())?;
|
||||
let mut icmp_packet =
|
||||
icmp::IcmpPacket::new(ipv4.payload_mut())?;
|
||||
if icmp_packet.kind() == Kind::EchoRequest {
|
||||
//开启ping
|
||||
icmp_packet.set_kind(Kind::EchoReply);
|
||||
@@ -175,8 +205,8 @@ impl ChannelDataHandler {
|
||||
net_packet.set_source(destination);
|
||||
net_packet.set_destination(source);
|
||||
//不管加不加密,和接收到的数据长度都一致
|
||||
let _ = self.cipher.encrypt_ipv4(net_packet.payload().len() - 16, &mut net_packet)?;
|
||||
context.send_by_key(net_packet.buffer(), route_key).await?;
|
||||
self.client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||
context.try_send_by_key(net_packet.buffer(), route_key)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@@ -185,53 +215,88 @@ impl ChannelDataHandler {
|
||||
}
|
||||
if not_broadcast && ipv4.destination_ip() != destination {
|
||||
if let Some(ip_proxy_map) = &self.ip_proxy_map {
|
||||
if let Some(gate_way) = self.out_external_route.route(&ipv4.destination_ip()) {
|
||||
if self.out_external_route.allow(&ipv4.destination_ip()) {
|
||||
match ipv4.protocol() {
|
||||
ipv4::protocol::Protocol::Tcp => {
|
||||
let dest_ip = ipv4.destination_ip();
|
||||
//转发到代理目标地址
|
||||
let mut tcp_packet = packet::tcp::tcp::TcpPacket::new(source, destination, ipv4.payload_mut())?;
|
||||
let mut tcp_packet = packet::tcp::tcp::TcpPacket::new(
|
||||
source,
|
||||
destination,
|
||||
ipv4.payload_mut(),
|
||||
)?;
|
||||
let source_port = tcp_packet.source_port();
|
||||
let dest_port = tcp_packet.destination_port();
|
||||
tcp_packet.set_destination_port(ip_proxy_map.tcp_proxy_port);
|
||||
tcp_packet
|
||||
.set_destination_port(ip_proxy_map.tcp_proxy_port);
|
||||
tcp_packet.update_checksum();
|
||||
ipv4.set_destination_ip(destination);
|
||||
ipv4.update_checksum();
|
||||
ip_proxy_map.tcp_proxy_map.insert(SocketAddrV4::new(source, source_port),
|
||||
(SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port)));
|
||||
let key = SocketAddrV4::new(source, source_port);
|
||||
//https://github.com/crossbeam-rs/crossbeam/issues/1023
|
||||
ip_proxy_map
|
||||
.tcp_proxy_map
|
||||
.insert(key, SocketAddrV4::new(dest_ip, dest_port));
|
||||
}
|
||||
ipv4::protocol::Protocol::Udp => {
|
||||
let dest_ip = ipv4.destination_ip();
|
||||
//转发到代理目标地址
|
||||
let mut udp_packet = packet::udp::udp::UdpPacket::new(source, destination, ipv4.payload_mut())?;
|
||||
let mut udp_packet = packet::udp::udp::UdpPacket::new(
|
||||
source,
|
||||
destination,
|
||||
ipv4.payload_mut(),
|
||||
)?;
|
||||
let source_port = udp_packet.source_port();
|
||||
let dest_port = udp_packet.destination_port();
|
||||
udp_packet.set_destination_port(ip_proxy_map.udp_proxy_port);
|
||||
udp_packet
|
||||
.set_destination_port(ip_proxy_map.udp_proxy_port);
|
||||
udp_packet.update_checksum();
|
||||
ipv4.set_destination_ip(destination);
|
||||
ipv4.update_checksum();
|
||||
ip_proxy_map.udp_proxy_map.insert(SocketAddrV4::new(source, source_port),
|
||||
(SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port)));
|
||||
let key = SocketAddrV4::new(source, source_port);
|
||||
ip_proxy_map
|
||||
.udp_proxy_map
|
||||
.insert(key, SocketAddrV4::new(dest_ip, dest_port));
|
||||
}
|
||||
#[cfg(not(target_os = "android"))]
|
||||
ipv4::protocol::Protocol::Icmp => {
|
||||
let dest_ip = ipv4.destination_ip();
|
||||
//转发到代理目标地址
|
||||
let icmp_packet = icmp::IcmpPacket::new(ipv4.payload())?;
|
||||
let icmp_packet =
|
||||
icmp::IcmpPacket::new(ipv4.payload())?;
|
||||
match icmp_packet.header_other() {
|
||||
HeaderOther::Identifier(id, seq) => {
|
||||
ip_proxy_map.icmp_proxy_map.insert((dest_ip, id, seq), source);
|
||||
ip_proxy_map.send_icmp(ipv4.payload(), &gate_way, &dest_ip)?;
|
||||
icmp::HeaderOther::Identifier(id, seq) => {
|
||||
ip_proxy_map
|
||||
.icmp_proxy_map
|
||||
.insert((dest_ip, id, seq), source);
|
||||
ip_proxy_map
|
||||
.send_icmp(ipv4.payload(), &dest_ip)?;
|
||||
}
|
||||
_ => {
|
||||
return Ok(());
|
||||
log::warn!(
|
||||
"不支持的ip代理Icmp协议:{}",
|
||||
destination
|
||||
);
|
||||
return Err(Error::Warn(
|
||||
"不支持的ip代理Icmp协议".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Ok(());
|
||||
log::warn!("不支持的ip代理ipv4协议:{}", destination);
|
||||
return Err(Error::Warn(
|
||||
"不支持的ip代理ipv4协议".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::warn!("没有ip代理规则:{}", destination);
|
||||
return Err(Error::Warn("没有ip代理规则".to_string()));
|
||||
}
|
||||
} else {
|
||||
log::warn!("不支持ip代理:{}", destination);
|
||||
return Err(Error::Warn("不支持ip代理".to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,52 +310,404 @@ impl ChannelDataHandler {
|
||||
ip_turn_packet::Protocol::Unknown(_) => {}
|
||||
}
|
||||
}
|
||||
Protocol::Service => {
|
||||
self.service(context, current_device, source, net_packet, route_key).await?;
|
||||
}
|
||||
Protocol::Error => {
|
||||
self.error(context, current_device, source, net_packet, route_key).await?;
|
||||
}
|
||||
Protocol::Service => {}
|
||||
Protocol::Error => {}
|
||||
Protocol::Control => {
|
||||
self.control(context, current_device, source, net_packet, route_key).await?;
|
||||
self.control(context, current_device, source, net_packet, route_key)
|
||||
.await?;
|
||||
}
|
||||
Protocol::OtherTurn => {
|
||||
self.other_turn(context, current_device, source, net_packet, route_key).await?;
|
||||
self.other_turn(context, current_device, source, net_packet, route_key)
|
||||
.await?;
|
||||
}
|
||||
Protocol::UnKnow(e) => {
|
||||
log::info!("不支持的协议:{}",e);
|
||||
log::info!("不支持的协议:{}", e);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn service(&self, context: &Context, current_device: CurrentDeviceInfo, _source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
|
||||
|
||||
async fn pong_packet(
|
||||
&self,
|
||||
gateway: bool,
|
||||
metric: u8,
|
||||
context: &Context,
|
||||
current_device: CurrentDeviceInfo,
|
||||
source: Ipv4Addr,
|
||||
pong_packet: control_packet::PongPacket<&[u8]>,
|
||||
route_key: &RouteKey,
|
||||
) -> crate::Result<()> {
|
||||
let current_time = crate::handle::now_time() as u16;
|
||||
if current_time < pong_packet.time() {
|
||||
return Ok(());
|
||||
}
|
||||
let rt = (current_time - pong_packet.time()) as i64;
|
||||
let route = Route::from(*route_key, metric, rt);
|
||||
context.add_route(source, route);
|
||||
if gateway {
|
||||
let epoch = self.device_list.lock().0;
|
||||
if pong_packet.epoch() != epoch {
|
||||
let mut poll_device = NetPacket::new_encrypt([0; 12 + ENCRYPTION_RESERVED])?;
|
||||
poll_device.set_source(current_device.virtual_ip());
|
||||
poll_device.set_destination(source);
|
||||
poll_device.set_version(Version::V1);
|
||||
poll_device.set_gateway_flag(true);
|
||||
poll_device.first_set_ttl(MAX_TTL);
|
||||
poll_device.set_protocol(Protocol::Service);
|
||||
poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into());
|
||||
self.server_cipher.encrypt_ipv4(&mut poll_device)?;
|
||||
context.send_main(poll_device.buffer(), current_device.connect_server)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn control(
|
||||
&self,
|
||||
context: &Context,
|
||||
current_device: CurrentDeviceInfo,
|
||||
source: Ipv4Addr,
|
||||
mut net_packet: NetPacket<&mut [u8]>,
|
||||
route_key: &RouteKey,
|
||||
) -> crate::Result<()> {
|
||||
let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
|
||||
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
|
||||
ControlPacket::PingPacket(_) => {
|
||||
net_packet.set_transport_protocol(control_packet::Protocol::Pong.into());
|
||||
net_packet.set_source(current_device.virtual_ip());
|
||||
net_packet.set_destination(source);
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
self.client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||
context.try_send_by_key(net_packet.buffer(), route_key)?;
|
||||
let route = Route::from(*route_key, metric, 199);
|
||||
context.add_route_if_absent(source, route);
|
||||
}
|
||||
ControlPacket::PongPacket(pong_packet) => {
|
||||
self.pong_packet(
|
||||
false,
|
||||
metric,
|
||||
context,
|
||||
current_device,
|
||||
source,
|
||||
pong_packet,
|
||||
route_key,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
ControlPacket::PunchRequest => {
|
||||
if self.relay {
|
||||
return Ok(());
|
||||
}
|
||||
//回应
|
||||
net_packet.set_transport_protocol(control_packet::Protocol::PunchResponse.into());
|
||||
net_packet.set_source(current_device.virtual_ip());
|
||||
net_packet.set_destination(source);
|
||||
net_packet.first_set_ttl(1);
|
||||
self.client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||
context.try_send_by_key(net_packet.buffer(), route_key)?;
|
||||
let route = Route::from(*route_key, 1, 199);
|
||||
context.add_route_if_absent(source, route);
|
||||
}
|
||||
ControlPacket::PunchResponse => {
|
||||
if self.relay {
|
||||
return Ok(());
|
||||
}
|
||||
let route = Route::from(*route_key, 1, 199);
|
||||
context.add_route_if_absent(source, route);
|
||||
}
|
||||
ControlPacket::AddrRequest => match route_key.addr.ip() {
|
||||
std::net::IpAddr::V4(ipv4) => {
|
||||
let mut packet = NetPacket::new_encrypt([0; 12 + 6 + ENCRYPTION_RESERVED])?;
|
||||
packet.set_version(Version::V1);
|
||||
packet.set_protocol(Protocol::Control);
|
||||
packet.set_transport_protocol(control_packet::Protocol::AddrResponse.into());
|
||||
packet.first_set_ttl(MAX_TTL);
|
||||
packet.set_source(current_device.virtual_ip());
|
||||
packet.set_destination(source);
|
||||
let mut addr_packet = control_packet::AddrPacket::new(packet.payload_mut())?;
|
||||
addr_packet.set_ipv4(ipv4);
|
||||
addr_packet.set_port(route_key.addr.port());
|
||||
self.client_cipher.encrypt_ipv4(&mut packet)?;
|
||||
context.try_send_by_key(packet.buffer(), route_key)?;
|
||||
}
|
||||
std::net::IpAddr::V6(_) => {}
|
||||
},
|
||||
ControlPacket::AddrResponse(addr_packet) => {
|
||||
if !addr_packet.ipv4().is_multicast()
|
||||
&& !addr_packet.ipv4().is_broadcast()
|
||||
&& !addr_packet.ipv4().is_unspecified()
|
||||
&& !addr_packet.ipv4().is_loopback()
|
||||
&& !addr_packet.ipv4().is_private()
|
||||
&& addr_packet.port() != 0
|
||||
{
|
||||
self.nat_test
|
||||
.update_addr(addr_packet.ipv4(), addr_packet.port())
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn other_turn(
|
||||
&self,
|
||||
context: &Context,
|
||||
current_device: CurrentDeviceInfo,
|
||||
source: Ipv4Addr,
|
||||
net_packet: NetPacket<&mut [u8]>,
|
||||
route_key: &RouteKey,
|
||||
) -> crate::Result<()> {
|
||||
if self.relay {
|
||||
return Ok(());
|
||||
}
|
||||
match other_turn_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||
other_turn_packet::Protocol::Punch => {
|
||||
let punch_info = PunchInfo::parse_from_bytes(net_packet.payload())?;
|
||||
let public_ips = punch_info
|
||||
.public_ip_list
|
||||
.iter()
|
||||
.map(|v| Ipv4Addr::from(v.to_be_bytes()))
|
||||
.collect();
|
||||
let local_ipv4_addr = SocketAddrV4::new(
|
||||
Ipv4Addr::from(punch_info.local_ip.to_be_bytes()),
|
||||
punch_info.local_port as u16,
|
||||
);
|
||||
let ipv6_addr = if punch_info.ipv6.len() == 16 {
|
||||
let ipv6: [u8; 16] = punch_info.ipv6.try_into().unwrap();
|
||||
SocketAddrV6::new(Ipv6Addr::from(ipv6), punch_info.ipv6_port as u16, 0, 0)
|
||||
} else {
|
||||
SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0)
|
||||
};
|
||||
|
||||
let peer_nat_info = NatInfo::new(
|
||||
public_ips,
|
||||
punch_info.public_port as u16,
|
||||
punch_info.public_port_range as u16,
|
||||
local_ipv4_addr,
|
||||
ipv6_addr,
|
||||
punch_info.nat_type.enum_value_or_default().into(),
|
||||
);
|
||||
self.peer_nat_info_map.insert(source, peer_nat_info.clone());
|
||||
if !punch_info.reply {
|
||||
let mut punch_reply = PunchInfo::new();
|
||||
punch_reply.reply = true;
|
||||
let nat_info = self.nat_test.nat_info();
|
||||
punch_reply.public_ip_list = nat_info
|
||||
.public_ips
|
||||
.iter()
|
||||
.map(|ip| u32::from_be_bytes(ip.octets()))
|
||||
.collect();
|
||||
punch_reply.public_port = nat_info.public_port as u32;
|
||||
punch_reply.public_port_range = nat_info.public_port_range as u32;
|
||||
punch_reply.nat_type =
|
||||
protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type));
|
||||
punch_reply.local_ip =
|
||||
u32::from_be_bytes(nat_info.local_ipv4_addr.ip().octets());
|
||||
punch_reply.local_port = nat_info.local_ipv4_addr.port() as u32;
|
||||
if !nat_info.ipv6_addr.ip().is_unspecified() {
|
||||
punch_reply.ipv6 = nat_info.ipv6_addr.ip().octets().to_vec();
|
||||
punch_reply.ipv6_port = nat_info.ipv6_addr.port() as u32;
|
||||
}
|
||||
let bytes = punch_reply.write_to_bytes()?;
|
||||
let mut punch_packet =
|
||||
NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?;
|
||||
punch_packet.set_version(Version::V1);
|
||||
punch_packet.set_protocol(Protocol::OtherTurn);
|
||||
punch_packet.set_transport_protocol(other_turn_packet::Protocol::Punch.into());
|
||||
punch_packet.first_set_ttl(MAX_TTL);
|
||||
punch_packet.set_source(current_device.virtual_ip());
|
||||
punch_packet.set_destination(source);
|
||||
punch_packet.set_payload(&bytes)?;
|
||||
// if !peer_nat_info.local_ip.is_unspecified() && peer_nat_info.local_port != 0 {
|
||||
// let mut packet = NetPacket::new_encrypt([0u8; 12 + ENCRYPTION_RESERVED])?;
|
||||
// packet.set_version(Version::V1);
|
||||
// packet.first_set_ttl(1);
|
||||
// packet.set_protocol(Protocol::Control);
|
||||
// packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
|
||||
// packet.set_source(current_device.virtual_ip());
|
||||
// packet.set_destination(source);
|
||||
// self.client_cipher.encrypt_ipv4(&mut packet)?;
|
||||
// let _ = context.try_send_main_udp(packet.buffer(),
|
||||
// SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port)));
|
||||
// }
|
||||
if self.punch(source, peer_nat_info).await {
|
||||
self.client_cipher.encrypt_ipv4(&mut punch_packet)?;
|
||||
context.try_send_by_key(punch_packet.buffer(), route_key)?;
|
||||
}
|
||||
} else {
|
||||
self.punch(source, peer_nat_info).await;
|
||||
}
|
||||
}
|
||||
other_turn_packet::Protocol::Unknown(e) => {
|
||||
log::warn!("不支持的转发协议 {:?},source:{:?}", e, source);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn punch(&self, peer_ip: Ipv4Addr, peer_nat_info: NatInfo) -> bool {
|
||||
match peer_nat_info.nat_type {
|
||||
NatType::Symmetric => self
|
||||
.symmetric_sender
|
||||
.try_send((peer_ip, peer_nat_info))
|
||||
.is_ok(),
|
||||
NatType::Cone => self.cone_sender.try_send((peer_ip, peer_nat_info)).is_ok(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 处理服务端数据
|
||||
impl ChannelDataHandler {
|
||||
async fn server_packet_handle(
|
||||
&self,
|
||||
context: &Context,
|
||||
current_device: CurrentDeviceInfo,
|
||||
buf: &mut [u8],
|
||||
data_len: usize,
|
||||
route_key: &RouteKey,
|
||||
) -> crate::Result<()> {
|
||||
let net_packet = NetPacket::new0(data_len, &buf[14..])?;
|
||||
let source = net_packet.source();
|
||||
match net_packet.protocol() {
|
||||
Protocol::Service => {
|
||||
self.service(context, current_device, net_packet, route_key)
|
||||
.await?;
|
||||
}
|
||||
Protocol::Error => {
|
||||
self.error(context, current_device, source, net_packet, route_key)
|
||||
.await?;
|
||||
}
|
||||
Protocol::Control => {
|
||||
self.control_gateway(context, current_device, net_packet, route_key)
|
||||
.await?;
|
||||
}
|
||||
Protocol::IpTurn => {
|
||||
match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||
ip_turn_packet::Protocol::Ipv4 => {
|
||||
let ipv4 = IpV4Packet::new(net_packet.payload())?;
|
||||
match ipv4.protocol() {
|
||||
ipv4::protocol::Protocol::Igmp => {
|
||||
if let Some(igmp_server) = &self.igmp_server {
|
||||
igmp_server.handle(ipv4.payload(), source)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
ipv4::protocol::Protocol::Icmp => {
|
||||
if ipv4.destination_ip() == current_device.virtual_ip {
|
||||
let icmp_packet = icmp::IcmpPacket::new(ipv4.payload())?;
|
||||
if icmp_packet.kind() == Kind::EchoReply {
|
||||
self.device_writer.write_ipv4(&mut buf[12..])?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
ip_turn_packet::Protocol::Ipv4Broadcast => {}
|
||||
ip_turn_packet::Protocol::Unknown(_) => {}
|
||||
}
|
||||
}
|
||||
Protocol::OtherTurn => {}
|
||||
Protocol::UnKnow(_) => {}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
async fn control_gateway(
|
||||
&self,
|
||||
context: &Context,
|
||||
current_device: CurrentDeviceInfo,
|
||||
net_packet: NetPacket<&[u8]>,
|
||||
route_key: &RouteKey,
|
||||
) -> crate::Result<()> {
|
||||
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
|
||||
ControlPacket::PongPacket(pong_packet) => {
|
||||
let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
|
||||
self.pong_packet(
|
||||
true,
|
||||
metric,
|
||||
context,
|
||||
current_device,
|
||||
net_packet.source(),
|
||||
pong_packet,
|
||||
route_key,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
ControlPacket::AddrResponse(addr_packet) => {
|
||||
if addr_packet.port() != 0
|
||||
&& !addr_packet.ipv4().is_multicast()
|
||||
&& !addr_packet.ipv4().is_broadcast()
|
||||
&& !addr_packet.ipv4().is_unspecified()
|
||||
&& !addr_packet.ipv4().is_loopback()
|
||||
&& !addr_packet.ipv4().is_private()
|
||||
{
|
||||
self.nat_test
|
||||
.update_addr(addr_packet.ipv4(), addr_packet.port())
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn service(
|
||||
&self,
|
||||
context: &Context,
|
||||
current_device: CurrentDeviceInfo,
|
||||
net_packet: NetPacket<&[u8]>,
|
||||
route_key: &RouteKey,
|
||||
) -> crate::Result<()> {
|
||||
match service_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||
service_packet::Protocol::RegistrationRequest => {}
|
||||
service_packet::Protocol::RegistrationResponse => {
|
||||
let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?;
|
||||
let local_port = context.main_local_port()?;
|
||||
let local_ip = nat::local_ip()?;
|
||||
let nat_info = self.nat_test.re_test(Ipv4Addr::from(response.public_ip),
|
||||
response.public_port as u16, local_ip, local_port);
|
||||
context.switch(nat_info.nat_type);
|
||||
|
||||
{
|
||||
let context = context.clone();
|
||||
let nat_test = self.nat_test.clone();
|
||||
tokio::spawn(async move {
|
||||
let local_port = context.main_local_ipv4_port().unwrap_or(0);
|
||||
let local_ipv4_addr = nat::local_ipv4_addr(local_port);
|
||||
let local_port = context.main_local_ipv6_port().unwrap_or(0);
|
||||
let ipv6_addr = nat::local_ipv6_addr(local_port);
|
||||
let nat_info = nat_test
|
||||
.re_test(
|
||||
Ipv4Addr::from(response.public_ip),
|
||||
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 current_ip = current_device.virtual_ip();
|
||||
if current_ip != new_ip {
|
||||
// ip发生变化
|
||||
log::info!("ip发生变化,old_ip:{:?},new_ip:{:?}",current_ip,new_ip);
|
||||
log::info!("ip发生变化,old_ip:{:?},new_ip:{:?}", current_ip, new_ip);
|
||||
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
|
||||
let old_netmask = current_device.virtual_netmask;
|
||||
let old_netmask = current_device.virtual_netmask;
|
||||
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
|
||||
let old_gateway = current_device.virtual_gateway();
|
||||
let old_gateway = current_device.virtual_gateway();
|
||||
let virtual_ip = Ipv4Addr::from(response.virtual_ip);
|
||||
let virtual_gateway = Ipv4Addr::from(response.virtual_gateway);
|
||||
let virtual_netmask = Ipv4Addr::from(response.virtual_netmask);
|
||||
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
|
||||
self.device_writer.change_ip(virtual_ip, virtual_netmask, virtual_gateway, old_netmask, old_gateway)?;
|
||||
let new_current_device = CurrentDeviceInfo::new(virtual_ip, virtual_gateway,
|
||||
virtual_netmask, current_device.connect_server);
|
||||
if let Err(e) = self.current_device.compare_exchange(current_device, new_current_device) {
|
||||
log::warn!("替换失败:{:?}",e);
|
||||
self.device_writer.change_ip(
|
||||
virtual_ip,
|
||||
virtual_netmask,
|
||||
virtual_gateway,
|
||||
old_netmask,
|
||||
old_gateway,
|
||||
)?;
|
||||
let new_current_device = CurrentDeviceInfo::new(
|
||||
virtual_ip,
|
||||
virtual_gateway,
|
||||
virtual_netmask,
|
||||
current_device.connect_server,
|
||||
);
|
||||
if let Err(e) = self
|
||||
.current_device
|
||||
.compare_exchange(current_device, new_current_device)
|
||||
{
|
||||
log::warn!("替换失败:{:?}", e);
|
||||
}
|
||||
}
|
||||
self.connect_status.store(ConnectStatus::Connected);
|
||||
@@ -306,10 +723,11 @@ impl ChannelDataHandler {
|
||||
Ipv4Addr::from(info.virtual_ip),
|
||||
info.name,
|
||||
info.device_status as u8,
|
||||
info.client_secret,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let route = Route::from(*route_key, 2, 99);
|
||||
let route = Route::from(*route_key, 2, 199);
|
||||
for x in &ip_list {
|
||||
if x.status == PeerDeviceStatus::Online {
|
||||
context.add_route_if_absent(x.virtual_ip, route);
|
||||
@@ -322,13 +740,21 @@ impl ChannelDataHandler {
|
||||
}
|
||||
}
|
||||
service_packet::Protocol::Unknown(u) => {
|
||||
log::warn!("未知服务协议:{}",u);
|
||||
log::warn!("未知服务协议:{}", u);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn error(&self, _context: &Context, current_device: CurrentDeviceInfo, _source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, _route_key: &RouteKey) -> crate::Result<()> {
|
||||
log::info!("current_device:{:?}",current_device);
|
||||
async fn error(
|
||||
&self,
|
||||
_context: &Context,
|
||||
current_device: CurrentDeviceInfo,
|
||||
_source: Ipv4Addr,
|
||||
net_packet: NetPacket<&[u8]>,
|
||||
_route_key: &RouteKey,
|
||||
) -> crate::Result<()> {
|
||||
log::info!("current_device:{:?}", current_device);
|
||||
match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
|
||||
InErrorPacket::TokenError => {
|
||||
return Err(Error::Stop("Token error".to_string()));
|
||||
@@ -341,7 +767,7 @@ impl ChannelDataHandler {
|
||||
}
|
||||
|
||||
self.connect_status.store(ConnectStatus::Connecting);
|
||||
self.register.fast_register(current_device.virtual_ip).await?;
|
||||
self.register.fast_register(current_device.virtual_ip)?;
|
||||
}
|
||||
InErrorPacket::AddressExhausted => {
|
||||
//地址用尽
|
||||
@@ -356,169 +782,8 @@ impl ChannelDataHandler {
|
||||
InErrorPacket::InvalidIp => {
|
||||
log::error!("InvalidIp");
|
||||
}
|
||||
InErrorPacket::NoKey => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn control(&self, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, mut net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
|
||||
let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
|
||||
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
|
||||
ControlPacket::PingPacket(_) => {
|
||||
context.update_read_time(&source, route_key);
|
||||
net_packet.set_transport_protocol(control_packet::Protocol::Pong.into());
|
||||
net_packet.set_source(current_device.virtual_ip());
|
||||
net_packet.set_destination(source);
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
context.send_by_key(net_packet.buffer(), route_key).await?;
|
||||
let route = Route::from(*route_key, metric, 99);
|
||||
context.add_route_if_absent(source, route);
|
||||
}
|
||||
ControlPacket::PongPacket(pong_packet) => {
|
||||
context.update_read_time(&source, route_key);
|
||||
let current_time = crate::handle::now_time() as u16;
|
||||
if current_time < pong_packet.time() {
|
||||
return Ok(());
|
||||
}
|
||||
let rt = (current_time - pong_packet.time()) as i64;
|
||||
let route = Route::from(*route_key, metric, rt);
|
||||
context.add_route(source, route);
|
||||
if source == current_device.virtual_gateway() {
|
||||
let epoch = self.device_list.lock().0;
|
||||
if pong_packet.epoch() != epoch {
|
||||
let mut poll_device = NetPacket::new([0; 12])?;
|
||||
poll_device.set_source(current_device.virtual_ip());
|
||||
poll_device.set_destination(source);
|
||||
poll_device.set_version(Version::V1);
|
||||
poll_device.first_set_ttl(MAX_TTL);
|
||||
poll_device.set_protocol(Protocol::Service);
|
||||
poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into());
|
||||
context.send_main(poll_device.buffer(), current_device.connect_server).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
ControlPacket::PunchRequest => {
|
||||
if self.relay {
|
||||
return Ok(());
|
||||
}
|
||||
//回应
|
||||
net_packet.set_transport_protocol(control_packet::Protocol::PunchResponse.into());
|
||||
net_packet.set_source(current_device.virtual_ip());
|
||||
net_packet.set_destination(source);
|
||||
net_packet.first_set_ttl(1);
|
||||
context.send_by_key(net_packet.buffer(), route_key).await?;
|
||||
let route = Route::from(*route_key, metric, 99);
|
||||
context.add_route_if_absent(source, route);
|
||||
}
|
||||
ControlPacket::PunchResponse => {
|
||||
if self.relay {
|
||||
return Ok(());
|
||||
}
|
||||
// log::info!("PunchResponse route_key:{:?}",route_key);
|
||||
let route = Route::from(*route_key, metric, 99);
|
||||
context.add_route_if_absent(source, route);
|
||||
}
|
||||
ControlPacket::AddrRequest => {
|
||||
match route_key.addr.ip() {
|
||||
std::net::IpAddr::V4(ipv4) => {
|
||||
let mut packet = NetPacket::new([0;12+6])?;
|
||||
packet.set_version(Version::V1);
|
||||
packet.set_protocol(Protocol::Control);
|
||||
packet.set_transport_protocol(
|
||||
control_packet::Protocol::AddrResponse.into(),
|
||||
);
|
||||
packet.first_set_ttl(MAX_TTL);
|
||||
packet.set_source(current_device.virtual_ip());
|
||||
packet.set_destination(source);
|
||||
let mut addr_packet = control_packet::AddrPacket::new(packet.payload_mut())?;
|
||||
addr_packet.set_ipv4(ipv4);
|
||||
addr_packet.set_port(route_key.addr.port());
|
||||
context.send_by_key(packet.buffer(), route_key).await?;
|
||||
}
|
||||
std::net::IpAddr::V6(_) => {}
|
||||
}
|
||||
}
|
||||
ControlPacket::AddrResponse(addr_packet) => {
|
||||
if addr_packet.port() != 0
|
||||
&& !addr_packet.ipv4().is_multicast()
|
||||
&& !addr_packet.ipv4().is_broadcast()
|
||||
&& !addr_packet.ipv4().is_unspecified()
|
||||
&& !addr_packet.ipv4().is_loopback()
|
||||
&& !addr_packet.ipv4().is_private() {
|
||||
self.nat_test.update_addr(addr_packet.ipv4(), addr_packet.port())
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn other_turn(&self, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
|
||||
if self.relay {
|
||||
return Ok(());
|
||||
}
|
||||
match other_turn_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||
other_turn_packet::Protocol::Punch => {
|
||||
let punch_info = PunchInfo::parse_from_bytes(net_packet.payload())?;
|
||||
let public_ips = punch_info.public_ip_list.
|
||||
iter().map(|v| { Ipv4Addr::from(v.to_be_bytes()) }).collect();
|
||||
let peer_nat_info = NatInfo::new(public_ips,
|
||||
punch_info.public_port as u16,
|
||||
punch_info.public_port_range as u16,
|
||||
Ipv4Addr::from(punch_info.local_ip.to_be_bytes()),
|
||||
punch_info.local_port as u16,
|
||||
punch_info.nat_type.enum_value_or_default().into());
|
||||
self.peer_nat_info_map.insert(source, peer_nat_info.clone());
|
||||
if !punch_info.reply {
|
||||
let mut punch_reply = PunchInfo::new();
|
||||
punch_reply.reply = true;
|
||||
let nat_info = self.nat_test.nat_info();
|
||||
punch_reply.public_ip_list = nat_info.public_ips.iter().map(|ip| u32::from_be_bytes(ip.octets())).collect();
|
||||
punch_reply.public_port = nat_info.public_port as u32;
|
||||
punch_reply.public_port_range = nat_info.public_port_range as u32;
|
||||
punch_reply.nat_type =
|
||||
protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type));
|
||||
punch_reply.local_ip = u32::from_be_bytes(nat_info.local_ip.octets());
|
||||
punch_reply.local_port = nat_info.local_port as u32;
|
||||
let bytes = punch_reply.write_to_bytes()?;
|
||||
let mut net_packet =
|
||||
NetPacket::new(vec![0u8; 12 + bytes.len()])?;
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_protocol(Protocol::OtherTurn);
|
||||
net_packet.set_transport_protocol(
|
||||
other_turn_packet::Protocol::Punch.into(),
|
||||
);
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
net_packet.set_source(current_device.virtual_ip());
|
||||
net_packet.set_destination(source);
|
||||
net_packet.set_payload(&bytes);
|
||||
if !peer_nat_info.local_ip.is_unspecified() && peer_nat_info.local_port != 0 {
|
||||
let mut packet = NetPacket::new([0u8; 12])?;
|
||||
packet.set_version(Version::V1);
|
||||
packet.first_set_ttl(1);
|
||||
packet.set_protocol(Protocol::Control);
|
||||
packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
|
||||
packet.set_source(current_device.virtual_ip());
|
||||
packet.set_destination(source);
|
||||
let _ = context.send_main(packet.buffer(), SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port))).await;
|
||||
}
|
||||
if self.punch(source, peer_nat_info).await {
|
||||
context.send_by_key(net_packet.buffer(), route_key).await?;
|
||||
}
|
||||
} else {
|
||||
self.punch(source, peer_nat_info).await;
|
||||
}
|
||||
}
|
||||
other_turn_packet::Protocol::Unknown(e) => {
|
||||
log::warn!("不支持的转发协议 {:?},source:{:?}",e,source);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn punch(&self, peer_ip: Ipv4Addr, peer_nat_info: NatInfo) -> bool {
|
||||
match peer_nat_info.nat_type {
|
||||
NatType::Symmetric => {
|
||||
self.symmetric_sender.try_send((peer_ip, peer_nat_info)).is_ok()
|
||||
}
|
||||
NatType::Cone => {
|
||||
self.cone_sender.try_send((peer_ip, peer_nat_info)).is_ok()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
use std::io;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
use std::time::{Duration, Instant};
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
|
||||
use protobuf::Message;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::{TcpStream, UdpSocket};
|
||||
use crate::channel::sender::ChannelSender;
|
||||
use crate::cipher::Cipher;
|
||||
use crate::handle::PeerDeviceInfo;
|
||||
use protobuf::Message;
|
||||
use std::net::UdpSocket;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
|
||||
use crate::proto::message::{RegistrationRequest, RegistrationResponse};
|
||||
use crate::protocol::body::ENCRYPTION_RESERVED;
|
||||
use crate::protocol::error_packet::InErrorPacket;
|
||||
use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL};
|
||||
|
||||
@@ -38,14 +40,25 @@ pub struct RegResponse {
|
||||
pub async fn registration(
|
||||
main_channel: &UdpSocket,
|
||||
main_tcp_channel: Option<&mut TcpStream>,
|
||||
server_cipher: &Cipher,
|
||||
server_address: SocketAddr,
|
||||
token: String,
|
||||
device_id: String,
|
||||
name: String,
|
||||
ip: Ipv4Addr,
|
||||
client_secret: bool,
|
||||
) -> Result<RegResponse, ReqEnum> {
|
||||
let request_packet =
|
||||
registration_request_packet(token.clone(), device_id.clone(), name.clone(), ip, false, false).unwrap();
|
||||
let request_packet = registration_request_packet(
|
||||
server_cipher,
|
||||
token.clone(),
|
||||
device_id.clone(),
|
||||
name.clone(),
|
||||
ip,
|
||||
false,
|
||||
false,
|
||||
client_secret,
|
||||
)
|
||||
.unwrap();
|
||||
let buf = request_packet.buffer();
|
||||
let mut recv_buf = [0u8; 10240];
|
||||
let recv_buf = if let Some(main_tcp_channel) = main_tcp_channel {
|
||||
@@ -61,41 +74,38 @@ pub async fn registration(
|
||||
return Err(ReqEnum::Other(format!("read error:{}", e)));
|
||||
}
|
||||
let len = 4 + (((recv_buf[2] as u16) << 8) | recv_buf[3] as u16) as usize;
|
||||
if len > recv_buf.len() {
|
||||
return Err(ReqEnum::Other("too long".to_string()));
|
||||
}
|
||||
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[4..len]).await {
|
||||
return Err(ReqEnum::Other(format!("read error:{}", e)));
|
||||
}
|
||||
&recv_buf[4..len]
|
||||
&mut recv_buf[4..len]
|
||||
} else {
|
||||
if let Err(e) = main_channel.send_to(buf, server_address).await {
|
||||
if let Err(e) = main_channel.send_to(buf, server_address) {
|
||||
return Err(ReqEnum::Other(format!("send error:{}", e)));
|
||||
}
|
||||
match tokio::time::timeout(Duration::from_millis(300), main_channel.recv_from(&mut recv_buf)).await {
|
||||
Ok(rs) => {
|
||||
match rs {
|
||||
Ok((len, addr)) => {
|
||||
if server_address != addr {
|
||||
return Err(ReqEnum::Other(format!("invalid data,from {}", addr)));
|
||||
}
|
||||
&recv_buf[..len]
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(ReqEnum::Other(format!("receiver error:{}", e)));
|
||||
}
|
||||
match main_channel.recv_from(&mut recv_buf) {
|
||||
Ok((len, addr)) => {
|
||||
if server_address != addr {
|
||||
return Err(ReqEnum::Other(format!("invalid data,from {}", addr)));
|
||||
}
|
||||
&mut recv_buf[..len]
|
||||
}
|
||||
Err(_) => {
|
||||
return Err(ReqEnum::Timeout);
|
||||
Err(e) => {
|
||||
return Err(ReqEnum::Other(format!("receiver error:{}", e)));
|
||||
}
|
||||
}
|
||||
};
|
||||
let net_packet = match NetPacket::new(recv_buf) {
|
||||
Ok(net_packet) => {
|
||||
net_packet
|
||||
}
|
||||
let mut net_packet = match NetPacket::new(recv_buf) {
|
||||
Ok(net_packet) => net_packet,
|
||||
Err(e) => {
|
||||
return Err(ReqEnum::ServerError(format!("{}", e)));
|
||||
}
|
||||
};
|
||||
if let Err(e) = server_cipher.decrypt_ipv4(&mut net_packet) {
|
||||
return Err(ReqEnum::ServerError(format!("decrypt_ipv4 {}", e)));
|
||||
}
|
||||
match net_packet.protocol() {
|
||||
Protocol::Service => {
|
||||
match service_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||
@@ -110,6 +120,7 @@ pub async fn registration(
|
||||
Ipv4Addr::from(info.virtual_ip),
|
||||
info.name,
|
||||
info.device_status as u8,
|
||||
info.client_secret,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
@@ -123,14 +134,10 @@ pub async fn registration(
|
||||
public_port: response.public_port as u16,
|
||||
})
|
||||
}
|
||||
Err(_) => {
|
||||
Err(ReqEnum::ServerError("invalid data".to_string()))
|
||||
}
|
||||
Err(_) => Err(ReqEnum::ServerError("invalid data".to_string())),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
Err(ReqEnum::ServerError("invalid data".to_string()))
|
||||
}
|
||||
_ => Err(ReqEnum::ServerError("invalid data".to_string())),
|
||||
}
|
||||
}
|
||||
Protocol::Error => {
|
||||
@@ -140,21 +147,14 @@ pub async fn registration(
|
||||
InErrorPacket::Disconnect => {
|
||||
Err(ReqEnum::ServerError("disconnect".to_string()))
|
||||
}
|
||||
InErrorPacket::AddressExhausted => {
|
||||
Err(ReqEnum::AddressExhausted)
|
||||
}
|
||||
InErrorPacket::AddressExhausted => Err(ReqEnum::AddressExhausted),
|
||||
InErrorPacket::OtherError(e) => match e.message() {
|
||||
Ok(str) => {
|
||||
Err(ReqEnum::ServerError(str))
|
||||
}
|
||||
Ok(str) => Err(ReqEnum::ServerError(str)),
|
||||
Err(e) => Err(ReqEnum::Other(format!("{}", e))),
|
||||
},
|
||||
InErrorPacket::IpAlreadyExists => {
|
||||
Err(ReqEnum::IpAlreadyExists)
|
||||
}
|
||||
InErrorPacket::InvalidIp => {
|
||||
Err(ReqEnum::InvalidIp)
|
||||
}
|
||||
InErrorPacket::IpAlreadyExists => Err(ReqEnum::IpAlreadyExists),
|
||||
InErrorPacket::InvalidIp => Err(ReqEnum::InvalidIp),
|
||||
InErrorPacket::NoKey => Err(ReqEnum::ServerError("no key".to_string())),
|
||||
},
|
||||
Err(e) => Err(ReqEnum::Other(format!("{}", e))),
|
||||
}
|
||||
@@ -164,12 +164,14 @@ pub async fn registration(
|
||||
}
|
||||
|
||||
fn registration_request_packet(
|
||||
server_cipher: &Cipher,
|
||||
token: String,
|
||||
device_id: String,
|
||||
name: String,
|
||||
ip: Ipv4Addr,
|
||||
is_fast: bool,
|
||||
allow_ip_change: bool,
|
||||
client_secret: bool,
|
||||
) -> crate::Result<NetPacket<Vec<u8>>> {
|
||||
let mut request = RegistrationRequest::new();
|
||||
request.token = token;
|
||||
@@ -178,67 +180,74 @@ fn registration_request_packet(
|
||||
request.virtual_ip = ip.into();
|
||||
request.allow_ip_change = allow_ip_change;
|
||||
request.is_fast = is_fast;
|
||||
request.version = "1.1.1".to_string();
|
||||
request.version = crate::VNT_VERSION.to_string();
|
||||
request.client_secret = client_secret;
|
||||
let bytes = request.write_to_bytes()?;
|
||||
let buf = vec![0u8; 12 + bytes.len()];
|
||||
let mut net_packet = NetPacket::new(buf)?;
|
||||
let buf = vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED];
|
||||
let mut net_packet = NetPacket::new_encrypt(buf)?;
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_gateway_flag(true);
|
||||
net_packet.set_protocol(Protocol::Service);
|
||||
net_packet.set_transport_protocol(service_packet::Protocol::RegistrationRequest.into());
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
net_packet.set_payload(&bytes);
|
||||
net_packet.set_payload(&bytes)?;
|
||||
server_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||
Ok(net_packet)
|
||||
}
|
||||
|
||||
pub struct Register {
|
||||
server_cipher: Cipher,
|
||||
sender: ChannelSender,
|
||||
server_address: SocketAddr,
|
||||
token: String,
|
||||
device_id: String,
|
||||
name: String,
|
||||
time: AtomicCell<Instant>,
|
||||
client_secret: bool,
|
||||
}
|
||||
|
||||
impl Register {
|
||||
pub fn new(
|
||||
server_cipher: Cipher,
|
||||
sender: ChannelSender,
|
||||
server_address: SocketAddr,
|
||||
token: String,
|
||||
device_id: String,
|
||||
name: String,
|
||||
client_secret: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
server_cipher,
|
||||
sender,
|
||||
server_address,
|
||||
token,
|
||||
device_id,
|
||||
name,
|
||||
time: AtomicCell::new(Instant::now()),
|
||||
client_secret,
|
||||
}
|
||||
}
|
||||
pub async fn fast_register(&self, ip: Ipv4Addr) -> io::Result<()> {
|
||||
pub fn fast_register(&self, ip: Ipv4Addr) -> crate::Result<()> {
|
||||
let last = self.time.load();
|
||||
if last.elapsed() < Duration::from_secs(2)
|
||||
|| self
|
||||
.time
|
||||
.compare_exchange(last, Instant::now())
|
||||
.is_err()
|
||||
|| self.time.compare_exchange(last, Instant::now()).is_err()
|
||||
{
|
||||
//短时间不重复注册
|
||||
return Ok(());
|
||||
}
|
||||
log::info!("重新连接");
|
||||
let request_packet = registration_request_packet(
|
||||
&self.server_cipher,
|
||||
self.token.clone(),
|
||||
self.device_id.clone(),
|
||||
self.name.clone(),
|
||||
ip,
|
||||
false,
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
self.client_secret,
|
||||
)?;
|
||||
let buf = request_packet.buffer();
|
||||
self.sender.send_main(buf, self.server_address).await?;
|
||||
self.sender.send_main(buf, self.server_address)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
use byte_pool::Block;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BufSenderGroup(
|
||||
usize,
|
||||
Vec<std::sync::mpsc::SyncSender<(Block<'static>, usize, usize)>>,
|
||||
);
|
||||
|
||||
pub struct BufReceiverGroup(pub Vec<std::sync::mpsc::Receiver<(Block<'static>, usize, usize)>>);
|
||||
|
||||
impl BufSenderGroup {
|
||||
pub fn send(&mut self, val: (Block<'static>, usize, usize)) -> bool {
|
||||
let index = self.0 % self.1.len();
|
||||
self.0 = self.0.wrapping_add(1);
|
||||
self.1[index].send(val).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) {
|
||||
let mut buf_sender_group = Vec::with_capacity(size);
|
||||
let mut buf_receiver_group = Vec::with_capacity(size);
|
||||
for _ in 0..size {
|
||||
let (buf_sender, buf_receiver) =
|
||||
std::sync::mpsc::sync_channel::<(Block<'static>, usize, usize)>(1);
|
||||
buf_sender_group.push(buf_sender);
|
||||
buf_receiver_group.push(buf_receiver);
|
||||
}
|
||||
(
|
||||
BufSenderGroup(0, buf_sender_group),
|
||||
BufReceiverGroup(buf_receiver_group),
|
||||
)
|
||||
}
|
||||
+137
-113
@@ -1,28 +1,39 @@
|
||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||
use crate::channel::sender::ChannelSender;
|
||||
use crate::cipher::Cipher;
|
||||
use crate::error::*;
|
||||
use crate::external_route::ExternalRoute;
|
||||
use crate::handle::{check_dest, CurrentDeviceInfo};
|
||||
use crate::igmp_server::{IgmpServer, Multicast};
|
||||
use crate::ip_proxy::IpProxyMap;
|
||||
use crate::protocol;
|
||||
use crate::protocol::body::ENCRYPTION_RESERVED;
|
||||
use crate::protocol::ip_turn_packet::BroadcastPacket;
|
||||
use crate::protocol::{ip_turn_packet, NetPacket, Version, MAX_TTL};
|
||||
use packet::ip::ipv4::packet::IpV4Packet;
|
||||
use packet::ip::ipv4::protocol::Protocol;
|
||||
use packet::tcp::tcp::TcpPacket;
|
||||
use packet::udp::udp::UdpPacket;
|
||||
use crate::channel::sender::ChannelSender;
|
||||
use crate::cipher::Cipher;
|
||||
use crate::external_route::ExternalRoute;
|
||||
use crate::handle::{check_dest, CurrentDeviceInfo};
|
||||
use crate::ip_proxy::IpProxyMap;
|
||||
use crate::protocol::{ip_turn_packet, NetPacket, Version};
|
||||
use crate::error::*;
|
||||
use crate::igmp_server::IgmpServer;
|
||||
use crate::protocol;
|
||||
use crate::protocol::ip_turn_packet::BroadcastPacketEnd;
|
||||
use parking_lot::RwLock;
|
||||
use std::io;
|
||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub mod tun_handler;
|
||||
pub mod channel_group;
|
||||
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
|
||||
pub mod tap_handler;
|
||||
pub mod tun_handler;
|
||||
|
||||
async fn broadcast(sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]>, data_len: usize, current_device: &CurrentDeviceInfo) -> Result<()> {
|
||||
fn broadcast(
|
||||
server_cipher: &Cipher,
|
||||
multicast_members: Option<Arc<RwLock<Multicast>>>,
|
||||
sender: &ChannelSender,
|
||||
net_packet: &mut NetPacket<&mut [u8]>,
|
||||
current_device: &CurrentDeviceInfo,
|
||||
) -> Result<()> {
|
||||
let mut peer_ips = Vec::with_capacity(8);
|
||||
let vec = sender.route_table_one();
|
||||
let mut relay_count = 0;
|
||||
const MAX_COUNT: usize = u8::MAX as usize;
|
||||
const MAX_COUNT: usize = 8;
|
||||
for (peer_ip, route) in vec {
|
||||
if peer_ip == current_device.virtual_gateway {
|
||||
continue;
|
||||
@@ -30,8 +41,16 @@ async fn broadcast(sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]>
|
||||
if peer_ips.len() == MAX_COUNT {
|
||||
break;
|
||||
}
|
||||
if let Some(members) = &multicast_members {
|
||||
if !members.read().is_send(&peer_ip) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if route.is_p2p()
|
||||
&& sender.send_by_key(&net_packet.buffer()[..data_len], &route.route_key()).await.is_ok() {
|
||||
&& sender
|
||||
.try_send_by_key(net_packet.buffer(), &route.route_key())
|
||||
.is_ok()
|
||||
{
|
||||
peer_ips.push(peer_ip);
|
||||
} else {
|
||||
relay_count += 1;
|
||||
@@ -41,78 +60,58 @@ async fn broadcast(sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]>
|
||||
//不需要转发
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
//转发到服务端的可选择广播,还要进行服务端加密
|
||||
if peer_ips.is_empty() {
|
||||
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
|
||||
sender.send_main(net_packet.buffer(), current_device.connect_server)?;
|
||||
} else {
|
||||
let end_len = 1 + peer_ips.len() * 4;
|
||||
let buf = vec![
|
||||
0 as u8;
|
||||
12 + 1 + peer_ips.len() * 4 + net_packet.data_len() + ENCRYPTION_RESERVED
|
||||
];
|
||||
//剩余的发送到服务端,需要告知哪些已发送过
|
||||
//放在末尾可以减少复制次数
|
||||
let mut broadcast = BroadcastPacketEnd::unchecked(&mut net_packet.buffer_mut()[data_len..data_len + end_len]);
|
||||
broadcast.set_address(&peer_ips)?;
|
||||
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4Broadcast.into());
|
||||
sender.send_main(&net_packet.buffer()[..(data_len + end_len)], current_device.connect_server).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
let mut server_packet = NetPacket::new_encrypt(buf)?;
|
||||
server_packet.set_version(Version::V1);
|
||||
server_packet.set_gateway_flag(true);
|
||||
server_packet.first_set_ttl(MAX_TTL);
|
||||
server_packet.set_source(net_packet.source());
|
||||
//使用对应的目的地址
|
||||
server_packet.set_destination(net_packet.destination());
|
||||
server_packet.set_protocol(protocol::Protocol::IpTurn);
|
||||
server_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4Broadcast.into());
|
||||
|
||||
async fn multicast(igmp_server: &IgmpServer, multicast_addr: Ipv4Addr, sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]>, data_len: usize, current_device: &CurrentDeviceInfo) -> Result<()> {
|
||||
let mut peer_ips = Vec::with_capacity(8);
|
||||
let vec = sender.route_table_one();
|
||||
let mut relay_count = 0;
|
||||
const MAX_COUNT: usize = u8::MAX as usize;
|
||||
if let Some(members) = igmp_server.load(&multicast_addr) {
|
||||
for (peer_ip, route) in vec {
|
||||
if peer_ip == current_device.virtual_gateway {
|
||||
continue;
|
||||
}
|
||||
let is_send = { members.read().is_send(&peer_ip) };
|
||||
if is_send {
|
||||
if peer_ips.len() == MAX_COUNT {
|
||||
break;
|
||||
}
|
||||
if route.is_p2p()
|
||||
&& sender.send_by_key(&net_packet.buffer()[..data_len], &route.route_key()).await.is_ok() {
|
||||
peer_ips.push(peer_ip);
|
||||
} else {
|
||||
relay_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if relay_count == 0 && !peer_ips.is_empty() && peer_ips.len() != MAX_COUNT {
|
||||
//不需要转发
|
||||
return Ok(());
|
||||
}
|
||||
if peer_ips.is_empty() {
|
||||
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
|
||||
} else {
|
||||
let end_len = 1 + peer_ips.len() * 4;
|
||||
//剩余的发送到服务端,需要告知哪些已发送过
|
||||
//放在末尾可以减少复制次数
|
||||
let mut broadcast = BroadcastPacketEnd::unchecked(&mut net_packet.buffer_mut()[data_len..data_len + end_len]);
|
||||
let mut broadcast = BroadcastPacket::unchecked(server_packet.payload_mut());
|
||||
broadcast.set_address(&peer_ips)?;
|
||||
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4Broadcast.into());
|
||||
sender.send_main(&net_packet.buffer()[..(data_len + end_len)], current_device.connect_server).await?;
|
||||
broadcast.set_data(net_packet.buffer())?;
|
||||
server_cipher.encrypt_ipv4(&mut server_packet)?;
|
||||
sender.send_main(server_packet.buffer(), current_device.connect_server)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 实现一个原地发送,必须保证是如下结构
|
||||
/// |12字节开头|ip报文|至少1024字节+12字节结尾|
|
||||
/// |12字节开头|ip报文|至少1024字节结尾|
|
||||
///
|
||||
#[inline]
|
||||
pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8],
|
||||
mut data_len: usize,//数据总长度=ip长度+12
|
||||
igmp_server: &Option<IgmpServer>,
|
||||
current_device: CurrentDeviceInfo,
|
||||
ip_route: &Option<ExternalRoute>, proxy_map: &Option<IpProxyMap>, cipher: &Cipher) -> Result<()> {
|
||||
pub fn base_handle(
|
||||
sender: &ChannelSender,
|
||||
buf: &mut [u8],
|
||||
data_len: usize, //数据总长度=12+ip包长度
|
||||
igmp_server: &Option<IgmpServer>,
|
||||
current_device: CurrentDeviceInfo,
|
||||
ip_route: &Option<ExternalRoute>,
|
||||
proxy_map: &Option<IpProxyMap>,
|
||||
client_cipher: &Cipher,
|
||||
server_cipher: &Cipher,
|
||||
) -> Result<()> {
|
||||
let ipv4_packet = IpV4Packet::new(&buf[12..data_len])?;
|
||||
let protocol = ipv4_packet.protocol();
|
||||
let ip_head_len = ipv4_packet.header_len() as usize * 4;
|
||||
if 12 + ip_head_len >= data_len {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "ip_head_len err"))?
|
||||
}
|
||||
let src_ip = ipv4_packet.source_ip();
|
||||
let mut dest_ip = ipv4_packet.destination_ip();
|
||||
let mut net_packet = NetPacket::new(buf)?;
|
||||
let mut net_packet = NetPacket::new0(data_len, buf)?;
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_protocol(protocol::Protocol::IpTurn);
|
||||
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4.into());
|
||||
@@ -121,9 +120,9 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8],
|
||||
net_packet.set_destination(dest_ip);
|
||||
if dest_ip == current_device.virtual_gateway {
|
||||
if protocol == Protocol::Icmp {
|
||||
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Icmp.into());
|
||||
//发送到服务端的不加密
|
||||
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
|
||||
net_packet.set_gateway_flag(true);
|
||||
server_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||
sender.send_main(net_packet.buffer(), current_device.connect_server)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
@@ -131,42 +130,51 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8],
|
||||
match protocol {
|
||||
Protocol::Igmp => {
|
||||
if igmp_server.is_some() {
|
||||
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Igmp.into());
|
||||
//发送到服务端
|
||||
net_packet.set_destination(current_device.virtual_gateway);
|
||||
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
|
||||
net_packet.set_gateway_flag(true);
|
||||
server_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||
sender.send_main(net_packet.buffer(), current_device.connect_server)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
Protocol::Udp => {
|
||||
if let Some(igmp_server) = igmp_server {
|
||||
if let Some(len) = cipher.encrypt_ipv4(data_len - 12, &mut net_packet)? {
|
||||
data_len = 12 + len;
|
||||
}
|
||||
multicast(igmp_server, dest_ip, sender, &mut net_packet, data_len, ¤t_device).await?;
|
||||
return Ok(());
|
||||
let multicast_members = if let Some(igmp_server) = igmp_server {
|
||||
igmp_server.load(&dest_ip)
|
||||
} else {
|
||||
//当广播
|
||||
dest_ip = Ipv4Addr::BROADCAST;
|
||||
net_packet.set_destination(dest_ip);
|
||||
}
|
||||
//当作广播处理
|
||||
net_packet.set_destination(Ipv4Addr::BROADCAST);
|
||||
None
|
||||
};
|
||||
client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||
broadcast(
|
||||
server_cipher,
|
||||
multicast_members,
|
||||
sender,
|
||||
&mut net_packet,
|
||||
¤t_device,
|
||||
)?;
|
||||
}
|
||||
_ => {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
if dest_ip.is_broadcast() || current_device.broadcast_address == dest_ip {
|
||||
// 广播 发送到直连目标
|
||||
if Protocol::Udp == protocol {
|
||||
if let Some(len) = cipher.encrypt_ipv4(data_len - 12, &mut net_packet)? {
|
||||
data_len = 12 + len;
|
||||
}
|
||||
broadcast(sender, &mut net_packet, data_len, ¤t_device).await?;
|
||||
_ => {}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
if !check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) {
|
||||
if dest_ip.is_broadcast() || current_device.broadcast_address == dest_ip {
|
||||
// 广播 发送到直连目标
|
||||
client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||
broadcast(
|
||||
server_cipher,
|
||||
None,
|
||||
sender,
|
||||
&mut net_packet,
|
||||
¤t_device,
|
||||
)?;
|
||||
return Ok(());
|
||||
}
|
||||
if !check_dest(
|
||||
dest_ip,
|
||||
current_device.virtual_netmask,
|
||||
current_device.virtual_network,
|
||||
) {
|
||||
if let Some(ip_route) = ip_route {
|
||||
if let Some(r_dest_ip) = ip_route.route(&dest_ip) {
|
||||
//路由的目标不能是自己
|
||||
@@ -186,32 +194,48 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8],
|
||||
match protocol {
|
||||
Protocol::Tcp => {
|
||||
let dest_addr = {
|
||||
let tcp_packet = TcpPacket::new(src_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?;
|
||||
let tcp_packet = TcpPacket::new(
|
||||
src_ip,
|
||||
dest_ip,
|
||||
&mut net_packet.payload_mut()[ip_head_len..],
|
||||
)?;
|
||||
SocketAddrV4::new(dest_ip, tcp_packet.destination_port())
|
||||
};
|
||||
if let Some(entry) = proxy_map.tcp_proxy_map.get(&dest_addr) {
|
||||
let source_addr = entry.value().1;
|
||||
let source_addr = entry.value();
|
||||
let source_ip = *source_addr.ip();
|
||||
let mut tcp_packet = TcpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?;
|
||||
let mut tcp_packet = TcpPacket::new(
|
||||
source_ip,
|
||||
dest_ip,
|
||||
&mut net_packet.payload_mut()[ip_head_len..],
|
||||
)?;
|
||||
tcp_packet.set_source_port(source_addr.port());
|
||||
tcp_packet.update_checksum();
|
||||
let mut ipv4_packet = IpV4Packet::new(&mut net_packet.buffer_mut()[12..data_len])?;
|
||||
let mut ipv4_packet = IpV4Packet::new(net_packet.payload_mut())?;
|
||||
ipv4_packet.set_source_ip(source_ip);
|
||||
ipv4_packet.update_checksum();
|
||||
}
|
||||
}
|
||||
Protocol::Udp => {
|
||||
let dest_addr = {
|
||||
let udp_packet = UdpPacket::new(src_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?;
|
||||
let udp_packet = UdpPacket::new(
|
||||
src_ip,
|
||||
dest_ip,
|
||||
&mut net_packet.payload_mut()[ip_head_len..],
|
||||
)?;
|
||||
SocketAddrV4::new(dest_ip, udp_packet.destination_port())
|
||||
};
|
||||
if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) {
|
||||
let source_addr = entry.value().1;
|
||||
let source_addr = entry.value();
|
||||
let source_ip = *source_addr.ip();
|
||||
let mut udp_packet = UdpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?;
|
||||
let mut udp_packet = UdpPacket::new(
|
||||
source_ip,
|
||||
dest_ip,
|
||||
&mut net_packet.payload_mut()[ip_head_len..],
|
||||
)?;
|
||||
udp_packet.set_source_port(source_addr.port());
|
||||
udp_packet.update_checksum();
|
||||
let mut ipv4_packet = IpV4Packet::new(&mut net_packet.buffer_mut()[12..data_len])?;
|
||||
let mut ipv4_packet = IpV4Packet::new(net_packet.payload_mut())?;
|
||||
ipv4_packet.set_source_ip(source_ip);
|
||||
ipv4_packet.update_checksum();
|
||||
}
|
||||
@@ -219,13 +243,13 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8],
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if let Some(len) = cipher.encrypt_ipv4(data_len - 12, &mut net_packet)? {
|
||||
data_len = 12 + len;
|
||||
}
|
||||
|
||||
client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||
//优先发到直连到地址
|
||||
if sender.send_by_id(&net_packet.buffer()[..data_len], &dest_ip).await.is_err() {
|
||||
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
|
||||
if sender
|
||||
.try_send_by_id(net_packet.buffer(), &dest_ip)
|
||||
.is_err()
|
||||
{
|
||||
sender.send_main(net_packet.buffer(), current_device.connect_server)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use std::{io, thread};
|
||||
use byte_pool::BytePool;
|
||||
use std::sync::Arc;
|
||||
use std::{io, thread};
|
||||
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use packet::arp::arp::ArpPacket;
|
||||
use packet::ethernet;
|
||||
@@ -15,58 +17,169 @@ use crate::channel::sender::ChannelSender;
|
||||
use crate::cipher::Cipher;
|
||||
use crate::core::status::VntWorker;
|
||||
use crate::external_route::ExternalRoute;
|
||||
use crate::handle::tun_tap::channel_group::{buf_channel_group, BufSenderGroup};
|
||||
use crate::handle::CurrentDeviceInfo;
|
||||
use crate::igmp_server::IgmpServer;
|
||||
use crate::ip_proxy::IpProxyMap;
|
||||
use crate::tun_tap_device::{DeviceReader, DeviceWriter};
|
||||
|
||||
pub fn start(worker: VntWorker, sender: ChannelSender,
|
||||
device_reader: DeviceReader,
|
||||
device_writer: DeviceWriter,
|
||||
igmp_server: Option<IgmpServer>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
ip_route: Option<ExternalRoute>,
|
||||
ip_proxy_map: Option<IpProxyMap>,
|
||||
cipher: Cipher) {
|
||||
thread::Builder::new().name("tap_handler".into()).spawn(move || {
|
||||
tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all().build().unwrap()
|
||||
.block_on(async move {
|
||||
if let Err(e) = start_(sender, device_reader,
|
||||
device_writer, igmp_server,
|
||||
current_device, ip_route, ip_proxy_map, cipher).await {
|
||||
log::warn!("tap:{:?}",e);
|
||||
}
|
||||
worker.stop_all();
|
||||
});
|
||||
}).unwrap();
|
||||
lazy_static! {
|
||||
static ref POOL: BytePool<Vec<u8>> = BytePool::<Vec<u8>>::new();
|
||||
}
|
||||
|
||||
async fn start_(sender: ChannelSender,
|
||||
device_reader: DeviceReader,
|
||||
device_writer: DeviceWriter,
|
||||
igmp_server: Option<IgmpServer>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
ip_route: Option<ExternalRoute>,
|
||||
ip_proxy_map: Option<IpProxyMap>,
|
||||
cipher: Cipher) -> io::Result<()> {
|
||||
let mut buf = [0; 4096];
|
||||
pub fn start(
|
||||
worker: VntWorker,
|
||||
sender: ChannelSender,
|
||||
device_reader: DeviceReader,
|
||||
device_writer: DeviceWriter,
|
||||
igmp_server: Option<IgmpServer>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
ip_route: Option<ExternalRoute>,
|
||||
ip_proxy_map: Option<IpProxyMap>,
|
||||
client_cipher: Cipher,
|
||||
server_cipher: Cipher,
|
||||
parallel: usize,
|
||||
) {
|
||||
if parallel == 1 {
|
||||
thread::Builder::new()
|
||||
.name("tap_handler".into())
|
||||
.spawn(move || {
|
||||
if let Err(e) = start_simple(
|
||||
&sender,
|
||||
device_reader,
|
||||
&device_writer,
|
||||
igmp_server,
|
||||
current_device,
|
||||
ip_route,
|
||||
ip_proxy_map,
|
||||
client_cipher,
|
||||
server_cipher,
|
||||
) {
|
||||
log::warn!("tap:{:?}", e);
|
||||
}
|
||||
let _ = sender.close();
|
||||
let _ = device_writer.close();
|
||||
worker.stop_all();
|
||||
})
|
||||
.unwrap();
|
||||
} else {
|
||||
let (buf_sender, buf_receiver) = buf_channel_group(parallel);
|
||||
for buf_receiver in buf_receiver.0 {
|
||||
let sender = sender.clone();
|
||||
let device_writer = device_writer.clone();
|
||||
let igmp_server = igmp_server.clone();
|
||||
let current_device = current_device.clone();
|
||||
let ip_route = ip_route.clone();
|
||||
let ip_proxy_map = ip_proxy_map.clone();
|
||||
let client_cipher = client_cipher.clone();
|
||||
let server_cipher = server_cipher.clone();
|
||||
thread::spawn(move || {
|
||||
while let Ok((mut buf, _, len)) = buf_receiver.recv() {
|
||||
match handle(
|
||||
&mut buf,
|
||||
len,
|
||||
&igmp_server,
|
||||
¤t_device,
|
||||
&device_writer,
|
||||
&sender,
|
||||
&ip_route,
|
||||
&ip_proxy_map,
|
||||
&client_cipher,
|
||||
&server_cipher,
|
||||
) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("{:?}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
let _ = sender.close();
|
||||
let _ = device_writer.close();
|
||||
});
|
||||
}
|
||||
thread::Builder::new()
|
||||
.name("tap_handler".into())
|
||||
.spawn(move || {
|
||||
if let Err(e) = start_(&sender, device_reader, buf_sender) {
|
||||
log::warn!("tap:{:?}", e);
|
||||
}
|
||||
let _ = sender.close();
|
||||
let _ = device_writer.close();
|
||||
worker.stop_all();
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn start_(
|
||||
sender: &ChannelSender,
|
||||
device_reader: DeviceReader,
|
||||
mut buf_sender: BufSenderGroup,
|
||||
) -> io::Result<()> {
|
||||
loop {
|
||||
//ip拆包了会直接丢弃?
|
||||
let mut buf = POOL.alloc(4096);
|
||||
if sender.is_close() {
|
||||
return Ok(());
|
||||
}
|
||||
let start = 0;
|
||||
let len = device_reader.read(&mut buf)?;
|
||||
if let Err(e) = handle(&mut buf, len, &igmp_server, ¤t_device, &device_writer, &sender, &ip_route, &ip_proxy_map, &cipher).await {
|
||||
log::warn!("tap handle{:?}",e);
|
||||
if !buf_sender.send((buf, start, len)) {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"tap buf_sender发送失败",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle(buf: &mut [u8], len: usize, igmp_server: &Option<IgmpServer>, current_device: &AtomicCell<CurrentDeviceInfo>,
|
||||
device_writer: &DeviceWriter, sender: &ChannelSender, ip_route: &Option<ExternalRoute>, proxy_map: &Option<IpProxyMap>, cipher: &Cipher) -> crate::Result<()> {
|
||||
fn start_simple(
|
||||
sender: &ChannelSender,
|
||||
device_reader: DeviceReader,
|
||||
device_writer: &DeviceWriter,
|
||||
igmp_server: Option<IgmpServer>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
ip_route: Option<ExternalRoute>,
|
||||
ip_proxy_map: Option<IpProxyMap>,
|
||||
client_cipher: Cipher,
|
||||
server_cipher: Cipher,
|
||||
) -> io::Result<()> {
|
||||
let mut buf = [0; 4096];
|
||||
loop {
|
||||
let len = device_reader.read(&mut buf)?;
|
||||
if let Err(e) = handle(
|
||||
&mut buf,
|
||||
len,
|
||||
&igmp_server,
|
||||
¤t_device,
|
||||
device_writer,
|
||||
sender,
|
||||
&ip_route,
|
||||
&ip_proxy_map,
|
||||
&client_cipher,
|
||||
&server_cipher,
|
||||
) {
|
||||
log::warn!("tap handle{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle(
|
||||
buf: &mut [u8],
|
||||
len: usize,
|
||||
igmp_server: &Option<IgmpServer>,
|
||||
current_device: &AtomicCell<CurrentDeviceInfo>,
|
||||
device_writer: &DeviceWriter,
|
||||
sender: &ChannelSender,
|
||||
ip_route: &Option<ExternalRoute>,
|
||||
proxy_map: &Option<IpProxyMap>,
|
||||
client_cipher: &Cipher,
|
||||
server_cipher: &Cipher,
|
||||
) -> crate::Result<()> {
|
||||
let mut ethernet_packet = EthernetPacket::new(&mut buf[..len])?;
|
||||
let current_device = current_device.load();
|
||||
match ethernet_packet.protocol() {
|
||||
ethernet::protocol::Protocol::Arp => {
|
||||
let mut out_ethernet_packet = EthernetPacket::unchecked(ethernet_packet.buffer.to_vec());
|
||||
let mut out_ethernet_packet =
|
||||
EthernetPacket::unchecked(ethernet_packet.buffer.to_vec());
|
||||
let arp_packet = ArpPacket::unchecked(ethernet_packet.payload());
|
||||
let mut out_arp_packet = ArpPacket::unchecked(out_ethernet_packet.payload_mut());
|
||||
let sender_h = arp_packet.sender_hardware_addr();
|
||||
@@ -76,12 +189,26 @@ async fn handle(buf: &mut [u8], len: usize, igmp_server: &Option<IgmpServer>, cu
|
||||
return Ok(());
|
||||
}
|
||||
//回复一个虚假的MAC地址
|
||||
out_arp_packet.set_sender_hardware_addr(&[target_p[0], target_p[1], target_p[2], target_p[3], !sender_h[5], 234]);
|
||||
out_arp_packet.set_sender_hardware_addr(&[
|
||||
target_p[0],
|
||||
target_p[1],
|
||||
target_p[2],
|
||||
target_p[3],
|
||||
!sender_h[5],
|
||||
234,
|
||||
]);
|
||||
out_arp_packet.set_sender_protocol_addr(target_p);
|
||||
out_arp_packet.set_target_hardware_addr(sender_h);
|
||||
out_arp_packet.set_target_protocol_addr(sender_p);
|
||||
out_arp_packet.set_op_code(2);
|
||||
out_ethernet_packet.set_source(&[target_p[0], target_p[1], target_p[2], target_p[3], !sender_h[5], 234]);
|
||||
out_ethernet_packet.set_source(&[
|
||||
target_p[0],
|
||||
target_p[1],
|
||||
target_p[2],
|
||||
target_p[3],
|
||||
!sender_h[5],
|
||||
234,
|
||||
]);
|
||||
out_ethernet_packet.set_destination(sender_h);
|
||||
device_writer.write_ethernet_tap(&out_ethernet_packet.buffer)?;
|
||||
}
|
||||
@@ -112,8 +239,17 @@ async fn handle(buf: &mut [u8], len: usize, igmp_server: &Option<IgmpServer>, cu
|
||||
return Ok(());
|
||||
}
|
||||
// 以太网帧头部14字节,预留12字节
|
||||
return crate::handle::tun_tap::base_handle(sender, &mut buf[2..], len - 2, igmp_server, current_device,
|
||||
ip_route, proxy_map, cipher).await;
|
||||
return crate::handle::tun_tap::base_handle(
|
||||
sender,
|
||||
&mut buf[2..],
|
||||
len - 2,
|
||||
igmp_server,
|
||||
current_device,
|
||||
ip_route,
|
||||
proxy_map,
|
||||
client_cipher,
|
||||
server_cipher,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
// log::warn!("不支持的二层协议:{:?}",p)
|
||||
@@ -121,4 +257,3 @@ async fn handle(buf: &mut [u8], len: usize, igmp_server: &Option<IgmpServer>, cu
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
use std::{io, thread};
|
||||
use byte_pool::BytePool;
|
||||
use std::sync::Arc;
|
||||
use std::{io, thread};
|
||||
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
|
||||
use packet::icmp::Kind;
|
||||
use packet::icmp::icmp::IcmpPacket;
|
||||
use packet::ip::ipv4;
|
||||
use packet::ip::ipv4::packet::IpV4Packet;
|
||||
use crate::channel::sender::ChannelSender;
|
||||
use crate::cipher::Cipher;
|
||||
use crate::core::status::VntWorker;
|
||||
use packet::icmp::icmp::IcmpPacket;
|
||||
use packet::icmp::Kind;
|
||||
use packet::ip::ipv4;
|
||||
use packet::ip::ipv4::packet::IpV4Packet;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::external_route::ExternalRoute;
|
||||
use crate::handle::tun_tap::channel_group::{buf_channel_group, BufSenderGroup};
|
||||
use crate::handle::CurrentDeviceInfo;
|
||||
use crate::igmp_server::IgmpServer;
|
||||
use crate::ip_proxy::IpProxyMap;
|
||||
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<()> {
|
||||
if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp {
|
||||
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
|
||||
@@ -36,8 +40,18 @@ fn icmp(device_writer: &DeviceWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) ->
|
||||
|
||||
/// 接收tun数据,并且转发到udp上
|
||||
#[inline]
|
||||
async fn handle(sender: &ChannelSender, data: &mut [u8], len: usize, device_writer: &DeviceWriter, igmp_server: &Option<IgmpServer>, current_device: CurrentDeviceInfo,
|
||||
ip_route: &Option<ExternalRoute>, proxy_map: &Option<IpProxyMap>, cipher: &Cipher) -> Result<()> {
|
||||
fn handle(
|
||||
sender: &ChannelSender,
|
||||
data: &mut [u8],
|
||||
len: usize,
|
||||
device_writer: &DeviceWriter,
|
||||
igmp_server: &Option<IgmpServer>,
|
||||
current_device: CurrentDeviceInfo,
|
||||
ip_route: &Option<ExternalRoute>,
|
||||
proxy_map: &Option<IpProxyMap>,
|
||||
client_cipher: &Cipher,
|
||||
server_cipher: &Cipher,
|
||||
) -> Result<()> {
|
||||
let ipv4_packet = if let Ok(ipv4_packet) = IpV4Packet::new(&mut data[12..len]) {
|
||||
ipv4_packet
|
||||
} else {
|
||||
@@ -51,47 +65,160 @@ async fn handle(sender: &ChannelSender, data: &mut [u8], len: usize, device_writ
|
||||
if src_ip == dest_ip {
|
||||
return icmp(&device_writer, ipv4_packet);
|
||||
}
|
||||
return crate::handle::tun_tap::base_handle(sender, data, len, igmp_server, current_device, ip_route, proxy_map, cipher).await;
|
||||
return crate::handle::tun_tap::base_handle(
|
||||
sender,
|
||||
data,
|
||||
len,
|
||||
igmp_server,
|
||||
current_device,
|
||||
ip_route,
|
||||
proxy_map,
|
||||
client_cipher,
|
||||
server_cipher,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn start(worker: VntWorker, sender: ChannelSender,
|
||||
device_reader: DeviceReader,
|
||||
device_writer: DeviceWriter,
|
||||
igmp_server: Option<IgmpServer>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
ip_route: Option<ExternalRoute>,
|
||||
ip_proxy_map: Option<IpProxyMap>,
|
||||
cipher: Cipher) {
|
||||
thread::Builder::new().name("tun_handler".into()).spawn(move || {
|
||||
tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all().build().unwrap()
|
||||
.block_on(async move {
|
||||
if let Err(e) = start_(sender, device_reader, &device_writer, igmp_server, current_device, ip_route, ip_proxy_map, cipher).await {
|
||||
log::warn!("stop:{}",e);
|
||||
pub fn start(
|
||||
worker: VntWorker,
|
||||
sender: ChannelSender,
|
||||
device_reader: DeviceReader,
|
||||
device_writer: DeviceWriter,
|
||||
igmp_server: Option<IgmpServer>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
ip_route: Option<ExternalRoute>,
|
||||
ip_proxy_map: Option<IpProxyMap>,
|
||||
client_cipher: Cipher,
|
||||
server_cipher: Cipher,
|
||||
parallel: usize,
|
||||
) {
|
||||
if parallel == 1 {
|
||||
thread::Builder::new()
|
||||
.name("tun_handler".into())
|
||||
.spawn(move || {
|
||||
if let Err(e) = start_simple(
|
||||
&sender,
|
||||
device_reader,
|
||||
&device_writer,
|
||||
igmp_server,
|
||||
current_device,
|
||||
ip_route,
|
||||
ip_proxy_map,
|
||||
client_cipher,
|
||||
server_cipher,
|
||||
) {
|
||||
log::warn!("stop:{}", e);
|
||||
}
|
||||
let _ = sender.close();
|
||||
let _ = device_writer.close();
|
||||
worker.stop_all();
|
||||
})
|
||||
}).unwrap();
|
||||
.unwrap();
|
||||
} else {
|
||||
let (buf_sender, buf_receiver) = buf_channel_group(parallel);
|
||||
for buf_receiver in buf_receiver.0 {
|
||||
let sender = sender.clone();
|
||||
let device_writer = device_writer.clone();
|
||||
let igmp_server = igmp_server.clone();
|
||||
let current_device = current_device.clone();
|
||||
let ip_route = ip_route.clone();
|
||||
let ip_proxy_map = ip_proxy_map.clone();
|
||||
let client_cipher = client_cipher.clone();
|
||||
let server_cipher = server_cipher.clone();
|
||||
thread::spawn(move || {
|
||||
while let Ok((mut buf, start, len)) = buf_receiver.recv() {
|
||||
match handle(
|
||||
&sender,
|
||||
&mut buf[start..],
|
||||
len,
|
||||
&device_writer,
|
||||
&igmp_server,
|
||||
current_device.load(),
|
||||
&ip_route,
|
||||
&ip_proxy_map,
|
||||
&client_cipher,
|
||||
&server_cipher,
|
||||
) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("{:?}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
let _ = sender.close();
|
||||
let _ = device_writer.close();
|
||||
});
|
||||
}
|
||||
|
||||
thread::Builder::new()
|
||||
.name("tun_handler".into())
|
||||
.spawn(move || {
|
||||
if let Err(e) = start_(&sender, device_reader, buf_sender) {
|
||||
log::warn!("stop:{}", e);
|
||||
}
|
||||
let _ = sender.close();
|
||||
let _ = device_writer.close();
|
||||
worker.stop_all();
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
async fn start_(sender: ChannelSender,
|
||||
device_reader: DeviceReader,
|
||||
device_writer: &DeviceWriter,
|
||||
igmp_server: Option<IgmpServer>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
ip_route: Option<ExternalRoute>,
|
||||
ip_proxy_map: Option<IpProxyMap>,
|
||||
cipher: Cipher) -> io::Result<()> {
|
||||
fn start_(
|
||||
sender: &ChannelSender,
|
||||
device_reader: DeviceReader,
|
||||
mut buf_sender: BufSenderGroup,
|
||||
) -> io::Result<()> {
|
||||
loop {
|
||||
let mut buf = POOL.alloc(4096);
|
||||
buf[..12].fill(0);
|
||||
if sender.is_close() {
|
||||
return Ok(());
|
||||
}
|
||||
let start = 0;
|
||||
let len = device_reader.read(&mut buf[12..])? + 12;
|
||||
#[cfg(any(target_os = "macos"))]
|
||||
let start = 4;
|
||||
if !buf_sender.send((buf, start, len)) {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"tun buf_sender发送失败",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn start_simple(
|
||||
sender: &ChannelSender,
|
||||
device_reader: DeviceReader,
|
||||
device_writer: &DeviceWriter,
|
||||
igmp_server: Option<IgmpServer>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
ip_route: Option<ExternalRoute>,
|
||||
ip_proxy_map: Option<IpProxyMap>,
|
||||
client_cipher: Cipher,
|
||||
server_cipher: Cipher,
|
||||
) -> io::Result<()> {
|
||||
let mut buf = [0; 4096];
|
||||
loop {
|
||||
if sender.is_close() {
|
||||
return Ok(());
|
||||
}
|
||||
buf[..12].fill(0);
|
||||
let len = device_reader.read(&mut buf[12..])? + 12;
|
||||
#[cfg(any(target_os = "macos"))]
|
||||
let mut buf = &mut buf[4..];
|
||||
match handle(&sender, &mut buf, len, device_writer, &igmp_server, current_device.load(), &ip_route, &ip_proxy_map, &cipher).await {
|
||||
let mut buf = &mut buf[4..];
|
||||
match handle(
|
||||
sender,
|
||||
&mut buf,
|
||||
len,
|
||||
device_writer,
|
||||
&igmp_server,
|
||||
current_device.load(),
|
||||
&ip_route,
|
||||
&ip_proxy_map,
|
||||
&client_cipher,
|
||||
&server_cipher,
|
||||
) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("{:?}", e)
|
||||
|
||||
+46
-39
@@ -2,12 +2,16 @@ use std::collections::{HashMap, HashSet};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
|
||||
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分钟一次
|
||||
@@ -47,12 +51,12 @@ impl Multicast {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct IgmpServer {
|
||||
multicast: Arc<SkipMap<Ipv4Addr, Arc<RwLock<Multicast>>>>,
|
||||
multicast: Arc<DashMap<Ipv4Addr, Arc<RwLock<Multicast>>>>,
|
||||
}
|
||||
|
||||
impl IgmpServer {
|
||||
pub fn new(device_writer: DeviceWriter) -> Self {
|
||||
let multicast: Arc<SkipMap<Ipv4Addr, Arc<RwLock<Multicast>>>> = Arc::new(SkipMap::new());
|
||||
let multicast: Arc<DashMap<Ipv4Addr, Arc<RwLock<Multicast>>>> = Arc::new(DashMap::new0());
|
||||
std::thread::spawn(move || {
|
||||
//预留以太网帧头和ip头
|
||||
let mut buf = [0; 14 + 24 + 12];
|
||||
@@ -90,9 +94,7 @@ impl IgmpServer {
|
||||
std::thread::sleep(Duration::from_secs(20))
|
||||
}
|
||||
});
|
||||
Self {
|
||||
multicast,
|
||||
}
|
||||
Self { multicast }
|
||||
}
|
||||
pub fn load(&self, multicast_addr: &Ipv4Addr) -> Option<Arc<RwLock<Multicast>>> {
|
||||
if let Some(entry) = self.multicast.get(multicast_addr) {
|
||||
@@ -124,10 +126,14 @@ impl IgmpServer {
|
||||
if !multicast_addr.is_multicast() {
|
||||
return Ok(());
|
||||
}
|
||||
let multi = self.multicast.get_or_insert_with(multicast_addr, || {
|
||||
Arc::new(RwLock::new(Multicast::new()))
|
||||
});
|
||||
let mut guard = multi.value().write();
|
||||
let multi = {
|
||||
self.multicast
|
||||
.entry(multicast_addr)
|
||||
.or_insert_with(|| Arc::new(RwLock::new(Multicast::new())))
|
||||
.value()
|
||||
.clone()
|
||||
};
|
||||
let mut guard = multi.write();
|
||||
guard.members.insert(source, Instant::now());
|
||||
}
|
||||
IgmpType::LeaveV2 => {
|
||||
@@ -151,13 +157,17 @@ impl IgmpServer {
|
||||
if !multicast_addr.is_multicast() {
|
||||
return Ok(());
|
||||
}
|
||||
let multi = self.multicast.get_or_insert_with(multicast_addr, || {
|
||||
Arc::new(RwLock::new(Multicast::new()))
|
||||
});
|
||||
let mut guard = multi.value().write();
|
||||
let multi = self
|
||||
.multicast
|
||||
.entry(multicast_addr)
|
||||
.or_insert_with(|| Arc::new(RwLock::new(Multicast::new())))
|
||||
.value()
|
||||
.clone();
|
||||
let mut guard = multi.write();
|
||||
|
||||
match group_record.record_type() {
|
||||
IgmpV3RecordType::ModeIsInclude | IgmpV3RecordType::ChangeToIncludeMode => {
|
||||
IgmpV3RecordType::ModeIsInclude
|
||||
| IgmpV3RecordType::ChangeToIncludeMode => {
|
||||
match group_record.source_addresses() {
|
||||
None => {
|
||||
//不接收所有
|
||||
@@ -171,7 +181,8 @@ impl IgmpServer {
|
||||
}
|
||||
}
|
||||
|
||||
IgmpV3RecordType::ModeIsExclude | IgmpV3RecordType::ChangeToExcludeMode => {
|
||||
IgmpV3RecordType::ModeIsExclude
|
||||
| IgmpV3RecordType::ChangeToExcludeMode => {
|
||||
match group_record.source_addresses() {
|
||||
None => {
|
||||
//接收所有
|
||||
@@ -188,40 +199,36 @@ impl IgmpServer {
|
||||
//在已有源的基础上,接收目标源,如果是排除模式,则删除;是包含模式则添加
|
||||
match group_record.source_addresses() {
|
||||
None => {}
|
||||
Some(src) => {
|
||||
match guard.map.get_mut(&source) {
|
||||
None => {}
|
||||
Some((is_include, set)) => {
|
||||
for ip in src {
|
||||
if *is_include {
|
||||
set.insert(ip);
|
||||
} else {
|
||||
set.remove(&ip);
|
||||
}
|
||||
Some(src) => match guard.map.get_mut(&source) {
|
||||
None => {}
|
||||
Some((is_include, set)) => {
|
||||
for ip in src {
|
||||
if *is_include {
|
||||
set.insert(ip);
|
||||
} else {
|
||||
set.remove(&ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
IgmpV3RecordType::BlockOldSources => {
|
||||
//在已有源的基础上,不接收目标源
|
||||
match group_record.source_addresses() {
|
||||
None => {}
|
||||
Some(src) => {
|
||||
match guard.map.get_mut(&source) {
|
||||
None => {}
|
||||
Some((is_include, set)) => {
|
||||
for ip in src {
|
||||
if *is_include {
|
||||
set.remove(&ip);
|
||||
} else {
|
||||
set.insert(ip);
|
||||
}
|
||||
Some(src) => match guard.map.get_mut(&source) {
|
||||
None => {}
|
||||
Some((is_include, set)) => {
|
||||
for ip in src {
|
||||
if *is_include {
|
||||
set.remove(&ip);
|
||||
} else {
|
||||
set.insert(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
IgmpV3RecordType::Unknown(_) => {}
|
||||
@@ -233,4 +240,4 @@ impl IgmpServer {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,60 +1,50 @@
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use dashmap::DashMap;
|
||||
use std::io;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use socket2::{Domain, SockAddr, Socket, Type};
|
||||
|
||||
use crate::channel::sender::ChannelSender;
|
||||
use crate::cipher::Cipher;
|
||||
use crate::handle::CurrentDeviceInfo;
|
||||
use crate::protocol::body::ENCRYPTION_RESERVED;
|
||||
use crate::protocol::{NetPacket, Protocol, Version, MAX_TTL};
|
||||
use packet::icmp::icmp;
|
||||
use packet::icmp::icmp::HeaderOther;
|
||||
use packet::ip::ipv4;
|
||||
use crate::channel::sender::ChannelSender;
|
||||
use crate::handle::CurrentDeviceInfo;
|
||||
use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version};
|
||||
|
||||
pub struct IcmpProxy {
|
||||
icmp_socket: Arc<Socket>,
|
||||
// 对端-> 真实来源
|
||||
icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
|
||||
icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
|
||||
sender: ChannelSender,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
client_cipher: Cipher,
|
||||
}
|
||||
|
||||
impl IcmpProxy {
|
||||
pub fn new(addr: SocketAddrV4, icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>, sender: ChannelSender, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<IcmpProxy> {
|
||||
let icmp_socket = Arc::new(Socket::new(Domain::IPV4, Type::RAW, Some(socket2::Protocol::ICMPV4))?);
|
||||
pub fn new(
|
||||
addr: SocketAddrV4,
|
||||
icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
|
||||
sender: ChannelSender,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
client_cipher: Cipher,
|
||||
) -> io::Result<IcmpProxy> {
|
||||
let icmp_socket = Arc::new(Socket::new(
|
||||
Domain::IPV4,
|
||||
Type::RAW,
|
||||
Some(socket2::Protocol::ICMPV4),
|
||||
)?);
|
||||
icmp_socket.bind(&SockAddr::from(addr))?;
|
||||
// // 设置 SIO_RCVALL 参数
|
||||
// #[cfg(windows)]
|
||||
// {
|
||||
// use std::os::windows::io::AsRawSocket;
|
||||
// let raw_fd = icmp_socket.as_raw_socket();
|
||||
// let mut rcvall: winapi::shared::minwindef::DWORD = 1;
|
||||
// let mut bytes_returned: winapi::shared::minwindef::DWORD = 0;
|
||||
// let result = unsafe {
|
||||
// winapi::um::winsock2::WSAIoctl(
|
||||
// raw_fd as _,
|
||||
// winapi::shared::mstcpip::SIO_RCVALL,
|
||||
// &mut rcvall as *mut winapi::shared::minwindef::DWORD as *mut std::ffi::c_void,
|
||||
// std::mem::size_of::<winapi::shared::minwindef::DWORD>() as winapi::shared::minwindef::DWORD,
|
||||
// std::ptr::null_mut(),
|
||||
// 0,
|
||||
// &mut bytes_returned as winapi::shared::minwindef::LPDWORD,
|
||||
// std::ptr::null_mut(),
|
||||
// None,
|
||||
// )
|
||||
// };
|
||||
// if result != 0 {
|
||||
// return Err(io::Error::from_raw_os_error(unsafe { winapi::um::winsock2::WSAGetLastError() }));
|
||||
// }
|
||||
// }
|
||||
Ok(IcmpProxy {
|
||||
icmp_socket,
|
||||
icmp_proxy_map,
|
||||
sender,
|
||||
current_device,
|
||||
client_cipher,
|
||||
})
|
||||
}
|
||||
pub fn icmp_socket(&self) -> Arc<Socket> {
|
||||
@@ -62,13 +52,8 @@ impl IcmpProxy {
|
||||
}
|
||||
pub fn start(self) {
|
||||
let mut buf = [0 as u8; 1500];
|
||||
let data: &mut [MaybeUninit<u8>] =
|
||||
unsafe { std::mem::transmute(&mut buf[..]) };
|
||||
let mut net_packet = NetPacket::new([0u8; 4 + 8 + 1500]).unwrap();
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_protocol(Protocol::IpTurn);
|
||||
net_packet.set_transport_protocol(ipv4::protocol::Protocol::Icmp.into());
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
let data: &mut [MaybeUninit<u8>] = unsafe { std::mem::transmute(&mut buf[..]) };
|
||||
|
||||
loop {
|
||||
match self.recv(data) {
|
||||
Ok((len, peer_ip)) => {
|
||||
@@ -80,20 +65,54 @@ impl IcmpProxy {
|
||||
Ok(icmp_packet) => {
|
||||
match icmp_packet.header_other() {
|
||||
HeaderOther::Identifier(id, seq) => {
|
||||
if let Some(entry) = self.icmp_proxy_map.get(&(peer_ip, id, seq)) {
|
||||
if let Some(entry) =
|
||||
self.icmp_proxy_map.get(&(peer_ip, id, seq))
|
||||
{
|
||||
//将数据发送到真实的来源
|
||||
let dest_ip = *entry.value();
|
||||
drop(entry);
|
||||
ipv4_packet.set_destination_ip(dest_ip);
|
||||
ipv4_packet.update_checksum();
|
||||
let current_device = self.current_device.load();
|
||||
let virtual_ip = current_device.virtual_ip();
|
||||
let connect_server = current_device.connect_server;
|
||||
let current_device =
|
||||
self.current_device.load();
|
||||
let virtual_ip =
|
||||
current_device.virtual_ip();
|
||||
let connect_server =
|
||||
current_device.connect_server;
|
||||
let mut net_packet =
|
||||
NetPacket::new_encrypt(vec![
|
||||
0u8;
|
||||
12 + len + ENCRYPTION_RESERVED
|
||||
])
|
||||
.unwrap();
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_protocol(Protocol::IpTurn);
|
||||
net_packet.set_transport_protocol(crate::protocol::ip_turn_packet::Protocol::Ipv4.into());
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
net_packet.set_source(virtual_ip);
|
||||
net_packet.set_destination(dest_ip);
|
||||
let data_len = ipv4_packet.buffer.len();
|
||||
net_packet.set_payload(ipv4_packet.buffer);
|
||||
if self.sender.try_send_by_id(&net_packet.buffer()[..(12 + data_len)], &dest_ip).is_err() {
|
||||
let _ = self.sender.try_send_main(&net_packet.buffer()[..(12 + data_len)], connect_server);
|
||||
net_packet
|
||||
.set_payload(ipv4_packet.buffer)
|
||||
.unwrap();
|
||||
if let Err(e) = self
|
||||
.client_cipher
|
||||
.encrypt_ipv4(&mut net_packet)
|
||||
{
|
||||
log::warn!("加密失败:{}", e);
|
||||
continue;
|
||||
}
|
||||
if self
|
||||
.sender
|
||||
.try_send_by_id(
|
||||
net_packet.buffer(),
|
||||
&dest_ip,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
let _ = self.sender.send_main(
|
||||
net_packet.buffer(),
|
||||
connect_server,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,7 +131,7 @@ impl IcmpProxy {
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("icmp代理异常:{:?}",e);
|
||||
log::warn!("icmp代理异常:{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,16 +139,12 @@ impl IcmpProxy {
|
||||
fn recv(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<(usize, IpAddr)> {
|
||||
let (size, addr) = self.icmp_socket.recv_from(buf)?;
|
||||
let addr = match addr.as_socket() {
|
||||
None => {
|
||||
IpAddr::V4(Ipv4Addr::UNSPECIFIED)
|
||||
}
|
||||
Some(add) => {
|
||||
add.ip()
|
||||
}
|
||||
None => IpAddr::V4(Ipv4Addr::UNSPECIFIED),
|
||||
Some(add) => add.ip(),
|
||||
};
|
||||
Ok((size, addr))
|
||||
}
|
||||
// fn send_to(&self, buf: &[u8], addr: SocketAddrV4) -> io::Result<usize> {
|
||||
// self.icmp_socket.send_to(buf, &SockAddr::from(addr))
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
+88
-42
@@ -1,21 +1,48 @@
|
||||
use std::{io, thread};
|
||||
use std::collections::HashMap;
|
||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use socket2::{SockAddr, Socket};
|
||||
use tokio::net::{TcpListener, UdpSocket};
|
||||
use crate::channel::sender::ChannelSender;
|
||||
use crate::handle::CurrentDeviceInfo;
|
||||
use crate::ip_proxy::icmp_proxy::IcmpProxy;
|
||||
use crate::ip_proxy::tcp_proxy::TcpProxy;
|
||||
use crate::ip_proxy::udp_proxy::UdpProxy;
|
||||
use dashmap::DashMap;
|
||||
#[cfg(not(target_os = "android"))]
|
||||
use socket2::{SockAddr, Socket};
|
||||
#[cfg(not(target_os = "android"))]
|
||||
use std::net::Ipv4Addr;
|
||||
use std::net::SocketAddrV4;
|
||||
use std::sync::Arc;
|
||||
use std::{io, thread};
|
||||
use tokio::net::{TcpListener, UdpSocket};
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub mod icmp_proxy;
|
||||
pub mod tcp_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)]
|
||||
pub enum Protocol {
|
||||
Icmp,
|
||||
@@ -27,51 +54,70 @@ pub enum Protocol {
|
||||
pub struct IpProxyMap {
|
||||
pub(crate) tcp_proxy_port: u16,
|
||||
pub(crate) udp_proxy_port: u16,
|
||||
//真实源地址 -> (绑定地址,目的地址)
|
||||
pub(crate) tcp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
|
||||
pub(crate) udp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
|
||||
//真实源地址 -> 目的地址
|
||||
pub(crate) tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
||||
pub(crate) udp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
||||
// icmp用Identifier来区分,没有Identifier的一律不转发
|
||||
pub(crate) icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
|
||||
icmp_sockets: HashMap<Ipv4Addr, Arc<Socket>>,
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub(crate) icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
|
||||
#[cfg(not(target_os = "android"))]
|
||||
icmp_socket: Arc<Socket>,
|
||||
}
|
||||
|
||||
impl IpProxyMap {
|
||||
pub fn send_icmp(&self, buf: &[u8], src: &Ipv4Addr, dest: &Ipv4Addr) -> io::Result<usize> {
|
||||
if let Some(socket) = self.icmp_sockets.get(src) {
|
||||
socket.send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0)))
|
||||
} else {
|
||||
Err(io::Error::new(io::ErrorKind::Other, format!("not found src:{},dest:{}", src, dest)))
|
||||
}
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn send_icmp(&self, buf: &[u8], dest: &Ipv4Addr) -> io::Result<usize> {
|
||||
self.icmp_socket
|
||||
.send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0)))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn init_proxy(sender: ChannelSender, bind_ips: Vec<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> {
|
||||
let mut icmp_sockets = HashMap::new();
|
||||
let tcp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>> = Arc::new(SkipMap::new());
|
||||
let udp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>> = Arc::new(SkipMap::new());
|
||||
let icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>> = Arc::new(SkipMap::new());
|
||||
pub async fn init_proxy(
|
||||
#[cfg(not(target_os = "android"))] sender: crate::channel::sender::ChannelSender,
|
||||
#[cfg(not(target_os = "android"))] current_device: Arc<
|
||||
crossbeam_utils::atomic::AtomicCell<crate::handle::CurrentDeviceInfo>,
|
||||
>,
|
||||
#[cfg(not(target_os = "android"))] client_cipher: crate::cipher::Cipher,
|
||||
) -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> {
|
||||
let tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new0());
|
||||
let udp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new0());
|
||||
#[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 udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
|
||||
let tcp_proxy_port = tcp_listener.local_addr()?.port();
|
||||
let udp_proxy_port = udp_socket.local_addr()?.port();
|
||||
let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map.clone());
|
||||
let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map.clone());
|
||||
for ip in bind_ips {
|
||||
let addr = SocketAddrV4::new(ip, 0);
|
||||
let icmp_proxy_map = icmp_proxy_map.clone();
|
||||
let icmp_proxy = IcmpProxy::new(addr, icmp_proxy_map, sender.clone(), current_device.clone())?;
|
||||
icmp_sockets.insert(ip, icmp_proxy.icmp_socket());
|
||||
#[cfg(not(target_os = "android"))]
|
||||
let icmp_socket = {
|
||||
let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0);
|
||||
let icmp_proxy = icmp_proxy::IcmpProxy::new(
|
||||
addr,
|
||||
icmp_proxy_map.clone(),
|
||||
sender.clone(),
|
||||
current_device.clone(),
|
||||
client_cipher,
|
||||
)?;
|
||||
let icmp_socket = icmp_proxy.icmp_socket();
|
||||
thread::spawn(move || {
|
||||
icmp_proxy.start();
|
||||
});
|
||||
}
|
||||
icmp_socket
|
||||
};
|
||||
|
||||
Ok((tcp_proxy, udp_proxy, IpProxyMap {
|
||||
tcp_proxy_port,
|
||||
udp_proxy_port,
|
||||
tcp_proxy_map,
|
||||
udp_proxy_map,
|
||||
icmp_proxy_map,
|
||||
icmp_sockets,
|
||||
}))
|
||||
}
|
||||
Ok((
|
||||
tcp_proxy,
|
||||
udp_proxy,
|
||||
IpProxyMap {
|
||||
tcp_proxy_port,
|
||||
udp_proxy_port,
|
||||
tcp_proxy_map,
|
||||
udp_proxy_map,
|
||||
#[cfg(not(target_os = "android"))]
|
||||
icmp_proxy_map,
|
||||
#[cfg(not(target_os = "android"))]
|
||||
icmp_socket,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
@@ -1,59 +1,80 @@
|
||||
use dashmap::DashMap;
|
||||
use std::io;
|
||||
use std::net::{SocketAddr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
|
||||
pub struct TcpProxy {
|
||||
tcp_listener: TcpListener,
|
||||
map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
|
||||
tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
||||
}
|
||||
|
||||
impl TcpProxy {
|
||||
pub fn new(tcp_listener: TcpListener, map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>) -> Self {
|
||||
pub fn new(
|
||||
tcp_listener: TcpListener,
|
||||
tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
tcp_listener,
|
||||
map,
|
||||
tcp_proxy_map,
|
||||
}
|
||||
}
|
||||
pub async fn start(self) {
|
||||
pub async fn start(self) {
|
||||
let tcp_listener = self.tcp_listener;
|
||||
let map = self.map;
|
||||
let tcp_proxy_map = self.tcp_proxy_map;
|
||||
loop {
|
||||
match tcp_listener.accept().await {
|
||||
Ok((tcp_stream, sender_addr)) => {
|
||||
match sender_addr {
|
||||
SocketAddr::V4(sender_addr) => {
|
||||
if let Some(entry) = map.get(&sender_addr) {
|
||||
let (src_addr, dest_addr) = *entry.value();
|
||||
let peer_tcp_stream = match TcpStream::connect(dest_addr).await {
|
||||
Ok(peer_tcp_stream) => {peer_tcp_stream}
|
||||
Ok((tcp_stream, sender_addr)) => match sender_addr {
|
||||
SocketAddr::V4(sender_addr) => {
|
||||
if let Some(entry) = tcp_proxy_map.get(&sender_addr) {
|
||||
let dest_addr = *entry.value();
|
||||
drop(entry);
|
||||
|
||||
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,src_addr,dest_addr);
|
||||
continue;
|
||||
log::warn!(
|
||||
"tcp代理异常:{:?},来源:{},目标:{}",
|
||||
e,
|
||||
sender_addr,
|
||||
dest_addr
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let map = map.clone();
|
||||
tokio::spawn(async move {
|
||||
match proxy(tcp_stream, peer_tcp_stream).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
|
||||
}
|
||||
}
|
||||
map.remove(&sender_addr);
|
||||
});
|
||||
}
|
||||
if let Err(e) = proxy(tcp_stream, peer_tcp_stream).await {
|
||||
log::warn!("{}->{},{}", sender_addr, dest_addr, e);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log::warn!("tcp代理异常: 来源:{},未找到目标", sender_addr);
|
||||
}
|
||||
SocketAddr::V6(_) => {}
|
||||
}
|
||||
|
||||
}
|
||||
SocketAddr::V6(_) => {}
|
||||
},
|
||||
Err(e) => {
|
||||
log::warn!("tcp代理监听:{:?}",e);
|
||||
log::warn!("tcp代理监听:{:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,8 +85,9 @@ async fn proxy(mut client: TcpStream, mut server: TcpStream) -> io::Result<()> {
|
||||
|
||||
let client_to_server = tokio::io::copy(&mut client_reader, &mut server_writer);
|
||||
let server_to_client = tokio::io::copy(&mut server_reader, &mut client_writer);
|
||||
|
||||
tokio::try_join!(client_to_server, server_to_client)?;
|
||||
|
||||
tokio::select! {
|
||||
_ = tokio::time::timeout(Duration::from_secs(10), client_to_server) =>{},
|
||||
_ = tokio::time::timeout(Duration::from_secs(10), server_to_client) =>{},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,58 +1,65 @@
|
||||
use crate::ip_proxy::DashMapNew;
|
||||
use dashmap::DashMap;
|
||||
use std::io;
|
||||
use std::net::{SocketAddr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use tokio::net::UdpSocket;
|
||||
|
||||
/// 一个udp代理,作用是利用系统协议栈,将udp数据报解析出来再转发到目的地址
|
||||
pub struct UdpProxy {
|
||||
udp_socket: Arc<UdpSocket>,
|
||||
map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
|
||||
map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
||||
}
|
||||
|
||||
impl UdpProxy {
|
||||
pub fn new(udp_socket: UdpSocket, map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>) -> Self {
|
||||
pub fn new(udp_socket: UdpSocket, map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>) -> Self {
|
||||
let udp_socket = Arc::new(udp_socket);
|
||||
Self {
|
||||
udp_socket,
|
||||
map,
|
||||
}
|
||||
Self { udp_socket, map }
|
||||
}
|
||||
pub async fn start(self) {
|
||||
let map = self.map;
|
||||
let udp_socket = self.udp_socket;
|
||||
let mut buf = [0u8; 65536];
|
||||
let inner_map: Arc<SkipMap<SocketAddrV4, Arc<UdpSocket>>> = Arc::new(SkipMap::new());
|
||||
|
||||
let inner_map: Arc<DashMap<SocketAddrV4, Arc<UdpSocket>>> = Arc::new(DashMap::new0());
|
||||
|
||||
loop {
|
||||
match udp_socket.recv_from(&mut buf).await {
|
||||
Ok((len, sender_addr)) => {
|
||||
match sender_addr {
|
||||
SocketAddr::V4(sender_addr) => {
|
||||
match start0(&buf[..len], sender_addr, &inner_map, &map, &udp_socket).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("udp代理异常:{:?},来源:{}",e,sender_addr);
|
||||
}
|
||||
Ok((len, sender_addr)) => match sender_addr {
|
||||
SocketAddr::V4(sender_addr) => {
|
||||
match start0(&buf[..len], sender_addr, &inner_map, &map, &udp_socket).await
|
||||
{
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("udp代理异常:{:?},来源:{}", e, sender_addr);
|
||||
}
|
||||
}
|
||||
SocketAddr::V6(_) => {}
|
||||
}
|
||||
}
|
||||
SocketAddr::V6(_) => {}
|
||||
},
|
||||
Err(e) => {
|
||||
log::warn!("udp代理异常:{:?}",e);
|
||||
log::warn!("udp代理异常:{:?}", e);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn start0(buf: &[u8], sender_addr: SocketAddrV4, inner_map: &Arc<SkipMap<SocketAddrV4, Arc<UdpSocket>>>, map: &Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>, udp_socket: &Arc<UdpSocket>) -> io::Result<()> {
|
||||
async fn start0(
|
||||
buf: &[u8],
|
||||
sender_addr: SocketAddrV4,
|
||||
inner_map: &Arc<DashMap<SocketAddrV4, Arc<UdpSocket>>>,
|
||||
map: &Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
||||
udp_socket: &Arc<UdpSocket>,
|
||||
) -> io::Result<()> {
|
||||
if let Some(entry) = inner_map.get(&sender_addr) {
|
||||
entry.value().send(buf).await?;
|
||||
let udp = entry.value().clone();
|
||||
drop(entry);
|
||||
udp.send(buf).await?;
|
||||
} else if let Some(entry) = map.get(&sender_addr) {
|
||||
let (src_addr, dest_addr) = *entry.value();
|
||||
let dest_addr = *entry.value();
|
||||
drop(entry);
|
||||
let peer_udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
|
||||
peer_udp_socket.connect(dest_addr).await?;
|
||||
peer_udp_socket.send(buf).await?;
|
||||
@@ -64,27 +71,35 @@ async fn start0(buf: &[u8], sender_addr: SocketAddrV4, inner_map: &Arc<SkipMap<S
|
||||
tokio::spawn(async move {
|
||||
let mut buf = [0u8; 65536];
|
||||
loop {
|
||||
match tokio::time::timeout(Duration::from_secs(300), peer_udp_socket.recv(&mut buf)).await {
|
||||
Ok(rs) => {
|
||||
match rs {
|
||||
Ok(len) => {
|
||||
match udp_socket.send_to(&buf[..len], sender_addr).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
match tokio::time::timeout(Duration::from_secs(300), peer_udp_socket.recv(&mut buf))
|
||||
.await
|
||||
{
|
||||
Ok(rs) => match rs {
|
||||
Ok(len) => match udp_socket.send_to(&buf[..len], sender_addr).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
|
||||
log::warn!(
|
||||
"udp代理异常:{:?},来源:{},目标:{}",
|
||||
e,
|
||||
sender_addr,
|
||||
dest_addr
|
||||
);
|
||||
break;
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
log::warn!(
|
||||
"udp代理异常:{:?},来源:{},目标:{}",
|
||||
e,
|
||||
sender_addr,
|
||||
dest_addr
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
//超时关闭
|
||||
log::warn!("udp代理超时关闭,来源:{},目标:{}",src_addr,dest_addr);
|
||||
log::warn!("udp代理超时关闭,来源:{},目标:{}", sender_addr, dest_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -94,4 +109,4 @@ async fn start0(buf: &[u8], sender_addr: SocketAddrV4, inner_map: &Arc<SkipMap<S
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -1,17 +1,17 @@
|
||||
use crate::error::Error;
|
||||
|
||||
pub const VNT_VERSION: &'static str = "1.2.3";
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
pub mod channel;
|
||||
pub mod cipher;
|
||||
pub mod core;
|
||||
pub mod error;
|
||||
pub mod external_route;
|
||||
pub mod handle;
|
||||
pub mod igmp_server;
|
||||
pub mod ip_proxy;
|
||||
pub mod nat;
|
||||
pub mod proto;
|
||||
pub mod protocol;
|
||||
pub mod ip_proxy;
|
||||
pub mod external_route;
|
||||
pub mod igmp_server;
|
||||
pub mod tun_tap_device;
|
||||
pub mod core;
|
||||
pub mod channel;
|
||||
pub mod util;
|
||||
pub mod cipher;
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
use std::collections::HashSet;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
|
||||
use std::time::Duration;
|
||||
use std::{io, thread};
|
||||
use crate::channel::punch::NatType;
|
||||
|
||||
|
||||
/// 返回所有公网ip和端口变化范围
|
||||
pub fn public_ip_list(addrs: &Vec<SocketAddr>) -> io::Result<(NatType, Vec<Ipv4Addr>, u16)> {
|
||||
let mut hash_set = HashSet::new();
|
||||
let mut max_port_range = 0;
|
||||
let mut nat_type = NatType::Cone;
|
||||
let mut port = 88;
|
||||
for _ in 0..3 {
|
||||
let udp = loop {
|
||||
match UdpSocket::bind(SocketAddr::new(IpAddr::from(Ipv4Addr::from(0)), port)) {
|
||||
Ok(udp) => {
|
||||
break udp;
|
||||
}
|
||||
Err(e) => {
|
||||
if e.kind() == io::ErrorKind::AddrInUse {
|
||||
port += 1;
|
||||
continue;
|
||||
}
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
let (set, min_port, max_port) = public_ip_list_(&udp, addrs)?;
|
||||
drop(udp);
|
||||
let port_range = max_port - min_port;
|
||||
//有多个ip或者端口有变化,说明是对称nat
|
||||
if nat_type == NatType::Cone && (set.len() > 1 || port_range != 0) {
|
||||
nat_type = NatType::Symmetric;
|
||||
}
|
||||
if max_port_range < port_range {
|
||||
max_port_range = port_range;
|
||||
}
|
||||
for x in set {
|
||||
hash_set.insert(x);
|
||||
}
|
||||
thread::sleep(Duration::from_micros(5));
|
||||
}
|
||||
Ok((nat_type, hash_set.into_iter().collect(), max_port_range))
|
||||
}
|
||||
|
||||
/// 测试样本较少,可能不对
|
||||
///
|
||||
/// - 移动宽带:锥形网络、一个ip、端口和局域网端口不相同
|
||||
/// - 电信宽带:锥形网络、一个ip,端口和局域网端口不相同
|
||||
/// - 联调宽带:对称网络、端口不变ip轮流用
|
||||
/// - 移动4g:对称网络、ip端口都变 使用小的端口变化量小
|
||||
/// - 联通4g:对称网络、只有一个ip 端口变化大
|
||||
/// - 电信4g:对称网络只有一个ip 公网端口比较连续
|
||||
/// - 综上:客户端使用小端口,针对对称网络 尝试所有ip 公网端口+-变化量的范围
|
||||
/// - 打通概率 移动宽带=电信宽带>联调宽带>电信4g>移动4g>>联调4g
|
||||
pub fn public_ip_list_(
|
||||
udp: &UdpSocket,
|
||||
addrs: &Vec<SocketAddr>,
|
||||
) -> io::Result<(HashSet<Ipv4Addr>, u16, u16)> {
|
||||
udp.set_read_timeout(Some(Duration::from_millis(300)))?;
|
||||
let mut buf = [0u8; 128];
|
||||
for addr in addrs {
|
||||
let _ = udp.send_to(b"NatTest", addr)?;
|
||||
}
|
||||
let mut hash_set = HashSet::new();
|
||||
let mut count = 0;
|
||||
let mut min_port = 65535;
|
||||
let mut max_port = 0;
|
||||
for _ in 0..addrs.len() {
|
||||
if let Ok(len) = udp.recv(&mut buf) {
|
||||
if len != 16 || &buf[..10] != &b"NatType213"[..] {
|
||||
continue;
|
||||
}
|
||||
let port = u16::from_be_bytes([buf[14], buf[15]]);
|
||||
if min_port > port {
|
||||
min_port = port;
|
||||
}
|
||||
if max_port < port {
|
||||
max_port = port;
|
||||
}
|
||||
let ip = Ipv4Addr::new(buf[10], buf[11], buf[12], buf[13]);
|
||||
hash_set.insert(ip);
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
if count <= 1 {
|
||||
return Err(io::Error::from(io::ErrorKind::TimedOut));
|
||||
}
|
||||
Ok((hash_set, min_port, max_port))
|
||||
}
|
||||
|
||||
/// 返回nat类型
|
||||
pub fn nat_test() -> io::Result<NatType> {
|
||||
for _ in 0..3 {
|
||||
if NatType::Symmetric == nat_test_()? {
|
||||
return Ok(NatType::Symmetric);
|
||||
}
|
||||
thread::sleep(Duration::from_micros(5));
|
||||
}
|
||||
Ok(NatType::Cone)
|
||||
}
|
||||
|
||||
pub fn nat_test_() -> io::Result<NatType> {
|
||||
let udp = UdpSocket::bind("0.0.0.0:0")?;
|
||||
udp.set_read_timeout(Some(Duration::from_millis(300)))?;
|
||||
let mut buf = [0u8; 128];
|
||||
let _ = udp.send_to(b"NatTest", "nat1.wherewego.top:35061")?;
|
||||
let _ = udp.send_to(b"NatTest", "nat1.wherewego.top:35062")?;
|
||||
let _ = udp.send_to(b"NatTest", "nat2.wherewego.top:35061")?;
|
||||
let _ = udp.send_to(b"NatTest", "nat2.wherewego.top:35062")?;
|
||||
let mut tmp_ip_port: Option<[u8; 6]> = None;
|
||||
let mut count = 0;
|
||||
for _ in 0..4 {
|
||||
if let Ok(len) = udp.recv(&mut buf) {
|
||||
if len != 16 || &buf[..10] != &b"NatType213"[..] {
|
||||
continue;
|
||||
}
|
||||
count += 1;
|
||||
let mut ip_port = [0u8; 6];
|
||||
ip_port.copy_from_slice(&buf[10..16]);
|
||||
if let Some(tmp_ip_port) = &tmp_ip_port {
|
||||
if tmp_ip_port != &ip_port {
|
||||
return Ok(NatType::Symmetric);
|
||||
}
|
||||
} else {
|
||||
tmp_ip_port = Some(ip_port);
|
||||
}
|
||||
}
|
||||
}
|
||||
if count <= 1 {
|
||||
return Err(io::Error::from(io::ErrorKind::TimedOut));
|
||||
}
|
||||
Ok(NatType::Cone)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nat_test_run() {
|
||||
let udp = UdpSocket::bind("0.0.0.0:101").unwrap();
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr, ToSocketAddrs, UdpSocket};
|
||||
let addrs = vec![
|
||||
"nat1.wherewego.top:35062"
|
||||
.to_socket_addrs()
|
||||
.unwrap()
|
||||
.next()
|
||||
.unwrap(),
|
||||
"nat2.wherewego.top:35062"
|
||||
.to_socket_addrs()
|
||||
.unwrap()
|
||||
.next()
|
||||
.unwrap(),
|
||||
];
|
||||
let print = public_ip_list_(&udp, &addrs).unwrap();
|
||||
println!("{:?}", print);
|
||||
}
|
||||
+68
-39
@@ -1,31 +1,58 @@
|
||||
use crate::proto::message::PunchNatType;
|
||||
use parking_lot::Mutex;
|
||||
use std::io;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::net::UdpSocket;
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub mod check;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use std::net::UdpSocket;
|
||||
use crate::channel::punch::{NatInfo, NatType};
|
||||
use crate::proto::message::PunchNatType;
|
||||
|
||||
pub fn local_ip() -> io::Result<Ipv4Addr> {
|
||||
mod stun_test;
|
||||
|
||||
pub fn local_ipv4() -> io::Result<Ipv4Addr> {
|
||||
let socket = UdpSocket::bind("0.0.0.0:0")?;
|
||||
socket.connect("8.8.8.8:80")?;
|
||||
let addr = socket.local_addr()?;
|
||||
match addr.ip() {
|
||||
IpAddr::V4(ip) => {
|
||||
Ok(ip)
|
||||
IpAddr::V4(ip) => Ok(ip),
|
||||
IpAddr::V6(_) => Ok(Ipv4Addr::UNSPECIFIED),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_ipv6() -> io::Result<Ipv6Addr> {
|
||||
let socket = UdpSocket::bind("[::]:0")?;
|
||||
socket.connect("[2001:4860:4860::8888]:80")?;
|
||||
let addr = socket.local_addr()?;
|
||||
match addr.ip() {
|
||||
IpAddr::V4(_) => Ok(Ipv6Addr::UNSPECIFIED),
|
||||
IpAddr::V6(ip) => Ok(ip),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_ipv4_addr(port: u16) -> SocketAddrV4 {
|
||||
match local_ipv4() {
|
||||
Ok(ipv4) => SocketAddrV4::new(ipv4, port),
|
||||
Err(e) => {
|
||||
log::warn!("获取本地ipv4地址失败:{}", e);
|
||||
SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0)
|
||||
}
|
||||
IpAddr::V6(_) => {
|
||||
Ok(Ipv4Addr::UNSPECIFIED)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_ipv6_addr(port: u16) -> SocketAddrV6 {
|
||||
match local_ipv6() {
|
||||
Ok(ipv6) => SocketAddrV6::new(ipv6, port, 0, 0),
|
||||
Err(e) => {
|
||||
log::warn!("获取本地ipv6地址失败:{}", e);
|
||||
SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct NatTest {
|
||||
nat_test_server: Arc<Vec<SocketAddr>>,
|
||||
stun_server: Vec<String>,
|
||||
info: Arc<Mutex<NatInfo>>,
|
||||
}
|
||||
|
||||
@@ -49,23 +76,24 @@ impl Into<NatType> for PunchNatType {
|
||||
|
||||
impl NatTest {
|
||||
pub fn new(
|
||||
nat_test_server: Vec<SocketAddr>,
|
||||
mut stun_server: Vec<String>,
|
||||
public_ip: Ipv4Addr,
|
||||
public_port: u16,
|
||||
local_ip: Ipv4Addr,
|
||||
local_port: u16,
|
||||
local_ipv4_addr: SocketAddrV4,
|
||||
ipv6_addr: SocketAddrV6,
|
||||
) -> NatTest {
|
||||
let info = NatTest::re_test_(
|
||||
&nat_test_server,
|
||||
public_ip,
|
||||
let server = stun_server[0].clone();
|
||||
stun_server.resize(3, server);
|
||||
let nat_info = NatInfo::new(
|
||||
vec![public_ip],
|
||||
public_port,
|
||||
local_ip,
|
||||
local_port,
|
||||
0,
|
||||
local_ipv4_addr,
|
||||
ipv6_addr,
|
||||
NatType::Cone,
|
||||
);
|
||||
NatTest {
|
||||
nat_test_server: Arc::new(nat_test_server),
|
||||
info: Arc::new(Mutex::new(info)),
|
||||
}
|
||||
let info = Arc::new(Mutex::new(nat_info));
|
||||
NatTest { stun_server, info }
|
||||
}
|
||||
pub fn nat_info(&self) -> NatInfo {
|
||||
self.info.lock().clone()
|
||||
@@ -77,31 +105,32 @@ impl NatTest {
|
||||
guard.public_ips.push(ip);
|
||||
}
|
||||
}
|
||||
pub fn re_test(
|
||||
pub async fn re_test(
|
||||
&self,
|
||||
public_ip: Ipv4Addr,
|
||||
public_port: u16,
|
||||
local_ip: Ipv4Addr,
|
||||
local_port: u16,
|
||||
local_ipv4_addr: SocketAddrV4,
|
||||
ipv6_addr: SocketAddrV6,
|
||||
) -> NatInfo {
|
||||
let info = NatTest::re_test_(
|
||||
&self.nat_test_server,
|
||||
&self.stun_server,
|
||||
public_ip,
|
||||
public_port,
|
||||
local_ip,
|
||||
local_port,
|
||||
);
|
||||
local_ipv4_addr,
|
||||
ipv6_addr,
|
||||
)
|
||||
.await;
|
||||
*self.info.lock() = info.clone();
|
||||
info
|
||||
}
|
||||
fn re_test_(
|
||||
nat_test_server: &Vec<SocketAddr>,
|
||||
async fn re_test_(
|
||||
stun_server: &Vec<String>,
|
||||
public_ip: Ipv4Addr,
|
||||
public_port: u16,
|
||||
local_ip: Ipv4Addr,
|
||||
local_port: u16,
|
||||
local_ipv4_addr: SocketAddrV4,
|
||||
ipv6_addr: SocketAddrV6,
|
||||
) -> NatInfo {
|
||||
return match check::public_ip_list(nat_test_server) {
|
||||
return match stun_test::stun_test_nat(stun_server.clone()).await {
|
||||
Ok((nat_type, ips, port_range)) => {
|
||||
let mut public_ips = Vec::new();
|
||||
public_ips.push(Ipv4Addr::from(public_ip));
|
||||
@@ -114,8 +143,8 @@ impl NatTest {
|
||||
public_ips,
|
||||
public_port,
|
||||
port_range,
|
||||
local_ip,
|
||||
local_port,
|
||||
local_ipv4_addr,
|
||||
ipv6_addr,
|
||||
nat_type,
|
||||
)
|
||||
}
|
||||
@@ -125,8 +154,8 @@ impl NatTest {
|
||||
vec![public_ip],
|
||||
public_port,
|
||||
0,
|
||||
local_ip,
|
||||
local_port,
|
||||
local_ipv4_addr,
|
||||
ipv6_addr,
|
||||
NatType::Cone,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
use std::collections::HashSet;
|
||||
use std::io;
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::channel::punch::NatType;
|
||||
use stun_format::Attr;
|
||||
use tokio::net::UdpSocket;
|
||||
|
||||
pub async fn stun_test_nat(stun_servers: Vec<String>) -> io::Result<(NatType, Vec<Ipv4Addr>, u16)> {
|
||||
let mut h = Vec::new();
|
||||
for x in stun_servers {
|
||||
let handle = tokio::spawn(test_nat(x));
|
||||
h.push(handle);
|
||||
}
|
||||
let mut nat_type = NatType::Cone;
|
||||
let mut port_range = 0;
|
||||
let mut hash_set = HashSet::new();
|
||||
for x in h {
|
||||
if let Ok(rs) = x.await {
|
||||
if let Ok((nat_type_t, ip_list_t, port_range_t)) = rs {
|
||||
if nat_type_t == NatType::Symmetric {
|
||||
nat_type = NatType::Symmetric;
|
||||
}
|
||||
for x in ip_list_t {
|
||||
hash_set.insert(x);
|
||||
}
|
||||
if port_range < port_range_t {
|
||||
port_range = port_range_t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok((nat_type, hash_set.into_iter().collect(), port_range))
|
||||
}
|
||||
|
||||
async fn test_nat(stun_server: String) -> io::Result<(NatType, Vec<Ipv4Addr>, u16)> {
|
||||
let udp = UdpSocket::bind("0.0.0.0:0").await?;
|
||||
udp.connect(stun_server).await?;
|
||||
let mut nat_type = NatType::Cone;
|
||||
let mut port_range = 0;
|
||||
let mut hash_set = HashSet::new();
|
||||
match test_nat_(&udp, true, true).await {
|
||||
Ok((mapped_addr1, changed_addr1)) => {
|
||||
match mapped_addr1.ip() {
|
||||
IpAddr::V4(ip) => {
|
||||
hash_set.insert(ip);
|
||||
}
|
||||
IpAddr::V6(_) => {}
|
||||
}
|
||||
if udp.connect(changed_addr1).await.is_ok() {
|
||||
if let Ok((mapped_addr2, _)) = test_nat_(&udp, false, false).await {
|
||||
match mapped_addr2.ip() {
|
||||
IpAddr::V4(ip) => {
|
||||
hash_set.insert(ip);
|
||||
}
|
||||
IpAddr::V6(_) => {}
|
||||
}
|
||||
port_range = mapped_addr2.port().abs_diff(mapped_addr1.port());
|
||||
if mapped_addr1 != mapped_addr2 {
|
||||
nat_type = NatType::Symmetric;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
Ok((nat_type, hash_set.into_iter().collect(), port_range))
|
||||
}
|
||||
|
||||
async fn test_nat_(
|
||||
udp: &UdpSocket,
|
||||
change_ip: bool,
|
||||
change_port: bool,
|
||||
) -> io::Result<(SocketAddr, SocketAddr)> {
|
||||
for _ in 0..2 {
|
||||
let mut buf = [0u8; 28];
|
||||
let mut msg = stun_format::MsgBuilder::from(buf.as_mut_slice());
|
||||
msg.typ(stun_format::MsgType::BindingRequest).unwrap();
|
||||
msg.tid(1).unwrap();
|
||||
msg.add_attr(Attr::ChangeRequest {
|
||||
change_ip,
|
||||
change_port,
|
||||
})
|
||||
.unwrap();
|
||||
udp.send(msg.as_bytes()).await?;
|
||||
let mut buf = [0; 10240];
|
||||
let (len, addr) =
|
||||
match tokio::time::timeout(Duration::from_millis(300), udp.recv_from(&mut buf)).await {
|
||||
Ok(rs) => rs?,
|
||||
Err(_) => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let msg = stun_format::Msg::from(&buf[..len]);
|
||||
let mut mapped_addr = None;
|
||||
let mut changed_addr = None;
|
||||
for x in msg.attrs_iter() {
|
||||
match x {
|
||||
Attr::MappedAddress(addr) => {
|
||||
if mapped_addr.is_none() {
|
||||
let _ = mapped_addr.insert(stun_addr(addr));
|
||||
}
|
||||
}
|
||||
Attr::ChangedAddress(addr) => {
|
||||
if changed_addr.is_none() {
|
||||
let _ = changed_addr.insert(stun_addr(addr));
|
||||
}
|
||||
}
|
||||
Attr::XorMappedAddress(addr) => {
|
||||
if mapped_addr.is_none() {
|
||||
let _ = mapped_addr.insert(stun_addr(addr));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if changed_addr.is_some() && mapped_addr.is_some() {
|
||||
return Ok((mapped_addr.unwrap(), changed_addr.unwrap()));
|
||||
}
|
||||
}
|
||||
if mapped_addr.is_some() {
|
||||
return Ok((mapped_addr.unwrap(), changed_addr.unwrap_or(addr)));
|
||||
}
|
||||
}
|
||||
Err(io::Error::new(io::ErrorKind::Other, "stun response err"))
|
||||
}
|
||||
|
||||
fn stun_addr(addr: stun_format::SocketAddr) -> SocketAddr {
|
||||
match addr {
|
||||
stun_format::SocketAddr::V4(ip, port) => {
|
||||
SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from(ip), port))
|
||||
}
|
||||
stun_format::SocketAddr::V6(ip, port) => {
|
||||
SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from(ip), port, 0, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
+568
-46
@@ -25,6 +25,462 @@
|
||||
/// of protobuf runtime.
|
||||
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_2_0;
|
||||
|
||||
#[derive(PartialEq,Clone,Default,Debug)]
|
||||
// @@protoc_insertion_point(message:HandshakeRequest)
|
||||
pub struct HandshakeRequest {
|
||||
// message fields
|
||||
// @@protoc_insertion_point(field:HandshakeRequest.version)
|
||||
pub version: ::std::string::String,
|
||||
// @@protoc_insertion_point(field:HandshakeRequest.secret)
|
||||
pub secret: bool,
|
||||
// special fields
|
||||
// @@protoc_insertion_point(special_field:HandshakeRequest.special_fields)
|
||||
pub special_fields: ::protobuf::SpecialFields,
|
||||
}
|
||||
|
||||
impl<'a> ::std::default::Default for &'a HandshakeRequest {
|
||||
fn default() -> &'a HandshakeRequest {
|
||||
<HandshakeRequest as ::protobuf::Message>::default_instance()
|
||||
}
|
||||
}
|
||||
|
||||
impl HandshakeRequest {
|
||||
pub fn new() -> HandshakeRequest {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
|
||||
let mut fields = ::std::vec::Vec::with_capacity(2);
|
||||
let mut oneofs = ::std::vec::Vec::with_capacity(0);
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"version",
|
||||
|m: &HandshakeRequest| { &m.version },
|
||||
|m: &mut HandshakeRequest| { &mut m.version },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"secret",
|
||||
|m: &HandshakeRequest| { &m.secret },
|
||||
|m: &mut HandshakeRequest| { &mut m.secret },
|
||||
));
|
||||
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<HandshakeRequest>(
|
||||
"HandshakeRequest",
|
||||
fields,
|
||||
oneofs,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for HandshakeRequest {
|
||||
const NAME: &'static str = "HandshakeRequest";
|
||||
|
||||
fn is_initialized(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
|
||||
while let Some(tag) = is.read_raw_tag_or_eof()? {
|
||||
match tag {
|
||||
10 => {
|
||||
self.version = is.read_string()?;
|
||||
},
|
||||
16 => {
|
||||
self.secret = is.read_bool()?;
|
||||
},
|
||||
tag => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
|
||||
},
|
||||
};
|
||||
}
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
// Compute sizes of nested messages
|
||||
#[allow(unused_variables)]
|
||||
fn compute_size(&self) -> u64 {
|
||||
let mut my_size = 0;
|
||||
if !self.version.is_empty() {
|
||||
my_size += ::protobuf::rt::string_size(1, &self.version);
|
||||
}
|
||||
if self.secret != false {
|
||||
my_size += 1 + 1;
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
|
||||
self.special_fields.cached_size().set(my_size as u32);
|
||||
my_size
|
||||
}
|
||||
|
||||
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
|
||||
if !self.version.is_empty() {
|
||||
os.write_string(1, &self.version)?;
|
||||
}
|
||||
if self.secret != false {
|
||||
os.write_bool(2, self.secret)?;
|
||||
}
|
||||
os.write_unknown_fields(self.special_fields.unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
fn special_fields(&self) -> &::protobuf::SpecialFields {
|
||||
&self.special_fields
|
||||
}
|
||||
|
||||
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
|
||||
&mut self.special_fields
|
||||
}
|
||||
|
||||
fn new() -> HandshakeRequest {
|
||||
HandshakeRequest::new()
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.version.clear();
|
||||
self.secret = false;
|
||||
self.special_fields.clear();
|
||||
}
|
||||
|
||||
fn default_instance() -> &'static HandshakeRequest {
|
||||
static instance: HandshakeRequest = HandshakeRequest {
|
||||
version: ::std::string::String::new(),
|
||||
secret: false,
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
};
|
||||
&instance
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::MessageFull for HandshakeRequest {
|
||||
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
|
||||
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
|
||||
descriptor.get(|| file_descriptor().message_by_package_relative_name("HandshakeRequest").unwrap()).clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for HandshakeRequest {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
::protobuf::text_format::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for HandshakeRequest {
|
||||
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Clone,Default,Debug)]
|
||||
// @@protoc_insertion_point(message:HandshakeResponse)
|
||||
pub struct HandshakeResponse {
|
||||
// message fields
|
||||
// @@protoc_insertion_point(field:HandshakeResponse.version)
|
||||
pub version: ::std::string::String,
|
||||
// @@protoc_insertion_point(field:HandshakeResponse.secret)
|
||||
pub secret: bool,
|
||||
// @@protoc_insertion_point(field:HandshakeResponse.public_key)
|
||||
pub public_key: ::std::vec::Vec<u8>,
|
||||
// @@protoc_insertion_point(field:HandshakeResponse.key_finger)
|
||||
pub key_finger: ::std::string::String,
|
||||
// special fields
|
||||
// @@protoc_insertion_point(special_field:HandshakeResponse.special_fields)
|
||||
pub special_fields: ::protobuf::SpecialFields,
|
||||
}
|
||||
|
||||
impl<'a> ::std::default::Default for &'a HandshakeResponse {
|
||||
fn default() -> &'a HandshakeResponse {
|
||||
<HandshakeResponse as ::protobuf::Message>::default_instance()
|
||||
}
|
||||
}
|
||||
|
||||
impl HandshakeResponse {
|
||||
pub fn new() -> HandshakeResponse {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
|
||||
let mut fields = ::std::vec::Vec::with_capacity(4);
|
||||
let mut oneofs = ::std::vec::Vec::with_capacity(0);
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"version",
|
||||
|m: &HandshakeResponse| { &m.version },
|
||||
|m: &mut HandshakeResponse| { &mut m.version },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"secret",
|
||||
|m: &HandshakeResponse| { &m.secret },
|
||||
|m: &mut HandshakeResponse| { &mut m.secret },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"public_key",
|
||||
|m: &HandshakeResponse| { &m.public_key },
|
||||
|m: &mut HandshakeResponse| { &mut m.public_key },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"key_finger",
|
||||
|m: &HandshakeResponse| { &m.key_finger },
|
||||
|m: &mut HandshakeResponse| { &mut m.key_finger },
|
||||
));
|
||||
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<HandshakeResponse>(
|
||||
"HandshakeResponse",
|
||||
fields,
|
||||
oneofs,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for HandshakeResponse {
|
||||
const NAME: &'static str = "HandshakeResponse";
|
||||
|
||||
fn is_initialized(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
|
||||
while let Some(tag) = is.read_raw_tag_or_eof()? {
|
||||
match tag {
|
||||
10 => {
|
||||
self.version = is.read_string()?;
|
||||
},
|
||||
16 => {
|
||||
self.secret = is.read_bool()?;
|
||||
},
|
||||
26 => {
|
||||
self.public_key = is.read_bytes()?;
|
||||
},
|
||||
34 => {
|
||||
self.key_finger = is.read_string()?;
|
||||
},
|
||||
tag => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
|
||||
},
|
||||
};
|
||||
}
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
// Compute sizes of nested messages
|
||||
#[allow(unused_variables)]
|
||||
fn compute_size(&self) -> u64 {
|
||||
let mut my_size = 0;
|
||||
if !self.version.is_empty() {
|
||||
my_size += ::protobuf::rt::string_size(1, &self.version);
|
||||
}
|
||||
if self.secret != false {
|
||||
my_size += 1 + 1;
|
||||
}
|
||||
if !self.public_key.is_empty() {
|
||||
my_size += ::protobuf::rt::bytes_size(3, &self.public_key);
|
||||
}
|
||||
if !self.key_finger.is_empty() {
|
||||
my_size += ::protobuf::rt::string_size(4, &self.key_finger);
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
|
||||
self.special_fields.cached_size().set(my_size as u32);
|
||||
my_size
|
||||
}
|
||||
|
||||
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
|
||||
if !self.version.is_empty() {
|
||||
os.write_string(1, &self.version)?;
|
||||
}
|
||||
if self.secret != false {
|
||||
os.write_bool(2, self.secret)?;
|
||||
}
|
||||
if !self.public_key.is_empty() {
|
||||
os.write_bytes(3, &self.public_key)?;
|
||||
}
|
||||
if !self.key_finger.is_empty() {
|
||||
os.write_string(4, &self.key_finger)?;
|
||||
}
|
||||
os.write_unknown_fields(self.special_fields.unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
fn special_fields(&self) -> &::protobuf::SpecialFields {
|
||||
&self.special_fields
|
||||
}
|
||||
|
||||
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
|
||||
&mut self.special_fields
|
||||
}
|
||||
|
||||
fn new() -> HandshakeResponse {
|
||||
HandshakeResponse::new()
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.version.clear();
|
||||
self.secret = false;
|
||||
self.public_key.clear();
|
||||
self.key_finger.clear();
|
||||
self.special_fields.clear();
|
||||
}
|
||||
|
||||
fn default_instance() -> &'static HandshakeResponse {
|
||||
static instance: HandshakeResponse = HandshakeResponse {
|
||||
version: ::std::string::String::new(),
|
||||
secret: false,
|
||||
public_key: ::std::vec::Vec::new(),
|
||||
key_finger: ::std::string::String::new(),
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
};
|
||||
&instance
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::MessageFull for HandshakeResponse {
|
||||
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
|
||||
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
|
||||
descriptor.get(|| file_descriptor().message_by_package_relative_name("HandshakeResponse").unwrap()).clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for HandshakeResponse {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
::protobuf::text_format::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for HandshakeResponse {
|
||||
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Clone,Default,Debug)]
|
||||
// @@protoc_insertion_point(message:SecretHandshakeRequest)
|
||||
pub struct SecretHandshakeRequest {
|
||||
// message fields
|
||||
// @@protoc_insertion_point(field:SecretHandshakeRequest.token)
|
||||
pub token: ::std::string::String,
|
||||
// @@protoc_insertion_point(field:SecretHandshakeRequest.key)
|
||||
pub key: ::std::vec::Vec<u8>,
|
||||
// special fields
|
||||
// @@protoc_insertion_point(special_field:SecretHandshakeRequest.special_fields)
|
||||
pub special_fields: ::protobuf::SpecialFields,
|
||||
}
|
||||
|
||||
impl<'a> ::std::default::Default for &'a SecretHandshakeRequest {
|
||||
fn default() -> &'a SecretHandshakeRequest {
|
||||
<SecretHandshakeRequest as ::protobuf::Message>::default_instance()
|
||||
}
|
||||
}
|
||||
|
||||
impl SecretHandshakeRequest {
|
||||
pub fn new() -> SecretHandshakeRequest {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
|
||||
let mut fields = ::std::vec::Vec::with_capacity(2);
|
||||
let mut oneofs = ::std::vec::Vec::with_capacity(0);
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"token",
|
||||
|m: &SecretHandshakeRequest| { &m.token },
|
||||
|m: &mut SecretHandshakeRequest| { &mut m.token },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"key",
|
||||
|m: &SecretHandshakeRequest| { &m.key },
|
||||
|m: &mut SecretHandshakeRequest| { &mut m.key },
|
||||
));
|
||||
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<SecretHandshakeRequest>(
|
||||
"SecretHandshakeRequest",
|
||||
fields,
|
||||
oneofs,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for SecretHandshakeRequest {
|
||||
const NAME: &'static str = "SecretHandshakeRequest";
|
||||
|
||||
fn is_initialized(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
|
||||
while let Some(tag) = is.read_raw_tag_or_eof()? {
|
||||
match tag {
|
||||
10 => {
|
||||
self.token = is.read_string()?;
|
||||
},
|
||||
18 => {
|
||||
self.key = is.read_bytes()?;
|
||||
},
|
||||
tag => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
|
||||
},
|
||||
};
|
||||
}
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
// Compute sizes of nested messages
|
||||
#[allow(unused_variables)]
|
||||
fn compute_size(&self) -> u64 {
|
||||
let mut my_size = 0;
|
||||
if !self.token.is_empty() {
|
||||
my_size += ::protobuf::rt::string_size(1, &self.token);
|
||||
}
|
||||
if !self.key.is_empty() {
|
||||
my_size += ::protobuf::rt::bytes_size(2, &self.key);
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
|
||||
self.special_fields.cached_size().set(my_size as u32);
|
||||
my_size
|
||||
}
|
||||
|
||||
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
|
||||
if !self.token.is_empty() {
|
||||
os.write_string(1, &self.token)?;
|
||||
}
|
||||
if !self.key.is_empty() {
|
||||
os.write_bytes(2, &self.key)?;
|
||||
}
|
||||
os.write_unknown_fields(self.special_fields.unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
fn special_fields(&self) -> &::protobuf::SpecialFields {
|
||||
&self.special_fields
|
||||
}
|
||||
|
||||
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
|
||||
&mut self.special_fields
|
||||
}
|
||||
|
||||
fn new() -> SecretHandshakeRequest {
|
||||
SecretHandshakeRequest::new()
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.token.clear();
|
||||
self.key.clear();
|
||||
self.special_fields.clear();
|
||||
}
|
||||
|
||||
fn default_instance() -> &'static SecretHandshakeRequest {
|
||||
static instance: SecretHandshakeRequest = SecretHandshakeRequest {
|
||||
token: ::std::string::String::new(),
|
||||
key: ::std::vec::Vec::new(),
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
};
|
||||
&instance
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::MessageFull for SecretHandshakeRequest {
|
||||
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
|
||||
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
|
||||
descriptor.get(|| file_descriptor().message_by_package_relative_name("SecretHandshakeRequest").unwrap()).clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for SecretHandshakeRequest {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
::protobuf::text_format::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for SecretHandshakeRequest {
|
||||
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Clone,Default,Debug)]
|
||||
// @@protoc_insertion_point(message:RegistrationRequest)
|
||||
pub struct RegistrationRequest {
|
||||
@@ -43,6 +499,8 @@ pub struct RegistrationRequest {
|
||||
pub virtual_ip: u32,
|
||||
// @@protoc_insertion_point(field:RegistrationRequest.allow_ip_change)
|
||||
pub allow_ip_change: bool,
|
||||
// @@protoc_insertion_point(field:RegistrationRequest.client_secret)
|
||||
pub client_secret: bool,
|
||||
// special fields
|
||||
// @@protoc_insertion_point(special_field:RegistrationRequest.special_fields)
|
||||
pub special_fields: ::protobuf::SpecialFields,
|
||||
@@ -60,7 +518,7 @@ impl RegistrationRequest {
|
||||
}
|
||||
|
||||
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
|
||||
let mut fields = ::std::vec::Vec::with_capacity(7);
|
||||
let mut fields = ::std::vec::Vec::with_capacity(8);
|
||||
let mut oneofs = ::std::vec::Vec::with_capacity(0);
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"token",
|
||||
@@ -97,6 +555,11 @@ impl RegistrationRequest {
|
||||
|m: &RegistrationRequest| { &m.allow_ip_change },
|
||||
|m: &mut RegistrationRequest| { &mut m.allow_ip_change },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"client_secret",
|
||||
|m: &RegistrationRequest| { &m.client_secret },
|
||||
|m: &mut RegistrationRequest| { &mut m.client_secret },
|
||||
));
|
||||
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<RegistrationRequest>(
|
||||
"RegistrationRequest",
|
||||
fields,
|
||||
@@ -136,6 +599,9 @@ impl ::protobuf::Message for RegistrationRequest {
|
||||
56 => {
|
||||
self.allow_ip_change = is.read_bool()?;
|
||||
},
|
||||
64 => {
|
||||
self.client_secret = is.read_bool()?;
|
||||
},
|
||||
tag => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
|
||||
},
|
||||
@@ -169,6 +635,9 @@ impl ::protobuf::Message for RegistrationRequest {
|
||||
if self.allow_ip_change != false {
|
||||
my_size += 1 + 1;
|
||||
}
|
||||
if self.client_secret != false {
|
||||
my_size += 1 + 1;
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
|
||||
self.special_fields.cached_size().set(my_size as u32);
|
||||
my_size
|
||||
@@ -196,6 +665,9 @@ impl ::protobuf::Message for RegistrationRequest {
|
||||
if self.allow_ip_change != false {
|
||||
os.write_bool(7, self.allow_ip_change)?;
|
||||
}
|
||||
if self.client_secret != false {
|
||||
os.write_bool(8, self.client_secret)?;
|
||||
}
|
||||
os.write_unknown_fields(self.special_fields.unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
@@ -220,6 +692,7 @@ impl ::protobuf::Message for RegistrationRequest {
|
||||
self.version.clear();
|
||||
self.virtual_ip = 0;
|
||||
self.allow_ip_change = false;
|
||||
self.client_secret = false;
|
||||
self.special_fields.clear();
|
||||
}
|
||||
|
||||
@@ -232,6 +705,7 @@ impl ::protobuf::Message for RegistrationRequest {
|
||||
version: ::std::string::String::new(),
|
||||
virtual_ip: 0,
|
||||
allow_ip_change: false,
|
||||
client_secret: false,
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
};
|
||||
&instance
|
||||
@@ -514,6 +988,8 @@ pub struct DeviceInfo {
|
||||
pub virtual_ip: u32,
|
||||
// @@protoc_insertion_point(field:DeviceInfo.device_status)
|
||||
pub device_status: u32,
|
||||
// @@protoc_insertion_point(field:DeviceInfo.client_secret)
|
||||
pub client_secret: bool,
|
||||
// special fields
|
||||
// @@protoc_insertion_point(special_field:DeviceInfo.special_fields)
|
||||
pub special_fields: ::protobuf::SpecialFields,
|
||||
@@ -531,7 +1007,7 @@ impl DeviceInfo {
|
||||
}
|
||||
|
||||
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
|
||||
let mut fields = ::std::vec::Vec::with_capacity(3);
|
||||
let mut fields = ::std::vec::Vec::with_capacity(4);
|
||||
let mut oneofs = ::std::vec::Vec::with_capacity(0);
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"name",
|
||||
@@ -548,6 +1024,11 @@ impl DeviceInfo {
|
||||
|m: &DeviceInfo| { &m.device_status },
|
||||
|m: &mut DeviceInfo| { &mut m.device_status },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"client_secret",
|
||||
|m: &DeviceInfo| { &m.client_secret },
|
||||
|m: &mut DeviceInfo| { &mut m.client_secret },
|
||||
));
|
||||
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<DeviceInfo>(
|
||||
"DeviceInfo",
|
||||
fields,
|
||||
@@ -575,6 +1056,9 @@ impl ::protobuf::Message for DeviceInfo {
|
||||
24 => {
|
||||
self.device_status = is.read_uint32()?;
|
||||
},
|
||||
32 => {
|
||||
self.client_secret = is.read_bool()?;
|
||||
},
|
||||
tag => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
|
||||
},
|
||||
@@ -596,6 +1080,9 @@ impl ::protobuf::Message for DeviceInfo {
|
||||
if self.device_status != 0 {
|
||||
my_size += ::protobuf::rt::uint32_size(3, self.device_status);
|
||||
}
|
||||
if self.client_secret != false {
|
||||
my_size += 1 + 1;
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
|
||||
self.special_fields.cached_size().set(my_size as u32);
|
||||
my_size
|
||||
@@ -611,6 +1098,9 @@ impl ::protobuf::Message for DeviceInfo {
|
||||
if self.device_status != 0 {
|
||||
os.write_uint32(3, self.device_status)?;
|
||||
}
|
||||
if self.client_secret != false {
|
||||
os.write_bool(4, self.client_secret)?;
|
||||
}
|
||||
os.write_unknown_fields(self.special_fields.unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
@@ -631,6 +1121,7 @@ impl ::protobuf::Message for DeviceInfo {
|
||||
self.name.clear();
|
||||
self.virtual_ip = 0;
|
||||
self.device_status = 0;
|
||||
self.client_secret = false;
|
||||
self.special_fields.clear();
|
||||
}
|
||||
|
||||
@@ -639,6 +1130,7 @@ impl ::protobuf::Message for DeviceInfo {
|
||||
name: ::std::string::String::new(),
|
||||
virtual_ip: 0,
|
||||
device_status: 0,
|
||||
client_secret: false,
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
};
|
||||
&instance
|
||||
@@ -821,8 +1313,10 @@ pub struct PunchInfo {
|
||||
pub local_ip: u32,
|
||||
// @@protoc_insertion_point(field:PunchInfo.local_port)
|
||||
pub local_port: u32,
|
||||
// @@protoc_insertion_point(field:PunchInfo.public_ipv6_list)
|
||||
pub public_ipv6_list: ::std::vec::Vec<::std::vec::Vec<u8>>,
|
||||
// @@protoc_insertion_point(field:PunchInfo.ipv6)
|
||||
pub ipv6: ::std::vec::Vec<u8>,
|
||||
// @@protoc_insertion_point(field:PunchInfo.ipv6_port)
|
||||
pub ipv6_port: u32,
|
||||
// special fields
|
||||
// @@protoc_insertion_point(special_field:PunchInfo.special_fields)
|
||||
pub special_fields: ::protobuf::SpecialFields,
|
||||
@@ -840,7 +1334,7 @@ impl PunchInfo {
|
||||
}
|
||||
|
||||
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
|
||||
let mut fields = ::std::vec::Vec::with_capacity(8);
|
||||
let mut fields = ::std::vec::Vec::with_capacity(9);
|
||||
let mut oneofs = ::std::vec::Vec::with_capacity(0);
|
||||
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
|
||||
"public_ip_list",
|
||||
@@ -877,10 +1371,15 @@ impl PunchInfo {
|
||||
|m: &PunchInfo| { &m.local_port },
|
||||
|m: &mut PunchInfo| { &mut m.local_port },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
|
||||
"public_ipv6_list",
|
||||
|m: &PunchInfo| { &m.public_ipv6_list },
|
||||
|m: &mut PunchInfo| { &mut m.public_ipv6_list },
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"ipv6",
|
||||
|m: &PunchInfo| { &m.ipv6 },
|
||||
|m: &mut PunchInfo| { &mut m.ipv6 },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
|
||||
"ipv6_port",
|
||||
|m: &PunchInfo| { &m.ipv6_port },
|
||||
|m: &mut PunchInfo| { &mut m.ipv6_port },
|
||||
));
|
||||
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<PunchInfo>(
|
||||
"PunchInfo",
|
||||
@@ -925,7 +1424,10 @@ impl ::protobuf::Message for PunchInfo {
|
||||
self.local_port = is.read_uint32()?;
|
||||
},
|
||||
74 => {
|
||||
self.public_ipv6_list.push(is.read_bytes()?);
|
||||
self.ipv6 = is.read_bytes()?;
|
||||
},
|
||||
80 => {
|
||||
self.ipv6_port = is.read_uint32()?;
|
||||
},
|
||||
tag => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
|
||||
@@ -958,9 +1460,12 @@ impl ::protobuf::Message for PunchInfo {
|
||||
if self.local_port != 0 {
|
||||
my_size += ::protobuf::rt::uint32_size(8, self.local_port);
|
||||
}
|
||||
for value in &self.public_ipv6_list {
|
||||
my_size += ::protobuf::rt::bytes_size(9, &value);
|
||||
};
|
||||
if !self.ipv6.is_empty() {
|
||||
my_size += ::protobuf::rt::bytes_size(9, &self.ipv6);
|
||||
}
|
||||
if self.ipv6_port != 0 {
|
||||
my_size += ::protobuf::rt::uint32_size(10, self.ipv6_port);
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
|
||||
self.special_fields.cached_size().set(my_size as u32);
|
||||
my_size
|
||||
@@ -988,9 +1493,12 @@ impl ::protobuf::Message for PunchInfo {
|
||||
if self.local_port != 0 {
|
||||
os.write_uint32(8, self.local_port)?;
|
||||
}
|
||||
for v in &self.public_ipv6_list {
|
||||
os.write_bytes(9, &v)?;
|
||||
};
|
||||
if !self.ipv6.is_empty() {
|
||||
os.write_bytes(9, &self.ipv6)?;
|
||||
}
|
||||
if self.ipv6_port != 0 {
|
||||
os.write_uint32(10, self.ipv6_port)?;
|
||||
}
|
||||
os.write_unknown_fields(self.special_fields.unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
@@ -1015,7 +1523,8 @@ impl ::protobuf::Message for PunchInfo {
|
||||
self.reply = false;
|
||||
self.local_ip = 0;
|
||||
self.local_port = 0;
|
||||
self.public_ipv6_list.clear();
|
||||
self.ipv6.clear();
|
||||
self.ipv6_port = 0;
|
||||
self.special_fields.clear();
|
||||
}
|
||||
|
||||
@@ -1028,7 +1537,8 @@ impl ::protobuf::Message for PunchInfo {
|
||||
reply: false,
|
||||
local_ip: 0,
|
||||
local_port: 0,
|
||||
public_ipv6_list: ::std::vec::Vec::new(),
|
||||
ipv6: ::std::vec::Vec::new(),
|
||||
ipv6_port: 0,
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
};
|
||||
&instance
|
||||
@@ -1107,33 +1617,42 @@ impl PunchNatType {
|
||||
}
|
||||
|
||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||
\n\rmessage.proto\"\xd6\x01\n\x13RegistrationRequest\x12\x14\n\x05token\
|
||||
\x18\x01\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\tR\
|
||||
\x08deviceId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\x07\
|
||||
is_fast\x18\x04\x20\x01(\x08R\x06isFast\x12\x18\n\x07version\x18\x05\x20\
|
||||
\x01(\tR\x07version\x12\x1d\n\nvirtual_ip\x18\x06\x20\x01(\x07R\tvirtual\
|
||||
Ip\x12&\n\x0fallow_ip_change\x18\x07\x20\x01(\x08R\rallowIpChange\"\xb3\
|
||||
\x02\n\x14RegistrationResponse\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\
|
||||
\x07R\tvirtualIp\x12'\n\x0fvirtual_gateway\x18\x02\x20\x01(\x07R\x0evirt\
|
||||
ualGateway\x12'\n\x0fvirtual_netmask\x18\x03\x20\x01(\x07R\x0evirtualNet\
|
||||
mask\x12\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05epoch\x125\n\x10device_in\
|
||||
fo_list\x18\x05\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\x12\x1b\
|
||||
\n\tpublic_ip\x18\x06\x20\x01(\x07R\x08publicIp\x12\x1f\n\x0bpublic_port\
|
||||
\x18\x07\x20\x01(\rR\npublicPort\x12\x1f\n\x0bpublic_ipv6\x18\x08\x20\
|
||||
\x01(\x0cR\npublicIpv6\"d\n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\
|
||||
\x01(\tR\x04name\x12\x1d\n\nvirtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\
|
||||
\x12#\n\rdevice_status\x18\x03\x20\x01(\rR\x0cdeviceStatus\"Y\n\nDeviceL\
|
||||
ist\x12\x14\n\x05epoch\x18\x01\x20\x01(\rR\x05epoch\x125\n\x10device_inf\
|
||||
o_list\x18\x02\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xa2\x02\
|
||||
\n\tPunchInfo\x12$\n\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIp\
|
||||
List\x12\x1f\n\x0bpublic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11\
|
||||
public_port_range\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12(\n\x08nat_t\
|
||||
ype\x18\x05\x20\x01(\x0e2\r.PunchNatTypeR\x07natType\x12\x14\n\x05reply\
|
||||
\x18\x06\x20\x01(\x08R\x05reply\x12\x19\n\x08local_ip\x18\x07\x20\x01(\
|
||||
\x07R\x07localIp\x12\x1d\n\nlocal_port\x18\x08\x20\x01(\rR\tlocalPort\
|
||||
\x12(\n\x10public_ipv6_list\x18\t\x20\x03(\x0cR\x0epublicIpv6List*'\n\
|
||||
\x0cPunchNatType\x12\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\x10\x01b\x06\
|
||||
proto3\
|
||||
\n\rmessage.proto\"D\n\x10HandshakeRequest\x12\x18\n\x07version\x18\x01\
|
||||
\x20\x01(\tR\x07version\x12\x16\n\x06secret\x18\x02\x20\x01(\x08R\x06sec\
|
||||
ret\"\x83\x01\n\x11HandshakeResponse\x12\x18\n\x07version\x18\x01\x20\
|
||||
\x01(\tR\x07version\x12\x16\n\x06secret\x18\x02\x20\x01(\x08R\x06secret\
|
||||
\x12\x1d\n\npublic_key\x18\x03\x20\x01(\x0cR\tpublicKey\x12\x1d\n\nkey_f\
|
||||
inger\x18\x04\x20\x01(\tR\tkeyFinger\"@\n\x16SecretHandshakeRequest\x12\
|
||||
\x14\n\x05token\x18\x01\x20\x01(\tR\x05token\x12\x10\n\x03key\x18\x02\
|
||||
\x20\x01(\x0cR\x03key\"\xfb\x01\n\x13RegistrationRequest\x12\x14\n\x05to\
|
||||
ken\x18\x01\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\t\
|
||||
R\x08deviceId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\
|
||||
\x07is_fast\x18\x04\x20\x01(\x08R\x06isFast\x12\x18\n\x07version\x18\x05\
|
||||
\x20\x01(\tR\x07version\x12\x1d\n\nvirtual_ip\x18\x06\x20\x01(\x07R\tvir\
|
||||
tualIp\x12&\n\x0fallow_ip_change\x18\x07\x20\x01(\x08R\rallowIpChange\
|
||||
\x12#\n\rclient_secret\x18\x08\x20\x01(\x08R\x0cclientSecret\"\xb3\x02\n\
|
||||
\x14RegistrationResponse\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tvi\
|
||||
rtualIp\x12'\n\x0fvirtual_gateway\x18\x02\x20\x01(\x07R\x0evirtualGatewa\
|
||||
y\x12'\n\x0fvirtual_netmask\x18\x03\x20\x01(\x07R\x0evirtualNetmask\x12\
|
||||
\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\
|
||||
\x18\x05\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\x12\x1b\n\tpubl\
|
||||
ic_ip\x18\x06\x20\x01(\x07R\x08publicIp\x12\x1f\n\x0bpublic_port\x18\x07\
|
||||
\x20\x01(\rR\npublicPort\x12\x1f\n\x0bpublic_ipv6\x18\x08\x20\x01(\x0cR\
|
||||
\npublicIpv6\"\x89\x01\n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\x01(\
|
||||
\tR\x04name\x12\x1d\n\nvirtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\x12#\
|
||||
\n\rdevice_status\x18\x03\x20\x01(\rR\x0cdeviceStatus\x12#\n\rclient_sec\
|
||||
ret\x18\x04\x20\x01(\x08R\x0cclientSecret\"Y\n\nDeviceList\x12\x14\n\x05\
|
||||
epoch\x18\x01\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x02\
|
||||
\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xa9\x02\n\tPunchInfo\
|
||||
\x12$\n\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIpList\x12\x1f\
|
||||
\n\x0bpublic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11public_port_\
|
||||
range\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12(\n\x08nat_type\x18\x05\
|
||||
\x20\x01(\x0e2\r.PunchNatTypeR\x07natType\x12\x14\n\x05reply\x18\x06\x20\
|
||||
\x01(\x08R\x05reply\x12\x19\n\x08local_ip\x18\x07\x20\x01(\x07R\x07local\
|
||||
Ip\x12\x1d\n\nlocal_port\x18\x08\x20\x01(\rR\tlocalPort\x12\x12\n\x04ipv\
|
||||
6\x18\t\x20\x01(\x0cR\x04ipv6\x12\x1b\n\tipv6_port\x18\n\x20\x01(\rR\x08\
|
||||
ipv6Port*'\n\x0cPunchNatType\x12\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\
|
||||
\x10\x01b\x06proto3\
|
||||
";
|
||||
|
||||
/// `FileDescriptorProto` object which was a source for this generated file
|
||||
@@ -1151,7 +1670,10 @@ pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor {
|
||||
file_descriptor.get(|| {
|
||||
let generated_file_descriptor = generated_file_descriptor_lazy.get(|| {
|
||||
let mut deps = ::std::vec::Vec::with_capacity(0);
|
||||
let mut messages = ::std::vec::Vec::with_capacity(5);
|
||||
let mut messages = ::std::vec::Vec::with_capacity(8);
|
||||
messages.push(HandshakeRequest::generated_message_descriptor_data());
|
||||
messages.push(HandshakeResponse::generated_message_descriptor_data());
|
||||
messages.push(SecretHandshakeRequest::generated_message_descriptor_data());
|
||||
messages.push(RegistrationRequest::generated_message_descriptor_data());
|
||||
messages.push(RegistrationResponse::generated_message_descriptor_data());
|
||||
messages.push(DeviceInfo::generated_message_descriptor_data());
|
||||
|
||||
@@ -0,0 +1,338 @@
|
||||
use std::{fmt, io};
|
||||
|
||||
pub const ENCRYPTION_RESERVED: usize = 32 + 12;
|
||||
pub const AES_GCM_ENCRYPTION_RESERVED: usize = 32;
|
||||
pub const RSA_ENCRYPTION_RESERVED: usize = 32;
|
||||
|
||||
/* aes_gcm加密数据体
|
||||
0 15 31
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 数据体 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| random(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| tag(32) |
|
||||
| tag(32) |
|
||||
| tag(32) |
|
||||
| tag(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| finger(32) |
|
||||
| finger(32) |
|
||||
| finger(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
注:finger用于快速校验数据是否被修改,上层可使用token、协议头参与计算finger,
|
||||
确保服务端和客户端都能感知修改(服务端不能解密也能校验指纹)
|
||||
*/
|
||||
pub struct SecretBody<B> {
|
||||
buffer: B,
|
||||
exist_finger: bool,
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> SecretBody<B> {
|
||||
pub fn new(buffer: B, exist_finger: bool) -> io::Result<SecretBody<B>> {
|
||||
let len = buffer.as_ref().len();
|
||||
let min_len = if exist_finger { 32 } else { 32 - 12 };
|
||||
// 不能大于udp最大载荷长度
|
||||
if len < min_len || len > 65535 - 20 - 8 - 12 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"SecretBody length overflow",
|
||||
));
|
||||
}
|
||||
Ok(SecretBody {
|
||||
buffer,
|
||||
exist_finger,
|
||||
})
|
||||
}
|
||||
pub fn random(&self) -> u32 {
|
||||
let mut end = self.buffer.as_ref().len() - 16;
|
||||
if self.exist_finger {
|
||||
end -= 12;
|
||||
}
|
||||
u32::from_be_bytes(self.buffer.as_ref()[end - 4..end].try_into().unwrap())
|
||||
}
|
||||
pub fn body(&self) -> &[u8] {
|
||||
let mut end = self.buffer.as_ref().len() - 16;
|
||||
if self.exist_finger {
|
||||
end -= 12;
|
||||
}
|
||||
&self.buffer.as_ref()[..end]
|
||||
}
|
||||
pub fn tag(&self) -> &[u8] {
|
||||
let mut end = self.buffer.as_ref().len();
|
||||
if self.exist_finger {
|
||||
end -= 12;
|
||||
}
|
||||
&self.buffer.as_ref()[end - 16..end]
|
||||
}
|
||||
/// 数据部分+tag部分
|
||||
pub fn en_body(&self) -> &[u8] {
|
||||
let mut end = self.buffer.as_ref().len();
|
||||
if self.exist_finger {
|
||||
end -= 12;
|
||||
}
|
||||
&self.buffer.as_ref()[..end]
|
||||
}
|
||||
pub fn finger(&self) -> &[u8] {
|
||||
if self.exist_finger {
|
||||
let end = self.buffer.as_ref().len();
|
||||
&self.buffer.as_ref()[end - 12..end]
|
||||
} else {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
self.buffer.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> SecretBody<B> {
|
||||
pub fn set_random(&mut self, random: u32) {
|
||||
let mut end = self.buffer.as_ref().len() - 16;
|
||||
if self.exist_finger {
|
||||
end -= 12;
|
||||
}
|
||||
self.buffer.as_mut()[end - 4..end].copy_from_slice(&random.to_be_bytes());
|
||||
}
|
||||
|
||||
pub fn set_tag(&mut self, tag: &[u8]) -> io::Result<()> {
|
||||
if tag.len() != 16 {
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "tag.len != 16"));
|
||||
}
|
||||
let mut end = self.buffer.as_ref().len();
|
||||
if self.exist_finger {
|
||||
end -= 12;
|
||||
}
|
||||
self.buffer.as_mut()[end - 16..end].copy_from_slice(tag);
|
||||
Ok(())
|
||||
}
|
||||
pub fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> {
|
||||
if self.exist_finger {
|
||||
if finger.len() != 12 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"finger.len != 12",
|
||||
));
|
||||
}
|
||||
let end = self.buffer.as_ref().len();
|
||||
self.buffer.as_mut()[end - 12..end].copy_from_slice(finger);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"not exist finger",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// 数据部分
|
||||
pub fn body_mut(&mut self) -> &mut [u8] {
|
||||
let mut end = self.buffer.as_ref().len() - 16;
|
||||
if self.exist_finger {
|
||||
end -= 12;
|
||||
}
|
||||
&mut self.buffer.as_mut()[..end]
|
||||
}
|
||||
pub fn tag_mut(&mut self) -> &mut [u8] {
|
||||
let mut end = self.buffer.as_ref().len();
|
||||
if self.exist_finger {
|
||||
end -= 12;
|
||||
}
|
||||
&mut self.buffer.as_mut()[end - 16..end]
|
||||
}
|
||||
/// 数据部分+tag部分
|
||||
pub fn en_body_mut(&mut self) -> &mut [u8] {
|
||||
let mut end = self.buffer.as_ref().len();
|
||||
if self.exist_finger {
|
||||
end -= 12;
|
||||
}
|
||||
&mut self.buffer.as_mut()[..end]
|
||||
}
|
||||
pub fn buffer_mut(&mut self) -> &mut [u8] {
|
||||
self.buffer.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> fmt::Debug for SecretBody<B> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("SecretBody")
|
||||
.field("random", &self.random())
|
||||
.field("body", &self.body())
|
||||
.field("tag", &self.tag())
|
||||
.field("finger", &self.finger())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
/* aes_cbc加密数据体
|
||||
0 15 31
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 数据体 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| random(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| finger(32) |
|
||||
| finger(32) |
|
||||
| finger(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
注:finger用于快速校验数据是否被修改,上层可使用token、协议头参与计算finger,
|
||||
确保服务端和客户端都能感知修改(服务端不能解密也能校验指纹)
|
||||
*/
|
||||
pub struct AesCbcSecretBody<B> {
|
||||
buffer: B,
|
||||
exist_finger: bool,
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> AesCbcSecretBody<B> {
|
||||
pub fn new(buffer: B, exist_finger: bool) -> io::Result<AesCbcSecretBody<B>> {
|
||||
let len = buffer.as_ref().len();
|
||||
let min_len = if exist_finger { 16 } else { 16 - 12 };
|
||||
// 不能大于udp最大载荷长度
|
||||
if len < min_len || len > 65535 - 20 - 8 - 12 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"AesCbcSecretBody length overflow",
|
||||
));
|
||||
}
|
||||
Ok(AesCbcSecretBody {
|
||||
buffer,
|
||||
exist_finger,
|
||||
})
|
||||
}
|
||||
pub fn en_body(&self) -> &[u8] {
|
||||
let mut end = self.buffer.as_ref().len();
|
||||
if self.exist_finger {
|
||||
end -= 12;
|
||||
}
|
||||
&self.buffer.as_ref()[..end]
|
||||
}
|
||||
pub fn finger(&self) -> &[u8] {
|
||||
if self.exist_finger {
|
||||
let end = self.buffer.as_ref().len();
|
||||
&self.buffer.as_ref()[end - 12..end]
|
||||
} else {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> AesCbcSecretBody<B> {
|
||||
pub fn set_random(&mut self, random: u32) {
|
||||
let mut end = self.buffer.as_ref().len();
|
||||
if self.exist_finger {
|
||||
end -= 12;
|
||||
}
|
||||
self.buffer.as_mut()[end - 4..end].copy_from_slice(&random.to_be_bytes());
|
||||
}
|
||||
pub fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> {
|
||||
if self.exist_finger {
|
||||
if finger.len() != 12 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"finger.len != 12",
|
||||
));
|
||||
}
|
||||
let end = self.buffer.as_ref().len();
|
||||
self.buffer.as_mut()[end - 12..end].copy_from_slice(finger);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"cbc not exist finger",
|
||||
))
|
||||
}
|
||||
}
|
||||
pub fn en_body_mut(&mut self) -> &mut [u8] {
|
||||
let mut end = self.buffer.as_ref().len();
|
||||
if self.exist_finger {
|
||||
end -= 12;
|
||||
}
|
||||
&mut self.buffer.as_mut()[..end]
|
||||
}
|
||||
}
|
||||
|
||||
/* rsa加密数据体
|
||||
0 15 31
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 数据体(n) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| random(32) |
|
||||
| random(32) |
|
||||
| random(32) |
|
||||
| random(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| finger(32) |
|
||||
| finger(32) |
|
||||
| finger(32) |
|
||||
| finger(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
pub struct RsaSecretBody<B> {
|
||||
buffer: B,
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> RsaSecretBody<B> {
|
||||
pub fn new(buffer: B) -> io::Result<RsaSecretBody<B>> {
|
||||
let len = buffer.as_ref().len();
|
||||
// 不能大于udp最大载荷长度
|
||||
if len < 32 || len > 65535 - 20 - 8 - 12 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"length overflow",
|
||||
));
|
||||
}
|
||||
Ok(RsaSecretBody { buffer })
|
||||
}
|
||||
pub fn data(&self) -> &[u8] {
|
||||
let end = self.buffer.as_ref().len() - 32;
|
||||
&self.buffer.as_ref()[..end]
|
||||
}
|
||||
pub fn random(&self) -> &[u8] {
|
||||
let end = self.buffer.as_ref().len() - 16;
|
||||
&self.buffer.as_ref()[end - 16..end]
|
||||
}
|
||||
pub fn body(&self) -> &[u8] {
|
||||
let end = self.buffer.as_ref().len() - 16;
|
||||
&self.buffer.as_ref()[..end]
|
||||
}
|
||||
pub fn finger(&self) -> &[u8] {
|
||||
let end = self.buffer.as_ref().len() - 16;
|
||||
&self.buffer.as_ref()[end..]
|
||||
}
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
&self.buffer.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> RsaSecretBody<B> {
|
||||
pub fn set_random(&mut self, random: &[u8]) -> io::Result<()> {
|
||||
if random.len() != 16 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"random.len != 16",
|
||||
));
|
||||
}
|
||||
let end = self.buffer.as_ref().len() - 16;
|
||||
self.buffer.as_mut()[end - 16..end].copy_from_slice(random);
|
||||
Ok(())
|
||||
}
|
||||
pub fn random_mut(&mut self) -> &mut [u8] {
|
||||
let end = self.buffer.as_ref().len() - 16;
|
||||
&mut self.buffer.as_mut()[end - 16..end]
|
||||
}
|
||||
pub fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> {
|
||||
if finger.len() != 16 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"finger.len != 16",
|
||||
));
|
||||
}
|
||||
let end = self.buffer.as_ref().len();
|
||||
self.buffer.as_mut()[end - 16..end].copy_from_slice(finger);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::{fmt, io};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{fmt, io};
|
||||
|
||||
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
||||
pub enum Protocol {
|
||||
|
||||
@@ -7,6 +7,7 @@ pub enum Protocol {
|
||||
AddressExhausted,
|
||||
IpAlreadyExists,
|
||||
InvalidIp,
|
||||
NoKey,
|
||||
Other(u8),
|
||||
}
|
||||
|
||||
@@ -18,6 +19,7 @@ impl From<u8> for Protocol {
|
||||
3 => Self::AddressExhausted,
|
||||
4 => Self::IpAlreadyExists,
|
||||
5 => Self::InvalidIp,
|
||||
6 => Self::NoKey,
|
||||
val => Self::Other(val),
|
||||
}
|
||||
}
|
||||
@@ -31,6 +33,7 @@ impl Into<u8> for Protocol {
|
||||
Protocol::AddressExhausted => 3,
|
||||
Protocol::IpAlreadyExists => 4,
|
||||
Protocol::InvalidIp => 5,
|
||||
Protocol::NoKey => 6,
|
||||
Protocol::Other(val) => val,
|
||||
}
|
||||
}
|
||||
@@ -42,6 +45,7 @@ pub enum InErrorPacket<B> {
|
||||
AddressExhausted,
|
||||
IpAlreadyExists,
|
||||
InvalidIp,
|
||||
NoKey,
|
||||
OtherError(ErrorPacket<B>),
|
||||
}
|
||||
|
||||
@@ -53,6 +57,7 @@ impl<B: AsRef<[u8]>> InErrorPacket<B> {
|
||||
Protocol::AddressExhausted => Ok(InErrorPacket::AddressExhausted),
|
||||
Protocol::IpAlreadyExists => Ok(InErrorPacket::IpAlreadyExists),
|
||||
Protocol::InvalidIp => Ok(InErrorPacket::InvalidIp),
|
||||
Protocol::NoKey => Ok(InErrorPacket::NoKey),
|
||||
Protocol::Other(_) => Ok(InErrorPacket::OtherError(ErrorPacket::new(buffer)?)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@ use std::net::Ipv4Addr;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum Protocol {
|
||||
Icmp,
|
||||
Igmp,
|
||||
Ipv4,
|
||||
Ipv4Broadcast,
|
||||
Unknown(u8),
|
||||
@@ -13,8 +11,6 @@ pub enum Protocol {
|
||||
impl From<u8> for Protocol {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
1 => Protocol::Icmp,
|
||||
2 => Protocol::Igmp,
|
||||
4 => Protocol::Ipv4,
|
||||
201 => Protocol::Ipv4Broadcast,
|
||||
val => Protocol::Unknown(val),
|
||||
@@ -25,8 +21,6 @@ impl From<u8> for Protocol {
|
||||
impl Into<u8> for Protocol {
|
||||
fn into(self) -> u8 {
|
||||
match self {
|
||||
Protocol::Icmp => 1,
|
||||
Protocol::Igmp => 2,
|
||||
Protocol::Ipv4 => 4,
|
||||
Protocol::Ipv4Broadcast => 201,
|
||||
Protocol::Unknown(val) => val,
|
||||
@@ -34,21 +28,21 @@ impl Into<u8> for Protocol {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BroadcastPacketEnd<B> {
|
||||
pub struct BroadcastPacket<B> {
|
||||
buffer: B,
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
|
||||
impl<B: AsRef<[u8]>> BroadcastPacket<B> {
|
||||
pub fn unchecked(buffer: B) -> Self {
|
||||
Self { buffer }
|
||||
}
|
||||
pub fn new(buffer: B) -> io::Result<Self> {
|
||||
let len = buffer.as_ref().len();
|
||||
let packet = Self::unchecked(buffer);
|
||||
if len < 1 || packet.len() != len {
|
||||
if len < 2 + 4 || packet.addr_num() == 0 {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"InvalidData",
|
||||
"BroadcastPacket InvalidData",
|
||||
))
|
||||
} else {
|
||||
Ok(packet)
|
||||
@@ -56,50 +50,66 @@ impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
|
||||
pub fn len(&self) -> usize {
|
||||
1 + self.num() as usize * 4
|
||||
}
|
||||
pub fn num(&self) -> u8 {
|
||||
let len = self.buffer.as_ref().len();
|
||||
self.buffer.as_ref()[len - 1]
|
||||
impl<B: AsRef<[u8]>> BroadcastPacket<B> {
|
||||
pub fn addr_num(&self) -> u8 {
|
||||
self.buffer.as_ref()[0]
|
||||
}
|
||||
/// 已经发送给了这些地址
|
||||
/// 从尾往头拿
|
||||
pub fn addresses(&self) -> Vec<Ipv4Addr> {
|
||||
let num = self.num() as usize;
|
||||
let num = self.addr_num() as usize;
|
||||
let mut list = Vec::with_capacity(num);
|
||||
let buf = self.buffer.as_ref();
|
||||
let mut offset = buf.len() + 4 - 2;
|
||||
let mut offset = 1;
|
||||
for _ in 0..num {
|
||||
offset -= 4;
|
||||
list.push(Ipv4Addr::new(buf[offset - 3], buf[offset - 2], buf[offset - 1], buf[offset]));
|
||||
list.push(Ipv4Addr::new(
|
||||
buf[offset],
|
||||
buf[offset + 1],
|
||||
buf[offset + 2],
|
||||
buf[offset + 3],
|
||||
));
|
||||
offset += 4;
|
||||
}
|
||||
list
|
||||
}
|
||||
pub fn data(&self) -> io::Result<&[u8]> {
|
||||
let start = 1 + self.addr_num() as usize * 4;
|
||||
if start > self.buffer.as_ref().len() {
|
||||
Err(io::Error::new(io::ErrorKind::InvalidData, "InvalidData"))
|
||||
} else {
|
||||
Ok(&self.buffer.as_ref()[start..])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> BroadcastPacketEnd<B> {
|
||||
/// 从头往尾放
|
||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> BroadcastPacket<B> {
|
||||
pub fn set_address(&mut self, addr: &[Ipv4Addr]) -> io::Result<()> {
|
||||
let buf = self.buffer.as_mut();
|
||||
if buf.len() < 1 + addr.len() * 4 || addr.len() > u8::MAX as usize {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"InvalidData",
|
||||
"addr invalid data",
|
||||
))
|
||||
} else {
|
||||
let mut offset = 0;
|
||||
buf[0] = addr.len() as u8;
|
||||
let mut offset = 1;
|
||||
for ip in addr {
|
||||
buf[offset..offset + 4].copy_from_slice(&ip.octets());
|
||||
offset += 4;
|
||||
}
|
||||
self.buffer.as_mut()[offset] = addr.len() as u8;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
pub fn set_data(&mut self, data: &[u8]) -> io::Result<()> {
|
||||
let num = self.addr_num() as usize;
|
||||
let start = 1 + 4 * num;
|
||||
let buf = self.buffer.as_mut();
|
||||
if start >= buf.len() || start + data.len() != buf.len() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"data invalid data",
|
||||
));
|
||||
}
|
||||
buf[start..].copy_from_slice(data);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+79
-11
@@ -1,3 +1,4 @@
|
||||
use crate::protocol::body::ENCRYPTION_RESERVED;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{fmt, io};
|
||||
|
||||
@@ -5,7 +6,7 @@ use std::{fmt, io};
|
||||
0 15 31
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| p|unused| 版本(4) | 协议(8) | 上层协议(8) | 初始ttl(4) | 生存时间(4) |
|
||||
|e |s |u |u| 版本(4) | 协议(8) | 上层协议(8) | 初始ttl(4) | 生存时间(4) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 源ip地址(32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
@@ -13,13 +14,16 @@ use std::{fmt, io};
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 数据体 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
注:e为是否加密标志,s为服务端通信包标志,u未使用
|
||||
*/
|
||||
pub const HEAD_LEN: usize = 12;
|
||||
|
||||
pub mod body;
|
||||
pub mod control_packet;
|
||||
pub mod error_packet;
|
||||
pub mod service_packet;
|
||||
pub mod ip_turn_packet;
|
||||
pub mod other_turn_packet;
|
||||
pub mod service_packet;
|
||||
|
||||
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
||||
pub enum Version {
|
||||
@@ -91,33 +95,68 @@ pub const MAX_SOURCE: u8 = 0b11110000;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct NetPacket<B> {
|
||||
data_len: usize,
|
||||
buffer: B,
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> NetPacket<B> {
|
||||
pub fn new(buffer: B) -> io::Result<NetPacket<B>> {
|
||||
let len = buffer.as_ref().len();
|
||||
// 不能大于udp最大载荷长度
|
||||
if len < 12 || len > 65535 - 20 - 8 {
|
||||
let data_len = buffer.as_ref().len();
|
||||
Self::new0(data_len, buffer)
|
||||
}
|
||||
pub fn new_encrypt(buffer: B) -> io::Result<NetPacket<B>> {
|
||||
if 12 + ENCRYPTION_RESERVED > buffer.as_ref().len() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"length overflow",
|
||||
));
|
||||
}
|
||||
Ok(NetPacket { buffer })
|
||||
//加密需要预留ENCRYPTION_RESERVED字节
|
||||
let data_len = buffer.as_ref().len() - ENCRYPTION_RESERVED;
|
||||
Self::new0(data_len, buffer)
|
||||
}
|
||||
pub fn new0(data_len: usize, buffer: B) -> io::Result<NetPacket<B>> {
|
||||
if data_len > buffer.as_ref().len() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"length overflow",
|
||||
));
|
||||
}
|
||||
// 不能大于udp最大载荷长度
|
||||
if data_len < 12 || buffer.as_ref().len() > 65535 - 20 - 8 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"length overflow",
|
||||
));
|
||||
}
|
||||
Ok(NetPacket { data_len, buffer })
|
||||
}
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
&self.buffer.as_ref()[..self.data_len]
|
||||
}
|
||||
pub fn raw_buffer(&self) -> &[u8] {
|
||||
self.buffer.as_ref()
|
||||
}
|
||||
pub fn data_len(&self) -> usize {
|
||||
self.data_len
|
||||
}
|
||||
pub fn reserve(&self) -> usize {
|
||||
self.buffer.as_ref().len() - self.data_len
|
||||
}
|
||||
pub fn into_buffer(self) -> B {
|
||||
self.buffer
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> NetPacket<B> {
|
||||
/// 数据加密
|
||||
pub fn is_encrypt(&self) -> bool {
|
||||
self.buffer.as_ref()[0] & 0x80 == 0x80
|
||||
}
|
||||
/// 网关通信的标识
|
||||
pub fn is_gateway(&self) -> bool {
|
||||
self.buffer.as_ref()[0] & 0x50 == 0x50
|
||||
}
|
||||
pub fn version(&self) -> Version {
|
||||
Version::from(self.buffer.as_ref()[0] & 0x0F)
|
||||
}
|
||||
@@ -142,13 +181,13 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
|
||||
Ipv4Addr::from(tmp)
|
||||
}
|
||||
pub fn payload(&self) -> &[u8] {
|
||||
&self.buffer.as_ref()[12..]
|
||||
&self.buffer.as_ref()[12..self.data_len]
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
||||
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) {
|
||||
if is_encrypt {
|
||||
@@ -157,6 +196,13 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
||||
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0x7F
|
||||
};
|
||||
}
|
||||
pub fn set_gateway_flag(&mut self, is_gateway: bool) {
|
||||
if is_gateway {
|
||||
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x50
|
||||
} else {
|
||||
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF
|
||||
};
|
||||
}
|
||||
pub fn set_version(&mut self, version: Version) {
|
||||
let v: u8 = version.into();
|
||||
self.buffer.as_mut()[0] = (self.buffer.as_ref()[0] & 0xF0) | (0x0F & v);
|
||||
@@ -182,11 +228,31 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
||||
pub fn set_destination(&mut self, destination: Ipv4Addr) {
|
||||
self.buffer.as_mut()[8..12].copy_from_slice(&destination.octets());
|
||||
}
|
||||
pub fn set_payload(&mut self, payload: &[u8]) {
|
||||
self.buffer.as_mut()[12..payload.len() + 12].copy_from_slice(payload);
|
||||
pub fn set_payload(&mut self, payload: &[u8]) -> io::Result<()> {
|
||||
if self.data_len - 12 != payload.len() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"data_len - 12 != payload.len",
|
||||
));
|
||||
}
|
||||
self.buffer.as_mut()[12..self.data_len].copy_from_slice(payload);
|
||||
Ok(())
|
||||
}
|
||||
pub fn payload_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.buffer.as_mut()[12..]
|
||||
&mut self.buffer.as_mut()[12..self.data_len]
|
||||
}
|
||||
pub fn set_data_len(&mut self, data_len: usize) -> io::Result<()> {
|
||||
if data_len > self.buffer.as_ref().len() || data_len < 12 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"data_len invalid",
|
||||
));
|
||||
}
|
||||
self.data_len = data_len;
|
||||
Ok(())
|
||||
}
|
||||
pub fn set_data_len_max(&mut self) {
|
||||
self.data_len = self.buffer.as_ref().len();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,6 +260,8 @@ impl<B: AsRef<[u8]>> fmt::Debug for NetPacket<B> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("NetPacket")
|
||||
.field("version", &self.version())
|
||||
.field("gateway", &self.is_gateway())
|
||||
.field("encrypt", &self.is_encrypt())
|
||||
.field("protocol", &self.protocol())
|
||||
.field("transport_protocol", &self.transport_protocol())
|
||||
.field("ttl", &self.ttl())
|
||||
|
||||
@@ -8,6 +8,11 @@ pub enum Protocol {
|
||||
PollDeviceList,
|
||||
/// 推送设备列表
|
||||
PushDeviceList,
|
||||
/// 和服务端握手
|
||||
HandshakeRequest,
|
||||
HandshakeResponse,
|
||||
SecretHandshakeRequest,
|
||||
SecretHandshakeResponse,
|
||||
Unknown(u8),
|
||||
}
|
||||
|
||||
@@ -18,6 +23,10 @@ impl From<u8> for Protocol {
|
||||
2 => Self::RegistrationResponse,
|
||||
3 => Self::PollDeviceList,
|
||||
4 => Self::PushDeviceList,
|
||||
5 => Self::HandshakeRequest,
|
||||
6 => Self::HandshakeResponse,
|
||||
7 => Self::SecretHandshakeRequest,
|
||||
8 => Self::SecretHandshakeResponse,
|
||||
val => Self::Unknown(val),
|
||||
}
|
||||
}
|
||||
@@ -30,6 +39,10 @@ impl Into<u8> for Protocol {
|
||||
Self::RegistrationResponse => 2,
|
||||
Self::PollDeviceList => 3,
|
||||
Self::PushDeviceList => 4,
|
||||
Self::HandshakeRequest => 5,
|
||||
Self::HandshakeResponse => 6,
|
||||
Self::SecretHandshakeRequest => 7,
|
||||
Self::SecretHandshakeResponse => 8,
|
||||
Self::Unknown(val) => val,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,4 +45,4 @@ impl DeviceReader {
|
||||
|
||||
pub fn create(fd: i32) -> (DeviceWriter, DeviceReader) {
|
||||
(DeviceWriter(fd as _), DeviceReader(fd as _))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,33 @@
|
||||
use crate::tun_tap_device::linux_mac::DeviceW;
|
||||
use crate::tun_tap_device::{DeviceReader, DeviceType, DeviceWriter, DriverInfo};
|
||||
use parking_lot::Mutex;
|
||||
use std::io;
|
||||
use std::net::Ipv4Addr;
|
||||
use crate::tun_tap_device::{DeviceReader, DeviceType, DeviceWriter, DriverInfo};
|
||||
use tun::Device;
|
||||
use parking_lot::Mutex;
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
use crate::tun_tap_device::linux_mac::DeviceW;
|
||||
use tun::Device;
|
||||
|
||||
pub const TUN_INTERFACE_NAME: &str = "vnt-tun";
|
||||
pub const TAP_INTERFACE_NAME: &str = "vnt-tap";
|
||||
|
||||
impl DeviceWriter {
|
||||
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> {
|
||||
pub fn change_ip(
|
||||
&self,
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
_old_netmask: Ipv4Addr,
|
||||
_old_gateway: Ipv4Addr,
|
||||
) -> io::Result<()> {
|
||||
let mut config = tun::Configuration::default();
|
||||
let broadcast_address =
|
||||
(!u32::from_be_bytes(netmask.octets())) | u32::from_be_bytes(gateway.octets());
|
||||
let broadcast_address = Ipv4Addr::from(broadcast_address);
|
||||
config
|
||||
.destination(gateway)
|
||||
.address(address)
|
||||
.netmask(netmask)
|
||||
.broadcast(broadcast_address)
|
||||
// .queues(2)
|
||||
.up();
|
||||
let mut dev = self.lock.lock();
|
||||
@@ -29,50 +42,64 @@ impl DeviceWriter {
|
||||
// add_route(name, address, netmask)?;
|
||||
// 广播和组播路由
|
||||
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
|
||||
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
|
||||
add_route(
|
||||
name,
|
||||
Ipv4Addr::from([224, 0, 0, 0]),
|
||||
Ipv4Addr::from([240, 0, 0, 0]),
|
||||
)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
|
||||
let route_add_str: String = format!(
|
||||
"ip route add {:?}/{:?} dev {}",
|
||||
address, netmask, name
|
||||
);
|
||||
let route_add_str: String = format!("ip route add {:?}/{:?} dev {}", address, netmask, name);
|
||||
let route_add_out = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(&route_add_str)
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !route_add_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: cmd:{},out:{:?}", route_add_str, route_add_out)));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!(
|
||||
"添加路由失败: cmd:{},out:{:?}",
|
||||
route_add_str, route_add_out
|
||||
),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn create_device(device_type: DeviceType,
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
mtu: u16,
|
||||
) -> io::Result<(DeviceWriter, DeviceReader,DriverInfo)> {
|
||||
pub fn create_device(
|
||||
device_type: DeviceType,
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
mtu: u16,
|
||||
) -> io::Result<(DeviceWriter, DeviceReader, DriverInfo)> {
|
||||
let mut config = tun::Configuration::default();
|
||||
|
||||
let broadcast_address =
|
||||
(!u32::from_be_bytes(netmask.octets())) | u32::from_be_bytes(gateway.octets());
|
||||
let broadcast_address = Ipv4Addr::from(broadcast_address);
|
||||
config
|
||||
.destination(gateway)
|
||||
.address(address)
|
||||
.netmask(netmask)
|
||||
.mtu(mtu.into())
|
||||
.broadcast(broadcast_address)
|
||||
// .queues(2) 用多个队列有兼容性问题
|
||||
.up();
|
||||
match device_type {
|
||||
DeviceType::Tun => {}
|
||||
DeviceType::Tun => {
|
||||
config.name(TUN_INTERFACE_NAME);
|
||||
}
|
||||
DeviceType::Tap => {
|
||||
config.name(TAP_INTERFACE_NAME);
|
||||
config.layer(tun::Layer::L2);
|
||||
}
|
||||
}
|
||||
let dev = tun::create(&config).unwrap();
|
||||
let dev = tun::create(&config).expect("tun/tap failed to create");
|
||||
let packet_information = dev.has_packet_information();
|
||||
let queue = dev.queue(0).unwrap();
|
||||
let reader = queue.reader();
|
||||
@@ -85,11 +112,13 @@ pub fn create_device(device_type: DeviceType,
|
||||
// add_route(name, address, netmask)?;
|
||||
// 广播和组播路由
|
||||
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
|
||||
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
|
||||
add_route(
|
||||
name,
|
||||
Ipv4Addr::from([224, 0, 0, 0]),
|
||||
Ipv4Addr::from([240, 0, 0, 0]),
|
||||
)?;
|
||||
let device_w = match device_type {
|
||||
DeviceType::Tun => {
|
||||
DeviceW::Tun(writer)
|
||||
}
|
||||
DeviceType::Tun => DeviceW::Tun(writer),
|
||||
DeviceType::Tap => {
|
||||
let get_mac_cmd = format!("cat /sys/class/net/{}/address", name);
|
||||
let mac_out = Command::new("sh")
|
||||
@@ -98,7 +127,10 @@ pub fn create_device(device_type: DeviceType,
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !mac_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("获取mac地址错误: {:?}", mac_out)));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("获取mac地址错误: {:?}", mac_out),
|
||||
));
|
||||
}
|
||||
let mac_str = String::from_utf8(mac_out.stdout).unwrap();
|
||||
let mut mac = [0; 6];
|
||||
@@ -111,15 +143,33 @@ pub fn create_device(device_type: DeviceType,
|
||||
};
|
||||
let driver_info = DriverInfo {
|
||||
device_type,
|
||||
name:name.to_string(),
|
||||
version:String::new(),
|
||||
name: name.to_string(),
|
||||
version: String::new(),
|
||||
mac: None,
|
||||
};
|
||||
Ok((
|
||||
DeviceWriter::new(device_w, Arc::new(Mutex::new(dev)), in_ips, address, packet_information),
|
||||
DeviceWriter::new(
|
||||
device_w,
|
||||
Arc::new(Mutex::new(dev)),
|
||||
in_ips,
|
||||
address,
|
||||
packet_information,
|
||||
),
|
||||
DeviceReader::new(reader),
|
||||
driver_info,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn delete_device(_device_type: DeviceType) {}
|
||||
pub fn delete_device(_device_type: DeviceType) {
|
||||
for name in [TUN_INTERFACE_NAME, TAP_INTERFACE_NAME] {
|
||||
let cmd = format!("ip link delete {}", name);
|
||||
let delete_tun = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(&cmd)
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !delete_tun.status.success() {
|
||||
log::warn!("删除网卡失败:{:?}", delete_tun);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,18 @@ use std::io;
|
||||
use std::sync::Arc;
|
||||
|
||||
use bytes::BufMut;
|
||||
use tun::platform::posix::{Reader, Writer};
|
||||
use packet::ethernet;
|
||||
use parking_lot::Mutex;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
use tun::platform::linux::Device;
|
||||
#[cfg(any(target_os = "macos"))]
|
||||
use tun::platform::macos::Device;
|
||||
use parking_lot::Mutex;
|
||||
use packet::ethernet;
|
||||
use tun::platform::posix::{Reader, Writer};
|
||||
|
||||
use packet::ethernet::packet::EthernetPacket;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum DeviceW {
|
||||
Tun(Writer),
|
||||
@@ -22,12 +23,8 @@ pub enum DeviceW {
|
||||
impl DeviceW {
|
||||
pub fn is_tun(&self) -> bool {
|
||||
match self {
|
||||
DeviceW::Tun(_) => {
|
||||
true
|
||||
}
|
||||
DeviceW::Tap(_) => {
|
||||
false
|
||||
}
|
||||
DeviceW::Tun(_) => true,
|
||||
DeviceW::Tap(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,7 +38,13 @@ pub struct DeviceWriter {
|
||||
}
|
||||
|
||||
impl DeviceWriter {
|
||||
pub fn new(writer: DeviceW,lock: Arc<Mutex<Device>>, in_ips: Vec<(Ipv4Addr, Ipv4Addr)>, _ip: Ipv4Addr, packet_information: bool) -> Self {
|
||||
pub fn new(
|
||||
writer: DeviceW,
|
||||
lock: Arc<Mutex<Device>>,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
_ip: Ipv4Addr,
|
||||
packet_information: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
writer,
|
||||
lock,
|
||||
@@ -61,41 +64,45 @@ impl DeviceWriter {
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
buf.put_u16(libc::ETH_P_IP as u16);
|
||||
buf.extend_from_slice(packet);
|
||||
writer.write_all(&buf)
|
||||
let len = writer.write(&buf)?;
|
||||
if len != buf.len() {
|
||||
log::error!("tun write error");
|
||||
}
|
||||
} else {
|
||||
writer.write_all(packet)
|
||||
let len = writer.write(packet)?;
|
||||
if len != packet.len() {
|
||||
log::error!("tun write error");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
///tun网卡写入ipv4数据
|
||||
pub fn write_ipv4_tun(&self, buf: &[u8]) -> io::Result<()> {
|
||||
match &self.writer {
|
||||
DeviceW::Tun(writer) => {
|
||||
Self::write(self.packet_information, writer, buf)
|
||||
}
|
||||
DeviceW::Tap(_) => {
|
||||
Err(io::Error::from(io::ErrorKind::Unsupported))
|
||||
}
|
||||
DeviceW::Tun(writer) => Self::write(self.packet_information, writer, buf),
|
||||
DeviceW::Tap(_) => Err(io::Error::from(io::ErrorKind::Unsupported)),
|
||||
}
|
||||
}
|
||||
/// tap网卡写入以太网帧
|
||||
pub fn write_ethernet_tap(&self, buf: &[u8]) -> io::Result<()> {
|
||||
match &self.writer {
|
||||
DeviceW::Tun(_) => {
|
||||
Err(io::Error::from(io::ErrorKind::Unsupported))
|
||||
}
|
||||
DeviceW::Tap((writer, _)) => {
|
||||
Self::write(self.packet_information, writer, buf)
|
||||
}
|
||||
DeviceW::Tun(_) => Err(io::Error::from(io::ErrorKind::Unsupported)),
|
||||
DeviceW::Tap((writer, _)) => Self::write(self.packet_information, writer, buf),
|
||||
}
|
||||
}
|
||||
///写入ipv4数据,头部必须留14字节,给tap写入以太网帧头
|
||||
pub fn write_ipv4(&self, buf: &mut [u8]) -> io::Result<()> {
|
||||
match &self.writer {
|
||||
DeviceW::Tun(writer) => {
|
||||
Self::write(self.packet_information, writer, &buf[14..])
|
||||
}
|
||||
DeviceW::Tun(writer) => Self::write(self.packet_information, writer, &buf[14..]),
|
||||
DeviceW::Tap((writer, mac)) => {
|
||||
let source_mac = [buf[14 + 12], buf[14 + 13], buf[14 + 14], buf[14 + 15], !mac[5], 234];
|
||||
let source_mac = [
|
||||
buf[14 + 12],
|
||||
buf[14 + 13],
|
||||
buf[14 + 14],
|
||||
buf[14 + 15],
|
||||
!mac[5],
|
||||
234,
|
||||
];
|
||||
let mut ethernet_packet = EthernetPacket::unchecked(buf);
|
||||
ethernet_packet.set_source(&source_mac);
|
||||
ethernet_packet.set_destination(mac);
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
use crate::tun_tap_device::linux_mac::DeviceW;
|
||||
use crate::tun_tap_device::{DeviceReader, DeviceType, DeviceWriter, DriverInfo};
|
||||
use parking_lot::Mutex;
|
||||
use std::io;
|
||||
use std::net::Ipv4Addr;
|
||||
use crate::tun_tap_device::{DeviceReader, DeviceType, DeviceWriter, DriverInfo};
|
||||
use tun::Device;
|
||||
use parking_lot::Mutex;
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
use crate::tun_tap_device::linux_mac::DeviceW;
|
||||
use tun::Device;
|
||||
|
||||
impl DeviceWriter {
|
||||
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> {
|
||||
pub fn change_ip(
|
||||
&self,
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
_old_netmask: Ipv4Addr,
|
||||
_old_gateway: Ipv4Addr,
|
||||
) -> io::Result<()> {
|
||||
let mut config = tun::Configuration::default();
|
||||
config
|
||||
.destination(gateway)
|
||||
@@ -21,7 +27,7 @@ impl DeviceWriter {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)));
|
||||
}
|
||||
if let Err(e) = config_ip(dev.name(), address, netmask, gateway) {
|
||||
log::error!("{}",e);
|
||||
log::error!("{}", e);
|
||||
}
|
||||
let name = dev.name();
|
||||
for (address, netmask) in &self.in_ips {
|
||||
@@ -31,17 +37,22 @@ impl DeviceWriter {
|
||||
add_route(name, address, netmask)?;
|
||||
// 广播和组播路由
|
||||
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
|
||||
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
|
||||
add_route(
|
||||
name,
|
||||
Ipv4Addr::from([224, 0, 0, 0]),
|
||||
Ipv4Addr::from([240, 0, 0, 0]),
|
||||
)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_device(device_type: DeviceType,
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
mtu: u16,
|
||||
pub fn create_device(
|
||||
device_type: DeviceType,
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
mtu: u16,
|
||||
) -> io::Result<(DeviceWriter, DeviceReader, DriverInfo)> {
|
||||
match device_type {
|
||||
DeviceType::Tun => {}
|
||||
@@ -68,7 +79,11 @@ pub fn create_device(device_type: DeviceType,
|
||||
add_route(name, address, netmask)?;
|
||||
// 广播和组播路由
|
||||
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
|
||||
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
|
||||
add_route(
|
||||
name,
|
||||
Ipv4Addr::from([224, 0, 0, 0]),
|
||||
Ipv4Addr::from([240, 0, 0, 0]),
|
||||
)?;
|
||||
let packet_information = dev.has_packet_information();
|
||||
let queue = dev.queue(0).unwrap();
|
||||
let reader = queue.reader();
|
||||
@@ -80,9 +95,15 @@ pub fn create_device(device_type: DeviceType,
|
||||
mac: None,
|
||||
};
|
||||
Ok((
|
||||
DeviceWriter::new(DeviceW::Tun(writer), Arc::new(Mutex::new(dev)), in_ips, address, packet_information),
|
||||
DeviceWriter::new(
|
||||
DeviceW::Tun(writer),
|
||||
Arc::new(Mutex::new(dev)),
|
||||
in_ips,
|
||||
address,
|
||||
packet_information,
|
||||
),
|
||||
DeviceReader::new(reader),
|
||||
driver_info
|
||||
driver_info,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -97,12 +118,23 @@ fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()>
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !route_add_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: cmd:{},out:{:?}", route_add_str, route_add_out)));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!(
|
||||
"添加路由失败: cmd:{},out:{:?}",
|
||||
route_add_str, route_add_out
|
||||
),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_ip(name: &str, address: Ipv4Addr, _netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
|
||||
fn config_ip(
|
||||
name: &str,
|
||||
address: Ipv4Addr,
|
||||
_netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
) -> io::Result<()> {
|
||||
let up_eth_str: String = format!("ifconfig {} {:?} {:?} up ", name, address, gateway);
|
||||
let up_eth_out = Command::new("sh")
|
||||
.arg("-c")
|
||||
@@ -110,9 +142,12 @@ fn config_ip(name: &str, address: Ipv4Addr, _netmask: Ipv4Addr, gateway: Ipv4Add
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !up_eth_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("设置网络地址失败: cmd:{},out:{:?}", up_eth_str, up_eth_out)));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("设置网络地址失败: cmd:{},out:{:?}", up_eth_str, up_eth_out),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn delete_device(_device_type: DeviceType) {}
|
||||
pub fn delete_device(_device_type: DeviceType) {}
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
#[cfg(target_os = "windows")]
|
||||
mod windows;
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
mod linux;
|
||||
#[cfg(target_os = "macos")]
|
||||
mod mac;
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
mod linux_mac;
|
||||
#[cfg(target_os = "android")]
|
||||
mod android;
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
mod linux;
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
mod linux_mac;
|
||||
#[cfg(target_os = "macos")]
|
||||
mod mac;
|
||||
#[cfg(target_os = "windows")]
|
||||
mod windows;
|
||||
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub use android::create;
|
||||
#[cfg(target_os = "android")]
|
||||
pub use android::{DeviceReader, DeviceWriter};
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
pub use linux::create_device;
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
pub use linux::delete_device;
|
||||
#[cfg(target_os = "android")]
|
||||
pub use android::create;
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
pub use linux_mac::{DeviceWriter, DeviceReader};
|
||||
#[cfg(target_os = "android")]
|
||||
pub use android::{DeviceWriter, DeviceReader};
|
||||
pub use linux_mac::{DeviceReader, DeviceWriter};
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use mac::create_device;
|
||||
#[cfg(target_os = "macos")]
|
||||
@@ -30,7 +29,7 @@ pub use windows::create_device;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows::delete_device;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows::{DeviceWriter, DeviceReader};
|
||||
pub use windows::{DeviceReader, DeviceWriter};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum DeviceType {
|
||||
@@ -50,4 +49,4 @@ pub struct DriverInfo {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub mac: Option<String>,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use std::{io, thread};
|
||||
use crate::tun_tap_device::{DeviceType, DriverInfo};
|
||||
use libloading::Library;
|
||||
use packet::ethernet;
|
||||
use packet::ethernet::packet::EthernetPacket;
|
||||
use parking_lot::Mutex;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::os::windows::process::CommandExt;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use libloading::Library;
|
||||
use parking_lot::Mutex;
|
||||
use packet::ethernet;
|
||||
use packet::ethernet::packet::EthernetPacket;
|
||||
use std::{io, thread};
|
||||
use win_tun_tap::{IFace, TapDevice, TunDevice};
|
||||
use crate::tun_tap_device::{DriverInfo, DeviceType};
|
||||
|
||||
pub const TUN_INTERFACE_NAME: &str = "Vnt-Tun-V1";
|
||||
pub const TUN_POOL_NAME: &str = "Vnt-Tun-V1";
|
||||
@@ -22,12 +22,8 @@ pub enum Device {
|
||||
impl Device {
|
||||
pub fn is_tun(&self) -> bool {
|
||||
match self {
|
||||
Device::Tun(_) => {
|
||||
true
|
||||
}
|
||||
Device::Tap(_) => {
|
||||
false
|
||||
}
|
||||
Device::Tun(_) => true,
|
||||
Device::Tap(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,17 +55,13 @@ impl DeviceWriter {
|
||||
dev.send_packet(packet);
|
||||
Ok(())
|
||||
}
|
||||
Device::Tap(_) => {
|
||||
Err(io::Error::from(io::ErrorKind::Unsupported))
|
||||
}
|
||||
Device::Tap(_) => Err(io::Error::from(io::ErrorKind::Unsupported)),
|
||||
}
|
||||
}
|
||||
/// tap网卡写入以太网帧
|
||||
pub fn write_ethernet_tap(&self, buf: &[u8]) -> io::Result<()> {
|
||||
match self.device.as_ref() {
|
||||
Device::Tun(_) => {
|
||||
Err(io::Error::from(io::ErrorKind::Unsupported))
|
||||
}
|
||||
Device::Tun(_) => Err(io::Error::from(io::ErrorKind::Unsupported)),
|
||||
Device::Tap((dev, _)) => {
|
||||
dev.write(buf)?;
|
||||
Ok(())
|
||||
@@ -85,7 +77,14 @@ impl DeviceWriter {
|
||||
dev.send_packet(packet);
|
||||
}
|
||||
Device::Tap((dev, mac)) => {
|
||||
let source_mac = [buf[14 + 12], buf[14 + 13], buf[14 + 14], buf[14 + 15], !mac[5], 234];
|
||||
let source_mac = [
|
||||
buf[14 + 12],
|
||||
buf[14 + 13],
|
||||
buf[14 + 14],
|
||||
buf[14 + 15],
|
||||
!mac[5],
|
||||
234,
|
||||
];
|
||||
let mut ethernet_packet = EthernetPacket::unchecked(buf);
|
||||
ethernet_packet.set_source(&source_mac);
|
||||
ethernet_packet.set_destination(mac);
|
||||
@@ -105,16 +104,10 @@ impl DeviceWriter {
|
||||
) -> io::Result<()> {
|
||||
let _guard = self.lock.lock();
|
||||
let dev: &dyn IFace = match self.device.as_ref() {
|
||||
Device::Tun(dev) => {
|
||||
dev as &dyn IFace
|
||||
}
|
||||
Device::Tap((dev, _)) => {
|
||||
dev as &dyn IFace
|
||||
}
|
||||
Device::Tun(dev) => dev as &dyn IFace,
|
||||
Device::Tap((dev, _)) => dev as &dyn IFace,
|
||||
};
|
||||
if let Err(e) =
|
||||
dev.delete_route(dest(old_gateway, old_gateway), old_netmask, old_gateway)
|
||||
{
|
||||
if let Err(e) = dev.delete_route(dest(old_gateway, old_gateway), old_netmask, old_gateway) {
|
||||
log::warn!("{:?}", e);
|
||||
}
|
||||
dev.set_ip(address, netmask)?;
|
||||
@@ -125,18 +118,19 @@ impl DeviceWriter {
|
||||
dev.add_route(address, netmask, gateway, 1)?;
|
||||
// 广播和组播路由
|
||||
dev.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
||||
dev.add_route(Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]), gateway, 1)?;
|
||||
dev.add_route(
|
||||
Ipv4Addr::from([224, 0, 0, 0]),
|
||||
Ipv4Addr::from([240, 0, 0, 0]),
|
||||
gateway,
|
||||
1,
|
||||
)?;
|
||||
delete_cache();
|
||||
Ok(())
|
||||
}
|
||||
pub fn close(&self) -> io::Result<()> {
|
||||
match self.device.as_ref() {
|
||||
Device::Tun(dev) => {
|
||||
dev.shutdown()
|
||||
}
|
||||
Device::Tap((dev, _)) => {
|
||||
dev.shutdown()
|
||||
}
|
||||
Device::Tun(dev) => dev.shutdown(),
|
||||
Device::Tap((dev, _)) => dev.shutdown(),
|
||||
}
|
||||
}
|
||||
pub fn is_tun(&self) -> bool {
|
||||
@@ -161,9 +155,7 @@ pub struct DeviceReader {
|
||||
|
||||
impl DeviceReader {
|
||||
pub fn new(device: Arc<Device>) -> Self {
|
||||
Self {
|
||||
device,
|
||||
}
|
||||
Self { device }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,9 +172,7 @@ impl DeviceReader {
|
||||
buf[..len].copy_from_slice(packet);
|
||||
Ok(len)
|
||||
}
|
||||
Device::Tap((dev, _)) => {
|
||||
dev.read(buf)
|
||||
}
|
||||
Device::Tap((dev, _)) => dev.read(buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,10 +214,7 @@ fn create_tun(
|
||||
) {
|
||||
Ok(tun_device) => tun_device,
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("{:?}", e),
|
||||
));
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -245,7 +232,12 @@ fn create_tun(
|
||||
tun_device.add_route(address, netmask, gateway, 1)?;
|
||||
// 广播和组播路由
|
||||
tun_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
||||
tun_device.add_route(Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]), gateway, 1)?;
|
||||
tun_device.add_route(
|
||||
Ipv4Addr::from([224, 0, 0, 0]),
|
||||
Ipv4Addr::from([240, 0, 0, 0]),
|
||||
gateway,
|
||||
1,
|
||||
)?;
|
||||
delete_cache();
|
||||
let device = Arc::new(Device::Tun(tun_device));
|
||||
let driver_info = DriverInfo {
|
||||
@@ -257,7 +249,7 @@ fn create_tun(
|
||||
Ok((
|
||||
DeviceWriter::new(device.clone(), in_ips, address),
|
||||
DeviceReader::new(device),
|
||||
driver_info
|
||||
driver_info,
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -272,7 +264,7 @@ fn delete_cache() {
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
log::warn!("删除缓存失败:{:?}",out);
|
||||
log::warn!("删除缓存失败:{:?}", out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +310,12 @@ fn create_tap(
|
||||
}
|
||||
// 广播和组播路由
|
||||
tap_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
||||
tap_device.add_route(Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]), gateway, 1)?;
|
||||
tap_device.add_route(
|
||||
Ipv4Addr::from([224, 0, 0, 0]),
|
||||
Ipv4Addr::from([240, 0, 0, 0]),
|
||||
gateway,
|
||||
1,
|
||||
)?;
|
||||
delete_cache();
|
||||
let tap = Arc::new(Device::Tap((tap_device, mac)));
|
||||
let driver_info = DriverInfo {
|
||||
@@ -330,7 +327,7 @@ fn create_tap(
|
||||
Ok((
|
||||
DeviceWriter::new(tap.clone(), in_ips, address),
|
||||
DeviceReader::new(tap),
|
||||
driver_info
|
||||
driver_info,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -344,29 +341,23 @@ fn delete_tap() {
|
||||
let _ = tap_device.delete();
|
||||
}
|
||||
|
||||
pub fn create_device(device_type: DeviceType, address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
mtu: u16) -> io::Result<(DeviceWriter, DeviceReader, DriverInfo)> {
|
||||
pub fn create_device(
|
||||
device_type: DeviceType,
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
mtu: u16,
|
||||
) -> io::Result<(DeviceWriter, DeviceReader, DriverInfo)> {
|
||||
match device_type {
|
||||
DeviceType::Tun => {
|
||||
create_tun(address, netmask, gateway, in_ips, mtu)
|
||||
}
|
||||
DeviceType::Tap => {
|
||||
create_tap(address, netmask, gateway, in_ips, mtu)
|
||||
}
|
||||
DeviceType::Tun => create_tun(address, netmask, gateway, in_ips, mtu),
|
||||
DeviceType::Tap => create_tap(address, netmask, gateway, in_ips, mtu),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_device(device_type: DeviceType) {
|
||||
match device_type {
|
||||
DeviceType::Tun => {
|
||||
delete_tun()
|
||||
}
|
||||
DeviceType::Tap => {
|
||||
delete_tap()
|
||||
}
|
||||
DeviceType::Tun => delete_tun(),
|
||||
DeviceType::Tap => delete_tap(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
pub mod wait;
|
||||
pub mod wait;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicIsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::watch::{channel, Receiver, Sender};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -41,4 +41,4 @@ impl WaitGroup {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
-49
@@ -21,8 +21,8 @@ use winapi::um::winioctl::*;
|
||||
use winapi::um::winnt::*;
|
||||
use winapi::um::winreg::*;
|
||||
|
||||
use std::{io, mem, ptr};
|
||||
use std::error::Error;
|
||||
use std::{io, mem, ptr};
|
||||
use winapi::um::minwinbase::OVERLAPPED_u;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
@@ -46,9 +46,7 @@ pub fn string_from_guid(guid: &GUID) -> io::Result<Vec<WCHAR>> {
|
||||
// GUID_STRING_CHARACTERS + 1
|
||||
let mut string = vec![0; 39];
|
||||
|
||||
match unsafe {
|
||||
StringFromGUID2(guid, string.as_mut_ptr(), string.len() as _)
|
||||
} {
|
||||
match unsafe { StringFromGUID2(guid, string.as_mut_ptr(), string.len() as _) } {
|
||||
0 => Err(io::Error::new(io::ErrorKind::Other, "Insufficent buffer")),
|
||||
_ => Ok(string),
|
||||
}
|
||||
@@ -85,12 +83,8 @@ pub fn luid_to_alias(luid: &NET_LUID) -> io::Result<Vec<WCHAR>> {
|
||||
// IF_MAX_STRING_SIZE + 1
|
||||
let mut alias = vec![0; 257];
|
||||
|
||||
match unsafe {
|
||||
ConvertInterfaceLuidToAlias(luid, alias.as_mut_ptr(), alias.len())
|
||||
} {
|
||||
0 => {
|
||||
Ok(alias)
|
||||
}
|
||||
match unsafe { ConvertInterfaceLuidToAlias(luid, alias.as_mut_ptr(), alias.len()) } {
|
||||
0 => Ok(alias),
|
||||
err => Err(io::Error::from_raw_os_error(err as _)),
|
||||
}
|
||||
}
|
||||
@@ -140,7 +134,8 @@ pub fn read_file(handle: HANDLE, buffer: &mut [u8]) -> io::Result<DWORD> {
|
||||
buffer.as_mut_ptr() as _,
|
||||
buffer.len() as _,
|
||||
&mut ret,
|
||||
&mut ip_overlapped, ) {
|
||||
&mut ip_overlapped,
|
||||
) {
|
||||
let e = io::Error::last_os_error();
|
||||
if e.raw_os_error().unwrap_or(0) == 997 {
|
||||
if 0 == GetOverlappedResult(handle, &mut ip_overlapped, &mut ret, 1) {
|
||||
@@ -191,9 +186,7 @@ pub fn create_device_info_list(guid: &GUID) -> io::Result<HDEVINFO> {
|
||||
}
|
||||
|
||||
pub fn get_class_devs(guid: &GUID, flags: DWORD) -> io::Result<HDEVINFO> {
|
||||
match unsafe {
|
||||
SetupDiGetClassDevsW(guid, ptr::null(), ptr::null_mut(), flags)
|
||||
} {
|
||||
match unsafe { SetupDiGetClassDevsW(guid, ptr::null(), ptr::null_mut(), flags) } {
|
||||
INVALID_HANDLE_VALUE => Err(io::Error::last_os_error()),
|
||||
devinfo => Ok(devinfo),
|
||||
}
|
||||
@@ -248,13 +241,8 @@ pub fn create_device_info(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_selected_device(
|
||||
devinfo: HDEVINFO,
|
||||
devinfo_data: &SP_DEVINFO_DATA,
|
||||
) -> io::Result<()> {
|
||||
match unsafe {
|
||||
SetupDiSetSelectedDevice(devinfo, devinfo_data as *const _ as _)
|
||||
} {
|
||||
pub fn set_selected_device(devinfo: HDEVINFO, devinfo_data: &SP_DEVINFO_DATA) -> io::Result<()> {
|
||||
match unsafe { SetupDiSetSelectedDevice(devinfo, devinfo_data as *const _ as _) } {
|
||||
0 => Err(io::Error::last_os_error()),
|
||||
_ => Ok(()),
|
||||
}
|
||||
@@ -308,13 +296,8 @@ pub fn build_driver_info_list(
|
||||
devinfo_data: &SP_DEVINFO_DATA,
|
||||
driver_type: DWORD,
|
||||
) -> io::Result<()> {
|
||||
match unsafe {
|
||||
SetupDiBuildDriverInfoList(
|
||||
devinfo,
|
||||
devinfo_data as *const _ as _,
|
||||
driver_type,
|
||||
)
|
||||
} {
|
||||
match unsafe { SetupDiBuildDriverInfoList(devinfo, devinfo_data as *const _ as _, driver_type) }
|
||||
{
|
||||
0 => Err(io::Error::last_os_error()),
|
||||
_ => Ok(()),
|
||||
}
|
||||
@@ -326,11 +309,7 @@ pub fn destroy_driver_info_list(
|
||||
driver_type: DWORD,
|
||||
) -> io::Result<()> {
|
||||
match unsafe {
|
||||
SetupDiDestroyDriverInfoList(
|
||||
devinfo,
|
||||
devinfo_data as *const _ as _,
|
||||
driver_type,
|
||||
)
|
||||
SetupDiDestroyDriverInfoList(devinfo, devinfo_data as *const _ as _, driver_type)
|
||||
} {
|
||||
0 => Err(io::Error::last_os_error()),
|
||||
_ => Ok(()),
|
||||
@@ -342,8 +321,7 @@ pub fn get_driver_info_detail(
|
||||
devinfo_data: &SP_DEVINFO_DATA,
|
||||
drvinfo_data: &SP_DRVINFO_DATA_W,
|
||||
) -> io::Result<SP_DRVINFO_DETAIL_DATA_W2> {
|
||||
let mut drvinfo_detail: SP_DRVINFO_DETAIL_DATA_W2 =
|
||||
unsafe { mem::zeroed() };
|
||||
let mut drvinfo_detail: SP_DRVINFO_DETAIL_DATA_W2 = unsafe { mem::zeroed() };
|
||||
drvinfo_detail.cbSize = mem::size_of::<SP_DRVINFO_DETAIL_DATA_W>() as _;
|
||||
|
||||
match unsafe {
|
||||
@@ -402,11 +380,7 @@ pub fn call_class_installer(
|
||||
install_function: DI_FUNCTION,
|
||||
) -> io::Result<()> {
|
||||
match unsafe {
|
||||
SetupDiCallClassInstaller(
|
||||
install_function,
|
||||
devinfo,
|
||||
devinfo_data as *const _ as _,
|
||||
)
|
||||
SetupDiCallClassInstaller(install_function, devinfo, devinfo_data as *const _ as _)
|
||||
} {
|
||||
0 => Err(io::Error::last_os_error()),
|
||||
_ => Ok(()),
|
||||
@@ -444,16 +418,12 @@ pub fn notify_change_key_value(
|
||||
notify_filter: DWORD,
|
||||
milliseconds: DWORD,
|
||||
) -> io::Result<()> {
|
||||
let event = match unsafe {
|
||||
CreateEventW(ptr::null_mut(), FALSE, FALSE, ptr::null())
|
||||
} {
|
||||
let event = match unsafe { CreateEventW(ptr::null_mut(), FALSE, FALSE, ptr::null()) } {
|
||||
INVALID_HANDLE_VALUE => Err(io::Error::last_os_error()),
|
||||
event => Ok(event),
|
||||
}?;
|
||||
|
||||
match unsafe {
|
||||
RegNotifyChangeKeyValue(key, watch_subtree, notify_filter, event, TRUE)
|
||||
} {
|
||||
match unsafe { RegNotifyChangeKeyValue(key, watch_subtree, notify_filter, event, TRUE) } {
|
||||
0 => Ok(()),
|
||||
err => Err(io::Error::from_raw_os_error(err)),
|
||||
}?;
|
||||
@@ -499,9 +469,7 @@ pub fn enum_device_info(
|
||||
let mut devinfo_data: SP_DEVINFO_DATA = unsafe { mem::zeroed() };
|
||||
devinfo_data.cbSize = mem::size_of_val(&devinfo_data) as _;
|
||||
|
||||
match unsafe {
|
||||
SetupDiEnumDeviceInfo(devinfo, member_index, &mut devinfo_data)
|
||||
} {
|
||||
match unsafe { SetupDiEnumDeviceInfo(devinfo, member_index, &mut devinfo_data) } {
|
||||
0 if unsafe { GetLastError() == ERROR_NO_MORE_ITEMS } => None,
|
||||
0 => Some(Err(io::Error::last_os_error())),
|
||||
_ => Some(Ok(devinfo_data)),
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#![cfg(windows)]
|
||||
|
||||
mod tap;
|
||||
mod tun;
|
||||
mod ffi;
|
||||
mod netsh;
|
||||
mod route;
|
||||
use std::{io, net};
|
||||
mod tap;
|
||||
mod tun;
|
||||
use std::io;
|
||||
use std::net::Ipv4Addr;
|
||||
pub use tap::TapDevice;
|
||||
pub use tun::*;
|
||||
@@ -33,13 +33,15 @@ pub trait IFace {
|
||||
/// 设置ip
|
||||
fn set_ip(&self, address: Ipv4Addr, mask: Ipv4Addr) -> io::Result<()>;
|
||||
/// 设置路由
|
||||
fn add_route(&self, dest: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr, metric: u16) -> io::Result<()>;
|
||||
fn add_route(
|
||||
&self,
|
||||
dest: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
metric: u16,
|
||||
) -> io::Result<()>;
|
||||
/// 删除路由
|
||||
fn delete_route(&self, dest: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr, ) -> io::Result<()>;
|
||||
fn delete_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()>;
|
||||
/// 设置最大传输单元
|
||||
fn set_mtu(&self, mtu: u16) -> io::Result<()>;
|
||||
/// 设置跃点
|
||||
|
||||
@@ -4,14 +4,17 @@ use std::os::windows::process::CommandExt;
|
||||
|
||||
/// 设置网卡名称
|
||||
pub fn set_interface_name(old_name: &str, new_name: &str) -> io::Result<()> {
|
||||
let cmd = format!(" netsh interface set interface name={:?} newname={:?}", old_name, new_name);
|
||||
let cmd = format!(
|
||||
" netsh interface set interface name={:?} newname={:?}",
|
||||
old_name, new_name
|
||||
);
|
||||
let out = std::process::Command::new("cmd")
|
||||
.creation_flags(0x08000000) //winapi-0.3.9/src/um/winbase.rs:283
|
||||
.arg("/C")
|
||||
.arg(&cmd)
|
||||
.output()?;
|
||||
if !out.status.success() {
|
||||
log::warn!("修改网卡名称失败:cmd={:?},out={:?}",cmd,out);
|
||||
log::warn!("修改网卡名称失败:cmd={:?},out={:?}", cmd, out);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "修改网卡名称失败"));
|
||||
}
|
||||
Ok(())
|
||||
@@ -28,8 +31,11 @@ pub fn set_interface_ip(index: u32, address: &Ipv4Addr, netmask: &Ipv4Addr) -> i
|
||||
.arg(&set_address)
|
||||
.output()?;
|
||||
if !out.status.success() {
|
||||
log::error!("cmd={:?},out={:?}",set_address,out);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("设置网络地址失败: {:?}", out)));
|
||||
log::error!("cmd={:?},out={:?}", set_address, out);
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("设置网络地址失败: {:?}", out),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -45,21 +51,30 @@ pub fn set_interface_mtu(index: u32, mtu: u16) -> io::Result<()> {
|
||||
.arg(&set_mtu)
|
||||
.output()?;
|
||||
if !out.status.success() {
|
||||
log::error!("cmd={:?},out={:?}",set_mtu,out);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("设置mtu失败: {:?}", out)));
|
||||
log::error!("cmd={:?},out={:?}", set_mtu, out);
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("设置mtu失败: {:?}", out),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn set_interface_metric(index: u32, metric: u16) -> io::Result<()> {
|
||||
let set_metric = format!("netsh interface ip set interface {} metric={}", index,metric);
|
||||
let set_metric = format!(
|
||||
"netsh interface ip set interface {} metric={}",
|
||||
index, metric
|
||||
);
|
||||
let out = std::process::Command::new("cmd")
|
||||
.creation_flags(0x08000000)
|
||||
.arg("/C")
|
||||
.arg(&set_metric)
|
||||
.output()?;
|
||||
if !out.status.success() {
|
||||
log::error!("cmd={:?},out={:?}",set_metric,out);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("设置metric失败: {:?}", out)));
|
||||
log::error!("cmd={:?},out={:?}", set_metric, out);
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("设置metric失败: {:?}", out),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,13 @@ use std::net::Ipv4Addr;
|
||||
use std::os::windows::process::CommandExt;
|
||||
|
||||
/// 添加路由
|
||||
pub fn add_route(index: u32, dest: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr, metric: u16) -> io::Result<()> {
|
||||
pub fn add_route(
|
||||
index: u32,
|
||||
dest: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
metric: u16,
|
||||
) -> io::Result<()> {
|
||||
let set_route = format!(
|
||||
"route add {:?} mask {:?} {:?} metric {} if {}",
|
||||
dest, netmask, gateway, metric, index
|
||||
@@ -18,16 +22,27 @@ pub fn add_route(index: u32, dest: Ipv4Addr,
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
log::error!("cmd={:?},out={:?}",set_route,out);
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: {:?}", out)));
|
||||
log::error!("cmd={:?},out={:?}", set_route, out);
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("添加路由失败: {:?}", out),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 删除路由
|
||||
pub fn delete_route(index: u32, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
|
||||
pub fn delete_route(
|
||||
index: u32,
|
||||
dest: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
) -> io::Result<()> {
|
||||
if index == 0 {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("网络接口索引错误: {:?}", index)));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("网络接口索引错误: {:?}", index),
|
||||
));
|
||||
}
|
||||
let delete_route = format!(
|
||||
"route delete {:?} mask {:?} {:?} if {}",
|
||||
@@ -41,7 +56,10 @@ pub fn delete_route(index: u32, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("删除路由失败: {:?}", out)));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("删除路由失败: {:?}", out),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,22 +51,15 @@ pub fn create_interface() -> io::Result<NET_LUID> {
|
||||
ffi::build_driver_info_list(devinfo, &devinfo_data, SPDIT_COMPATDRIVER)?;
|
||||
|
||||
let _guard = guard((), |_| {
|
||||
let _ = ffi::destroy_driver_info_list(
|
||||
devinfo,
|
||||
&devinfo_data,
|
||||
SPDIT_COMPATDRIVER,
|
||||
);
|
||||
let _ = ffi::destroy_driver_info_list(devinfo, &devinfo_data, SPDIT_COMPATDRIVER);
|
||||
});
|
||||
|
||||
let mut driver_version = 0;
|
||||
let mut member_index = 0;
|
||||
|
||||
while let Some(drvinfo_data) = ffi::enum_driver_info(
|
||||
devinfo,
|
||||
&devinfo_data,
|
||||
SPDIT_COMPATDRIVER,
|
||||
member_index,
|
||||
) {
|
||||
while let Some(drvinfo_data) =
|
||||
ffi::enum_driver_info(devinfo, &devinfo_data, SPDIT_COMPATDRIVER, member_index)
|
||||
{
|
||||
member_index += 1;
|
||||
|
||||
let drvinfo_data = match drvinfo_data {
|
||||
@@ -78,14 +71,11 @@ pub fn create_interface() -> io::Result<NET_LUID> {
|
||||
continue;
|
||||
}
|
||||
|
||||
let drvinfo_detail = match ffi::get_driver_info_detail(
|
||||
devinfo,
|
||||
&devinfo_data,
|
||||
&drvinfo_data,
|
||||
) {
|
||||
Ok(drvinfo_detail) => drvinfo_detail,
|
||||
_ => continue,
|
||||
};
|
||||
let drvinfo_detail =
|
||||
match ffi::get_driver_info_detail(devinfo, &devinfo_data, &drvinfo_data) {
|
||||
Ok(drvinfo_detail) => drvinfo_detail,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
let is_compatible = drvinfo_detail
|
||||
.HardwareID
|
||||
@@ -115,16 +105,8 @@ pub fn create_interface() -> io::Result<NET_LUID> {
|
||||
|
||||
ffi::call_class_installer(devinfo, &devinfo_data, DIF_REGISTERDEVICE)?;
|
||||
|
||||
let _ = ffi::call_class_installer(
|
||||
devinfo,
|
||||
&devinfo_data,
|
||||
DIF_REGISTER_COINSTALLERS,
|
||||
);
|
||||
let _ = ffi::call_class_installer(
|
||||
devinfo,
|
||||
&devinfo_data,
|
||||
DIF_INSTALLINTERFACES,
|
||||
);
|
||||
let _ = ffi::call_class_installer(devinfo, &devinfo_data, DIF_REGISTER_COINSTALLERS);
|
||||
let _ = ffi::call_class_installer(devinfo, &devinfo_data, DIF_INSTALLINTERFACES);
|
||||
|
||||
ffi::call_class_installer(devinfo, &devinfo_data, DIF_INSTALLDEVICE)?;
|
||||
|
||||
@@ -140,21 +122,11 @@ pub fn create_interface() -> io::Result<NET_LUID> {
|
||||
let key = RegKey::predef(key);
|
||||
|
||||
while let Err(_) = key.get_value::<DWORD, &str>("*IfType") {
|
||||
ffi::notify_change_key_value(
|
||||
key.raw_handle(),
|
||||
TRUE,
|
||||
REG_NOTIFY_CHANGE_NAME,
|
||||
2000,
|
||||
)?;
|
||||
ffi::notify_change_key_value(key.raw_handle(), TRUE, REG_NOTIFY_CHANGE_NAME, 2000)?;
|
||||
}
|
||||
|
||||
while let Err(_) = key.get_value::<DWORD, &str>("NetLuidIndex") {
|
||||
ffi::notify_change_key_value(
|
||||
key.raw_handle(),
|
||||
TRUE,
|
||||
REG_NOTIFY_CHANGE_NAME,
|
||||
2000,
|
||||
)?;
|
||||
ffi::notify_change_key_value(key.raw_handle(), TRUE, REG_NOTIFY_CHANGE_NAME, 2000)?;
|
||||
}
|
||||
|
||||
let if_type: DWORD = key.get_value("*IfType")?;
|
||||
@@ -181,8 +153,7 @@ pub fn check_interface(luid: &NET_LUID) -> io::Result<()> {
|
||||
|
||||
let mut member_index = 0;
|
||||
|
||||
while let Some(devinfo_data) = ffi::enum_device_info(devinfo, member_index)
|
||||
{
|
||||
while let Some(devinfo_data) = ffi::enum_device_info(devinfo, member_index) {
|
||||
member_index += 1;
|
||||
|
||||
let devinfo_data = match devinfo_data {
|
||||
@@ -190,14 +161,11 @@ pub fn check_interface(luid: &NET_LUID) -> io::Result<()> {
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
let hardware_id = match ffi::get_device_registry_property(
|
||||
devinfo,
|
||||
&devinfo_data,
|
||||
SPDRP_HARDWAREID,
|
||||
) {
|
||||
Ok(hardware_id) => hardware_id,
|
||||
Err(_) => continue,
|
||||
};
|
||||
let hardware_id =
|
||||
match ffi::get_device_registry_property(devinfo, &devinfo_data, SPDRP_HARDWAREID) {
|
||||
Ok(hardware_id) => hardware_id,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
if !decode_utf16(&hardware_id).eq_ignore_ascii_case(HARDWARE_ID) {
|
||||
continue;
|
||||
@@ -238,7 +206,10 @@ pub fn check_interface(luid: &NET_LUID) -> io::Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Err(io::Error::new(io::ErrorKind::NotFound, "TAP Device not found"))
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
"TAP Device not found",
|
||||
))
|
||||
}
|
||||
|
||||
/// Deletes an existing interface
|
||||
@@ -251,8 +222,7 @@ pub fn delete_interface(luid: &NET_LUID) -> io::Result<()> {
|
||||
|
||||
let mut member_index = 0;
|
||||
|
||||
while let Some(devinfo_data) = ffi::enum_device_info(devinfo, member_index)
|
||||
{
|
||||
while let Some(devinfo_data) = ffi::enum_device_info(devinfo, member_index) {
|
||||
member_index += 1;
|
||||
|
||||
let devinfo_data = match devinfo_data {
|
||||
@@ -260,14 +230,11 @@ pub fn delete_interface(luid: &NET_LUID) -> io::Result<()> {
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
let hardware_id = match ffi::get_device_registry_property(
|
||||
devinfo,
|
||||
&devinfo_data,
|
||||
SPDRP_HARDWAREID,
|
||||
) {
|
||||
Ok(hardware_id) => hardware_id,
|
||||
Err(_) => continue,
|
||||
};
|
||||
let hardware_id =
|
||||
match ffi::get_device_registry_property(devinfo, &devinfo_data, SPDRP_HARDWAREID) {
|
||||
Ok(hardware_id) => hardware_id,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
if !decode_utf16(&hardware_id).eq_ignore_ascii_case(HARDWARE_ID) {
|
||||
continue;
|
||||
@@ -308,13 +275,15 @@ pub fn delete_interface(luid: &NET_LUID) -> io::Result<()> {
|
||||
return ffi::call_class_installer(devinfo, &devinfo_data, DIF_REMOVE);
|
||||
}
|
||||
|
||||
Err(io::Error::new(io::ErrorKind::NotFound, "TAP Device not found"))
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
"TAP Device not found",
|
||||
))
|
||||
}
|
||||
|
||||
/// Open an handle to an interface
|
||||
pub fn open_interface(luid: &NET_LUID) -> io::Result<HANDLE> {
|
||||
let guid = ffi::luid_to_guid(luid)
|
||||
.and_then(|guid| ffi::string_from_guid(&guid))?;
|
||||
let guid = ffi::luid_to_guid(luid).and_then(|guid| ffi::string_from_guid(&guid))?;
|
||||
|
||||
let path = format!(r"\\.\Global\{}.tap", &decode_utf16(&guid));
|
||||
|
||||
@@ -323,6 +292,6 @@ pub fn open_interface(luid: &NET_LUID) -> io::Result<HANDLE> {
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,//FILE_ATTRIBUTE_SYSTEM,
|
||||
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, //FILE_ATTRIBUTE_SYSTEM,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::{io, time};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::{io, time};
|
||||
|
||||
use winapi::shared::ifdef::NET_LUID;
|
||||
use winapi::um::winioctl::*;
|
||||
use winapi::um::winnt::HANDLE;
|
||||
|
||||
use crate::{decode_utf16, encode_utf16, ffi, IFace, netsh, route};
|
||||
use crate::{decode_utf16, encode_utf16, ffi, netsh, route, IFace};
|
||||
|
||||
mod iface;
|
||||
|
||||
@@ -13,7 +13,6 @@ pub struct TapDevice {
|
||||
index: u32,
|
||||
luid: NET_LUID,
|
||||
handle: HANDLE,
|
||||
|
||||
}
|
||||
|
||||
unsafe impl Send for TapDevice {}
|
||||
@@ -31,7 +30,7 @@ impl TapDevice {
|
||||
&(),
|
||||
&mut mac,
|
||||
)
|
||||
.map(|_| mac)
|
||||
.map(|_| mac)
|
||||
}
|
||||
|
||||
/// Retrieve the version of the driver
|
||||
@@ -44,7 +43,7 @@ impl TapDevice {
|
||||
&(),
|
||||
&mut version,
|
||||
)
|
||||
.map(|_| version)
|
||||
.map(|_| version)
|
||||
}
|
||||
|
||||
/// Retieve the mtu of the interface
|
||||
@@ -57,10 +56,9 @@ impl TapDevice {
|
||||
&(),
|
||||
&mut mtu,
|
||||
)
|
||||
.map(|_| mtu)
|
||||
.map(|_| mtu)
|
||||
}
|
||||
|
||||
|
||||
/// Set the status of the interface, true for connected,
|
||||
/// false for disconnected.
|
||||
pub fn set_status(&self, status: bool) -> io::Result<()> {
|
||||
@@ -98,7 +96,11 @@ impl TapDevice {
|
||||
};
|
||||
};
|
||||
let index = ffi::luid_to_index(&luid).map(|index| index as u32)?;
|
||||
Ok(Self { index, luid, handle })
|
||||
Ok(Self {
|
||||
index,
|
||||
luid,
|
||||
handle,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn open(name: &str) -> io::Result<Self> {
|
||||
@@ -109,7 +111,11 @@ impl TapDevice {
|
||||
|
||||
let handle = iface::open_interface(&luid)?;
|
||||
let index = ffi::luid_to_index(&luid).map(|index| index as u32)?;
|
||||
Ok(Self { index, luid, handle })
|
||||
Ok(Self {
|
||||
index,
|
||||
luid,
|
||||
handle,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn delete(self) -> io::Result<()> {
|
||||
@@ -140,12 +146,18 @@ impl IFace for TapDevice {
|
||||
netsh::set_interface_ip(index, &address, &mask)
|
||||
}
|
||||
|
||||
fn add_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr, metric: u16) -> io::Result<()> {
|
||||
fn add_route(
|
||||
&self,
|
||||
dest: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
metric: u16,
|
||||
) -> io::Result<()> {
|
||||
let index = self.get_index()?;
|
||||
route::add_route(index, dest, netmask, gateway,metric)
|
||||
route::add_route(index, dest, netmask, gateway, metric)
|
||||
}
|
||||
|
||||
fn delete_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
|
||||
fn delete_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
|
||||
let index = self.get_index()?;
|
||||
route::delete_route(index, dest, netmask, gateway)
|
||||
}
|
||||
@@ -161,7 +173,6 @@ impl IFace for TapDevice {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl TapDevice {
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
ffi::read_file(self.handle, buf).map(|res| res as _)
|
||||
@@ -177,6 +188,3 @@ impl Drop for TapDevice {
|
||||
let _ = iface::delete_interface(&self.luid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use log::*;
|
||||
|
||||
use crate::tun::wintun_raw;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use widestring::U16CStr;
|
||||
use crate::tun::wintun_raw;
|
||||
|
||||
/// Sets the logger wintun will use when logging. Maps to the WintunSetLogger C function
|
||||
pub fn set_logger(win_tun: &wintun_raw::wintun, f: wintun_raw::WINTUN_LOGGER_CALLBACK) {
|
||||
|
||||
@@ -3,11 +3,11 @@ use std::net::Ipv4Addr;
|
||||
|
||||
use winapi::um::{handleapi, synchapi, winbase, winnt};
|
||||
|
||||
use crate::{decode_utf16, encode_utf16, ffi, IFace, netsh, route};
|
||||
use crate::{decode_utf16, encode_utf16, ffi, netsh, route, IFace};
|
||||
use rand::Rng;
|
||||
mod wintun_raw;
|
||||
mod log;
|
||||
pub mod packet;
|
||||
mod wintun_raw;
|
||||
|
||||
/// The maximum size of wintun's internal ring buffer (in bytes)
|
||||
pub const MAX_RING_CAPACITY: u32 = 0x400_0000;
|
||||
@@ -18,7 +18,6 @@ pub const MIN_RING_CAPACITY: u32 = 0x2_0000;
|
||||
/// Maximum pool name length including zero terminator
|
||||
pub const MAX_POOL: usize = 256;
|
||||
|
||||
|
||||
pub struct TunDevice {
|
||||
pub(crate) luid: u64,
|
||||
pub(crate) index: u32,
|
||||
@@ -38,7 +37,6 @@ pub struct TunDevice {
|
||||
|
||||
/// The adapter that owns this session
|
||||
pub(crate) adapter: wintun_raw::WINTUN_ADAPTER_HANDLE,
|
||||
|
||||
}
|
||||
|
||||
unsafe impl Send for TunDevice {}
|
||||
@@ -47,20 +45,31 @@ unsafe impl Sync for TunDevice {}
|
||||
|
||||
impl TunDevice {
|
||||
pub unsafe fn create<L>(library: L, pool: &str, name: &str) -> io::Result<Self>
|
||||
where L: Into<libloading::Library>, {
|
||||
where
|
||||
L: Into<libloading::Library>,
|
||||
{
|
||||
let win_tun = match wintun_raw::wintun::from_library(library) {
|
||||
Ok(win_tun) => { win_tun }
|
||||
Ok(win_tun) => win_tun,
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("library error {:?} ", e)));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("library error {:?} ", e),
|
||||
));
|
||||
}
|
||||
};
|
||||
let pool_utf16 = encode_utf16(pool);
|
||||
if pool_utf16.len() > MAX_POOL {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("长度大于{}:{:?}", MAX_POOL, pool)));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("长度大于{}:{:?}", MAX_POOL, pool),
|
||||
));
|
||||
}
|
||||
let name_utf16 = encode_utf16(name);
|
||||
if name_utf16.len() > MAX_POOL {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("长度大于{}:{:?}", MAX_POOL, pool)));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("长度大于{}:{:?}", MAX_POOL, pool),
|
||||
));
|
||||
}
|
||||
let mut guid_bytes: [u8; 16] = [0u8; 16];
|
||||
rand::thread_rng().fill(&mut guid_bytes);
|
||||
@@ -76,22 +85,32 @@ impl TunDevice {
|
||||
//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
|
||||
//applies for all Wintun* functions below
|
||||
let adapter = win_tun.WintunCreateAdapter(pool_utf16.as_ptr(), name_utf16.as_ptr(), guid_ptr);
|
||||
let adapter =
|
||||
win_tun.WintunCreateAdapter(pool_utf16.as_ptr(), name_utf16.as_ptr(), guid_ptr);
|
||||
if adapter.is_null() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "Failed to crate adapter"));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Failed to crate adapter",
|
||||
));
|
||||
}
|
||||
Self::init(win_tun, adapter)
|
||||
}
|
||||
pub unsafe fn init(win_tun: wintun_raw::wintun, adapter: wintun_raw::WINTUN_ADAPTER_HANDLE) -> io::Result<Self> {
|
||||
pub unsafe fn init(
|
||||
win_tun: wintun_raw::wintun,
|
||||
adapter: wintun_raw::WINTUN_ADAPTER_HANDLE,
|
||||
) -> io::Result<Self> {
|
||||
// 开启session
|
||||
let session = win_tun.WintunStartSession(adapter, 128 * 1024);
|
||||
if session.is_null() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "WintunStartSession failed"));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"WintunStartSession failed",
|
||||
));
|
||||
}
|
||||
//SAFETY: We follow the contract required by CreateEventA. See MSDN
|
||||
//(the pointers are allowed to be null, and 0 is okay for the others)
|
||||
let shutdown_event = synchapi::CreateEventA(std::ptr::null_mut(),
|
||||
0, 0, std::ptr::null_mut());
|
||||
let shutdown_event =
|
||||
synchapi::CreateEventA(std::ptr::null_mut(), 0, 0, std::ptr::null_mut());
|
||||
let read_event = win_tun.WintunGetReadWaitEvent(session) as winnt::HANDLE;
|
||||
let mut luid: wintun_raw::NET_LUID = std::mem::zeroed();
|
||||
win_tun.WintunGetAdapterLUID(adapter, &mut luid as *mut wintun_raw::NET_LUID);
|
||||
@@ -107,18 +126,26 @@ impl TunDevice {
|
||||
})
|
||||
}
|
||||
pub unsafe fn delete_for_name<L>(library: L, name: &str) -> io::Result<()>
|
||||
where L: Into<libloading::Library>, {
|
||||
where
|
||||
L: Into<libloading::Library>,
|
||||
{
|
||||
let win_tun = match wintun_raw::wintun::from_library(library) {
|
||||
Ok(win_tun) => win_tun,
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("library error {:?} ", e)));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("library error {:?} ", e),
|
||||
));
|
||||
}
|
||||
};
|
||||
log::set_default_logger_if_unset(&win_tun);
|
||||
let name_utf16 = encode_utf16(name);
|
||||
let adapter = win_tun.WintunOpenAdapter(name_utf16.as_ptr());
|
||||
if adapter.is_null() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "Failed to open adapter"));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Failed to open adapter",
|
||||
));
|
||||
}
|
||||
win_tun.WintunCloseAdapter(adapter);
|
||||
win_tun.WintunDeleteDriver();
|
||||
@@ -131,7 +158,10 @@ impl TunDevice {
|
||||
pub fn version(&self) -> io::Result<Version> {
|
||||
let version = unsafe { self.win_tun.WintunGetRunningDriverVersion() };
|
||||
if version == 0 {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "WintunGetRunningDriverVersion"));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"WintunGetRunningDriverVersion",
|
||||
));
|
||||
} else {
|
||||
Ok(Version {
|
||||
major: ((version >> 16) & 0xFF) as u16,
|
||||
@@ -155,7 +185,6 @@ pub struct Version {
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
impl IFace for TunDevice {
|
||||
fn shutdown(&self) -> io::Result<()> {
|
||||
let _ = unsafe { synchapi::SetEvent(self.shutdown_event) };
|
||||
@@ -169,9 +198,7 @@ impl IFace for TunDevice {
|
||||
|
||||
fn get_name(&self) -> io::Result<String> {
|
||||
let luid = self.luid;
|
||||
ffi::luid_to_alias(&unsafe { std::mem::transmute(luid) }).map(|name| {
|
||||
decode_utf16(&name)
|
||||
})
|
||||
ffi::luid_to_alias(&unsafe { std::mem::transmute(luid) }).map(|name| decode_utf16(&name))
|
||||
}
|
||||
|
||||
fn set_name(&self, new_name: &str) -> io::Result<()> {
|
||||
@@ -179,15 +206,21 @@ impl IFace for TunDevice {
|
||||
netsh::set_interface_name(&name, new_name)
|
||||
}
|
||||
|
||||
fn set_ip(&self, address: Ipv4Addr, mask: Ipv4Addr) -> io::Result<()>{
|
||||
fn set_ip(&self, address: Ipv4Addr, mask: Ipv4Addr) -> io::Result<()> {
|
||||
netsh::set_interface_ip(self.get_index()?, &address, &mask)
|
||||
}
|
||||
|
||||
fn add_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr, metric: u16) -> io::Result<()> {
|
||||
fn add_route(
|
||||
&self,
|
||||
dest: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
metric: u16,
|
||||
) -> io::Result<()> {
|
||||
route::add_route(self.get_index()?, dest, netmask, gateway, metric)
|
||||
}
|
||||
|
||||
fn delete_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
|
||||
fn delete_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
|
||||
route::delete_route(self.get_index()?, dest, netmask, gateway)
|
||||
}
|
||||
|
||||
@@ -257,14 +290,19 @@ impl TunDevice {
|
||||
)
|
||||
};
|
||||
match result {
|
||||
winbase::WAIT_FAILED => return Err(io::Error::new(io::ErrorKind::Other, "WAIT_FAILED")),
|
||||
winbase::WAIT_FAILED => {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "WAIT_FAILED"))
|
||||
}
|
||||
_ => {
|
||||
if result == winbase::WAIT_OBJECT_0 {
|
||||
//We have data!
|
||||
continue;
|
||||
} else if result == winbase::WAIT_OBJECT_0 + 1 {
|
||||
//Shutdown event triggered
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "Shutdown event triggered"));
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Shutdown event triggered",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,10 +313,14 @@ impl TunDevice {
|
||||
impl TunDevice {
|
||||
pub fn allocate_send_packet(&self, size: u16) -> io::Result<packet::TunPacket> {
|
||||
let bytes_ptr = unsafe {
|
||||
self.win_tun.WintunAllocateSendPacket(self.session, size as u32)
|
||||
self.win_tun
|
||||
.WintunAllocateSendPacket(self.session, size as u32)
|
||||
};
|
||||
if bytes_ptr.is_null() {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "allocate_send_packet failed"))
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"allocate_send_packet failed",
|
||||
))
|
||||
} else {
|
||||
Ok(packet::TunPacket {
|
||||
kind: packet::Kind::SendPacketPending,
|
||||
@@ -302,7 +344,6 @@ impl TunDevice {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Drop for TunDevice {
|
||||
fn drop(&mut self) {
|
||||
//Close adapter on drop
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
use crate::TunDevice;
|
||||
|
||||
pub(crate) enum Kind {
|
||||
@@ -12,7 +11,7 @@ pub(crate) enum Kind {
|
||||
/// Represents a wintun packet
|
||||
pub struct TunPacket<'a> {
|
||||
pub(crate) kind: Kind,
|
||||
pub(crate) size:usize,
|
||||
pub(crate) size: usize,
|
||||
pub(crate) bytes_ptr: *const u8,
|
||||
|
||||
//Share ownership of session to prevent the session from being dropped before packets that
|
||||
@@ -20,7 +19,7 @@ pub struct TunPacket<'a> {
|
||||
pub(crate) tun_device: Option<&'a TunDevice>,
|
||||
}
|
||||
|
||||
impl <'a>TunPacket<'a> {
|
||||
impl<'a> TunPacket<'a> {
|
||||
/// Returns the bytes this packet holds as &mut.
|
||||
/// The lifetime of the bytes is tied to the lifetime of this packet.
|
||||
pub fn bytes_mut(&mut self) -> &mut [u8] {
|
||||
@@ -30,11 +29,11 @@ impl <'a>TunPacket<'a> {
|
||||
/// Returns an immutable reference to the bytes this packet holds.
|
||||
/// The lifetime of the bytes is tied to the lifetime of this packet.
|
||||
pub fn bytes(&self) -> &[u8] {
|
||||
unsafe { std::slice::from_raw_parts(self.bytes_ptr,self.size) }
|
||||
unsafe { std::slice::from_raw_parts(self.bytes_ptr, self.size) }
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a>Drop for TunPacket<'a> {
|
||||
impl<'a> Drop for TunPacket<'a> {
|
||||
fn drop(&mut self) {
|
||||
match self.kind {
|
||||
Kind::ReceivePacket => {
|
||||
@@ -46,7 +45,8 @@ impl <'a>Drop for TunPacket<'a> {
|
||||
// ring buffer that the wintun session owns. We return that region of
|
||||
// memory back to wintun here
|
||||
let tun_device = self.tun_device.unwrap();
|
||||
tun_device.win_tun
|
||||
tun_device
|
||||
.win_tun
|
||||
.WintunReleaseReceivePacket(tun_device.session, self.bytes_ptr)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ impl<Storage> __BindgenBitfieldUnit<Storage> {
|
||||
}
|
||||
}
|
||||
impl<Storage> __BindgenBitfieldUnit<Storage>
|
||||
where
|
||||
Storage: AsRef<[u8]> + AsMut<[u8]>,
|
||||
where
|
||||
Storage: AsRef<[u8]> + AsMut<[u8]>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn get_bit(&self, index: usize) -> bool {
|
||||
@@ -112,40 +112,40 @@ fn bindgen_test_layout__GUID() {
|
||||
unsafe { &(*(::std::ptr::null::<_GUID>())).Data1 as *const _ as usize },
|
||||
0usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(_GUID),
|
||||
"::",
|
||||
stringify!(Data1)
|
||||
"Offset of field: ",
|
||||
stringify!(_GUID),
|
||||
"::",
|
||||
stringify!(Data1)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { &(*(::std::ptr::null::<_GUID>())).Data2 as *const _ as usize },
|
||||
4usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(_GUID),
|
||||
"::",
|
||||
stringify!(Data2)
|
||||
"Offset of field: ",
|
||||
stringify!(_GUID),
|
||||
"::",
|
||||
stringify!(Data2)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { &(*(::std::ptr::null::<_GUID>())).Data3 as *const _ as usize },
|
||||
6usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(_GUID),
|
||||
"::",
|
||||
stringify!(Data3)
|
||||
"Offset of field: ",
|
||||
stringify!(_GUID),
|
||||
"::",
|
||||
stringify!(Data3)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { &(*(::std::ptr::null::<_GUID>())).Data4 as *const _ as usize },
|
||||
8usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(_GUID),
|
||||
"::",
|
||||
stringify!(Data4)
|
||||
"Offset of field: ",
|
||||
stringify!(_GUID),
|
||||
"::",
|
||||
stringify!(Data4)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -248,20 +248,20 @@ fn bindgen_test_layout__NET_LUID_LH() {
|
||||
unsafe { &(*(::std::ptr::null::<_NET_LUID_LH>())).Value as *const _ as usize },
|
||||
0usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(_NET_LUID_LH),
|
||||
"::",
|
||||
stringify!(Value)
|
||||
"Offset of field: ",
|
||||
stringify!(_NET_LUID_LH),
|
||||
"::",
|
||||
stringify!(Value)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { &(*(::std::ptr::null::<_NET_LUID_LH>())).Info as *const _ as usize },
|
||||
0usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(_NET_LUID_LH),
|
||||
"::",
|
||||
stringify!(Info)
|
||||
"Offset of field: ",
|
||||
stringify!(_NET_LUID_LH),
|
||||
"::",
|
||||
stringify!(Info)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -310,33 +310,33 @@ pub struct wintun {
|
||||
pub WintunCloseAdapter: unsafe extern "C" fn(arg1: WINTUN_ADAPTER_HANDLE),
|
||||
pub WintunOpenAdapter: unsafe extern "C" fn(arg1: LPCWSTR) -> WINTUN_ADAPTER_HANDLE,
|
||||
pub WintunGetAdapterLUID:
|
||||
unsafe extern "C" fn(arg1: WINTUN_ADAPTER_HANDLE, arg2: *mut NET_LUID),
|
||||
unsafe extern "C" fn(arg1: WINTUN_ADAPTER_HANDLE, arg2: *mut NET_LUID),
|
||||
pub WintunGetRunningDriverVersion: unsafe extern "C" fn() -> DWORD,
|
||||
pub WintunDeleteDriver: unsafe extern "C" fn() -> BOOL,
|
||||
pub WintunSetLogger: unsafe extern "C" fn(arg1: WINTUN_LOGGER_CALLBACK),
|
||||
pub WintunStartSession:
|
||||
unsafe extern "C" fn(arg1: WINTUN_ADAPTER_HANDLE, arg2: DWORD) -> WINTUN_SESSION_HANDLE,
|
||||
unsafe extern "C" fn(arg1: WINTUN_ADAPTER_HANDLE, arg2: DWORD) -> WINTUN_SESSION_HANDLE,
|
||||
pub WintunEndSession: unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE),
|
||||
pub WintunGetReadWaitEvent: unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE) -> HANDLE,
|
||||
pub WintunReceivePacket:
|
||||
unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE, arg2: *mut DWORD) -> *mut BYTE,
|
||||
unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE, arg2: *mut DWORD) -> *mut BYTE,
|
||||
pub WintunReleaseReceivePacket:
|
||||
unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE, arg2: *const BYTE),
|
||||
unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE, arg2: *const BYTE),
|
||||
pub WintunAllocateSendPacket:
|
||||
unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE, arg2: DWORD) -> *mut BYTE,
|
||||
unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE, arg2: DWORD) -> *mut BYTE,
|
||||
pub WintunSendPacket: unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE, arg2: *const BYTE),
|
||||
}
|
||||
impl wintun {
|
||||
pub unsafe fn new<P>(path: P) -> Result<Self, ::libloading::Error>
|
||||
where
|
||||
P: AsRef<::std::ffi::OsStr>,
|
||||
where
|
||||
P: AsRef<::std::ffi::OsStr>,
|
||||
{
|
||||
let library = ::libloading::Library::new(path)?;
|
||||
Self::from_library(library)
|
||||
}
|
||||
pub unsafe fn from_library<L>(library: L) -> Result<Self, ::libloading::Error>
|
||||
where
|
||||
L: Into<::libloading::Library>,
|
||||
where
|
||||
L: Into<::libloading::Library>,
|
||||
{
|
||||
let __library = library.into();
|
||||
let WintunCreateAdapter = __library.get(b"WintunCreateAdapter\0").map(|sym| *sym)?;
|
||||
|
||||
Reference in New Issue
Block a user