Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26d68ac059 | ||
|
|
6292c1c381 | ||
|
|
b0c3f25a29 | ||
|
|
d2e09d3da5 | ||
|
|
293c5b90a4 | ||
|
|
e2323361f9 | ||
|
|
d05cff99ee | ||
|
|
e9b1b2ef3b | ||
|
|
a8ea2c14fc | ||
|
|
0688cb4515 | ||
|
|
c3261d7a57 | ||
|
|
ef8d13f61b | ||
|
|
fc104d5dee | ||
|
|
9ad0525216 | ||
|
|
3ea1250b53 | ||
|
|
9df34207f7 | ||
|
|
dacce892ff | ||
|
|
a9495f1d30 | ||
|
|
0892c6eee9 | ||
|
|
f746eadcf1 | ||
|
|
da2371541c | ||
|
|
cca91d4331 | ||
|
|
11aa3b1d2c | ||
|
|
d0b0c61a03 | ||
|
|
b0501db4e5 | ||
|
|
465a5c75ae | ||
|
|
978460aca8 | ||
|
|
4b86752c79 | ||
|
|
bd61cad7b6 | ||
|
|
40cbd2e26b | ||
|
|
2cab580b4e | ||
|
|
3d243fb01d | ||
|
|
ca4e8d14f0 | ||
|
|
9c098c55c9 | ||
|
|
707b07b8d3 | ||
|
|
de5a6971f0 | ||
|
|
056036c4d2 | ||
|
|
1cfb188845 | ||
|
|
73a2c31854 | ||
|
|
92eea536f8 | ||
|
|
00936a923e | ||
|
|
ba69ba78af | ||
|
|
17b206bace | ||
|
|
58d5a4f5da | ||
|
|
2438d14175 | ||
|
|
99f8526799 | ||
|
|
56fcbd64ed | ||
|
|
3766b2b7c1 | ||
|
|
baf0698fe4 | ||
|
|
301938b9fc | ||
|
|
16a37c713a | ||
|
|
d412a769dd | ||
|
|
c8eecc87fd | ||
|
|
6a11db70c8 | ||
|
|
d7c121a756 | ||
|
|
3429ee8bd6 | ||
|
|
4422f9f8b7 | ||
|
|
57ed454c93 | ||
|
|
236205c0f3 | ||
|
|
99b4bf0041 | ||
|
|
9495e39700 | ||
|
|
75e244e3a8 | ||
|
|
bf8397e6e3 | ||
|
|
8cee974866 | ||
|
|
5e018801db | ||
|
|
c4f7f4c19e | ||
|
|
29945eb3da | ||
|
|
7db415d243 | ||
|
|
808dcec795 | ||
|
|
f4dda173c2 | ||
|
|
84e70149a1 |
+63
-49
@@ -37,49 +37,41 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
# a list of all the targets
|
# a list of all the targets
|
||||||
|
# 选择使用openssl或者ring,并不是所有平台都支持
|
||||||
include:
|
include:
|
||||||
- TARGET: i686-unknown-linux-musl # test in an alpine container on a mac
|
- TARGET: i686-unknown-linux-musl # test in an alpine container on a mac
|
||||||
OS: ubuntu-latest
|
OS: ubuntu-latest
|
||||||
FEATURES: normal
|
FEATURES: default
|
||||||
- TARGET: x86_64-unknown-linux-gnu # tested in a debian container on a mac
|
|
||||||
OS: ubuntu-latest
|
|
||||||
FEATURES: ring-cipher
|
|
||||||
- TARGET: x86_64-unknown-linux-musl # test in an alpine container on a mac
|
- TARGET: x86_64-unknown-linux-musl # test in an alpine container on a mac
|
||||||
OS: ubuntu-latest
|
OS: ubuntu-latest
|
||||||
FEATURES: ring-cipher
|
FEATURES: ring-cipher,openssl-vendored
|
||||||
- TARGET: aarch64-unknown-linux-gnu # tested on aws t4g.nano
|
|
||||||
OS: ubuntu-latest
|
|
||||||
FEATURES: ring-cipher
|
|
||||||
- TARGET: aarch64-unknown-linux-musl # tested on aws t4g.nano in alpine container
|
- TARGET: aarch64-unknown-linux-musl # tested on aws t4g.nano in alpine container
|
||||||
OS: ubuntu-latest
|
OS: ubuntu-latest
|
||||||
FEATURES: normal
|
FEATURES: ring-cipher,openssl-vendored
|
||||||
- TARGET: armv7-unknown-linux-gnueabihf # raspberry pi 2-3-4, not tested
|
|
||||||
OS: ubuntu-latest
|
|
||||||
FEATURES: ring-cipher
|
|
||||||
- TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested
|
- TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested
|
||||||
OS: ubuntu-latest
|
OS: ubuntu-latest
|
||||||
FEATURES: normal
|
FEATURES: openssl-vendored
|
||||||
- TARGET: arm-unknown-linux-gnueabihf # raspberry pi 0-1, not tested
|
|
||||||
OS: ubuntu-latest
|
|
||||||
FEATURES: ring-cipher
|
|
||||||
- TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested
|
- TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested
|
||||||
OS: ubuntu-latest
|
OS: ubuntu-latest
|
||||||
FEATURES: normal
|
FEATURES: ring-cipher,openssl-vendored
|
||||||
- TARGET: x86_64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
|
- TARGET: x86_64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
|
||||||
OS: macos-latest
|
OS: macos-latest
|
||||||
FEATURES: ring-cipher
|
FEATURES: ring-cipher,openssl-vendored
|
||||||
- TARGET: aarch64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
|
- TARGET: aarch64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
|
||||||
OS: macos-latest
|
OS: macos-latest
|
||||||
FEATURES: ring-cipher
|
FEATURES: ring-cipher,openssl-vendored
|
||||||
- TARGET: i686-pc-windows-msvc # tested on a windows machine
|
- TARGET: i686-pc-windows-msvc # tested on a windows machine
|
||||||
OS: windows-latest
|
OS: windows-2019
|
||||||
FEATURES: ring-cipher
|
FEATURES: ring-cipher,openssl-vendored
|
||||||
- TARGET: x86_64-pc-windows-msvc # tested on a windows machine
|
- TARGET: x86_64-pc-windows-msvc # tested on a windows machine
|
||||||
OS: windows-latest
|
OS: windows-latest
|
||||||
FEATURES: ring-cipher
|
FEATURES: ring-cipher,openssl-vendored
|
||||||
- TARGET: mipsel-unknown-linux-musl # openwrt
|
- TARGET: mipsel-unknown-linux-musl # openwrt
|
||||||
OS: ubuntu-latest
|
OS: ubuntu-latest
|
||||||
FEATURES: normal
|
FEATURES: openssl-vendored,ring-cipher
|
||||||
|
- TARGET: mips-unknown-linux-musl # openwrt
|
||||||
|
OS: ubuntu-latest
|
||||||
|
FEATURES: openssl-vendored
|
||||||
# needs: test
|
# needs: test
|
||||||
runs-on: ${{ matrix.OS }}
|
runs-on: ${{ matrix.OS }}
|
||||||
env:
|
env:
|
||||||
@@ -98,6 +90,9 @@ jobs:
|
|||||||
~/.cargo/registry
|
~/.cargo/registry
|
||||||
./target
|
./target
|
||||||
key: build-cargo-registry-${{matrix.TARGET}}
|
key: build-cargo-registry-${{matrix.TARGET}}
|
||||||
|
- name: Use strawberry perl
|
||||||
|
if: startsWith(matrix.os, 'windows')
|
||||||
|
run: echo OPENSSL_SRC_PERL=C:/Strawberry/perl/bin/perl >> $GITHUB_ENV
|
||||||
- name: List
|
- name: List
|
||||||
run: find ./
|
run: find ./
|
||||||
- name: Install and configure dependencies
|
- name: Install and configure dependencies
|
||||||
@@ -105,45 +100,64 @@ jobs:
|
|||||||
# dependencies are only needed on ubuntu as that's the only place where
|
# dependencies are only needed on ubuntu as that's the only place where
|
||||||
# we make cross-compilation
|
# we make cross-compilation
|
||||||
if [[ $OS =~ ^ubuntu.*$ ]]; then
|
if [[ $OS =~ ^ubuntu.*$ ]]; then
|
||||||
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools gcc-mipsel-linux-gnu
|
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools
|
||||||
|
# curl -s musl.cc | grep mipsel
|
||||||
|
case $TARGET in
|
||||||
|
mipsel-unknown-linux-musl)
|
||||||
|
MUSL_URI=mipsel-linux-musl-cross
|
||||||
|
;;
|
||||||
|
aarch64-unknown-linux-musl)
|
||||||
|
MUSL_URI=aarch64-linux-musl-cross
|
||||||
|
;;
|
||||||
|
armv7-unknown-linux-musleabihf)
|
||||||
|
MUSL_URI=armv7l-linux-musleabihf-cross
|
||||||
|
;;
|
||||||
|
arm-unknown-linux-musleabihf)
|
||||||
|
MUSL_URI=arm-linux-musleabihf-cross
|
||||||
|
;;
|
||||||
|
mips-unknown-linux-musl)
|
||||||
|
MUSL_URI=mips-linux-musl-cross
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -n "$MUSL_URI" ]; then
|
||||||
|
mkdir -p ./musl_gcc
|
||||||
|
wget -c https://musl.cc/$MUSL_URI.tgz -P ./musl_gcc/
|
||||||
|
tar zxf ./musl_gcc/$MUSL_URI.tgz -C ./musl_gcc/
|
||||||
|
sudo ln -s $(pwd)/musl_gcc/$MUSL_URI/bin/*gcc /usr/bin/
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# some additional configuration for cross-compilation on linux
|
# some additional configuration for cross-compilation on linux
|
||||||
cat >>~/.cargo/config <<EOF
|
cat >>~/.cargo/config <<EOF
|
||||||
[target.x86_64-unknown-linux-musl]
|
[target.x86_64-unknown-linux-musl]
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||||
[target.aarch64-unknown-linux-gnu]
|
|
||||||
linker = "aarch64-linux-gnu-gcc"
|
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
|
||||||
[target.aarch64-unknown-linux-musl]
|
[target.aarch64-unknown-linux-musl]
|
||||||
linker = "aarch64-linux-gnu-gcc"
|
linker = "aarch64-linux-musl-gcc"
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||||
[target.armv7-unknown-linux-gnueabihf]
|
|
||||||
linker = "arm-linux-gnueabihf-gcc"
|
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
|
||||||
[target.armv7-unknown-linux-musleabihf]
|
[target.armv7-unknown-linux-musleabihf]
|
||||||
linker = "arm-linux-gnueabihf-gcc"
|
linker = "armv7l-linux-musleabihf-gcc"
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||||
[target.arm-unknown-linux-gnueabihf]
|
|
||||||
linker = "arm-linux-gnueabihf-gcc"
|
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
|
||||||
[target.arm-unknown-linux-musleabihf]
|
[target.arm-unknown-linux-musleabihf]
|
||||||
linker = "arm-linux-gnueabihf-gcc"
|
linker = "arm-linux-musleabihf-gcc"
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||||
[target.mipsel-unknown-linux-musl]
|
[target.mipsel-unknown-linux-musl]
|
||||||
linker = "mipsel-linux-gnu-gcc"
|
linker = "mipsel-linux-musl-gcc"
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||||
|
[target.mips-unknown-linux-musl]
|
||||||
|
linker = "mips-linux-musl-gcc"
|
||||||
|
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||||
[target.x86_64-pc-windows-msvc]
|
[target.x86_64-pc-windows-msvc]
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||||
[target.i686-pc-windows-msvc]
|
[target.i686-pc-windows-msvc]
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||||
[target.x86_64-apple-darwin]
|
[target.x86_64-apple-darwin]
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||||
[target.aarch64-apple-darwin]
|
[target.aarch64-apple-darwin]
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||||
[target.i686-unknown-linux-musl]
|
[target.i686-unknown-linux-musl]
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols"]
|
||||||
[target.x86_64-unknown-linux-gnu]
|
|
||||||
rustflags = ["-C", "target-feature=+crt-static","-C", "strip=symbols","--cfg","aes_armv8"]
|
|
||||||
EOF
|
EOF
|
||||||
- name: Install rust target
|
- name: Install rust target
|
||||||
run: rustup target add $TARGET
|
run: rustup target add $TARGET
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ opt-level = 'z'
|
|||||||
debug = 0
|
debug = 0
|
||||||
debug-assertions = false
|
debug-assertions = false
|
||||||
strip= "debuginfo"
|
strip= "debuginfo"
|
||||||
overflow-checks = true
|
|
||||||
lto = true
|
lto = true
|
||||||
panic = 'abort'
|
panic = 'abort'
|
||||||
incremental = false
|
incremental = false
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
A virtual network tool (VPN)
|
A virtual network tool (VPN)
|
||||||
|
|
||||||
将不同网络下的多个设备虚拟到一个局域网下
|
将不同网络下的多个设备虚拟到一个局域网下
|
||||||
|
|
||||||
### vnt-cli参数详解 [参数说明](https://github.com/lbl8603/vnt/blob/main/vnt-cli/README.md)
|
### vnt-cli参数详解 [参数说明](https://github.com/lbl8603/vnt/blob/main/vnt-cli/README.md)
|
||||||
|
|
||||||
### 快速使用:
|
### 快速使用:
|
||||||
|
|
||||||
1. 指定一个token,在多台设备上运行该程序,例如:
|
1. 指定一个token,在多台设备上运行该程序,例如:
|
||||||
@@ -61,17 +63,107 @@ A virtual network tool (VPN)
|
|||||||
|
|
||||||
前提条件:安装rust编译环境([install rust](https://www.rust-lang.org/zh-CN/tools/install))
|
前提条件:安装rust编译环境([install rust](https://www.rust-lang.org/zh-CN/tools/install))
|
||||||
|
|
||||||
|
```
|
||||||
到项目根目录下执行 cargo build -p vnt-cli
|
到项目根目录下执行 cargo build -p vnt-cli
|
||||||
|
|
||||||
|
也可按需编译,将得到更小的二进制文件,使用--no-default-features排除默认features
|
||||||
|
|
||||||
|
cargo build -p vnt-cli --no-default-features
|
||||||
|
```
|
||||||
|
|
||||||
|
features说明
|
||||||
|
|
||||||
|
| feature | 说明 | 是否默认 |
|
||||||
|
|------------------|----------------------|------|
|
||||||
|
| openssl | 使用openssl中的aes_ecb算法 | 否 |
|
||||||
|
| openssl-vendored | 从源码编译openssl | 否 |
|
||||||
|
| ring-cipher | 使用ring中的aes_gcm算法 | 否 |
|
||||||
|
| aes_cbc | 支持aes_cbc加密 | 是 |
|
||||||
|
| aes_ecb | 支持aes_ecb加密 | 是 |
|
||||||
|
| aes_gcm | 支持aes_gcm加密 | 是 |
|
||||||
|
| sm4_cbc | 支持sm4_cbc加密 | 是 |
|
||||||
|
| server_encrypt | 支持服务端加密 | 是 |
|
||||||
|
| ip_proxy | 内置ip代理 | 是 |
|
||||||
|
|
||||||
|
如果编译时去除了内置的ip代理(或使用--no-proxy关闭了代理),则可以使用网卡NAT转发来实现点对网,
|
||||||
|
一般来说使用网卡NAT转发会比内置的ip代理性能更好
|
||||||
|
<details> <summary>NAT配置可参考如下示例,点击展开</summary>
|
||||||
|
|
||||||
|
### 在出口一端做如下配置
|
||||||
|
注意原有的-i(入口)和-o(出口)的参数不能少
|
||||||
|
|
||||||
|
### windows
|
||||||
|
参考 https://learn.microsoft.com/zh-cn/virtualization/hyper-v-on-windows/user-guide/setup-nat-network
|
||||||
|
```shell
|
||||||
|
#设置nat,名字可以自己取,网段是vnt的网段
|
||||||
|
New-NetNat -Name vntnat -InternalIPInterfaceAddressPrefix 10.26.0.0/24
|
||||||
|
#查看设置
|
||||||
|
Get-NetNat
|
||||||
|
```
|
||||||
|
### linux
|
||||||
|
```shell
|
||||||
|
# 开启ip转发
|
||||||
|
sudo sysctl -w net.ipv4.ip_forward=1
|
||||||
|
# 开启nat转发 表示来源10.26.0.0/24的数据通过nat映射后再从vnt-tun以外的其他网卡发出去
|
||||||
|
sudo iptables -t nat -A POSTROUTING ! -o vnt-tun -s 10.26.0.0/24 -j MASQUERADE
|
||||||
|
# 或者这样 表示来源10.26.0.0/24的数据通过nat映射后再从eth0网卡发出去
|
||||||
|
sudo iptables -t nat -A POSTROUTING -o eth0 -s 10.26.0.0/24 -j MASQUERADE
|
||||||
|
# 查看设置
|
||||||
|
iptables -vnL -t nat
|
||||||
|
```
|
||||||
|
|
||||||
|
### Arch Linux
|
||||||
|
|
||||||
|
[](https://repology.org/project/vnt/versions)
|
||||||
|
|
||||||
|
- 通过 AUR 安装 [vnt-git](https://aur.archlinux.org/packages/vnt-git)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yay -Syu vnt
|
||||||
|
```
|
||||||
|
|
||||||
|
- 通过 `systemd` 设置开机自启及配置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl enable --now vnt-cli@
|
||||||
|
sudo systemctl status vnt-cli@
|
||||||
|
```
|
||||||
|
|
||||||
|
- 启用内置 `IPv4` 转发规则
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo sysctl --system
|
||||||
|
```
|
||||||
|
|
||||||
|
- 通过内置防火墙文件配置防火墙转发规则
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo cat /etc/vnt/iptables-vnt.rules >> /etc/iptables/iptables.rules
|
||||||
|
sudo iptables-restore iptables.rules
|
||||||
|
```
|
||||||
|
|
||||||
|
### macos
|
||||||
|
```shell
|
||||||
|
# 开启ip转发
|
||||||
|
sudo sysctl -w net.ipv4.ip_forward=1
|
||||||
|
# 配置NAT转发规则
|
||||||
|
# 在/etc/pf.conf文件中添加以下规则,en0是出口网卡,10.26.0.0/24是来源网段
|
||||||
|
nat on en0 from 10.26.0.0/24 to any -> (en0)
|
||||||
|
# 加载规则
|
||||||
|
sudo pfctl -f /etc/pf.conf -e
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
### 支持平台
|
### 支持平台
|
||||||
|
|
||||||
- Mac
|
- Mac
|
||||||
- Linux
|
- Linux
|
||||||
|
- Arch Linux `yay -Syu vnt`
|
||||||
- Windows
|
- Windows
|
||||||
- 使用tun网卡 依赖wintun.dll([win-tun](https://www.wintun.net/))(将dll放到同目录下,建议使用版本0.14.1)
|
- 默认使用tun网卡 依赖wintun.dll([win-tun](https://www.wintun.net/))(将dll放到同目录下,建议使用版本0.14.1)
|
||||||
- 使用tap网卡 依赖tap-windows([win-tap](https://build.openvpn.net/downloads/releases/))(建议使用版本9.24.7)
|
- 使用tap网卡 依赖tap-windows([win-tap](https://build.openvpn.net/downloads/releases/))(建议使用版本9.24.7)
|
||||||
- Android
|
- Android
|
||||||
- [SwitchApp](https://github.com/lbl8603/SwitchApp)
|
- [VntApp](https://github.com/lbl8603/VntApp)
|
||||||
|
|
||||||
### 特性
|
### 特性
|
||||||
|
|
||||||
@@ -86,9 +178,11 @@ A virtual network tool (VPN)
|
|||||||
- p2p组播/广播
|
- p2p组播/广播
|
||||||
- 客户端数据加密
|
- 客户端数据加密
|
||||||
- 服务端数据加密
|
- 服务端数据加密
|
||||||
|
|
||||||
### 结构
|
### 结构
|
||||||
|
|
||||||
<details> <summary>展开</summary>
|
<details> <summary>展开</summary>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
|
|
||||||
0 15 31
|
0 15 31
|
||||||
@@ -121,8 +215,9 @@ A virtual network tool (VPN)
|
|||||||
- 支持Ipv6(1.2.2已支持客户端之间的ipv6,待支持客户端和服务端之间的ipv6通信)
|
- 支持Ipv6(1.2.2已支持客户端之间的ipv6,待支持客户端和服务端之间的ipv6通信)
|
||||||
|
|
||||||
### 常见问题
|
### 常见问题
|
||||||
|
|
||||||
<details> <summary>展开</summary>
|
<details> <summary>展开</summary>
|
||||||
|
|
||||||
#### 问题1: 设置网络地址失败
|
#### 问题1: 设置网络地址失败
|
||||||
|
|
||||||
##### 可能原因:
|
##### 可能原因:
|
||||||
@@ -138,26 +233,41 @@ vnt默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突
|
|||||||
#### 问题2: windows系统上wintun.dll加载失败
|
#### 问题2: windows系统上wintun.dll加载失败
|
||||||
|
|
||||||
##### 可能原因:
|
##### 可能原因:
|
||||||
|
|
||||||
没有下载wintun.dll 或者使用的wintun.dll有问题
|
没有下载wintun.dll 或者使用的wintun.dll有问题
|
||||||
|
|
||||||
##### 解决方法:
|
##### 解决方法:
|
||||||
|
|
||||||
1. 下载最新版的wintun.dll [下载链接](https://www.wintun.net/builds/wintun-0.14.1.zip)
|
1. 下载最新版的wintun.dll [下载链接](https://www.wintun.net/builds/wintun-0.14.1.zip)
|
||||||
2. 解压后找到对应架构的目录,通常是amd64
|
2. 解压后找到对应架构的目录,通常是amd64
|
||||||
3. 将对应的wintun.dll放到和vnt-cli同目录下(或者放到C盘Windows目录下)
|
3. 将对应的wintun.dll放到和vnt-cli同目录下(或者放到C盘Windows目录下)
|
||||||
4. 再次启动vnt-cli
|
4. 再次启动vnt-cli
|
||||||
|
|
||||||
#### 问题3: 丢包严重,或是不能正常组网通信
|
#### 问题3: 丢包严重,或是不能正常组网通信
|
||||||
|
|
||||||
##### 可能原因:
|
##### 可能原因:
|
||||||
|
|
||||||
某些宽带下(比如广电宽带)UDP丢包严重
|
某些宽带下(比如广电宽带)UDP丢包严重
|
||||||
|
|
||||||
##### 解决方法:
|
##### 解决方法:
|
||||||
|
|
||||||
1. 使用TCP模式中继转发(vnt-cli增加--tcp参数)
|
1. 使用TCP模式中继转发(vnt-cli增加--tcp参数)
|
||||||
2. 如果p2p后效果很差,可以选择禁用p2p(vnt-cli增加--relay参数)
|
2. 如果p2p后效果很差,可以选择禁用p2p(vnt-cli增加--relay参数)
|
||||||
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 交流群
|
### 交流群
|
||||||
|
|
||||||
QQ:1034868233
|
QQ: 1034868233
|
||||||
|
|
||||||
### 其他
|
### 其他
|
||||||
|
|
||||||
可使用社区小伙伴搭建的中继服务器
|
可使用社区小伙伴搭建的中继服务器
|
||||||
|
|
||||||
1. -s vnt.8443.eu.org:29871
|
1. -s vnt.8443.eu.org:29871
|
||||||
|
|
||||||
|
### 参与贡献
|
||||||
|
|
||||||
|
<a href="https://github.com/lbl8603/vnt/graphs/contributors">
|
||||||
|
<img src="https://contrib.rocks/image?repo=lbl8603/vnt" />
|
||||||
|
</a>
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "common"
|
name = "common"
|
||||||
version = "1.2.2"
|
version = "1.2.7"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ pub fn out_ips_parse(ips: &Vec<String>) -> Result<Vec<(u32, u32)>, String> {
|
|||||||
|
|
||||||
pub fn to_ip(mask: &str) -> Result<u32, String> {
|
pub fn to_ip(mask: &str) -> Result<u32, String> {
|
||||||
if let Ok(m) = mask.parse::<u32>() {
|
if let Ok(m) = mask.parse::<u32>() {
|
||||||
|
if m >= 32 {
|
||||||
|
return Err("not netmask".to_string());
|
||||||
|
}
|
||||||
let mut mask = 0 as u32;
|
let mut mask = 0 as u32;
|
||||||
for i in 0..m {
|
for i in 0..m {
|
||||||
mask = mask | (1 << (31 - i));
|
mask = mask | (1 << (31 - i));
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
use std::process::Command;
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub fn get_unique_identifier() -> Option<String> {
|
pub fn get_unique_identifier() -> Option<String> {
|
||||||
use std::os::windows::process::CommandExt;
|
use std::os::windows::process::CommandExt;
|
||||||
|
use std::process::Command;
|
||||||
let output = match Command::new("wmic")
|
let output = match Command::new("wmic")
|
||||||
.creation_flags(0x08000000)
|
.creation_flags(0x08000000)
|
||||||
.args(&["csproduct", "get", "UUID"])
|
.args(&["csproduct", "get", "UUID"])
|
||||||
@@ -25,6 +24,7 @@ pub fn get_unique_identifier() -> Option<String> {
|
|||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
pub fn get_unique_identifier() -> Option<String> {
|
pub fn get_unique_identifier() -> Option<String> {
|
||||||
|
use std::process::Command;
|
||||||
let output = match Command::new("ioreg")
|
let output = match Command::new("ioreg")
|
||||||
.args(&["-rd1", "-c", "IOPlatformExpertDevice"])
|
.args(&["-rd1", "-c", "IOPlatformExpertDevice"])
|
||||||
.output()
|
.output()
|
||||||
@@ -50,6 +50,7 @@ pub fn get_unique_identifier() -> Option<String> {
|
|||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub fn get_unique_identifier() -> Option<String> {
|
pub fn get_unique_identifier() -> Option<String> {
|
||||||
|
use std::process::Command;
|
||||||
let output = match Command::new("dmidecode")
|
let output = match Command::new("dmidecode")
|
||||||
.arg("-s")
|
.arg("-s")
|
||||||
.arg("system-uuid")
|
.arg("system-uuid")
|
||||||
|
|||||||
+14
-8
@@ -1,20 +1,21 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "vnt-cli"
|
name = "vnt-cli"
|
||||||
version = "1.2.2"
|
version = "1.2.7"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
vnt = { path = "../vnt", package = "vnt", optional = true }
|
vnt = { path = "../vnt", package = "vnt",default-features = false }
|
||||||
common = { path = "../common" }
|
common = { path = "../common" }
|
||||||
tokio = { version = "1.28.1", features = ["full"] }
|
tokio = { version = "1.32.0", features = ["full"] }
|
||||||
getopts = "0.2.21"
|
getopts = "0.2.21"
|
||||||
console = "0.15.2"
|
console = "0.15.2"
|
||||||
os_info = "3.7.0"
|
os_info = "3.7.0"
|
||||||
dirs = "4.0.0"
|
dirs = "5.0.1"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_json = "1.0.94"
|
serde_json = "1.0.94"
|
||||||
|
serde_yaml = "0.8.26"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
log4rs = "1.2.0"
|
log4rs = "1.2.0"
|
||||||
[dependencies.uuid]
|
[dependencies.uuid]
|
||||||
@@ -30,10 +31,15 @@ sudo = "0.6.0"
|
|||||||
winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] }
|
winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["normal"]
|
default = ["server_encrypt","aes_gcm","aes_cbc","aes_ecb","sm4_cbc","ip_proxy"]
|
||||||
normal = ["vnt"]
|
openssl = ["vnt/openssl"]
|
||||||
|
openssl-vendored = ["vnt/openssl-vendored"]
|
||||||
ring-cipher = ["vnt/ring-cipher"]
|
ring-cipher = ["vnt/ring-cipher"]
|
||||||
|
aes_cbc=["vnt/aes_cbc"]
|
||||||
|
aes_ecb=["vnt/aes_ecb"]
|
||||||
|
sm4_cbc=["vnt/sm4_cbc"]
|
||||||
|
aes_gcm=["vnt/aes_gcm"]
|
||||||
|
server_encrypt=["vnt/server_encrypt"]
|
||||||
|
ip_proxy=["vnt/ip_proxy"]
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
embed-manifest = "1.4.0"
|
embed-manifest = "1.4.0"
|
||||||
+78
-17
@@ -19,21 +19,28 @@
|
|||||||
|
|
||||||
配置点对网(IP代理)时使用,例如A(虚拟ip:10.26.0.2)通过B(虚拟ip:10.26.0.3,本地出口ip:192.168.0.10)访问C(目标网段192.168.0.0/24),
|
配置点对网(IP代理)时使用,例如A(虚拟ip:10.26.0.2)通过B(虚拟ip:10.26.0.3,本地出口ip:192.168.0.10)访问C(目标网段192.168.0.0/24),
|
||||||
|
|
||||||
则在A配置 **-i 192.168.0.0/24,10.26.0.3** ,表示将192.168.0.0/24网段的数据都转发到10.26.0.3节点
|
则在A配置 **'-i 192.168.0.0/24,10.26.0.3'** ,表示将192.168.0.0/24网段的数据都转发到10.26.0.3节点
|
||||||
|
|
||||||
在B配置 **-o 192.168.0.0/24** ,表示允许将数据转发到 192.168.0.0/24
|
在B配置 **'-o 192.168.0.0/24'** ,表示允许将数据转发到 192.168.0.0/24 ,允许转发所有网段可以使用 **'-o 0.0.0.0/0'**
|
||||||
|
|
||||||
|
-i和-o参数均可使用多次,来指定不同网段,例如 **'-o 192.168.1.0/24 -o 192.168.2.0/24'** 表示允许转发目标为192.168.1.0/24或192.168.2.0/24这两个网段的数据
|
||||||
|
|
||||||
### -w `<password>`
|
### -w `<password>`
|
||||||
|
|
||||||
提升通信安全性,使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密(包括中继数据)。使用相同密码的客户端才能通信
|
提升通信安全性,使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密(包括中继数据)。使用相同密码的客户端才能通信
|
||||||
|
|
||||||
| 密码位数 | 加密算法 |
|
| 密码位数 | 加密算法 |
|
||||||
|---------|-------|
|
|-------|------------|
|
||||||
| 小于8 | AES128-GCM
|
| 小于8 | AES128-GCM |
|
||||||
| 大于等于8 | AES256-GCM |
|
| 大于等于8 | AES256-GCM |
|
||||||
|
|
||||||
### -W
|
### -W
|
||||||
开启和服务端通信加密,可以避免中间人攻击
|
开启和服务端通信的数据加密,采用rsa+aes256gcm加密客户端和服务端之间通信的数据,可以避免token泄漏、中间人攻击
|
||||||
|
|
||||||
|
注意:
|
||||||
|
1. -w `<password>`是用于客户端-客户端之间的加密,password不会传递到服务端,只添加这个参数不会加密客户端-服务端通信的数据
|
||||||
|
2. -W 用于开启客户端-服务端之间的加密
|
||||||
|
|
||||||
### -m
|
### -m
|
||||||
模拟组播,高频使用组播通信时,可以尝试开启此参数,默认情况下会把组播当作广播发给所有节点
|
模拟组播,高频使用组播通信时,可以尝试开启此参数,默认情况下会把组播当作广播发给所有节点
|
||||||
|
|
||||||
@@ -43,7 +50,7 @@
|
|||||||
|
|
||||||
### -u `<mtu>`
|
### -u `<mtu>`
|
||||||
|
|
||||||
设置虚拟网卡的mtu值,大多数情况下使用默认值效率会更高,也可根据实际情况微调这个值,不加密默认为1430,加密默认为1410
|
设置虚拟网卡的mtu值,大多数情况下使用默认值效率会更高,也可根据实际情况微调这个值,不加密默认为1450,加密默认为1410
|
||||||
|
|
||||||
### --tcp
|
### --tcp
|
||||||
和服务端使用tcp通信。有些网络提供商对UDP限制比较大,这个时候可以选择使用TCP模式,提高稳定性。一般来说udp延迟和消耗更低
|
和服务端使用tcp通信。有些网络提供商对UDP限制比较大,这个时候可以选择使用TCP模式,提高稳定性。一般来说udp延迟和消耗更低
|
||||||
@@ -51,20 +58,74 @@
|
|||||||
指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配
|
指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配
|
||||||
### --par `<parallel>`
|
### --par `<parallel>`
|
||||||
任务并行度(必须为正整数),默认值为1,该值表示处理网卡读写的任务数,组网设备数较多、处理延迟较大时可适当调大此值
|
任务并行度(必须为正整数),默认值为1,该值表示处理网卡读写的任务数,组网设备数较多、处理延迟较大时可适当调大此值
|
||||||
### --thread `<thread>`
|
|
||||||
线程数(必须为正整数),默认为核心数乘2,该值表示处理网络读写、ip代理、打洞等用到的线程数,组网设备数较多、处理延迟较大时可适当调大此值
|
|
||||||
### --model `<model>`
|
### --model `<model>`
|
||||||
加密模式,可选值 aes_gcm/aes_cbc,默认使用aes_gcm,通常情况使用aes_cbc性能更好
|
加密模式,可选值 aes_gcm/aes_cbc/aes_ecb/sm4_cbc,默认使用aes_gcm,通常情况aes_gcm安全性高、aes_ecb性能更好,但是在低性能设备上sm4_cbc也许速度会更快;
|
||||||
|
|
||||||
| 密码位数 | model | 加密算法 |
|
|
||||||
|-------|--------|------------|
|
| 密码位数 | model | 加密算法 |
|
||||||
| 1~8位 | aes_gcm | AES128-GCM |
|
|-------|---------|------------|
|
||||||
| `>=`8 | aes_gcm | AES256-GCM |
|
| 1~8位 | aes_gcm | AES128-GCM |
|
||||||
| 1~8位 | aes_cbc | AES128-CBC |
|
| `>=`8 | aes_gcm | AES256-GCM |
|
||||||
| `>=`8 | aes_cbc | AES256-CBC |
|
| 1~8位 | aes_cbc | AES128-CBC |
|
||||||
|
| `>=`8 | aes_cbc | AES256-CBC |
|
||||||
|
| 1~8位 | aes_ecb | AES128-ECB |
|
||||||
|
| `>=`8 | aes_ecb | AES256-ECB |
|
||||||
|
| `>0` | sm4_cbc | SM4-CBC |
|
||||||
### --finger
|
### --finger
|
||||||
|
|
||||||
开启数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启,开启会损耗一部分性能
|
开启数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启,开启会损耗一部分性能
|
||||||
|
|
||||||
|
注意:默认情况下服务端不会对中转的数据做校验,如果要对中转的数据做校验,则需要客户端、服务端都开启此参数
|
||||||
|
### --punch `<punch>`
|
||||||
|
取值ipv4/ipv6,选择只使用ipv4打洞或者只使用ipv6打洞,默认两则都会使用
|
||||||
|
### --port `<port>`
|
||||||
|
取值0~65535,指定本地监听的端口,默认取随机端口
|
||||||
|
### --cmd
|
||||||
|
开启交互式命令,开启后可以直接在窗口下输入命令,如需后台运行请勿开启
|
||||||
|
### --first_latency
|
||||||
|
优先使用低延迟通道,默认情况下优先使用p2p通道,某些情况下可能p2p比客户端中继延迟更高,可使用此参数进行优化传输
|
||||||
|
### --no-proxy
|
||||||
|
关闭内置的ip代理,内置的代理较为简单,而且一般来说直接使用网卡NAT转发性能会更高,
|
||||||
|
有需要可以自行配置NAT转发,[可参考‘编译’小节中的NAT配置](https://github.com/lbl8603/vnt#%E7%BC%96%E8%AF%91)
|
||||||
|
### -f `<conf>`
|
||||||
|
指定配置文件
|
||||||
|
配置文件采用yaml格式,可参考:
|
||||||
|
```yaml
|
||||||
|
# 全部参数
|
||||||
|
tap: false #是否使用tap
|
||||||
|
token: xxx #组网token
|
||||||
|
device_id: xxx #当前设备id
|
||||||
|
name: windows 11 #当前设备名称
|
||||||
|
server_address: ip:port #注册和中继服务器
|
||||||
|
stun_server: #stun服务器
|
||||||
|
- stun1.l.google.com:19302
|
||||||
|
- stun2.l.google.com:19302
|
||||||
|
in_ips: #代理ip入站
|
||||||
|
- 192.168.1.0/24,10.26.0.3
|
||||||
|
out_ips: #代理ip出站
|
||||||
|
- 0.0.0.0/0
|
||||||
|
password: xxx #密码
|
||||||
|
simulate_multicast: false #模拟组播
|
||||||
|
mtu: 1420 #mtu
|
||||||
|
tcp: false #tcp模式
|
||||||
|
ip: 10.26.0.2 #指定虚拟ip
|
||||||
|
relay: false #中继模式
|
||||||
|
server_encrypt: true #服务端加密
|
||||||
|
parallel: 1 #任务并行度
|
||||||
|
cipher_model: aes_gcm #客户端加密算法
|
||||||
|
finger: false #关闭数据指纹
|
||||||
|
punch_model: ipv4 #打洞模式
|
||||||
|
port: 0 #使用随机端口
|
||||||
|
cmd: false #关闭控制台输入
|
||||||
|
no_proxy: false #是否关闭内置代理,true为关闭
|
||||||
|
first_latency: false #是否优先低延迟通道,默认为false,表示优先使用p2p通道
|
||||||
|
```
|
||||||
|
|
||||||
|
或者需要哪个配置就加哪个,当然token是必须的
|
||||||
|
```yaml
|
||||||
|
# 部分参数
|
||||||
|
token: xxx #组网token
|
||||||
|
```
|
||||||
### --relay
|
### --relay
|
||||||
禁用p2p,在网络环境很差时,只使用服务器中转效果可能更好(可以配合--tcp参数一起使用)
|
禁用p2p,在网络环境很差时,只使用服务器中转效果可能更好(可以配合--tcp参数一起使用)
|
||||||
### --list
|
### --list
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ impl CommandClient {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let udp = UdpSocket::bind("127.0.0.1:0")?;
|
let udp = UdpSocket::bind("127.0.0.1:0")?;
|
||||||
udp.set_read_timeout(Some(Duration::from_secs(2)))?;
|
udp.set_read_timeout(Some(Duration::from_secs(5)))?;
|
||||||
udp.connect(SocketAddr::V4(SocketAddrV4::new(
|
udp.connect(SocketAddr::V4(SocketAddrV4::new(
|
||||||
Ipv4Addr::new(127, 0, 0, 1),
|
Ipv4Addr::new(127, 0, 0, 1),
|
||||||
port,
|
port,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ pub enum CommandEnum {
|
|||||||
|
|
||||||
pub fn command(cmd: CommandEnum) {
|
pub fn command(cmd: CommandEnum) {
|
||||||
if let Err(e) = command_(cmd) {
|
if let Err(e) = command_(cmd) {
|
||||||
println!("cmd: {}", e);
|
println!("cmd: {:?}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,15 +17,20 @@ impl CommandServer {
|
|||||||
let udp = UdpSocket::bind("127.0.0.1:0").await?;
|
let udp = UdpSocket::bind("127.0.0.1:0").await?;
|
||||||
let path_buf = crate::app_home()?.join("command-port");
|
let path_buf = crate::app_home()?.join("command-port");
|
||||||
let mut file = std::fs::File::create(path_buf)?;
|
let mut file = std::fs::File::create(path_buf)?;
|
||||||
file.write_all(udp.local_addr()?.port().to_string().as_bytes())?;
|
let addr = udp.local_addr()?;
|
||||||
|
file.write_all(addr.port().to_string().as_bytes())?;
|
||||||
file.sync_all()?;
|
file.sync_all()?;
|
||||||
|
log::info!("启动后台cmd:{:?}", addr);
|
||||||
let mut buf = [0u8; 64];
|
let mut buf = [0u8; 64];
|
||||||
loop {
|
loop {
|
||||||
let (len, addr) = udp.recv_from(&mut buf).await?;
|
let (len, addr) = udp.recv_from(&mut buf).await?;
|
||||||
match std::str::from_utf8(&buf[..len]) {
|
match std::str::from_utf8(&buf[..len]) {
|
||||||
Ok(cmd) => {
|
Ok(cmd) => {
|
||||||
|
log::info!("收到cmd={:?}", cmd);
|
||||||
if let Ok(out) = command(cmd, &vnt) {
|
if let Ok(out) = command(cmd, &vnt) {
|
||||||
let _ = udp.send_to(out.as_bytes(), addr).await;
|
if let Err(e) = udp.send_to(out.as_bytes(), addr).await {
|
||||||
|
log::warn!("cmd={},err={:?}", cmd, e);
|
||||||
|
}
|
||||||
if "stopped" == &out {
|
if "stopped" == &out {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,178 @@
|
|||||||
|
use std::io;
|
||||||
|
use std::net::{Ipv4Addr, ToSocketAddrs};
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use vnt::channel::punch::PunchModel;
|
||||||
|
use vnt::cipher::CipherModel;
|
||||||
|
use vnt::core::Config;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct FileConfig {
|
||||||
|
pub tap: bool,
|
||||||
|
pub token: String,
|
||||||
|
pub device_id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub server_address: String,
|
||||||
|
pub stun_server: Vec<String>,
|
||||||
|
pub in_ips: Vec<String>,
|
||||||
|
pub out_ips: Vec<String>,
|
||||||
|
pub password: Option<String>,
|
||||||
|
pub simulate_multicast: bool,
|
||||||
|
pub mtu: Option<u16>,
|
||||||
|
pub tcp: bool,
|
||||||
|
pub ip: Option<String>,
|
||||||
|
pub relay: bool,
|
||||||
|
pub no_proxy: bool,
|
||||||
|
pub server_encrypt: bool,
|
||||||
|
pub parallel: usize,
|
||||||
|
pub cipher_model: String,
|
||||||
|
pub finger: bool,
|
||||||
|
pub punch_model: String,
|
||||||
|
pub port: u16,
|
||||||
|
pub cmd: bool,
|
||||||
|
pub first_latency: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FileConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
tap: false,
|
||||||
|
token: "".to_string(),
|
||||||
|
device_id: get_device_id(),
|
||||||
|
name: os_info::get().to_string(),
|
||||||
|
server_address: "nat1.wherewego.top:29872".to_string(),
|
||||||
|
stun_server: vec![
|
||||||
|
"stun1.l.google.com:19302".to_string(),
|
||||||
|
"stun2.l.google.com:19302".to_string(),
|
||||||
|
"stun.qq.com:3478".to_string(),
|
||||||
|
],
|
||||||
|
in_ips: vec![],
|
||||||
|
out_ips: vec![],
|
||||||
|
password: None,
|
||||||
|
simulate_multicast: false,
|
||||||
|
mtu: None,
|
||||||
|
tcp: false,
|
||||||
|
ip: None,
|
||||||
|
relay: false,
|
||||||
|
no_proxy: false,
|
||||||
|
server_encrypt: false,
|
||||||
|
parallel: 1,
|
||||||
|
cipher_model: "aes_gcm".to_string(),
|
||||||
|
finger: false,
|
||||||
|
punch_model: "".to_string(),
|
||||||
|
port: 0,
|
||||||
|
cmd: false,
|
||||||
|
first_latency: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_config(file_path: &str) -> io::Result<(Config, bool)> {
|
||||||
|
let conf = std::fs::read_to_string(file_path)?;
|
||||||
|
let file_conf = match serde_yaml::from_str::<FileConfig>(&conf) {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("{:?}", e);
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, format!("{}", e)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if file_conf.token.is_empty() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "token is_empty"));
|
||||||
|
}
|
||||||
|
let server_address = match file_conf.server_address.to_socket_addrs() {
|
||||||
|
Ok(mut addr) => {
|
||||||
|
if let Some(addr) = addr.next() {
|
||||||
|
addr
|
||||||
|
} else {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("server_address {:?} error", &file_conf.server_address),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("server_address {:?} error:{}", &file_conf.server_address, e),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let in_ips = match common::args_parse::ips_parse(&file_conf.in_ips) {
|
||||||
|
Ok(in_ips) => in_ips,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("in_ips {:?} error:{}", &file_conf.in_ips, e),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let out_ips = match common::args_parse::out_ips_parse(&file_conf.out_ips) {
|
||||||
|
Ok(out_ips) => out_ips,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("out_ips {:?} error:{}", &file_conf.out_ips, e),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let virtual_ip = match file_conf.ip.clone().map(|v| Ipv4Addr::from_str(&v)) {
|
||||||
|
None => None,
|
||||||
|
Some(r) => Some(r.map_err(|e| {
|
||||||
|
io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("ip {:?} error:{}", &file_conf.ip, e),
|
||||||
|
)
|
||||||
|
})?),
|
||||||
|
};
|
||||||
|
|
||||||
|
let cipher_model = CipherModel::from_str(&file_conf.cipher_model)
|
||||||
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||||
|
|
||||||
|
let punch_model = PunchModel::from_str(&file_conf.punch_model)
|
||||||
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||||
|
let config = Config::new(
|
||||||
|
file_conf.tap,
|
||||||
|
file_conf.token,
|
||||||
|
file_conf.device_id,
|
||||||
|
file_conf.name,
|
||||||
|
server_address,
|
||||||
|
file_conf.server_address,
|
||||||
|
file_conf.stun_server,
|
||||||
|
in_ips,
|
||||||
|
out_ips,
|
||||||
|
file_conf.password,
|
||||||
|
file_conf.simulate_multicast,
|
||||||
|
file_conf.mtu,
|
||||||
|
file_conf.tcp,
|
||||||
|
virtual_ip,
|
||||||
|
file_conf.relay,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
|
file_conf.no_proxy,
|
||||||
|
file_conf.server_encrypt,
|
||||||
|
file_conf.parallel,
|
||||||
|
cipher_model,
|
||||||
|
file_conf.finger,
|
||||||
|
punch_model,
|
||||||
|
file_conf.port,
|
||||||
|
file_conf.first_latency,
|
||||||
|
);
|
||||||
|
Ok((config, file_conf.cmd))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_device_id() -> String {
|
||||||
|
if let Some(id) = common::identifier::get_unique_identifier() {
|
||||||
|
id
|
||||||
|
} else {
|
||||||
|
let path_buf = crate::app_home().unwrap().join("device-id");
|
||||||
|
if let Ok(id) = std::fs::read_to_string(path_buf.as_path()) {
|
||||||
|
id
|
||||||
|
} else {
|
||||||
|
let id = uuid::Uuid::new_v4().to_string();
|
||||||
|
let _ = std::fs::write(path_buf, &id);
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+240
-212
@@ -7,8 +7,6 @@ use console::style;
|
|||||||
use getopts::Options;
|
use getopts::Options;
|
||||||
use tokio::io::{AsyncBufReadExt, BufReader};
|
use tokio::io::{AsyncBufReadExt, BufReader};
|
||||||
use tokio::signal;
|
use tokio::signal;
|
||||||
#[cfg(unix)]
|
|
||||||
use tokio::signal::unix::{signal, SignalKind};
|
|
||||||
|
|
||||||
use common::args_parse::{ips_parse, out_ips_parse};
|
use common::args_parse::{ips_parse, out_ips_parse};
|
||||||
use vnt::channel::punch::PunchModel;
|
use vnt::channel::punch::PunchModel;
|
||||||
@@ -18,6 +16,7 @@ use vnt::handle::handshake_handler::HandshakeEnum;
|
|||||||
use vnt::handle::registration_handler::ReqEnum;
|
use vnt::handle::registration_handler::ReqEnum;
|
||||||
|
|
||||||
mod command;
|
mod command;
|
||||||
|
mod config;
|
||||||
mod console_out;
|
mod console_out;
|
||||||
mod root_check;
|
mod root_check;
|
||||||
|
|
||||||
@@ -56,12 +55,12 @@ fn main() {
|
|||||||
opts.optopt("", "thread", "线程数(必须为正整数)", "<thread>");
|
opts.optopt("", "thread", "线程数(必须为正整数)", "<thread>");
|
||||||
opts.optopt("", "model", "加密模式", "<model>");
|
opts.optopt("", "model", "加密模式", "<model>");
|
||||||
opts.optflag("", "finger", "指纹校验");
|
opts.optflag("", "finger", "指纹校验");
|
||||||
opts.optopt(
|
opts.optopt("", "punch", "取值ipv4/ipv6", "<punch>");
|
||||||
"",
|
opts.optopt("", "port", "监听的端口", "<port>");
|
||||||
"punch",
|
opts.optflag("", "cmd", "开启窗口输入");
|
||||||
"取值ipv4/ipv6,表示仅使用ipv4或ipv6打洞",
|
opts.optflag("", "no-proxy", "关闭内置代理");
|
||||||
"<punch>",
|
opts.optflag("", "first-latency", "优先延迟");
|
||||||
);
|
opts.optopt("f", "", "配置文件", "<conf>");
|
||||||
//"后台运行时,查看其他设备列表"
|
//"后台运行时,查看其他设备列表"
|
||||||
opts.optflag("", "list", "后台运行时,查看其他设备列表");
|
opts.optflag("", "list", "后台运行时,查看其他设备列表");
|
||||||
opts.optflag("", "all", "后台运行时,查看其他设备完整信息");
|
opts.optflag("", "all", "后台运行时,查看其他设备完整信息");
|
||||||
@@ -103,185 +102,221 @@ fn main() {
|
|||||||
command::command(command::CommandEnum::All);
|
command::command(command::CommandEnum::All);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if !matches.opt_present("k") {
|
let conf = matches.opt_str("f");
|
||||||
print_usage(&program, opts);
|
let (config, cmd) = if conf.is_some() {
|
||||||
println!("parameter -k not found .");
|
match config::read_config(&conf.unwrap()) {
|
||||||
return;
|
Ok(c) => c,
|
||||||
}
|
Err(e) => {
|
||||||
let tap = matches.opt_present("a");
|
println!("conf err {}", e);
|
||||||
let token: String = matches.opt_get("k").unwrap().unwrap();
|
|
||||||
let device_id = matches.opt_get_default("d", String::new()).unwrap();
|
|
||||||
let device_id = if device_id.is_empty() {
|
|
||||||
if let Some(id) = common::identifier::get_unique_identifier() {
|
|
||||||
id
|
|
||||||
} else {
|
|
||||||
let path_buf = app_home().unwrap().join("device-id");
|
|
||||||
if let Ok(id) = std::fs::read_to_string(path_buf.as_path()) {
|
|
||||||
id
|
|
||||||
} else {
|
|
||||||
let id = uuid::Uuid::new_v4().to_string();
|
|
||||||
let _ = std::fs::write(path_buf, &id);
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
device_id
|
|
||||||
};
|
|
||||||
if device_id.is_empty() {
|
|
||||||
print_usage(&program, opts);
|
|
||||||
println!("parameter -d not found .");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let name = matches
|
|
||||||
.opt_get_default("n", os_info::get().to_string())
|
|
||||||
.unwrap();
|
|
||||||
let server_address_str = matches
|
|
||||||
.opt_get_default("s", "nat1.wherewego.top:29872".to_string())
|
|
||||||
.unwrap();
|
|
||||||
let server_address = match server_address_str.to_socket_addrs() {
|
|
||||||
Ok(mut addr) => {
|
|
||||||
if let Some(addr) = addr.next() {
|
|
||||||
addr
|
|
||||||
} else {
|
|
||||||
println!("parameter -s error .");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
} else {
|
||||||
println!("parameter -s error {}.", e);
|
if !matches.opt_present("k") {
|
||||||
|
print_usage(&program, opts);
|
||||||
|
println!("parameter -k not found .");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
let tap = matches.opt_present("a");
|
||||||
let mut stun_server = matches.opt_strs("e");
|
let token: String = matches.opt_get("k").unwrap().unwrap();
|
||||||
if stun_server.is_empty() {
|
let device_id = matches.opt_get_default("d", String::new()).unwrap();
|
||||||
stun_server.push("stun1.l.google.com:19302".to_string());
|
let device_id = if device_id.is_empty() {
|
||||||
stun_server.push("stun2.l.google.com:19302".to_string());
|
config::get_device_id()
|
||||||
stun_server.push("stun.qq.com:3478".to_string());
|
} else {
|
||||||
}
|
device_id
|
||||||
|
};
|
||||||
|
if device_id.is_empty() {
|
||||||
|
print_usage(&program, opts);
|
||||||
|
println!("parameter -d not found .");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let name = matches
|
||||||
|
.opt_get_default("n", os_info::get().to_string())
|
||||||
|
.unwrap();
|
||||||
|
let server_address_str = matches
|
||||||
|
.opt_get_default("s", "nat1.wherewego.top:29872".to_string())
|
||||||
|
.unwrap();
|
||||||
|
let server_address = match server_address_str.to_socket_addrs() {
|
||||||
|
Ok(mut addr) => {
|
||||||
|
if let Some(addr) = addr.next() {
|
||||||
|
addr
|
||||||
|
} else {
|
||||||
|
println!("parameter '-s {}' error .", server_address_str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("parameter '-s {}' error {}.", server_address_str, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut stun_server = matches.opt_strs("e");
|
||||||
|
if stun_server.is_empty() {
|
||||||
|
stun_server.push("stun1.l.google.com:19302".to_string());
|
||||||
|
stun_server.push("stun2.l.google.com:19302".to_string());
|
||||||
|
stun_server.push("stun.qq.com:3478".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
let in_ip = matches.opt_strs("i");
|
let in_ip = matches.opt_strs("i");
|
||||||
let in_ip = match ips_parse(&in_ip) {
|
let in_ip = match ips_parse(&in_ip) {
|
||||||
Ok(in_ip) => in_ip,
|
Ok(in_ip) => in_ip,
|
||||||
Err(e) => {
|
|
||||||
print_usage(&program, opts);
|
|
||||||
println!();
|
|
||||||
println!("-i {}", e);
|
|
||||||
println!("example: -i 192.168.0.0/24,10.26.0.3");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let out_ip = matches.opt_strs("o");
|
|
||||||
let out_ip = match out_ips_parse(&out_ip) {
|
|
||||||
Ok(out_ip) => out_ip,
|
|
||||||
Err(e) => {
|
|
||||||
print_usage(&program, opts);
|
|
||||||
println!();
|
|
||||||
println!("-o {}", e);
|
|
||||||
println!("example: -o 0.0.0.0/0");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let password: Option<String> = matches.opt_get("w").unwrap();
|
|
||||||
let server_encrypt = matches.opt_present("W");
|
|
||||||
let simulate_multicast = matches.opt_present("m");
|
|
||||||
let unused_cmd = matches.opt_present("c");
|
|
||||||
let mtu: Option<String> = matches.opt_get("u").unwrap();
|
|
||||||
let mtu = if let Some(mtu) = mtu {
|
|
||||||
match u16::from_str(&mtu) {
|
|
||||||
Ok(mtu) => Some(mtu),
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
print_usage(&program, opts);
|
print_usage(&program, opts);
|
||||||
println!();
|
println!();
|
||||||
println!("-u {}", e);
|
println!("-i: {:?} {}", in_ip, e);
|
||||||
|
println!("example: -i 192.168.0.0/24,10.26.0.3");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let out_ip = matches.opt_strs("o");
|
||||||
|
let out_ip = match out_ips_parse(&out_ip) {
|
||||||
|
Ok(out_ip) => out_ip,
|
||||||
|
Err(e) => {
|
||||||
|
print_usage(&program, opts);
|
||||||
|
println!();
|
||||||
|
println!("-o: {:?} {}", out_ip, e);
|
||||||
|
println!("example: -o 0.0.0.0/0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let password: Option<String> = matches.opt_get("w").unwrap();
|
||||||
|
let server_encrypt = matches.opt_present("W");
|
||||||
|
#[cfg(not(feature = "server_encrypt"))]
|
||||||
|
{
|
||||||
|
if server_encrypt {
|
||||||
|
println!("Server encryption not supported");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
let simulate_multicast = matches.opt_present("m");
|
||||||
None
|
let mtu: Option<String> = matches.opt_get("u").unwrap();
|
||||||
};
|
let mtu = if let Some(mtu) = mtu {
|
||||||
let virtual_ip: Option<String> = matches.opt_get("ip").unwrap();
|
match u16::from_str(&mtu) {
|
||||||
let virtual_ip = virtual_ip.map(|v| Ipv4Addr::from_str(&v).expect("--ip error"));
|
Ok(mtu) => Some(mtu),
|
||||||
if let Some(virtual_ip) = virtual_ip {
|
Err(e) => {
|
||||||
if virtual_ip.is_unspecified() || virtual_ip.is_broadcast() || virtual_ip.is_multicast() {
|
print_usage(&program, opts);
|
||||||
println!("--ip invalid");
|
println!();
|
||||||
|
println!("'-u {}' {}", mtu, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let virtual_ip: Option<String> = matches.opt_get("ip").unwrap();
|
||||||
|
let virtual_ip =
|
||||||
|
virtual_ip.map(|v| Ipv4Addr::from_str(&v).expect(&format!("'--ip {}' error", v)));
|
||||||
|
if let Some(virtual_ip) = virtual_ip {
|
||||||
|
if virtual_ip.is_unspecified() || virtual_ip.is_broadcast() || virtual_ip.is_multicast()
|
||||||
|
{
|
||||||
|
println!("'--ip {}' invalid", virtual_ip);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let tcp_channel = matches.opt_present("tcp");
|
||||||
|
let relay = matches.opt_present("relay");
|
||||||
|
let parallel = matches.opt_get::<usize>("par").unwrap().unwrap_or(1);
|
||||||
|
if parallel == 0 {
|
||||||
|
println!("'--par {}' invalid", parallel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let tcp_channel = matches.opt_present("tcp");
|
let cipher_model = match matches.opt_get::<CipherModel>("model") {
|
||||||
let relay = matches.opt_present("relay");
|
Ok(model) => {
|
||||||
let parallel = matches.opt_get::<usize>("par").unwrap().unwrap_or(1);
|
#[cfg(not(any(
|
||||||
if parallel == 0 {
|
feature = "aes_gcm",
|
||||||
println!("--par invalid");
|
feature = "server_encrypt",
|
||||||
return;
|
feature = "aes_cbc",
|
||||||
}
|
feature = "aes_ecb",
|
||||||
let thread_num = matches
|
feature = "sm4_cbc"
|
||||||
.opt_get::<usize>("thread")
|
)))]
|
||||||
.unwrap()
|
{
|
||||||
.unwrap_or(std::thread::available_parallelism().unwrap().get() * 2);
|
if password.is_some() && model.is_none() {
|
||||||
let cipher_model = matches
|
println!("Encryption not supported");
|
||||||
.opt_get::<CipherModel>("model")
|
return;
|
||||||
.unwrap()
|
}
|
||||||
.unwrap_or(CipherModel::AesGcm);
|
}
|
||||||
if thread_num == 0 {
|
#[cfg(not(any(feature = "aes_gcm", feature = "server_encrypt")))]
|
||||||
println!("--thread invalid");
|
{
|
||||||
return;
|
if password.is_some() && model.is_none() {
|
||||||
}
|
println!("'--model ' undefined");
|
||||||
let finger = matches.opt_present("finger");
|
return;
|
||||||
let punch_model = matches
|
}
|
||||||
.opt_get::<PunchModel>("punch")
|
model.unwrap_or(CipherModel::None)
|
||||||
.unwrap()
|
}
|
||||||
.unwrap_or(PunchModel::All);
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
|
model.unwrap_or(CipherModel::AesGcm)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("'--model ' invalid,{}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let finger = matches.opt_present("finger");
|
||||||
|
let punch_model = matches
|
||||||
|
.opt_get::<PunchModel>("punch")
|
||||||
|
.unwrap()
|
||||||
|
.unwrap_or(PunchModel::All);
|
||||||
|
let port = matches.opt_get::<u16>("port").unwrap_or(None).unwrap_or(0);
|
||||||
|
let cmd = matches.opt_present("cmd");
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
|
let no_proxy = matches.opt_present("no-proxy");
|
||||||
|
let first_latency = matches.opt_present("first-latency");
|
||||||
|
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,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
|
no_proxy,
|
||||||
|
server_encrypt,
|
||||||
|
parallel,
|
||||||
|
cipher_model,
|
||||||
|
finger,
|
||||||
|
punch_model,
|
||||||
|
port,
|
||||||
|
first_latency,
|
||||||
|
);
|
||||||
|
(config, cmd)
|
||||||
|
};
|
||||||
println!("version {}", vnt::VNT_VERSION);
|
println!("version {}", vnt::VNT_VERSION);
|
||||||
let config = Config::new(
|
|
||||||
tap,
|
main0(config, cmd);
|
||||||
token,
|
|
||||||
device_id,
|
|
||||||
name,
|
|
||||||
server_address,
|
|
||||||
server_address_str,
|
|
||||||
stun_server,
|
|
||||||
in_ip,
|
|
||||||
out_ip,
|
|
||||||
password,
|
|
||||||
simulate_multicast,
|
|
||||||
mtu,
|
|
||||||
tcp_channel,
|
|
||||||
virtual_ip,
|
|
||||||
relay,
|
|
||||||
server_encrypt,
|
|
||||||
parallel,
|
|
||||||
cipher_model,
|
|
||||||
finger,
|
|
||||||
punch_model,
|
|
||||||
);
|
|
||||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
|
||||||
.enable_all()
|
|
||||||
.worker_threads(thread_num)
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
runtime.block_on(main0(config, !unused_cmd));
|
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
async fn main0(config: Config, show_cmd: bool) {
|
async fn main0(config: Config, show_cmd: bool) {
|
||||||
let server_encrypt = config.server_encrypt;
|
let server_encrypt = config.server_encrypt;
|
||||||
let mut vnt_util = VntUtil::new(config).await.unwrap();
|
let mut vnt_util = VntUtil::new(config).unwrap();
|
||||||
let mut conn_count = 0;
|
let mut conn_count = 0;
|
||||||
let response = loop {
|
let response = loop {
|
||||||
if conn_count > 0 {
|
if conn_count > 0 {
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
|
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
|
||||||
}
|
}
|
||||||
conn_count += 1;
|
conn_count += 1;
|
||||||
if let Err(e) = vnt_util.connect().await {
|
if let Err(e) = vnt_util.connect() {
|
||||||
println!("connect server failed {}", e);
|
println!("connect server failed {}", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match vnt_util.handshake().await {
|
match vnt_util.handshake() {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
if server_encrypt {
|
if server_encrypt {
|
||||||
let finger = response.unwrap().finger().unwrap();
|
let finger = response.unwrap().finger().unwrap();
|
||||||
println!("{}{}", green("server fingerprint:".to_string()), finger);
|
println!("{}{}", green("server fingerprint:".to_string()), finger);
|
||||||
match vnt_util.secret_handshake().await {
|
match vnt_util.secret_handshake() {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
match e {
|
match e {
|
||||||
@@ -301,7 +336,7 @@ async fn main0(config: Config, show_cmd: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match vnt_util.register().await {
|
match vnt_util.register() {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
break response;
|
break response;
|
||||||
}
|
}
|
||||||
@@ -370,11 +405,10 @@ async fn main0(config: Config, show_cmd: bool) {
|
|||||||
let vnt_c = vnt.clone();
|
let vnt_c = vnt.clone();
|
||||||
tokio::spawn(async {
|
tokio::spawn(async {
|
||||||
if let Err(e) = command::server::CommandServer::new().start(vnt_c).await {
|
if let Err(e) = command::server::CommandServer::new().start(vnt_c).await {
|
||||||
|
log::warn!("cmd:{:?}", e);
|
||||||
println!("command error :{}", e);
|
println!("command error :{}", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
#[cfg(unix)]
|
|
||||||
let mut sigterm = signal(SignalKind::terminate()).expect("Error setting SIGTERM handler");
|
|
||||||
if show_cmd {
|
if show_cmd {
|
||||||
let stdin = tokio::io::stdin();
|
let stdin = tokio::io::stdin();
|
||||||
let mut cmd = String::new();
|
let mut cmd = String::new();
|
||||||
@@ -382,7 +416,6 @@ async fn main0(config: Config, show_cmd: bool) {
|
|||||||
loop {
|
loop {
|
||||||
cmd.clear();
|
cmd.clear();
|
||||||
println!("input:list,info,route,all,stop");
|
println!("input:list,info,route,all,stop");
|
||||||
#[cfg(unix)]
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = vnt.wait_stop()=>{
|
_ = vnt.wait_stop()=>{
|
||||||
return;
|
return;
|
||||||
@@ -390,36 +423,7 @@ async fn main0(config: Config, show_cmd: bool) {
|
|||||||
_ = signal::ctrl_c()=>{
|
_ = signal::ctrl_c()=>{
|
||||||
let _ = vnt.stop();
|
let _ = vnt.stop();
|
||||||
vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await;
|
vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await;
|
||||||
return;
|
std::process::exit(0);
|
||||||
}
|
|
||||||
_ = sigterm.recv()=>{
|
|
||||||
let _ = vnt.stop();
|
|
||||||
vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rs = reader.read_line(&mut cmd)=>{
|
|
||||||
match rs {
|
|
||||||
Ok(len) => {
|
|
||||||
if !command(&cmd[..len],&vnt){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
println!("input err:{}",e);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(windows)]
|
|
||||||
tokio::select! {
|
|
||||||
_ = vnt.wait_stop()=>{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_ = signal::ctrl_c()=>{
|
|
||||||
let _ = vnt.stop();
|
|
||||||
vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
rs = reader.read_line(&mut cmd)=>{
|
rs = reader.read_line(&mut cmd)=>{
|
||||||
match rs {
|
match rs {
|
||||||
@@ -437,23 +441,6 @@ async fn main0(config: Config, show_cmd: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(unix)]
|
|
||||||
tokio::select! {
|
|
||||||
_ = vnt.wait_stop()=>{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_ = signal::ctrl_c()=>{
|
|
||||||
let _ = vnt.stop();
|
|
||||||
vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_ = sigterm.recv()=>{
|
|
||||||
let _ = vnt.stop();
|
|
||||||
vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(windows)]
|
|
||||||
vnt.wait_stop().await;
|
vnt.wait_stop().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,29 +481,70 @@ fn print_usage(program: &str, _opts: Options) {
|
|||||||
println!("Options:");
|
println!("Options:");
|
||||||
println!(
|
println!(
|
||||||
" -k <token> {}",
|
" -k <token> {}",
|
||||||
green("必选,使用相同的token,就能组建一个局域网络".to_string())
|
green("使用相同的token,就能组建一个局域网络".to_string())
|
||||||
);
|
);
|
||||||
println!(" -n <name> 给设备一个名字,便于区分不同设备,默认使用系统版本");
|
println!(" -n <name> 给设备一个名字,便于区分不同设备,默认使用系统版本");
|
||||||
println!(" -d <id> 设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip");
|
println!(" -d <id> 设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip");
|
||||||
println!(" -c 关闭交互式命令,使用此参数禁用控制台输入");
|
|
||||||
println!(" -s <server> 注册和中继服务器地址");
|
println!(" -s <server> 注册和中继服务器地址");
|
||||||
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可多次指定,如-e addr1 -e addr2");
|
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可多次指定,如-e addr1 -e addr2");
|
||||||
println!(" -a 使用tap模式,默认使用tun模式");
|
println!(" -a 使用tap模式,默认使用tun模式");
|
||||||
println!(" -i <in-ip> 配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据");
|
println!(" -i <in-ip> 配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据");
|
||||||
println!(" 并转发到10.26.0.3,可指定多个网段");
|
println!(" 并转发到10.26.0.3,可指定多个网段");
|
||||||
println!(" -o <out-ip> 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段");
|
println!(" -o <out-ip> 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段");
|
||||||
println!(" -w <password> 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信");
|
#[cfg(not(feature = "ip_proxy"))]
|
||||||
|
println!(" 注意需要在系统配置ip转发才可正常使用");
|
||||||
|
#[cfg(not(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
)))]
|
||||||
|
let enums = String::new();
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
))]
|
||||||
|
let mut enums = String::new();
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
|
enums.push_str("/aes_gcm");
|
||||||
|
#[cfg(feature = "aes_cbc")]
|
||||||
|
enums.push_str("/aes_cbc");
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
|
enums.push_str("/aes_ecb");
|
||||||
|
#[cfg(feature = "sm4_cbc")]
|
||||||
|
enums.push_str("/sm4_cbc");
|
||||||
|
if !enums.is_empty() {
|
||||||
|
println!(" -w <password> 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信");
|
||||||
|
}
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确");
|
println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确");
|
||||||
println!(" -m 模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送");
|
println!(" -m 模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送");
|
||||||
println!(" -u <mtu> 自定义mtu(不加密默认为1430,加密默认为1410)");
|
println!(" -u <mtu> 自定义mtu(不加密默认为1450,加密默认为1410)");
|
||||||
|
println!(" -f <conf_file> 读取配置文件中的配置");
|
||||||
|
|
||||||
println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp");
|
println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp");
|
||||||
println!(" --ip <ip> 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配");
|
println!(" --ip <ip> 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配");
|
||||||
println!(" --relay 仅使用服务器转发,不使用p2p,默认情况允许使用p2p");
|
println!(" --relay 仅使用服务器转发,不使用p2p,默认情况允许使用p2p");
|
||||||
println!(" --par <parallel> 任务并行度(必须为正整数),默认值为1");
|
println!(" --par <parallel> 任务并行度(必须为正整数),默认值为1");
|
||||||
println!(" --thread <thread> 线程数(必须为正整数),默认为核心数乘2");
|
if !enums.is_empty() {
|
||||||
println!(" --model <model> 加密模式(默认aes_gcm),可选值aes_gcm/aes_cbc/aes_ecb,通常性能aes_ecb>aes_cbc>aes_gcm,安全性则相反");
|
println!(
|
||||||
println!(" --finger 增加数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启");
|
" --model <model> 加密模式(默认aes_gcm),可选值{}",
|
||||||
|
&enums[1..]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if !enums.is_empty() {
|
||||||
|
println!(" --finger 增加数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启");
|
||||||
|
}
|
||||||
println!(" --punch <punch> 取值ipv4/ipv6,ipv4表示仅使用ipv4打洞");
|
println!(" --punch <punch> 取值ipv4/ipv6,ipv4表示仅使用ipv4打洞");
|
||||||
|
println!(" --port <port> 取值0~65535,指定本地监听的端口,默认取随机端口");
|
||||||
|
println!(" --cmd 开启交互式命令,使用此参数开启控制台输入");
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
|
println!(" --no-proxy 关闭内置代理,如需点对网则需要配置网卡NAT转发");
|
||||||
|
println!(" --first-latency 优先低延迟的通道,默认情况优先使用p2p通道");
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
println!(
|
println!(
|
||||||
|
|||||||
+2
-1
@@ -1,11 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "vnt-jni"
|
name = "vnt-jni"
|
||||||
version = "1.2.2"
|
version = "1.2.7"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
common = { path = "../common" }
|
||||||
vnt = {path="../vnt"}
|
vnt = {path="../vnt"}
|
||||||
|
|
||||||
jni = { version = "0.21.1", default-features = false }
|
jni = { version = "0.21.1", default-features = false }
|
||||||
|
|||||||
+37
-2
@@ -66,6 +66,38 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
|
|||||||
let cipher_model = to_string_not_null(env, &config, "cipherModel")?;
|
let cipher_model = to_string_not_null(env, &config, "cipherModel")?;
|
||||||
let tcp = env.get_field(&config, "tcp", "Z")?.z()?;
|
let tcp = env.get_field(&config, "tcp", "Z")?.z()?;
|
||||||
let finger = env.get_field(&config, "finger", "Z")?.z()?;
|
let finger = env.get_field(&config, "finger", "Z")?.z()?;
|
||||||
|
let first_latency = env.get_field(&config, "firstLatency", "Z")?.z()?;
|
||||||
|
let in_ips = to_string(env, &config, "inIps")?;
|
||||||
|
let out_ips = to_string(env, &config, "outIps")?;
|
||||||
|
let port = env.get_field(&config, "port", "I")?.i()? as u16;
|
||||||
|
let in_ips = if let Some(in_ips) = in_ips {
|
||||||
|
let in_ips: Vec<&str> = in_ips.split("\n").collect();
|
||||||
|
let in_ips = in_ips.iter().map(|v| v.to_string()).collect();
|
||||||
|
match common::args_parse::ips_parse(&in_ips) {
|
||||||
|
Ok(in_ips) => in_ips,
|
||||||
|
Err(e) => {
|
||||||
|
env.throw_new("java/lang/RuntimeException", format!("in_ips {}", e))
|
||||||
|
.expect("throw");
|
||||||
|
return Err(Error::JavaException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
let out_ips = if let Some(out_ips) = out_ips {
|
||||||
|
let out_ips: Vec<&str> = out_ips.split("\n").collect();
|
||||||
|
let out_ips = out_ips.iter().map(|v| v.to_string()).collect();
|
||||||
|
match common::args_parse::out_ips_parse(&out_ips) {
|
||||||
|
Ok(out_ips) => out_ips,
|
||||||
|
Err(e) => {
|
||||||
|
env.throw_new("java/lang/RuntimeException", format!("out_ips {}", e))
|
||||||
|
.expect("throw");
|
||||||
|
return Err(Error::JavaException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
let server_address = match server_address_str.to_socket_addrs() {
|
let server_address = match server_address_str.to_socket_addrs() {
|
||||||
Ok(mut rs) => {
|
Ok(mut rs) => {
|
||||||
@@ -106,8 +138,8 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
|
|||||||
server_address,
|
server_address,
|
||||||
server_address_str,
|
server_address_str,
|
||||||
stun_server,
|
stun_server,
|
||||||
vec![],
|
in_ips,
|
||||||
vec![],
|
out_ips,
|
||||||
password,
|
password,
|
||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
@@ -115,10 +147,13 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
|
|||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
1,
|
1,
|
||||||
cipher_model,
|
cipher_model,
|
||||||
finger,
|
finger,
|
||||||
PunchModel::All,
|
PunchModel::All,
|
||||||
|
port,
|
||||||
|
first_latency,
|
||||||
);
|
);
|
||||||
match VntUtilSync::new(config) {
|
match VntUtilSync::new(config) {
|
||||||
Ok(vnt_util) => Ok(vnt_util),
|
Ok(vnt_util) => Ok(vnt_util),
|
||||||
|
|||||||
+28
-20
@@ -1,49 +1,57 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "vnt"
|
name = "vnt"
|
||||||
version = "1.2.2"
|
version = "1.2.7"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
packet = { path = "./packet" }
|
packet = { path = "./packet" }
|
||||||
bytes = "1.3.0"
|
bytes = "1.5.0"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
libc = "0.2.137"
|
libc = "0.2.137"
|
||||||
crossbeam-utils = "0.8"
|
crossbeam-utils = "0.8"
|
||||||
dashmap = "5.5.1"
|
crossbeam-epoch = "0.9.15"
|
||||||
|
dashmap = {version = "5.5.3",optional = true}
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
byte-pool = "0.2.4"
|
|
||||||
lazy_static = "1.4.0"
|
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
sha2 = { version = "0.10.6", features = ["oid"] }
|
sha2 = { version = "0.10.6", features = ["oid"] }
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
protobuf = "3.2.0"
|
protobuf = "3.2.0"
|
||||||
socket2 ={ version = "0.5.2", features = ["all"] }
|
socket2 = { version = "0.5.2", features = ["all"] }
|
||||||
tokio = { version = "1.28.1", features = ["full"] }
|
tokio = { version = "1.32.0", features = ["full"] }
|
||||||
aes-gcm = {version="0.10.2", optional = true}
|
aes-gcm = { version = "0.10.2",optional = true }
|
||||||
ring = {version="0.16.20", optional = true}
|
ring = { version = "0.17.0", optional = true }
|
||||||
cbc = "0.1.2"
|
cbc = {version = "0.1.2",optional = true}
|
||||||
ecb = "0.1.2"
|
ecb = {version = "0.1.2",optional = true}
|
||||||
aes = "0.8.3"
|
aes = "0.8.3"
|
||||||
stun-format = {version="1.0.1",features=["fmt","rfc3489"]}
|
stun-format = { version = "1.0.1", features = ["fmt", "rfc3489"] }
|
||||||
rsa = {version="0.7.2", features = [] }
|
rsa = { version = "0.9.2", features = [] ,optional = true}
|
||||||
spki = {version="0.6.0",features=["fingerprint","alloc"]}
|
spki = { version = "0.7.2", features = ["fingerprint", "alloc","base64"] ,optional = true}
|
||||||
|
openssl-sys = { git = "https://github.com/lbl8603/rust-openssl" ,optional = true}
|
||||||
|
libsm = {git="https://github.com/lbl8603/libsm" ,optional = true}
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
|
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
|
||||||
tun = { path = "./rust-tun" }
|
tun = { path = "./rust-tun" }
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
|
win-tun-tap = { path = "./win-tun-tap" }
|
||||||
|
libloading = "0.8.0"
|
||||||
|
|
||||||
win-tun-tap = {path = "./win-tun-tap"}
|
|
||||||
libloading = "0.7.4"
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
protobuf-codegen = "3.2.0"
|
protobuf-codegen = "3.2.0"
|
||||||
protoc-bin-vendored = "3.0.0"
|
protoc-bin-vendored = "3.0.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default=["aes-gcm"]
|
default = ["server_encrypt","aes_gcm","aes_cbc","aes_ecb","sm4_cbc","ip_proxy"]
|
||||||
ring-cipher=["ring"]
|
openssl = ["openssl-sys"]
|
||||||
|
# 从源码编译
|
||||||
|
openssl-vendored = ["openssl-sys/vendored"]
|
||||||
|
ring-cipher = ["ring"]
|
||||||
|
aes_cbc=["cbc"]
|
||||||
|
aes_ecb=["ecb"]
|
||||||
|
sm4_cbc=["libsm"]
|
||||||
|
aes_gcm=["aes-gcm"]
|
||||||
|
server_encrypt =["aes-gcm","rsa","spki"]
|
||||||
|
ip_proxy=["dashmap"]
|
||||||
|
|||||||
@@ -76,7 +76,14 @@ impl<B: AsRef<[u8]>> TcpPacket<B> {
|
|||||||
Ok(packet)
|
Ok(packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<B: AsRef<[u8]> + AsMut<[u8]>> TcpPacket<B> {
|
||||||
|
pub fn set_source_ip(&mut self, value: Ipv4Addr) {
|
||||||
|
self.source_ip = value;
|
||||||
|
}
|
||||||
|
pub fn set_destination_ip(&mut self, value: Ipv4Addr) {
|
||||||
|
self.destination_ip = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> TcpPacket<B> {
|
impl<B: AsRef<[u8]> + AsMut<[u8]>> TcpPacket<B> {
|
||||||
fn set_checksum(&mut self, value: u16) {
|
fn set_checksum(&mut self, value: u16) {
|
||||||
self.buffer.as_mut()[16..18].copy_from_slice(&value.to_be_bytes())
|
self.buffer.as_mut()[16..18].copy_from_slice(&value.to_be_bytes())
|
||||||
|
|||||||
+393
-268
@@ -1,38 +1,36 @@
|
|||||||
use std::io;
|
use std::collections::HashMap;
|
||||||
use std::net::{Ipv4Addr, SocketAddr};
|
use std::io::{Read, Write};
|
||||||
|
use std::net::TcpStream;
|
||||||
|
use std::net::UdpSocket as StdUdpSocket;
|
||||||
|
use std::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
use std::{io, thread};
|
||||||
|
|
||||||
use byte_pool::{Block, BytePool};
|
|
||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
use dashmap::DashMap;
|
use parking_lot::RwLock;
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::net::UdpSocket;
|
||||||
use tokio::net::tcp::OwnedReadHalf;
|
|
||||||
use tokio::net::{TcpStream, UdpSocket};
|
|
||||||
use tokio::sync::watch::{channel, Receiver, Sender};
|
use tokio::sync::watch::{channel, Receiver, Sender};
|
||||||
|
|
||||||
use crate::channel::punch::NatType;
|
use crate::channel::punch::NatType;
|
||||||
use crate::channel::{Route, RouteKey, Status};
|
use crate::channel::{Route, RouteKey, Status, TCP_ID, UDP_ID, UDP_V6_ID};
|
||||||
use crate::core::status::VntWorker;
|
use crate::core::status::VntWorker;
|
||||||
use crate::handle::recv_handler::ChannelDataHandler;
|
use crate::handle::recv_handler::ChannelDataHandler;
|
||||||
use crate::handle::CurrentDeviceInfo;
|
use crate::handle::CurrentDeviceInfo;
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
|
||||||
static ref POOL:BytePool = BytePool::new();
|
|
||||||
}
|
|
||||||
pub struct ContextInner {
|
pub struct ContextInner {
|
||||||
//udp用于打洞、服务端通信(可选)
|
//udp用于打洞、服务端通信(可选)
|
||||||
pub(crate) main_channel: Arc<UdpSocket>,
|
pub(crate) main_channel: Arc<StdUdpSocket>,
|
||||||
pub(crate) main_channel_ipv6: Option<Arc<UdpSocket>>,
|
pub(crate) main_channel_ipv6: Option<Arc<StdUdpSocket>>,
|
||||||
//在udp的基础上,可以选择使用tcp和服务端通信
|
//在udp的基础上,可以选择使用tcp和服务端通信
|
||||||
pub(crate) main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>,
|
pub(crate) main_tcp_channel: Option<std::sync::mpsc::SyncSender<Vec<u8>>>,
|
||||||
pub(crate) route_table: DashMap<Ipv4Addr, Vec<Route>>,
|
pub(crate) route_table: RwLock<HashMap<Ipv4Addr, Vec<(Route, AtomicCell<Instant>)>>>,
|
||||||
pub(crate) route_table_time: DashMap<(RouteKey, Ipv4Addr), Instant>,
|
|
||||||
pub(crate) status_receiver: Receiver<Status>,
|
pub(crate) status_receiver: Receiver<Status>,
|
||||||
pub(crate) status_sender: Sender<Status>,
|
pub(crate) status_sender: Sender<Status>,
|
||||||
pub(crate) udp_map: DashMap<usize, Arc<UdpSocket>>,
|
pub(crate) udp_map: RwLock<HashMap<usize, Arc<UdpSocket>>>,
|
||||||
pub(crate) channel_num: usize,
|
pub(crate) channel_num: usize,
|
||||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
|
first_latency: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -42,11 +40,12 @@ pub struct Context {
|
|||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
main_channel: Arc<UdpSocket>,
|
main_channel: Arc<StdUdpSocket>,
|
||||||
main_channel_ipv6: Option<Arc<UdpSocket>>,
|
main_channel_ipv6: Option<Arc<StdUdpSocket>>,
|
||||||
main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>,
|
main_tcp_channel: Option<std::sync::mpsc::SyncSender<Vec<u8>>>,
|
||||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
_channel_num: usize,
|
_channel_num: usize,
|
||||||
|
first_latency: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
//当前版本只支持一个通道
|
//当前版本只支持一个通道
|
||||||
let channel_num = 1;
|
let channel_num = 1;
|
||||||
@@ -55,13 +54,13 @@ impl Context {
|
|||||||
main_channel,
|
main_channel,
|
||||||
main_channel_ipv6,
|
main_channel_ipv6,
|
||||||
main_tcp_channel,
|
main_tcp_channel,
|
||||||
route_table: DashMap::with_capacity(16),
|
route_table: RwLock::new(HashMap::with_capacity(16)),
|
||||||
route_table_time: DashMap::with_capacity(16),
|
|
||||||
status_receiver,
|
status_receiver,
|
||||||
status_sender,
|
status_sender,
|
||||||
udp_map: DashMap::new(),
|
udp_map: RwLock::new(HashMap::with_capacity(16)),
|
||||||
channel_num,
|
channel_num,
|
||||||
current_device,
|
current_device,
|
||||||
|
first_latency,
|
||||||
});
|
});
|
||||||
Self { inner }
|
Self { inner }
|
||||||
}
|
}
|
||||||
@@ -74,8 +73,24 @@ impl Context {
|
|||||||
pub fn is_cone(&self) -> bool {
|
pub fn is_cone(&self) -> bool {
|
||||||
*self.inner.status_receiver.borrow() == Status::Cone
|
*self.inner.status_receiver.borrow() == Status::Cone
|
||||||
}
|
}
|
||||||
pub fn close(&self) {
|
pub fn close(&self) -> io::Result<()> {
|
||||||
let _ = self.inner.status_sender.send(Status::Close);
|
let _ = self.inner.status_sender.send(Status::Close);
|
||||||
|
if let Ok(port) = self.main_local_ipv4_port() {
|
||||||
|
let _ = StdUdpSocket::bind("127.0.0.1:0")?.send_to(
|
||||||
|
b"stop",
|
||||||
|
SocketAddr::V4(std::net::SocketAddrV4::new(Ipv4Addr::LOCALHOST, port)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Ok(port) = self.main_local_ipv6_port() {
|
||||||
|
let _ = StdUdpSocket::bind("[::]:0")?.send_to(
|
||||||
|
b"stop",
|
||||||
|
SocketAddr::V6(std::net::SocketAddrV6::new(Ipv6Addr::LOCALHOST, port, 0, 0)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Some(tcp) = &self.inner.main_tcp_channel {
|
||||||
|
let _ = tcp.send(vec![]);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn is_main_tcp(&self) -> bool {
|
pub fn is_main_tcp(&self) -> bool {
|
||||||
self.inner.main_tcp_channel.is_some()
|
self.inner.main_tcp_channel.is_some()
|
||||||
@@ -106,134 +121,142 @@ impl Context {
|
|||||||
Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
|
Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub async fn send_main_udp(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
|
fn insert_udp(&self, id: usize, udp: Arc<UdpSocket>) {
|
||||||
|
self.inner.udp_map.write().insert(id, udp);
|
||||||
|
}
|
||||||
|
fn remove_udp(&self, id: usize) {
|
||||||
|
self.inner.udp_map.write().remove(&id);
|
||||||
|
}
|
||||||
|
pub fn send_main_udp(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
|
||||||
if addr.is_ipv6() {
|
if addr.is_ipv6() {
|
||||||
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
|
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
|
||||||
udp_ipv6.send_to(buf, addr).await
|
udp_ipv6.send_to(buf, addr)
|
||||||
} else {
|
} else {
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
|
Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.inner.main_channel.send_to(buf, addr).await
|
self.inner.main_channel.send_to(buf, addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn try_send_main_udp(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
|
|
||||||
if addr.is_ipv6() {
|
pub fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
|
||||||
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
|
|
||||||
udp_ipv6.try_send_to(buf, addr)
|
|
||||||
} else {
|
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.inner.main_channel.try_send_to(buf, addr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub async fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
|
|
||||||
if let Some(sender) = &self.inner.main_tcp_channel {
|
if let Some(sender) = &self.inner.main_tcp_channel {
|
||||||
if sender.send(buf.to_vec()).await.is_ok() {
|
if sender.try_send(buf.to_vec()).is_ok() {
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
} else {
|
} else {
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "send_main err"))
|
Err(io::Error::new(io::ErrorKind::Other, "send_main err"))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.send_main_udp(buf, addr).await
|
self.send_main_udp(buf, addr)
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn try_send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
|
|
||||||
if let Some(sender) = &self.inner.main_tcp_channel {
|
|
||||||
if sender.try_send(buf.to_vec()).is_ok() {
|
|
||||||
Ok(buf.len())
|
|
||||||
} else {
|
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "try_send_main err"))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.try_send_main_udp(buf, addr)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn send_all(&self, buf: &[u8], addr: SocketAddr) -> io::Result<()> {
|
pub(crate) fn try_send_all(&self, buf: &[u8], addr: SocketAddr) -> io::Result<()> {
|
||||||
for udp_ref in self.inner.udp_map.iter() {
|
let table = self.inner.udp_map.read();
|
||||||
let udp = udp_ref.clone();
|
if table.is_empty() {
|
||||||
drop(udp_ref);
|
log::error!("udp列表为空,addr={}", addr);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
for (_, udp) in table.iter() {
|
||||||
//使用ipv6的udp发送ipv4报文会出错
|
//使用ipv6的udp发送ipv4报文会出错
|
||||||
let _ = udp.send_to(buf, addr).await;
|
if let Err(e) = udp.try_send_to(buf, addr) {
|
||||||
|
log::error!("{:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> {
|
pub async fn send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> {
|
||||||
if let Some(v) = self.inner.route_table.get(id) {
|
let route = self.get_route_by_id(id)?;
|
||||||
if v.value().is_empty() {
|
self.send_by_key(buf, &route.route_key()).await
|
||||||
|
}
|
||||||
|
pub fn try_send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> {
|
||||||
|
let route = self.get_route_by_id(id)?;
|
||||||
|
self.try_send_by_key(buf, &route.route_key())
|
||||||
|
}
|
||||||
|
fn get_route_by_id(&self, id: &Ipv4Addr) -> io::Result<Route> {
|
||||||
|
if let Some(v) = self.inner.route_table.read().get(id) {
|
||||||
|
if v.is_empty() {
|
||||||
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
|
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
|
||||||
}
|
}
|
||||||
let route = v.value()[0];
|
let (route, time) = &v[0];
|
||||||
drop(v);
|
|
||||||
if route.rt == 199 {
|
if route.rt == 199 {
|
||||||
//这通常是刚加入路由,直接放弃使用,避免抖动
|
//这通常是刚加入路由,直接放弃使用,避免抖动
|
||||||
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
|
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
|
||||||
}
|
}
|
||||||
if !route.is_p2p() {
|
if !route.is_p2p() {
|
||||||
if let Some(time) = self.inner.route_table_time.get(&(route.route_key(), *id)) {
|
//借道传输时,长时间不通信的通道不使用
|
||||||
//借道传输时,长时间不通信的通道不使用
|
if time.load().elapsed() > Duration::from_secs(6) {
|
||||||
if time.value().elapsed() > Duration::from_secs(6) {
|
return Err(io::Error::new(io::ErrorKind::NotFound, "route time out"));
|
||||||
return Err(io::Error::new(io::ErrorKind::NotFound, "route time out"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self.send_by_key(buf, &route.route_key()).await;
|
return Ok(*route);
|
||||||
}
|
}
|
||||||
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
|
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> {
|
|
||||||
if let Some(v) = self.inner.route_table.get(id) {
|
|
||||||
if v.value().is_empty() {
|
|
||||||
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
|
|
||||||
}
|
|
||||||
let route = v.value()[0];
|
|
||||||
drop(v);
|
|
||||||
if let Some(udp) = self.inner.udp_map.get(&route.index) {
|
|
||||||
return udp.value().try_send_to(buf, route.addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
|
|
||||||
}
|
|
||||||
pub async fn send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
|
pub async fn send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
|
||||||
if route_key.index == 0 {
|
match route_key.index {
|
||||||
if let Some(sender) = &self.inner.main_tcp_channel {
|
TCP_ID => {
|
||||||
let mut vec = vec![0; 4 + buf.len()];
|
if let Some(sender) = &self.inner.main_tcp_channel {
|
||||||
vec[4..].copy_from_slice(buf);
|
if sender.send(buf.to_vec()).is_ok() {
|
||||||
return if sender.send(vec).await.is_ok() {
|
Ok(buf.len())
|
||||||
Ok(buf.len())
|
} else {
|
||||||
|
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
|
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
UDP_ID => self.inner.main_channel.send_to(buf, route_key.addr),
|
||||||
|
UDP_V6_ID => {
|
||||||
|
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
|
||||||
|
udp_ipv6.send_to(buf, route_key.addr)
|
||||||
|
} else {
|
||||||
|
Err(io::Error::new(io::ErrorKind::Other, "not ipv6 udp"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if let Some(udp) = self.get_udp_by_route(route_key) {
|
||||||
|
return udp.send_to(buf, route_key.addr).await;
|
||||||
|
}
|
||||||
|
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(udp_ref) = self.inner.udp_map.get(&route_key.index) {
|
|
||||||
let udp = udp_ref.value().clone();
|
|
||||||
drop(udp_ref);
|
|
||||||
return udp.send_to(buf, route_key.addr).await;
|
|
||||||
}
|
|
||||||
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
|
|
||||||
}
|
}
|
||||||
pub fn try_send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
|
pub fn try_send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
|
||||||
if route_key.index == 0 {
|
match route_key.index {
|
||||||
if let Some(sender) = &self.inner.main_tcp_channel {
|
TCP_ID => {
|
||||||
let mut vec = vec![0; 4 + buf.len()];
|
if let Some(sender) = &self.inner.main_tcp_channel {
|
||||||
vec[4..].copy_from_slice(buf);
|
if sender.try_send(buf.to_vec()).is_ok() {
|
||||||
return if sender.try_send(vec).is_ok() {
|
Ok(buf.len())
|
||||||
Ok(buf.len())
|
} else {
|
||||||
|
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "try_send_by_key err"))
|
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
UDP_ID => self.inner.main_channel.send_to(buf, route_key.addr),
|
||||||
|
UDP_V6_ID => {
|
||||||
|
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
|
||||||
|
udp_ipv6.send_to(buf, route_key.addr)
|
||||||
|
} else {
|
||||||
|
Err(io::Error::new(io::ErrorKind::Other, "not ipv6 udp"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if let Some(udp) = self.get_udp_by_route(route_key) {
|
||||||
|
return udp.try_send_to(buf, route_key.addr);
|
||||||
|
}
|
||||||
|
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(udp) = self.inner.udp_map.get(&route_key.index) {
|
|
||||||
return udp.value().try_send_to(buf, route_key.addr);
|
|
||||||
}
|
|
||||||
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
|
|
||||||
}
|
}
|
||||||
|
fn get_udp_by_route(&self, route_key: &RouteKey) -> Option<Arc<UdpSocket>> {
|
||||||
|
self.inner.udp_map.read().get(&route_key.index).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_route_if_absent(&self, id: Ipv4Addr, route: Route) {
|
pub fn add_route_if_absent(&self, id: Ipv4Addr, route: Route) {
|
||||||
self.add_route_(id, route, true)
|
self.add_route_(id, route, true)
|
||||||
}
|
}
|
||||||
@@ -242,13 +265,12 @@ impl Context {
|
|||||||
}
|
}
|
||||||
fn add_route_(&self, id: Ipv4Addr, route: Route, only_if_absent: bool) {
|
fn add_route_(&self, id: Ipv4Addr, route: Route, only_if_absent: bool) {
|
||||||
let key = route.route_key();
|
let key = route.route_key();
|
||||||
let mut list = self
|
let mut route_table = self.inner.route_table.write();
|
||||||
.inner
|
let list = route_table
|
||||||
.route_table
|
|
||||||
.entry(id)
|
.entry(id)
|
||||||
.or_insert_with(|| Vec::with_capacity(4));
|
.or_insert_with(|| Vec::with_capacity(4));
|
||||||
let mut exist = false;
|
let mut exist = false;
|
||||||
for x in list.iter_mut() {
|
for (x, time) in list.iter_mut() {
|
||||||
if x.metric < route.metric {
|
if x.metric < route.metric {
|
||||||
//不能比当前的路径更长
|
//不能比当前的路径更长
|
||||||
return;
|
return;
|
||||||
@@ -260,105 +282,103 @@ impl Context {
|
|||||||
x.metric = route.metric;
|
x.metric = route.metric;
|
||||||
x.rt = route.rt;
|
x.rt = route.rt;
|
||||||
exist = true;
|
exist = true;
|
||||||
|
time.store(Instant::now());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if exist {
|
if exist {
|
||||||
list.sort_by_key(|k| k.sort_key());
|
list.sort_by_key(|(k, _)| k.rt);
|
||||||
} else {
|
} else {
|
||||||
if route.metric == 1 {
|
if route.metric == 1 && !self.inner.first_latency {
|
||||||
//添加了直连的则排除非直连的
|
//非优先延迟的情况下 添加了直连的则排除非直连的
|
||||||
list.retain(|k| k.metric == 1);
|
list.retain(|(k, _)| k.metric == 1);
|
||||||
}
|
}
|
||||||
list.push(route);
|
list.sort_by_key(|(k, _)| k.rt);
|
||||||
list.sort_by_key(|k| k.sort_key());
|
let max_len = self.inner.channel_num;
|
||||||
let max_len = self.inner.channel_num + 1;
|
|
||||||
if list.len() > max_len {
|
if list.len() > max_len {
|
||||||
list.truncate(max_len);
|
list.truncate(max_len);
|
||||||
}
|
}
|
||||||
|
list.push((route, AtomicCell::new(Instant::now())));
|
||||||
}
|
}
|
||||||
self.inner
|
|
||||||
.route_table_time
|
|
||||||
.insert((key, id), Instant::now());
|
|
||||||
}
|
}
|
||||||
pub fn route(&self, id: &Ipv4Addr) -> Option<Vec<Route>> {
|
pub fn route(&self, id: &Ipv4Addr) -> Option<Vec<Route>> {
|
||||||
if let Some(v) = self.inner.route_table.get(id) {
|
if let Some(v) = self.inner.route_table.read().get(id) {
|
||||||
Some(v.value().clone())
|
Some(v.iter().map(|(i, _)| *i).collect())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn route_one(&self, id: &Ipv4Addr) -> Option<Route> {
|
pub fn route_one(&self, id: &Ipv4Addr) -> Option<Route> {
|
||||||
if let Some(v) = self.inner.route_table.get(id) {
|
if let Some(v) = self.inner.route_table.read().get(id) {
|
||||||
v.value().first().map(|v| *v)
|
v.first().map(|(i, _)| *i)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn route_to_id(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
|
pub fn route_to_id(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
|
||||||
for x in self.inner.route_table.iter() {
|
let table = self.inner.route_table.read();
|
||||||
for route in x.value() {
|
for (k, v) in table.iter() {
|
||||||
|
for (route, _) in v {
|
||||||
if &route.route_key() == route_key && route.is_p2p() {
|
if &route.route_key() == route_key && route.is_p2p() {
|
||||||
return Some(*x.key());
|
return Some(*k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
pub fn need_punch(&self, id: &Ipv4Addr) -> bool {
|
pub fn need_punch(&self, id: &Ipv4Addr) -> bool {
|
||||||
if let Some(v) = self.inner.route_table.get(id) {
|
if let Some(v) = self.inner.route_table.read().get(id) {
|
||||||
if v.value().iter().filter(|k| k.is_p2p()).count() >= self.inner.channel_num {
|
if v.iter().filter(|(k, _)| k.is_p2p()).count() >= self.inner.channel_num {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec<Route>)> {
|
pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec<Route>)> {
|
||||||
self.inner
|
let table = self.inner.route_table.read();
|
||||||
.route_table
|
table
|
||||||
.iter()
|
.iter()
|
||||||
.map(|k| (k.key().clone(), k.value().clone()))
|
.map(|(k, v)| (k.clone(), v.iter().map(|(i, _)| *i).collect()))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
pub fn route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
|
pub fn route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
|
||||||
let mut v = Vec::with_capacity(8);
|
let mut list = Vec::with_capacity(8);
|
||||||
for x in self.inner.route_table.iter() {
|
let table = self.inner.route_table.read();
|
||||||
if let Some(route) = x.value().first() {
|
for (k, v) in table.iter() {
|
||||||
v.push((*x.key(), *route));
|
if let Some((route, _)) = v.first() {
|
||||||
|
list.push((*k, *route));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v
|
list
|
||||||
}
|
}
|
||||||
pub fn direct_route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
|
pub fn direct_route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
|
||||||
let mut v = Vec::with_capacity(8);
|
let mut list = Vec::with_capacity(8);
|
||||||
for x in self.inner.route_table.iter() {
|
let table = self.inner.route_table.read();
|
||||||
if let Some(route) = x.value().first() {
|
for (k, v) in table.iter() {
|
||||||
|
if let Some((route, _)) = v.first() {
|
||||||
if route.metric == 1 {
|
if route.metric == 1 {
|
||||||
v.push((*x.key(), *route));
|
list.push((*k, *route));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v
|
list
|
||||||
}
|
|
||||||
pub fn remove_route_all(&self, id: &Ipv4Addr) {
|
|
||||||
if let Some((_, routes)) = self.inner.route_table.remove(id) {
|
|
||||||
for x in routes {
|
|
||||||
self.inner.route_table_time.remove(&(x.route_key(), *id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_route(&self, id: &Ipv4Addr, route_key: RouteKey) {
|
pub fn remove_route(&self, id: &Ipv4Addr, route_key: RouteKey) {
|
||||||
if let Some(v) = self.inner.route_table.get(id) {
|
if let Some(routes) = self.inner.route_table.write().get_mut(id) {
|
||||||
let mut routes = v.value().clone();
|
routes.retain(|(x, _)| x.route_key() != route_key);
|
||||||
drop(v);
|
} else {
|
||||||
routes.retain(|x| x.route_key() != route_key);
|
return;
|
||||||
self.inner.route_table.insert(*id, routes);
|
|
||||||
}
|
}
|
||||||
self.inner.route_table_time.remove(&(route_key, *id));
|
|
||||||
}
|
}
|
||||||
pub fn update_read_time(&self, id: &Ipv4Addr, route_key: &RouteKey) {
|
pub fn update_read_time(&self, id: &Ipv4Addr, route_key: &RouteKey) {
|
||||||
if let Some(mut time) = self.inner.route_table_time.get_mut(&(*route_key, *id)) {
|
if let Some(routes) = self.inner.route_table.read().get(id) {
|
||||||
*time.value_mut() = Instant::now();
|
for (route, time) in routes {
|
||||||
|
if &route.route_key() == route_key {
|
||||||
|
time.store(Instant::now());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -377,16 +397,16 @@ impl Channel {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct BufSenderGroup(
|
struct BufSenderGroup(
|
||||||
usize,
|
usize,
|
||||||
Vec<tokio::sync::mpsc::Sender<(Block<'static>, usize, usize, RouteKey)>>,
|
Vec<std::sync::mpsc::SyncSender<(Vec<u8>, usize, usize, RouteKey)>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
struct BufReceiverGroup(Vec<tokio::sync::mpsc::Receiver<(Block<'static>, usize, usize, RouteKey)>>);
|
struct BufReceiverGroup(Vec<std::sync::mpsc::Receiver<(Vec<u8>, usize, usize, RouteKey)>>);
|
||||||
|
|
||||||
impl BufSenderGroup {
|
impl BufSenderGroup {
|
||||||
pub async fn send(&mut self, val: (Block<'static>, usize, usize, RouteKey)) -> bool {
|
pub fn send(&mut self, val: (Vec<u8>, usize, usize, RouteKey)) -> bool {
|
||||||
let index = self.0 % self.1.len();
|
let index = self.0 % self.1.len();
|
||||||
self.0 = self.0.wrapping_add(1);
|
self.0 = self.0.wrapping_add(1);
|
||||||
self.1[index].send(val).await.is_ok()
|
self.1[index].send(val).is_ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,7 +415,7 @@ fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) {
|
|||||||
let mut buf_receiver_group = Vec::with_capacity(size);
|
let mut buf_receiver_group = Vec::with_capacity(size);
|
||||||
for _ in 0..size {
|
for _ in 0..size {
|
||||||
let (buf_sender, buf_receiver) =
|
let (buf_sender, buf_receiver) =
|
||||||
tokio::sync::mpsc::channel::<(Block<'static, Vec<u8>>, usize, usize, RouteKey)>(10);
|
std::sync::mpsc::sync_channel::<(Vec<u8>, usize, usize, RouteKey)>(1);
|
||||||
buf_sender_group.push(buf_sender);
|
buf_sender_group.push(buf_sender);
|
||||||
buf_receiver_group.push(buf_receiver);
|
buf_receiver_group.push(buf_receiver);
|
||||||
}
|
}
|
||||||
@@ -406,17 +426,18 @@ fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Channel {
|
impl Channel {
|
||||||
async fn tcp_handle(
|
fn tcp_handle(
|
||||||
mut tcp_r: OwnedReadHalf,
|
tcp_r: &mut TcpStream,
|
||||||
mut buf_sender: BufSenderGroup,
|
context: Context,
|
||||||
|
handler: ChannelDataHandler,
|
||||||
head_reserve: usize,
|
head_reserve: usize,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
let mut head = [0; 4];
|
let mut head = [0; 4];
|
||||||
let addr = tcp_r.peer_addr()?;
|
let addr = tcp_r.peer_addr()?;
|
||||||
let key = RouteKey::new(0, addr);
|
let key = RouteKey::new(TCP_ID, addr);
|
||||||
loop {
|
loop {
|
||||||
let mut buf = POOL.alloc(4096);
|
let mut buf = [0; 4096];
|
||||||
tcp_r.read_exact(&mut head).await?;
|
tcp_r.read_exact(&mut head)?;
|
||||||
let len = (((head[2] as u16) << 8) | head[3] as u16) as usize;
|
let len = (((head[2] as u16) << 8) | head[3] as u16) as usize;
|
||||||
if len < 12 || len > buf.len() {
|
if len < 12 || len > buf.len() {
|
||||||
return Err(io::Error::new(
|
return Err(io::Error::new(
|
||||||
@@ -424,87 +445,98 @@ impl Channel {
|
|||||||
"length overflow",
|
"length overflow",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
tcp_r
|
tcp_r.read_exact(&mut buf[head_reserve..head_reserve + len])?;
|
||||||
.read_exact(&mut buf[head_reserve..head_reserve + len])
|
handler.handle(&mut buf, head_reserve, head_reserve + len, key, &context);
|
||||||
.await?;
|
|
||||||
if !buf_sender
|
|
||||||
.send((buf, head_reserve, head_reserve + len, key))
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
return Err(io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
"buf_sender发送数据失败",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async fn start_tcp(
|
fn start_tcp(
|
||||||
mut worker: VntWorker,
|
worker: VntWorker,
|
||||||
tcp_stream: TcpStream,
|
mut tcp_stream: TcpStream,
|
||||||
mut receiver: tokio::sync::mpsc::Receiver<Vec<u8>>,
|
receiver: std::sync::mpsc::Receiver<Vec<u8>>,
|
||||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
context: Context,
|
||||||
buf_sender: BufSenderGroup,
|
handler: ChannelDataHandler,
|
||||||
head_reserve: usize,
|
head_reserve: usize,
|
||||||
) {
|
) {
|
||||||
let (tcp_r, mut tcp_w) = tcp_stream.into_split();
|
let current_device = context.inner.current_device.clone();
|
||||||
{
|
{
|
||||||
let buf_sender = buf_sender.clone();
|
let mut tcp_r = tcp_stream.try_clone().unwrap();
|
||||||
tokio::spawn(async move {
|
let context = context.clone();
|
||||||
if let Err(e) = Self::tcp_handle(tcp_r, buf_sender, head_reserve).await {
|
let handler = handler.clone();
|
||||||
log::info!("tcp链接断开:{:?}", e);
|
thread::Builder::new()
|
||||||
}
|
.name("tcp_reader".into())
|
||||||
});
|
.spawn(move || {
|
||||||
|
if let Err(e) = Self::tcp_handle(&mut tcp_r, context, handler, head_reserve) {
|
||||||
|
log::info!("tcp链接断开:{:?}", e);
|
||||||
|
}
|
||||||
|
if let Err(e) = tcp_r.shutdown(Shutdown::Both) {
|
||||||
|
log::info!("tcp链接关闭异常:{:?}", e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
let mut head = [0; 4];
|
let mut head = [0; 4];
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
let data = match receiver.recv() {
|
||||||
_=worker.stop_wait()=>{
|
Ok(data) => data,
|
||||||
|
Err(_) => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rs=receiver.recv()=>{
|
};
|
||||||
if let Some(data) = rs{
|
let len = data.len();
|
||||||
let len = data.len();
|
if len == 0 {
|
||||||
head[2] = (len >> 8) as u8;
|
break;
|
||||||
head[3] = (len & 0xFF) as u8;
|
}
|
||||||
let mut err = false;
|
head[2] = (len >> 8) as u8;
|
||||||
if let Err(e) = tcp_w.write_all(&head).await{
|
head[3] = (len & 0xFF) as u8;
|
||||||
err = true;
|
let mut err = false;
|
||||||
log::info!("发送失败,需要重连:{:?}",e);
|
if let Err(e) = tcp_stream.write_all(&head) {
|
||||||
}else if let Err(e) = tcp_w.write_all(&data).await{
|
err = true;
|
||||||
err = true;
|
log::info!("发送失败,需要重连:{:?}", e);
|
||||||
log::info!("发送失败,需要重连:{:?}",e);
|
} else if let Err(e) = tcp_stream.write_all(&data) {
|
||||||
}
|
err = true;
|
||||||
if err {
|
log::info!("发送失败,需要重连:{:?}", e);
|
||||||
let _ = tcp_w.shutdown().await;
|
}
|
||||||
match TcpStream::connect(current_device.load().connect_server).await {
|
if err {
|
||||||
Ok(tcp_stream) => {
|
if let Err(e) = tcp_stream.shutdown(Shutdown::Both) {
|
||||||
let (r, w) = tcp_stream.into_split();
|
log::info!("tcp链接关闭异常:{:?}", e);
|
||||||
tcp_w = w;
|
}
|
||||||
let buf_sender = buf_sender.clone();
|
match TcpStream::connect(current_device.load().connect_server) {
|
||||||
tokio::spawn(async move {
|
Ok(tcp) => {
|
||||||
if let Err(e) = Self::tcp_handle(r, buf_sender, head_reserve).await {
|
tcp.set_read_timeout(Some(Duration::from_secs(10))).unwrap();
|
||||||
log::info!("tcp 链接断开:{:?}",e);
|
tcp_stream = tcp;
|
||||||
}
|
let mut tcp_r = tcp_stream.try_clone().unwrap();
|
||||||
});
|
let context = context.clone();
|
||||||
|
let handler = handler.clone();
|
||||||
|
thread::Builder::new()
|
||||||
|
.name("tcp_reader".into())
|
||||||
|
.spawn(move || {
|
||||||
|
if let Err(e) =
|
||||||
|
Self::tcp_handle(&mut tcp_r, context, handler, head_reserve)
|
||||||
|
{
|
||||||
|
log::info!("重连后 tcp链接断开:{:?}", e);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
if let Err(e) = tcp_r.shutdown(Shutdown::Both) {
|
||||||
log::info!("重连失败:{:?}",e);
|
log::info!("重连后 tcp链接关闭异常:{:?}", e);
|
||||||
}
|
}
|
||||||
};
|
})
|
||||||
}
|
.unwrap();
|
||||||
}else{
|
}
|
||||||
break;
|
Err(e) => {
|
||||||
|
log::info!("重连失败:{:?}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Err(e) = tcp_stream.shutdown(Shutdown::Both) {
|
||||||
|
log::info!("tcp链接关闭异常:{:?}", e);
|
||||||
|
}
|
||||||
worker.stop_all();
|
worker.stop_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start(
|
pub async fn start(
|
||||||
self,
|
self,
|
||||||
mut worker: VntWorker,
|
mut worker: VntWorker,
|
||||||
tcp: Option<(TcpStream, tokio::sync::mpsc::Receiver<Vec<u8>>)>,
|
tcp: Option<(TcpStream, std::sync::mpsc::Receiver<Vec<u8>>)>,
|
||||||
head_reserve: usize, //头部预留字节
|
head_reserve: usize, //头部预留字节
|
||||||
symmetric_channel_num: usize, //对称网络,则再加一组监听,提升打洞成功率
|
symmetric_channel_num: usize, //对称网络,则再加一组监听,提升打洞成功率
|
||||||
relay: bool,
|
relay: bool,
|
||||||
@@ -513,53 +545,89 @@ impl Channel {
|
|||||||
let handler = self.handler.clone();
|
let handler = self.handler.clone();
|
||||||
let context = self.context;
|
let context = self.context;
|
||||||
let main_channel = context.inner.main_channel.clone();
|
let main_channel = context.inner.main_channel.clone();
|
||||||
let buf_sender = if parallel > 1 || tcp.is_some() {
|
let buf_sender = if parallel > 1 {
|
||||||
let (buf_sender, buf_receiver) = buf_channel_group(parallel);
|
let (buf_sender, buf_receiver) = buf_channel_group(parallel);
|
||||||
for mut buf_receiver in buf_receiver.0 {
|
let mut num = 0;
|
||||||
|
for buf_receiver in buf_receiver.0 {
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let handler = handler.clone();
|
let handler = handler.clone();
|
||||||
tokio::spawn(async move {
|
thread::Builder::new()
|
||||||
while let Some((mut buf, start, end, route_key)) = buf_receiver.recv().await {
|
.name(format!("recv-handler-{}", num))
|
||||||
handler
|
.spawn(move || {
|
||||||
.handle(&mut buf, start, end, route_key, &context)
|
while let Ok((mut buf, start, end, route_key)) = buf_receiver.recv() {
|
||||||
.await;
|
handler.handle(&mut buf, start, end, route_key, &context);
|
||||||
}
|
}
|
||||||
});
|
log::warn!("异步处理停止");
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
num += 1;
|
||||||
}
|
}
|
||||||
Some(buf_sender)
|
Some(buf_sender)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
if let Some((tcp_stream, receiver)) = tcp {
|
if let Some((tcp_stream, receiver)) = tcp {
|
||||||
tokio::spawn(Self::start_tcp(
|
let context = context.clone();
|
||||||
worker.worker("main_channel_tcp"),
|
let handler = handler.clone();
|
||||||
tcp_stream,
|
let main_channel_tcp = worker.worker("main_channel_tcp");
|
||||||
receiver,
|
thread::Builder::new()
|
||||||
context.inner.current_device.clone(),
|
.name("main_channel_tcp".into())
|
||||||
buf_sender.clone().unwrap(),
|
.spawn(move || {
|
||||||
head_reserve,
|
Self::start_tcp(
|
||||||
));
|
main_channel_tcp,
|
||||||
|
tcp_stream,
|
||||||
|
receiver,
|
||||||
|
context,
|
||||||
|
handler,
|
||||||
|
head_reserve,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
if let Some(main_channel_ipv6) = &context.inner.main_channel_ipv6 {
|
if let Some(main_channel_ipv6) = &context.inner.main_channel_ipv6 {
|
||||||
tokio::spawn(Self::start_(
|
let worker = worker.worker("main_channel_ipv6");
|
||||||
worker.worker("main_channel_ipv6"),
|
let context = context.clone();
|
||||||
context.clone(),
|
let main_channel_ipv6 = main_channel_ipv6.clone();
|
||||||
main_channel_ipv6.clone(),
|
let handler = handler.clone();
|
||||||
handler.clone(),
|
let buf_sender = buf_sender.clone();
|
||||||
buf_sender.clone(),
|
thread::Builder::new()
|
||||||
head_reserve,
|
.name("ipv6-recv".into())
|
||||||
true,
|
.spawn(move || {
|
||||||
));
|
log::info!("启动udp v6");
|
||||||
|
Self::main_start_(
|
||||||
|
worker,
|
||||||
|
context,
|
||||||
|
UDP_V6_ID,
|
||||||
|
main_channel_ipv6,
|
||||||
|
handler,
|
||||||
|
buf_sender,
|
||||||
|
head_reserve,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let worker = worker.worker("main_channel_1");
|
||||||
|
let context = context.clone();
|
||||||
|
let main_channel = main_channel.clone();
|
||||||
|
let handler = handler.clone();
|
||||||
|
let buf_sender = buf_sender.clone();
|
||||||
|
thread::Builder::new()
|
||||||
|
.name("ipv4-recv".into())
|
||||||
|
.spawn(move || {
|
||||||
|
log::info!("启动udp v4");
|
||||||
|
Self::main_start_(
|
||||||
|
worker,
|
||||||
|
context,
|
||||||
|
UDP_ID,
|
||||||
|
main_channel,
|
||||||
|
handler,
|
||||||
|
buf_sender,
|
||||||
|
head_reserve,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
tokio::spawn(Self::start_(
|
|
||||||
worker.worker("main_channel_1"),
|
|
||||||
context.clone(),
|
|
||||||
main_channel.clone(),
|
|
||||||
handler.clone(),
|
|
||||||
buf_sender.clone(),
|
|
||||||
head_reserve,
|
|
||||||
true,
|
|
||||||
));
|
|
||||||
if relay {
|
if relay {
|
||||||
worker.stop_wait().await;
|
worker.stop_wait().await;
|
||||||
return;
|
return;
|
||||||
@@ -611,6 +679,62 @@ impl Channel {
|
|||||||
}
|
}
|
||||||
worker.stop_all();
|
worker.stop_all();
|
||||||
}
|
}
|
||||||
|
fn main_start_(
|
||||||
|
worker: VntWorker,
|
||||||
|
context: Context,
|
||||||
|
id: usize,
|
||||||
|
udp: Arc<StdUdpSocket>,
|
||||||
|
handler: ChannelDataHandler,
|
||||||
|
buf_sender: Option<BufSenderGroup>,
|
||||||
|
head_reserve: usize,
|
||||||
|
) {
|
||||||
|
match buf_sender {
|
||||||
|
None => {
|
||||||
|
let mut buf = [0; 4096];
|
||||||
|
loop {
|
||||||
|
match udp.recv_from(&mut buf[head_reserve..]) {
|
||||||
|
Ok((len, addr)) => {
|
||||||
|
let end = head_reserve + len;
|
||||||
|
if &buf[head_reserve..end] == b"stop" {
|
||||||
|
if context.is_close() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler.handle(
|
||||||
|
&mut buf,
|
||||||
|
head_reserve,
|
||||||
|
end,
|
||||||
|
RouteKey::new(id, addr),
|
||||||
|
&context,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("udp :{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(mut buf_sender) => loop {
|
||||||
|
let mut buf = vec![0; 4096];
|
||||||
|
match udp.recv_from(&mut buf[head_reserve..]) {
|
||||||
|
Ok((len, addr)) => {
|
||||||
|
let end = head_reserve + len;
|
||||||
|
if &buf[head_reserve..end] == b"stop" {
|
||||||
|
if context.is_close() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf_sender.send((buf, head_reserve, end, RouteKey::new(id, addr)));
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("udp :{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
worker.stop_all();
|
||||||
|
}
|
||||||
async fn start_(
|
async fn start_(
|
||||||
mut worker: VntWorker,
|
mut worker: VntWorker,
|
||||||
context: Context,
|
context: Context,
|
||||||
@@ -624,12 +748,13 @@ impl Channel {
|
|||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use std::os::windows::io::AsRawSocket;
|
use std::os::windows::io::AsRawSocket;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let id = 1 + udp.as_raw_socket() as usize;
|
let id = 3 + udp.as_raw_socket() as usize;
|
||||||
#[cfg(any(unix))]
|
#[cfg(any(unix))]
|
||||||
use std::os::fd::AsRawFd;
|
use std::os::fd::AsRawFd;
|
||||||
#[cfg(any(unix))]
|
#[cfg(any(unix))]
|
||||||
let id = 1 + udp.as_raw_fd() as usize;
|
let id = 3 + udp.as_raw_fd() as usize;
|
||||||
context.inner.udp_map.insert(id, udp.clone());
|
|
||||||
|
context.insert_udp(id, udp.clone());
|
||||||
match buf_sender {
|
match buf_sender {
|
||||||
None => {
|
None => {
|
||||||
let mut buf = [0; 4096];
|
let mut buf = [0; 4096];
|
||||||
@@ -638,7 +763,7 @@ impl Channel {
|
|||||||
rs=udp.recv_from(&mut buf[head_reserve..])=>{
|
rs=udp.recv_from(&mut buf[head_reserve..])=>{
|
||||||
match rs {
|
match rs {
|
||||||
Ok((len, addr)) => {
|
Ok((len, addr)) => {
|
||||||
handler.handle(&mut buf, head_reserve, head_reserve + len, RouteKey::new(id, addr), &context).await;
|
handler.handle(&mut buf, head_reserve, head_reserve + len, RouteKey::new(id, addr), &context);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("{:?}",e)
|
log::error!("{:?}",e)
|
||||||
@@ -672,12 +797,12 @@ impl Channel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(mut buf_sender) => loop {
|
Some(mut buf_sender) => loop {
|
||||||
let mut buf = POOL.alloc(4096);
|
let mut buf = vec![0; 4096];
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
rs=udp.recv_from(&mut buf[head_reserve..])=>{
|
rs=udp.recv_from(&mut buf[head_reserve..])=>{
|
||||||
match rs {
|
match rs {
|
||||||
Ok((len, addr)) => {
|
Ok((len, addr)) => {
|
||||||
if !buf_sender.send((buf,head_reserve,head_reserve+len,RouteKey::new(id, addr))).await{
|
if !buf_sender.send((buf,head_reserve,head_reserve+len,RouteKey::new(id, addr))){
|
||||||
log::error!("udp buf_sender发送数据失败");
|
log::error!("udp buf_sender发送数据失败");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -713,7 +838,7 @@ impl Channel {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
context.inner.udp_map.remove(&id);
|
context.remove_udp(id);
|
||||||
if is_core {
|
if is_core {
|
||||||
worker.stop_all();
|
worker.stop_all();
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-9
@@ -1,10 +1,11 @@
|
|||||||
use crate::channel::channel::Context;
|
|
||||||
use crate::channel::RouteKey;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::{Error, ErrorKind};
|
use std::io::{Error, ErrorKind};
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::channel::channel::Context;
|
||||||
|
use crate::channel::RouteKey;
|
||||||
|
|
||||||
pub struct Idle {
|
pub struct Idle {
|
||||||
read_idle: Duration,
|
read_idle: Duration,
|
||||||
context: Context,
|
context: Context,
|
||||||
@@ -21,13 +22,17 @@ impl Idle {
|
|||||||
pub async fn next_idle(&self) -> io::Result<(Ipv4Addr, RouteKey)> {
|
pub async fn next_idle(&self) -> io::Result<(Ipv4Addr, RouteKey)> {
|
||||||
loop {
|
loop {
|
||||||
let mut max = Duration::from_secs(0);
|
let mut max = Duration::from_secs(0);
|
||||||
for entry in self.context.inner.route_table_time.iter() {
|
{
|
||||||
let last_read = entry.value().elapsed();
|
for (ip, routes) in self.context.inner.route_table.read().iter() {
|
||||||
if last_read >= self.read_idle {
|
for (route, time) in routes {
|
||||||
return Ok((entry.key().1.clone(), entry.key().0.clone()));
|
let last_read = time.load().elapsed();
|
||||||
} else {
|
if last_read >= self.read_idle {
|
||||||
if max < last_read {
|
return Ok((*ip, route.route_key()));
|
||||||
max = last_read;
|
} else {
|
||||||
|
if max < last_read {
|
||||||
|
max = last_read;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ pub mod idle;
|
|||||||
pub mod punch;
|
pub mod punch;
|
||||||
pub mod sender;
|
pub mod sender;
|
||||||
|
|
||||||
|
const TCP_ID: usize = 0;
|
||||||
|
const UDP_ID: usize = 1;
|
||||||
|
const UDP_V6_ID: usize = 2;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum Status {
|
pub enum Status {
|
||||||
Cone,
|
Cone,
|
||||||
@@ -70,4 +74,7 @@ impl RouteKey {
|
|||||||
pub(crate) fn new(index: usize, addr: SocketAddr) -> Self {
|
pub(crate) fn new(index: usize, addr: SocketAddr) -> Self {
|
||||||
Self { index, addr }
|
Self { index, addr }
|
||||||
}
|
}
|
||||||
|
pub fn is_tcp(&self) -> bool {
|
||||||
|
self.index == TCP_ID
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -50,9 +50,12 @@ impl NatInfo {
|
|||||||
public_port_range: u16,
|
public_port_range: u16,
|
||||||
local_ipv4_addr: SocketAddrV4,
|
local_ipv4_addr: SocketAddrV4,
|
||||||
ipv6_addr: SocketAddrV6,
|
ipv6_addr: SocketAddrV6,
|
||||||
nat_type: NatType,
|
mut nat_type: NatType,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
public_ips.retain(|ip| !ip.is_loopback() && !ip.is_private());
|
public_ips.retain(|ip| !ip.is_loopback() && !ip.is_private() && !ip.is_unspecified());
|
||||||
|
if public_ips.len() > 1 {
|
||||||
|
nat_type = NatType::Symmetric;
|
||||||
|
}
|
||||||
Self {
|
Self {
|
||||||
public_ips,
|
public_ips,
|
||||||
public_port,
|
public_port,
|
||||||
@@ -95,8 +98,7 @@ impl Punch {
|
|||||||
if !nat_info.local_ipv4_addr.ip().is_unspecified() && nat_info.local_ipv4_addr.port() != 0 {
|
if !nat_info.local_ipv4_addr.ip().is_unspecified() && nat_info.local_ipv4_addr.port() != 0 {
|
||||||
let _ = self
|
let _ = self
|
||||||
.context
|
.context
|
||||||
.send_main_udp(buf, SocketAddr::V4(nat_info.local_ipv4_addr))
|
.send_main_udp(buf, SocketAddr::V4(nat_info.local_ipv4_addr));
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
if self.punch_model != PunchModel::IPv4
|
if self.punch_model != PunchModel::IPv4
|
||||||
&& !nat_info.ipv6_addr.ip().is_unspecified()
|
&& !nat_info.ipv6_addr.ip().is_unspecified()
|
||||||
@@ -104,8 +106,7 @@ impl Punch {
|
|||||||
{
|
{
|
||||||
let rs = self
|
let rs = self
|
||||||
.context
|
.context
|
||||||
.send_main_udp(buf, SocketAddr::V6(nat_info.ipv6_addr))
|
.send_main_udp(buf, SocketAddr::V6(nat_info.ipv6_addr));
|
||||||
.await;
|
|
||||||
log::info!("发送到ipv6地址:{:?},rs={:?}", nat_info.ipv6_addr, rs);
|
log::info!("发送到ipv6地址:{:?},rs={:?}", nat_info.ipv6_addr, rs);
|
||||||
if rs.is_ok() && self.punch_model == PunchModel::IPv6 {
|
if rs.is_ok() && self.punch_model == PunchModel::IPv6 {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -167,11 +168,10 @@ impl Punch {
|
|||||||
let is_cone = self.context.is_cone();
|
let is_cone = self.context.is_cone();
|
||||||
for ip in nat_info.public_ips {
|
for ip in nat_info.public_ips {
|
||||||
let addr = SocketAddr::V4(SocketAddrV4::new(ip, nat_info.public_port));
|
let addr = SocketAddr::V4(SocketAddrV4::new(ip, nat_info.public_port));
|
||||||
if is_cone {
|
self.context.send_main_udp(buf, addr)?;
|
||||||
self.context.send_main_udp(buf, addr).await?;
|
if !is_cone {
|
||||||
} else {
|
|
||||||
//只有一方是对称,则对称方要使用全部端口发送数据,符合上述计算的概率
|
//只有一方是对称,则对称方要使用全部端口发送数据,符合上述计算的概率
|
||||||
self.context.send_all(buf, addr).await?;
|
self.context.try_send_all(buf, addr)?;
|
||||||
}
|
}
|
||||||
tokio::time::sleep(Duration::from_millis(2)).await;
|
tokio::time::sleep(Duration::from_millis(2)).await;
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ impl Punch {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let addr = SocketAddr::V4(SocketAddrV4::new(*pub_ip, *port));
|
let addr = SocketAddr::V4(SocketAddrV4::new(*pub_ip, *port));
|
||||||
self.context.send_main_udp(buf, addr).await?;
|
self.context.send_main_udp(buf, addr)?;
|
||||||
tokio::time::sleep(Duration::from_millis(2)).await;
|
tokio::time::sleep(Duration::from_millis(2)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+90
-73
@@ -1,8 +1,6 @@
|
|||||||
use crate::cipher::Finger;
|
use crate::cipher::Finger;
|
||||||
use crate::protocol::body::AesCbcSecretBody;
|
|
||||||
use crate::protocol::{NetPacket, HEAD_LEN};
|
use crate::protocol::{NetPacket, HEAD_LEN};
|
||||||
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyInit};
|
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyInit};
|
||||||
use rand::RngCore;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
type Aes128EcbEnc = ecb::Encryptor<aes::Aes128>;
|
type Aes128EcbEnc = ecb::Encryptor<aes::Aes128>;
|
||||||
@@ -12,11 +10,11 @@ type Aes256EcbDec = ecb::Decryptor<aes::Aes256>;
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AesEcbCipher {
|
pub struct AesEcbCipher {
|
||||||
pub(crate) cipher: AesEcbEnum,
|
key: AesEcbEnum,
|
||||||
pub(crate) finger: Option<Finger>,
|
pub(crate) finger: Option<Finger>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum AesEcbEnum {
|
pub enum AesEcbEnum {
|
||||||
AES128ECB([u8; 16]),
|
AES128ECB([u8; 16]),
|
||||||
AES256ECB([u8; 32]),
|
AES256ECB([u8; 32]),
|
||||||
@@ -24,7 +22,7 @@ pub enum AesEcbEnum {
|
|||||||
|
|
||||||
impl AesEcbCipher {
|
impl AesEcbCipher {
|
||||||
pub fn key(&self) -> &[u8] {
|
pub fn key(&self) -> &[u8] {
|
||||||
match &self.cipher {
|
match &self.key {
|
||||||
AesEcbEnum::AES128ECB(key) => key,
|
AesEcbEnum::AES128ECB(key) => key,
|
||||||
AesEcbEnum::AES256ECB(key) => key,
|
AesEcbEnum::AES256ECB(key) => key,
|
||||||
}
|
}
|
||||||
@@ -34,13 +32,13 @@ impl AesEcbCipher {
|
|||||||
impl AesEcbCipher {
|
impl AesEcbCipher {
|
||||||
pub fn new_128(key: [u8; 16], finger: Option<Finger>) -> Self {
|
pub fn new_128(key: [u8; 16], finger: Option<Finger>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cipher: AesEcbEnum::AES128ECB(key),
|
key: AesEcbEnum::AES128ECB(key),
|
||||||
finger,
|
finger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn new_256(key: [u8; 32], finger: Option<Finger>) -> Self {
|
pub fn new_256(key: [u8; 32], finger: Option<Finger>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cipher: AesEcbEnum::AES256ECB(key),
|
key: AesEcbEnum::AES256ECB(key),
|
||||||
finger,
|
finger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,46 +51,67 @@ impl AesEcbCipher {
|
|||||||
//未加密的数据直接丢弃
|
//未加密的数据直接丢弃
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(finger) = &self.finger {
|
||||||
|
let mut nonce_raw = [0; 12];
|
||||||
|
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||||
|
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||||
|
nonce_raw[8] = net_packet.protocol().into();
|
||||||
|
nonce_raw[9] = net_packet.transport_protocol();
|
||||||
|
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||||
|
nonce_raw[11] = net_packet.source_ttl();
|
||||||
|
let len = net_packet.payload().len();
|
||||||
|
if len < 12 {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "payload len <12"));
|
||||||
|
}
|
||||||
|
let secret_body = &net_packet.payload()[..len - 12];
|
||||||
|
let finger = finger.calculate_finger(&nonce_raw, secret_body);
|
||||||
|
if &finger != &net_packet.payload()[len - 12..] {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
||||||
|
}
|
||||||
|
net_packet.set_data_len(net_packet.data_len() - finger.len())?;
|
||||||
|
}
|
||||||
if net_packet.payload().len() < 16 {
|
if net_packet.payload().len() < 16 {
|
||||||
log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16);
|
log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16);
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
}
|
}
|
||||||
let mut iv = [0; 16];
|
let mut out = [0u8; 1024 * 5];
|
||||||
iv[0..4].copy_from_slice(&net_packet.source().octets());
|
let rs = match self.key {
|
||||||
iv[4..8].copy_from_slice(&net_packet.destination().octets());
|
AesEcbEnum::AES128ECB(key) => Aes128EcbDec::new(&key.into())
|
||||||
iv[8] = net_packet.protocol().into();
|
.decrypt_padded_b2b_mut::<Pkcs7>(net_packet.payload(), &mut out),
|
||||||
iv[9] = net_packet.transport_protocol();
|
AesEcbEnum::AES256ECB(key) => Aes256EcbDec::new(&key.into())
|
||||||
iv[10] = net_packet.is_gateway() as u8;
|
.decrypt_padded_b2b_mut::<Pkcs7>(net_packet.payload(), &mut out),
|
||||||
iv[11] = net_packet.source_ttl();
|
|
||||||
if let Some(finger) = &self.finger {
|
|
||||||
iv[12..16].copy_from_slice(&finger.hash[0..4]);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut secret_body =
|
|
||||||
AesCbcSecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
|
||||||
if let Some(finger) = &self.finger {
|
|
||||||
let finger = finger.calculate_finger(&iv[..12], secret_body.en_body());
|
|
||||||
if &finger != secret_body.finger() {
|
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let rs = match &self.cipher {
|
|
||||||
AesEcbEnum::AES128ECB(key) => Aes128EcbDec::new(&(*key).into())
|
|
||||||
.decrypt_padded_mut::<Pkcs7>(secret_body.en_body_mut()),
|
|
||||||
AesEcbEnum::AES256ECB(key) => Aes256EcbDec::new(&(*key).into())
|
|
||||||
.decrypt_padded_mut::<Pkcs7>(secret_body.en_body_mut()),
|
|
||||||
};
|
};
|
||||||
match rs {
|
match rs {
|
||||||
Ok(buf) => {
|
Ok(buf) => {
|
||||||
let len = buf.len();
|
//校验头部
|
||||||
|
let src_net_packet = NetPacket::new(buf)?;
|
||||||
|
if src_net_packet.source() != net_packet.source() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.destination() != net_packet.destination() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.protocol() != net_packet.protocol() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.transport_protocol() != net_packet.transport_protocol() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.is_gateway() != net_packet.is_gateway() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.source_ttl() != net_packet.source_ttl() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
net_packet.set_data_len(buf.len())?;
|
||||||
|
net_packet.set_payload(src_net_packet.payload())?;
|
||||||
net_packet.set_encrypt_flag(false);
|
net_packet.set_encrypt_flag(false);
|
||||||
//减去末尾的随机数
|
|
||||||
net_packet.set_data_len(HEAD_LEN + len - 4)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => Err(io::Error::new(
|
Err(e) => Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("解密失败:{}", e),
|
format!("aes_ecb解密失败:{}", e),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,53 +121,51 @@ impl AesEcbCipher {
|
|||||||
&self,
|
&self,
|
||||||
net_packet: &mut NetPacket<B>,
|
net_packet: &mut NetPacket<B>,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
let data_len = net_packet.data_len();
|
let mut out = [0u8; 1024 * 5];
|
||||||
let mut iv = [0; 16];
|
let rs = match self.key {
|
||||||
iv[0..4].copy_from_slice(&net_packet.source().octets());
|
AesEcbEnum::AES128ECB(key) => Aes128EcbEnc::new(&key.into())
|
||||||
iv[4..8].copy_from_slice(&net_packet.destination().octets());
|
.encrypt_padded_b2b_mut::<Pkcs7>(net_packet.buffer(), &mut out),
|
||||||
iv[8] = net_packet.protocol().into();
|
AesEcbEnum::AES256ECB(key) => Aes256EcbEnc::new(&key.into())
|
||||||
iv[9] = net_packet.transport_protocol();
|
.encrypt_padded_b2b_mut::<Pkcs7>(net_packet.buffer(), &mut out),
|
||||||
iv[10] = net_packet.is_gateway() as u8;
|
|
||||||
iv[11] = net_packet.source_ttl();
|
|
||||||
if let Some(finger) = &self.finger {
|
|
||||||
iv[12..16].copy_from_slice(&finger.hash[0..4]);
|
|
||||||
net_packet.set_data_len(data_len + 16)?;
|
|
||||||
} else {
|
|
||||||
net_packet.set_data_len(data_len + 4)?;
|
|
||||||
}
|
|
||||||
//先扩充随机数
|
|
||||||
|
|
||||||
let mut secret_body =
|
|
||||||
AesCbcSecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
|
||||||
secret_body.set_random(rand::thread_rng().next_u32());
|
|
||||||
let p_len = secret_body.en_body().len();
|
|
||||||
net_packet.set_data_len_max();
|
|
||||||
let rs = match &self.cipher {
|
|
||||||
AesEcbEnum::AES128ECB(key) => Aes128EcbEnc::new(&(*key).into())
|
|
||||||
.encrypt_padded_mut::<Pkcs7>(net_packet.payload_mut(), p_len),
|
|
||||||
AesEcbEnum::AES256ECB(key) => Aes256EcbEnc::new(&(*key).into())
|
|
||||||
.encrypt_padded_mut::<Pkcs7>(net_packet.payload_mut(), p_len),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return match rs {
|
return match rs {
|
||||||
Ok(buf) => {
|
Ok(buf) => {
|
||||||
let len = buf.len();
|
net_packet.set_data_len(HEAD_LEN + buf.len())?;
|
||||||
if let Some(finger) = &self.finger {
|
net_packet.set_payload(buf)?;
|
||||||
let finger = finger.calculate_finger(&iv[..12], buf);
|
|
||||||
//设置实际长度
|
|
||||||
net_packet.set_data_len(HEAD_LEN + len + finger.len())?;
|
|
||||||
let mut secret_body = AesCbcSecretBody::new(net_packet.payload_mut(), true)?;
|
|
||||||
secret_body.set_finger(&finger)?;
|
|
||||||
} else {
|
|
||||||
net_packet.set_data_len(HEAD_LEN + len)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
net_packet.set_encrypt_flag(true);
|
net_packet.set_encrypt_flag(true);
|
||||||
|
|
||||||
|
if let Some(finger) = &self.finger {
|
||||||
|
let mut nonce_raw = [0; 12];
|
||||||
|
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||||
|
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||||
|
nonce_raw[8] = net_packet.protocol().into();
|
||||||
|
nonce_raw[9] = net_packet.transport_protocol();
|
||||||
|
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||||
|
nonce_raw[11] = net_packet.source_ttl();
|
||||||
|
let finger = finger.calculate_finger(&nonce_raw, buf);
|
||||||
|
let src_data_len = net_packet.data_len();
|
||||||
|
//设置实际长度
|
||||||
|
net_packet.set_data_len(src_data_len + finger.len())?;
|
||||||
|
|
||||||
|
net_packet.buffer_mut()[src_data_len..].copy_from_slice(&finger);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => Err(io::Error::new(
|
Err(e) => Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("加密失败:{}", e),
|
format!("aes_ecb加密失败:{}", e),
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_aes_ecb() {
|
||||||
|
let d = AesEcbCipher::new_128([0; 16], Some(Finger::new("123")));
|
||||||
|
let mut p = NetPacket::new_encrypt([0; 100]).unwrap();
|
||||||
|
let src = p.buffer().to_vec();
|
||||||
|
d.encrypt_ipv4(&mut p).unwrap();
|
||||||
|
d.decrypt_ipv4(&mut p).unwrap();
|
||||||
|
assert_eq!(p.buffer(), &src)
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, KeyInit, Nonce, Tag};
|
|||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
|
||||||
use crate::cipher::finger::Finger;
|
use crate::cipher::finger::Finger;
|
||||||
use crate::protocol::{body::SecretBody, body::ENCRYPTION_RESERVED, NetPacket};
|
use crate::protocol::{body::SecretBody, body::AES_GCM_ENCRYPTION_RESERVED, NetPacket};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AesGcmCipher {
|
pub struct AesGcmCipher {
|
||||||
@@ -44,8 +44,8 @@ impl AesGcmCipher {
|
|||||||
//未加密的数据直接丢弃
|
//未加密的数据直接丢弃
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||||
}
|
}
|
||||||
if net_packet.payload().len() < ENCRYPTION_RESERVED {
|
if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED {
|
||||||
log::error!("数据异常,长度小于{}", ENCRYPTION_RESERVED);
|
log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED);
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
}
|
}
|
||||||
let mut nonce_raw = [0; 12];
|
let mut nonce_raw = [0; 12];
|
||||||
@@ -81,7 +81,7 @@ impl AesGcmCipher {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
net_packet.set_encrypt_flag(false);
|
net_packet.set_encrypt_flag(false);
|
||||||
net_packet.set_data_len(net_packet.data_len() - ENCRYPTION_RESERVED)?;
|
net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
/// net_packet 必须预留足够长度
|
/// net_packet 必须预留足够长度
|
||||||
@@ -90,7 +90,7 @@ impl AesGcmCipher {
|
|||||||
&self,
|
&self,
|
||||||
net_packet: &mut NetPacket<B>,
|
net_packet: &mut NetPacket<B>,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
if net_packet.reserve() < ENCRYPTION_RESERVED {
|
if net_packet.reserve() < AES_GCM_ENCRYPTION_RESERVED {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "too short"));
|
return Err(io::Error::new(io::ErrorKind::Other, "too short"));
|
||||||
}
|
}
|
||||||
let mut nonce_raw = [0; 12];
|
let mut nonce_raw = [0; 12];
|
||||||
@@ -101,7 +101,7 @@ impl AesGcmCipher {
|
|||||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||||
nonce_raw[11] = net_packet.source_ttl();
|
nonce_raw[11] = net_packet.source_ttl();
|
||||||
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
|
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
|
||||||
let data_len = net_packet.data_len() + ENCRYPTION_RESERVED;
|
let data_len = net_packet.data_len() + AES_GCM_ENCRYPTION_RESERVED;
|
||||||
net_packet.set_data_len(data_len)?;
|
net_packet.set_data_len(data_len)?;
|
||||||
let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
||||||
secret_body.set_random(rand::thread_rng().next_u32());
|
secret_body.set_random(rand::thread_rng().next_u32());
|
||||||
|
|||||||
+205
-14
@@ -1,44 +1,136 @@
|
|||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
|
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
|
||||||
use crate::cipher::aes_ecb::AesEcbCipher;
|
use crate::cipher::aes_ecb::AesEcbCipher;
|
||||||
|
|
||||||
|
#[cfg(feature = "aes_cbc")]
|
||||||
|
use crate::cipher::aes_cbc::AesCbcCipher;
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
#[cfg(not(feature = "ring-cipher"))]
|
#[cfg(not(feature = "ring-cipher"))]
|
||||||
use crate::cipher::aes_gcm_cipher::AesGcmCipher;
|
use crate::cipher::aes_gcm_cipher::AesGcmCipher;
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
|
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
|
||||||
|
use crate::cipher::openssl_aes_ecb::AesEcbCipher;
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
#[cfg(feature = "ring-cipher")]
|
#[cfg(feature = "ring-cipher")]
|
||||||
use crate::cipher::ring_aes_gcm_cipher::AesGcmCipher;
|
use crate::cipher::ring_aes_gcm_cipher::AesGcmCipher;
|
||||||
use crate::cipher::{aes_cbc, Finger};
|
#[cfg(feature = "sm4_cbc")]
|
||||||
|
use crate::cipher::sm4_cbc::Sm4CbcCipher;
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
))]
|
||||||
|
use crate::cipher::Finger;
|
||||||
use crate::protocol::NetPacket;
|
use crate::protocol::NetPacket;
|
||||||
use aes_cbc::AesCbcCipher;
|
#[cfg(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
))]
|
||||||
use sha2::Digest;
|
use sha2::Digest;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||||
pub enum CipherModel {
|
pub enum CipherModel {
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
AesGcm,
|
AesGcm,
|
||||||
|
#[cfg(feature = "aes_cbc")]
|
||||||
AesCbc,
|
AesCbc,
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
AesEcb,
|
AesEcb,
|
||||||
|
#[cfg(feature = "sm4_cbc")]
|
||||||
|
Sm4Cbc,
|
||||||
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for CipherModel {
|
impl FromStr for CipherModel {
|
||||||
type Err = String;
|
type Err = String;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
#[cfg(not(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
)))]
|
||||||
|
return Err(format!("not match '{}', no encrypt", s));
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
))]
|
||||||
match s.to_lowercase().trim() {
|
match s.to_lowercase().trim() {
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
"aes_gcm" => Ok(CipherModel::AesGcm),
|
"aes_gcm" => Ok(CipherModel::AesGcm),
|
||||||
|
#[cfg(feature = "aes_cbc")]
|
||||||
"aes_cbc" => Ok(CipherModel::AesCbc),
|
"aes_cbc" => Ok(CipherModel::AesCbc),
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
"aes_ecb" => Ok(CipherModel::AesEcb),
|
"aes_ecb" => Ok(CipherModel::AesEcb),
|
||||||
_ => Err(format!("not match '{}'", s)),
|
#[cfg(feature = "sm4_cbc")]
|
||||||
|
"sm4_cbc" => Ok(CipherModel::Sm4Cbc),
|
||||||
|
_ => {
|
||||||
|
let mut enums = String::new();
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
|
enums.push_str("/aes_gcm");
|
||||||
|
#[cfg(feature = "aes_cbc")]
|
||||||
|
enums.push_str("/aes_cbc");
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
|
enums.push_str("/aes_ecb");
|
||||||
|
#[cfg(feature = "sm4_cbc")]
|
||||||
|
enums.push_str("/sm4_cbc");
|
||||||
|
let str = if enums.is_empty() {
|
||||||
|
"no encrypt"
|
||||||
|
} else {
|
||||||
|
&enums[1..]
|
||||||
|
};
|
||||||
|
Err(format!("not match '{}', enum:{}", s, str))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Cipher {
|
pub enum Cipher {
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
AesGcm((AesGcmCipher, Vec<u8>)),
|
AesGcm((AesGcmCipher, Vec<u8>)),
|
||||||
|
#[cfg(feature = "aes_cbc")]
|
||||||
AesCbc(AesCbcCipher),
|
AesCbc(AesCbcCipher),
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
AesEcb(AesEcbCipher),
|
AesEcb(AesEcbCipher),
|
||||||
|
#[cfg(feature = "sm4_cbc")]
|
||||||
|
Sm4Cbc(Sm4CbcCipher),
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cipher {
|
impl Cipher {
|
||||||
|
#[cfg(not(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
)))]
|
||||||
|
pub fn new_password(
|
||||||
|
_model: CipherModel,
|
||||||
|
_password: Option<String>,
|
||||||
|
_token: Option<String>,
|
||||||
|
) -> Self {
|
||||||
|
Cipher::None
|
||||||
|
}
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
))]
|
||||||
pub fn new_password(
|
pub fn new_password(
|
||||||
model: CipherModel,
|
model: CipherModel,
|
||||||
password: Option<String>,
|
password: Option<String>,
|
||||||
@@ -50,6 +142,7 @@ impl Cipher {
|
|||||||
hasher.update(password.as_bytes());
|
hasher.update(password.as_bytes());
|
||||||
let key: [u8; 32] = hasher.finalize().into();
|
let key: [u8; 32] = hasher.finalize().into();
|
||||||
match model {
|
match model {
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
CipherModel::AesGcm => {
|
CipherModel::AesGcm => {
|
||||||
if password.len() < 8 {
|
if password.len() < 8 {
|
||||||
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
|
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||||
@@ -59,6 +152,7 @@ impl Cipher {
|
|||||||
Cipher::AesGcm((aes, key.to_vec()))
|
Cipher::AesGcm((aes, key.to_vec()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "aes_cbc")]
|
||||||
CipherModel::AesCbc => {
|
CipherModel::AesCbc => {
|
||||||
if password.len() < 8 {
|
if password.len() < 8 {
|
||||||
let aes = AesCbcCipher::new_128(key[..16].try_into().unwrap(), finger);
|
let aes = AesCbcCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||||
@@ -68,6 +162,7 @@ impl Cipher {
|
|||||||
Cipher::AesCbc(aes)
|
Cipher::AesCbc(aes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
CipherModel::AesEcb => {
|
CipherModel::AesEcb => {
|
||||||
if password.len() < 8 {
|
if password.len() < 8 {
|
||||||
let aes = AesEcbCipher::new_128(key[..16].try_into().unwrap(), finger);
|
let aes = AesEcbCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||||
@@ -77,18 +172,43 @@ impl Cipher {
|
|||||||
Cipher::AesEcb(aes)
|
Cipher::AesEcb(aes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "sm4_cbc")]
|
||||||
|
CipherModel::Sm4Cbc => {
|
||||||
|
let aes = Sm4CbcCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||||
|
Cipher::Sm4Cbc(aes)
|
||||||
|
}
|
||||||
|
CipherModel::None => Cipher::None,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Cipher::None
|
Cipher::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
)))]
|
||||||
|
pub fn new_key(_key: [u8; 32], _token: String) -> io::Result<Self> {
|
||||||
|
Err(io::Error::new(io::ErrorKind::Other, "key error"))
|
||||||
|
}
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
))]
|
||||||
pub fn new_key(key: [u8; 32], token: String) -> io::Result<Self> {
|
pub fn new_key(key: [u8; 32], token: String) -> io::Result<Self> {
|
||||||
let finger = Some(Finger::new(&token));
|
let finger = Some(Finger::new(&token));
|
||||||
match key.len() {
|
match key.len() {
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
16 => {
|
16 => {
|
||||||
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
|
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||||
Ok(Cipher::AesGcm((aes, key[..16].to_vec())))
|
Ok(Cipher::AesGcm((aes, key[..16].to_vec())))
|
||||||
}
|
}
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
32 => {
|
32 => {
|
||||||
let aes = AesGcmCipher::new_256(key, finger);
|
let aes = AesGcmCipher::new_256(key, finger);
|
||||||
Ok(Cipher::AesGcm((aes, key.to_vec())))
|
Ok(Cipher::AesGcm((aes, key.to_vec())))
|
||||||
@@ -101,9 +221,14 @@ impl Cipher {
|
|||||||
net_packet: &mut NetPacket<B>,
|
net_packet: &mut NetPacket<B>,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.decrypt_ipv4(net_packet),
|
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.decrypt_ipv4(net_packet),
|
||||||
|
#[cfg(feature = "aes_cbc")]
|
||||||
Cipher::AesCbc(aes_cbc) => aes_cbc.decrypt_ipv4(net_packet),
|
Cipher::AesCbc(aes_cbc) => aes_cbc.decrypt_ipv4(net_packet),
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
Cipher::AesEcb(aes_ecb) => aes_ecb.decrypt_ipv4(net_packet),
|
Cipher::AesEcb(aes_ecb) => aes_ecb.decrypt_ipv4(net_packet),
|
||||||
|
#[cfg(feature = "sm4_cbc")]
|
||||||
|
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.decrypt_ipv4(net_packet),
|
||||||
Cipher::None => {
|
Cipher::None => {
|
||||||
if net_packet.is_encrypt() {
|
if net_packet.is_encrypt() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "not key"));
|
return Err(io::Error::new(io::ErrorKind::Other, "not key"));
|
||||||
@@ -112,35 +237,101 @@ impl Cipher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
)))]
|
||||||
|
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
_net_packet: &mut NetPacket<B>,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
))]
|
||||||
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
net_packet: &mut NetPacket<B>,
|
net_packet: &mut NetPacket<B>,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.encrypt_ipv4(net_packet),
|
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.encrypt_ipv4(net_packet),
|
||||||
|
#[cfg(feature = "aes_cbc")]
|
||||||
Cipher::AesCbc(aes_cbc) => aes_cbc.encrypt_ipv4(net_packet),
|
Cipher::AesCbc(aes_cbc) => aes_cbc.encrypt_ipv4(net_packet),
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
Cipher::AesEcb(aes_ecb) => aes_ecb.encrypt_ipv4(net_packet),
|
Cipher::AesEcb(aes_ecb) => aes_ecb.encrypt_ipv4(net_packet),
|
||||||
|
#[cfg(feature = "sm4_cbc")]
|
||||||
|
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.encrypt_ipv4(net_packet),
|
||||||
Cipher::None => Ok(()),
|
Cipher::None => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
)))]
|
||||||
|
pub fn check_finger<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
_net_packet: &NetPacket<B>,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
))]
|
||||||
pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> io::Result<()> {
|
pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> io::Result<()> {
|
||||||
let finger = match self {
|
match self {
|
||||||
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.finger.as_ref(),
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
Cipher::AesCbc(aes_cbc) => aes_cbc.finger.as_ref(),
|
Cipher::AesGcm((aes_gcm, _)) => aes_gcm
|
||||||
Cipher::AesEcb(aes_ecb) => aes_ecb.finger.as_ref(),
|
.finger
|
||||||
Cipher::None => None,
|
.as_ref()
|
||||||
};
|
.map(|f| f.check_finger(net_packet))
|
||||||
if let Some(finger) = finger {
|
.unwrap_or(Ok(())),
|
||||||
finger.check_finger(net_packet)
|
#[cfg(feature = "aes_cbc")]
|
||||||
} else {
|
Cipher::AesCbc(aes_cbc) => aes_cbc
|
||||||
Ok(())
|
.finger
|
||||||
|
.as_ref()
|
||||||
|
.map(|f| f.check_finger(net_packet))
|
||||||
|
.unwrap_or(Ok(())),
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
|
Cipher::AesEcb(aes_ecb) => aes_ecb
|
||||||
|
.finger
|
||||||
|
.as_ref()
|
||||||
|
.map(|f| f.check_finger(net_packet))
|
||||||
|
.unwrap_or(Ok(())),
|
||||||
|
#[cfg(feature = "sm4_cbc")]
|
||||||
|
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc
|
||||||
|
.finger
|
||||||
|
.as_ref()
|
||||||
|
.map(|f| f.check_finger(net_packet))
|
||||||
|
.unwrap_or(Ok(())),
|
||||||
|
Cipher::None => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn key(&self) -> Option<&[u8]> {
|
pub fn key(&self) -> Option<&[u8]> {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
Cipher::AesGcm((_, key)) => Some(key),
|
Cipher::AesGcm((_, key)) => Some(key),
|
||||||
|
#[cfg(feature = "aes_cbc")]
|
||||||
Cipher::AesCbc(aes_cbc) => Some(aes_cbc.key()),
|
Cipher::AesCbc(aes_cbc) => Some(aes_cbc.key()),
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
Cipher::AesEcb(aes_ecb) => Some(aes_ecb.key()),
|
Cipher::AesEcb(aes_ecb) => Some(aes_ecb.key()),
|
||||||
|
#[cfg(feature = "sm4_cbc")]
|
||||||
|
Cipher::Sm4Cbc(sm4_cbc) => Some(sm4_cbc.key()),
|
||||||
Cipher::None => None,
|
Cipher::None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-1
@@ -1,14 +1,37 @@
|
|||||||
|
#[cfg(feature = "aes_cbc")]
|
||||||
mod aes_cbc;
|
mod aes_cbc;
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
|
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
|
||||||
mod aes_ecb;
|
mod aes_ecb;
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
#[cfg(not(feature = "ring-cipher"))]
|
#[cfg(not(feature = "ring-cipher"))]
|
||||||
mod aes_gcm_cipher;
|
mod aes_gcm_cipher;
|
||||||
mod cipher;
|
mod cipher;
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
))]
|
||||||
mod finger;
|
mod finger;
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
|
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
|
||||||
|
mod openssl_aes_ecb;
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
#[cfg(feature = "ring-cipher")]
|
#[cfg(feature = "ring-cipher")]
|
||||||
mod ring_aes_gcm_cipher;
|
mod ring_aes_gcm_cipher;
|
||||||
mod rsa_cipher;
|
mod rsa_cipher;
|
||||||
|
#[cfg(feature = "sm4_cbc")]
|
||||||
|
mod sm4_cbc;
|
||||||
pub use cipher::Cipher;
|
pub use cipher::Cipher;
|
||||||
pub use cipher::CipherModel;
|
pub use cipher::CipherModel;
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "aes_gcm",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
))]
|
||||||
pub use finger::Finger;
|
pub use finger::Finger;
|
||||||
pub use rsa_cipher::RsaCipher;
|
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 let Some(finger) = &self.finger {
|
||||||
|
let mut nonce_raw = [0; 12];
|
||||||
|
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||||
|
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||||
|
nonce_raw[8] = net_packet.protocol().into();
|
||||||
|
nonce_raw[9] = net_packet.transport_protocol();
|
||||||
|
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||||
|
nonce_raw[11] = net_packet.source_ttl();
|
||||||
|
let len = net_packet.payload().len();
|
||||||
|
if len < 12 {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data len err"));
|
||||||
|
}
|
||||||
|
let secret_body = &net_packet.payload()[..len - 12];
|
||||||
|
let finger = finger.calculate_finger(&nonce_raw, secret_body);
|
||||||
|
if &finger != &net_packet.payload()[len - 12..] {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
||||||
|
}
|
||||||
|
net_packet.set_data_len(net_packet.data_len() - finger.len())?;
|
||||||
|
}
|
||||||
|
if net_packet.payload().len() < 16 {
|
||||||
|
log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16);
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
let input = net_packet.payload();
|
||||||
|
let mut out = [0u8; 1024 * 5];
|
||||||
|
let mut out_len = 0;
|
||||||
|
let ctx = self.de_ctx;
|
||||||
|
unsafe {
|
||||||
|
let out_ptr = out.as_mut_ptr();
|
||||||
|
let in_len = input.len() as c_int;
|
||||||
|
openssl_sys::EVP_DecryptUpdate(ctx, out_ptr, &mut out_len, input.as_ptr(), in_len);
|
||||||
|
let mut last_len = 0;
|
||||||
|
openssl_sys::EVP_DecryptFinal_ex(ctx, out_ptr.offset(out_len as isize), &mut last_len);
|
||||||
|
out_len += last_len;
|
||||||
|
}
|
||||||
|
let out_len = out_len as usize;
|
||||||
|
let text = &out[..out_len];
|
||||||
|
{
|
||||||
|
//校验头部
|
||||||
|
let src_net_packet = NetPacket::new(text)?;
|
||||||
|
if src_net_packet.source() != net_packet.source() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.destination() != net_packet.destination() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.protocol() != net_packet.protocol() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.transport_protocol() != net_packet.transport_protocol() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.is_gateway() != net_packet.is_gateway() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.source_ttl() != net_packet.source_ttl() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
net_packet.set_encrypt_flag(false);
|
||||||
|
net_packet.set_data_len(out_len)?;
|
||||||
|
net_packet.set_payload(&text[12..])?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
/// net_packet 必须预留足够长度 大于 12+16+16
|
||||||
|
/// data_len是有效载荷的长度
|
||||||
|
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
net_packet: &mut NetPacket<B>,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
let input = net_packet.buffer();
|
||||||
|
let mut out = [0u8; 1024 * 5];
|
||||||
|
let mut out_len = 0;
|
||||||
|
let ctx = self.en_ctx;
|
||||||
|
//将头部也参与加密
|
||||||
|
unsafe {
|
||||||
|
let out_ptr = out.as_mut_ptr();
|
||||||
|
let in_len = input.len() as c_int;
|
||||||
|
openssl_sys::EVP_EncryptUpdate(ctx, out_ptr, &mut out_len, input.as_ptr(), in_len);
|
||||||
|
let mut last_len = 0;
|
||||||
|
openssl_sys::EVP_EncryptFinal_ex(ctx, out_ptr.offset(out_len as isize), &mut last_len);
|
||||||
|
out_len += last_len;
|
||||||
|
}
|
||||||
|
let out_len = out_len as usize;
|
||||||
|
if out_len == 0 {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "ciphertext len err"));
|
||||||
|
}
|
||||||
|
//密文
|
||||||
|
let ciphertext = &out[..out_len];
|
||||||
|
net_packet.set_data_len(HEAD_LEN + out_len)?;
|
||||||
|
net_packet.payload_mut().copy_from_slice(ciphertext);
|
||||||
|
net_packet.set_encrypt_flag(true);
|
||||||
|
if let Some(finger) = &self.finger {
|
||||||
|
let mut nonce_raw = [0; 12];
|
||||||
|
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||||
|
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||||
|
nonce_raw[8] = net_packet.protocol().into();
|
||||||
|
nonce_raw[9] = net_packet.transport_protocol();
|
||||||
|
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||||
|
nonce_raw[11] = net_packet.source_ttl();
|
||||||
|
let finger = finger.calculate_finger(&nonce_raw, ciphertext);
|
||||||
|
let src_data_len = net_packet.data_len();
|
||||||
|
//设置实际长度
|
||||||
|
net_packet.set_data_len(src_data_len + finger.len())?;
|
||||||
|
|
||||||
|
net_packet.buffer_mut()[src_data_len..].copy_from_slice(&finger);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_openssl_aes_ecb() {
|
||||||
|
let d = AesEcbCipher::new_128([0; 16], Some(Finger::new("123")));
|
||||||
|
let mut p = NetPacket::new_encrypt([0; 100]).unwrap();
|
||||||
|
d.encrypt_ipv4(&mut p).unwrap();
|
||||||
|
d.decrypt_ipv4(&mut p).unwrap();
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ use ring::aead;
|
|||||||
use ring::aead::{LessSafeKey, UnboundKey};
|
use ring::aead::{LessSafeKey, UnboundKey};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crate::protocol::body::{SecretBody, ENCRYPTION_RESERVED};
|
use crate::protocol::body::{SecretBody, AES_GCM_ENCRYPTION_RESERVED};
|
||||||
use crate::protocol::NetPacket;
|
use crate::protocol::NetPacket;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -58,8 +58,8 @@ impl AesGcmCipher {
|
|||||||
//未加密的数据直接丢弃
|
//未加密的数据直接丢弃
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||||
}
|
}
|
||||||
if net_packet.payload().len() < ENCRYPTION_RESERVED {
|
if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED {
|
||||||
log::error!("数据异常,长度小于{}", ENCRYPTION_RESERVED);
|
log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED);
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
}
|
}
|
||||||
let mut nonce_raw = [0; 12];
|
let mut nonce_raw = [0; 12];
|
||||||
@@ -93,7 +93,7 @@ impl AesGcmCipher {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
net_packet.set_encrypt_flag(false);
|
net_packet.set_encrypt_flag(false);
|
||||||
net_packet.set_data_len(net_packet.data_len() - ENCRYPTION_RESERVED)?;
|
net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
/// net_packet 必须预留足够长度
|
/// net_packet 必须预留足够长度
|
||||||
@@ -111,7 +111,7 @@ impl AesGcmCipher {
|
|||||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||||
nonce_raw[11] = net_packet.source_ttl();
|
nonce_raw[11] = net_packet.source_ttl();
|
||||||
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
|
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
|
||||||
let data_len = net_packet.data_len() + ENCRYPTION_RESERVED;
|
let data_len = net_packet.data_len() + AES_GCM_ENCRYPTION_RESERVED;
|
||||||
net_packet.set_data_len(data_len)?;
|
net_packet.set_data_len(data_len)?;
|
||||||
let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
||||||
secret_body.set_random(rand::thread_rng().next_u32());
|
secret_body.set_random(rand::thread_rng().next_u32());
|
||||||
|
|||||||
@@ -1,23 +1,32 @@
|
|||||||
use crate::protocol::body::{RsaSecretBody, ENCRYPTION_RESERVED};
|
|
||||||
use crate::protocol::NetPacket;
|
use crate::protocol::NetPacket;
|
||||||
use rand::Rng;
|
|
||||||
use rsa::pkcs8::der::Decode;
|
|
||||||
use rsa::{PublicKey, RsaPublicKey};
|
|
||||||
use sha2::Digest;
|
|
||||||
use spki::{DecodePublicKey, EncodePublicKey};
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
|
use crate::protocol::body::{RsaSecretBody, RSA_ENCRYPTION_RESERVED};
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
|
use rand::Rng;
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
|
use rsa::pkcs8::der::Decode;
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
|
use rsa::RsaPublicKey;
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
|
use sha2::Digest;
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
|
use spki::{DecodePublicKey, EncodePublicKey};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RsaCipher {
|
pub struct RsaCipher {
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
inner: Inner,
|
inner: Inner,
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Inner {
|
struct Inner {
|
||||||
public_key: RsaPublicKey,
|
public_key: RsaPublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RsaCipher {
|
impl RsaCipher {
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
pub fn new(der: &[u8]) -> io::Result<Self> {
|
pub fn new(der: &[u8]) -> io::Result<Self> {
|
||||||
match RsaPublicKey::from_public_key_der(der) {
|
match RsaPublicKey::from_public_key_der(der) {
|
||||||
Ok(public_key) => {
|
Ok(public_key) => {
|
||||||
@@ -30,9 +39,14 @@ impl RsaCipher {
|
|||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(feature = "server_encrypt"))]
|
||||||
|
pub fn new(_der: &[u8]) -> io::Result<Self> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
pub fn finger(&self) -> io::Result<String> {
|
pub fn finger(&self) -> io::Result<String> {
|
||||||
match self.inner.public_key.to_public_key_der() {
|
match self.inner.public_key.to_public_key_der() {
|
||||||
Ok(der) => match rsa::pkcs8::SubjectPublicKeyInfo::from_der(der.as_bytes()) {
|
Ok(der) => match rsa::pkcs8::SubjectPublicKeyInfoRef::from_der(der.as_bytes()) {
|
||||||
Ok(spki) => match spki.fingerprint_base64() {
|
Ok(spki) => match spki.fingerprint_base64() {
|
||||||
Ok(finger) => Ok(finger),
|
Ok(finger) => Ok(finger),
|
||||||
Err(e) => Err(io::Error::new(
|
Err(e) => Err(io::Error::new(
|
||||||
@@ -51,18 +65,30 @@ impl RsaCipher {
|
|||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(feature = "server_encrypt"))]
|
||||||
|
pub fn finger(&self) -> io::Result<String> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RsaCipher {
|
impl RsaCipher {
|
||||||
|
#[cfg(not(feature = "server_encrypt"))]
|
||||||
|
pub fn encrypt<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
_net_packet: &mut NetPacket<B>,
|
||||||
|
) -> io::Result<NetPacket<Vec<u8>>> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
/// net_packet 必须预留足够长度
|
/// net_packet 必须预留足够长度
|
||||||
pub fn encrypt<B: AsRef<[u8]> + AsMut<[u8]>>(
|
pub fn encrypt<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
net_packet: &mut NetPacket<B>,
|
net_packet: &mut NetPacket<B>,
|
||||||
) -> io::Result<NetPacket<Vec<u8>>> {
|
) -> io::Result<NetPacket<Vec<u8>>> {
|
||||||
if net_packet.reserve() < ENCRYPTION_RESERVED {
|
if net_packet.reserve() < RSA_ENCRYPTION_RESERVED {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "too short"));
|
return Err(io::Error::new(io::ErrorKind::Other, "too short"));
|
||||||
}
|
}
|
||||||
let data_len = net_packet.data_len() + ENCRYPTION_RESERVED;
|
let data_len = net_packet.data_len() + RSA_ENCRYPTION_RESERVED;
|
||||||
net_packet.set_data_len(data_len)?;
|
net_packet.set_data_len(data_len)?;
|
||||||
let mut nonce_raw = [0; 12];
|
let mut nonce_raw = [0; 12];
|
||||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||||
@@ -83,7 +109,7 @@ impl RsaCipher {
|
|||||||
secret_body.set_finger(&key[16..])?;
|
secret_body.set_finger(&key[16..])?;
|
||||||
match self.inner.public_key.encrypt(
|
match self.inner.public_key.encrypt(
|
||||||
&mut rng,
|
&mut rng,
|
||||||
rsa::PaddingScheme::PKCS1v15Encrypt,
|
rsa::pkcs1v15::Pkcs1v15Encrypt,
|
||||||
secret_body.buffer(),
|
secret_body.buffer(),
|
||||||
) {
|
) {
|
||||||
Ok(enc_data) => {
|
Ok(enc_data) => {
|
||||||
|
|||||||
@@ -0,0 +1,171 @@
|
|||||||
|
use crate::cipher::Finger;
|
||||||
|
use crate::protocol::{NetPacket, HEAD_LEN};
|
||||||
|
use libsm::sm4::cipher_mode::CipherMode;
|
||||||
|
use libsm::sm4::Sm4CipherMode;
|
||||||
|
use rand::RngCore;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
pub struct Sm4CbcCipher {
|
||||||
|
key: [u8; 16],
|
||||||
|
pub(crate) cipher: Sm4CipherMode,
|
||||||
|
pub(crate) finger: Option<Finger>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Sm4CbcCipher {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
let cipher = Sm4CipherMode::new(&self.key, CipherMode::Cbc).unwrap();
|
||||||
|
Self {
|
||||||
|
key: self.key,
|
||||||
|
cipher,
|
||||||
|
finger: self.finger.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sm4CbcCipher {
|
||||||
|
pub fn key(&self) -> &[u8] {
|
||||||
|
&self.key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sm4CbcCipher {
|
||||||
|
pub fn new_128(key: [u8; 16], finger: Option<Finger>) -> Self {
|
||||||
|
let cipher = Sm4CipherMode::new(&key, CipherMode::Cbc).unwrap();
|
||||||
|
Self {
|
||||||
|
key,
|
||||||
|
cipher,
|
||||||
|
finger,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
net_packet: &mut NetPacket<B>,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
if !net_packet.is_encrypt() {
|
||||||
|
//未加密的数据直接丢弃
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(finger) = &self.finger {
|
||||||
|
let mut nonce_raw = [0; 12];
|
||||||
|
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||||
|
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||||
|
nonce_raw[8] = net_packet.protocol().into();
|
||||||
|
nonce_raw[9] = net_packet.transport_protocol();
|
||||||
|
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||||
|
nonce_raw[11] = net_packet.source_ttl();
|
||||||
|
let len = net_packet.payload().len();
|
||||||
|
if len < 12 {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "payload len <12"));
|
||||||
|
}
|
||||||
|
let secret_body = &net_packet.payload()[..len - 12];
|
||||||
|
let finger = finger.calculate_finger(&nonce_raw, secret_body);
|
||||||
|
if &finger != &net_packet.payload()[len - 12..] {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
||||||
|
}
|
||||||
|
net_packet.set_data_len(net_packet.data_len() - finger.len())?;
|
||||||
|
}
|
||||||
|
let payload = net_packet.payload();
|
||||||
|
let len = payload.len();
|
||||||
|
if len < 16 || len > 1024 * 4 {
|
||||||
|
log::error!("数据异常,长度{}小于16或大于4096", len);
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
let mut out = [0u8; 1024 * 4];
|
||||||
|
let data = &payload[..len - 16];
|
||||||
|
let iv = &payload[len - 16..];
|
||||||
|
match self.cipher.decrypt(data, iv, &mut out) {
|
||||||
|
Ok(len) => {
|
||||||
|
let src_net_packet = NetPacket::new(&out[..len])?;
|
||||||
|
if src_net_packet.source() != net_packet.source() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.destination() != net_packet.destination() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.protocol() != net_packet.protocol() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.transport_protocol() != net_packet.transport_protocol() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.is_gateway() != net_packet.is_gateway() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
if src_net_packet.source_ttl() != net_packet.source_ttl() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
net_packet.set_data_len(len)?;
|
||||||
|
net_packet.set_payload(src_net_packet.payload())?;
|
||||||
|
net_packet.set_encrypt_flag(false);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(e) => Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("sm4_cbc解密失败:{}", e),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// net_packet 必须预留足够长度
|
||||||
|
/// data_len是有效载荷的长度
|
||||||
|
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
net_packet: &mut NetPacket<B>,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
let mut out = [0u8; 1024 * 4];
|
||||||
|
let mut iv = [0u8; 16];
|
||||||
|
rand::thread_rng().fill_bytes(&mut iv);
|
||||||
|
if net_packet.data_len() > 1024 * 4 - 32 {
|
||||||
|
log::error!(
|
||||||
|
"数据异常,长度{}大于1024 * 4 - 32",
|
||||||
|
net_packet.buffer().len()
|
||||||
|
);
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
||||||
|
}
|
||||||
|
match self.cipher.encrypt(net_packet.buffer(), &iv, &mut out) {
|
||||||
|
Ok(len) => {
|
||||||
|
net_packet.set_data_len(HEAD_LEN + len + 16)?;
|
||||||
|
net_packet.payload_mut()[..len].copy_from_slice(&out[..len]);
|
||||||
|
net_packet.payload_mut()[len..].copy_from_slice(&iv);
|
||||||
|
if let Some(finger) = &self.finger {
|
||||||
|
let mut nonce_raw = [0; 12];
|
||||||
|
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||||
|
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
||||||
|
nonce_raw[8] = net_packet.protocol().into();
|
||||||
|
nonce_raw[9] = net_packet.transport_protocol();
|
||||||
|
nonce_raw[10] = net_packet.is_gateway() as u8;
|
||||||
|
nonce_raw[11] = net_packet.source_ttl();
|
||||||
|
let finger = finger.calculate_finger(&nonce_raw, net_packet.payload());
|
||||||
|
let src_data_len = net_packet.data_len();
|
||||||
|
//设置实际长度
|
||||||
|
net_packet.set_data_len(src_data_len + finger.len())?;
|
||||||
|
|
||||||
|
net_packet.buffer_mut()[src_data_len..].copy_from_slice(&finger);
|
||||||
|
}
|
||||||
|
net_packet.set_encrypt_flag(true);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(e) => Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("sm4_cbc加密失败:{}", e),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sm4_ecb() {
|
||||||
|
let d = Sm4CbcCipher::new_128([0; 16], Some(Finger::new("123")));
|
||||||
|
let mut p = NetPacket::new_encrypt([1; 1024]).unwrap();
|
||||||
|
let src = p.buffer().to_vec();
|
||||||
|
d.encrypt_ipv4(&mut p).unwrap();
|
||||||
|
d.decrypt_ipv4(&mut p).unwrap();
|
||||||
|
assert_eq!(p.buffer(), &src);
|
||||||
|
let d = Sm4CbcCipher::new_128([0; 16], None);
|
||||||
|
let mut p = NetPacket::new_encrypt([1; 102]).unwrap();
|
||||||
|
let src = p.buffer().to_vec();
|
||||||
|
d.encrypt_ipv4(&mut p).unwrap();
|
||||||
|
d.decrypt_ipv4(&mut p).unwrap();
|
||||||
|
assert_eq!(p.buffer(), &src)
|
||||||
|
}
|
||||||
+87
-45
@@ -1,13 +1,14 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::net::TcpStream;
|
||||||
|
use std::net::UdpSocket;
|
||||||
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
use dashmap::DashMap;
|
use parking_lot::{Mutex, RwLock};
|
||||||
use parking_lot::Mutex;
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use tokio::net::{TcpStream, UdpSocket};
|
|
||||||
use tokio::sync::mpsc::channel;
|
use tokio::sync::mpsc::channel;
|
||||||
|
|
||||||
use crate::channel::channel::{Channel, Context};
|
use crate::channel::channel::{Channel, Context};
|
||||||
@@ -50,7 +51,7 @@ pub struct Vnt {
|
|||||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||||
nat_test: NatTest,
|
nat_test: NatTest,
|
||||||
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
||||||
peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>>,
|
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VntUtil {
|
pub struct VntUtil {
|
||||||
@@ -65,17 +66,27 @@ pub struct VntUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VntUtil {
|
impl VntUtil {
|
||||||
pub async fn new(config: Config) -> io::Result<VntUtil> {
|
pub fn new(config: Config) -> io::Result<VntUtil> {
|
||||||
let main_channel = UdpSocket::bind("0.0.0.0:0").await?;
|
//单个udp用同步的性能更好,但是代理和多端口监听用异步更方便,这里将两者结合起来
|
||||||
let main_channel_ipv6 = match UdpSocket::bind("[::]:0").await {
|
let main_channel = UdpSocket::bind(format!("0.0.0.0:{}", config.port))?;
|
||||||
Ok(main_channel_ipv6) => Some(main_channel_ipv6),
|
main_channel.set_write_timeout(Some(Duration::from_secs(5)))?;
|
||||||
Err(e) => {
|
main_channel.set_read_timeout(Some(Duration::from_secs(2)))?;
|
||||||
log::warn!("绑定ipv6地址失败:{}", e);
|
let main_channel_ipv6 = if config.punch_model != PunchModel::IPv4 {
|
||||||
None
|
match UdpSocket::bind(format!("[::]:{}", config.port)) {
|
||||||
|
Ok(main_channel_ipv6) => {
|
||||||
|
main_channel_ipv6.set_write_timeout(Some(Duration::from_secs(5)))?;
|
||||||
|
Some(main_channel_ipv6)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("绑定ipv6地址失败:{}", e);
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
};
|
};
|
||||||
let server_cipher = if config.server_encrypt {
|
let server_cipher = if config.server_encrypt {
|
||||||
let mut key = [0 as u8; 32];
|
let mut key = [0u8; 32];
|
||||||
rand::thread_rng().fill(&mut key);
|
rand::thread_rng().fill(&mut key);
|
||||||
Cipher::new_key(key, config.token.clone())?
|
Cipher::new_key(key, config.token.clone())?
|
||||||
} else {
|
} else {
|
||||||
@@ -93,28 +104,28 @@ impl VntUtil {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
///链接
|
///链接
|
||||||
pub async fn connect(&mut self) -> io::Result<()> {
|
pub fn connect(&mut self) -> io::Result<()> {
|
||||||
if self.config.tcp {
|
if self.config.tcp {
|
||||||
let tcp = TcpStream::connect(self.config.server_address).await?;
|
let tcp = TcpStream::connect(self.config.server_address)?;
|
||||||
|
tcp.set_read_timeout(Some(Duration::from_secs(10)))?;
|
||||||
let _ = self.main_tcp_channel.insert(tcp);
|
let _ = self.main_tcp_channel.insert(tcp);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
///握手 用于获取公钥
|
///握手 用于获取公钥
|
||||||
pub async fn handshake(&mut self) -> Result<Option<RsaCipher>, HandshakeEnum> {
|
pub fn handshake(&mut self) -> Result<Option<RsaCipher>, HandshakeEnum> {
|
||||||
let rsa_cipher = handshake_handler::handshake(
|
let rsa_cipher = handshake_handler::handshake(
|
||||||
&self.main_channel,
|
&self.main_channel,
|
||||||
self.main_tcp_channel.as_mut(),
|
self.main_tcp_channel.as_mut(),
|
||||||
self.config.server_address,
|
self.config.server_address,
|
||||||
self.config.server_encrypt,
|
self.config.server_encrypt,
|
||||||
)
|
)?;
|
||||||
.await?;
|
|
||||||
self.rsa_cipher = rsa_cipher.clone();
|
self.rsa_cipher = rsa_cipher.clone();
|
||||||
Ok(rsa_cipher)
|
Ok(rsa_cipher)
|
||||||
}
|
}
|
||||||
/// 加密握手 用于同步密钥
|
/// 加密握手 用于同步密钥
|
||||||
pub async fn secret_handshake(&mut self) -> Result<(), HandshakeEnum> {
|
pub fn secret_handshake(&mut self) -> Result<(), HandshakeEnum> {
|
||||||
handshake_handler::secret_handshake(
|
handshake_handler::secret_handshake(
|
||||||
&self.main_channel,
|
&self.main_channel,
|
||||||
self.main_tcp_channel.as_mut(),
|
self.main_tcp_channel.as_mut(),
|
||||||
@@ -123,10 +134,9 @@ impl VntUtil {
|
|||||||
&self.server_cipher,
|
&self.server_cipher,
|
||||||
self.config.token.clone(),
|
self.config.token.clone(),
|
||||||
)
|
)
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
/// 注册
|
/// 注册
|
||||||
pub async fn register(&mut self) -> Result<RegResponse, ReqEnum> {
|
pub fn register(&mut self) -> Result<RegResponse, ReqEnum> {
|
||||||
match registration_handler::registration(
|
match registration_handler::registration(
|
||||||
&self.main_channel,
|
&self.main_channel,
|
||||||
self.main_tcp_channel.as_mut(),
|
self.main_tcp_channel.as_mut(),
|
||||||
@@ -137,9 +147,7 @@ impl VntUtil {
|
|||||||
self.config.name.clone(),
|
self.config.name.clone(),
|
||||||
self.config.ip.unwrap_or(Ipv4Addr::UNSPECIFIED),
|
self.config.ip.unwrap_or(Ipv4Addr::UNSPECIFIED),
|
||||||
self.config.password.is_some(),
|
self.config.password.is_some(),
|
||||||
)
|
) {
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
let _ = self.response.insert(res.clone());
|
let _ = self.response.insert(res.clone());
|
||||||
Ok(res)
|
Ok(res)
|
||||||
@@ -181,7 +189,7 @@ impl VntUtil {
|
|||||||
if self.config.password.is_none() {
|
if self.config.password.is_none() {
|
||||||
1450
|
1450
|
||||||
} else {
|
} else {
|
||||||
1420
|
1410
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(mtu) => mtu,
|
Some(mtu) => mtu,
|
||||||
@@ -205,6 +213,8 @@ impl VntUtil {
|
|||||||
Ok(driver_info)
|
Ok(driver_info)
|
||||||
}
|
}
|
||||||
pub async fn build(self) -> crate::Result<Vnt> {
|
pub async fn build(self) -> crate::Result<Vnt> {
|
||||||
|
//将读的超时时间清空
|
||||||
|
self.main_channel.set_read_timeout(None)?;
|
||||||
let response = match self.response {
|
let response = match self.response {
|
||||||
None => {
|
None => {
|
||||||
return Err(Error::Stop("response None".to_string()));
|
return Err(Error::Stop("response None".to_string()));
|
||||||
@@ -239,7 +249,7 @@ impl VntUtil {
|
|||||||
let (cone_sender, cone_receiver) = channel(3);
|
let (cone_sender, cone_receiver) = channel(3);
|
||||||
let (symmetric_sender, symmetric_receiver) = channel(2);
|
let (symmetric_sender, symmetric_receiver) = channel(2);
|
||||||
let (tcp_sender, tcp) = if let Some(main_tcp_channel) = self.main_tcp_channel {
|
let (tcp_sender, tcp) = if let Some(main_tcp_channel) = self.main_tcp_channel {
|
||||||
let (tcp_sender, tcp_receiver) = channel::<Vec<u8>>(100);
|
let (tcp_sender, tcp_receiver) = std::sync::mpsc::sync_channel::<Vec<u8>>(100);
|
||||||
(Some(tcp_sender), Some((main_tcp_channel, tcp_receiver)))
|
(Some(tcp_sender), Some((main_tcp_channel, tcp_receiver)))
|
||||||
} else {
|
} else {
|
||||||
(None, None)
|
(None, None)
|
||||||
@@ -250,6 +260,7 @@ impl VntUtil {
|
|||||||
tcp_sender,
|
tcp_sender,
|
||||||
current_device.clone(),
|
current_device.clone(),
|
||||||
1,
|
1,
|
||||||
|
config.first_latency,
|
||||||
);
|
);
|
||||||
let punch = Punch::new(context.clone(), config.punch_model);
|
let punch = Punch::new(context.clone(), config.punch_model);
|
||||||
let idle = Idle::new(Duration::from_secs(16), context.clone());
|
let idle = Idle::new(Duration::from_secs(16), context.clone());
|
||||||
@@ -266,9 +277,11 @@ impl VntUtil {
|
|||||||
));
|
));
|
||||||
let device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>> =
|
let device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>> =
|
||||||
Arc::new(Mutex::new((response.epoch, response.device_info_list)));
|
Arc::new(Mutex::new((response.epoch, response.device_info_list)));
|
||||||
let peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>> = Arc::new(DashMap::new());
|
let peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>> =
|
||||||
|
Arc::new(RwLock::new(HashMap::with_capacity(16)));
|
||||||
let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected));
|
let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected));
|
||||||
|
let public_ip = response.public_ip;
|
||||||
|
let public_port = response.public_port;
|
||||||
let local_port = context.main_local_ipv4_port().unwrap_or(0);
|
let local_port = context.main_local_ipv4_port().unwrap_or(0);
|
||||||
|
|
||||||
let local_ipv4_addr = crate::nat::local_ipv4_addr(local_port);
|
let local_ipv4_addr = crate::nat::local_ipv4_addr(local_port);
|
||||||
@@ -277,23 +290,26 @@ impl VntUtil {
|
|||||||
// NAT检测
|
// NAT检测
|
||||||
let nat_test = NatTest::new(
|
let nat_test = NatTest::new(
|
||||||
config.stun_server.clone(),
|
config.stun_server.clone(),
|
||||||
response.public_ip,
|
public_ip,
|
||||||
response.public_port,
|
public_port,
|
||||||
local_ipv4_addr,
|
local_ipv4_addr,
|
||||||
ipv6_addr,
|
ipv6_addr,
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
let in_external_route = if config.in_ips.is_empty() {
|
let in_external_route = if config.in_ips.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(ExternalRoute::new(config.in_ips))
|
Some(ExternalRoute::new(config.in_ips))
|
||||||
};
|
};
|
||||||
let (tcp_proxy, udp_proxy, ip_proxy_map) = if config.out_ips.is_empty() {
|
#[cfg(feature = "ip_proxy")]
|
||||||
|
let (tcp_proxy, udp_proxy, ip_proxy_map) = if config.out_ips.is_empty() || config.no_proxy {
|
||||||
(None, None, None)
|
(None, None, None)
|
||||||
} else {
|
} else {
|
||||||
let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(
|
let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
channel_sender.clone(),
|
channel_sender.clone(),
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
current_device.clone(),
|
current_device.clone(),
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
client_cipher.clone(),
|
client_cipher.clone(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -316,6 +332,7 @@ impl VntUtil {
|
|||||||
igmp_server.clone(),
|
igmp_server.clone(),
|
||||||
current_device.clone(),
|
current_device.clone(),
|
||||||
in_external_route,
|
in_external_route,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
ip_proxy_map.clone(),
|
ip_proxy_map.clone(),
|
||||||
client_cipher.clone(),
|
client_cipher.clone(),
|
||||||
self.server_cipher.clone(),
|
self.server_cipher.clone(),
|
||||||
@@ -330,12 +347,12 @@ impl VntUtil {
|
|||||||
igmp_server.clone(),
|
igmp_server.clone(),
|
||||||
current_device.clone(),
|
current_device.clone(),
|
||||||
in_external_route,
|
in_external_route,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
ip_proxy_map.clone(),
|
ip_proxy_map.clone(),
|
||||||
client_cipher.clone(),
|
client_cipher.clone(),
|
||||||
self.server_cipher.clone(),
|
self.server_cipher.clone(),
|
||||||
config.parallel,
|
config.parallel,
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
#[cfg(any(target_os = "android"))]
|
#[cfg(any(target_os = "android"))]
|
||||||
tun_handler::start(
|
tun_handler::start(
|
||||||
@@ -346,12 +363,12 @@ impl VntUtil {
|
|||||||
igmp_server.clone(),
|
igmp_server.clone(),
|
||||||
current_device.clone(),
|
current_device.clone(),
|
||||||
in_external_route,
|
in_external_route,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
ip_proxy_map.clone(),
|
ip_proxy_map.clone(),
|
||||||
client_cipher.clone(),
|
client_cipher.clone(),
|
||||||
self.server_cipher.clone(),
|
self.server_cipher.clone(),
|
||||||
config.parallel,
|
config.parallel,
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
//外部数据接收处理
|
//外部数据接收处理
|
||||||
let channel_recv_handler = ChannelDataHandler::new(
|
let channel_recv_handler = ChannelDataHandler::new(
|
||||||
@@ -363,6 +380,7 @@ impl VntUtil {
|
|||||||
device_writer.clone(),
|
device_writer.clone(),
|
||||||
connect_status.clone(),
|
connect_status.clone(),
|
||||||
peer_nat_info_map.clone(),
|
peer_nat_info_map.clone(),
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
ip_proxy_map,
|
ip_proxy_map,
|
||||||
out_external_route,
|
out_external_route,
|
||||||
cone_sender,
|
cone_sender,
|
||||||
@@ -388,12 +406,20 @@ impl VntUtil {
|
|||||||
let device_list = device_list.clone();
|
let device_list = device_list.clone();
|
||||||
let current_device = current_device.clone();
|
let current_device = current_device.clone();
|
||||||
// 定时心跳
|
// 定时心跳
|
||||||
|
heartbeat_handler::start_heartbeat_main(
|
||||||
|
vnt_status_manager.worker("main-heartbeat"),
|
||||||
|
channel_sender.clone(),
|
||||||
|
device_list.clone(),
|
||||||
|
current_device.clone(),
|
||||||
|
config.server_address_str,
|
||||||
|
client_cipher.clone(),
|
||||||
|
self.server_cipher.clone(),
|
||||||
|
);
|
||||||
heartbeat_handler::start_heartbeat(
|
heartbeat_handler::start_heartbeat(
|
||||||
vnt_status_manager.worker("heartbeat"),
|
vnt_status_manager.worker("heartbeat"),
|
||||||
channel_sender.clone(),
|
channel_sender.clone(),
|
||||||
device_list.clone(),
|
device_list.clone(),
|
||||||
current_device.clone(),
|
current_device.clone(),
|
||||||
config.server_address_str,
|
|
||||||
client_cipher.clone(),
|
client_cipher.clone(),
|
||||||
self.server_cipher.clone(),
|
self.server_cipher.clone(),
|
||||||
);
|
);
|
||||||
@@ -429,6 +455,7 @@ impl VntUtil {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
{
|
{
|
||||||
//代理
|
//代理
|
||||||
if let Some(tcp_proxy) = tcp_proxy {
|
if let Some(tcp_proxy) = tcp_proxy {
|
||||||
@@ -437,12 +464,15 @@ impl VntUtil {
|
|||||||
if let Some(udp_proxy) = udp_proxy {
|
if let Some(udp_proxy) = udp_proxy {
|
||||||
tokio::spawn(udp_proxy.start());
|
tokio::spawn(udp_proxy.start());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let nat_test = nat_test.clone();
|
let nat_test = nat_test.clone();
|
||||||
//延迟切换类型,避免无效流量
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
tokio::time::sleep(Duration::from_secs(15)).await;
|
let info = nat_test
|
||||||
context.switch(nat_test.nat_info().nat_type);
|
.re_test(public_ip, public_port, local_ipv4_addr, ipv6_addr)
|
||||||
|
.await;
|
||||||
|
context.switch(info.nat_type);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Ok(Vnt {
|
Ok(Vnt {
|
||||||
@@ -473,7 +503,7 @@ impl Vnt {
|
|||||||
self.current_device.load()
|
self.current_device.load()
|
||||||
}
|
}
|
||||||
pub fn peer_nat_info(&self, ip: &Ipv4Addr) -> Option<NatInfo> {
|
pub fn peer_nat_info(&self, ip: &Ipv4Addr) -> Option<NatInfo> {
|
||||||
self.peer_nat_info_map.get(ip).map(|e| e.value().clone())
|
self.peer_nat_info_map.read().get(ip).cloned()
|
||||||
}
|
}
|
||||||
pub fn connection_status(&self) -> ConnectStatus {
|
pub fn connection_status(&self) -> ConnectStatus {
|
||||||
self.connect_status.load()
|
self.connect_status.load()
|
||||||
@@ -497,14 +527,15 @@ impl Vnt {
|
|||||||
self.context.route_table_one()
|
self.context.route_table_one()
|
||||||
}
|
}
|
||||||
pub fn stop(&self) -> io::Result<()> {
|
pub fn stop(&self) -> io::Result<()> {
|
||||||
self.context.close();
|
let _ = self.context.close();
|
||||||
self.vnt_status_manager.stop_all();
|
self.vnt_status_manager.stop_all();
|
||||||
self.device_writer.close()?;
|
let _ = self.device_writer.close();
|
||||||
let virtual_gateway = self.current_device.load().virtual_gateway;
|
let virtual_gateway = self.current_device.load().virtual_gateway;
|
||||||
let _ = std::net::UdpSocket::bind("0.0.0.0:0")?.send_to(
|
let _ = UdpSocket::bind("0.0.0.0:0")?.send_to(
|
||||||
&[0],
|
b"stop",
|
||||||
SocketAddr::V4(SocketAddrV4::new(virtual_gateway, 10000)),
|
SocketAddr::V4(SocketAddrV4::new(virtual_gateway, 10000)),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub async fn wait_stop(&mut self) {
|
pub async fn wait_stop(&mut self) {
|
||||||
@@ -547,11 +578,15 @@ pub struct Config {
|
|||||||
pub tcp: bool,
|
pub tcp: bool,
|
||||||
pub ip: Option<Ipv4Addr>,
|
pub ip: Option<Ipv4Addr>,
|
||||||
pub relay: bool,
|
pub relay: bool,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
|
pub no_proxy: bool,
|
||||||
pub server_encrypt: bool,
|
pub server_encrypt: bool,
|
||||||
pub parallel: usize,
|
pub parallel: usize,
|
||||||
pub cipher_model: CipherModel,
|
pub cipher_model: CipherModel,
|
||||||
pub finger: bool,
|
pub finger: bool,
|
||||||
pub punch_model: PunchModel,
|
pub punch_model: PunchModel,
|
||||||
|
pub port: u16,
|
||||||
|
pub first_latency: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
@@ -571,11 +606,14 @@ impl Config {
|
|||||||
tcp: bool,
|
tcp: bool,
|
||||||
ip: Option<Ipv4Addr>,
|
ip: Option<Ipv4Addr>,
|
||||||
relay: bool,
|
relay: bool,
|
||||||
|
#[cfg(feature = "ip_proxy")] no_proxy: bool,
|
||||||
server_encrypt: bool,
|
server_encrypt: bool,
|
||||||
parallel: usize,
|
parallel: usize,
|
||||||
cipher_model: CipherModel,
|
cipher_model: CipherModel,
|
||||||
finger: bool,
|
finger: bool,
|
||||||
punch_model: PunchModel,
|
punch_model: PunchModel,
|
||||||
|
port: u16,
|
||||||
|
first_latency: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
for x in stun_server.iter_mut() {
|
for x in stun_server.iter_mut() {
|
||||||
if !x.contains(":") {
|
if !x.contains(":") {
|
||||||
@@ -598,11 +636,15 @@ impl Config {
|
|||||||
tcp,
|
tcp,
|
||||||
ip,
|
ip,
|
||||||
relay,
|
relay,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
|
no_proxy,
|
||||||
server_encrypt,
|
server_encrypt,
|
||||||
parallel,
|
parallel,
|
||||||
cipher_model,
|
cipher_model,
|
||||||
finger,
|
finger,
|
||||||
punch_model,
|
punch_model,
|
||||||
|
port,
|
||||||
|
first_latency,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,20 +22,20 @@ impl VntUtilSync {
|
|||||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
let runtime = tokio::runtime::Builder::new_multi_thread()
|
||||||
.enable_all()
|
.enable_all()
|
||||||
.build()?;
|
.build()?;
|
||||||
let vnt_util = runtime.block_on(VntUtil::new(config))?;
|
let vnt_util = VntUtil::new(config)?;
|
||||||
Ok(VntUtilSync { vnt_util, runtime })
|
Ok(VntUtilSync { vnt_util, runtime })
|
||||||
}
|
}
|
||||||
pub fn connect(&mut self) -> io::Result<()> {
|
pub fn connect(&mut self) -> io::Result<()> {
|
||||||
self.runtime.block_on(self.vnt_util.connect())
|
self.vnt_util.connect()
|
||||||
}
|
}
|
||||||
pub fn handshake(&mut self) -> Result<Option<RsaCipher>, HandshakeEnum> {
|
pub fn handshake(&mut self) -> Result<Option<RsaCipher>, HandshakeEnum> {
|
||||||
self.runtime.block_on(self.vnt_util.handshake())
|
self.vnt_util.handshake()
|
||||||
}
|
}
|
||||||
pub fn secret_handshake(&mut self) -> Result<(), HandshakeEnum> {
|
pub fn secret_handshake(&mut self) -> Result<(), HandshakeEnum> {
|
||||||
self.runtime.block_on(self.vnt_util.secret_handshake())
|
self.vnt_util.secret_handshake()
|
||||||
}
|
}
|
||||||
pub fn register(&mut self) -> Result<RegResponse, ReqEnum> {
|
pub fn register(&mut self) -> Result<RegResponse, ReqEnum> {
|
||||||
self.runtime.block_on(self.vnt_util.register())
|
self.vnt_util.register()
|
||||||
}
|
}
|
||||||
#[cfg(any(target_os = "android"))]
|
#[cfg(any(target_os = "android"))]
|
||||||
pub fn create_iface(&mut self, vpn_fd: i32) {
|
pub fn create_iface(&mut self, vpn_fd: i32) {
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ impl AllowExternalRoute {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn allow(&self, ip: &Ipv4Addr) -> bool {
|
pub fn allow(&self, ip: &Ipv4Addr) -> bool {
|
||||||
|
if self.route_table.is_empty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
let ip = u32::from_be_bytes(ip.octets());
|
let ip = u32::from_be_bytes(ip.octets());
|
||||||
for (dest, mask) in self.route_table.iter() {
|
for (dest, mask) in self.route_table.iter() {
|
||||||
if *mask & ip == *mask & *dest {
|
if *mask & ip == *mask & *dest {
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use protobuf::Message;
|
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
|
||||||
use tokio::net::{TcpStream, UdpSocket};
|
|
||||||
|
|
||||||
use crate::channel::channel::Context;
|
use crate::channel::channel::Context;
|
||||||
|
use crate::channel::RouteKey;
|
||||||
use crate::cipher::{Cipher, RsaCipher};
|
use crate::cipher::{Cipher, RsaCipher};
|
||||||
use crate::proto::message::{HandshakeRequest, HandshakeResponse, SecretHandshakeRequest};
|
use crate::proto::message::{HandshakeRequest, HandshakeResponse, SecretHandshakeRequest};
|
||||||
use crate::protocol::body::ENCRYPTION_RESERVED;
|
use crate::protocol::body::RSA_ENCRYPTION_RESERVED;
|
||||||
use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL};
|
use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL};
|
||||||
|
use protobuf::Message;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::net::TcpStream;
|
||||||
|
use std::net::UdpSocket;
|
||||||
|
|
||||||
pub enum HandshakeEnum {
|
pub enum HandshakeEnum {
|
||||||
NotSecret,
|
NotSecret,
|
||||||
@@ -44,7 +44,10 @@ fn secret_handshake_request_packet(
|
|||||||
request.token = token;
|
request.token = token;
|
||||||
request.key = key.to_vec();
|
request.key = key.to_vec();
|
||||||
let bytes = request.write_to_bytes()?;
|
let bytes = request.write_to_bytes()?;
|
||||||
let mut net_packet = NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?;
|
let mut net_packet = NetPacket::new0(
|
||||||
|
12 + bytes.len(),
|
||||||
|
vec![0u8; 12 + bytes.len() + RSA_ENCRYPTION_RESERVED],
|
||||||
|
)?;
|
||||||
net_packet.set_version(Version::V1);
|
net_packet.set_version(Version::V1);
|
||||||
net_packet.set_gateway_flag(true);
|
net_packet.set_gateway_flag(true);
|
||||||
net_packet.set_protocol(Protocol::Service);
|
net_packet.set_protocol(Protocol::Service);
|
||||||
@@ -55,7 +58,7 @@ fn secret_handshake_request_packet(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 第一次握手,拿到公钥
|
/// 第一次握手,拿到公钥
|
||||||
pub async fn handshake(
|
pub fn handshake(
|
||||||
main_channel: &UdpSocket,
|
main_channel: &UdpSocket,
|
||||||
main_tcp_channel: Option<&mut TcpStream>,
|
main_tcp_channel: Option<&mut TcpStream>,
|
||||||
server_address: SocketAddr,
|
server_address: SocketAddr,
|
||||||
@@ -70,8 +73,7 @@ pub async fn handshake(
|
|||||||
server_address,
|
server_address,
|
||||||
send_buf,
|
send_buf,
|
||||||
&mut recv_buf,
|
&mut recv_buf,
|
||||||
)
|
)?;
|
||||||
.await?;
|
|
||||||
let net_packet = match NetPacket::new(&recv_buf[..len]) {
|
let net_packet = match NetPacket::new(&recv_buf[..len]) {
|
||||||
Ok(net_packet) => net_packet,
|
Ok(net_packet) => net_packet,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -136,7 +138,7 @@ pub async fn handshake(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_recv(
|
fn send_recv(
|
||||||
main_channel: &UdpSocket,
|
main_channel: &UdpSocket,
|
||||||
main_tcp_channel: Option<&mut TcpStream>,
|
main_tcp_channel: Option<&mut TcpStream>,
|
||||||
server_address: SocketAddr,
|
server_address: SocketAddr,
|
||||||
@@ -148,50 +150,42 @@ async fn send_recv(
|
|||||||
let len = send_buf.len();
|
let len = send_buf.len();
|
||||||
head[2] = (len >> 8) as u8;
|
head[2] = (len >> 8) as u8;
|
||||||
head[3] = (len & 0xFF) as u8;
|
head[3] = (len & 0xFF) as u8;
|
||||||
if let Err(e) = main_tcp_channel.write_all(&head).await {
|
if let Err(e) = main_tcp_channel.write_all(&head) {
|
||||||
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
|
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
|
||||||
}
|
}
|
||||||
if let Err(e) = main_tcp_channel.write_all(send_buf).await {
|
if let Err(e) = main_tcp_channel.write_all(send_buf) {
|
||||||
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
|
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
|
||||||
}
|
}
|
||||||
if let Err(e) = main_tcp_channel.read_exact(&mut head).await {
|
if let Err(e) = main_tcp_channel.read_exact(&mut head) {
|
||||||
return Err(HandshakeEnum::Other(format!("read error:{}", e)));
|
return Err(HandshakeEnum::Other(format!("read error:{}", e)));
|
||||||
}
|
}
|
||||||
let len = (((head[2] as u16) << 8) | head[3] as u16) as usize;
|
let len = (((head[2] as u16) << 8) | head[3] as u16) as usize;
|
||||||
if len > recv_buf.len() {
|
if len > recv_buf.len() {
|
||||||
return Err(HandshakeEnum::Other("too long".to_string()));
|
return Err(HandshakeEnum::Other("too long".to_string()));
|
||||||
}
|
}
|
||||||
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[..len]).await {
|
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[..len]) {
|
||||||
return Err(HandshakeEnum::Other(format!("read error:{}", e)));
|
return Err(HandshakeEnum::Other(format!("read error:{}", e)));
|
||||||
}
|
}
|
||||||
Ok(len)
|
Ok(len)
|
||||||
} else {
|
} else {
|
||||||
if let Err(e) = main_channel.send_to(send_buf, server_address).await {
|
if let Err(e) = main_channel.send_to(send_buf, server_address) {
|
||||||
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
|
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
|
||||||
}
|
}
|
||||||
match tokio::time::timeout(Duration::from_millis(300), main_channel.recv_from(recv_buf))
|
match main_channel.recv_from(recv_buf) {
|
||||||
.await
|
Ok((len, addr)) => {
|
||||||
{
|
if server_address != addr {
|
||||||
Ok(rs) => match rs {
|
Err(HandshakeEnum::Other(format!("invalid data,from {}", addr)))
|
||||||
Ok((len, addr)) => {
|
} else {
|
||||||
if server_address != addr {
|
|
||||||
return Err(HandshakeEnum::Other(format!("invalid data,from {}", addr)));
|
|
||||||
}
|
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
|
||||||
return Err(HandshakeEnum::Other(format!("receiver error:{}", e)));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(_) => {
|
|
||||||
return Err(HandshakeEnum::Timeout);
|
|
||||||
}
|
}
|
||||||
|
Err(e) => Err(HandshakeEnum::Other(format!("receiver error:{}", e))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 第二次握手,同步对称密钥,后续将使用对称加密
|
/// 第二次握手,同步对称密钥,后续将使用对称加密
|
||||||
pub async fn secret_handshake(
|
pub fn secret_handshake(
|
||||||
main_channel: &UdpSocket,
|
main_channel: &UdpSocket,
|
||||||
main_tcp_channel: Option<&mut TcpStream>,
|
main_tcp_channel: Option<&mut TcpStream>,
|
||||||
server_address: SocketAddr,
|
server_address: SocketAddr,
|
||||||
@@ -217,8 +211,7 @@ pub async fn secret_handshake(
|
|||||||
server_address,
|
server_address,
|
||||||
send_buf,
|
send_buf,
|
||||||
&mut recv_buf,
|
&mut recv_buf,
|
||||||
)
|
)?;
|
||||||
.await?;
|
|
||||||
let mut net_packet = match NetPacket::new(&mut recv_buf[..len]) {
|
let mut net_packet = match NetPacket::new(&mut recv_buf[..len]) {
|
||||||
Ok(net_packet) => net_packet,
|
Ok(net_packet) => net_packet,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -241,22 +234,20 @@ pub async fn secret_handshake(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn secret_handshake_req(
|
pub fn secret_handshake_req(
|
||||||
context: &Context,
|
context: &Context,
|
||||||
server_address: SocketAddr,
|
server_address: SocketAddr,
|
||||||
rsa_cipher: &RsaCipher,
|
rsa_cipher: &RsaCipher,
|
||||||
server_cipher: &Cipher,
|
server_cipher: &Cipher,
|
||||||
token: String,
|
token: String,
|
||||||
|
route_key: &RouteKey,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
let secret_packet =
|
let secret_packet =
|
||||||
secret_handshake_request_packet(rsa_cipher, token, server_cipher.key().unwrap())?;
|
secret_handshake_request_packet(rsa_cipher, token, server_cipher.key().unwrap())?;
|
||||||
context
|
if route_key.is_tcp() {
|
||||||
.send_main(secret_packet.buffer(), server_address)
|
context.send_main(secret_packet.buffer(), server_address)?;
|
||||||
.await?;
|
} else {
|
||||||
if context.is_main_tcp() {
|
context.send_main_udp(secret_packet.buffer(), server_address)?;
|
||||||
context
|
|
||||||
.send_main_udp(secret_packet.buffer(), server_address)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,28 @@ async fn start_idle_(idle: Idle, sender: ChannelSender) -> io::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_heartbeat(
|
pub fn start_heartbeat(
|
||||||
|
mut worker: VntWorker,
|
||||||
|
sender: ChannelSender,
|
||||||
|
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||||
|
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
|
client_cipher: Cipher,
|
||||||
|
server_cipher: Cipher,
|
||||||
|
) {
|
||||||
|
tokio::spawn(async move {
|
||||||
|
tokio::select! {
|
||||||
|
_=worker.stop_wait()=>{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rs=start_heartbeat_(sender, device_list, current_device,client_cipher,server_cipher)=>{
|
||||||
|
if let Err(e) = rs {
|
||||||
|
log::warn!("心跳任务停止:{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
worker.stop_all();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
pub fn start_heartbeat_main(
|
||||||
mut worker: VntWorker,
|
mut worker: VntWorker,
|
||||||
sender: ChannelSender,
|
sender: ChannelSender,
|
||||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||||
@@ -56,11 +78,11 @@ pub fn start_heartbeat(
|
|||||||
_=worker.stop_wait()=>{
|
_=worker.stop_wait()=>{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rs=start_heartbeat_(sender, device_list, current_device,server_address_str,client_cipher,server_cipher)=>{
|
rs=start_heartbeat_main_(sender, device_list, current_device,server_address_str,client_cipher,server_cipher)=>{
|
||||||
if let Err(e) = rs {
|
if let Err(e) = rs {
|
||||||
log::warn!("心跳任务停止:{:?}", e);
|
log::warn!("主心跳任务停止:{:?}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
worker.stop_all();
|
worker.stop_all();
|
||||||
});
|
});
|
||||||
@@ -74,7 +96,7 @@ fn heartbeat_packet(
|
|||||||
gateway: bool,
|
gateway: bool,
|
||||||
src: Ipv4Addr,
|
src: Ipv4Addr,
|
||||||
dest: Ipv4Addr,
|
dest: Ipv4Addr,
|
||||||
) -> NetPacket<[u8; 48]> {
|
) -> NetPacket<[u8; 12 + 4 + ENCRYPTION_RESERVED]> {
|
||||||
let mut net_packet = NetPacket::new_encrypt([0u8; 12 + 4 + ENCRYPTION_RESERVED]).unwrap();
|
let mut net_packet = NetPacket::new_encrypt([0u8; 12 + 4 + ENCRYPTION_RESERVED]).unwrap();
|
||||||
net_packet.set_version(Version::V1);
|
net_packet.set_version(Version::V1);
|
||||||
net_packet.set_protocol(Protocol::Control);
|
net_packet.set_protocol(Protocol::Control);
|
||||||
@@ -97,7 +119,7 @@ fn heartbeat_packet(
|
|||||||
net_packet
|
net_packet
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start_heartbeat_(
|
async fn start_heartbeat_main_(
|
||||||
sender: ChannelSender,
|
sender: ChannelSender,
|
||||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
@@ -106,28 +128,14 @@ async fn start_heartbeat_(
|
|||||||
server_cipher: Cipher,
|
server_cipher: Cipher,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
log::info!("启动心跳任务");
|
log::info!("启动主心跳任务");
|
||||||
loop {
|
loop {
|
||||||
if sender.is_close() {
|
if sender.is_close() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let mut current_dev = current_device.load();
|
let mut current_dev = current_device.load();
|
||||||
//如果和服务端使用tcp连接,则维持udp洞的频率要更高些
|
let src = current_dev.virtual_ip();
|
||||||
if (sender.is_main_tcp() && count % 2 == 0) || (!sender.is_main_tcp() && count % 20 == 1) {
|
if count % 40 == 19 {
|
||||||
let mut packet = NetPacket::new_encrypt([0; 12 + ENCRYPTION_RESERVED])?;
|
|
||||||
packet.set_version(Version::V1);
|
|
||||||
packet.set_gateway_flag(true);
|
|
||||||
packet.set_protocol(Protocol::Control);
|
|
||||||
packet.set_transport_protocol(control_packet::Protocol::AddrRequest.into());
|
|
||||||
packet.first_set_ttl(MAX_TTL);
|
|
||||||
packet.set_source(current_dev.virtual_ip());
|
|
||||||
packet.set_destination(current_dev.virtual_gateway);
|
|
||||||
server_cipher.encrypt_ipv4(&mut packet)?;
|
|
||||||
let _ = sender
|
|
||||||
.send_main_udp(packet.buffer(), current_dev.connect_server)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
if count % 20 == 19 {
|
|
||||||
if let Ok(mut addr) = server_address_str.to_socket_addrs() {
|
if let Ok(mut addr) = server_address_str.to_socket_addrs() {
|
||||||
if let Some(addr) = addr.next() {
|
if let Some(addr) = addr.next() {
|
||||||
if addr != current_dev.connect_server {
|
if addr != current_dev.connect_server {
|
||||||
@@ -145,7 +153,6 @@ async fn start_heartbeat_(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let src = current_dev.virtual_ip();
|
|
||||||
let server_packet = heartbeat_packet(
|
let server_packet = heartbeat_packet(
|
||||||
MAX_TTL,
|
MAX_TTL,
|
||||||
&device_list,
|
&device_list,
|
||||||
@@ -155,12 +162,44 @@ async fn start_heartbeat_(
|
|||||||
src,
|
src,
|
||||||
current_dev.virtual_gateway,
|
current_dev.virtual_gateway,
|
||||||
);
|
);
|
||||||
if let Err(e) = sender
|
if let Err(e) = sender.send_main(server_packet.buffer(), current_dev.connect_server) {
|
||||||
.send_main(server_packet.buffer(), current_dev.connect_server)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
log::warn!("connect_server:{:?},e:{:?}", current_dev.connect_server, e);
|
log::warn!("connect_server:{:?},e:{:?}", current_dev.connect_server, e);
|
||||||
}
|
}
|
||||||
|
count += 1;
|
||||||
|
tokio::time::sleep(Duration::from_millis(3000)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn start_heartbeat_(
|
||||||
|
sender: ChannelSender,
|
||||||
|
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||||
|
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
|
client_cipher: Cipher,
|
||||||
|
server_cipher: Cipher,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
let mut count = 0;
|
||||||
|
log::info!("启动心跳任务");
|
||||||
|
loop {
|
||||||
|
if sender.is_close() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let current_dev = current_device.load();
|
||||||
|
//如果和服务端使用tcp连接,则维持udp洞的频率要更高些
|
||||||
|
if (sender.is_main_tcp() && count % 4 == 0) || (!sender.is_main_tcp() && count % 40 == 1) {
|
||||||
|
let mut packet = NetPacket::new_encrypt([0; 12 + ENCRYPTION_RESERVED])?;
|
||||||
|
packet.set_version(Version::V1);
|
||||||
|
packet.set_gateway_flag(true);
|
||||||
|
packet.set_protocol(Protocol::Control);
|
||||||
|
packet.set_transport_protocol(control_packet::Protocol::AddrRequest.into());
|
||||||
|
packet.first_set_ttl(MAX_TTL);
|
||||||
|
packet.set_source(current_dev.virtual_ip());
|
||||||
|
packet.set_destination(current_dev.virtual_gateway);
|
||||||
|
server_cipher.encrypt_ipv4(&mut packet)?;
|
||||||
|
let _ = sender.send_main_udp(packet.buffer(), current_dev.connect_server);
|
||||||
|
}
|
||||||
|
|
||||||
|
let src = current_dev.virtual_ip();
|
||||||
|
|
||||||
if count < 7 || count % 7 == 0 {
|
if count < 7 || count % 7 == 0 {
|
||||||
let mut route_list: Option<Vec<(Ipv4Addr, Vec<Route>)>> = None;
|
let mut route_list: Option<Vec<(Ipv4Addr, Vec<Route>)>> = None;
|
||||||
let peer_list = { device_list.lock().1.clone() };
|
let peer_list = { device_list.lock().1.clone() };
|
||||||
@@ -178,9 +217,8 @@ async fn start_heartbeat_(
|
|||||||
peer.virtual_ip,
|
peer.virtual_ip,
|
||||||
);
|
);
|
||||||
if let Some(route) = sender.route_one(&peer.virtual_ip) {
|
if let Some(route) = sender.route_one(&peer.virtual_ip) {
|
||||||
if let Err(e) = sender
|
if let Err(e) =
|
||||||
.send_by_key(client_packet.buffer(), &route.route_key())
|
sender.try_send_by_key(client_packet.buffer(), &route.route_key())
|
||||||
.await
|
|
||||||
{
|
{
|
||||||
log::warn!("virtual_ip:{},route:{:?},e:{:?}", peer.virtual_ip, route, e);
|
log::warn!("virtual_ip:{},route:{:?},e:{:?}", peer.virtual_ip, route, e);
|
||||||
}
|
}
|
||||||
@@ -189,9 +227,8 @@ async fn start_heartbeat_(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//没有直连路由则发送到网关
|
//没有直连路由则发送到网关
|
||||||
if let Err(e) = sender
|
if let Err(e) =
|
||||||
.send_main(client_packet.buffer(), current_dev.connect_server)
|
sender.send_main(client_packet.buffer(), current_dev.connect_server)
|
||||||
.await
|
|
||||||
{
|
{
|
||||||
log::warn!(
|
log::warn!(
|
||||||
"virtual_ip:{},connect_server:{:?},e:{:?}",
|
"virtual_ip:{},connect_server:{:?},e:{:?}",
|
||||||
@@ -247,9 +284,8 @@ async fn start_heartbeat_(
|
|||||||
*peer_ip,
|
*peer_ip,
|
||||||
);
|
);
|
||||||
for route in route_list {
|
for route in route_list {
|
||||||
if let Err(e) = sender
|
if let Err(e) =
|
||||||
.send_by_key(client_packet.buffer(), &route.route_key())
|
sender.try_send_by_key(client_packet.buffer(), &route.route_key())
|
||||||
.await
|
|
||||||
{
|
{
|
||||||
log::warn!("peer_ip:{:?},route:{:?},e:{:?}", peer_ip, route, e);
|
log::warn!("peer_ip:{:?},route:{:?},e:{:?}", peer_ip, route, e);
|
||||||
}
|
}
|
||||||
@@ -259,6 +295,6 @@ async fn start_heartbeat_(
|
|||||||
}
|
}
|
||||||
|
|
||||||
count += 1;
|
count += 1;
|
||||||
tokio::time::sleep(Duration::from_millis(5000)).await;
|
tokio::time::sleep(Duration::from_millis(3000)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,9 +137,7 @@ async fn start_punch_(
|
|||||||
info.virtual_ip,
|
info.virtual_ip,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let _ = sender
|
let _ = sender.send_main(packet.buffer(), current_device.connect_server);
|
||||||
.send_main(packet.buffer(), current_device.connect_server)
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
tokio::time::sleep(sleep_time).await;
|
tokio::time::sleep(sleep_time).await;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
+97
-179
@@ -1,13 +1,13 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
|
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
use dashmap::DashMap;
|
use parking_lot::{Mutex, RwLock};
|
||||||
use parking_lot::Mutex;
|
|
||||||
use protobuf::Message;
|
use protobuf::Message;
|
||||||
use tokio::sync::mpsc::Sender;
|
use tokio::sync::mpsc::Sender;
|
||||||
|
|
||||||
use packet::icmp::icmp::HeaderOther;
|
|
||||||
use packet::icmp::{icmp, Kind};
|
use packet::icmp::{icmp, Kind};
|
||||||
use packet::ip::ipv4;
|
use packet::ip::ipv4;
|
||||||
use packet::ip::ipv4::packet::IpV4Packet;
|
use packet::ip::ipv4::packet::IpV4Packet;
|
||||||
@@ -22,7 +22,8 @@ use crate::handle::handshake_handler::secret_handshake_req;
|
|||||||
use crate::handle::registration_handler::Register;
|
use crate::handle::registration_handler::Register;
|
||||||
use crate::handle::{ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo, PeerDeviceStatus};
|
use crate::handle::{ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo, PeerDeviceStatus};
|
||||||
use crate::igmp_server::IgmpServer;
|
use crate::igmp_server::IgmpServer;
|
||||||
use crate::ip_proxy::IpProxyMap;
|
#[cfg(feature = "ip_proxy")]
|
||||||
|
use crate::ip_proxy::{IpProxyMap, ProxyHandler};
|
||||||
use crate::nat;
|
use crate::nat;
|
||||||
use crate::nat::NatTest;
|
use crate::nat::NatTest;
|
||||||
use crate::proto::message::{DeviceList, PunchInfo, PunchNatType, RegistrationResponse};
|
use crate::proto::message::{DeviceList, PunchInfo, PunchNatType, RegistrationResponse};
|
||||||
@@ -44,7 +45,8 @@ pub struct ChannelDataHandler {
|
|||||||
igmp_server: Option<IgmpServer>,
|
igmp_server: Option<IgmpServer>,
|
||||||
device_writer: DeviceWriter,
|
device_writer: DeviceWriter,
|
||||||
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
||||||
peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>>,
|
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
ip_proxy_map: Option<IpProxyMap>,
|
ip_proxy_map: Option<IpProxyMap>,
|
||||||
out_external_route: AllowExternalRoute,
|
out_external_route: AllowExternalRoute,
|
||||||
cone_sender: Sender<(Ipv4Addr, NatInfo)>,
|
cone_sender: Sender<(Ipv4Addr, NatInfo)>,
|
||||||
@@ -54,6 +56,7 @@ pub struct ChannelDataHandler {
|
|||||||
rsa_cipher: Option<RsaCipher>,
|
rsa_cipher: Option<RsaCipher>,
|
||||||
relay: bool,
|
relay: bool,
|
||||||
token: String,
|
token: String,
|
||||||
|
time: Arc<AtomicCell<Instant>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChannelDataHandler {
|
impl ChannelDataHandler {
|
||||||
@@ -65,8 +68,8 @@ impl ChannelDataHandler {
|
|||||||
igmp_server: Option<IgmpServer>,
|
igmp_server: Option<IgmpServer>,
|
||||||
device_writer: DeviceWriter,
|
device_writer: DeviceWriter,
|
||||||
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
||||||
peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>>,
|
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
|
||||||
ip_proxy_map: Option<IpProxyMap>,
|
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
|
||||||
out_external_route: AllowExternalRoute,
|
out_external_route: AllowExternalRoute,
|
||||||
cone_sender: Sender<(Ipv4Addr, NatInfo)>,
|
cone_sender: Sender<(Ipv4Addr, NatInfo)>,
|
||||||
symmetric_sender: Sender<(Ipv4Addr, NatInfo)>,
|
symmetric_sender: Sender<(Ipv4Addr, NatInfo)>,
|
||||||
@@ -85,6 +88,7 @@ impl ChannelDataHandler {
|
|||||||
device_writer,
|
device_writer,
|
||||||
connect_status,
|
connect_status,
|
||||||
peer_nat_info_map,
|
peer_nat_info_map,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
ip_proxy_map,
|
ip_proxy_map,
|
||||||
out_external_route,
|
out_external_route,
|
||||||
cone_sender,
|
cone_sender,
|
||||||
@@ -94,12 +98,13 @@ impl ChannelDataHandler {
|
|||||||
rsa_cipher,
|
rsa_cipher,
|
||||||
relay,
|
relay,
|
||||||
token,
|
token,
|
||||||
|
time: Arc::new(AtomicCell::new(Instant::now())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChannelDataHandler {
|
impl ChannelDataHandler {
|
||||||
pub async fn handle(
|
pub fn handle(
|
||||||
&self,
|
&self,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
start: usize,
|
start: usize,
|
||||||
@@ -108,14 +113,14 @@ impl ChannelDataHandler {
|
|||||||
context: &Context,
|
context: &Context,
|
||||||
) {
|
) {
|
||||||
assert_eq!(start, 14);
|
assert_eq!(start, 14);
|
||||||
match self.handle0(&mut buf[..end], &route_key, context).await {
|
match self.handle0(&mut buf[..end], &route_key, context) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("{:?}", e);
|
log::warn!("{:?}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async fn handle0(
|
fn handle0(
|
||||||
&self,
|
&self,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
route_key: &RouteKey,
|
route_key: &RouteKey,
|
||||||
@@ -133,6 +138,7 @@ impl ChannelDataHandler {
|
|||||||
&& !destination.is_multicast()
|
&& !destination.is_multicast()
|
||||||
&& destination != current_device.broadcast_address;
|
&& destination != current_device.broadcast_address;
|
||||||
if current_device.virtual_ip() != destination
|
if current_device.virtual_ip() != destination
|
||||||
|
&& !net_packet.is_gateway()
|
||||||
&& not_broadcast
|
&& not_broadcast
|
||||||
&& !destination.is_unspecified()
|
&& !destination.is_unspecified()
|
||||||
{
|
{
|
||||||
@@ -144,17 +150,13 @@ impl ChannelDataHandler {
|
|||||||
// 转发
|
// 转发
|
||||||
if let Some(route) = context.route_one(&destination) {
|
if let Some(route) = context.route_one(&destination) {
|
||||||
if route.metric <= net_packet.ttl() {
|
if route.metric <= net_packet.ttl() {
|
||||||
context
|
context.try_send_by_key(net_packet.buffer(), &route.route_key())?;
|
||||||
.send_by_key(net_packet.buffer(), &route.route_key())
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
} else if (ttl > 1 || destination == current_device.virtual_gateway())
|
} else if (ttl > 1 || destination == current_device.virtual_gateway())
|
||||||
&& source != current_device.virtual_gateway()
|
&& source != current_device.virtual_gateway()
|
||||||
{
|
{
|
||||||
//网关默认要转发一次,生存时间不够的发到网关也会被丢弃
|
//网关默认要转发一次,生存时间不够的发到网关也会被丢弃
|
||||||
context
|
context.send_main(net_packet.buffer(), current_device.connect_server)?;
|
||||||
.send_main(net_packet.buffer(), current_device.connect_server)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -165,21 +167,28 @@ impl ChannelDataHandler {
|
|||||||
== crate::protocol::error_packet::Protocol::NoKey.into()
|
== crate::protocol::error_packet::Protocol::NoKey.into()
|
||||||
{
|
{
|
||||||
if let Some(rsa_cipher) = &self.rsa_cipher {
|
if let Some(rsa_cipher) = &self.rsa_cipher {
|
||||||
|
let last = self.time.load();
|
||||||
|
if last.elapsed() < Duration::from_secs(3)
|
||||||
|
|| self.time.compare_exchange(last, Instant::now()).is_err()
|
||||||
|
{
|
||||||
|
//短时间不重复上传服务端密钥
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
log::warn!("上传服务端密钥");
|
||||||
secret_handshake_req(
|
secret_handshake_req(
|
||||||
context,
|
context,
|
||||||
current_device.connect_server,
|
current_device.connect_server,
|
||||||
rsa_cipher,
|
rsa_cipher,
|
||||||
&self.server_cipher,
|
&self.server_cipher,
|
||||||
self.token.clone(),
|
self.token.clone(),
|
||||||
)
|
route_key,
|
||||||
.await?;
|
)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//服务端解密
|
//服务端解密
|
||||||
self.server_cipher.decrypt_ipv4(&mut net_packet)?;
|
self.server_cipher.decrypt_ipv4(&mut net_packet)?;
|
||||||
let data_len = net_packet.data_len();
|
let data_len = net_packet.data_len();
|
||||||
self.server_packet_handle(context, current_device, buf, data_len, route_key)
|
self.server_packet_handle(context, current_device, buf, data_len, route_key)?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -211,7 +220,7 @@ impl ChannelDataHandler {
|
|||||||
net_packet.set_destination(source);
|
net_packet.set_destination(source);
|
||||||
//不管加不加密,和接收到的数据长度都一致
|
//不管加不加密,和接收到的数据长度都一致
|
||||||
self.client_cipher.encrypt_ipv4(&mut net_packet)?;
|
self.client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||||
context.send_by_key(net_packet.buffer(), route_key).await?;
|
context.try_send_by_key(net_packet.buffer(), route_key)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,88 +228,22 @@ impl ChannelDataHandler {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
if not_broadcast && ipv4.destination_ip() != destination {
|
if not_broadcast && ipv4.destination_ip() != destination {
|
||||||
if let Some(ip_proxy_map) = &self.ip_proxy_map {
|
if self.out_external_route.allow(&ipv4.destination_ip()) {
|
||||||
if self.out_external_route.allow(&ipv4.destination_ip()) {
|
#[cfg(feature = "ip_proxy")]
|
||||||
match ipv4.protocol() {
|
if let Some(ip_proxy_map) = &self.ip_proxy_map {
|
||||||
ipv4::protocol::Protocol::Tcp => {
|
if ip_proxy_map.recv_handle(&mut ipv4, source, destination)? {
|
||||||
let dest_ip = ipv4.destination_ip();
|
return Ok(());
|
||||||
//转发到代理目标地址
|
|
||||||
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.update_checksum();
|
|
||||||
ipv4.set_destination_ip(destination);
|
|
||||||
ipv4.update_checksum();
|
|
||||||
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 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.update_checksum();
|
|
||||||
ipv4.set_destination_ip(destination);
|
|
||||||
ipv4.update_checksum();
|
|
||||||
let key = SocketAddrV4::new(source, source_port);
|
|
||||||
ip_proxy_map
|
|
||||||
.udp_proxy_map
|
|
||||||
.insert(key, SocketAddrV4::new(dest_ip, dest_port));
|
|
||||||
}
|
|
||||||
ipv4::protocol::Protocol::Icmp => {
|
|
||||||
let dest_ip = ipv4.destination_ip();
|
|
||||||
//转发到代理目标地址
|
|
||||||
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(), &dest_ip)?;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
log::warn!(
|
|
||||||
"不支持的ip代理Icmp协议:{}",
|
|
||||||
destination
|
|
||||||
);
|
|
||||||
return Err(Error::Warn(
|
|
||||||
"不支持的ip代理Icmp协议".to_string(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
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 {
|
} else {
|
||||||
log::warn!("不支持ip代理:{}", destination);
|
log::warn!(
|
||||||
return Err(Error::Warn("不支持ip代理".to_string()));
|
"没有ip代理规则{:?}:{}->{}->{}",
|
||||||
|
ipv4.protocol(),
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
ipv4.destination_ip()
|
||||||
|
);
|
||||||
|
return Err(Error::Warn("没有ip代理规则".to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,12 +260,10 @@ impl ChannelDataHandler {
|
|||||||
Protocol::Service => {}
|
Protocol::Service => {}
|
||||||
Protocol::Error => {}
|
Protocol::Error => {}
|
||||||
Protocol::Control => {
|
Protocol::Control => {
|
||||||
self.control(context, current_device, source, net_packet, route_key)
|
self.control(context, current_device, source, net_packet, route_key)?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
Protocol::OtherTurn => {
|
Protocol::OtherTurn => {
|
||||||
self.other_turn(context, current_device, source, net_packet, route_key)
|
self.other_turn(context, current_device, source, net_packet, route_key)?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
Protocol::UnKnow(e) => {
|
Protocol::UnKnow(e) => {
|
||||||
log::info!("不支持的协议:{}", e);
|
log::info!("不支持的协议:{}", e);
|
||||||
@@ -331,7 +272,7 @@ impl ChannelDataHandler {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn pong_packet(
|
fn pong_packet(
|
||||||
&self,
|
&self,
|
||||||
gateway: bool,
|
gateway: bool,
|
||||||
metric: u8,
|
metric: u8,
|
||||||
@@ -360,14 +301,12 @@ impl ChannelDataHandler {
|
|||||||
poll_device.set_protocol(Protocol::Service);
|
poll_device.set_protocol(Protocol::Service);
|
||||||
poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into());
|
poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into());
|
||||||
self.server_cipher.encrypt_ipv4(&mut poll_device)?;
|
self.server_cipher.encrypt_ipv4(&mut poll_device)?;
|
||||||
context
|
context.send_main(poll_device.buffer(), current_device.connect_server)?;
|
||||||
.send_main(poll_device.buffer(), current_device.connect_server)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
async fn control(
|
fn control(
|
||||||
&self,
|
&self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
current_device: CurrentDeviceInfo,
|
current_device: CurrentDeviceInfo,
|
||||||
@@ -383,7 +322,7 @@ impl ChannelDataHandler {
|
|||||||
net_packet.set_destination(source);
|
net_packet.set_destination(source);
|
||||||
net_packet.first_set_ttl(MAX_TTL);
|
net_packet.first_set_ttl(MAX_TTL);
|
||||||
self.client_cipher.encrypt_ipv4(&mut net_packet)?;
|
self.client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||||
context.send_by_key(net_packet.buffer(), route_key).await?;
|
context.try_send_by_key(net_packet.buffer(), route_key)?;
|
||||||
let route = Route::from(*route_key, metric, 199);
|
let route = Route::from(*route_key, metric, 199);
|
||||||
context.add_route_if_absent(source, route);
|
context.add_route_if_absent(source, route);
|
||||||
}
|
}
|
||||||
@@ -396,8 +335,7 @@ impl ChannelDataHandler {
|
|||||||
source,
|
source,
|
||||||
pong_packet,
|
pong_packet,
|
||||||
route_key,
|
route_key,
|
||||||
)
|
)?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
ControlPacket::PunchRequest => {
|
ControlPacket::PunchRequest => {
|
||||||
if self.relay {
|
if self.relay {
|
||||||
@@ -409,7 +347,7 @@ impl ChannelDataHandler {
|
|||||||
net_packet.set_destination(source);
|
net_packet.set_destination(source);
|
||||||
net_packet.first_set_ttl(1);
|
net_packet.first_set_ttl(1);
|
||||||
self.client_cipher.encrypt_ipv4(&mut net_packet)?;
|
self.client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||||
context.send_by_key(net_packet.buffer(), route_key).await?;
|
context.try_send_by_key(net_packet.buffer(), route_key)?;
|
||||||
let route = Route::from(*route_key, 1, 199);
|
let route = Route::from(*route_key, 1, 199);
|
||||||
context.add_route_if_absent(source, route);
|
context.add_route_if_absent(source, route);
|
||||||
}
|
}
|
||||||
@@ -433,26 +371,17 @@ impl ChannelDataHandler {
|
|||||||
addr_packet.set_ipv4(ipv4);
|
addr_packet.set_ipv4(ipv4);
|
||||||
addr_packet.set_port(route_key.addr.port());
|
addr_packet.set_port(route_key.addr.port());
|
||||||
self.client_cipher.encrypt_ipv4(&mut packet)?;
|
self.client_cipher.encrypt_ipv4(&mut packet)?;
|
||||||
context.send_by_key(packet.buffer(), route_key).await?;
|
context.try_send_by_key(packet.buffer(), route_key)?;
|
||||||
}
|
}
|
||||||
std::net::IpAddr::V6(_) => {}
|
std::net::IpAddr::V6(_) => {}
|
||||||
},
|
},
|
||||||
ControlPacket::AddrResponse(addr_packet) => {
|
ControlPacket::AddrResponse(addr_packet) => self
|
||||||
if !addr_packet.ipv4().is_multicast()
|
.nat_test
|
||||||
&& !addr_packet.ipv4().is_broadcast()
|
.update_addr(addr_packet.ipv4(), addr_packet.port()),
|
||||||
&& !addr_packet.ipv4().is_unspecified()
|
|
||||||
&& !addr_packet.ipv4().is_loopback()
|
|
||||||
&& !addr_packet.ipv4().is_private()
|
|
||||||
&& addr_packet.port() != 0
|
|
||||||
{
|
|
||||||
self.nat_test
|
|
||||||
.update_addr(addr_packet.ipv4(), addr_packet.port())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
async fn other_turn(
|
fn other_turn(
|
||||||
&self,
|
&self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
current_device: CurrentDeviceInfo,
|
current_device: CurrentDeviceInfo,
|
||||||
@@ -490,7 +419,10 @@ impl ChannelDataHandler {
|
|||||||
ipv6_addr,
|
ipv6_addr,
|
||||||
punch_info.nat_type.enum_value_or_default().into(),
|
punch_info.nat_type.enum_value_or_default().into(),
|
||||||
);
|
);
|
||||||
self.peer_nat_info_map.insert(source, peer_nat_info.clone());
|
{
|
||||||
|
let peer_nat_info = peer_nat_info.clone();
|
||||||
|
self.peer_nat_info_map.write().insert(source, peer_nat_info);
|
||||||
|
}
|
||||||
if !punch_info.reply {
|
if !punch_info.reply {
|
||||||
let mut punch_reply = PunchInfo::new();
|
let mut punch_reply = PunchInfo::new();
|
||||||
punch_reply.reply = true;
|
punch_reply.reply = true;
|
||||||
@@ -533,14 +465,12 @@ impl ChannelDataHandler {
|
|||||||
// let _ = context.try_send_main_udp(packet.buffer(),
|
// let _ = context.try_send_main_udp(packet.buffer(),
|
||||||
// SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port)));
|
// SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port)));
|
||||||
// }
|
// }
|
||||||
if self.punch(source, peer_nat_info).await {
|
if self.punch(source, peer_nat_info) {
|
||||||
self.client_cipher.encrypt_ipv4(&mut punch_packet)?;
|
self.client_cipher.encrypt_ipv4(&mut punch_packet)?;
|
||||||
context
|
context.try_send_by_key(punch_packet.buffer(), route_key)?;
|
||||||
.send_by_key(punch_packet.buffer(), route_key)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.punch(source, peer_nat_info).await;
|
self.punch(source, peer_nat_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
other_turn_packet::Protocol::Unknown(e) => {
|
other_turn_packet::Protocol::Unknown(e) => {
|
||||||
@@ -549,7 +479,7 @@ impl ChannelDataHandler {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
async fn punch(&self, peer_ip: Ipv4Addr, peer_nat_info: NatInfo) -> bool {
|
fn punch(&self, peer_ip: Ipv4Addr, peer_nat_info: NatInfo) -> bool {
|
||||||
match peer_nat_info.nat_type {
|
match peer_nat_info.nat_type {
|
||||||
NatType::Symmetric => self
|
NatType::Symmetric => self
|
||||||
.symmetric_sender
|
.symmetric_sender
|
||||||
@@ -562,7 +492,7 @@ impl ChannelDataHandler {
|
|||||||
|
|
||||||
/// 处理服务端数据
|
/// 处理服务端数据
|
||||||
impl ChannelDataHandler {
|
impl ChannelDataHandler {
|
||||||
async fn server_packet_handle(
|
fn server_packet_handle(
|
||||||
&self,
|
&self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
current_device: CurrentDeviceInfo,
|
current_device: CurrentDeviceInfo,
|
||||||
@@ -574,16 +504,13 @@ impl ChannelDataHandler {
|
|||||||
let source = net_packet.source();
|
let source = net_packet.source();
|
||||||
match net_packet.protocol() {
|
match net_packet.protocol() {
|
||||||
Protocol::Service => {
|
Protocol::Service => {
|
||||||
self.service(context, current_device, net_packet, route_key)
|
self.service(context, current_device, net_packet, route_key)?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
Protocol::Error => {
|
Protocol::Error => {
|
||||||
self.error(context, current_device, source, net_packet, route_key)
|
self.error(context, current_device, source, net_packet, route_key)?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
Protocol::Control => {
|
Protocol::Control => {
|
||||||
self.control_gateway(context, current_device, net_packet, route_key)
|
self.control_gateway(context, current_device, net_packet, route_key)?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
Protocol::IpTurn => {
|
Protocol::IpTurn => {
|
||||||
match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) {
|
match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||||
@@ -617,16 +544,13 @@ impl ChannelDataHandler {
|
|||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
async fn control_gateway(
|
fn control_gateway(
|
||||||
&self,
|
&self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
current_device: CurrentDeviceInfo,
|
current_device: CurrentDeviceInfo,
|
||||||
net_packet: NetPacket<&[u8]>,
|
net_packet: NetPacket<&[u8]>,
|
||||||
route_key: &RouteKey,
|
route_key: &RouteKey,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
if net_packet.source() != current_device.virtual_gateway {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
|
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
|
||||||
ControlPacket::PongPacket(pong_packet) => {
|
ControlPacket::PongPacket(pong_packet) => {
|
||||||
let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
|
let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
|
||||||
@@ -638,26 +562,16 @@ impl ChannelDataHandler {
|
|||||||
net_packet.source(),
|
net_packet.source(),
|
||||||
pong_packet,
|
pong_packet,
|
||||||
route_key,
|
route_key,
|
||||||
)
|
)?;
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
ControlPacket::AddrResponse(addr_packet) => {
|
|
||||||
if addr_packet.port() != 0
|
|
||||||
&& !addr_packet.ipv4().is_multicast()
|
|
||||||
&& !addr_packet.ipv4().is_broadcast()
|
|
||||||
&& !addr_packet.ipv4().is_unspecified()
|
|
||||||
&& !addr_packet.ipv4().is_loopback()
|
|
||||||
&& !addr_packet.ipv4().is_private()
|
|
||||||
{
|
|
||||||
self.nat_test
|
|
||||||
.update_addr(addr_packet.ipv4(), addr_packet.port())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ControlPacket::AddrResponse(addr_packet) => self
|
||||||
|
.nat_test
|
||||||
|
.update_addr(addr_packet.ipv4(), addr_packet.port()),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
async fn service(
|
fn service(
|
||||||
&self,
|
&self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
current_device: CurrentDeviceInfo,
|
current_device: CurrentDeviceInfo,
|
||||||
@@ -669,23 +583,29 @@ impl ChannelDataHandler {
|
|||||||
service_packet::Protocol::RegistrationResponse => {
|
service_packet::Protocol::RegistrationResponse => {
|
||||||
let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?;
|
let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?;
|
||||||
|
|
||||||
{
|
if self.nat_test.can_update() {
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let nat_test = self.nat_test.clone();
|
let nat_test = self.nat_test.clone();
|
||||||
tokio::spawn(async move {
|
std::thread::spawn(move || {
|
||||||
let local_port = context.main_local_ipv4_port().unwrap_or(0);
|
tokio::runtime::Builder::new_current_thread()
|
||||||
let local_ipv4_addr = nat::local_ipv4_addr(local_port);
|
.enable_all()
|
||||||
let local_port = context.main_local_ipv6_port().unwrap_or(0);
|
.build()
|
||||||
let ipv6_addr = nat::local_ipv6_addr(local_port);
|
.unwrap()
|
||||||
let nat_info = nat_test
|
.block_on(async move {
|
||||||
.re_test(
|
let local_port = context.main_local_ipv4_port().unwrap_or(0);
|
||||||
Ipv4Addr::from(response.public_ip),
|
let local_ipv4_addr = nat::local_ipv4_addr(local_port);
|
||||||
response.public_port as u16,
|
let local_port = context.main_local_ipv6_port().unwrap_or(0);
|
||||||
local_ipv4_addr,
|
let ipv6_addr = nat::local_ipv6_addr(local_port);
|
||||||
ipv6_addr,
|
let nat_info = nat_test
|
||||||
)
|
.re_test(
|
||||||
.await;
|
Ipv4Addr::from(response.public_ip),
|
||||||
context.switch(nat_info.nat_type);
|
response.public_port as u16,
|
||||||
|
local_ipv4_addr,
|
||||||
|
ipv6_addr,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
context.switch(nat_info.nat_type);
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let new_ip = Ipv4Addr::from(response.virtual_ip);
|
let new_ip = Ipv4Addr::from(response.virtual_ip);
|
||||||
@@ -757,7 +677,7 @@ impl ChannelDataHandler {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
async fn error(
|
fn error(
|
||||||
&self,
|
&self,
|
||||||
_context: &Context,
|
_context: &Context,
|
||||||
current_device: CurrentDeviceInfo,
|
current_device: CurrentDeviceInfo,
|
||||||
@@ -778,9 +698,7 @@ impl ChannelDataHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.connect_status.store(ConnectStatus::Connecting);
|
self.connect_status.store(ConnectStatus::Connecting);
|
||||||
self.register
|
self.register.fast_register(current_device.virtual_ip)?;
|
||||||
.fast_register(current_device.virtual_ip)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
InErrorPacket::AddressExhausted => {
|
InErrorPacket::AddressExhausted => {
|
||||||
//地址用尽
|
//地址用尽
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
|
use std::io::{Read, Write};
|
||||||
use std::net::{Ipv4Addr, SocketAddr};
|
use std::net::{Ipv4Addr, SocketAddr};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
@@ -6,8 +7,8 @@ use crate::channel::sender::ChannelSender;
|
|||||||
use crate::cipher::Cipher;
|
use crate::cipher::Cipher;
|
||||||
use crate::handle::PeerDeviceInfo;
|
use crate::handle::PeerDeviceInfo;
|
||||||
use protobuf::Message;
|
use protobuf::Message;
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use std::net::TcpStream;
|
||||||
use tokio::net::{TcpStream, UdpSocket};
|
use std::net::UdpSocket;
|
||||||
|
|
||||||
use crate::proto::message::{RegistrationRequest, RegistrationResponse};
|
use crate::proto::message::{RegistrationRequest, RegistrationResponse};
|
||||||
use crate::protocol::body::ENCRYPTION_RESERVED;
|
use crate::protocol::body::ENCRYPTION_RESERVED;
|
||||||
@@ -36,7 +37,7 @@ pub struct RegResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
///向中继服务器注册,token标识一个虚拟网关,device_id防止多次注册时得到的ip不一致
|
///向中继服务器注册,token标识一个虚拟网关,device_id防止多次注册时得到的ip不一致
|
||||||
pub async fn registration(
|
pub fn registration(
|
||||||
main_channel: &UdpSocket,
|
main_channel: &UdpSocket,
|
||||||
main_tcp_channel: Option<&mut TcpStream>,
|
main_tcp_channel: Option<&mut TcpStream>,
|
||||||
server_cipher: &Cipher,
|
server_cipher: &Cipher,
|
||||||
@@ -66,43 +67,33 @@ pub async fn registration(
|
|||||||
vec[2] = (len >> 8) as u8;
|
vec[2] = (len >> 8) as u8;
|
||||||
vec[3] = (len & 0xFF) as u8;
|
vec[3] = (len & 0xFF) as u8;
|
||||||
vec[4..].copy_from_slice(buf);
|
vec[4..].copy_from_slice(buf);
|
||||||
if let Err(e) = main_tcp_channel.write_all(&vec).await {
|
if let Err(e) = main_tcp_channel.write_all(&vec) {
|
||||||
return Err(ReqEnum::Other(format!("send error:{}", e)));
|
return Err(ReqEnum::Other(format!("send error:{}", e)));
|
||||||
}
|
}
|
||||||
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[..4]).await {
|
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[..4]) {
|
||||||
return Err(ReqEnum::Other(format!("read error:{}", e)));
|
return Err(ReqEnum::Other(format!("read error:{}", e)));
|
||||||
}
|
}
|
||||||
let len = 4 + (((recv_buf[2] as u16) << 8) | recv_buf[3] as u16) as usize;
|
let len = 4 + (((recv_buf[2] as u16) << 8) | recv_buf[3] as u16) as usize;
|
||||||
if len > recv_buf.len() {
|
if len > recv_buf.len() {
|
||||||
return Err(ReqEnum::Other("too long".to_string()));
|
return Err(ReqEnum::Other("too long".to_string()));
|
||||||
}
|
}
|
||||||
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[4..len]).await {
|
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[4..len]) {
|
||||||
return Err(ReqEnum::Other(format!("read error:{}", e)));
|
return Err(ReqEnum::Other(format!("read error:{}", e)));
|
||||||
}
|
}
|
||||||
&mut recv_buf[4..len]
|
&mut recv_buf[4..len]
|
||||||
} else {
|
} else {
|
||||||
if let Err(e) = main_channel.send_to(buf, server_address).await {
|
if let Err(e) = main_channel.send_to(buf, server_address) {
|
||||||
return Err(ReqEnum::Other(format!("send error:{}", e)));
|
return Err(ReqEnum::Other(format!("send error:{}", e)));
|
||||||
}
|
}
|
||||||
match tokio::time::timeout(
|
match main_channel.recv_from(&mut recv_buf) {
|
||||||
Duration::from_millis(300),
|
Ok((len, addr)) => {
|
||||||
main_channel.recv_from(&mut recv_buf),
|
if server_address != addr {
|
||||||
)
|
return Err(ReqEnum::Other(format!("invalid data,from {}", addr)));
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(rs) => match rs {
|
|
||||||
Ok((len, addr)) => {
|
|
||||||
if server_address != addr {
|
|
||||||
return Err(ReqEnum::Other(format!("invalid data,from {}", addr)));
|
|
||||||
}
|
|
||||||
&mut recv_buf[..len]
|
|
||||||
}
|
}
|
||||||
Err(e) => {
|
&mut recv_buf[..len]
|
||||||
return Err(ReqEnum::Other(format!("receiver error:{}", e)));
|
}
|
||||||
}
|
Err(e) => {
|
||||||
},
|
return Err(ReqEnum::Other(format!("receiver error:{}", e)));
|
||||||
Err(_) => {
|
|
||||||
return Err(ReqEnum::Timeout);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -236,9 +227,9 @@ impl Register {
|
|||||||
client_secret,
|
client_secret,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub async fn fast_register(&self, ip: Ipv4Addr) -> crate::Result<()> {
|
pub fn fast_register(&self, ip: Ipv4Addr) -> crate::Result<()> {
|
||||||
let last = self.time.load();
|
let last = self.time.load();
|
||||||
if last.elapsed() < Duration::from_secs(2)
|
if last.elapsed() < Duration::from_secs(3)
|
||||||
|| self.time.compare_exchange(last, Instant::now()).is_err()
|
|| self.time.compare_exchange(last, Instant::now()).is_err()
|
||||||
{
|
{
|
||||||
//短时间不重复注册
|
//短时间不重复注册
|
||||||
@@ -256,7 +247,7 @@ impl Register {
|
|||||||
self.client_secret,
|
self.client_secret,
|
||||||
)?;
|
)?;
|
||||||
let buf = request_packet.buffer();
|
let buf = request_packet.buffer();
|
||||||
self.sender.send_main(buf, self.server_address).await?;
|
self.sender.send_main(buf, self.server_address)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
use byte_pool::Block;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct BufSenderGroup(
|
pub struct BufSenderGroup(
|
||||||
usize,
|
usize,
|
||||||
Vec<tokio::sync::mpsc::Sender<(Block<'static>, usize, usize)>>,
|
Vec<std::sync::mpsc::SyncSender<(Vec<u8>, usize, usize)>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
pub struct BufReceiverGroup(pub Vec<tokio::sync::mpsc::Receiver<(Block<'static>, usize, usize)>>);
|
pub struct BufReceiverGroup(pub Vec<std::sync::mpsc::Receiver<(Vec<u8>, usize, usize)>>);
|
||||||
|
|
||||||
impl BufSenderGroup {
|
impl BufSenderGroup {
|
||||||
pub async fn send(&mut self, val: (Block<'static>, usize, usize)) -> bool {
|
pub fn send(&mut self, val: (Vec<u8>, usize, usize)) -> bool {
|
||||||
let index = self.0 % self.1.len();
|
let index = self.0 % self.1.len();
|
||||||
self.0 = self.0.wrapping_add(1);
|
self.0 = self.0.wrapping_add(1);
|
||||||
self.1[index].send(val).await.is_ok()
|
self.1[index].send(val).is_ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +19,7 @@ pub fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) {
|
|||||||
let mut buf_receiver_group = Vec::with_capacity(size);
|
let mut buf_receiver_group = Vec::with_capacity(size);
|
||||||
for _ in 0..size {
|
for _ in 0..size {
|
||||||
let (buf_sender, buf_receiver) =
|
let (buf_sender, buf_receiver) =
|
||||||
tokio::sync::mpsc::channel::<(Block<'static>, usize, usize)>(10);
|
std::sync::mpsc::sync_channel::<(Vec<u8>, usize, usize)>(1);
|
||||||
buf_sender_group.push(buf_sender);
|
buf_sender_group.push(buf_sender);
|
||||||
buf_receiver_group.push(buf_receiver);
|
buf_receiver_group.push(buf_receiver);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,30 @@
|
|||||||
|
use std::net::Ipv4Addr;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
|
use packet::ip::ipv4::packet::IpV4Packet;
|
||||||
|
use packet::ip::ipv4::protocol::Protocol;
|
||||||
|
|
||||||
use crate::channel::sender::ChannelSender;
|
use crate::channel::sender::ChannelSender;
|
||||||
use crate::cipher::Cipher;
|
use crate::cipher::Cipher;
|
||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
use crate::external_route::ExternalRoute;
|
use crate::external_route::ExternalRoute;
|
||||||
use crate::handle::{check_dest, CurrentDeviceInfo};
|
use crate::handle::{check_dest, CurrentDeviceInfo};
|
||||||
use crate::igmp_server::{IgmpServer, Multicast};
|
use crate::igmp_server::{IgmpServer, Multicast};
|
||||||
use crate::ip_proxy::IpProxyMap;
|
#[cfg(feature = "ip_proxy")]
|
||||||
|
use crate::ip_proxy::{IpProxyMap, ProxyHandler};
|
||||||
use crate::protocol;
|
use crate::protocol;
|
||||||
use crate::protocol::body::ENCRYPTION_RESERVED;
|
use crate::protocol::body::ENCRYPTION_RESERVED;
|
||||||
use crate::protocol::ip_turn_packet::BroadcastPacket;
|
use crate::protocol::ip_turn_packet::BroadcastPacket;
|
||||||
use crate::protocol::{ip_turn_packet, NetPacket, Version, MAX_TTL};
|
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 parking_lot::RwLock;
|
|
||||||
use std::io;
|
|
||||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
|
||||||
use std::sync::Arc;
|
|
||||||
pub mod channel_group;
|
pub mod channel_group;
|
||||||
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
|
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
|
||||||
pub mod tap_handler;
|
pub mod tap_handler;
|
||||||
pub mod tun_handler;
|
pub mod tun_handler;
|
||||||
|
|
||||||
async fn broadcast(
|
fn broadcast(
|
||||||
server_cipher: &Cipher,
|
server_cipher: &Cipher,
|
||||||
multicast_members: Option<Arc<RwLock<Multicast>>>,
|
multicast_members: Option<Arc<RwLock<Multicast>>>,
|
||||||
sender: &ChannelSender,
|
sender: &ChannelSender,
|
||||||
@@ -47,8 +49,7 @@ async fn broadcast(
|
|||||||
}
|
}
|
||||||
if route.is_p2p()
|
if route.is_p2p()
|
||||||
&& sender
|
&& sender
|
||||||
.send_by_key(net_packet.buffer(), &route.route_key())
|
.try_send_by_key(net_packet.buffer(), &route.route_key())
|
||||||
.await
|
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
peer_ips.push(peer_ip);
|
peer_ips.push(peer_ip);
|
||||||
@@ -62,14 +63,10 @@ async fn broadcast(
|
|||||||
}
|
}
|
||||||
//转发到服务端的可选择广播,还要进行服务端加密
|
//转发到服务端的可选择广播,还要进行服务端加密
|
||||||
if peer_ips.is_empty() {
|
if peer_ips.is_empty() {
|
||||||
sender
|
sender.send_main(net_packet.buffer(), current_device.connect_server)?;
|
||||||
.send_main(net_packet.buffer(), current_device.connect_server)
|
|
||||||
.await?;
|
|
||||||
} else {
|
} else {
|
||||||
let buf = vec![
|
let buf =
|
||||||
0 as u8;
|
vec![0u8; 12 + 1 + peer_ips.len() * 4 + net_packet.data_len() + ENCRYPTION_RESERVED];
|
||||||
12 + 1 + peer_ips.len() * 4 + net_packet.data_len() + ENCRYPTION_RESERVED
|
|
||||||
];
|
|
||||||
//剩余的发送到服务端,需要告知哪些已发送过
|
//剩余的发送到服务端,需要告知哪些已发送过
|
||||||
let mut server_packet = NetPacket::new_encrypt(buf)?;
|
let mut server_packet = NetPacket::new_encrypt(buf)?;
|
||||||
server_packet.set_version(Version::V1);
|
server_packet.set_version(Version::V1);
|
||||||
@@ -85,9 +82,7 @@ async fn broadcast(
|
|||||||
broadcast.set_address(&peer_ips)?;
|
broadcast.set_address(&peer_ips)?;
|
||||||
broadcast.set_data(net_packet.buffer())?;
|
broadcast.set_data(net_packet.buffer())?;
|
||||||
server_cipher.encrypt_ipv4(&mut server_packet)?;
|
server_cipher.encrypt_ipv4(&mut server_packet)?;
|
||||||
sender
|
sender.send_main(server_packet.buffer(), current_device.connect_server)?;
|
||||||
.send_main(server_packet.buffer(), current_device.connect_server)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -96,23 +91,19 @@ async fn broadcast(
|
|||||||
/// |12字节开头|ip报文|至少1024字节结尾|
|
/// |12字节开头|ip报文|至少1024字节结尾|
|
||||||
///
|
///
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn base_handle(
|
pub fn base_handle(
|
||||||
sender: &ChannelSender,
|
sender: &ChannelSender,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
data_len: usize, //数据总长度=12+ip包长度
|
data_len: usize, //数据总长度=12+ip包长度
|
||||||
igmp_server: &Option<IgmpServer>,
|
igmp_server: &Option<IgmpServer>,
|
||||||
current_device: CurrentDeviceInfo,
|
current_device: CurrentDeviceInfo,
|
||||||
ip_route: &Option<ExternalRoute>,
|
ip_route: &Option<ExternalRoute>,
|
||||||
proxy_map: &Option<IpProxyMap>,
|
#[cfg(feature = "ip_proxy")] proxy_map: &Option<IpProxyMap>,
|
||||||
client_cipher: &Cipher,
|
client_cipher: &Cipher,
|
||||||
server_cipher: &Cipher,
|
server_cipher: &Cipher,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ipv4_packet = IpV4Packet::new(&buf[12..data_len])?;
|
let ipv4_packet = IpV4Packet::new(&buf[12..data_len])?;
|
||||||
let protocol = ipv4_packet.protocol();
|
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 src_ip = ipv4_packet.source_ip();
|
||||||
let mut dest_ip = ipv4_packet.destination_ip();
|
let mut dest_ip = ipv4_packet.destination_ip();
|
||||||
let mut net_packet = NetPacket::new0(data_len, buf)?;
|
let mut net_packet = NetPacket::new0(data_len, buf)?;
|
||||||
@@ -126,9 +117,7 @@ pub async fn base_handle(
|
|||||||
if protocol == Protocol::Icmp {
|
if protocol == Protocol::Icmp {
|
||||||
net_packet.set_gateway_flag(true);
|
net_packet.set_gateway_flag(true);
|
||||||
server_cipher.encrypt_ipv4(&mut net_packet)?;
|
server_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||||
sender
|
sender.send_main(net_packet.buffer(), current_device.connect_server)?;
|
||||||
.send_main(net_packet.buffer(), current_device.connect_server)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -140,9 +129,7 @@ pub async fn base_handle(
|
|||||||
net_packet.set_destination(current_device.virtual_gateway);
|
net_packet.set_destination(current_device.virtual_gateway);
|
||||||
net_packet.set_gateway_flag(true);
|
net_packet.set_gateway_flag(true);
|
||||||
server_cipher.encrypt_ipv4(&mut net_packet)?;
|
server_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||||
sender
|
sender.send_main(net_packet.buffer(), current_device.connect_server)?;
|
||||||
.send_main(net_packet.buffer(), current_device.connect_server)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Protocol::Udp => {
|
Protocol::Udp => {
|
||||||
@@ -160,8 +147,7 @@ pub async fn base_handle(
|
|||||||
sender,
|
sender,
|
||||||
&mut net_packet,
|
&mut net_packet,
|
||||||
¤t_device,
|
¤t_device,
|
||||||
)
|
)?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -176,8 +162,7 @@ pub async fn base_handle(
|
|||||||
sender,
|
sender,
|
||||||
&mut net_packet,
|
&mut net_packet,
|
||||||
¤t_device,
|
¤t_device,
|
||||||
)
|
)?;
|
||||||
.await?;
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if !check_dest(
|
if !check_dest(
|
||||||
@@ -200,69 +185,19 @@ pub async fn base_handle(
|
|||||||
} else {
|
} else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
} else if let Some(proxy_map) = proxy_map {
|
}
|
||||||
match protocol {
|
#[cfg(feature = "ip_proxy")]
|
||||||
Protocol::Tcp => {
|
if let Some(proxy_map) = proxy_map {
|
||||||
let dest_addr = {
|
let mut ipv4_packet = IpV4Packet::new(net_packet.payload_mut())?;
|
||||||
let tcp_packet = TcpPacket::new(
|
proxy_map.send_handle(&mut ipv4_packet)?;
|
||||||
src_ip,
|
|
||||||
dest_ip,
|
|
||||||
&mut net_packet.payload_mut()[ip_head_len..],
|
|
||||||
)?;
|
|
||||||
SocketAddrV4::new(dest_ip, tcp_packet.destination_port())
|
|
||||||
};
|
|
||||||
if let Some(entry) = proxy_map.tcp_proxy_map.get(&dest_addr) {
|
|
||||||
let source_addr = entry.value();
|
|
||||||
let source_ip = *source_addr.ip();
|
|
||||||
let mut tcp_packet = TcpPacket::new(
|
|
||||||
source_ip,
|
|
||||||
dest_ip,
|
|
||||||
&mut net_packet.payload_mut()[ip_head_len..],
|
|
||||||
)?;
|
|
||||||
tcp_packet.set_source_port(source_addr.port());
|
|
||||||
tcp_packet.update_checksum();
|
|
||||||
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.payload_mut()[ip_head_len..],
|
|
||||||
)?;
|
|
||||||
SocketAddrV4::new(dest_ip, udp_packet.destination_port())
|
|
||||||
};
|
|
||||||
if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) {
|
|
||||||
let source_addr = entry.value();
|
|
||||||
let source_ip = *source_addr.ip();
|
|
||||||
let mut udp_packet = UdpPacket::new(
|
|
||||||
source_ip,
|
|
||||||
dest_ip,
|
|
||||||
&mut net_packet.payload_mut()[ip_head_len..],
|
|
||||||
)?;
|
|
||||||
udp_packet.set_source_port(source_addr.port());
|
|
||||||
udp_packet.update_checksum();
|
|
||||||
let mut ipv4_packet = IpV4Packet::new(net_packet.payload_mut())?;
|
|
||||||
ipv4_packet.set_source_ip(source_ip);
|
|
||||||
ipv4_packet.update_checksum();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
client_cipher.encrypt_ipv4(&mut net_packet)?;
|
client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||||
//优先发到直连到地址
|
//优先发到直连到地址
|
||||||
if sender
|
if sender
|
||||||
.send_by_id(net_packet.buffer(), &dest_ip)
|
.try_send_by_id(net_packet.buffer(), &dest_ip)
|
||||||
.await
|
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
sender
|
sender.send_main(net_packet.buffer(), current_device.connect_server)?;
|
||||||
.send_main(net_packet.buffer(), current_device.connect_server)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
use byte_pool::BytePool;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{io, thread};
|
use std::{io, thread};
|
||||||
|
|
||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
use lazy_static::lazy_static;
|
|
||||||
|
|
||||||
use packet::arp::arp::ArpPacket;
|
use packet::arp::arp::ArpPacket;
|
||||||
use packet::ethernet;
|
use packet::ethernet;
|
||||||
@@ -20,11 +18,9 @@ use crate::external_route::ExternalRoute;
|
|||||||
use crate::handle::tun_tap::channel_group::{buf_channel_group, BufSenderGroup};
|
use crate::handle::tun_tap::channel_group::{buf_channel_group, BufSenderGroup};
|
||||||
use crate::handle::CurrentDeviceInfo;
|
use crate::handle::CurrentDeviceInfo;
|
||||||
use crate::igmp_server::IgmpServer;
|
use crate::igmp_server::IgmpServer;
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
use crate::ip_proxy::IpProxyMap;
|
use crate::ip_proxy::IpProxyMap;
|
||||||
use crate::tun_tap_device::{DeviceReader, DeviceWriter};
|
use crate::tun_tap_device::{DeviceReader, DeviceWriter};
|
||||||
lazy_static! {
|
|
||||||
static ref POOL: BytePool<Vec<u8>> = BytePool::<Vec<u8>>::new();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start(
|
pub fn start(
|
||||||
worker: VntWorker,
|
worker: VntWorker,
|
||||||
@@ -34,7 +30,7 @@ pub fn start(
|
|||||||
igmp_server: Option<IgmpServer>,
|
igmp_server: Option<IgmpServer>,
|
||||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
ip_route: Option<ExternalRoute>,
|
ip_route: Option<ExternalRoute>,
|
||||||
ip_proxy_map: Option<IpProxyMap>,
|
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
|
||||||
client_cipher: Cipher,
|
client_cipher: Cipher,
|
||||||
server_cipher: Cipher,
|
server_cipher: Cipher,
|
||||||
parallel: usize,
|
parallel: usize,
|
||||||
@@ -43,43 +39,39 @@ pub fn start(
|
|||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
.name("tap_handler".into())
|
.name("tap_handler".into())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
tokio::runtime::Builder::new_current_thread()
|
if let Err(e) = start_simple(
|
||||||
.enable_all()
|
&sender,
|
||||||
.build()
|
device_reader,
|
||||||
.unwrap()
|
&device_writer,
|
||||||
.block_on(async move {
|
igmp_server,
|
||||||
if let Err(e) = start_simple(
|
current_device,
|
||||||
sender,
|
ip_route,
|
||||||
device_reader,
|
#[cfg(feature = "ip_proxy")]
|
||||||
device_writer,
|
ip_proxy_map,
|
||||||
igmp_server,
|
client_cipher,
|
||||||
current_device,
|
server_cipher,
|
||||||
ip_route,
|
) {
|
||||||
ip_proxy_map,
|
log::warn!("tap:{:?}", e);
|
||||||
client_cipher,
|
}
|
||||||
server_cipher,
|
let _ = sender.close();
|
||||||
)
|
let _ = device_writer.close();
|
||||||
.await
|
worker.stop_all();
|
||||||
{
|
|
||||||
log::warn!("tap:{:?}", e);
|
|
||||||
}
|
|
||||||
worker.stop_all();
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
let (buf_sender, buf_receiver) = buf_channel_group(parallel);
|
let (buf_sender, buf_receiver) = buf_channel_group(parallel);
|
||||||
for mut buf_receiver in buf_receiver.0 {
|
for buf_receiver in buf_receiver.0 {
|
||||||
let sender = sender.clone();
|
let sender = sender.clone();
|
||||||
let device_writer = device_writer.clone();
|
let device_writer = device_writer.clone();
|
||||||
let igmp_server = igmp_server.clone();
|
let igmp_server = igmp_server.clone();
|
||||||
let current_device = current_device.clone();
|
let current_device = current_device.clone();
|
||||||
let ip_route = ip_route.clone();
|
let ip_route = ip_route.clone();
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
let ip_proxy_map = ip_proxy_map.clone();
|
let ip_proxy_map = ip_proxy_map.clone();
|
||||||
let client_cipher = client_cipher.clone();
|
let client_cipher = client_cipher.clone();
|
||||||
let server_cipher = server_cipher.clone();
|
let server_cipher = server_cipher.clone();
|
||||||
tokio::spawn(async move {
|
thread::spawn(move || {
|
||||||
while let Some((mut buf, _, len)) = buf_receiver.recv().await {
|
while let Ok((mut buf, _, len)) = buf_receiver.recv() {
|
||||||
match handle(
|
match handle(
|
||||||
&mut buf,
|
&mut buf,
|
||||||
len,
|
len,
|
||||||
@@ -88,51 +80,48 @@ pub fn start(
|
|||||||
&device_writer,
|
&device_writer,
|
||||||
&sender,
|
&sender,
|
||||||
&ip_route,
|
&ip_route,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
&ip_proxy_map,
|
&ip_proxy_map,
|
||||||
&client_cipher,
|
&client_cipher,
|
||||||
&server_cipher,
|
&server_cipher,
|
||||||
)
|
) {
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("{:?}", e)
|
log::warn!("{:?}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let _ = sender.close();
|
||||||
|
let _ = device_writer.close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
.name("tap_handler".into())
|
.name("tap_handler".into())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
tokio::runtime::Builder::new_current_thread()
|
if let Err(e) = start_(&sender, device_reader, buf_sender) {
|
||||||
.enable_all()
|
log::warn!("tap:{:?}", e);
|
||||||
.build()
|
}
|
||||||
.unwrap()
|
let _ = sender.close();
|
||||||
.block_on(async move {
|
let _ = device_writer.close();
|
||||||
if let Err(e) = start_(sender, device_reader, buf_sender).await {
|
worker.stop_all();
|
||||||
log::warn!("tap:{:?}", e);
|
|
||||||
}
|
|
||||||
worker.stop_all();
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start_(
|
fn start_(
|
||||||
sender: ChannelSender,
|
sender: &ChannelSender,
|
||||||
device_reader: DeviceReader,
|
device_reader: DeviceReader,
|
||||||
mut buf_sender: BufSenderGroup,
|
mut buf_sender: BufSenderGroup,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
loop {
|
loop {
|
||||||
let mut buf = POOL.alloc(4096);
|
let mut buf = vec![0; 4096];
|
||||||
if sender.is_close() {
|
if sender.is_close() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let start = 0;
|
let start = 0;
|
||||||
let len = device_reader.read(&mut buf)?;
|
let len = device_reader.read(&mut buf)?;
|
||||||
if !buf_sender.send((buf, start, len)).await {
|
if !buf_sender.send((buf, start, len)) {
|
||||||
return Err(io::Error::new(
|
return Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
"tap buf_sender发送失败",
|
"tap buf_sender发送失败",
|
||||||
@@ -141,40 +130,42 @@ async fn start_(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start_simple(
|
fn start_simple(
|
||||||
sender: ChannelSender,
|
sender: &ChannelSender,
|
||||||
device_reader: DeviceReader,
|
device_reader: DeviceReader,
|
||||||
device_writer: DeviceWriter,
|
device_writer: &DeviceWriter,
|
||||||
igmp_server: Option<IgmpServer>,
|
igmp_server: Option<IgmpServer>,
|
||||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
ip_route: Option<ExternalRoute>,
|
ip_route: Option<ExternalRoute>,
|
||||||
ip_proxy_map: Option<IpProxyMap>,
|
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
|
||||||
client_cipher: Cipher,
|
client_cipher: Cipher,
|
||||||
server_cipher: Cipher,
|
server_cipher: Cipher,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
let mut buf = [0; 4096];
|
let mut buf = [0; 4096];
|
||||||
loop {
|
loop {
|
||||||
|
if sender.is_close() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
let len = device_reader.read(&mut buf)?;
|
let len = device_reader.read(&mut buf)?;
|
||||||
if let Err(e) = handle(
|
if let Err(e) = handle(
|
||||||
&mut buf,
|
&mut buf,
|
||||||
len,
|
len,
|
||||||
&igmp_server,
|
&igmp_server,
|
||||||
¤t_device,
|
¤t_device,
|
||||||
&device_writer,
|
device_writer,
|
||||||
&sender,
|
sender,
|
||||||
&ip_route,
|
&ip_route,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
&ip_proxy_map,
|
&ip_proxy_map,
|
||||||
&client_cipher,
|
&client_cipher,
|
||||||
&server_cipher,
|
&server_cipher,
|
||||||
)
|
) {
|
||||||
.await
|
|
||||||
{
|
|
||||||
log::warn!("tap handle{:?}", e);
|
log::warn!("tap handle{:?}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle(
|
fn handle(
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
len: usize,
|
len: usize,
|
||||||
igmp_server: &Option<IgmpServer>,
|
igmp_server: &Option<IgmpServer>,
|
||||||
@@ -182,7 +173,7 @@ async fn handle(
|
|||||||
device_writer: &DeviceWriter,
|
device_writer: &DeviceWriter,
|
||||||
sender: &ChannelSender,
|
sender: &ChannelSender,
|
||||||
ip_route: &Option<ExternalRoute>,
|
ip_route: &Option<ExternalRoute>,
|
||||||
proxy_map: &Option<IpProxyMap>,
|
#[cfg(feature = "ip_proxy")] proxy_map: &Option<IpProxyMap>,
|
||||||
client_cipher: &Cipher,
|
client_cipher: &Cipher,
|
||||||
server_cipher: &Cipher,
|
server_cipher: &Cipher,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
@@ -227,9 +218,6 @@ async fn handle(
|
|||||||
ethernet::protocol::Protocol::Ipv4 => {
|
ethernet::protocol::Protocol::Ipv4 => {
|
||||||
let mut ipv4_packet = IpV4Packet::unchecked(ethernet_packet.payload_mut());
|
let mut ipv4_packet = IpV4Packet::unchecked(ethernet_packet.payload_mut());
|
||||||
let src_ip = ipv4_packet.source_ip();
|
let src_ip = ipv4_packet.source_ip();
|
||||||
if src_ip != current_device.virtual_ip() {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
let dest_ip = ipv4_packet.destination_ip();
|
let dest_ip = ipv4_packet.destination_ip();
|
||||||
let protocol = ipv4_packet.protocol();
|
let protocol = ipv4_packet.protocol();
|
||||||
if src_ip == dest_ip {
|
if src_ip == dest_ip {
|
||||||
@@ -258,11 +246,11 @@ async fn handle(
|
|||||||
igmp_server,
|
igmp_server,
|
||||||
current_device,
|
current_device,
|
||||||
ip_route,
|
ip_route,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
proxy_map,
|
proxy_map,
|
||||||
client_cipher,
|
client_cipher,
|
||||||
server_cipher,
|
server_cipher,
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// log::warn!("不支持的二层协议:{:?}",p)
|
// log::warn!("不支持的二层协议:{:?}",p)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use byte_pool::BytePool;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{io, thread};
|
use std::{io, thread};
|
||||||
|
|
||||||
@@ -17,11 +16,9 @@ use crate::external_route::ExternalRoute;
|
|||||||
use crate::handle::tun_tap::channel_group::{buf_channel_group, BufSenderGroup};
|
use crate::handle::tun_tap::channel_group::{buf_channel_group, BufSenderGroup};
|
||||||
use crate::handle::CurrentDeviceInfo;
|
use crate::handle::CurrentDeviceInfo;
|
||||||
use crate::igmp_server::IgmpServer;
|
use crate::igmp_server::IgmpServer;
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
use crate::ip_proxy::IpProxyMap;
|
use crate::ip_proxy::IpProxyMap;
|
||||||
use crate::tun_tap_device::{DeviceReader, DeviceWriter};
|
use crate::tun_tap_device::{DeviceReader, DeviceWriter};
|
||||||
lazy_static::lazy_static! {
|
|
||||||
static ref POOL:BytePool<Vec<u8>> = BytePool::<Vec<u8>>::new();
|
|
||||||
}
|
|
||||||
fn icmp(device_writer: &DeviceWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Result<()> {
|
fn icmp(device_writer: &DeviceWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Result<()> {
|
||||||
if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp {
|
if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp {
|
||||||
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
|
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
|
||||||
@@ -40,7 +37,7 @@ fn icmp(device_writer: &DeviceWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) ->
|
|||||||
|
|
||||||
/// 接收tun数据,并且转发到udp上
|
/// 接收tun数据,并且转发到udp上
|
||||||
#[inline]
|
#[inline]
|
||||||
async fn handle(
|
fn handle(
|
||||||
sender: &ChannelSender,
|
sender: &ChannelSender,
|
||||||
data: &mut [u8],
|
data: &mut [u8],
|
||||||
len: usize,
|
len: usize,
|
||||||
@@ -48,20 +45,13 @@ async fn handle(
|
|||||||
igmp_server: &Option<IgmpServer>,
|
igmp_server: &Option<IgmpServer>,
|
||||||
current_device: CurrentDeviceInfo,
|
current_device: CurrentDeviceInfo,
|
||||||
ip_route: &Option<ExternalRoute>,
|
ip_route: &Option<ExternalRoute>,
|
||||||
proxy_map: &Option<IpProxyMap>,
|
#[cfg(feature = "ip_proxy")] proxy_map: &Option<IpProxyMap>,
|
||||||
client_cipher: &Cipher,
|
client_cipher: &Cipher,
|
||||||
server_cipher: &Cipher,
|
server_cipher: &Cipher,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ipv4_packet = if let Ok(ipv4_packet) = IpV4Packet::new(&mut data[12..len]) {
|
let ipv4_packet = IpV4Packet::new(&mut data[12..len])?;
|
||||||
ipv4_packet
|
|
||||||
} else {
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
let src_ip = ipv4_packet.source_ip();
|
let src_ip = ipv4_packet.source_ip();
|
||||||
let dest_ip = ipv4_packet.destination_ip();
|
let dest_ip = ipv4_packet.destination_ip();
|
||||||
if src_ip != current_device.virtual_ip() {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
if src_ip == dest_ip {
|
if src_ip == dest_ip {
|
||||||
return icmp(&device_writer, ipv4_packet);
|
return icmp(&device_writer, ipv4_packet);
|
||||||
}
|
}
|
||||||
@@ -72,14 +62,14 @@ async fn handle(
|
|||||||
igmp_server,
|
igmp_server,
|
||||||
current_device,
|
current_device,
|
||||||
ip_route,
|
ip_route,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
proxy_map,
|
proxy_map,
|
||||||
client_cipher,
|
client_cipher,
|
||||||
server_cipher,
|
server_cipher,
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start(
|
pub fn start(
|
||||||
worker: VntWorker,
|
worker: VntWorker,
|
||||||
sender: ChannelSender,
|
sender: ChannelSender,
|
||||||
device_reader: DeviceReader,
|
device_reader: DeviceReader,
|
||||||
@@ -87,7 +77,7 @@ pub async fn start(
|
|||||||
igmp_server: Option<IgmpServer>,
|
igmp_server: Option<IgmpServer>,
|
||||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
ip_route: Option<ExternalRoute>,
|
ip_route: Option<ExternalRoute>,
|
||||||
ip_proxy_map: Option<IpProxyMap>,
|
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
|
||||||
client_cipher: Cipher,
|
client_cipher: Cipher,
|
||||||
server_cipher: Cipher,
|
server_cipher: Cipher,
|
||||||
parallel: usize,
|
parallel: usize,
|
||||||
@@ -96,44 +86,39 @@ pub async fn start(
|
|||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
.name("tun_handler".into())
|
.name("tun_handler".into())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
tokio::runtime::Builder::new_current_thread()
|
if let Err(e) = start_simple(
|
||||||
.enable_all()
|
&sender,
|
||||||
.build()
|
device_reader,
|
||||||
.unwrap()
|
&device_writer,
|
||||||
.block_on(async move {
|
igmp_server,
|
||||||
if let Err(e) = start_simple(
|
current_device,
|
||||||
sender,
|
ip_route,
|
||||||
device_reader,
|
#[cfg(feature = "ip_proxy")]
|
||||||
&device_writer,
|
ip_proxy_map,
|
||||||
igmp_server,
|
client_cipher,
|
||||||
current_device,
|
server_cipher,
|
||||||
ip_route,
|
) {
|
||||||
ip_proxy_map,
|
log::warn!("stop:{}", e);
|
||||||
client_cipher,
|
}
|
||||||
server_cipher,
|
let _ = sender.close();
|
||||||
)
|
let _ = device_writer.close();
|
||||||
.await
|
worker.stop_all();
|
||||||
{
|
|
||||||
log::warn!("stop:{}", e);
|
|
||||||
}
|
|
||||||
let _ = device_writer.close();
|
|
||||||
worker.stop_all();
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
let (buf_sender, buf_receiver) = buf_channel_group(parallel);
|
let (buf_sender, buf_receiver) = buf_channel_group(parallel);
|
||||||
for mut buf_receiver in buf_receiver.0 {
|
for buf_receiver in buf_receiver.0 {
|
||||||
let sender = sender.clone();
|
let sender = sender.clone();
|
||||||
let device_writer = device_writer.clone();
|
let device_writer = device_writer.clone();
|
||||||
let igmp_server = igmp_server.clone();
|
let igmp_server = igmp_server.clone();
|
||||||
let current_device = current_device.clone();
|
let current_device = current_device.clone();
|
||||||
let ip_route = ip_route.clone();
|
let ip_route = ip_route.clone();
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
let ip_proxy_map = ip_proxy_map.clone();
|
let ip_proxy_map = ip_proxy_map.clone();
|
||||||
let client_cipher = client_cipher.clone();
|
let client_cipher = client_cipher.clone();
|
||||||
let server_cipher = server_cipher.clone();
|
let server_cipher = server_cipher.clone();
|
||||||
tokio::spawn(async move {
|
thread::spawn(move || {
|
||||||
while let Some((mut buf, start, len)) = buf_receiver.recv().await {
|
while let Ok((mut buf, start, len)) = buf_receiver.recv() {
|
||||||
match handle(
|
match handle(
|
||||||
&sender,
|
&sender,
|
||||||
&mut buf[start..],
|
&mut buf[start..],
|
||||||
@@ -142,47 +127,43 @@ pub async fn start(
|
|||||||
&igmp_server,
|
&igmp_server,
|
||||||
current_device.load(),
|
current_device.load(),
|
||||||
&ip_route,
|
&ip_route,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
&ip_proxy_map,
|
&ip_proxy_map,
|
||||||
&client_cipher,
|
&client_cipher,
|
||||||
&server_cipher,
|
&server_cipher,
|
||||||
)
|
) {
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("{:?}", e)
|
log::warn!("{:?}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let _ = sender.close();
|
||||||
|
let _ = device_writer.close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
.name("tun_handler".into())
|
.name("tun_handler".into())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
tokio::runtime::Builder::new_current_thread()
|
if let Err(e) = start_(&sender, device_reader, buf_sender) {
|
||||||
.enable_all()
|
log::warn!("stop:{}", e);
|
||||||
.build()
|
}
|
||||||
.unwrap()
|
let _ = sender.close();
|
||||||
.block_on(async move {
|
let _ = device_writer.close();
|
||||||
if let Err(e) = start_(sender, device_reader, buf_sender).await {
|
worker.stop_all();
|
||||||
log::warn!("stop:{}", e);
|
|
||||||
}
|
|
||||||
let _ = device_writer.close();
|
|
||||||
worker.stop_all();
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start_(
|
fn start_(
|
||||||
sender: ChannelSender,
|
sender: &ChannelSender,
|
||||||
device_reader: DeviceReader,
|
device_reader: DeviceReader,
|
||||||
mut buf_sender: BufSenderGroup,
|
mut buf_sender: BufSenderGroup,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
loop {
|
loop {
|
||||||
let mut buf = POOL.alloc(4096);
|
let mut buf = vec![0; 4096];
|
||||||
buf[..12].fill(0);
|
buf[..12].fill(0);
|
||||||
if sender.is_close() {
|
if sender.is_close() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -191,7 +172,7 @@ async fn start_(
|
|||||||
let len = device_reader.read(&mut buf[12..])? + 12;
|
let len = device_reader.read(&mut buf[12..])? + 12;
|
||||||
#[cfg(any(target_os = "macos"))]
|
#[cfg(any(target_os = "macos"))]
|
||||||
let start = 4;
|
let start = 4;
|
||||||
if !buf_sender.send((buf, start, len)).await {
|
if !buf_sender.send((buf, start, len)) {
|
||||||
return Err(io::Error::new(
|
return Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
"tun buf_sender发送失败",
|
"tun buf_sender发送失败",
|
||||||
@@ -200,14 +181,14 @@ async fn start_(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start_simple(
|
fn start_simple(
|
||||||
sender: ChannelSender,
|
sender: &ChannelSender,
|
||||||
device_reader: DeviceReader,
|
device_reader: DeviceReader,
|
||||||
device_writer: &DeviceWriter,
|
device_writer: &DeviceWriter,
|
||||||
igmp_server: Option<IgmpServer>,
|
igmp_server: Option<IgmpServer>,
|
||||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
ip_route: Option<ExternalRoute>,
|
ip_route: Option<ExternalRoute>,
|
||||||
ip_proxy_map: Option<IpProxyMap>,
|
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
|
||||||
client_cipher: Cipher,
|
client_cipher: Cipher,
|
||||||
server_cipher: Cipher,
|
server_cipher: Cipher,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
@@ -221,19 +202,18 @@ async fn start_simple(
|
|||||||
#[cfg(any(target_os = "macos"))]
|
#[cfg(any(target_os = "macos"))]
|
||||||
let mut buf = &mut buf[4..];
|
let mut buf = &mut buf[4..];
|
||||||
match handle(
|
match handle(
|
||||||
&sender,
|
sender,
|
||||||
&mut buf,
|
&mut buf,
|
||||||
len,
|
len,
|
||||||
device_writer,
|
device_writer,
|
||||||
&igmp_server,
|
&igmp_server,
|
||||||
current_device.load(),
|
current_device.load(),
|
||||||
&ip_route,
|
&ip_route,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
&ip_proxy_map,
|
&ip_proxy_map,
|
||||||
&client_cipher,
|
&client_cipher,
|
||||||
&server_cipher,
|
&server_cipher,
|
||||||
)
|
) {
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("{:?}", e)
|
log::warn!("{:?}", e)
|
||||||
|
|||||||
+25
-31
@@ -1,15 +1,17 @@
|
|||||||
use crate::tun_tap_device::DeviceWriter;
|
|
||||||
use dashmap::DashMap;
|
|
||||||
use packet::igmp::igmp_v2::IgmpV2Packet;
|
|
||||||
use packet::igmp::igmp_v3::{IgmpV3QueryPacket, IgmpV3RecordType, IgmpV3ReportPacket};
|
|
||||||
use packet::igmp::IgmpType;
|
|
||||||
use packet::ip::ipv4::protocol::Protocol;
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
use 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::tun_tap_device::DeviceWriter;
|
||||||
|
|
||||||
//1. 定时发送query,启动时20秒一次,连发3次,之后8分钟一次
|
//1. 定时发送query,启动时20秒一次,连发3次,之后8分钟一次
|
||||||
//2. 接收网关的igmp report 维护组播源信息
|
//2. 接收网关的igmp report 维护组播源信息
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@@ -47,12 +49,13 @@ impl Multicast {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct IgmpServer {
|
pub struct IgmpServer {
|
||||||
multicast: Arc<DashMap<Ipv4Addr, Arc<RwLock<Multicast>>>>,
|
multicast: Arc<RwLock<HashMap<Ipv4Addr, Arc<RwLock<Multicast>>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IgmpServer {
|
impl IgmpServer {
|
||||||
pub fn new(device_writer: DeviceWriter) -> Self {
|
pub fn new(device_writer: DeviceWriter) -> Self {
|
||||||
let multicast: Arc<DashMap<Ipv4Addr, Arc<RwLock<Multicast>>>> = Arc::new(DashMap::new());
|
let multicast: Arc<RwLock<HashMap<Ipv4Addr, Arc<RwLock<Multicast>>>>> =
|
||||||
|
Arc::new(RwLock::new(HashMap::with_capacity(16)));
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
//预留以太网帧头和ip头
|
//预留以太网帧头和ip头
|
||||||
let mut buf = [0; 14 + 24 + 12];
|
let mut buf = [0; 14 + 24 + 12];
|
||||||
@@ -93,16 +96,13 @@ impl IgmpServer {
|
|||||||
Self { multicast }
|
Self { multicast }
|
||||||
}
|
}
|
||||||
pub fn load(&self, multicast_addr: &Ipv4Addr) -> Option<Arc<RwLock<Multicast>>> {
|
pub fn load(&self, multicast_addr: &Ipv4Addr) -> Option<Arc<RwLock<Multicast>>> {
|
||||||
if let Some(entry) = self.multicast.get(multicast_addr) {
|
self.multicast.read().get(multicast_addr).cloned()
|
||||||
Some(entry.value().clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn handle(&self, buf: &[u8], source: Ipv4Addr) -> crate::Result<()> {
|
pub fn handle(&self, buf: &[u8], source: Ipv4Addr) -> crate::Result<()> {
|
||||||
for x in self.multicast.iter() {
|
let multicast = self.multicast.read();
|
||||||
|
for (_, v) in multicast.iter() {
|
||||||
let mut list = Vec::new();
|
let mut list = Vec::new();
|
||||||
let mut write_guard = x.value().write();
|
let mut write_guard = v.write();
|
||||||
for (ip, time) in &write_guard.members {
|
for (ip, time) in &write_guard.members {
|
||||||
if time.elapsed() > Duration::from_secs(30) {
|
if time.elapsed() > Duration::from_secs(30) {
|
||||||
list.push(*ip);
|
list.push(*ip);
|
||||||
@@ -122,13 +122,7 @@ impl IgmpServer {
|
|||||||
if !multicast_addr.is_multicast() {
|
if !multicast_addr.is_multicast() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let multi = {
|
let multi = self.add_multicast(multicast_addr);
|
||||||
self.multicast
|
|
||||||
.entry(multicast_addr)
|
|
||||||
.or_insert_with(|| Arc::new(RwLock::new(Multicast::new())))
|
|
||||||
.value()
|
|
||||||
.clone()
|
|
||||||
};
|
|
||||||
let mut guard = multi.write();
|
let mut guard = multi.write();
|
||||||
guard.members.insert(source, Instant::now());
|
guard.members.insert(source, Instant::now());
|
||||||
}
|
}
|
||||||
@@ -139,8 +133,8 @@ impl IgmpServer {
|
|||||||
if !multicast_addr.is_multicast() {
|
if !multicast_addr.is_multicast() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if let Some(entry) = self.multicast.get(&multicast_addr) {
|
if let Some(entry) = self.load(&multicast_addr) {
|
||||||
let mut guard = entry.value().write();
|
let mut guard = entry.write();
|
||||||
guard.map.remove(&source);
|
guard.map.remove(&source);
|
||||||
guard.members.remove(&source);
|
guard.members.remove(&source);
|
||||||
}
|
}
|
||||||
@@ -153,12 +147,7 @@ impl IgmpServer {
|
|||||||
if !multicast_addr.is_multicast() {
|
if !multicast_addr.is_multicast() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let multi = self
|
let multi = self.add_multicast(multicast_addr);
|
||||||
.multicast
|
|
||||||
.entry(multicast_addr)
|
|
||||||
.or_insert_with(|| Arc::new(RwLock::new(Multicast::new())))
|
|
||||||
.value()
|
|
||||||
.clone();
|
|
||||||
let mut guard = multi.write();
|
let mut guard = multi.write();
|
||||||
|
|
||||||
match group_record.record_type() {
|
match group_record.record_type() {
|
||||||
@@ -236,4 +225,9 @@ impl IgmpServer {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
fn add_multicast(&self, multicast_addr: Ipv4Addr) -> Arc<RwLock<Multicast>> {
|
||||||
|
let value = Arc::new(RwLock::new(Multicast::new()));
|
||||||
|
self.multicast.write().insert(multicast_addr, value.clone());
|
||||||
|
value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
use crossbeam_utils::atomic::AtomicCell;
|
|
||||||
use dashmap::DashMap;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddrV4};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddrV4};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
|
use dashmap::DashMap;
|
||||||
use socket2::{Domain, SockAddr, Socket, Type};
|
use socket2::{Domain, SockAddr, Socket, Type};
|
||||||
|
|
||||||
|
use packet::icmp::icmp;
|
||||||
|
use packet::icmp::icmp::HeaderOther;
|
||||||
|
use packet::ip::ipv4::packet::IpV4Packet;
|
||||||
|
|
||||||
use crate::channel::sender::ChannelSender;
|
use crate::channel::sender::ChannelSender;
|
||||||
use crate::cipher::Cipher;
|
use crate::cipher::Cipher;
|
||||||
use crate::handle::CurrentDeviceInfo;
|
use crate::handle::CurrentDeviceInfo;
|
||||||
use crate::protocol::body::ENCRYPTION_RESERVED;
|
use crate::ip_proxy::{send, ProxyHandler};
|
||||||
use crate::protocol::{NetPacket, Protocol, Version, MAX_TTL};
|
|
||||||
use packet::icmp::icmp;
|
|
||||||
use packet::icmp::icmp::HeaderOther;
|
|
||||||
use packet::ip::ipv4;
|
|
||||||
|
|
||||||
pub struct IcmpProxy {
|
pub struct IcmpProxy {
|
||||||
icmp_socket: Arc<Socket>,
|
icmp_socket: Arc<Socket>,
|
||||||
@@ -47,19 +47,19 @@ impl IcmpProxy {
|
|||||||
client_cipher,
|
client_cipher,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn icmp_socket(&self) -> Arc<Socket> {
|
pub fn icmp_handler(&self) -> IcmpHandler {
|
||||||
self.icmp_socket.clone()
|
IcmpHandler(self.icmp_socket.clone(), self.icmp_proxy_map.clone())
|
||||||
}
|
}
|
||||||
pub fn start(self) {
|
pub fn start(self) {
|
||||||
let mut buf = [0 as u8; 1500];
|
let mut buf = [0u8; 4096];
|
||||||
let data: &mut [MaybeUninit<u8>] = unsafe { std::mem::transmute(&mut buf[..]) };
|
let data: &mut [MaybeUninit<u8>] = unsafe { std::mem::transmute(&mut buf[12..]) };
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match self.recv(data) {
|
match self.recv(data) {
|
||||||
Ok((len, peer_ip)) => {
|
Ok((len, peer_ip)) => {
|
||||||
match peer_ip {
|
match peer_ip {
|
||||||
IpAddr::V4(peer_ip) => {
|
IpAddr::V4(peer_ip) => {
|
||||||
match ipv4::packet::IpV4Packet::new(&mut buf[..len]) {
|
match IpV4Packet::new(&mut buf[12..12 + len]) {
|
||||||
Ok(mut ipv4_packet) => {
|
Ok(mut ipv4_packet) => {
|
||||||
match icmp::IcmpPacket::new(ipv4_packet.payload()) {
|
match icmp::IcmpPacket::new(ipv4_packet.payload()) {
|
||||||
Ok(icmp_packet) => {
|
Ok(icmp_packet) => {
|
||||||
@@ -73,47 +73,14 @@ impl IcmpProxy {
|
|||||||
drop(entry);
|
drop(entry);
|
||||||
ipv4_packet.set_destination_ip(dest_ip);
|
ipv4_packet.set_destination_ip(dest_ip);
|
||||||
ipv4_packet.update_checksum();
|
ipv4_packet.update_checksum();
|
||||||
let current_device =
|
send(
|
||||||
self.current_device.load();
|
&mut buf,
|
||||||
let virtual_ip =
|
len,
|
||||||
current_device.virtual_ip();
|
dest_ip,
|
||||||
let connect_server =
|
&self.sender,
|
||||||
current_device.connect_server;
|
&self.current_device,
|
||||||
let mut net_packet =
|
&self.client_cipher,
|
||||||
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);
|
|
||||||
net_packet
|
|
||||||
.set_payload(ipv4_packet.buffer)
|
|
||||||
.unwrap();
|
|
||||||
if let Err(e) = self
|
|
||||||
.client_cipher
|
|
||||||
.encrypt_ipv4(&mut net_packet)
|
|
||||||
{
|
|
||||||
log::warn!("加密失败:{}", e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if self
|
|
||||||
.sender
|
|
||||||
.try_send_by_id(
|
|
||||||
net_packet.buffer(),
|
|
||||||
&dest_ip,
|
|
||||||
)
|
|
||||||
.is_err()
|
|
||||||
{
|
|
||||||
let _ = self.sender.try_send_main(
|
|
||||||
net_packet.buffer(),
|
|
||||||
connect_server,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -144,7 +111,42 @@ impl IcmpProxy {
|
|||||||
};
|
};
|
||||||
Ok((size, addr))
|
Ok((size, addr))
|
||||||
}
|
}
|
||||||
// fn send_to(&self, buf: &[u8], addr: SocketAddrV4) -> io::Result<usize> {
|
}
|
||||||
// self.icmp_socket.send_to(buf, &SockAddr::from(addr))
|
/// icmp用Identifier来区分,没有Identifier的一律不转发
|
||||||
// }
|
#[derive(Clone)]
|
||||||
|
pub struct IcmpHandler(Arc<Socket>, Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>>);
|
||||||
|
|
||||||
|
impl ProxyHandler for IcmpHandler {
|
||||||
|
fn recv_handle(
|
||||||
|
&self,
|
||||||
|
ipv4: &mut IpV4Packet<&mut [u8]>,
|
||||||
|
source: Ipv4Addr,
|
||||||
|
destination: Ipv4Addr,
|
||||||
|
) -> io::Result<bool> {
|
||||||
|
let dest_ip = ipv4.destination_ip();
|
||||||
|
//转发到代理目标地址
|
||||||
|
let icmp_packet = icmp::IcmpPacket::new(ipv4.payload())?;
|
||||||
|
match icmp_packet.header_other() {
|
||||||
|
HeaderOther::Identifier(id, seq) => {
|
||||||
|
self.1.insert((dest_ip, id, seq), source);
|
||||||
|
self.0.send_to(
|
||||||
|
ipv4.payload(),
|
||||||
|
&SockAddr::from(SocketAddrV4::new(dest_ip, 0)),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
log::warn!(
|
||||||
|
"不支持的ip代理Icmp协议:{}->{}->{}",
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
dest_ip
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_handle(&self, _ipv4: &mut IpV4Packet<&mut [u8]>) -> io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+182
-50
@@ -1,21 +1,68 @@
|
|||||||
|
use std::net::Ipv4Addr;
|
||||||
|
use std::net::SocketAddrV4;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::{io, thread};
|
||||||
|
|
||||||
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
|
use dashmap::DashMap;
|
||||||
|
use packet::ip::ipv4;
|
||||||
|
use tokio::net::UdpSocket;
|
||||||
|
|
||||||
|
use packet::ip::ipv4::packet::IpV4Packet;
|
||||||
|
|
||||||
use crate::channel::sender::ChannelSender;
|
use crate::channel::sender::ChannelSender;
|
||||||
use crate::cipher::Cipher;
|
use crate::cipher::Cipher;
|
||||||
use crate::handle::CurrentDeviceInfo;
|
use crate::handle::CurrentDeviceInfo;
|
||||||
use crate::ip_proxy::icmp_proxy::IcmpProxy;
|
#[cfg(not(target_os = "android"))]
|
||||||
use crate::ip_proxy::tcp_proxy::TcpProxy;
|
use crate::ip_proxy::icmp_proxy::IcmpHandler;
|
||||||
use crate::ip_proxy::udp_proxy::UdpProxy;
|
use crate::ip_proxy::tcp_proxy::{TcpHandler, TcpProxy};
|
||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crate::ip_proxy::udp_proxy::{UdpHandler, UdpProxy};
|
||||||
use dashmap::DashMap;
|
use crate::protocol;
|
||||||
use socket2::{SockAddr, Socket};
|
use crate::protocol::{NetPacket, Version, MAX_TTL};
|
||||||
use std::net::{Ipv4Addr, 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 icmp_proxy;
|
||||||
pub mod tcp_proxy;
|
pub mod tcp_proxy;
|
||||||
pub mod udp_proxy;
|
pub mod udp_proxy;
|
||||||
|
|
||||||
|
pub trait DashMapNew {
|
||||||
|
fn new0() -> Self;
|
||||||
|
fn new_cap(capacity: usize) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ProxyHandler {
|
||||||
|
fn recv_handle(
|
||||||
|
&self,
|
||||||
|
ipv4: &mut IpV4Packet<&mut [u8]>,
|
||||||
|
source: Ipv4Addr,
|
||||||
|
destination: Ipv4Addr,
|
||||||
|
) -> io::Result<bool>;
|
||||||
|
fn send_handle(&self, ipv4: &mut IpV4Packet<&mut [u8]>) -> io::Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K: 'a + Eq + std::hash::Hash, V: 'a> DashMapNew for DashMap<K, V> {
|
||||||
|
fn new0() -> Self {
|
||||||
|
Self::new_cap(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_cap(capacity: usize) -> Self {
|
||||||
|
let shard_amount = (thread::available_parallelism().map_or(4, |v| {
|
||||||
|
// https://github.com/rust-lang/rust/issues/115868
|
||||||
|
let n: usize = v.get() * 4;
|
||||||
|
if n == 0 {
|
||||||
|
log::warn!("available_parallelism=0");
|
||||||
|
println!("warn available_parallelism=0");
|
||||||
|
}
|
||||||
|
if n < 4 {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
n
|
||||||
|
}))
|
||||||
|
.next_power_of_two();
|
||||||
|
DashMap::with_capacity_and_shard_amount(capacity, shard_amount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)]
|
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)]
|
||||||
pub enum Protocol {
|
pub enum Protocol {
|
||||||
Icmp,
|
Icmp,
|
||||||
@@ -25,60 +72,145 @@ pub enum Protocol {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct IpProxyMap {
|
pub struct IpProxyMap {
|
||||||
pub(crate) tcp_proxy_port: u16,
|
#[cfg(not(target_os = "android"))]
|
||||||
pub(crate) udp_proxy_port: u16,
|
pub(crate) icmp_handler: IcmpHandler,
|
||||||
//真实源地址 -> 目的地址
|
pub(crate) tcp_handler: TcpHandler,
|
||||||
pub(crate) tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
pub(crate) udp_handler: UdpHandler,
|
||||||
pub(crate) udp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
|
||||||
// icmp用Identifier来区分,没有Identifier的一律不转发
|
|
||||||
pub(crate) icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
|
|
||||||
icmp_socket: Arc<Socket>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IpProxyMap {
|
|
||||||
pub fn send_icmp(&self, buf: &[u8], dest: &Ipv4Addr) -> io::Result<usize> {
|
|
||||||
self.icmp_socket
|
|
||||||
.send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
pub async fn init_proxy(
|
pub async fn init_proxy(
|
||||||
sender: ChannelSender,
|
sender: ChannelSender,
|
||||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
client_cipher: Cipher,
|
client_cipher: Cipher,
|
||||||
) -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> {
|
) -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> {
|
||||||
let tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new());
|
let tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new0());
|
||||||
let udp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new());
|
let udp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new0());
|
||||||
let icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>> = Arc::new(DashMap::new());
|
|
||||||
let tcp_listener = TcpListener::bind("0.0.0.0:0").await?;
|
let icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>> = Arc::new(DashMap::new0());
|
||||||
let udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
|
let udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
|
||||||
let tcp_proxy_port = tcp_listener.local_addr()?.port();
|
|
||||||
let 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());
|
|
||||||
let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0);
|
let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0);
|
||||||
let icmp_proxy = IcmpProxy::new(
|
let tcp_proxy = TcpProxy::new(addr, tcp_proxy_map.clone()).await?;
|
||||||
addr,
|
let tcp_handler = tcp_proxy.tcp_handler();
|
||||||
icmp_proxy_map.clone(),
|
let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map.clone())?;
|
||||||
sender.clone(),
|
let udp_handler = udp_proxy.udp_handler();
|
||||||
current_device.clone(),
|
|
||||||
client_cipher,
|
let icmp_handler = {
|
||||||
)?;
|
let icmp_proxy = icmp_proxy::IcmpProxy::new(
|
||||||
let icmp_socket = icmp_proxy.icmp_socket();
|
addr,
|
||||||
thread::spawn(move || {
|
icmp_proxy_map.clone(),
|
||||||
icmp_proxy.start();
|
sender.clone(),
|
||||||
});
|
current_device.clone(),
|
||||||
|
client_cipher.clone(),
|
||||||
|
)?;
|
||||||
|
let icmp_handler = icmp_proxy.icmp_handler();
|
||||||
|
thread::spawn(move || {
|
||||||
|
icmp_proxy.start();
|
||||||
|
});
|
||||||
|
icmp_handler
|
||||||
|
};
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
tcp_proxy,
|
tcp_proxy,
|
||||||
udp_proxy,
|
udp_proxy,
|
||||||
IpProxyMap {
|
IpProxyMap {
|
||||||
tcp_proxy_port,
|
tcp_handler,
|
||||||
udp_proxy_port,
|
udp_handler,
|
||||||
tcp_proxy_map,
|
icmp_handler,
|
||||||
udp_proxy_map,
|
|
||||||
icmp_proxy_map,
|
|
||||||
icmp_socket,
|
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
pub async fn init_proxy() -> 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());
|
||||||
|
let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0);
|
||||||
|
let udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
|
||||||
|
let tcp_proxy = TcpProxy::new(addr, tcp_proxy_map.clone()).await?;
|
||||||
|
let tcp_handler = tcp_proxy.tcp_handler();
|
||||||
|
let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map.clone())?;
|
||||||
|
let udp_handler = udp_proxy.udp_handler();
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
tcp_proxy,
|
||||||
|
udp_proxy,
|
||||||
|
IpProxyMap {
|
||||||
|
tcp_handler,
|
||||||
|
udp_handler,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send(
|
||||||
|
buf: &mut [u8],
|
||||||
|
data_len: usize,
|
||||||
|
dest_ip: Ipv4Addr,
|
||||||
|
sender: &ChannelSender,
|
||||||
|
current_device: &AtomicCell<CurrentDeviceInfo>,
|
||||||
|
client_cipher: &Cipher,
|
||||||
|
) {
|
||||||
|
let current_device = current_device.load();
|
||||||
|
let virtual_ip = current_device.virtual_ip();
|
||||||
|
|
||||||
|
let mut net_packet = NetPacket::new0(12 + data_len, buf).unwrap();
|
||||||
|
net_packet.set_version(Version::V1);
|
||||||
|
net_packet.set_protocol(protocol::Protocol::IpTurn);
|
||||||
|
net_packet.set_transport_protocol(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);
|
||||||
|
if let Err(e) = client_cipher.encrypt_ipv4(&mut net_packet) {
|
||||||
|
log::warn!("加密失败:{}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if sender
|
||||||
|
.try_send_by_id(net_packet.buffer(), &dest_ip)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
let connect_server = current_device.connect_server;
|
||||||
|
if let Err(e) = sender.send_main(net_packet.buffer(), connect_server) {
|
||||||
|
log::warn!("发送到目标失败:{},{}", e, connect_server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProxyHandler for IpProxyMap {
|
||||||
|
fn recv_handle(
|
||||||
|
&self,
|
||||||
|
ipv4: &mut IpV4Packet<&mut [u8]>,
|
||||||
|
source: Ipv4Addr,
|
||||||
|
destination: Ipv4Addr,
|
||||||
|
) -> io::Result<bool> {
|
||||||
|
match ipv4.protocol() {
|
||||||
|
ipv4::protocol::Protocol::Tcp => {
|
||||||
|
self.tcp_handler.recv_handle(ipv4, source, destination)
|
||||||
|
}
|
||||||
|
ipv4::protocol::Protocol::Udp => {
|
||||||
|
self.udp_handler.recv_handle(ipv4, source, destination)
|
||||||
|
}
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
|
ipv4::protocol::Protocol::Icmp => {
|
||||||
|
self.icmp_handler.recv_handle(ipv4, source, destination)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
log::warn!(
|
||||||
|
"不支持的ip代理ipv4协议{:?}:{}->{}->{}",
|
||||||
|
ipv4.protocol(),
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
ipv4.destination_ip()
|
||||||
|
);
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_handle(&self, ipv4: &mut IpV4Packet<&mut [u8]>) -> io::Result<()> {
|
||||||
|
match ipv4.protocol() {
|
||||||
|
ipv4::protocol::Protocol::Tcp => self.tcp_handler.send_handle(ipv4),
|
||||||
|
ipv4::protocol::Protocol::Udp => self.udp_handler.send_handle(ipv4),
|
||||||
|
_ => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+131
-28
@@ -1,24 +1,38 @@
|
|||||||
|
use crate::ip_proxy::ProxyHandler;
|
||||||
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
|
use packet::ip::ipv4::packet::IpV4Packet;
|
||||||
|
use packet::tcp::tcp::TcpPacket;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::{SocketAddr, SocketAddrV4};
|
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
use tokio::io::AsyncReadExt;
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
|
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
||||||
use tokio::net::{TcpListener, TcpStream};
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
|
||||||
pub struct TcpProxy {
|
pub struct TcpProxy {
|
||||||
|
tcp_proxy_port: u16,
|
||||||
tcp_listener: TcpListener,
|
tcp_listener: TcpListener,
|
||||||
|
//真实源地址 -> 目的地址
|
||||||
tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcpProxy {
|
impl TcpProxy {
|
||||||
pub fn new(
|
pub async fn new(
|
||||||
tcp_listener: TcpListener,
|
addr: SocketAddrV4,
|
||||||
tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
||||||
) -> Self {
|
) -> io::Result<Self> {
|
||||||
Self {
|
let tcp_listener = TcpListener::bind(addr).await?;
|
||||||
|
Ok(Self {
|
||||||
|
tcp_proxy_port: tcp_listener.local_addr()?.port(),
|
||||||
tcp_listener,
|
tcp_listener,
|
||||||
tcp_proxy_map,
|
tcp_proxy_map,
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
pub fn tcp_handler(&self) -> TcpHandler {
|
||||||
|
TcpHandler(self.tcp_proxy_port, self.tcp_proxy_map.clone())
|
||||||
}
|
}
|
||||||
pub async fn start(self) {
|
pub async fn start(self) {
|
||||||
let tcp_listener = self.tcp_listener;
|
let tcp_listener = self.tcp_listener;
|
||||||
@@ -30,19 +44,36 @@ impl TcpProxy {
|
|||||||
if let Some(entry) = tcp_proxy_map.get(&sender_addr) {
|
if let Some(entry) = tcp_proxy_map.get(&sender_addr) {
|
||||||
let dest_addr = *entry.value();
|
let dest_addr = *entry.value();
|
||||||
drop(entry);
|
drop(entry);
|
||||||
let peer_tcp_stream = match TcpStream::connect(dest_addr).await {
|
|
||||||
Ok(peer_tcp_stream) => peer_tcp_stream,
|
|
||||||
Err(e) => {
|
|
||||||
log::warn!(
|
|
||||||
"tcp代理异常:{:?},来源:{},目标:{}",
|
|
||||||
e,
|
|
||||||
sender_addr,
|
|
||||||
dest_addr
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
let peer_tcp_stream = match tokio::time::timeout(
|
||||||
|
Duration::from_secs(5),
|
||||||
|
TcpStream::connect(dest_addr),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(peer_tcp_stream) => match peer_tcp_stream {
|
||||||
|
Ok(peer_tcp_stream) => peer_tcp_stream,
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!(
|
||||||
|
"tcp代理异常:{:?},来源:{},目标:{}",
|
||||||
|
e,
|
||||||
|
sender_addr,
|
||||||
|
dest_addr
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!(
|
||||||
|
"tcp代理异常:{:?},来源:{},目标:{}",
|
||||||
|
e,
|
||||||
|
sender_addr,
|
||||||
|
dest_addr
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
if let Err(e) = proxy(tcp_stream, peer_tcp_stream).await {
|
if let Err(e) = proxy(tcp_stream, peer_tcp_stream).await {
|
||||||
log::warn!("{}->{},{}", sender_addr, dest_addr, e);
|
log::warn!("{}->{},{}", sender_addr, dest_addr, e);
|
||||||
}
|
}
|
||||||
@@ -61,15 +92,87 @@ impl TcpProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn proxy(mut client: TcpStream, mut server: TcpStream) -> io::Result<()> {
|
async fn proxy(client: TcpStream, server: TcpStream) -> io::Result<()> {
|
||||||
let (mut client_reader, mut client_writer) = client.split();
|
let (client_read, client_write) = client.into_split();
|
||||||
let (mut server_reader, mut server_writer) = server.split();
|
let (server_read, server_write) = server.into_split();
|
||||||
|
let time = Arc::new(AtomicCell::new(Instant::now()));
|
||||||
|
let time1 = time.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = copy(client_read, server_write, &time1).await {
|
||||||
|
log::warn!("{:?}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
copy(server_read, client_write, &time).await
|
||||||
|
}
|
||||||
|
|
||||||
let client_to_server = tokio::io::copy(&mut client_reader, &mut server_writer);
|
async fn copy(
|
||||||
let server_to_client = tokio::io::copy(&mut server_reader, &mut client_writer);
|
mut read: OwnedReadHalf,
|
||||||
|
mut write: OwnedWriteHalf,
|
||||||
let (r1, r2) = tokio::join!(client_to_server, server_to_client);
|
time: &AtomicCell<Instant>,
|
||||||
r1?;
|
) -> io::Result<()> {
|
||||||
r2?;
|
let mut buf = [0; 10240];
|
||||||
|
loop {
|
||||||
|
tokio::select! {
|
||||||
|
result = read.read(&mut buf) =>{
|
||||||
|
let len = result?;
|
||||||
|
if len==0{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
write.write_all(&buf[..len]).await?;
|
||||||
|
time.store(Instant::now());
|
||||||
|
}
|
||||||
|
_ = tokio::time::sleep(Duration::from_secs(600)) =>{
|
||||||
|
if time.load().elapsed()>=Duration::from_secs(580){
|
||||||
|
//读写均超时再退出
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TcpHandler(u16, Arc<DashMap<SocketAddrV4, SocketAddrV4>>);
|
||||||
|
|
||||||
|
impl ProxyHandler for TcpHandler {
|
||||||
|
fn recv_handle(
|
||||||
|
&self,
|
||||||
|
ipv4: &mut IpV4Packet<&mut [u8]>,
|
||||||
|
source: Ipv4Addr,
|
||||||
|
destination: Ipv4Addr,
|
||||||
|
) -> io::Result<bool> {
|
||||||
|
let dest_ip = ipv4.destination_ip();
|
||||||
|
//转发到代理目标地址
|
||||||
|
let mut tcp_packet = 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(self.0);
|
||||||
|
tcp_packet.update_checksum();
|
||||||
|
ipv4.set_destination_ip(destination);
|
||||||
|
ipv4.update_checksum();
|
||||||
|
let key = SocketAddrV4::new(source, source_port);
|
||||||
|
//https://github.com/crossbeam-rs/crossbeam/issues/1023
|
||||||
|
self.1.insert(key, SocketAddrV4::new(dest_ip, dest_port));
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_handle(&self, ipv4: &mut IpV4Packet<&mut [u8]>) -> io::Result<()> {
|
||||||
|
let src_ip = ipv4.source_ip();
|
||||||
|
let dest_ip = ipv4.destination_ip();
|
||||||
|
let dest_addr = {
|
||||||
|
let tcp_packet = TcpPacket::new(src_ip, dest_ip, ipv4.payload_mut())?;
|
||||||
|
SocketAddrV4::new(dest_ip, tcp_packet.destination_port())
|
||||||
|
};
|
||||||
|
if let Some(entry) = self.1.get(&dest_addr) {
|
||||||
|
let source_addr = entry.value();
|
||||||
|
let source_ip = *source_addr.ip();
|
||||||
|
let mut tcp_packet = TcpPacket::new(source_ip, dest_ip, ipv4.payload_mut())?;
|
||||||
|
tcp_packet.set_source_port(source_addr.port());
|
||||||
|
tcp_packet.update_checksum();
|
||||||
|
ipv4.set_source_ip(source_ip);
|
||||||
|
ipv4.update_checksum();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,26 +1,45 @@
|
|||||||
|
use crate::ip_proxy::{DashMapNew, ProxyHandler};
|
||||||
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
|
use packet::ip::ipv4::packet::IpV4Packet;
|
||||||
|
use packet::udp::udp::UdpPacket;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::{SocketAddr, SocketAddrV4};
|
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::net::UdpSocket;
|
use tokio::net::UdpSocket;
|
||||||
|
use tokio::time::Instant;
|
||||||
|
|
||||||
/// 一个udp代理,作用是利用系统协议栈,将udp数据报解析出来再转发到目的地址
|
/// 一个udp代理,作用是利用系统协议栈,将udp数据报解析出来再转发到目的地址
|
||||||
pub struct UdpProxy {
|
pub struct UdpProxy {
|
||||||
|
udp_proxy_port: u16,
|
||||||
udp_socket: Arc<UdpSocket>,
|
udp_socket: Arc<UdpSocket>,
|
||||||
map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UdpProxy {
|
impl UdpProxy {
|
||||||
pub fn new(udp_socket: UdpSocket, map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>) -> Self {
|
pub fn new(
|
||||||
|
udp_socket: UdpSocket,
|
||||||
|
map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
||||||
|
) -> io::Result<Self> {
|
||||||
let udp_socket = Arc::new(udp_socket);
|
let udp_socket = Arc::new(udp_socket);
|
||||||
Self { udp_socket, map }
|
let udp_proxy_port = udp_socket.local_addr()?.port();
|
||||||
|
Ok(Self {
|
||||||
|
udp_proxy_port,
|
||||||
|
udp_socket,
|
||||||
|
map,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn udp_handler(&self) -> UdpHandler {
|
||||||
|
UdpHandler(self.udp_proxy_port, self.map.clone())
|
||||||
}
|
}
|
||||||
pub async fn start(self) {
|
pub async fn start(self) {
|
||||||
let map = self.map;
|
let map = self.map;
|
||||||
let udp_socket = self.udp_socket;
|
let udp_socket = self.udp_socket;
|
||||||
let mut buf = [0u8; 65536];
|
let mut buf = [0u8; 65536];
|
||||||
let inner_map: Arc<DashMap<SocketAddrV4, Arc<UdpSocket>>> = Arc::new(DashMap::new());
|
|
||||||
|
let inner_map: Arc<DashMap<SocketAddrV4, (Arc<UdpSocket>, Arc<AtomicCell<Instant>>)>> =
|
||||||
|
Arc::new(DashMap::new0());
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match udp_socket.recv_from(&mut buf).await {
|
match udp_socket.recv_from(&mut buf).await {
|
||||||
@@ -47,29 +66,36 @@ impl UdpProxy {
|
|||||||
async fn start0(
|
async fn start0(
|
||||||
buf: &[u8],
|
buf: &[u8],
|
||||||
sender_addr: SocketAddrV4,
|
sender_addr: SocketAddrV4,
|
||||||
inner_map: &Arc<DashMap<SocketAddrV4, Arc<UdpSocket>>>,
|
inner_map: &Arc<DashMap<SocketAddrV4, (Arc<UdpSocket>, Arc<AtomicCell<Instant>>)>>,
|
||||||
map: &Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
map: &Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
|
||||||
udp_socket: &Arc<UdpSocket>,
|
udp_socket: &Arc<UdpSocket>,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
if let Some(entry) = inner_map.get(&sender_addr) {
|
if let Some(entry) = inner_map.get(&sender_addr) {
|
||||||
let udp = entry.value().clone();
|
entry.value().1.store(Instant::now());
|
||||||
|
let udp = entry.value().0.clone();
|
||||||
drop(entry);
|
drop(entry);
|
||||||
udp.send(buf).await?;
|
udp.send(buf).await?;
|
||||||
} else if let Some(entry) = map.get(&sender_addr) {
|
} else if let Some(entry) = map.get(&sender_addr) {
|
||||||
let dest_addr = *entry.value();
|
let dest_addr = *entry.value();
|
||||||
drop(entry);
|
drop(entry);
|
||||||
let peer_udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
|
//先使用相同的端口,冲突了再随机端口
|
||||||
|
let peer_udp_socket = match UdpSocket::bind(format!("0.0.0.0:{}", sender_addr.port())).await
|
||||||
|
{
|
||||||
|
Ok(udp) => udp,
|
||||||
|
Err(_) => UdpSocket::bind("0.0.0.0:0").await?,
|
||||||
|
};
|
||||||
peer_udp_socket.connect(dest_addr).await?;
|
peer_udp_socket.connect(dest_addr).await?;
|
||||||
peer_udp_socket.send(buf).await?;
|
peer_udp_socket.send(buf).await?;
|
||||||
let peer_udp_socket = Arc::new(peer_udp_socket);
|
let peer_udp_socket = Arc::new(peer_udp_socket);
|
||||||
let inner_map = inner_map.clone();
|
let inner_map = inner_map.clone();
|
||||||
inner_map.insert(sender_addr, peer_udp_socket.clone());
|
let time = Arc::new(AtomicCell::new(Instant::now()));
|
||||||
|
inner_map.insert(sender_addr, (peer_udp_socket.clone(), time.clone()));
|
||||||
let udp_socket = udp_socket.clone();
|
let udp_socket = udp_socket.clone();
|
||||||
let map = map.clone();
|
let map = map.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut buf = [0u8; 65536];
|
let mut buf = [0u8; 65536];
|
||||||
loop {
|
loop {
|
||||||
match tokio::time::timeout(Duration::from_secs(300), peer_udp_socket.recv(&mut buf))
|
match tokio::time::timeout(Duration::from_secs(600), peer_udp_socket.recv(&mut buf))
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(rs) => match rs {
|
Ok(rs) => match rs {
|
||||||
@@ -96,9 +122,11 @@ async fn start0(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
//超时关闭
|
if time.load().elapsed() > Duration::from_secs(580) {
|
||||||
log::warn!("udp代理超时关闭,来源:{},目标:{}", sender_addr, dest_addr);
|
//超时关闭
|
||||||
break;
|
log::warn!("udp代理超时关闭,来源:{},目标:{}", sender_addr, dest_addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,3 +136,47 @@ async fn start0(
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct UdpHandler(u16, Arc<DashMap<SocketAddrV4, SocketAddrV4>>);
|
||||||
|
|
||||||
|
impl ProxyHandler for UdpHandler {
|
||||||
|
fn recv_handle(
|
||||||
|
&self,
|
||||||
|
ipv4: &mut IpV4Packet<&mut [u8]>,
|
||||||
|
source: Ipv4Addr,
|
||||||
|
destination: Ipv4Addr,
|
||||||
|
) -> io::Result<bool> {
|
||||||
|
let dest_ip = ipv4.destination_ip();
|
||||||
|
//转发到代理目标地址
|
||||||
|
let mut udp_packet = 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(self.0);
|
||||||
|
udp_packet.update_checksum();
|
||||||
|
ipv4.set_destination_ip(destination);
|
||||||
|
ipv4.update_checksum();
|
||||||
|
let key = SocketAddrV4::new(source, source_port);
|
||||||
|
self.1.insert(key, SocketAddrV4::new(dest_ip, dest_port));
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_handle(&self, ipv4: &mut IpV4Packet<&mut [u8]>) -> io::Result<()> {
|
||||||
|
let src_ip = ipv4.source_ip();
|
||||||
|
let dest_ip = ipv4.destination_ip();
|
||||||
|
let dest_addr = {
|
||||||
|
let udp_packet = UdpPacket::new(src_ip, dest_ip, ipv4.payload_mut())?;
|
||||||
|
SocketAddrV4::new(dest_ip, udp_packet.destination_port())
|
||||||
|
};
|
||||||
|
if let Some(entry) = self.1.get(&dest_addr) {
|
||||||
|
let source_addr = entry.value();
|
||||||
|
let source_ip = *source_addr.ip();
|
||||||
|
let mut udp_packet = UdpPacket::new(source_ip, dest_ip, ipv4.payload_mut())?;
|
||||||
|
udp_packet.set_source_port(source_addr.port());
|
||||||
|
udp_packet.update_checksum();
|
||||||
|
ipv4.set_source_ip(source_ip);
|
||||||
|
ipv4.update_checksum();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+2
-1
@@ -1,5 +1,5 @@
|
|||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
pub const VNT_VERSION: &'static str = "1.2.2";
|
pub const VNT_VERSION: &'static str = "1.2.7";
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
pub mod channel;
|
pub mod channel;
|
||||||
@@ -9,6 +9,7 @@ pub mod error;
|
|||||||
pub mod external_route;
|
pub mod external_route;
|
||||||
pub mod handle;
|
pub mod handle;
|
||||||
pub mod igmp_server;
|
pub mod igmp_server;
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
pub mod ip_proxy;
|
pub mod ip_proxy;
|
||||||
pub mod nat;
|
pub mod nat;
|
||||||
pub mod proto;
|
pub mod proto;
|
||||||
|
|||||||
+36
-19
@@ -1,7 +1,9 @@
|
|||||||
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
|
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
@@ -22,7 +24,7 @@ pub fn local_ipv4() -> io::Result<Ipv4Addr> {
|
|||||||
|
|
||||||
pub fn local_ipv6() -> io::Result<Ipv6Addr> {
|
pub fn local_ipv6() -> io::Result<Ipv6Addr> {
|
||||||
let socket = UdpSocket::bind("[::]:0")?;
|
let socket = UdpSocket::bind("[::]:0")?;
|
||||||
socket.connect("[2001:4860:4860::8888]:80")?;
|
socket.connect("[2001:4860:4860:0000:0000:0000:0000:8888]:80")?;
|
||||||
let addr = socket.local_addr()?;
|
let addr = socket.local_addr()?;
|
||||||
match addr.ip() {
|
match addr.ip() {
|
||||||
IpAddr::V4(_) => Ok(Ipv6Addr::UNSPECIFIED),
|
IpAddr::V4(_) => Ok(Ipv6Addr::UNSPECIFIED),
|
||||||
@@ -54,6 +56,7 @@ pub fn local_ipv6_addr(port: u16) -> SocketAddrV6 {
|
|||||||
pub struct NatTest {
|
pub struct NatTest {
|
||||||
stun_server: Vec<String>,
|
stun_server: Vec<String>,
|
||||||
info: Arc<Mutex<NatInfo>>,
|
info: Arc<Mutex<NatInfo>>,
|
||||||
|
time: Arc<AtomicCell<Instant>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NatType> for PunchNatType {
|
impl From<NatType> for PunchNatType {
|
||||||
@@ -75,7 +78,7 @@ impl Into<NatType> for PunchNatType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NatTest {
|
impl NatTest {
|
||||||
pub async fn new(
|
pub fn new(
|
||||||
mut stun_server: Vec<String>,
|
mut stun_server: Vec<String>,
|
||||||
public_ip: Ipv4Addr,
|
public_ip: Ipv4Addr,
|
||||||
public_port: u16,
|
public_port: u16,
|
||||||
@@ -84,25 +87,42 @@ impl NatTest {
|
|||||||
) -> NatTest {
|
) -> NatTest {
|
||||||
let server = stun_server[0].clone();
|
let server = stun_server[0].clone();
|
||||||
stun_server.resize(3, server);
|
stun_server.resize(3, server);
|
||||||
let nat_info = Self::re_test_(
|
let nat_info = NatInfo::new(
|
||||||
&stun_server,
|
vec![public_ip],
|
||||||
public_ip,
|
|
||||||
public_port,
|
public_port,
|
||||||
|
0,
|
||||||
local_ipv4_addr,
|
local_ipv4_addr,
|
||||||
ipv6_addr,
|
ipv6_addr,
|
||||||
)
|
NatType::Cone,
|
||||||
.await;
|
);
|
||||||
let info = Arc::new(Mutex::new(nat_info));
|
let info = Arc::new(Mutex::new(nat_info));
|
||||||
NatTest { stun_server, info }
|
NatTest {
|
||||||
|
stun_server,
|
||||||
|
info,
|
||||||
|
time: Arc::new(AtomicCell::new(Instant::now())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn can_update(&self) -> bool {
|
||||||
|
let last = self.time.load();
|
||||||
|
last.elapsed() > Duration::from_secs(10)
|
||||||
|
&& self.time.compare_exchange(last, Instant::now()).is_ok()
|
||||||
}
|
}
|
||||||
pub fn nat_info(&self) -> NatInfo {
|
pub fn nat_info(&self) -> NatInfo {
|
||||||
self.info.lock().clone()
|
self.info.lock().clone()
|
||||||
}
|
}
|
||||||
pub fn update_addr(&self, ip: Ipv4Addr, port: u16) {
|
pub fn update_addr(&self, ip: Ipv4Addr, port: u16) {
|
||||||
let mut guard = self.info.lock();
|
if !ip.is_multicast()
|
||||||
guard.public_port = port;
|
&& !ip.is_broadcast()
|
||||||
if !guard.public_ips.contains(&ip) {
|
&& !ip.is_unspecified()
|
||||||
guard.public_ips.push(ip);
|
&& !ip.is_loopback()
|
||||||
|
&& !ip.is_private()
|
||||||
|
&& port != 0
|
||||||
|
{
|
||||||
|
let mut guard = self.info.lock();
|
||||||
|
guard.public_port = port;
|
||||||
|
if !guard.public_ips.contains(&ip) {
|
||||||
|
guard.public_ips.push(ip);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub async fn re_test(
|
pub async fn re_test(
|
||||||
@@ -120,6 +140,7 @@ impl NatTest {
|
|||||||
ipv6_addr,
|
ipv6_addr,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
log::info!("探测nat类型={:?}", info);
|
||||||
*self.info.lock() = info.clone();
|
*self.info.lock() = info.clone();
|
||||||
info
|
info
|
||||||
}
|
}
|
||||||
@@ -131,13 +152,9 @@ impl NatTest {
|
|||||||
ipv6_addr: SocketAddrV6,
|
ipv6_addr: SocketAddrV6,
|
||||||
) -> NatInfo {
|
) -> NatInfo {
|
||||||
return match stun_test::stun_test_nat(stun_server.clone()).await {
|
return match stun_test::stun_test_nat(stun_server.clone()).await {
|
||||||
Ok((nat_type, ips, port_range)) => {
|
Ok((nat_type, mut public_ips, port_range)) => {
|
||||||
let mut public_ips = Vec::new();
|
if !public_ips.contains(&public_ip) {
|
||||||
public_ips.push(Ipv4Addr::from(public_ip));
|
public_ips.push(public_ip)
|
||||||
for ip in ips {
|
|
||||||
if ip != public_ip {
|
|
||||||
public_ips.push(ip);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
NatInfo::new(
|
NatInfo::new(
|
||||||
public_ips,
|
public_ips,
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
use std::{fmt, io};
|
use std::{fmt, io};
|
||||||
|
|
||||||
pub const ENCRYPTION_RESERVED: usize = 32;
|
pub const ENCRYPTION_RESERVED: usize = 16 + 32 + 12;
|
||||||
|
pub const AES_GCM_ENCRYPTION_RESERVED: usize = 32;
|
||||||
|
pub const RSA_ENCRYPTION_RESERVED: usize = 32;
|
||||||
|
|
||||||
/* aes_gcm加密数据体
|
/* aes_gcm加密数据体
|
||||||
0 15 31
|
0 15 31
|
||||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
|
|||||||
"length overflow",
|
"length overflow",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
//加密需要预留32字节
|
//加密需要预留ENCRYPTION_RESERVED字节
|
||||||
let data_len = buffer.as_ref().len() - ENCRYPTION_RESERVED;
|
let data_len = buffer.as_ref().len() - ENCRYPTION_RESERVED;
|
||||||
Self::new0(data_len, buffer)
|
Self::new0(data_len, buffer)
|
||||||
}
|
}
|
||||||
@@ -155,7 +155,7 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
|
|||||||
}
|
}
|
||||||
/// 网关通信的标识
|
/// 网关通信的标识
|
||||||
pub fn is_gateway(&self) -> bool {
|
pub fn is_gateway(&self) -> bool {
|
||||||
self.buffer.as_ref()[0] & 0x50 == 0x50
|
self.buffer.as_ref()[0] & 0x40 == 0x40
|
||||||
}
|
}
|
||||||
pub fn version(&self) -> Version {
|
pub fn version(&self) -> Version {
|
||||||
Version::from(self.buffer.as_ref()[0] & 0x0F)
|
Version::from(self.buffer.as_ref()[0] & 0x0F)
|
||||||
@@ -187,7 +187,7 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
|
|||||||
|
|
||||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
||||||
pub fn buffer_mut(&mut self) -> &mut [u8] {
|
pub fn buffer_mut(&mut self) -> &mut [u8] {
|
||||||
self.buffer.as_mut()
|
&mut self.buffer.as_mut()[..self.data_len]
|
||||||
}
|
}
|
||||||
pub fn set_encrypt_flag(&mut self, is_encrypt: bool) {
|
pub fn set_encrypt_flag(&mut self, is_encrypt: bool) {
|
||||||
if is_encrypt {
|
if is_encrypt {
|
||||||
@@ -198,6 +198,7 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
|||||||
}
|
}
|
||||||
pub fn set_gateway_flag(&mut self, is_gateway: bool) {
|
pub fn set_gateway_flag(&mut self, is_gateway: bool) {
|
||||||
if is_gateway {
|
if is_gateway {
|
||||||
|
// 后面的版本再改为0x40,改了之后不兼容1.2.5之前的版本
|
||||||
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x50
|
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x50
|
||||||
} else {
|
} else {
|
||||||
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF
|
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ pub fn delete_device(_device_type: DeviceType) {
|
|||||||
.output()
|
.output()
|
||||||
.expect("sh exec error!");
|
.expect("sh exec error!");
|
||||||
if !delete_tun.status.success() {
|
if !delete_tun.status.success() {
|
||||||
log::warn!("删除网卡失败:{:?}",delete_tun);
|
log::warn!("删除网卡失败:{:?}", delete_tun);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ use bytes::BufMut;
|
|||||||
use packet::ethernet;
|
use packet::ethernet;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::os::unix::io::AsRawFd;
|
|
||||||
#[cfg(any(target_os = "linux"))]
|
#[cfg(any(target_os = "linux"))]
|
||||||
use tun::platform::linux::Device;
|
use tun::platform::linux::Device;
|
||||||
#[cfg(any(target_os = "macos"))]
|
#[cfg(any(target_os = "macos"))]
|
||||||
@@ -13,6 +12,7 @@ use tun::platform::macos::Device;
|
|||||||
use tun::platform::posix::{Reader, Writer};
|
use tun::platform::posix::{Reader, Writer};
|
||||||
|
|
||||||
use packet::ethernet::packet::EthernetPacket;
|
use packet::ethernet::packet::EthernetPacket;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum DeviceW {
|
pub enum DeviceW {
|
||||||
Tun(Writer),
|
Tun(Writer),
|
||||||
@@ -63,10 +63,17 @@ impl DeviceWriter {
|
|||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
buf.put_u16(libc::ETH_P_IP as u16);
|
buf.put_u16(libc::ETH_P_IP as u16);
|
||||||
buf.extend_from_slice(packet);
|
buf.extend_from_slice(packet);
|
||||||
writer.write_all(&buf)
|
let len = writer.write(&buf)?;
|
||||||
|
if len != buf.len() {
|
||||||
|
log::error!("tun write error");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
writer.write_all(packet)
|
let len = writer.write(packet)?;
|
||||||
|
if len != packet.len() {
|
||||||
|
log::error!("tun write error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
///tun网卡写入ipv4数据
|
///tun网卡写入ipv4数据
|
||||||
pub fn write_ipv4_tun(&self, buf: &[u8]) -> io::Result<()> {
|
pub fn write_ipv4_tun(&self, buf: &[u8]) -> io::Result<()> {
|
||||||
@@ -104,16 +111,17 @@ impl DeviceWriter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn close(&self) -> io::Result<()> {
|
pub fn close(&self) -> io::Result<()> {
|
||||||
unsafe {
|
//早期使用close直接切断网卡,现在并不需要这么做也能正常关闭
|
||||||
match &self.writer {
|
// unsafe {
|
||||||
DeviceW::Tun(writer) => {
|
// match &self.writer {
|
||||||
libc::close(writer.as_raw_fd());
|
// DeviceW::Tun(writer) => {
|
||||||
}
|
// libc::close(writer.as_raw_fd());
|
||||||
DeviceW::Tap((writer, _)) => {
|
// }
|
||||||
libc::close(writer.as_raw_fd());
|
// DeviceW::Tap((writer, _)) => {
|
||||||
}
|
// libc::close(writer.as_raw_fd());
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn is_tun(&self) -> bool {
|
pub fn is_tun(&self) -> bool {
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ impl DeviceWriter {
|
|||||||
// 当前网段路由
|
// 当前网段路由
|
||||||
dev.add_route(address, netmask, gateway, 1)?;
|
dev.add_route(address, netmask, gateway, 1)?;
|
||||||
// 广播和组播路由
|
// 广播和组播路由
|
||||||
dev.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
// dev.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
||||||
dev.add_route(
|
dev.add_route(
|
||||||
Ipv4Addr::from([224, 0, 0, 0]),
|
Ipv4Addr::from([224, 0, 0, 0]),
|
||||||
Ipv4Addr::from([240, 0, 0, 0]),
|
Ipv4Addr::from([240, 0, 0, 0]),
|
||||||
@@ -230,8 +230,8 @@ fn create_tun(
|
|||||||
}
|
}
|
||||||
// 当前网段路由
|
// 当前网段路由
|
||||||
tun_device.add_route(address, netmask, gateway, 1)?;
|
tun_device.add_route(address, netmask, gateway, 1)?;
|
||||||
// 广播和组播路由
|
// 广播和组播路由 修改了广播路由会导致发不出广播
|
||||||
tun_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
// tun_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
||||||
tun_device.add_route(
|
tun_device.add_route(
|
||||||
Ipv4Addr::from([224, 0, 0, 0]),
|
Ipv4Addr::from([224, 0, 0, 0]),
|
||||||
Ipv4Addr::from([240, 0, 0, 0]),
|
Ipv4Addr::from([240, 0, 0, 0]),
|
||||||
@@ -309,7 +309,7 @@ fn create_tap(
|
|||||||
tap_device.add_route(*address, *netmask, gateway, 1)?;
|
tap_device.add_route(*address, *netmask, gateway, 1)?;
|
||||||
}
|
}
|
||||||
// 广播和组播路由
|
// 广播和组播路由
|
||||||
tap_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
// tap_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
||||||
tap_device.add_route(
|
tap_device.add_route(
|
||||||
Ipv4Addr::from([224, 0, 0, 0]),
|
Ipv4Addr::from([224, 0, 0, 0]),
|
||||||
Ipv4Addr::from([240, 0, 0, 0]),
|
Ipv4Addr::from([240, 0, 0, 0]),
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
winreg = "0.7"
|
winreg = "0.51.0"
|
||||||
scopeguard = "1.1"
|
scopeguard = "1.1"
|
||||||
libloading = "0.7"
|
libloading = "0.8.0"
|
||||||
widestring = "0.4"
|
widestring = "1.0.2"
|
||||||
once_cell = "1.8"
|
once_cell = "1.8"
|
||||||
itertools = "0.10.1"
|
itertools = "0.11.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
[dependencies.winapi]
|
[dependencies.winapi]
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
@@ -29,5 +29,9 @@ features = [
|
|||||||
"winerror",
|
"winerror",
|
||||||
"ipexport",
|
"ipexport",
|
||||||
"iphlpapi",
|
"iphlpapi",
|
||||||
"handleapi"
|
"handleapi",
|
||||||
|
"ifdef",
|
||||||
|
"minwinbase",
|
||||||
|
"basetsd",
|
||||||
|
"impl-default"
|
||||||
]
|
]
|
||||||
@@ -119,14 +119,14 @@ pub fn create_interface() -> io::Result<NET_LUID> {
|
|||||||
KEY_QUERY_VALUE | KEY_NOTIFY,
|
KEY_QUERY_VALUE | KEY_NOTIFY,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let key = RegKey::predef(key);
|
let key = RegKey::predef(key as _);
|
||||||
|
|
||||||
while let Err(_) = key.get_value::<DWORD, &str>("*IfType") {
|
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() as _, TRUE, REG_NOTIFY_CHANGE_NAME, 2000)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Err(_) = key.get_value::<DWORD, &str>("NetLuidIndex") {
|
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() as _, TRUE, REG_NOTIFY_CHANGE_NAME, 2000)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let if_type: DWORD = key.get_value("*IfType")?;
|
let if_type: DWORD = key.get_value("*IfType")?;
|
||||||
@@ -179,7 +179,7 @@ pub fn check_interface(luid: &NET_LUID) -> io::Result<()> {
|
|||||||
DIREG_DRV,
|
DIREG_DRV,
|
||||||
KEY_QUERY_VALUE | KEY_NOTIFY,
|
KEY_QUERY_VALUE | KEY_NOTIFY,
|
||||||
) {
|
) {
|
||||||
Ok(key) => RegKey::predef(key),
|
Ok(key) => RegKey::predef(key as _),
|
||||||
Err(_) => continue,
|
Err(_) => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -248,7 +248,7 @@ pub fn delete_interface(luid: &NET_LUID) -> io::Result<()> {
|
|||||||
DIREG_DRV,
|
DIREG_DRV,
|
||||||
KEY_QUERY_VALUE | KEY_NOTIFY,
|
KEY_QUERY_VALUE | KEY_NOTIFY,
|
||||||
) {
|
) {
|
||||||
Ok(key) => RegKey::predef(key),
|
Ok(key) => RegKey::predef(key as _),
|
||||||
Err(_) => continue,
|
Err(_) => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,8 @@ impl TapDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete(self) -> io::Result<()> {
|
pub fn delete(self) -> io::Result<()> {
|
||||||
iface::delete_interface(&self.luid)
|
// iface::delete_interface(&self.luid)
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
use winapi::um::{handleapi, synchapi, winbase, winnt};
|
use winapi::um::{synchapi, winbase, winnt};
|
||||||
|
|
||||||
use crate::{decode_utf16, encode_utf16, ffi, netsh, route, IFace};
|
use crate::{decode_utf16, encode_utf16, ffi, netsh, route, IFace};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
mod log;
|
|
||||||
pub mod packet;
|
pub mod packet;
|
||||||
|
mod wintun_log;
|
||||||
mod wintun_raw;
|
mod wintun_raw;
|
||||||
|
|
||||||
/// The maximum size of wintun's internal ring buffer (in bytes)
|
/// The maximum size of wintun's internal ring buffer (in bytes)
|
||||||
@@ -80,7 +80,7 @@ impl TunDevice {
|
|||||||
let guid_struct: wintun_raw::GUID = unsafe { std::mem::transmute(guid) };
|
let guid_struct: wintun_raw::GUID = unsafe { std::mem::transmute(guid) };
|
||||||
let guid_ptr = &guid_struct as *const wintun_raw::GUID;
|
let guid_ptr = &guid_struct as *const wintun_raw::GUID;
|
||||||
|
|
||||||
log::set_default_logger_if_unset(&win_tun);
|
wintun_log::set_default_logger_if_unset(&win_tun);
|
||||||
|
|
||||||
//SAFETY: the function is loaded from the wintun dll properly, we are providing valid
|
//SAFETY: the function is loaded from the wintun dll properly, we are providing valid
|
||||||
//pointers, and all the strings are correct null terminated UTF-16. This safety rationale
|
//pointers, and all the strings are correct null terminated UTF-16. This safety rationale
|
||||||
@@ -88,6 +88,7 @@ impl TunDevice {
|
|||||||
let adapter =
|
let adapter =
|
||||||
win_tun.WintunCreateAdapter(pool_utf16.as_ptr(), name_utf16.as_ptr(), guid_ptr);
|
win_tun.WintunCreateAdapter(pool_utf16.as_ptr(), name_utf16.as_ptr(), guid_ptr);
|
||||||
if adapter.is_null() {
|
if adapter.is_null() {
|
||||||
|
log::error!("adapter.is_null {:?}", io::Error::last_os_error());
|
||||||
return Err(io::Error::new(
|
return Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
"Failed to crate adapter",
|
"Failed to crate adapter",
|
||||||
@@ -102,6 +103,7 @@ impl TunDevice {
|
|||||||
// 开启session
|
// 开启session
|
||||||
let session = win_tun.WintunStartSession(adapter, 128 * 1024);
|
let session = win_tun.WintunStartSession(adapter, 128 * 1024);
|
||||||
if session.is_null() {
|
if session.is_null() {
|
||||||
|
log::error!("session.is_null {:?}", io::Error::last_os_error());
|
||||||
return Err(io::Error::new(
|
return Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
"WintunStartSession failed",
|
"WintunStartSession failed",
|
||||||
@@ -138,10 +140,14 @@ impl TunDevice {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
log::set_default_logger_if_unset(&win_tun);
|
wintun_log::set_default_logger_if_unset(&win_tun);
|
||||||
let name_utf16 = encode_utf16(name);
|
let name_utf16 = encode_utf16(name);
|
||||||
let adapter = win_tun.WintunOpenAdapter(name_utf16.as_ptr());
|
let adapter = win_tun.WintunOpenAdapter(name_utf16.as_ptr());
|
||||||
if adapter.is_null() {
|
if adapter.is_null() {
|
||||||
|
log::error!(
|
||||||
|
"delete_for_name adapter.is_null {:?}",
|
||||||
|
io::Error::last_os_error()
|
||||||
|
);
|
||||||
return Err(io::Error::new(
|
return Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
"Failed to open adapter",
|
"Failed to open adapter",
|
||||||
@@ -187,8 +193,8 @@ pub struct Version {
|
|||||||
|
|
||||||
impl IFace for TunDevice {
|
impl IFace for TunDevice {
|
||||||
fn shutdown(&self) -> io::Result<()> {
|
fn shutdown(&self) -> io::Result<()> {
|
||||||
let _ = unsafe { synchapi::SetEvent(self.shutdown_event) };
|
// let _ = unsafe { synchapi::SetEvent(self.shutdown_event) };
|
||||||
let _ = unsafe { handleapi::CloseHandle(self.shutdown_event) };
|
// let _ = unsafe { handleapi::CloseHandle(self.shutdown_event) };
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user