Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3045e239ff | ||
|
|
5363558118 | ||
|
|
13ba7cf0b8 | ||
|
|
a5a43e762d | ||
|
|
cb6101a835 | ||
|
|
255f84c969 | ||
|
|
7617d6c409 | ||
|
|
f75691b483 | ||
|
|
c5dbb79ed2 | ||
|
|
60ba3c64b2 | ||
|
|
080e58eeb7 | ||
|
|
5d228b9c27 | ||
|
|
ba87a2780d | ||
|
|
fccc3478c8 | ||
|
|
a76280c53b | ||
|
|
90ff03e27c | ||
|
|
5eed05989f | ||
|
|
ac939746bd | ||
|
|
b7532e89c2 | ||
|
|
74f44d6961 | ||
|
|
86fc27c233 | ||
|
|
4b6bb0e5f7 | ||
|
|
215337fd8a | ||
|
|
e54341567a | ||
|
|
1ce3e9ff2e | ||
|
|
ffdb5ceb6b | ||
|
|
faa78445b1 | ||
|
|
440a832ace | ||
|
|
01cf8806e2 | ||
|
|
a85e0c6d06 | ||
|
|
fee3b24df4 | ||
|
|
d8a9ec5732 |
Generated
+111
-4
@@ -195,6 +195,10 @@ name = "cc"
|
|||||||
version = "1.0.94"
|
version = "1.0.94"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7"
|
checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7"
|
||||||
|
dependencies = [
|
||||||
|
"jobserver",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cesu8"
|
name = "cesu8"
|
||||||
@@ -208,6 +212,36 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg_aliases"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chacha20"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cipher",
|
||||||
|
"cpufeatures",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chacha20poly1305"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
|
||||||
|
dependencies = [
|
||||||
|
"aead",
|
||||||
|
"chacha20",
|
||||||
|
"cipher",
|
||||||
|
"poly1305",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.38"
|
version = "0.4.38"
|
||||||
@@ -230,6 +264,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
"inout",
|
"inout",
|
||||||
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -244,7 +279,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "common"
|
name = "common"
|
||||||
version = "1.2.9"
|
version = "1.2.10"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "console"
|
name = "console"
|
||||||
@@ -606,6 +641,15 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jobserver"
|
||||||
|
version = "0.1.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.69"
|
version = "0.3.69"
|
||||||
@@ -720,6 +764,12 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lz4_flex"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.2"
|
version = "2.7.2"
|
||||||
@@ -948,6 +998,17 @@ version = "0.3.30"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
|
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "poly1305"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
|
||||||
|
dependencies = [
|
||||||
|
"cpufeatures",
|
||||||
|
"opaque-debug",
|
||||||
|
"universal-hash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polyval"
|
name = "polyval"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
@@ -1305,6 +1366,16 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook"
|
||||||
|
version = "0.3.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"signal-hook-registry",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.2"
|
version = "1.4.2"
|
||||||
@@ -1586,22 +1657,27 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vnt"
|
name = "vnt"
|
||||||
version = "1.2.9"
|
version = "1.2.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
"cbc",
|
"cbc",
|
||||||
|
"cfg_aliases",
|
||||||
|
"chacha20",
|
||||||
|
"chacha20poly1305",
|
||||||
"crossbeam-epoch",
|
"crossbeam-epoch",
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
"dns-parser",
|
"dns-parser",
|
||||||
"ecb",
|
"ecb",
|
||||||
|
"fnv",
|
||||||
"libc",
|
"libc",
|
||||||
"libloading",
|
"libloading",
|
||||||
"libsm",
|
"libsm",
|
||||||
"log",
|
"log",
|
||||||
|
"lz4_flex",
|
||||||
"mio",
|
"mio",
|
||||||
"openssl-sys",
|
"openssl-sys",
|
||||||
"packet",
|
"packet",
|
||||||
@@ -1619,12 +1695,14 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tun",
|
"tun",
|
||||||
|
"zstd",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vnt-cli"
|
name = "vnt-cli"
|
||||||
version = "1.2.9"
|
version = "1.2.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
"common",
|
"common",
|
||||||
"console",
|
"console",
|
||||||
@@ -1636,6 +1714,7 @@ dependencies = [
|
|||||||
"rand",
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
|
"signal-hook",
|
||||||
"sudo",
|
"sudo",
|
||||||
"uuid",
|
"uuid",
|
||||||
"vnt",
|
"vnt",
|
||||||
@@ -1644,7 +1723,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vnt-jni"
|
name = "vnt-jni"
|
||||||
version = "1.2.9"
|
version = "1.2.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android_logger",
|
"android_logger",
|
||||||
"common",
|
"common",
|
||||||
@@ -2002,3 +2081,31 @@ name = "zeroize"
|
|||||||
version = "1.7.0"
|
version = "1.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
|
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-safe",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-safe"
|
||||||
|
version = "7.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-sys"
|
||||||
|
version = "2.0.10+zstd.1.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ A virtual network tool (VPN)
|
|||||||
```
|
```
|
||||||
4. 最后可以用虚拟ip实现设备间相互访问
|
4. 最后可以用虚拟ip实现设备间相互访问
|
||||||
|
|
||||||
<img width="506" alt="ssh" src="https://raw.githubusercontent.com/lbl8603/vnt/dev/documents/img/ssh.jpg">
|
<img width="506" alt="ssh" src="https://raw.githubusercontent.com/lbl8603/vnt/main/documents/img/ssh.jpg">
|
||||||
5. 帮助,使用-h命令查看
|
5. 帮助,使用-h命令查看
|
||||||
|
|
||||||
### 更多玩法
|
### 更多玩法
|
||||||
@@ -73,35 +73,48 @@ cargo build -p vnt-cli --no-default-features
|
|||||||
|
|
||||||
features说明
|
features说明
|
||||||
|
|
||||||
| feature | 说明 | 是否默认 |
|
| feature | 说明 | 是否默认 |
|
||||||
|------------------|----------------------|------|
|
|-------------------|--------------------------------|------|
|
||||||
| openssl | 使用openssl中的aes_ecb算法 | 否 |
|
| openssl | 使用openssl中的加密算法 | 否 |
|
||||||
| openssl-vendored | 从源码编译openssl | 否 |
|
| openssl-vendored | 从源码编译openssl | 否 |
|
||||||
| ring-cipher | 使用ring中的aes_gcm算法 | 否 |
|
| ring-cipher | 使用ring中的加密算法 | 否 |
|
||||||
| aes_cbc | 支持aes_cbc加密 | 是 |
|
| aes_cbc | 支持aes_cbc加密 | 是 |
|
||||||
| aes_ecb | 支持aes_ecb加密 | 是 |
|
| aes_ecb | 支持aes_ecb加密 | 是 |
|
||||||
| aes_gcm | 支持aes_gcm加密 | 是 |
|
| aes_gcm | 支持aes_gcm加密 | 是 |
|
||||||
| sm4_cbc | 支持sm4_cbc加密 | 是 |
|
| sm4_cbc | 支持sm4_cbc加密 | 是 |
|
||||||
| server_encrypt | 支持服务端加密 | 是 |
|
| chacha20_poly1305 | 支持chacha20和chacha20_poly1305加密 | 是 |
|
||||||
| ip_proxy | 内置ip代理 | 是 |
|
| server_encrypt | 支持服务端加密 | 是 |
|
||||||
|
| ip_proxy | 内置ip代理 | 是 |
|
||||||
|
| port_mapping | 端口映射 | 是 |
|
||||||
|
| log | 日志 | 是 |
|
||||||
|
| command | list、route等命令 | 是 |
|
||||||
|
| file_config | yaml配置文件 | 是 |
|
||||||
|
| lz4 | lz4压缩 | 是 |
|
||||||
|
| zstd | zstd压缩 | 否 |
|
||||||
|
|
||||||
### ip转发/代理
|
### ip转发/代理
|
||||||
|
|
||||||
如果编译时去除了内置的ip代理(或使用--no-proxy关闭了代理),则可以使用网卡NAT转发来实现点对网,
|
如果编译时去除了内置的ip代理(或使用--no-proxy关闭了代理),则可以使用网卡NAT转发来实现点对网,
|
||||||
一般来说使用网卡NAT转发会比内置的ip代理性能更好
|
一般来说使用网卡NAT转发会比内置的ip代理性能更好
|
||||||
<details> <summary>NAT配置可参考如下示例,点击展开</summary>
|
<details> <summary>NAT配置可参考如下示例,点击展开</summary>
|
||||||
|
|
||||||
### 在出口一端做如下配置
|
### 在出口一端做如下配置
|
||||||
|
|
||||||
注意原有的-i(入口)和-o(出口)的参数不能少
|
注意原有的-i(入口)和-o(出口)的参数不能少
|
||||||
|
|
||||||
### windows
|
### windows
|
||||||
|
|
||||||
参考 https://learn.microsoft.com/zh-cn/virtualization/hyper-v-on-windows/user-guide/setup-nat-network
|
参考 https://learn.microsoft.com/zh-cn/virtualization/hyper-v-on-windows/user-guide/setup-nat-network
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
#设置nat,名字可以自己取,网段是vnt的网段
|
#设置nat,名字可以自己取,网段是vnt的网段
|
||||||
New-NetNat -Name vntnat -InternalIPInterfaceAddressPrefix 10.26.0.0/24
|
New-NetNat -Name vntnat -InternalIPInterfaceAddressPrefix 10.26.0.0/24
|
||||||
#查看设置
|
#查看设置
|
||||||
Get-NetNat
|
Get-NetNat
|
||||||
```
|
```
|
||||||
|
|
||||||
### linux
|
### linux
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# 开启ip转发
|
# 开启ip转发
|
||||||
sudo sysctl -w net.ipv4.ip_forward=1
|
sudo sysctl -w net.ipv4.ip_forward=1
|
||||||
@@ -144,6 +157,7 @@ sudo iptables-restore iptables.rules
|
|||||||
```
|
```
|
||||||
|
|
||||||
### macos
|
### macos
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# 开启ip转发
|
# 开启ip转发
|
||||||
sudo sysctl -w net.ipv4.ip_forward=1
|
sudo sysctl -w net.ipv4.ip_forward=1
|
||||||
@@ -153,18 +167,21 @@ nat on en0 from 10.26.0.0/24 to any -> (en0)
|
|||||||
# 加载规则
|
# 加载规则
|
||||||
sudo pfctl -f /etc/pf.conf -e
|
sudo pfctl -f /etc/pf.conf -e
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</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
|
||||||
- [VntApp](https://github.com/lbl8603/VntApp)
|
|
||||||
|
### GUI
|
||||||
|
|
||||||
|
支持安卓和Windows [下载](https://github.com/lbl8603/VntApp/releases/)
|
||||||
|
|
||||||
### 特性
|
### 特性
|
||||||
|
|
||||||
@@ -255,21 +272,33 @@ vnt默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突
|
|||||||
2. 如果p2p后效果很差,可以选择禁用p2p(vnt-cli增加--use-channel relay 参数)
|
2. 如果p2p后效果很差,可以选择禁用p2p(vnt-cli增加--use-channel relay 参数)
|
||||||
|
|
||||||
#### 问题4:重启后虚拟IP发生变化,或指定了IP不能启动
|
#### 问题4:重启后虚拟IP发生变化,或指定了IP不能启动
|
||||||
|
|
||||||
##### 可能原因:
|
##### 可能原因:
|
||||||
|
|
||||||
设备重启后程序自动获取的id值改变,导致注册时重新分配了新的IP,或是IP冲突
|
设备重启后程序自动获取的id值改变,导致注册时重新分配了新的IP,或是IP冲突
|
||||||
|
|
||||||
##### 解决方法:
|
##### 解决方法:
|
||||||
|
|
||||||
1. 命令行启动增加-d参数(使用配置文件启动则在配置文件中增加device_id参数),要保证每个设备的值都不一样,取值可以任意64位以内字符串
|
1. 命令行启动增加-d参数(使用配置文件启动则在配置文件中增加device_id参数),要保证每个设备的值都不一样,取值可以任意64位以内字符串
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 交流群
|
### 交流群
|
||||||
|
|
||||||
|
对VNT有任何问题均可以加群联系作者
|
||||||
|
|
||||||
QQ: 1034868233
|
QQ: 1034868233
|
||||||
|
### 赞助
|
||||||
|
如果VNT对你有帮助,欢迎打赏作者
|
||||||
|
|
||||||
|
<img width="300" alt="" src="https://github.com/lbl8603/vnt/assets/49143209/0d3a7311-43fc-4ed7-9507-863b5d69b6b2">
|
||||||
|
|
||||||
### 其他
|
### 其他
|
||||||
|
|
||||||
可使用社区小伙伴搭建的中继服务器
|
可使用社区小伙伴搭建的中继服务器
|
||||||
|
|
||||||
1. -s vnt.8443.eu.org:29871
|
1. -s vnt.8443.eu.org:29871
|
||||||
|
2. -s vnt.wherewego.top:29872
|
||||||
|
|
||||||
### 参与贡献
|
### 参与贡献
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "common"
|
name = "common"
|
||||||
version = "1.2.9"
|
version = "1.2.10"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
+11
-3
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "vnt-cli"
|
name = "vnt-cli"
|
||||||
version = "1.2.9"
|
version = "1.2.10"
|
||||||
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
|
||||||
@@ -14,7 +14,8 @@ os_info = "3.7.0"
|
|||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_yaml = "0.9.32"
|
serde_yaml = "0.9.32"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
log4rs = "1.2.0"
|
log4rs = { version = "1.2.0", optional = true }
|
||||||
|
anyhow = "1.0.82"
|
||||||
[dependencies.uuid]
|
[dependencies.uuid]
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
features = [
|
features = [
|
||||||
@@ -23,12 +24,13 @@ features = [
|
|||||||
|
|
||||||
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
|
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
|
||||||
sudo = "0.6.0"
|
sudo = "0.6.0"
|
||||||
|
signal-hook = "0.3.17"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
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 = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "ip_proxy", "port_mapping"]
|
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "chacha20_poly1305", "ip_proxy", "port_mapping", "log", "command", "file_config", "lz4"]
|
||||||
openssl = ["vnt/openssl"]
|
openssl = ["vnt/openssl"]
|
||||||
openssl-vendored = ["vnt/openssl-vendored"]
|
openssl-vendored = ["vnt/openssl-vendored"]
|
||||||
ring-cipher = ["vnt/ring-cipher"]
|
ring-cipher = ["vnt/ring-cipher"]
|
||||||
@@ -36,9 +38,15 @@ aes_cbc = ["vnt/aes_cbc"]
|
|||||||
aes_ecb = ["vnt/aes_ecb"]
|
aes_ecb = ["vnt/aes_ecb"]
|
||||||
sm4_cbc = ["vnt/sm4_cbc"]
|
sm4_cbc = ["vnt/sm4_cbc"]
|
||||||
aes_gcm = ["vnt/aes_gcm"]
|
aes_gcm = ["vnt/aes_gcm"]
|
||||||
|
chacha20_poly1305 = ["vnt/chacha20_poly1305"]
|
||||||
server_encrypt = ["vnt/server_encrypt"]
|
server_encrypt = ["vnt/server_encrypt"]
|
||||||
ip_proxy = ["vnt/ip_proxy"]
|
ip_proxy = ["vnt/ip_proxy"]
|
||||||
port_mapping = ["vnt/port_mapping"]
|
port_mapping = ["vnt/port_mapping"]
|
||||||
|
lz4 = ["vnt/lz4_compress"]
|
||||||
|
zstd = ["vnt/zstd_compress"]
|
||||||
|
log = ["log4rs"]
|
||||||
|
command = []
|
||||||
|
file_config = []
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
embed-manifest = "1.4.0"
|
embed-manifest = "1.4.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
|||||||
+96
-17
@@ -1,33 +1,56 @@
|
|||||||
## 模块介绍
|
## 模块介绍
|
||||||
|
|
||||||
体积小,可以在服务器、路由器等环境使用
|
体积小,可以在服务器、路由器等环境使用
|
||||||
|
|
||||||
## 详细参数说明
|
## 详细参数说明
|
||||||
|
|
||||||
### -k `<token>`
|
### -k `<token>`
|
||||||
|
|
||||||
一个虚拟局域网的标识,在同一服务器下,相同token的设备会组建一个局域网
|
一个虚拟局域网的标识,在同一服务器下,相同token的设备会组建一个局域网
|
||||||
|
|
||||||
### -n `<name>`
|
### -n `<name>`
|
||||||
|
|
||||||
设备名称,方便区分不同设备
|
设备名称,方便区分不同设备
|
||||||
|
|
||||||
### -d `<id>`
|
### -d `<id>`
|
||||||
|
|
||||||
设备id,每台设备的唯一标识,注意不要重复
|
设备id,每台设备的唯一标识,注意不要重复
|
||||||
|
|
||||||
### -c
|
### -c
|
||||||
|
|
||||||
关闭控制台交互式命令,后台运行时可以加此参数
|
关闭控制台交互式命令,后台运行时可以加此参数
|
||||||
|
|
||||||
### -s `<server>`
|
### -s `<server>`
|
||||||
|
|
||||||
注册和中继服务器地址,注册和转发数据,以'TXT:'开头表示解析TXT记录,TXT记录内容必须是'host:port'形式的服务器地址
|
注册和中继服务器地址,注册和转发数据,以'TXT:'开头表示解析TXT记录,TXT记录内容必须是'host:port'形式的服务器地址
|
||||||
|
|
||||||
### -e `<stun-server>`
|
### -e `<stun-server>`
|
||||||
|
|
||||||
使用stun服务探测客户端NAT类型,不同类型有不同的打洞策略
|
使用stun服务探测客户端NAT类型,不同类型有不同的打洞策略
|
||||||
|
|
||||||
### -a
|
### -a
|
||||||
|
|
||||||
加了此参数表示使用tap网卡,默认使用tun网卡,tun网卡效率更高
|
加了此参数表示使用tap网卡,默认使用tun网卡,tun网卡效率更高
|
||||||
|
|
||||||
注意:仅在windows上支持使用tap,用于兼容低版本windows系统(低版本windows不支持wintun)
|
注意:仅在windows上支持使用tap,用于兼容低版本windows系统(低版本windows不支持wintun)
|
||||||
|
|
||||||
|
使用tap模式需要手动创建tap网卡,使用--nic参数指定已经创建好的tap网卡名称
|
||||||
|
|
||||||
### --nic `<tun0>`
|
### --nic `<tun0>`
|
||||||
|
|
||||||
指定虚拟网卡名称,默认tun模式使用vnt-tun,tap模式使用vnt-tap
|
指定虚拟网卡名称,默认tun模式使用vnt-tun,tap模式使用vnt-tap
|
||||||
|
|
||||||
### -i `<in-ip>`、-o `<out-ip>`
|
### -i `<in-ip>`、-o `<out-ip>`
|
||||||
|
|
||||||
配置点对网(IP代理)时使用,例如A(虚拟ip:10.26.0.2)通过B(虚拟ip:10.26.0.3,本地出口ip:192.168.0.10)访问C(目标网段192.168.0.0/24),
|
配置点对网(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 ,允许转发所有网段可以使用 **'-o 0.0.0.0/0'**
|
在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这两个网段的数据
|
-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>`
|
||||||
|
|
||||||
@@ -39,9 +62,11 @@
|
|||||||
| 大于等于8 | AES256-GCM |
|
| 大于等于8 | AES256-GCM |
|
||||||
|
|
||||||
### -W
|
### -W
|
||||||
|
|
||||||
开启和服务端通信的数据加密,采用rsa+aes256gcm加密客户端和服务端之间通信的数据,可以避免token泄漏、中间人攻击
|
开启和服务端通信的数据加密,采用rsa+aes256gcm加密客户端和服务端之间通信的数据,可以避免token泄漏、中间人攻击
|
||||||
|
|
||||||
注意:
|
注意:
|
||||||
|
|
||||||
1. -w `<password>`是用于客户端-客户端之间的加密,password不会传递到服务端,只添加这个参数不会加密客户端-服务端通信的数据
|
1. -w `<password>`是用于客户端-客户端之间的加密,password不会传递到服务端,只添加这个参数不会加密客户端-服务端通信的数据
|
||||||
2. -W 用于开启客户端-服务端之间的加密
|
2. -W 用于开启客户端-服务端之间的加密
|
||||||
|
|
||||||
@@ -49,55 +74,93 @@
|
|||||||
|
|
||||||
设置虚拟网卡的mtu值,大多数情况下使用默认值效率会更高,也可根据实际情况微调这个值,不加密默认为1450,加密默认为1410
|
设置虚拟网卡的mtu值,大多数情况下使用默认值效率会更高,也可根据实际情况微调这个值,不加密默认为1450,加密默认为1410
|
||||||
|
|
||||||
### --tcp
|
### --tcp
|
||||||
|
|
||||||
和服务端使用tcp通信。有些网络提供商对UDP限制比较大,这个时候可以选择使用TCP模式,提高稳定性。一般来说udp延迟和消耗更低
|
和服务端使用tcp通信。有些网络提供商对UDP限制比较大,这个时候可以选择使用TCP模式,提高稳定性。一般来说udp延迟和消耗更低
|
||||||
|
|
||||||
### --ip `<IP>`
|
### --ip `<IP>`
|
||||||
|
|
||||||
指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配
|
指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配
|
||||||
|
|
||||||
### --par `<parallel>`
|
### --par `<parallel>`
|
||||||
|
|
||||||
任务并行度(必须为正整数),默认值为1,该值表示处理网卡读写的任务数,组网设备数较多、处理延迟较大时可适当调大此值
|
任务并行度(必须为正整数),默认值为1,该值表示处理网卡读写的任务数,组网设备数较多、处理延迟较大时可适当调大此值
|
||||||
|
|
||||||
### --model `<model>`
|
### --model `<model>`
|
||||||
加密模式,可选值 aes_gcm/aes_cbc/aes_ecb/sm4_cbc,默认使用aes_gcm,通常情况aes_gcm安全性高、aes_ecb性能更好,但是在低性能设备上sm4_cbc也许速度会更快;
|
|
||||||
|
|
||||||
|
加密模式,可选值
|
||||||
|
aes_gcm/aes_cbc/aes_ecb/sm4_cbc/chacha20_poly1305/chacha20/xor,默认使用aes_gcm,通常情况aes_gcm和chacha20_poly1305安全性高。
|
||||||
|
各种加密模式的安全性和速度都不相同,请按需选取
|
||||||
|
|
||||||
| 密码位数 | model | 加密算法 |
|
特别说明:xor只是对数据进行简单异或,仅仅避免了明文传输,安全性很差,同时对性能影响也极小;
|
||||||
|-------|---------|------------|
|
|
||||||
| 1~8位 | aes_gcm | AES128-GCM |
|
| 密码位数 | model | 加密算法 |
|
||||||
| `>=`8 | aes_gcm | AES256-GCM |
|
|--------|-------------------|-------------------|
|
||||||
| 1~8位 | aes_cbc | AES128-CBC |
|
| `< 8` | aes_gcm | AES128-GCM |
|
||||||
| `>=`8 | aes_cbc | AES256-CBC |
|
| `>= 8` | aes_gcm | AES256-GCM |
|
||||||
| 1~8位 | aes_ecb | AES128-ECB |
|
| `< 8` | aes_cbc | AES128-CBC |
|
||||||
| `>=`8 | aes_ecb | AES256-ECB |
|
| `>= 8` | aes_cbc | AES256-CBC |
|
||||||
| `>0` | sm4_cbc | SM4-CBC |
|
| `< 8` | aes_ecb | AES128-ECB |
|
||||||
### --finger
|
| `>= 8` | aes_ecb | AES256-ECB |
|
||||||
|
| `> 0` | sm4_cbc | SM4-CBC |
|
||||||
|
| `> 0` | chacha20_poly1305 | ChaCha20-Poly1305 |
|
||||||
|
| `> 0` | chacha20 | ChaCha20 |
|
||||||
|
| `> 0` | xor | 简单异或混淆 |
|
||||||
|
|
||||||
|
### --finger
|
||||||
|
|
||||||
开启数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启,开启会损耗一部分性能
|
开启数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启,开启会损耗一部分性能
|
||||||
|
|
||||||
注意:默认情况下服务端不会对中转的数据做校验,如果要对中转的数据做校验,则需要客户端、服务端都开启此参数
|
注意:默认情况下服务端不会对中转的数据做校验,如果要对中转的数据做校验,则需要客户端、服务端都开启此参数
|
||||||
|
|
||||||
### --punch `<punch>`
|
### --punch `<punch>`
|
||||||
|
|
||||||
取值ipv4/ipv6,选择只使用ipv4打洞或者只使用ipv6打洞,默认两者都会使用
|
取值ipv4/ipv6,选择只使用ipv4打洞或者只使用ipv6打洞,默认两者都会使用
|
||||||
|
|
||||||
### --ports `<port1,port2>`
|
### --ports `<port1,port2>`
|
||||||
|
|
||||||
指定本地监听的端口组,多个端口使用逗号分隔,多个端口可以分摊流量,增加并发、减缓流量限制,tcp会监听端口组的第一个端口,用于tcp直连
|
指定本地监听的端口组,多个端口使用逗号分隔,多个端口可以分摊流量,增加并发、减缓流量限制,tcp会监听端口组的第一个端口,用于tcp直连
|
||||||
|
|
||||||
- 例1:‘--ports 12345,12346,12347’ 表示udp监听12345、12346、12347这三个端口,tcp监听12345端口
|
- 例1:‘--ports 12345,12346,12347’ 表示udp监听12345、12346、12347这三个端口,tcp监听12345端口
|
||||||
- 例2:‘--ports 0,0’ 表示udp监听两个未使用的端口,tcp监听一个未使用的端口
|
- 例2:‘--ports 0,0’ 表示udp监听两个未使用的端口,tcp监听一个未使用的端口
|
||||||
|
|
||||||
### --cmd
|
### --cmd
|
||||||
|
|
||||||
开启交互式命令,开启后可以直接在窗口下输入命令,如需后台运行请勿开启
|
开启交互式命令,开启后可以直接在窗口下输入命令,如需后台运行请勿开启
|
||||||
|
|
||||||
### --first_latency
|
### --first_latency
|
||||||
|
|
||||||
优先使用低延迟通道,默认情况下优先使用p2p通道,某些情况下可能p2p比客户端中继延迟更高,可使用此参数进行优化传输
|
优先使用低延迟通道,默认情况下优先使用p2p通道,某些情况下可能p2p比客户端中继延迟更高,可使用此参数进行优化传输
|
||||||
|
|
||||||
### --no-proxy
|
### --no-proxy
|
||||||
|
|
||||||
关闭内置的ip代理,内置的代理较为简单,而且一般来说直接使用网卡NAT转发性能会更高,
|
关闭内置的ip代理,内置的代理较为简单,而且一般来说直接使用网卡NAT转发性能会更高,
|
||||||
有需要可以自行配置NAT转发,[可参考‘编译’小节中的NAT配置](https://github.com/lbl8603/vnt#%E7%BC%96%E8%AF%91)
|
有需要可以自行配置NAT转发,[可参考‘编译’小节中的NAT配置](https://github.com/lbl8603/vnt#%E7%BC%96%E8%AF%91)
|
||||||
|
|
||||||
### --dns `<223.5.5.5>`
|
### --dns `<223.5.5.5>`
|
||||||
|
|
||||||
设置域名解析服务器地址,可以设置多个。如果使用TXT记录的域名,则dns默认使用223.5.5.5和114.114.114.114,端口省略值为53
|
设置域名解析服务器地址,可以设置多个。如果使用TXT记录的域名,则dns默认使用223.5.5.5和114.114.114.114,端口省略值为53
|
||||||
|
|
||||||
当地址解析失败时,会依次尝试后面的dns,直到有A记录、AAAA记录(或TXT记录)的解析结果
|
当地址解析失败时,会依次尝试后面的dns,直到有A记录、AAAA记录(或TXT记录)的解析结果
|
||||||
|
|
||||||
### --mapping `<udp:0.0.0.0:80->10.26.0.10:80>`
|
### --mapping `<udp:0.0.0.0:80->10.26.0.10:80>`
|
||||||
|
|
||||||
端口映射,可以设置多个映射地址,例如 '--mapping udp:0.0.0.0:80->10.26.0.10:80 --mapping tcp:0.0.0.0:80->10.26.0.11:81'
|
端口映射,可以设置多个映射地址,例如 '--mapping udp:0.0.0.0:80->10.26.0.10:80 --mapping tcp:0.0.0.0:80->10.26.0.11:81'
|
||||||
表示将本地udp 80端口的数据转发到10.26.0.10:80,将本地tcp 80端口的数据转发到10.26.0.11:81,转发的目的地址可以使用域名+端口
|
表示将本地udp 80端口的数据转发到10.26.0.10:80,将本地tcp 80端口的数据转发到10.26.0.11:81,转发的目的地址可以使用域名+端口
|
||||||
|
|
||||||
|
### --compressor `<lz4>`
|
||||||
|
|
||||||
|
启用压缩,默认仅支持lz4压缩,开启压缩后,如果数据包长度大于等于128,则会使用压缩,否则还是会按原数据发送
|
||||||
|
|
||||||
|
也支持开启zstd压缩,但是需要自行编译,编译时加入参数--features zstd
|
||||||
|
|
||||||
|
如果宽度速度比较慢,可以考虑使用高级别的压缩
|
||||||
|
|
||||||
### -f `<conf>`
|
### -f `<conf>`
|
||||||
|
|
||||||
指定配置文件
|
指定配置文件
|
||||||
配置文件采用yaml格式,可参考:
|
配置文件采用yaml格式,可参考:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# 全部参数
|
# 全部参数
|
||||||
tap: false #是否使用tap 仅在windows上支持使用tap
|
tap: false #是否使用tap 仅在windows上支持使用tap
|
||||||
@@ -105,7 +168,7 @@ token: xxx #组网token
|
|||||||
device_id: xxx #当前设备id
|
device_id: xxx #当前设备id
|
||||||
name: windows 11 #当前设备名称
|
name: windows 11 #当前设备名称
|
||||||
server_address: ip:port #注册和中继服务器
|
server_address: ip:port #注册和中继服务器
|
||||||
stun_server: #stun服务器
|
stun_server: #stun服务器
|
||||||
- stun1.l.google.com:19302
|
- stun1.l.google.com:19302
|
||||||
- stun2.l.google.com:19302
|
- stun2.l.google.com:19302
|
||||||
in_ips: #代理ip入站
|
in_ips: #代理ip入站
|
||||||
@@ -122,7 +185,7 @@ parallel: 1 #任务并行度
|
|||||||
cipher_model: aes_gcm #客户端加密算法
|
cipher_model: aes_gcm #客户端加密算法
|
||||||
finger: false #关闭数据指纹
|
finger: false #关闭数据指纹
|
||||||
punch_model: ipv4 #打洞模式,表示只使用ipv4地址打洞,默认会同时使用v6和v4
|
punch_model: ipv4 #打洞模式,表示只使用ipv4地址打洞,默认会同时使用v6和v4
|
||||||
ports:
|
ports:
|
||||||
- 0 #使用随机端口,tcp监听此端口
|
- 0 #使用随机端口,tcp监听此端口
|
||||||
- 0
|
- 0
|
||||||
cmd: false #关闭控制台输入
|
cmd: false #关闭控制台输入
|
||||||
@@ -141,25 +204,41 @@ mapping:
|
|||||||
```
|
```
|
||||||
|
|
||||||
或者需要哪个配置就加哪个,当然token是必须的
|
或者需要哪个配置就加哪个,当然token是必须的
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# 部分参数
|
# 部分参数
|
||||||
token: xxx #组网token
|
token: xxx #组网token
|
||||||
```
|
```
|
||||||
|
|
||||||
### --use-channel `<relay/p2p>`
|
### --use-channel `<relay/p2p>`
|
||||||
|
|
||||||
- relay:仅中继模式,会禁止打洞/p2p直连,只使用服务器转发
|
- relay:仅中继模式,会禁止打洞/p2p直连,只使用服务器转发
|
||||||
- p2p:仅直连模式,会禁止网络数据从服务器/客户端转发,只会使用服务器转发控制包
|
- p2p:仅直连模式,会禁止网络数据从服务器/客户端转发,只会使用服务器转发控制包
|
||||||
|
|
||||||
### --packet-loss `<0>`
|
### --packet-loss `<0>`
|
||||||
|
|
||||||
模拟丢包,取值0~1之间的小数,程序会按设定的概率主动丢包。在模拟弱网环境时会有帮助。
|
模拟丢包,取值0~1之间的小数,程序会按设定的概率主动丢包。在模拟弱网环境时会有帮助。
|
||||||
|
|
||||||
### --packet-delay `<0>`
|
### --packet-delay `<0>`
|
||||||
|
|
||||||
模拟延迟,整数,单位毫秒(ms),程序会按设定的值延迟发包,可用于模拟弱网
|
模拟延迟,整数,单位毫秒(ms),程序会按设定的值延迟发包,可用于模拟弱网
|
||||||
|
|
||||||
### --list
|
### --list
|
||||||
|
|
||||||
在后台运行时,查看其他设备列表
|
在后台运行时,查看其他设备列表
|
||||||
|
|
||||||
### --all
|
### --all
|
||||||
|
|
||||||
在后台运行时,查看其他设备完整信息
|
在后台运行时,查看其他设备完整信息
|
||||||
|
|
||||||
### --info
|
### --info
|
||||||
|
|
||||||
在后台运行时,查看当前设备信息
|
在后台运行时,查看当前设备信息
|
||||||
### --route
|
|
||||||
|
### --route
|
||||||
|
|
||||||
在后台运行时,查看数据转发路径
|
在后台运行时,查看数据转发路径
|
||||||
|
|
||||||
### --stop
|
### --stop
|
||||||
|
|
||||||
停止后台运行
|
停止后台运行
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use std::time::Duration;
|
|||||||
use crate::command::entity::{DeviceItem, Info, RouteItem};
|
use crate::command::entity::{DeviceItem, Info, RouteItem};
|
||||||
|
|
||||||
pub struct CommandClient {
|
pub struct CommandClient {
|
||||||
buf: [u8; 10240],
|
buf: Vec<u8>,
|
||||||
udp: UdpSocket,
|
udp: UdpSocket,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ impl CommandClient {
|
|||||||
)))?;
|
)))?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
udp,
|
udp,
|
||||||
buf: [0; 10240],
|
buf: vec![0; 65536 * 8],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,8 +59,16 @@ impl CommandClient {
|
|||||||
match serde_yaml::from_slice::<V>(&self.buf[..len]) {
|
match serde_yaml::from_slice::<V>(&self.buf[..len]) {
|
||||||
Ok(val) => Ok(val),
|
Ok(val) => Ok(val),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("{:?},{:?}", &self.buf[..len], e);
|
log::error!(
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "data error"))
|
"send_cmd {:?} {:?},{:?}",
|
||||||
|
std::str::from_utf8(cmd),
|
||||||
|
std::str::from_utf8(&self.buf[..len]),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("data error {:?} buf_len={}", e, len),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,7 +185,10 @@ pub fn command_info(vnt: &Vnt) -> Info {
|
|||||||
.unwrap_or("None".to_string());
|
.unwrap_or("None".to_string());
|
||||||
let up = vnt.up_stream();
|
let up = vnt.up_stream();
|
||||||
let down = vnt.down_stream();
|
let down = vnt.down_stream();
|
||||||
|
#[cfg(feature = "port_mapping")]
|
||||||
let port_mapping_list = vnt.config().port_mapping_list.clone();
|
let port_mapping_list = vnt.config().port_mapping_list.clone();
|
||||||
|
#[cfg(not(feature = "port_mapping"))]
|
||||||
|
let port_mapping_list = vec![];
|
||||||
let in_ips = vnt.config().in_ips.clone();
|
let in_ips = vnt.config().in_ips.clone();
|
||||||
let out_ips = vnt.config().out_ips.clone();
|
let out_ips = vnt.config().out_ips.clone();
|
||||||
Info {
|
Info {
|
||||||
|
|||||||
@@ -0,0 +1,171 @@
|
|||||||
|
use anyhow::anyhow;
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::config::get_device_id;
|
||||||
|
use vnt::channel::punch::PunchModel;
|
||||||
|
use vnt::channel::UseChannelType;
|
||||||
|
use vnt::cipher::CipherModel;
|
||||||
|
use vnt::compression::Compressor;
|
||||||
|
use vnt::core::Config;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct FileConfig {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub tap: bool,
|
||||||
|
pub token: String,
|
||||||
|
pub device_id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub server_address: String,
|
||||||
|
pub stun_server: Vec<String>,
|
||||||
|
pub dns: Vec<String>,
|
||||||
|
pub in_ips: Vec<String>,
|
||||||
|
pub out_ips: Vec<String>,
|
||||||
|
pub password: Option<String>,
|
||||||
|
pub mtu: Option<u32>,
|
||||||
|
pub tcp: bool,
|
||||||
|
pub ip: Option<String>,
|
||||||
|
pub use_channel: String,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
|
pub no_proxy: bool,
|
||||||
|
pub server_encrypt: bool,
|
||||||
|
pub parallel: usize,
|
||||||
|
pub cipher_model: Option<String>,
|
||||||
|
pub finger: bool,
|
||||||
|
pub punch_model: String,
|
||||||
|
pub ports: Option<Vec<u16>>,
|
||||||
|
pub cmd: bool,
|
||||||
|
pub first_latency: bool,
|
||||||
|
pub device_name: Option<String>,
|
||||||
|
pub packet_loss: Option<f64>,
|
||||||
|
pub packet_delay: u32,
|
||||||
|
#[cfg(feature = "port_mapping")]
|
||||||
|
pub mapping: Vec<String>,
|
||||||
|
pub compressor: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FileConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
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.miwifi.com:3478".to_string(),
|
||||||
|
],
|
||||||
|
dns: vec![],
|
||||||
|
in_ips: vec![],
|
||||||
|
out_ips: vec![],
|
||||||
|
password: None,
|
||||||
|
mtu: None,
|
||||||
|
tcp: false,
|
||||||
|
ip: None,
|
||||||
|
use_channel: "all".to_string(),
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
|
no_proxy: false,
|
||||||
|
server_encrypt: false,
|
||||||
|
parallel: 1,
|
||||||
|
cipher_model: None,
|
||||||
|
finger: false,
|
||||||
|
punch_model: "all".to_string(),
|
||||||
|
ports: None,
|
||||||
|
cmd: false,
|
||||||
|
first_latency: false,
|
||||||
|
device_name: None,
|
||||||
|
packet_loss: None,
|
||||||
|
packet_delay: 0,
|
||||||
|
#[cfg(feature = "port_mapping")]
|
||||||
|
mapping: vec![],
|
||||||
|
compressor: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_config(file_path: &str) -> anyhow::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(anyhow!("{}", e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if file_conf.token.is_empty() {
|
||||||
|
return Err(anyhow!("token is_empty"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let in_ips = match common::args_parse::ips_parse(&file_conf.in_ips) {
|
||||||
|
Ok(in_ips) => in_ips,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(anyhow!("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(anyhow!("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| anyhow!("ip {:?} error:{}", &file_conf.ip, e))?),
|
||||||
|
};
|
||||||
|
let cipher_model = {
|
||||||
|
#[cfg(not(any(feature = "aes_gcm", feature = "server_encrypt")))]
|
||||||
|
if file_conf.password.is_some() && file_conf.cipher_model.is_none() {
|
||||||
|
Err(anyhow!("cipher_model undefined"))?
|
||||||
|
}
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
|
CipherModel::AesGcm
|
||||||
|
};
|
||||||
|
|
||||||
|
let punch_model = PunchModel::from_str(&file_conf.punch_model).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
let use_channel_type =
|
||||||
|
UseChannelType::from_str(&file_conf.use_channel).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
let compressor = if let Some(compressor) = file_conf.compressor.as_ref() {
|
||||||
|
Compressor::from_str(compressor).map_err(|e| anyhow!("{}", e))?
|
||||||
|
} else {
|
||||||
|
Compressor::None
|
||||||
|
};
|
||||||
|
let config = Config::new(
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
file_conf.tap,
|
||||||
|
file_conf.token,
|
||||||
|
file_conf.device_id,
|
||||||
|
file_conf.name,
|
||||||
|
file_conf.server_address,
|
||||||
|
file_conf.dns,
|
||||||
|
file_conf.stun_server,
|
||||||
|
in_ips,
|
||||||
|
out_ips,
|
||||||
|
file_conf.password,
|
||||||
|
file_conf.mtu,
|
||||||
|
file_conf.tcp,
|
||||||
|
virtual_ip,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
|
file_conf.no_proxy,
|
||||||
|
file_conf.server_encrypt,
|
||||||
|
file_conf.parallel,
|
||||||
|
cipher_model,
|
||||||
|
file_conf.finger,
|
||||||
|
punch_model,
|
||||||
|
file_conf.ports,
|
||||||
|
file_conf.first_latency,
|
||||||
|
file_conf.device_name,
|
||||||
|
use_channel_type,
|
||||||
|
file_conf.packet_loss,
|
||||||
|
file_conf.packet_delay,
|
||||||
|
#[cfg(feature = "port_mapping")]
|
||||||
|
file_conf.mapping,
|
||||||
|
compressor,
|
||||||
|
)?;
|
||||||
|
Ok((config, file_conf.cmd))
|
||||||
|
}
|
||||||
+7
-166
@@ -1,171 +1,12 @@
|
|||||||
use std::io;
|
#[cfg(feature = "file_config")]
|
||||||
use std::net::Ipv4Addr;
|
mod file_config;
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
#[cfg(feature = "file_config")]
|
||||||
|
pub use file_config::read_config;
|
||||||
|
|
||||||
use vnt::channel::punch::PunchModel;
|
#[cfg(not(feature = "file_config"))]
|
||||||
use vnt::channel::UseChannelType;
|
pub fn read_config(_file_path: &str) -> anyhow::Result<(vnt::core::Config, bool)> {
|
||||||
use vnt::cipher::CipherModel;
|
unimplemented!()
|
||||||
use vnt::core::Config;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
#[serde(default)]
|
|
||||||
pub struct FileConfig {
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub tap: bool,
|
|
||||||
pub token: String,
|
|
||||||
pub device_id: String,
|
|
||||||
pub name: String,
|
|
||||||
pub server_address: String,
|
|
||||||
pub stun_server: Vec<String>,
|
|
||||||
pub dns: Vec<String>,
|
|
||||||
pub in_ips: Vec<String>,
|
|
||||||
pub out_ips: Vec<String>,
|
|
||||||
pub password: Option<String>,
|
|
||||||
pub mtu: Option<u32>,
|
|
||||||
pub tcp: bool,
|
|
||||||
pub ip: Option<String>,
|
|
||||||
pub use_channel: String,
|
|
||||||
#[cfg(feature = "ip_proxy")]
|
|
||||||
pub no_proxy: bool,
|
|
||||||
pub server_encrypt: bool,
|
|
||||||
pub parallel: usize,
|
|
||||||
pub cipher_model: String,
|
|
||||||
pub finger: bool,
|
|
||||||
pub punch_model: String,
|
|
||||||
pub ports: Option<Vec<u16>>,
|
|
||||||
pub cmd: bool,
|
|
||||||
pub first_latency: bool,
|
|
||||||
pub device_name: Option<String>,
|
|
||||||
pub packet_loss: Option<f64>,
|
|
||||||
pub packet_delay: u32,
|
|
||||||
#[cfg(feature = "port_mapping")]
|
|
||||||
pub mapping: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for FileConfig {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
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.miwifi.com:3478".to_string(),
|
|
||||||
],
|
|
||||||
dns: vec![],
|
|
||||||
in_ips: vec![],
|
|
||||||
out_ips: vec![],
|
|
||||||
password: None,
|
|
||||||
mtu: None,
|
|
||||||
tcp: false,
|
|
||||||
ip: None,
|
|
||||||
use_channel: "all".to_string(),
|
|
||||||
#[cfg(feature = "ip_proxy")]
|
|
||||||
no_proxy: false,
|
|
||||||
server_encrypt: false,
|
|
||||||
parallel: 1,
|
|
||||||
cipher_model: "aes_gcm".to_string(),
|
|
||||||
finger: false,
|
|
||||||
punch_model: "all".to_string(),
|
|
||||||
ports: None,
|
|
||||||
cmd: false,
|
|
||||||
first_latency: false,
|
|
||||||
device_name: None,
|
|
||||||
packet_loss: None,
|
|
||||||
packet_delay: 0,
|
|
||||||
#[cfg(feature = "port_mapping")]
|
|
||||||
mapping: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 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 use_channel_type = UseChannelType::from_str(&file_conf.use_channel)
|
|
||||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
|
||||||
let config = Config::new(
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
file_conf.tap,
|
|
||||||
file_conf.token,
|
|
||||||
file_conf.device_id,
|
|
||||||
file_conf.name,
|
|
||||||
file_conf.server_address,
|
|
||||||
file_conf.dns,
|
|
||||||
file_conf.stun_server,
|
|
||||||
in_ips,
|
|
||||||
out_ips,
|
|
||||||
file_conf.password,
|
|
||||||
file_conf.mtu,
|
|
||||||
file_conf.tcp,
|
|
||||||
virtual_ip,
|
|
||||||
#[cfg(feature = "ip_proxy")]
|
|
||||||
file_conf.no_proxy,
|
|
||||||
file_conf.server_encrypt,
|
|
||||||
file_conf.parallel,
|
|
||||||
cipher_model,
|
|
||||||
file_conf.finger,
|
|
||||||
punch_model,
|
|
||||||
file_conf.ports,
|
|
||||||
file_conf.first_latency,
|
|
||||||
file_conf.device_name,
|
|
||||||
use_channel_type,
|
|
||||||
file_conf.packet_loss,
|
|
||||||
file_conf.packet_delay,
|
|
||||||
#[cfg(feature = "port_mapping")]
|
|
||||||
file_conf.mapping,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
Ok((config, file_conf.cmd))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_device_id() -> String {
|
pub fn get_device_id() -> String {
|
||||||
|
|||||||
+137
-96
@@ -1,7 +1,8 @@
|
|||||||
|
use anyhow::anyhow;
|
||||||
|
use std::io;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::{io, thread};
|
|
||||||
|
|
||||||
use console::style;
|
use console::style;
|
||||||
use getopts::Options;
|
use getopts::Options;
|
||||||
@@ -10,10 +11,13 @@ use common::args_parse::{ips_parse, out_ips_parse};
|
|||||||
use vnt::channel::punch::PunchModel;
|
use vnt::channel::punch::PunchModel;
|
||||||
use vnt::channel::UseChannelType;
|
use vnt::channel::UseChannelType;
|
||||||
use vnt::cipher::CipherModel;
|
use vnt::cipher::CipherModel;
|
||||||
|
use vnt::compression::Compressor;
|
||||||
use vnt::core::{Config, Vnt};
|
use vnt::core::{Config, Vnt};
|
||||||
|
|
||||||
|
#[cfg(feature = "command")]
|
||||||
mod command;
|
mod command;
|
||||||
mod config;
|
mod config;
|
||||||
|
#[cfg(feature = "command")]
|
||||||
mod console_out;
|
mod console_out;
|
||||||
mod generated_serial_number;
|
mod generated_serial_number;
|
||||||
mod root_check;
|
mod root_check;
|
||||||
@@ -41,6 +45,7 @@ pub fn app_home() -> io::Result<PathBuf> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
#[cfg(feature = "log")]
|
||||||
let _ = log4rs::init_file("log4rs.yaml", Default::default());
|
let _ = log4rs::init_file("log4rs.yaml", Default::default());
|
||||||
let args: Vec<String> = std::env::args().collect();
|
let args: Vec<String> = std::env::args().collect();
|
||||||
let program = args[0].clone();
|
let program = args[0].clone();
|
||||||
@@ -75,6 +80,7 @@ fn main() {
|
|||||||
opts.optmulti("", "dns", "dns", "<dns>");
|
opts.optmulti("", "dns", "dns", "<dns>");
|
||||||
opts.optmulti("", "mapping", "mapping", "<mapping>");
|
opts.optmulti("", "mapping", "mapping", "<mapping>");
|
||||||
opts.optopt("f", "", "配置文件", "<conf>");
|
opts.optopt("f", "", "配置文件", "<conf>");
|
||||||
|
opts.optopt("", "compressor", "压缩算法", "<lz4>");
|
||||||
//"后台运行时,查看其他设备列表"
|
//"后台运行时,查看其他设备列表"
|
||||||
opts.optflag("", "list", "后台运行时,查看其他设备列表");
|
opts.optflag("", "list", "后台运行时,查看其他设备列表");
|
||||||
opts.optflag("", "all", "后台运行时,查看其他设备完整信息");
|
opts.optflag("", "all", "后台运行时,查看其他设备完整信息");
|
||||||
@@ -100,6 +106,7 @@ fn main() {
|
|||||||
sudo::escalate_if_needed().unwrap();
|
sudo::escalate_if_needed().unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "command")]
|
||||||
if matches.opt_present("list") {
|
if matches.opt_present("list") {
|
||||||
command::command(command::CommandEnum::List);
|
command::command(command::CommandEnum::List);
|
||||||
return;
|
return;
|
||||||
@@ -226,19 +233,6 @@ fn main() {
|
|||||||
|
|
||||||
let cipher_model = match matches.opt_get::<CipherModel>("model") {
|
let cipher_model = match matches.opt_get::<CipherModel>("model") {
|
||||||
Ok(model) => {
|
Ok(model) => {
|
||||||
#[cfg(not(any(
|
|
||||||
feature = "aes_gcm",
|
|
||||||
feature = "server_encrypt",
|
|
||||||
feature = "aes_cbc",
|
|
||||||
feature = "aes_ecb",
|
|
||||||
feature = "sm4_cbc"
|
|
||||||
)))]
|
|
||||||
{
|
|
||||||
if password.is_some() && model.is_none() {
|
|
||||||
println!("Encryption not supported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(any(feature = "aes_gcm", feature = "server_encrypt")))]
|
#[cfg(not(any(feature = "aes_gcm", feature = "server_encrypt")))]
|
||||||
{
|
{
|
||||||
if password.is_some() && model.is_none() {
|
if password.is_some() && model.is_none() {
|
||||||
@@ -290,6 +284,13 @@ fn main() {
|
|||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
#[cfg(feature = "port_mapping")]
|
#[cfg(feature = "port_mapping")]
|
||||||
let port_mapping_list = matches.opt_strs("mapping");
|
let port_mapping_list = matches.opt_strs("mapping");
|
||||||
|
let compressor = if let Some(compressor) = matches.opt_str("compressor").as_ref() {
|
||||||
|
Compressor::from_str(compressor)
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.unwrap()
|
||||||
|
} else {
|
||||||
|
Compressor::None
|
||||||
|
};
|
||||||
let config = match Config::new(
|
let config = match Config::new(
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
tap,
|
tap,
|
||||||
@@ -320,11 +321,12 @@ fn main() {
|
|||||||
packet_delay,
|
packet_delay,
|
||||||
#[cfg(feature = "port_mapping")]
|
#[cfg(feature = "port_mapping")]
|
||||||
port_mapping_list,
|
port_mapping_list,
|
||||||
|
compressor,
|
||||||
) {
|
) {
|
||||||
Ok(config) => config,
|
Ok(config) => config,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("config error: {}", e);
|
println!("config.toml error: {}", e);
|
||||||
return;
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
(config, cmd)
|
(config, cmd)
|
||||||
@@ -342,7 +344,7 @@ fn main() {
|
|||||||
|
|
||||||
mod callback;
|
mod callback;
|
||||||
|
|
||||||
fn main0(config: Config, show_cmd: bool) {
|
fn main0(config: Config, _show_cmd: bool) {
|
||||||
#[cfg(feature = "port_mapping")]
|
#[cfg(feature = "port_mapping")]
|
||||||
for (is_tcp, addr, dest) in config.port_mapping_list.iter() {
|
for (is_tcp, addr, dest) in config.port_mapping_list.iter() {
|
||||||
if *is_tcp {
|
if *is_tcp {
|
||||||
@@ -351,37 +353,71 @@ fn main0(config: Config, show_cmd: bool) {
|
|||||||
println!("UDP port mapping {}->{}", addr, dest)
|
println!("UDP port mapping {}->{}", addr, dest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let vnt_util = Vnt::new(config, callback::VntHandler {}).unwrap();
|
let vnt_util = match Vnt::new(config, callback::VntHandler {}) {
|
||||||
let vnt_c = vnt_util.clone();
|
Ok(vnt) => vnt,
|
||||||
thread::Builder::new()
|
Err(e) => {
|
||||||
.name("CommandServer".into())
|
println!("error: {:?}", e);
|
||||||
.spawn(move || {
|
std::process::exit(1);
|
||||||
if let Err(e) = command::server::CommandServer::new().start(vnt_c) {
|
}
|
||||||
log::warn!("cmd:{:?}", e);
|
};
|
||||||
}
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||||
})
|
{
|
||||||
.expect("CommandServer");
|
let vnt_c = vnt_util.clone();
|
||||||
if show_cmd {
|
let mut signals = signal_hook::iterator::Signals::new(&[
|
||||||
let mut cmd = String::new();
|
signal_hook::consts::SIGINT,
|
||||||
loop {
|
signal_hook::consts::SIGTERM,
|
||||||
cmd.clear();
|
])
|
||||||
println!("======== input:list,info,route,all,stop ========");
|
.unwrap();
|
||||||
match io::stdin().read_line(&mut cmd) {
|
let handle = signals.handle();
|
||||||
Ok(len) => {
|
std::thread::spawn(move || {
|
||||||
if !command(&cmd[..len], &vnt_util) {
|
for sig in signals.forever() {
|
||||||
|
match sig {
|
||||||
|
signal_hook::consts::SIGINT | signal_hook::consts::SIGTERM => {
|
||||||
|
println!("Received SIGINT, {}", sig);
|
||||||
|
vnt_c.stop();
|
||||||
|
handle.close();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
}
|
||||||
println!("input err:{}", e);
|
});
|
||||||
break;
|
}
|
||||||
|
#[cfg(feature = "command")]
|
||||||
|
{
|
||||||
|
let vnt_c = vnt_util.clone();
|
||||||
|
std::thread::Builder::new()
|
||||||
|
.name("CommandServer".into())
|
||||||
|
.spawn(move || {
|
||||||
|
if let Err(e) = command::server::CommandServer::new().start(vnt_c) {
|
||||||
|
log::warn!("cmd:{:?}", e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.expect("CommandServer");
|
||||||
|
if _show_cmd {
|
||||||
|
let mut cmd = String::new();
|
||||||
|
loop {
|
||||||
|
cmd.clear();
|
||||||
|
println!("======== input:list,info,route,all,stop ========");
|
||||||
|
match io::stdin().read_line(&mut cmd) {
|
||||||
|
Ok(len) => {
|
||||||
|
if !command(&cmd[..len], &vnt_util) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("input err:{}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vnt_util.wait()
|
vnt_util.wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "command")]
|
||||||
fn command(cmd: &str, vnt: &Vnt) -> bool {
|
fn command(cmd: &str, vnt: &Vnt) -> bool {
|
||||||
if cmd.is_empty() {
|
if cmd.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
@@ -427,57 +463,51 @@ fn print_usage(program: &str, _opts: Options) {
|
|||||||
println!(" -s <server> 注册和中继服务器地址,以'TXT:'开头表示解析TXT记录");
|
println!(" -s <server> 注册和中继服务器地址,以'TXT:'开头表示解析TXT记录");
|
||||||
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可使用多个地址,如-e stun1.l.google.com -e stun2.l.google.com");
|
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可使用多个地址,如-e stun1.l.google.com -e stun2.l.google.com");
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
println!(" -a 使用tap模式,默认使用tun模式");
|
println!(
|
||||||
|
" -a 使用tap模式,默认使用tun模式,使用tap时需要配合'--nic'参数指定tap网卡"
|
||||||
|
);
|
||||||
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,可指定多个网段");
|
||||||
#[cfg(feature = "ip_proxy")]
|
|
||||||
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,可指定多个网段");
|
||||||
#[cfg(not(any(
|
|
||||||
feature = "aes_gcm",
|
println!(" -w <password> 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信");
|
||||||
feature = "server_encrypt",
|
#[cfg(feature = "server_encrypt")]
|
||||||
feature = "aes_cbc",
|
println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确");
|
||||||
feature = "aes_ecb",
|
println!(" -u <mtu> 自定义mtu(不加密默认为1450,加密默认为1410)");
|
||||||
feature = "sm4_cbc"
|
#[cfg(feature = "file_config")]
|
||||||
)))]
|
println!(" -f <conf_file> 读取配置文件中的配置");
|
||||||
let enums = String::new();
|
|
||||||
#[cfg(any(
|
println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp");
|
||||||
feature = "aes_gcm",
|
println!(" --ip <ip> 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配");
|
||||||
feature = "server_encrypt",
|
println!(" --par <parallel> 任务并行度(必须为正整数),默认值为1");
|
||||||
feature = "aes_cbc",
|
|
||||||
feature = "aes_ecb",
|
|
||||||
feature = "sm4_cbc"
|
|
||||||
))]
|
|
||||||
let mut enums = String::new();
|
let mut enums = String::new();
|
||||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
enums.push_str("/aes_gcm");
|
enums.push_str("/aes_gcm");
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
enums.push_str("/chacha20_poly1305/chacha20");
|
||||||
#[cfg(feature = "aes_cbc")]
|
#[cfg(feature = "aes_cbc")]
|
||||||
enums.push_str("/aes_cbc");
|
enums.push_str("/aes_cbc");
|
||||||
#[cfg(feature = "aes_ecb")]
|
#[cfg(feature = "aes_ecb")]
|
||||||
enums.push_str("/aes_ecb");
|
enums.push_str("/aes_ecb");
|
||||||
#[cfg(feature = "sm4_cbc")]
|
#[cfg(feature = "sm4_cbc")]
|
||||||
enums.push_str("/sm4_cbc");
|
enums.push_str("/sm4_cbc");
|
||||||
if !enums.is_empty() {
|
enums.push_str("/xor");
|
||||||
println!(" -w <password> 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信");
|
println!(
|
||||||
}
|
" --model <model> 加密模式(默认aes_gcm),可选值{}",
|
||||||
#[cfg(feature = "server_encrypt")]
|
&enums[1..]
|
||||||
println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确");
|
);
|
||||||
println!(" -u <mtu> 自定义mtu(不加密默认为1450,加密默认为1410)");
|
#[cfg(any(
|
||||||
println!(" -f <conf_file> 读取配置文件中的配置");
|
feature = "aes_gcm",
|
||||||
|
feature = "chacha20_poly1305",
|
||||||
println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp");
|
feature = "server_encrypt",
|
||||||
println!(" --ip <ip> 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配");
|
feature = "aes_cbc",
|
||||||
println!(" --par <parallel> 任务并行度(必须为正整数),默认值为1");
|
feature = "aes_ecb",
|
||||||
if !enums.is_empty() {
|
feature = "sm4_cbc"
|
||||||
println!(
|
))]
|
||||||
" --model <model> 加密模式(默认aes_gcm),可选值{}",
|
println!(" --finger 增加数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启");
|
||||||
&enums[1..]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if !enums.is_empty() {
|
|
||||||
println!(" --finger 增加数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启");
|
|
||||||
}
|
|
||||||
println!(" --punch <punch> 取值ipv4/ipv6/all,ipv4表示仅使用ipv4打洞");
|
println!(" --punch <punch> 取值ipv4/ipv6/all,ipv4表示仅使用ipv4打洞");
|
||||||
println!(" --ports <port,port> 取值0~65535,指定本地监听的一组端口,默认监听两个随机端口,使用过多端口会增加网络负担");
|
println!(" --ports <port,port> 取值0~65535,指定本地监听的一组端口,默认监听两个随机端口,使用过多端口会增加网络负担");
|
||||||
|
#[cfg(feature = "command")]
|
||||||
println!(" --cmd 开启交互式命令,使用此参数开启控制台输入");
|
println!(" --cmd 开启交互式命令,使用此参数开启控制台输入");
|
||||||
#[cfg(feature = "ip_proxy")]
|
#[cfg(feature = "ip_proxy")]
|
||||||
println!(" --no-proxy 关闭内置代理,如需点对网则需要配置网卡NAT转发");
|
println!(" --no-proxy 关闭内置代理,如需点对网则需要配置网卡NAT转发");
|
||||||
@@ -491,28 +521,38 @@ fn print_usage(program: &str, _opts: Options) {
|
|||||||
println!(" --dns <host:port> DNS服务器地址,可使用多个dns,不指定时使用系统解析");
|
println!(" --dns <host:port> DNS服务器地址,可使用多个dns,不指定时使用系统解析");
|
||||||
#[cfg(feature = "port_mapping")]
|
#[cfg(feature = "port_mapping")]
|
||||||
println!(" --mapping <mapping> 端口映射,例如 --mapping udp:0.0.0.0:80->10.26.0.10:80 --mapping tcp:0.0.0.0:80->10.26.0.10:80");
|
println!(" --mapping <mapping> 端口映射,例如 --mapping udp:0.0.0.0:80->10.26.0.10:80 --mapping tcp:0.0.0.0:80->10.26.0.10:80");
|
||||||
|
#[cfg(all(feature = "lz4", feature = "zstd"))]
|
||||||
|
println!(" --compressor <lz4> 启用压缩,可选值lz4/zstd<,level>,level为压缩级别,例如 --compressor lz4 或--compressor zstd,10");
|
||||||
|
#[cfg(feature = "lz4")]
|
||||||
|
#[cfg(not(feature = "zstd"))]
|
||||||
|
println!(" --compressor <lz4> 启用压缩,可选值lz4,例如 --compressor lz4");
|
||||||
|
#[cfg(feature = "zstd")]
|
||||||
|
#[cfg(not(feature = "lz4"))]
|
||||||
|
println!(" --compressor <zstd> 启用压缩,可选值zstd<,level>,level为压缩级别,例如 --compressor zstd,10");
|
||||||
println!();
|
println!();
|
||||||
println!(
|
#[cfg(feature = "command")]
|
||||||
" --list {}",
|
{
|
||||||
yellow("后台运行时,查看其他设备列表".to_string())
|
println!(
|
||||||
);
|
" --list {}",
|
||||||
println!(
|
yellow("后台运行时,查看其他设备列表".to_string())
|
||||||
" --all {}",
|
);
|
||||||
yellow("后台运行时,查看其他设备完整信息".to_string())
|
println!(
|
||||||
);
|
" --all {}",
|
||||||
println!(
|
yellow("后台运行时,查看其他设备完整信息".to_string())
|
||||||
" --info {}",
|
);
|
||||||
yellow("后台运行时,查看当前设备信息".to_string())
|
println!(
|
||||||
);
|
" --info {}",
|
||||||
println!(
|
yellow("后台运行时,查看当前设备信息".to_string())
|
||||||
" --route {}",
|
);
|
||||||
yellow("后台运行时,查看数据转发路径".to_string())
|
println!(
|
||||||
);
|
" --route {}",
|
||||||
println!(
|
yellow("后台运行时,查看数据转发路径".to_string())
|
||||||
" --stop {}",
|
);
|
||||||
yellow("停止后台运行".to_string())
|
println!(
|
||||||
);
|
" --stop {}",
|
||||||
|
yellow("停止后台运行".to_string())
|
||||||
|
);
|
||||||
|
}
|
||||||
println!(" -h, --help 帮助");
|
println!(" -h, --help 帮助");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,6 +560,7 @@ fn green(str: String) -> impl std::fmt::Display {
|
|||||||
style(str).green()
|
style(str).green()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "command")]
|
||||||
fn yellow(str: String) -> impl std::fmt::Display {
|
fn yellow(str: String) -> impl std::fmt::Display {
|
||||||
style(str).yellow()
|
style(str).yellow()
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "vnt-jni"
|
name = "vnt-jni"
|
||||||
version = "1.2.9"
|
version = "1.2.10"
|
||||||
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
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use jni::JNIEnv;
|
|||||||
use vnt::channel::punch::PunchModel;
|
use vnt::channel::punch::PunchModel;
|
||||||
use vnt::channel::UseChannelType;
|
use vnt::channel::UseChannelType;
|
||||||
use vnt::cipher::CipherModel;
|
use vnt::cipher::CipherModel;
|
||||||
|
use vnt::compression::Compressor;
|
||||||
use vnt::core::Config;
|
use vnt::core::Config;
|
||||||
|
|
||||||
use crate::utils::*;
|
use crate::utils::*;
|
||||||
@@ -118,6 +119,7 @@ pub fn new_config(env: &mut JNIEnv, config: JObject) -> Result<Config, Error> {
|
|||||||
packet_loss_rate,
|
packet_loss_rate,
|
||||||
packet_delay,
|
packet_delay,
|
||||||
port_mapping,
|
port_mapping,
|
||||||
|
Compressor::None,
|
||||||
) {
|
) {
|
||||||
Ok(config) => config,
|
Ok(config) => config,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|||||||
+12
-3
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "vnt"
|
name = "vnt"
|
||||||
version = "1.2.9"
|
version = "1.2.10"
|
||||||
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
|
||||||
@@ -23,6 +23,8 @@ aes-gcm = { version = "0.10.2", optional = true }
|
|||||||
ring = { version = "0.17.0", optional = true }
|
ring = { version = "0.17.0", optional = true }
|
||||||
cbc = { version = "0.1.2", optional = true }
|
cbc = { version = "0.1.2", optional = true }
|
||||||
ecb = { version = "0.1.2", optional = true }
|
ecb = { version = "0.1.2", optional = true }
|
||||||
|
chacha20poly1305 = { version = "0.10.1", optional = true }
|
||||||
|
chacha20 = { version = "0.9.1", 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.9.2", features = [], optional = true }
|
rsa = { version = "0.9.2", features = [], optional = true }
|
||||||
@@ -30,14 +32,17 @@ spki = { version = "0.7.2", features = ["fingerprint", "alloc", "base64"], optio
|
|||||||
openssl-sys = { git = "https://github.com/lbl8603/rust-openssl", optional = true }
|
openssl-sys = { git = "https://github.com/lbl8603/rust-openssl", optional = true }
|
||||||
libsm = { git = "https://github.com/lbl8603/libsm", optional = true }
|
libsm = { git = "https://github.com/lbl8603/libsm", optional = true }
|
||||||
|
|
||||||
mio = { version = "0.8.10", features = ["os-poll", "net"] }
|
mio = { version = "0.8.10", features = ["os-poll", "net", "os-ext"] }
|
||||||
crossbeam-queue = "0.3.11"
|
crossbeam-queue = "0.3.11"
|
||||||
anyhow = "1.0.82"
|
anyhow = "1.0.82"
|
||||||
dns-parser = "0.8.0"
|
dns-parser = "0.8.0"
|
||||||
|
|
||||||
tokio = { version = "1.37.0", features = ["full"], optional = true }
|
tokio = { version = "1.37.0", features = ["full"], optional = true }
|
||||||
|
|
||||||
|
lz4_flex = { version = "0.11", default-features = false, optional = true }
|
||||||
|
zstd = { version = "0.13.1", optional = true }
|
||||||
|
|
||||||
|
fnv = "1.0.7"
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
libloading = "0.8.0"
|
libloading = "0.8.0"
|
||||||
|
|
||||||
@@ -45,9 +50,10 @@ libloading = "0.8.0"
|
|||||||
[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"
|
||||||
|
cfg_aliases = "0.2.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "ip_proxy", "port_mapping"]
|
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "chacha20_poly1305", "ip_proxy", "port_mapping", "lz4_compress", "zstd_compress"]
|
||||||
openssl = ["openssl-sys"]
|
openssl = ["openssl-sys"]
|
||||||
# 从源码编译
|
# 从源码编译
|
||||||
openssl-vendored = ["openssl-sys/vendored"]
|
openssl-vendored = ["openssl-sys/vendored"]
|
||||||
@@ -56,6 +62,9 @@ aes_cbc = ["cbc"]
|
|||||||
aes_ecb = ["ecb"]
|
aes_ecb = ["ecb"]
|
||||||
sm4_cbc = ["libsm"]
|
sm4_cbc = ["libsm"]
|
||||||
aes_gcm = ["aes-gcm"]
|
aes_gcm = ["aes-gcm"]
|
||||||
|
chacha20_poly1305 = ["chacha20poly1305", "chacha20"]
|
||||||
server_encrypt = ["aes-gcm", "rsa", "spki"]
|
server_encrypt = ["aes-gcm", "rsa", "spki"]
|
||||||
ip_proxy = ["tokio"]
|
ip_proxy = ["tokio"]
|
||||||
port_mapping = ["tokio"]
|
port_mapping = ["tokio"]
|
||||||
|
lz4_compress = ["lz4_flex"]
|
||||||
|
zstd_compress = ["zstd"]
|
||||||
|
|||||||
@@ -1,4 +1,17 @@
|
|||||||
|
use cfg_aliases::cfg_aliases;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
cfg_aliases! {
|
||||||
|
cipher: {
|
||||||
|
any(feature = "aes_gcm",
|
||||||
|
feature = "chacha20_poly1305",
|
||||||
|
feature = "server_encrypt",
|
||||||
|
feature = "aes_cbc",
|
||||||
|
feature = "aes_ecb",
|
||||||
|
feature = "sm4_cbc"
|
||||||
|
)},
|
||||||
|
}
|
||||||
|
|
||||||
std::fs::create_dir_all("src/proto").unwrap();
|
std::fs::create_dir_all("src/proto").unwrap();
|
||||||
protobuf_codegen::Codegen::new()
|
protobuf_codegen::Codegen::new()
|
||||||
.pure()
|
.pure()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use fnv::FnvHashMap;
|
||||||
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV6, UdpSocket};
|
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV6, UdpSocket};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use std::{io, thread};
|
use std::{io, thread};
|
||||||
@@ -44,11 +44,10 @@ impl ChannelContext {
|
|||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
let inner = ContextInner {
|
let inner = ContextInner {
|
||||||
main_udp_socket,
|
main_udp_socket,
|
||||||
sub_udp_socket: RwLock::new(Vec::with_capacity(64)),
|
sub_udp_socket: RwLock::new(Vec::new()),
|
||||||
tcp_map: RwLock::new(HashMap::with_capacity(64)),
|
tcp_map: RwLock::new(FnvHashMap::default()),
|
||||||
route_table: RouteTable::new(use_channel_type, first_latency, channel_num),
|
route_table: RouteTable::new(use_channel_type, first_latency, channel_num),
|
||||||
is_tcp,
|
is_tcp,
|
||||||
state: AtomicBool::new(true),
|
|
||||||
packet_loss_rate,
|
packet_loss_rate,
|
||||||
packet_delay,
|
packet_delay,
|
||||||
main_index: AtomicUsize::new(0),
|
main_index: AtomicUsize::new(0),
|
||||||
@@ -81,13 +80,11 @@ pub struct ContextInner {
|
|||||||
// 对称网络增加的udp socket
|
// 对称网络增加的udp socket
|
||||||
sub_udp_socket: RwLock<Vec<UdpSocket>>,
|
sub_udp_socket: RwLock<Vec<UdpSocket>>,
|
||||||
// tcp数据发送器
|
// tcp数据发送器
|
||||||
pub(crate) tcp_map: RwLock<HashMap<SocketAddr, PacketSender>>,
|
pub(crate) tcp_map: RwLock<FnvHashMap<SocketAddr, PacketSender>>,
|
||||||
// 路由信息
|
// 路由信息
|
||||||
pub route_table: RouteTable,
|
pub route_table: RouteTable,
|
||||||
// 是否使用tcp连接服务器
|
// 是否使用tcp连接服务器
|
||||||
is_tcp: bool,
|
is_tcp: bool,
|
||||||
//状态
|
|
||||||
state: AtomicBool,
|
|
||||||
//控制丢包率,取值v=[0,100_0000] 丢包率r=v/100_0000
|
//控制丢包率,取值v=[0,100_0000] 丢包率r=v/100_0000
|
||||||
packet_loss_rate: u32,
|
packet_loss_rate: u32,
|
||||||
//控制延迟
|
//控制延迟
|
||||||
@@ -100,12 +97,6 @@ impl ContextInner {
|
|||||||
pub fn use_channel_type(&self) -> UseChannelType {
|
pub fn use_channel_type(&self) -> UseChannelType {
|
||||||
self.route_table.use_channel_type
|
self.route_table.use_channel_type
|
||||||
}
|
}
|
||||||
pub fn is_stop(&self) -> bool {
|
|
||||||
!self.state.load(Ordering::Acquire)
|
|
||||||
}
|
|
||||||
pub fn stop(&self) {
|
|
||||||
self.state.store(false, Ordering::Release);
|
|
||||||
}
|
|
||||||
/// 通过sub_udp_socket是否为空来判断是否为锥形网络
|
/// 通过sub_udp_socket是否为空来判断是否为锥形网络
|
||||||
pub fn is_cone(&self) -> bool {
|
pub fn is_cone(&self) -> bool {
|
||||||
self.sub_udp_socket.read().is_empty()
|
self.sub_udp_socket.read().is_empty()
|
||||||
@@ -297,7 +288,7 @@ impl ContextInner {
|
|||||||
|
|
||||||
pub struct RouteTable {
|
pub struct RouteTable {
|
||||||
pub(crate) route_table:
|
pub(crate) route_table:
|
||||||
RwLock<HashMap<Ipv4Addr, (AtomicUsize, Vec<(Route, AtomicCell<Instant>)>)>>,
|
RwLock<FnvHashMap<Ipv4Addr, (AtomicUsize, Vec<(Route, AtomicCell<Instant>)>)>>,
|
||||||
first_latency: bool,
|
first_latency: bool,
|
||||||
channel_num: usize,
|
channel_num: usize,
|
||||||
use_channel_type: UseChannelType,
|
use_channel_type: UseChannelType,
|
||||||
@@ -306,7 +297,7 @@ pub struct RouteTable {
|
|||||||
impl RouteTable {
|
impl RouteTable {
|
||||||
fn new(use_channel_type: UseChannelType, first_latency: bool, channel_num: usize) -> Self {
|
fn new(use_channel_type: UseChannelType, first_latency: bool, channel_num: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
route_table: RwLock::new(HashMap::with_capacity(64)),
|
route_table: RwLock::new(FnvHashMap::with_capacity_and_hasher(64, Default::default())),
|
||||||
use_channel_type,
|
use_channel_type,
|
||||||
first_latency,
|
first_latency,
|
||||||
channel_num,
|
channel_num,
|
||||||
|
|||||||
@@ -2,5 +2,11 @@ use crate::channel::context::ChannelContext;
|
|||||||
use crate::channel::RouteKey;
|
use crate::channel::RouteKey;
|
||||||
|
|
||||||
pub trait RecvChannelHandler: Clone + Send + 'static {
|
pub trait RecvChannelHandler: Clone + Send + 'static {
|
||||||
fn handle(&mut self, buf: &mut [u8], route_key: RouteKey, context: &ChannelContext);
|
fn handle(
|
||||||
|
&mut self,
|
||||||
|
buf: &mut [u8],
|
||||||
|
extend: &mut [u8],
|
||||||
|
route_key: RouteKey,
|
||||||
|
context: &ChannelContext,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ pub mod sender;
|
|||||||
pub mod tcp_channel;
|
pub mod tcp_channel;
|
||||||
pub mod udp_channel;
|
pub mod udp_channel;
|
||||||
|
|
||||||
const BUFFER_SIZE: usize = 1024 * 16;
|
pub const BUFFER_SIZE: usize = 1024 * 16;
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum UseChannelType {
|
pub enum UseChannelType {
|
||||||
Relay,
|
Relay,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ pub fn tcp_listen<H>(
|
|||||||
stop_manager: StopManager,
|
stop_manager: StopManager,
|
||||||
recv_handler: H,
|
recv_handler: H,
|
||||||
context: ChannelContext,
|
context: ChannelContext,
|
||||||
) -> io::Result<AcceptSocketSender<(TcpStream, SocketAddr, Option<Vec<u8>>)>>
|
) -> anyhow::Result<AcceptSocketSender<(TcpStream, SocketAddr, Option<Vec<u8>>)>>
|
||||||
where
|
where
|
||||||
H: RecvChannelHandler,
|
H: RecvChannelHandler,
|
||||||
{
|
{
|
||||||
@@ -75,7 +75,7 @@ fn tcp_listen0<H>(
|
|||||||
accept_tcp_receiver: Receiver<(TcpStream, SocketAddr, Option<Vec<u8>>)>,
|
accept_tcp_receiver: Receiver<(TcpStream, SocketAddr, Option<Vec<u8>>)>,
|
||||||
mut recv_handler: H,
|
mut recv_handler: H,
|
||||||
context: ChannelContext,
|
context: ChannelContext,
|
||||||
) -> io::Result<()>
|
) -> anyhow::Result<()>
|
||||||
where
|
where
|
||||||
H: RecvChannelHandler,
|
H: RecvChannelHandler,
|
||||||
{
|
{
|
||||||
@@ -87,8 +87,12 @@ where
|
|||||||
|
|
||||||
let mut read_map: HashMap<Token, (RouteKey, TcpStream, Box<[u8; BUFFER_SIZE]>, usize)> =
|
let mut read_map: HashMap<Token, (RouteKey, TcpStream, Box<[u8; BUFFER_SIZE]>, usize)> =
|
||||||
HashMap::with_capacity(32);
|
HashMap::with_capacity(32);
|
||||||
|
let mut extend = [0; BUFFER_SIZE];
|
||||||
loop {
|
loop {
|
||||||
poll.poll(&mut events, None)?;
|
if let Err(e) = poll.poll(&mut events, None) {
|
||||||
|
crate::ignore_io_interrupted(e)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for event in events.iter() {
|
for event in events.iter() {
|
||||||
match event.token() {
|
match event.token() {
|
||||||
SERVER => loop {
|
SERVER => loop {
|
||||||
@@ -108,7 +112,7 @@ where
|
|||||||
if e.kind() == io::ErrorKind::WouldBlock {
|
if e.kind() == io::ErrorKind::WouldBlock {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return Err(e);
|
return Err(e)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -132,9 +136,13 @@ where
|
|||||||
}
|
}
|
||||||
token => {
|
token => {
|
||||||
if event.is_readable() {
|
if event.is_readable() {
|
||||||
if let Err(e) =
|
if let Err(e) = readable_handle(
|
||||||
readable_handle(&token, &mut read_map, &mut recv_handler, &context)
|
&token,
|
||||||
{
|
&mut read_map,
|
||||||
|
&mut recv_handler,
|
||||||
|
&context,
|
||||||
|
&mut extend,
|
||||||
|
) {
|
||||||
closed_handle_r(&token, &mut read_map);
|
closed_handle_r(&token, &mut read_map);
|
||||||
log::warn!("{:?}", e);
|
log::warn!("{:?}", e);
|
||||||
if let Err(e) = write_waker.notify(token, false) {
|
if let Err(e) = write_waker.notify(token, false) {
|
||||||
@@ -159,7 +167,7 @@ fn init_writable_handler(
|
|||||||
receiver: Receiver<(TcpStream, Token, SocketAddr, Option<Vec<u8>>)>,
|
receiver: Receiver<(TcpStream, Token, SocketAddr, Option<Vec<u8>>)>,
|
||||||
stop_manager: StopManager,
|
stop_manager: StopManager,
|
||||||
context: ChannelContext,
|
context: ChannelContext,
|
||||||
) -> io::Result<WritableNotify> {
|
) -> anyhow::Result<WritableNotify> {
|
||||||
let poll = Poll::new()?;
|
let poll = Poll::new()?;
|
||||||
let writable_notify = WritableNotify::new(Waker::new(poll.registry(), NOTIFY)?);
|
let writable_notify = WritableNotify::new(Waker::new(poll.registry(), NOTIFY)?);
|
||||||
let worker = {
|
let worker = {
|
||||||
@@ -203,7 +211,10 @@ fn tcp_writable_listen(
|
|||||||
),
|
),
|
||||||
> = HashMap::with_capacity(32);
|
> = HashMap::with_capacity(32);
|
||||||
loop {
|
loop {
|
||||||
poll.poll(&mut events, None)?;
|
if let Err(e) = poll.poll(&mut events, None) {
|
||||||
|
crate::ignore_io_interrupted(e)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for event in events.iter() {
|
for event in events.iter() {
|
||||||
match event.token() {
|
match event.token() {
|
||||||
NOTIFY => {
|
NOTIFY => {
|
||||||
@@ -339,6 +350,7 @@ fn readable_handle<H>(
|
|||||||
map: &mut HashMap<Token, (RouteKey, TcpStream, Box<[u8; BUFFER_SIZE]>, usize)>,
|
map: &mut HashMap<Token, (RouteKey, TcpStream, Box<[u8; BUFFER_SIZE]>, usize)>,
|
||||||
recv_handler: &mut H,
|
recv_handler: &mut H,
|
||||||
context: &ChannelContext,
|
context: &ChannelContext,
|
||||||
|
extend: &mut [u8],
|
||||||
) -> io::Result<()>
|
) -> io::Result<()>
|
||||||
where
|
where
|
||||||
H: RecvChannelHandler,
|
H: RecvChannelHandler,
|
||||||
@@ -360,7 +372,7 @@ where
|
|||||||
}
|
}
|
||||||
*begin += len;
|
*begin += len;
|
||||||
if end > 4 && *begin == end {
|
if end > 4 && *begin == end {
|
||||||
recv_handler.handle(&mut buf[4..end], *route_key, context);
|
recv_handler.handle(&mut buf[4..end], extend, *route_key, context);
|
||||||
*begin = 0;
|
*begin = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ pub fn udp_listen<H>(
|
|||||||
stop_manager: StopManager,
|
stop_manager: StopManager,
|
||||||
recv_handler: H,
|
recv_handler: H,
|
||||||
context: ChannelContext,
|
context: ChannelContext,
|
||||||
) -> io::Result<AcceptSocketSender<Option<Vec<UdpSocket>>>>
|
) -> anyhow::Result<AcceptSocketSender<Option<Vec<UdpSocket>>>>
|
||||||
where
|
where
|
||||||
H: RecvChannelHandler,
|
H: RecvChannelHandler,
|
||||||
{
|
{
|
||||||
@@ -31,7 +31,7 @@ fn sub_udp_listen<H>(
|
|||||||
stop_manager: StopManager,
|
stop_manager: StopManager,
|
||||||
recv_handler: H,
|
recv_handler: H,
|
||||||
context: ChannelContext,
|
context: ChannelContext,
|
||||||
) -> io::Result<AcceptSocketSender<Option<Vec<UdpSocket>>>>
|
) -> anyhow::Result<AcceptSocketSender<Option<Vec<UdpSocket>>>>
|
||||||
where
|
where
|
||||||
H: RecvChannelHandler,
|
H: RecvChannelHandler,
|
||||||
{
|
{
|
||||||
@@ -70,9 +70,13 @@ where
|
|||||||
{
|
{
|
||||||
let mut events = Events::with_capacity(1024);
|
let mut events = Events::with_capacity(1024);
|
||||||
let mut buf = [0; BUFFER_SIZE];
|
let mut buf = [0; BUFFER_SIZE];
|
||||||
|
let mut extend = [0; BUFFER_SIZE];
|
||||||
let mut read_map: HashMap<Token, UdpSocket> = HashMap::with_capacity(32);
|
let mut read_map: HashMap<Token, UdpSocket> = HashMap::with_capacity(32);
|
||||||
loop {
|
loop {
|
||||||
poll.poll(&mut events, None)?;
|
if let Err(e) = poll.poll(&mut events, None) {
|
||||||
|
crate::ignore_io_interrupted(e)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for event in events.iter() {
|
for event in events.iter() {
|
||||||
match event.token() {
|
match event.token() {
|
||||||
NOTIFY => {
|
NOTIFY => {
|
||||||
@@ -115,6 +119,7 @@ where
|
|||||||
Ok((len, addr)) => {
|
Ok((len, addr)) => {
|
||||||
recv_handler.handle(
|
recv_handler.handle(
|
||||||
&mut buf[..len],
|
&mut buf[..len],
|
||||||
|
&mut extend,
|
||||||
RouteKey::new(false, token.0, addr),
|
RouteKey::new(false, token.0, addr),
|
||||||
&context,
|
&context,
|
||||||
);
|
);
|
||||||
@@ -206,7 +211,7 @@ fn main_udp_listen<H>(
|
|||||||
stop_manager: StopManager,
|
stop_manager: StopManager,
|
||||||
recv_handler: H,
|
recv_handler: H,
|
||||||
context: ChannelContext,
|
context: ChannelContext,
|
||||||
) -> io::Result<()>
|
) -> anyhow::Result<()>
|
||||||
where
|
where
|
||||||
H: RecvChannelHandler,
|
H: RecvChannelHandler,
|
||||||
{
|
{
|
||||||
@@ -252,8 +257,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut events = Events::with_capacity(udps.len());
|
let mut events = Events::with_capacity(udps.len());
|
||||||
|
let mut extend = [0; BUFFER_SIZE];
|
||||||
loop {
|
loop {
|
||||||
poll.poll(&mut events, None)?;
|
if let Err(e) = poll.poll(&mut events, None) {
|
||||||
|
crate::ignore_io_interrupted(e)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for x in events.iter() {
|
for x in events.iter() {
|
||||||
let index = match x.token() {
|
let index = match x.token() {
|
||||||
NOTIFY => return Ok(()),
|
NOTIFY => return Ok(()),
|
||||||
@@ -270,6 +279,7 @@ where
|
|||||||
Ok((len, addr)) => {
|
Ok((len, addr)) => {
|
||||||
recv_handler.handle(
|
recv_handler.handle(
|
||||||
&mut buf[..len],
|
&mut buf[..len],
|
||||||
|
&mut extend,
|
||||||
RouteKey::new(false, index, addr),
|
RouteKey::new(false, index, addr),
|
||||||
&context,
|
&context,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
mod rs_aes_cbc;
|
||||||
|
pub use rs_aes_cbc::*;
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
use std::io;
|
|
||||||
|
|
||||||
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyIvInit};
|
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyIvInit};
|
||||||
|
use anyhow::anyhow;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
|
||||||
use crate::cipher::Finger;
|
use crate::cipher::Finger;
|
||||||
@@ -50,22 +49,17 @@ impl AesCbcCipher {
|
|||||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
net_packet: &mut NetPacket<B>,
|
net_packet: &mut NetPacket<B>,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if !net_packet.is_encrypt() {
|
if !net_packet.is_encrypt() {
|
||||||
//未加密的数据直接丢弃
|
//未加密的数据直接丢弃
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
return Err(anyhow!("not encrypt"));
|
||||||
}
|
}
|
||||||
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(anyhow!("aes_cbc data err"));
|
||||||
}
|
}
|
||||||
let mut iv = [0; 16];
|
let mut iv = [0; 16];
|
||||||
iv[0..4].copy_from_slice(&net_packet.source().octets());
|
iv[0..12].copy_from_slice(&net_packet.head_tag());
|
||||||
iv[4..8].copy_from_slice(&net_packet.destination().octets());
|
|
||||||
iv[8] = net_packet.protocol().into();
|
|
||||||
iv[9] = net_packet.transport_protocol();
|
|
||||||
iv[10] = net_packet.is_gateway() as u8;
|
|
||||||
iv[11] = net_packet.source_ttl();
|
|
||||||
if let Some(finger) = &self.finger {
|
if let Some(finger) = &self.finger {
|
||||||
iv[12..16].copy_from_slice(&finger.hash[0..4]);
|
iv[12..16].copy_from_slice(&finger.hash[0..4]);
|
||||||
}
|
}
|
||||||
@@ -75,7 +69,7 @@ impl AesCbcCipher {
|
|||||||
if let Some(finger) = &self.finger {
|
if let Some(finger) = &self.finger {
|
||||||
let finger = finger.calculate_finger(&iv[..12], secret_body.en_body());
|
let finger = finger.calculate_finger(&iv[..12], secret_body.en_body());
|
||||||
if &finger != secret_body.finger() {
|
if &finger != secret_body.finger() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
return Err(anyhow!("aes_cbc finger err"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let rs = match &self.cipher {
|
let rs = match &self.cipher {
|
||||||
@@ -92,10 +86,7 @@ impl AesCbcCipher {
|
|||||||
net_packet.set_data_len(HEAD_LEN + len - 4)?;
|
net_packet.set_data_len(HEAD_LEN + len - 4)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => Err(io::Error::new(
|
Err(e) => Err(anyhow!("aes_cbc 解密失败:{}", e)),
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("解密失败:{}", e),
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// net_packet 必须预留足够长度
|
/// net_packet 必须预留足够长度
|
||||||
@@ -103,15 +94,10 @@ impl AesCbcCipher {
|
|||||||
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<()> {
|
) -> anyhow::Result<()> {
|
||||||
let data_len = net_packet.data_len();
|
let data_len = net_packet.data_len();
|
||||||
let mut iv = [0; 16];
|
let mut iv = [0; 16];
|
||||||
iv[0..4].copy_from_slice(&net_packet.source().octets());
|
iv[0..12].copy_from_slice(&net_packet.head_tag());
|
||||||
iv[4..8].copy_from_slice(&net_packet.destination().octets());
|
|
||||||
iv[8] = net_packet.protocol().into();
|
|
||||||
iv[9] = net_packet.transport_protocol();
|
|
||||||
iv[10] = net_packet.is_gateway() as u8;
|
|
||||||
iv[11] = net_packet.source_ttl();
|
|
||||||
if let Some(finger) = &self.finger {
|
if let Some(finger) = &self.finger {
|
||||||
iv[12..16].copy_from_slice(&finger.hash[0..4]);
|
iv[12..16].copy_from_slice(&finger.hash[0..4]);
|
||||||
net_packet.set_data_len(data_len + 16)?;
|
net_packet.set_data_len(data_len + 16)?;
|
||||||
@@ -146,10 +132,22 @@ impl AesCbcCipher {
|
|||||||
net_packet.set_encrypt_flag(true);
|
net_packet.set_encrypt_flag(true);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => Err(io::Error::new(
|
Err(e) => Err(anyhow!("aes_cbc 加密失败:{}", e)),
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("加密失败:{}", e),
|
|
||||||
)),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_aes_cbc() {
|
||||||
|
let d = AesCbcCipher::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);
|
||||||
|
let d = AesCbcCipher::new_128([0; 16], None);
|
||||||
|
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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
|
||||||
|
mod rs_aes_ecb;
|
||||||
|
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
|
||||||
|
pub use rs_aes_ecb::*;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
|
||||||
|
mod openssl_aes_ecb;
|
||||||
|
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
|
||||||
|
pub use openssl_aes_ecb::*;
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
use crate::cipher::Finger;
|
use std::ptr;
|
||||||
use crate::protocol::{NetPacket, HEAD_LEN};
|
|
||||||
|
use anyhow::anyhow;
|
||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
use openssl_sys::EVP_CIPHER_CTX;
|
use openssl_sys::EVP_CIPHER_CTX;
|
||||||
use std::{io, ptr};
|
|
||||||
|
use crate::cipher::Finger;
|
||||||
|
use crate::protocol::{NetPacket, HEAD_LEN};
|
||||||
|
|
||||||
pub struct AesEcbCipher {
|
pub struct AesEcbCipher {
|
||||||
key: Vec<u8>,
|
key: Vec<u8>,
|
||||||
@@ -100,34 +103,28 @@ impl AesEcbCipher {
|
|||||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
net_packet: &mut NetPacket<B>,
|
net_packet: &mut NetPacket<B>,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if !net_packet.is_encrypt() {
|
if !net_packet.is_encrypt() {
|
||||||
//未加密的数据直接丢弃
|
//未加密的数据直接丢弃
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
return Err(anyhow!("not encrypt"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(finger) = &self.finger {
|
if let Some(finger) = &self.finger {
|
||||||
let mut nonce_raw = [0; 12];
|
let nonce_raw = net_packet.head_tag();
|
||||||
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();
|
let len = net_packet.payload().len();
|
||||||
if len < 12 {
|
if len < 12 {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data len err"));
|
return Err(anyhow!("data len err"));
|
||||||
}
|
}
|
||||||
let secret_body = &net_packet.payload()[..len - 12];
|
let secret_body = &net_packet.payload()[..len - 12];
|
||||||
let finger = finger.calculate_finger(&nonce_raw, secret_body);
|
let finger = finger.calculate_finger(&nonce_raw, secret_body);
|
||||||
if &finger != &net_packet.payload()[len - 12..] {
|
if &finger != &net_packet.payload()[len - 12..] {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
return Err(anyhow!("finger err"));
|
||||||
}
|
}
|
||||||
net_packet.set_data_len(net_packet.data_len() - finger.len())?;
|
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(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
let input = net_packet.payload();
|
let input = net_packet.payload();
|
||||||
let mut out = [0u8; 1024 * 5];
|
let mut out = [0u8; 1024 * 5];
|
||||||
@@ -147,22 +144,22 @@ impl AesEcbCipher {
|
|||||||
//校验头部
|
//校验头部
|
||||||
let src_net_packet = NetPacket::new(text)?;
|
let src_net_packet = NetPacket::new(text)?;
|
||||||
if src_net_packet.source() != net_packet.source() {
|
if src_net_packet.source() != net_packet.source() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.destination() != net_packet.destination() {
|
if src_net_packet.destination() != net_packet.destination() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.protocol() != net_packet.protocol() {
|
if src_net_packet.protocol() != net_packet.protocol() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.transport_protocol() != net_packet.transport_protocol() {
|
if src_net_packet.transport_protocol() != net_packet.transport_protocol() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.is_gateway() != net_packet.is_gateway() {
|
if src_net_packet.is_gateway() != net_packet.is_gateway() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.source_ttl() != net_packet.source_ttl() {
|
if src_net_packet.source_ttl() != net_packet.source_ttl() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
net_packet.set_encrypt_flag(false);
|
net_packet.set_encrypt_flag(false);
|
||||||
@@ -175,7 +172,7 @@ impl AesEcbCipher {
|
|||||||
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<()> {
|
) -> anyhow::Result<()> {
|
||||||
let input = net_packet.buffer();
|
let input = net_packet.buffer();
|
||||||
let mut out = [0u8; 1024 * 5];
|
let mut out = [0u8; 1024 * 5];
|
||||||
let mut out_len = 0;
|
let mut out_len = 0;
|
||||||
@@ -191,7 +188,7 @@ impl AesEcbCipher {
|
|||||||
}
|
}
|
||||||
let out_len = out_len as usize;
|
let out_len = out_len as usize;
|
||||||
if out_len == 0 {
|
if out_len == 0 {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "ciphertext len err"));
|
return Err(anyhow!("ciphertext len err"));
|
||||||
}
|
}
|
||||||
//密文
|
//密文
|
||||||
let ciphertext = &out[..out_len];
|
let ciphertext = &out[..out_len];
|
||||||
@@ -199,13 +196,7 @@ impl AesEcbCipher {
|
|||||||
net_packet.payload_mut().copy_from_slice(ciphertext);
|
net_packet.payload_mut().copy_from_slice(ciphertext);
|
||||||
net_packet.set_encrypt_flag(true);
|
net_packet.set_encrypt_flag(true);
|
||||||
if let Some(finger) = &self.finger {
|
if let Some(finger) = &self.finger {
|
||||||
let mut nonce_raw = [0; 12];
|
let nonce_raw = net_packet.head_tag();
|
||||||
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 finger = finger.calculate_finger(&nonce_raw, ciphertext);
|
||||||
let src_data_len = net_packet.data_len();
|
let src_data_len = net_packet.data_len();
|
||||||
//设置实际长度
|
//设置实际长度
|
||||||
@@ -221,6 +212,8 @@ impl AesEcbCipher {
|
|||||||
fn test_openssl_aes_ecb() {
|
fn test_openssl_aes_ecb() {
|
||||||
let d = AesEcbCipher::new_128([0; 16], Some(Finger::new("123")));
|
let d = AesEcbCipher::new_128([0; 16], Some(Finger::new("123")));
|
||||||
let mut p = NetPacket::new_encrypt([0; 100]).unwrap();
|
let mut p = NetPacket::new_encrypt([0; 100]).unwrap();
|
||||||
|
let src = p.buffer().to_vec();
|
||||||
d.encrypt_ipv4(&mut p).unwrap();
|
d.encrypt_ipv4(&mut p).unwrap();
|
||||||
d.decrypt_ipv4(&mut p).unwrap();
|
d.decrypt_ipv4(&mut p).unwrap();
|
||||||
|
assert_eq!(p.buffer(), &src);
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
|
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyInit};
|
||||||
|
use anyhow::anyhow;
|
||||||
|
|
||||||
use crate::cipher::Finger;
|
use crate::cipher::Finger;
|
||||||
use crate::protocol::{NetPacket, HEAD_LEN};
|
use crate::protocol::{NetPacket, HEAD_LEN};
|
||||||
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyInit};
|
|
||||||
use std::io;
|
|
||||||
|
|
||||||
type Aes128EcbEnc = ecb::Encryptor<aes::Aes128>;
|
type Aes128EcbEnc = ecb::Encryptor<aes::Aes128>;
|
||||||
type Aes128EcbDec = ecb::Decryptor<aes::Aes128>;
|
type Aes128EcbDec = ecb::Decryptor<aes::Aes128>;
|
||||||
@@ -46,34 +47,28 @@ impl AesEcbCipher {
|
|||||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
net_packet: &mut NetPacket<B>,
|
net_packet: &mut NetPacket<B>,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if !net_packet.is_encrypt() {
|
if !net_packet.is_encrypt() {
|
||||||
//未加密的数据直接丢弃
|
//未加密的数据直接丢弃
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
return Err(anyhow!("not encrypt"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(finger) = &self.finger {
|
if let Some(finger) = &self.finger {
|
||||||
let mut nonce_raw = [0; 12];
|
let nonce_raw = net_packet.head_tag();
|
||||||
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();
|
let len = net_packet.payload().len();
|
||||||
if len < 12 {
|
if len < 12 {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "payload len <12"));
|
return Err(anyhow!("payload len <12"));
|
||||||
}
|
}
|
||||||
let secret_body = &net_packet.payload()[..len - 12];
|
let secret_body = &net_packet.payload()[..len - 12];
|
||||||
let finger = finger.calculate_finger(&nonce_raw, secret_body);
|
let finger = finger.calculate_finger(&nonce_raw, secret_body);
|
||||||
if &finger != &net_packet.payload()[len - 12..] {
|
if &finger != &net_packet.payload()[len - 12..] {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
return Err(anyhow!("finger err"));
|
||||||
}
|
}
|
||||||
net_packet.set_data_len(net_packet.data_len() - finger.len())?;
|
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(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
let mut out = [0u8; 1024 * 5];
|
let mut out = [0u8; 1024 * 5];
|
||||||
let rs = match self.key {
|
let rs = match self.key {
|
||||||
@@ -87,32 +82,29 @@ impl AesEcbCipher {
|
|||||||
//校验头部
|
//校验头部
|
||||||
let src_net_packet = NetPacket::new(buf)?;
|
let src_net_packet = NetPacket::new(buf)?;
|
||||||
if src_net_packet.source() != net_packet.source() {
|
if src_net_packet.source() != net_packet.source() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.destination() != net_packet.destination() {
|
if src_net_packet.destination() != net_packet.destination() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.protocol() != net_packet.protocol() {
|
if src_net_packet.protocol() != net_packet.protocol() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.transport_protocol() != net_packet.transport_protocol() {
|
if src_net_packet.transport_protocol() != net_packet.transport_protocol() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.is_gateway() != net_packet.is_gateway() {
|
if src_net_packet.is_gateway() != net_packet.is_gateway() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.source_ttl() != net_packet.source_ttl() {
|
if src_net_packet.source_ttl() != net_packet.source_ttl() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
net_packet.set_data_len(buf.len())?;
|
net_packet.set_data_len(buf.len())?;
|
||||||
net_packet.set_payload(src_net_packet.payload())?;
|
net_packet.set_payload(src_net_packet.payload())?;
|
||||||
net_packet.set_encrypt_flag(false);
|
net_packet.set_encrypt_flag(false);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => Err(io::Error::new(
|
Err(e) => Err(anyhow!("aes_ecb解密失败:{}", e)),
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("aes_ecb解密失败:{}", e),
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// net_packet 必须预留足够长度
|
/// net_packet 必须预留足够长度
|
||||||
@@ -120,7 +112,7 @@ impl AesEcbCipher {
|
|||||||
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<()> {
|
) -> anyhow::Result<()> {
|
||||||
let mut out = [0u8; 1024 * 5];
|
let mut out = [0u8; 1024 * 5];
|
||||||
let rs = match self.key {
|
let rs = match self.key {
|
||||||
AesEcbEnum::AES128ECB(key) => Aes128EcbEnc::new(&key.into())
|
AesEcbEnum::AES128ECB(key) => Aes128EcbEnc::new(&key.into())
|
||||||
@@ -136,13 +128,7 @@ impl AesEcbCipher {
|
|||||||
net_packet.set_encrypt_flag(true);
|
net_packet.set_encrypt_flag(true);
|
||||||
|
|
||||||
if let Some(finger) = &self.finger {
|
if let Some(finger) = &self.finger {
|
||||||
let mut nonce_raw = [0; 12];
|
let nonce_raw = net_packet.head_tag();
|
||||||
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 finger = finger.calculate_finger(&nonce_raw, buf);
|
||||||
let src_data_len = net_packet.data_len();
|
let src_data_len = net_packet.data_len();
|
||||||
//设置实际长度
|
//设置实际长度
|
||||||
@@ -152,10 +138,7 @@ impl AesEcbCipher {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => Err(io::Error::new(
|
Err(e) => Err(anyhow!("aes_ecb加密失败:{}", e)),
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("aes_ecb加密失败:{}", e),
|
|
||||||
)),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
use std::io;
|
|
||||||
|
|
||||||
use aes_gcm::aead::consts::{U12, U16};
|
use aes_gcm::aead::consts::{U12, U16};
|
||||||
use aes_gcm::aead::generic_array::GenericArray;
|
use aes_gcm::aead::generic_array::GenericArray;
|
||||||
use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, KeyInit, Nonce, Tag};
|
use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, KeyInit, Nonce, Tag};
|
||||||
|
use anyhow::anyhow;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
|
||||||
use crate::cipher::finger::Finger;
|
use crate::cipher::finger::Finger;
|
||||||
@@ -39,22 +38,16 @@ impl AesGcmCipher {
|
|||||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
net_packet: &mut NetPacket<B>,
|
net_packet: &mut NetPacket<B>,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if !net_packet.is_encrypt() {
|
if !net_packet.is_encrypt() {
|
||||||
//未加密的数据直接丢弃
|
//未加密的数据直接丢弃
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
return Err(anyhow!("not encrypt"));
|
||||||
}
|
}
|
||||||
if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED {
|
if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED {
|
||||||
log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED);
|
log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED);
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
let mut nonce_raw = [0; 12];
|
let nonce_raw = net_packet.head_tag();
|
||||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
|
||||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
|
||||||
nonce_raw[8] = net_packet.protocol().into();
|
|
||||||
nonce_raw[9] = net_packet.transport_protocol();
|
|
||||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
|
||||||
nonce_raw[11] = net_packet.source_ttl();
|
|
||||||
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
|
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
|
||||||
|
|
||||||
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())?;
|
||||||
@@ -62,7 +55,7 @@ impl AesGcmCipher {
|
|||||||
if let Some(finger) = &self.finger {
|
if let Some(finger) = &self.finger {
|
||||||
let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body());
|
let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body());
|
||||||
if &finger != secret_body.finger() {
|
if &finger != secret_body.finger() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
return Err(anyhow!("finger err"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let tag: GenericArray<u8, U16> = Tag::clone_from_slice(tag);
|
let tag: GenericArray<u8, U16> = Tag::clone_from_slice(tag);
|
||||||
@@ -75,10 +68,7 @@ impl AesGcmCipher {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Err(e) = rs {
|
if let Err(e) = rs {
|
||||||
return Err(io::Error::new(
|
return Err(anyhow!("解密失败:{}", e));
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("解密失败:{}", e),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
net_packet.set_encrypt_flag(false);
|
net_packet.set_encrypt_flag(false);
|
||||||
net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?;
|
net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?;
|
||||||
@@ -89,17 +79,11 @@ impl AesGcmCipher {
|
|||||||
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<()> {
|
) -> anyhow::Result<()> {
|
||||||
if net_packet.reserve() < AES_GCM_ENCRYPTION_RESERVED {
|
if net_packet.reserve() < AES_GCM_ENCRYPTION_RESERVED {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "too short"));
|
return Err(anyhow!("too short"));
|
||||||
}
|
}
|
||||||
let mut nonce_raw = [0; 12];
|
let nonce_raw = net_packet.head_tag();
|
||||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
|
||||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
|
||||||
nonce_raw[8] = net_packet.protocol().into();
|
|
||||||
nonce_raw[9] = net_packet.transport_protocol();
|
|
||||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
|
||||||
nonce_raw[11] = net_packet.source_ttl();
|
|
||||||
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
|
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
|
||||||
let data_len = net_packet.data_len() + AES_GCM_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)?;
|
||||||
@@ -123,10 +107,26 @@ impl AesGcmCipher {
|
|||||||
net_packet.set_encrypt_flag(true);
|
net_packet.set_encrypt_flag(true);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => Err(io::Error::new(
|
Err(e) => Err(anyhow!("加密失败:{}", e)),
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("加密失败:{}", e),
|
|
||||||
)),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_aes_gcm() {
|
||||||
|
let d = AesGcmCipher::new_256([0; 32], Some(Finger::new("123")));
|
||||||
|
let mut p =
|
||||||
|
NetPacket::new_encrypt([1; 13 + crate::protocol::body::ENCRYPTION_RESERVED]).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 = AesGcmCipher::new_256([0; 32], None);
|
||||||
|
let mut p =
|
||||||
|
NetPacket::new_encrypt([0; 13 + crate::protocol::body::ENCRYPTION_RESERVED]).unwrap();
|
||||||
|
let src = p.buffer().to_vec();
|
||||||
|
d.encrypt_ipv4(&mut p).unwrap();
|
||||||
|
d.decrypt_ipv4(&mut p).unwrap();
|
||||||
|
assert_eq!(p.buffer(), &src);
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#[cfg(feature = "ring-cipher")]
|
||||||
|
mod ring_aes_gcm_cipher;
|
||||||
|
#[cfg(feature = "ring-cipher")]
|
||||||
|
pub use ring_aes_gcm_cipher::*;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ring-cipher"))]
|
||||||
|
mod aes_gcm_cipher;
|
||||||
|
#[cfg(not(feature = "ring-cipher"))]
|
||||||
|
pub use aes_gcm_cipher::*;
|
||||||
+31
-33
@@ -1,9 +1,9 @@
|
|||||||
use crate::cipher::Finger;
|
use anyhow::anyhow;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use ring::aead;
|
use ring::aead;
|
||||||
use ring::aead::{LessSafeKey, UnboundKey};
|
use ring::aead::{LessSafeKey, UnboundKey};
|
||||||
use std::io;
|
|
||||||
|
|
||||||
|
use crate::cipher::Finger;
|
||||||
use crate::protocol::body::{SecretBody, AES_GCM_ENCRYPTION_RESERVED};
|
use crate::protocol::body::{SecretBody, AES_GCM_ENCRYPTION_RESERVED};
|
||||||
use crate::protocol::NetPacket;
|
use crate::protocol::NetPacket;
|
||||||
|
|
||||||
@@ -53,28 +53,22 @@ impl AesGcmCipher {
|
|||||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
net_packet: &mut NetPacket<B>,
|
net_packet: &mut NetPacket<B>,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if !net_packet.is_encrypt() {
|
if !net_packet.is_encrypt() {
|
||||||
//未加密的数据直接丢弃
|
//未加密的数据直接丢弃
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
return Err(anyhow!("not encrypt"));
|
||||||
}
|
}
|
||||||
if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED {
|
if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED {
|
||||||
log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED);
|
log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED);
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
let mut nonce_raw = [0; 12];
|
let nonce_raw = net_packet.head_tag();
|
||||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
|
||||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
|
||||||
nonce_raw[8] = net_packet.protocol().into();
|
|
||||||
nonce_raw[9] = net_packet.transport_protocol();
|
|
||||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
|
||||||
nonce_raw[11] = net_packet.source_ttl();
|
|
||||||
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
|
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
|
||||||
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())?;
|
||||||
if let Some(finger) = &self.finger {
|
if let Some(finger) = &self.finger {
|
||||||
let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body());
|
let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body());
|
||||||
if &finger != secret_body.finger() {
|
if &finger != secret_body.finger() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "ring aes finger err"));
|
return Err(anyhow!("ring aes finger err"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,10 +81,7 @@ impl AesGcmCipher {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Err(e) = rs {
|
if let Err(e) = rs {
|
||||||
return Err(io::Error::new(
|
return Err(anyhow!("解密失败:{}", e));
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("解密失败:{}", e),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
net_packet.set_encrypt_flag(false);
|
net_packet.set_encrypt_flag(false);
|
||||||
net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?;
|
net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?;
|
||||||
@@ -102,14 +93,8 @@ impl AesGcmCipher {
|
|||||||
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<()> {
|
) -> anyhow::Result<()> {
|
||||||
let mut nonce_raw = [0; 12];
|
let nonce_raw = net_packet.head_tag();
|
||||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
|
||||||
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
|
|
||||||
nonce_raw[8] = net_packet.protocol().into();
|
|
||||||
nonce_raw[9] = net_packet.transport_protocol();
|
|
||||||
nonce_raw[10] = net_packet.is_gateway() as u8;
|
|
||||||
nonce_raw[11] = net_packet.source_ttl();
|
|
||||||
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
|
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
|
||||||
let data_len = net_packet.data_len() + AES_GCM_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)?;
|
||||||
@@ -128,10 +113,7 @@ impl AesGcmCipher {
|
|||||||
Ok(tag) => {
|
Ok(tag) => {
|
||||||
let tag = tag.as_ref();
|
let tag = tag.as_ref();
|
||||||
if tag.len() != 16 {
|
if tag.len() != 16 {
|
||||||
return Err(io::Error::new(
|
return Err(anyhow!("加密tag长度错误:{}", tag.len()));
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("加密tag长度错误:{}", tag.len()),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
secret_body.set_tag(tag)?;
|
secret_body.set_tag(tag)?;
|
||||||
if let Some(finger) = &self.finger {
|
if let Some(finger) = &self.finger {
|
||||||
@@ -141,10 +123,26 @@ impl AesGcmCipher {
|
|||||||
net_packet.set_encrypt_flag(true);
|
net_packet.set_encrypt_flag(true);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => Err(io::Error::new(
|
Err(e) => Err(anyhow!("加密失败:{}", e)),
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("加密失败:{}", e),
|
|
||||||
)),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_aes_gcm() {
|
||||||
|
let d = AesGcmCipher::new_256([0; 32], Some(Finger::new("123")));
|
||||||
|
let mut p =
|
||||||
|
NetPacket::new_encrypt([0; 13 + crate::protocol::body::ENCRYPTION_RESERVED]).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 = AesGcmCipher::new_256([0; 32], None);
|
||||||
|
let mut p =
|
||||||
|
NetPacket::new_encrypt([0; 13 + crate::protocol::body::ENCRYPTION_RESERVED]).unwrap();
|
||||||
|
let src = p.buffer().to_vec();
|
||||||
|
d.encrypt_ipv4(&mut p).unwrap();
|
||||||
|
d.decrypt_ipv4(&mut p).unwrap();
|
||||||
|
assert_eq!(p.buffer(), &src);
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
mod rs_chacha20;
|
||||||
|
pub use rs_chacha20::*;
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
use aes::cipher::Iv;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use chacha20::cipher::{Key, KeyIvInit, StreamCipher};
|
||||||
|
use chacha20::ChaCha20;
|
||||||
|
|
||||||
|
use crate::cipher::finger::{gen_nonce, gen_random_nonce};
|
||||||
|
use crate::cipher::Finger;
|
||||||
|
use crate::protocol::body::{
|
||||||
|
IVSecretBody, SecretTail, SecretTailMut, FINGER_RESERVED, RANDOM_RESERVED,
|
||||||
|
};
|
||||||
|
use crate::protocol::NetPacket;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ChaCha20Cipher {
|
||||||
|
key: [u8; 32],
|
||||||
|
pub(crate) finger: Option<Finger>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChaCha20Cipher {
|
||||||
|
pub fn new_256(key: [u8; 32], finger: Option<Finger>) -> Self {
|
||||||
|
Self { key, finger }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChaCha20Cipher {
|
||||||
|
pub fn key(&self) -> &[u8] {
|
||||||
|
&self.key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChaCha20Cipher {
|
||||||
|
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
net_packet: &mut NetPacket<B>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
if !net_packet.is_encrypt() {
|
||||||
|
//未加密的数据直接丢弃
|
||||||
|
return Err(anyhow!("not encrypt"));
|
||||||
|
}
|
||||||
|
let mut head_tag = net_packet.head_tag();
|
||||||
|
|
||||||
|
let mut secret_body = IVSecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
||||||
|
if let Some(finger) = &self.finger {
|
||||||
|
let finger = finger.calculate_finger(&head_tag, secret_body.data());
|
||||||
|
if &finger != secret_body.finger() {
|
||||||
|
return Err(anyhow!("ChaCha20 finger err"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gen_nonce(&mut head_tag, secret_body.random_buf());
|
||||||
|
ChaCha20::new(
|
||||||
|
Key::<ChaCha20>::from_slice(&self.key),
|
||||||
|
Iv::<ChaCha20>::from_slice(&head_tag),
|
||||||
|
)
|
||||||
|
.apply_keystream(secret_body.data_mut());
|
||||||
|
let len = secret_body.data().len();
|
||||||
|
net_packet.set_encrypt_flag(false);
|
||||||
|
net_packet.set_payload_len(len)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
net_packet: &mut NetPacket<B>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let data_len = net_packet.data_len();
|
||||||
|
let head_tag = net_packet.head_tag();
|
||||||
|
if let Some(_) = &self.finger {
|
||||||
|
net_packet.set_data_len(data_len + RANDOM_RESERVED + FINGER_RESERVED)?;
|
||||||
|
} else {
|
||||||
|
net_packet.set_data_len(data_len + RANDOM_RESERVED)?;
|
||||||
|
}
|
||||||
|
let mut secret_body = IVSecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
||||||
|
let mut nonce = head_tag;
|
||||||
|
secret_body.set_random(&gen_random_nonce(&mut nonce));
|
||||||
|
|
||||||
|
ChaCha20::new(
|
||||||
|
Key::<ChaCha20>::from_slice(&self.key),
|
||||||
|
Iv::<ChaCha20>::from_slice(&nonce),
|
||||||
|
)
|
||||||
|
.apply_keystream(secret_body.data_mut());
|
||||||
|
if let Some(finger) = &self.finger {
|
||||||
|
let finger = finger.calculate_finger(&head_tag, secret_body.data());
|
||||||
|
let mut secret_body = IVSecretBody::new(net_packet.payload_mut(), true)?;
|
||||||
|
secret_body.set_finger(&finger)?;
|
||||||
|
}
|
||||||
|
net_packet.set_encrypt_flag(true);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_chacha20() {
|
||||||
|
let d = ChaCha20Cipher::new_256([0; 32], Some(Finger::new("123")));
|
||||||
|
let mut p =
|
||||||
|
NetPacket::new_encrypt([1; 13 + crate::protocol::body::ENCRYPTION_RESERVED]).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 = ChaCha20Cipher::new_256([0; 32], None);
|
||||||
|
let mut p =
|
||||||
|
NetPacket::new_encrypt([2; 13 + crate::protocol::body::ENCRYPTION_RESERVED]).unwrap();
|
||||||
|
let src = p.buffer().to_vec();
|
||||||
|
d.encrypt_ipv4(&mut p).unwrap();
|
||||||
|
d.decrypt_ipv4(&mut p).unwrap();
|
||||||
|
assert_eq!(p.buffer(), &src);
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#[cfg(feature = "ring-cipher")]
|
||||||
|
mod ring_chacha20_poly1305;
|
||||||
|
#[cfg(feature = "ring-cipher")]
|
||||||
|
pub use ring_chacha20_poly1305::*;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ring-cipher"))]
|
||||||
|
mod rs_chacha20_poly1305;
|
||||||
|
#[cfg(not(feature = "ring-cipher"))]
|
||||||
|
pub use rs_chacha20_poly1305::*;
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
use anyhow::anyhow;
|
||||||
|
|
||||||
|
use ring::aead;
|
||||||
|
use ring::aead::{LessSafeKey, UnboundKey};
|
||||||
|
|
||||||
|
use crate::cipher::finger::{gen_nonce, gen_random_nonce};
|
||||||
|
use crate::cipher::Finger;
|
||||||
|
use crate::protocol::body::{
|
||||||
|
AEADSecretBody, SecretTail, SecretTailMut, FINGER_RESERVED, RANDOM_RESERVED, TAG_RESERVED,
|
||||||
|
};
|
||||||
|
use crate::protocol::NetPacket;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ChaCha20Poly1305Cipher {
|
||||||
|
key: Vec<u8>,
|
||||||
|
pub(crate) cipher: LessSafeKey,
|
||||||
|
pub(crate) finger: Option<Finger>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChaCha20Poly1305Cipher {
|
||||||
|
pub fn new_256(key: [u8; 32], finger: Option<Finger>) -> Self {
|
||||||
|
let cipher = LessSafeKey::new(UnboundKey::new(&aead::CHACHA20_POLY1305, &key).unwrap());
|
||||||
|
Self {
|
||||||
|
key: key.to_vec(),
|
||||||
|
cipher,
|
||||||
|
finger,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChaCha20Poly1305Cipher {
|
||||||
|
pub fn key(&self) -> &[u8] {
|
||||||
|
&self.key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChaCha20Poly1305Cipher {
|
||||||
|
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
net_packet: &mut NetPacket<B>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
if !net_packet.is_encrypt() {
|
||||||
|
//未加密的数据直接丢弃
|
||||||
|
return Err(anyhow!("not encrypt"));
|
||||||
|
}
|
||||||
|
if net_packet.payload().len() < TAG_RESERVED {
|
||||||
|
log::error!("数据异常,长度小于{}", TAG_RESERVED);
|
||||||
|
return Err(anyhow!("data err"));
|
||||||
|
}
|
||||||
|
let mut head_tag = net_packet.head_tag();
|
||||||
|
let mut secret_body = AEADSecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
||||||
|
if let Some(finger) = &self.finger {
|
||||||
|
let finger = finger.calculate_finger(&head_tag, secret_body.data_tag_mut());
|
||||||
|
if &finger != secret_body.finger() {
|
||||||
|
return Err(anyhow!("ring CHACHA20_POLY1305 finger err"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gen_nonce(&mut head_tag, secret_body.random_buf());
|
||||||
|
let nonce = aead::Nonce::assume_unique_for_key(head_tag);
|
||||||
|
let rs = self
|
||||||
|
.cipher
|
||||||
|
.open_in_place(nonce, aead::Aad::empty(), secret_body.data_tag_mut());
|
||||||
|
if let Err(e) = rs {
|
||||||
|
return Err(anyhow!("ring CHACHA20_POLY1305 解密失败:{}", e));
|
||||||
|
}
|
||||||
|
let len = secret_body.data().len();
|
||||||
|
net_packet.set_encrypt_flag(false);
|
||||||
|
net_packet.set_payload_len(len)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
/// net_packet 必须预留足够长度
|
||||||
|
/// data_len是有效载荷的长度
|
||||||
|
/// 返回加密后载荷的长度
|
||||||
|
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
net_packet: &mut NetPacket<B>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let head_tag = net_packet.head_tag();
|
||||||
|
let data_len = net_packet.data_len();
|
||||||
|
if self.finger.is_some() {
|
||||||
|
net_packet.set_data_len(data_len + TAG_RESERVED + RANDOM_RESERVED + FINGER_RESERVED)?;
|
||||||
|
} else {
|
||||||
|
net_packet.set_data_len(data_len + TAG_RESERVED + RANDOM_RESERVED)?;
|
||||||
|
}
|
||||||
|
let mut secret_body = AEADSecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
||||||
|
let mut nonce = head_tag;
|
||||||
|
secret_body.set_random(&gen_random_nonce(&mut nonce));
|
||||||
|
let nonce = aead::Nonce::assume_unique_for_key(nonce);
|
||||||
|
let rs = self.cipher.seal_in_place_separate_tag(
|
||||||
|
nonce,
|
||||||
|
aead::Aad::empty(),
|
||||||
|
secret_body.data_mut(),
|
||||||
|
);
|
||||||
|
match rs {
|
||||||
|
Ok(tag) => {
|
||||||
|
let tag = tag.as_ref();
|
||||||
|
if tag.len() != 16 {
|
||||||
|
return Err(anyhow!("加密tag长度错误:{}", tag.len()));
|
||||||
|
}
|
||||||
|
secret_body.set_tag(tag)?;
|
||||||
|
if let Some(finger) = &self.finger {
|
||||||
|
let finger = finger.calculate_finger(&head_tag, secret_body.data_tag_mut());
|
||||||
|
secret_body.set_finger(&finger)?;
|
||||||
|
}
|
||||||
|
net_packet.set_encrypt_flag(true);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(e) => Err(anyhow!("ring CHACHA20_POLY1305 加密失败:{}", e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ring_chacha20_poly1305() {
|
||||||
|
let d = ChaCha20Poly1305Cipher::new_256([0; 32], Some(Finger::new("123")));
|
||||||
|
let mut p = NetPacket::new_encrypt([0; 73]).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 = ChaCha20Poly1305Cipher::new_256([0; 32], None);
|
||||||
|
let mut p = NetPacket::new_encrypt([0; 73]).unwrap();
|
||||||
|
let src = p.buffer().to_vec();
|
||||||
|
d.encrypt_ipv4(&mut p).unwrap();
|
||||||
|
d.decrypt_ipv4(&mut p).unwrap();
|
||||||
|
assert_eq!(p.buffer(), &src);
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
use crate::cipher::finger::{gen_nonce, gen_random_nonce};
|
||||||
|
use crate::cipher::Finger;
|
||||||
|
use crate::protocol::body::{
|
||||||
|
AEADSecretBody, SecretTail, SecretTailMut, FINGER_RESERVED, RANDOM_RESERVED, TAG_RESERVED,
|
||||||
|
};
|
||||||
|
use crate::protocol::NetPacket;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use chacha20poly1305::aead::{Nonce, Tag};
|
||||||
|
use chacha20poly1305::{AeadInPlace, ChaCha20Poly1305, Key, KeyInit};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ChaCha20Poly1305Cipher {
|
||||||
|
key: Vec<u8>,
|
||||||
|
pub(crate) cipher: ChaCha20Poly1305,
|
||||||
|
pub(crate) finger: Option<Finger>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChaCha20Poly1305Cipher {
|
||||||
|
pub fn new_256(key: [u8; 32], finger: Option<Finger>) -> Self {
|
||||||
|
let key: &Key = &key.into();
|
||||||
|
let cipher = ChaCha20Poly1305::new(key);
|
||||||
|
Self {
|
||||||
|
key: key.to_vec(),
|
||||||
|
cipher,
|
||||||
|
finger,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChaCha20Poly1305Cipher {
|
||||||
|
pub fn key(&self) -> &[u8] {
|
||||||
|
&self.key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChaCha20Poly1305Cipher {
|
||||||
|
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
net_packet: &mut NetPacket<B>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
if !net_packet.is_encrypt() {
|
||||||
|
//未加密的数据直接丢弃
|
||||||
|
return Err(anyhow!("not encrypt"));
|
||||||
|
}
|
||||||
|
if net_packet.payload().len() < TAG_RESERVED {
|
||||||
|
log::error!("数据异常,长度小于{}", TAG_RESERVED);
|
||||||
|
return Err(anyhow!("data err"));
|
||||||
|
}
|
||||||
|
let mut head_tag = net_packet.head_tag();
|
||||||
|
let mut secret_body = AEADSecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
||||||
|
if let Some(finger) = &self.finger {
|
||||||
|
let finger = finger.calculate_finger(&head_tag, secret_body.data_tag_mut());
|
||||||
|
if &finger != secret_body.finger() {
|
||||||
|
return Err(anyhow!("rs CHACHA20_POLY1305 finger err"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gen_nonce(&mut head_tag, secret_body.random_buf());
|
||||||
|
let nonce: Nonce<ChaCha20Poly1305> = head_tag.into();
|
||||||
|
let tag: Tag<ChaCha20Poly1305> =
|
||||||
|
Tag::<ChaCha20Poly1305>::from_slice(secret_body.tag()).clone();
|
||||||
|
if let Err(e) =
|
||||||
|
self.cipher
|
||||||
|
.decrypt_in_place_detached(&nonce, &[], secret_body.data_mut(), &tag)
|
||||||
|
{
|
||||||
|
return Err(anyhow!("rs CHACHA20_POLY1305 decrypt_ipv4 {:?}", e));
|
||||||
|
}
|
||||||
|
let len = secret_body.data().len();
|
||||||
|
net_packet.set_encrypt_flag(false);
|
||||||
|
net_packet.set_payload_len(len)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
/// net_packet 必须预留足够长度
|
||||||
|
/// data_len是有效载荷的长度
|
||||||
|
/// 返回加密后载荷的长度
|
||||||
|
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
net_packet: &mut NetPacket<B>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let head_tag = net_packet.head_tag();
|
||||||
|
let data_len = net_packet.data_len();
|
||||||
|
if self.finger.is_some() {
|
||||||
|
net_packet.set_data_len(data_len + TAG_RESERVED + RANDOM_RESERVED + FINGER_RESERVED)?;
|
||||||
|
} else {
|
||||||
|
net_packet.set_data_len(data_len + TAG_RESERVED + RANDOM_RESERVED)?;
|
||||||
|
}
|
||||||
|
let mut secret_body = AEADSecretBody::new(net_packet.payload_mut(), self.finger.is_some())?;
|
||||||
|
let mut nonce = head_tag;
|
||||||
|
secret_body.set_random(&gen_random_nonce(&mut nonce));
|
||||||
|
let nonce = nonce.into();
|
||||||
|
let rs = self
|
||||||
|
.cipher
|
||||||
|
.encrypt_in_place_detached(&nonce, &[], secret_body.data_mut());
|
||||||
|
match rs {
|
||||||
|
Ok(tag) => {
|
||||||
|
let tag: &[u8] = tag.as_ref();
|
||||||
|
if tag.len() != 16 {
|
||||||
|
return Err(anyhow!("加密tag长度错误:{}", tag.len(),));
|
||||||
|
}
|
||||||
|
secret_body.set_tag(tag)?;
|
||||||
|
if let Some(finger) = &self.finger {
|
||||||
|
let finger = finger.calculate_finger(&head_tag, secret_body.data_tag_mut());
|
||||||
|
secret_body.set_finger(&finger)?;
|
||||||
|
}
|
||||||
|
net_packet.set_encrypt_flag(true);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(e) => Err(anyhow!("rs CHACHA20_POLY1305 加密失败:{}", e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rs_chacha20_poly1305() {
|
||||||
|
let d = ChaCha20Poly1305Cipher::new_256([0; 32], Some(Finger::new("123")));
|
||||||
|
let mut p = NetPacket::new_encrypt([0; 73]).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 = ChaCha20Poly1305Cipher::new_256([0; 32], None);
|
||||||
|
let mut p = NetPacket::new_encrypt([0; 73]).unwrap();
|
||||||
|
let src = p.buffer().to_vec();
|
||||||
|
d.encrypt_ipv4(&mut p).unwrap();
|
||||||
|
d.decrypt_ipv4(&mut p).unwrap();
|
||||||
|
assert_eq!(p.buffer(), &src);
|
||||||
|
}
|
||||||
+126
-142
@@ -1,110 +1,99 @@
|
|||||||
#[cfg(feature = "aes_ecb")]
|
|
||||||
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
|
|
||||||
use crate::cipher::aes_ecb::AesEcbCipher;
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
|
#[cfg(cipher)]
|
||||||
|
use sha2::Digest;
|
||||||
|
|
||||||
#[cfg(feature = "aes_cbc")]
|
#[cfg(feature = "aes_cbc")]
|
||||||
use crate::cipher::aes_cbc::AesCbcCipher;
|
use crate::cipher::aes_cbc::AesCbcCipher;
|
||||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
|
||||||
#[cfg(not(feature = "ring-cipher"))]
|
|
||||||
use crate::cipher::aes_gcm_cipher::AesGcmCipher;
|
|
||||||
#[cfg(feature = "aes_ecb")]
|
#[cfg(feature = "aes_ecb")]
|
||||||
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
|
use crate::cipher::aes_ecb::AesEcbCipher;
|
||||||
use crate::cipher::openssl_aes_ecb::AesEcbCipher;
|
|
||||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
#[cfg(feature = "ring-cipher")]
|
use crate::cipher::aes_gcm::AesGcmCipher;
|
||||||
use crate::cipher::ring_aes_gcm_cipher::AesGcmCipher;
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
use crate::cipher::chacha20::ChaCha20Cipher;
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
use crate::cipher::chacha20_poly1305::ChaCha20Poly1305Cipher;
|
||||||
#[cfg(feature = "sm4_cbc")]
|
#[cfg(feature = "sm4_cbc")]
|
||||||
use crate::cipher::sm4_cbc::Sm4CbcCipher;
|
use crate::cipher::sm4_cbc::Sm4CbcCipher;
|
||||||
#[cfg(any(
|
use crate::cipher::xor::XORCipher;
|
||||||
feature = "aes_gcm",
|
#[cfg(cipher)]
|
||||||
feature = "server_encrypt",
|
|
||||||
feature = "aes_cbc",
|
|
||||||
feature = "aes_ecb",
|
|
||||||
feature = "sm4_cbc"
|
|
||||||
))]
|
|
||||||
use crate::cipher::Finger;
|
use crate::cipher::Finger;
|
||||||
use crate::protocol::NetPacket;
|
use crate::protocol::NetPacket;
|
||||||
#[cfg(any(
|
|
||||||
feature = "aes_gcm",
|
|
||||||
feature = "server_encrypt",
|
|
||||||
feature = "aes_cbc",
|
|
||||||
feature = "aes_ecb",
|
|
||||||
feature = "sm4_cbc"
|
|
||||||
))]
|
|
||||||
use sha2::Digest;
|
|
||||||
use std::io;
|
|
||||||
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"))]
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
AesGcm,
|
AesGcm,
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
Chacha20Poly1305,
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
Chacha20,
|
||||||
#[cfg(feature = "aes_cbc")]
|
#[cfg(feature = "aes_cbc")]
|
||||||
AesCbc,
|
AesCbc,
|
||||||
#[cfg(feature = "aes_ecb")]
|
#[cfg(feature = "aes_ecb")]
|
||||||
AesEcb,
|
AesEcb,
|
||||||
#[cfg(feature = "sm4_cbc")]
|
#[cfg(feature = "sm4_cbc")]
|
||||||
Sm4Cbc,
|
Sm4Cbc,
|
||||||
|
Xor,
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for CipherModel {
|
impl Display for CipherModel {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let str = match self {
|
let str = match self {
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
CipherModel::AesGcm => "aes_gcm".to_string(),
|
CipherModel::AesGcm => "aes_gcm".to_string(),
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
CipherModel::Chacha20Poly1305 => "chacha20_poly1305".to_string(),
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
CipherModel::Chacha20 => "chacha20".to_string(),
|
||||||
|
#[cfg(feature = "aes_cbc")]
|
||||||
CipherModel::AesCbc => "aes_cbc".to_string(),
|
CipherModel::AesCbc => "aes_cbc".to_string(),
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
CipherModel::AesEcb => "aes_ecb".to_string(),
|
CipherModel::AesEcb => "aes_ecb".to_string(),
|
||||||
|
#[cfg(feature = "sm4_cbc")]
|
||||||
CipherModel::Sm4Cbc => "sm4_cbc".to_string(),
|
CipherModel::Sm4Cbc => "sm4_cbc".to_string(),
|
||||||
|
CipherModel::Xor => "xor".to_string(),
|
||||||
CipherModel::None => "none".to_string(),
|
CipherModel::None => "none".to_string(),
|
||||||
};
|
};
|
||||||
write!(f, "{}", str)
|
write!(f, "{}", str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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"))]
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
"aes_gcm" => Ok(CipherModel::AesGcm),
|
"aes_gcm" => Ok(CipherModel::AesGcm),
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
"chacha20_poly1305" => Ok(CipherModel::Chacha20Poly1305),
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
"chacha20" => Ok(CipherModel::Chacha20),
|
||||||
#[cfg(feature = "aes_cbc")]
|
#[cfg(feature = "aes_cbc")]
|
||||||
"aes_cbc" => Ok(CipherModel::AesCbc),
|
"aes_cbc" => Ok(CipherModel::AesCbc),
|
||||||
#[cfg(feature = "aes_ecb")]
|
#[cfg(feature = "aes_ecb")]
|
||||||
"aes_ecb" => Ok(CipherModel::AesEcb),
|
"aes_ecb" => Ok(CipherModel::AesEcb),
|
||||||
#[cfg(feature = "sm4_cbc")]
|
#[cfg(feature = "sm4_cbc")]
|
||||||
"sm4_cbc" => Ok(CipherModel::Sm4Cbc),
|
"sm4_cbc" => Ok(CipherModel::Sm4Cbc),
|
||||||
|
"xor" => Ok(CipherModel::Xor),
|
||||||
_ => {
|
_ => {
|
||||||
let mut enums = String::new();
|
let mut enums = String::new();
|
||||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
enums.push_str("/aes_gcm");
|
enums.push_str("/aes_gcm");
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
enums.push_str("/chacha20_poly1305/chacha20");
|
||||||
#[cfg(feature = "aes_cbc")]
|
#[cfg(feature = "aes_cbc")]
|
||||||
enums.push_str("/aes_cbc");
|
enums.push_str("/aes_cbc");
|
||||||
#[cfg(feature = "aes_ecb")]
|
#[cfg(feature = "aes_ecb")]
|
||||||
enums.push_str("/aes_ecb");
|
enums.push_str("/aes_ecb");
|
||||||
#[cfg(feature = "sm4_cbc")]
|
#[cfg(feature = "sm4_cbc")]
|
||||||
enums.push_str("/sm4_cbc");
|
enums.push_str("/sm4_cbc");
|
||||||
let str = if enums.is_empty() {
|
enums.push_str("/xor");
|
||||||
"no encrypt"
|
Err(format!("not match '{}', enum:{}", s, &enums[1..]))
|
||||||
} else {
|
|
||||||
&enums[1..]
|
|
||||||
};
|
|
||||||
Err(format!("not match '{}', enum:{}", s, str))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,199 +103,176 @@ impl FromStr for CipherModel {
|
|||||||
pub enum Cipher {
|
pub enum Cipher {
|
||||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
AesGcm((AesGcmCipher, Vec<u8>)),
|
AesGcm((AesGcmCipher, Vec<u8>)),
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
Chacha20Poly1305(ChaCha20Poly1305Cipher),
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
Chacha20(ChaCha20Cipher),
|
||||||
#[cfg(feature = "aes_cbc")]
|
#[cfg(feature = "aes_cbc")]
|
||||||
AesCbc(AesCbcCipher),
|
AesCbc(AesCbcCipher),
|
||||||
#[cfg(feature = "aes_ecb")]
|
#[cfg(feature = "aes_ecb")]
|
||||||
AesEcb(AesEcbCipher),
|
AesEcb(AesEcbCipher),
|
||||||
#[cfg(feature = "sm4_cbc")]
|
#[cfg(feature = "sm4_cbc")]
|
||||||
Sm4Cbc(Sm4CbcCipher),
|
Sm4Cbc(Sm4CbcCipher),
|
||||||
|
Xor(XORCipher),
|
||||||
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>,
|
||||||
token: Option<String>,
|
token: Option<String>,
|
||||||
) -> Self {
|
) -> anyhow::Result<Self> {
|
||||||
let finger = token.map(|token| Finger::new(&token));
|
|
||||||
if let Some(password) = password {
|
if let Some(password) = password {
|
||||||
let mut hasher = sha2::Sha256::new();
|
#[cfg(cipher)]
|
||||||
hasher.update(password.as_bytes());
|
let key: [u8; 32] = {
|
||||||
let key: [u8; 32] = hasher.finalize().into();
|
let mut hasher = sha2::Sha256::new();
|
||||||
|
hasher.update(password.as_bytes());
|
||||||
|
hasher.finalize().into()
|
||||||
|
};
|
||||||
match model {
|
match model {
|
||||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
CipherModel::AesGcm => {
|
CipherModel::AesGcm => {
|
||||||
|
let finger = token.map(|token| Finger::new(&token));
|
||||||
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);
|
||||||
Cipher::AesGcm((aes, key[..16].to_vec()))
|
Ok(Cipher::AesGcm((aes, key[..16].to_vec())))
|
||||||
} else {
|
} else {
|
||||||
let aes = AesGcmCipher::new_256(key, finger);
|
let aes = AesGcmCipher::new_256(key, finger);
|
||||||
Cipher::AesGcm((aes, key.to_vec()))
|
Ok(Cipher::AesGcm((aes, key.to_vec())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
CipherModel::Chacha20Poly1305 => {
|
||||||
|
let finger = token.map(|token| Finger::new(&token));
|
||||||
|
let chacha = ChaCha20Poly1305Cipher::new_256(key, finger);
|
||||||
|
Ok(Cipher::Chacha20Poly1305(chacha))
|
||||||
|
}
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
CipherModel::Chacha20 => {
|
||||||
|
let finger = token.map(|token| Finger::new(&token));
|
||||||
|
let chacha = ChaCha20Cipher::new_256(key, finger);
|
||||||
|
Ok(Cipher::Chacha20(chacha))
|
||||||
|
}
|
||||||
#[cfg(feature = "aes_cbc")]
|
#[cfg(feature = "aes_cbc")]
|
||||||
CipherModel::AesCbc => {
|
CipherModel::AesCbc => {
|
||||||
|
let finger = token.map(|token| Finger::new(&token));
|
||||||
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);
|
||||||
Cipher::AesCbc(aes)
|
Ok(Cipher::AesCbc(aes))
|
||||||
} else {
|
} else {
|
||||||
let aes = AesCbcCipher::new_256(key, finger);
|
let aes = AesCbcCipher::new_256(key, finger);
|
||||||
Cipher::AesCbc(aes)
|
Ok(Cipher::AesCbc(aes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "aes_ecb")]
|
#[cfg(feature = "aes_ecb")]
|
||||||
CipherModel::AesEcb => {
|
CipherModel::AesEcb => {
|
||||||
|
let finger = token.map(|token| Finger::new(&token));
|
||||||
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);
|
||||||
Cipher::AesEcb(aes)
|
Ok(Cipher::AesEcb(aes))
|
||||||
} else {
|
} else {
|
||||||
let aes = AesEcbCipher::new_256(key, finger);
|
let aes = AesEcbCipher::new_256(key, finger);
|
||||||
Cipher::AesEcb(aes)
|
Ok(Cipher::AesEcb(aes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sm4_cbc")]
|
#[cfg(feature = "sm4_cbc")]
|
||||||
CipherModel::Sm4Cbc => {
|
CipherModel::Sm4Cbc => {
|
||||||
|
let finger = token.map(|token| Finger::new(&token));
|
||||||
let aes = Sm4CbcCipher::new_128(key[..16].try_into().unwrap(), finger);
|
let aes = Sm4CbcCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||||
Cipher::Sm4Cbc(aes)
|
Ok(Cipher::Sm4Cbc(aes))
|
||||||
}
|
}
|
||||||
CipherModel::None => Cipher::None,
|
CipherModel::Xor => {
|
||||||
|
if token.is_some() {
|
||||||
|
Err(anyhow::anyhow!(
|
||||||
|
"'finger' and 'xor' cannot be used simultaneously"
|
||||||
|
))?
|
||||||
|
}
|
||||||
|
Ok(Cipher::Xor(XORCipher::new_256(
|
||||||
|
crate::cipher::xor::simple_hash(&password),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
CipherModel::None => Ok(Cipher::None),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Cipher::None
|
Ok(Cipher::None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(any(
|
#[cfg(not(any(feature = "aes_gcm", feature = "server_encrypt")))]
|
||||||
feature = "aes_gcm",
|
pub fn new_key(_key: [u8; 32], _token: String) -> anyhow::Result<Self> {
|
||||||
feature = "server_encrypt",
|
Err(anyhow!("key error"))
|
||||||
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(
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
feature = "aes_gcm",
|
pub fn new_key(key: [u8; 32], token: String) -> anyhow::Result<Self> {
|
||||||
feature = "server_encrypt",
|
|
||||||
feature = "aes_cbc",
|
|
||||||
feature = "aes_ecb",
|
|
||||||
feature = "sm4_cbc"
|
|
||||||
))]
|
|
||||||
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())))
|
||||||
}
|
}
|
||||||
_ => Err(io::Error::new(io::ErrorKind::Other, "key error")),
|
_ => Err(anyhow!("key error")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
net_packet: &mut NetPacket<B>,
|
net_packet: &mut NetPacket<B>,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
#[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")]
|
#[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 = "chacha20_poly1305")]
|
||||||
|
Cipher::Chacha20Poly1305(chacha20poly1305) => chacha20poly1305.decrypt_ipv4(net_packet),
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
Cipher::Chacha20(chacha20) => chacha20.decrypt_ipv4(net_packet),
|
||||||
#[cfg(feature = "aes_ecb")]
|
#[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")]
|
#[cfg(feature = "sm4_cbc")]
|
||||||
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.decrypt_ipv4(net_packet),
|
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.decrypt_ipv4(net_packet),
|
||||||
|
Cipher::Xor(xor) => xor.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(anyhow!("not key"));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[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<()> {
|
) -> anyhow::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
#[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 = "chacha20_poly1305")]
|
||||||
|
Cipher::Chacha20Poly1305(chacha20poly1305) => chacha20poly1305.encrypt_ipv4(net_packet),
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
Cipher::Chacha20(chacha20) => chacha20.encrypt_ipv4(net_packet),
|
||||||
#[cfg(feature = "aes_cbc")]
|
#[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")]
|
#[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")]
|
#[cfg(feature = "sm4_cbc")]
|
||||||
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.encrypt_ipv4(net_packet),
|
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.encrypt_ipv4(net_packet),
|
||||||
|
Cipher::Xor(xor) => xor.encrypt_ipv4(net_packet),
|
||||||
Cipher::None => Ok(()),
|
Cipher::None => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(any(
|
#[cfg(not(cipher))]
|
||||||
feature = "aes_gcm",
|
|
||||||
feature = "server_encrypt",
|
|
||||||
feature = "aes_cbc",
|
|
||||||
feature = "aes_ecb",
|
|
||||||
feature = "sm4_cbc"
|
|
||||||
)))]
|
|
||||||
pub fn check_finger<B: AsRef<[u8]> + AsMut<[u8]>>(
|
pub fn check_finger<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
_net_packet: &NetPacket<B>,
|
_net_packet: &NetPacket<B>,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
#[cfg(any(
|
#[cfg(cipher)]
|
||||||
feature = "aes_gcm",
|
pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> anyhow::Result<()> {
|
||||||
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<()> {
|
|
||||||
match self {
|
match self {
|
||||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
Cipher::AesGcm((aes_gcm, _)) => aes_gcm
|
Cipher::AesGcm((aes_gcm, _)) => aes_gcm
|
||||||
@@ -314,6 +280,18 @@ impl Cipher {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|f| f.check_finger(net_packet))
|
.map(|f| f.check_finger(net_packet))
|
||||||
.unwrap_or(Ok(())),
|
.unwrap_or(Ok(())),
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
Cipher::Chacha20Poly1305(chacha20poly1305) => chacha20poly1305
|
||||||
|
.finger
|
||||||
|
.as_ref()
|
||||||
|
.map(|f| f.check_finger(net_packet))
|
||||||
|
.unwrap_or(Ok(())),
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
Cipher::Chacha20(chacha20) => chacha20
|
||||||
|
.finger
|
||||||
|
.as_ref()
|
||||||
|
.map(|f| f.check_finger(net_packet))
|
||||||
|
.unwrap_or(Ok(())),
|
||||||
#[cfg(feature = "aes_cbc")]
|
#[cfg(feature = "aes_cbc")]
|
||||||
Cipher::AesCbc(aes_cbc) => aes_cbc
|
Cipher::AesCbc(aes_cbc) => aes_cbc
|
||||||
.finger
|
.finger
|
||||||
@@ -332,6 +310,7 @@ impl Cipher {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|f| f.check_finger(net_packet))
|
.map(|f| f.check_finger(net_packet))
|
||||||
.unwrap_or(Ok(())),
|
.unwrap_or(Ok(())),
|
||||||
|
Cipher::Xor(_) => Ok(()),
|
||||||
Cipher::None => Ok(()),
|
Cipher::None => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,12 +318,17 @@ impl Cipher {
|
|||||||
match self {
|
match self {
|
||||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
Cipher::AesGcm((_, key)) => Some(key),
|
Cipher::AesGcm((_, key)) => Some(key),
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
Cipher::Chacha20Poly1305(chacha20poly1305) => Some(chacha20poly1305.key()),
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
Cipher::Chacha20(chacha20) => Some(chacha20.key()),
|
||||||
#[cfg(feature = "aes_cbc")]
|
#[cfg(feature = "aes_cbc")]
|
||||||
Cipher::AesCbc(aes_cbc) => Some(aes_cbc.key()),
|
Cipher::AesCbc(aes_cbc) => Some(aes_cbc.key()),
|
||||||
#[cfg(feature = "aes_ecb")]
|
#[cfg(feature = "aes_ecb")]
|
||||||
Cipher::AesEcb(aes_ecb) => Some(aes_ecb.key()),
|
Cipher::AesEcb(aes_ecb) => Some(aes_ecb.key()),
|
||||||
#[cfg(feature = "sm4_cbc")]
|
#[cfg(feature = "sm4_cbc")]
|
||||||
Cipher::Sm4Cbc(sm4_cbc) => Some(sm4_cbc.key()),
|
Cipher::Sm4Cbc(sm4_cbc) => Some(sm4_cbc.key()),
|
||||||
|
Cipher::Xor(xor) => Some(xor.key()),
|
||||||
Cipher::None => None,
|
Cipher::None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use std::io;
|
use anyhow::anyhow;
|
||||||
|
use rand::RngCore;
|
||||||
|
|
||||||
use sha2::Digest;
|
use sha2::Digest;
|
||||||
|
|
||||||
@@ -16,15 +17,15 @@ impl Finger {
|
|||||||
let hash: [u8; 32] = hasher.finalize().into();
|
let hash: [u8; 32] = hasher.finalize().into();
|
||||||
Finger { hash }
|
Finger { hash }
|
||||||
}
|
}
|
||||||
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>) -> anyhow::Result<()> {
|
||||||
if !net_packet.is_encrypt() {
|
if !net_packet.is_encrypt() {
|
||||||
//未加密的数据直接丢弃
|
//未加密的数据直接丢弃
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
return Err(anyhow!("not encrypt"));
|
||||||
}
|
}
|
||||||
let payload_len = net_packet.payload().len();
|
let payload_len = net_packet.payload().len();
|
||||||
if payload_len < 12 {
|
if payload_len < 12 {
|
||||||
log::error!("数据异常,长度小于{}", 12);
|
log::error!("数据异常,长度小于{}", 12);
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
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());
|
||||||
@@ -36,7 +37,7 @@ impl Finger {
|
|||||||
let payload = net_packet.payload();
|
let payload = net_packet.payload();
|
||||||
let finger = self.calculate_finger(&nonce_raw, &payload[..payload_len - 12]);
|
let finger = self.calculate_finger(&nonce_raw, &payload[..payload_len - 12]);
|
||||||
if &finger[..] != &payload[payload_len - 12..] {
|
if &finger[..] != &payload[payload_len - 12..] {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
return Err(anyhow!("finger err"));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -49,3 +50,27 @@ impl Finger {
|
|||||||
return key[20..].try_into().unwrap();
|
return key[20..].try_into().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<B: AsRef<[u8]>> NetPacket<B> {
|
||||||
|
pub fn head_tag(&self) -> [u8; 12] {
|
||||||
|
let mut tag = [0; 12];
|
||||||
|
tag[0..4].copy_from_slice(&self.buffer()[4..8]);
|
||||||
|
tag[4..8].copy_from_slice(&self.buffer()[8..12]);
|
||||||
|
tag[8] = self.protocol().into();
|
||||||
|
tag[9] = self.transport_protocol();
|
||||||
|
tag[10] = self.is_gateway() as u8;
|
||||||
|
tag[11] = self.source_ttl();
|
||||||
|
tag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn gen_nonce(tag: &mut [u8], random: &[u8]) {
|
||||||
|
tag[8] = random[0] ^ tag[8];
|
||||||
|
tag[9] = random[1] ^ tag[9];
|
||||||
|
tag[10] = random[2] ^ tag[10];
|
||||||
|
tag[11] = random[3] ^ tag[11];
|
||||||
|
}
|
||||||
|
pub fn gen_random_nonce(tag: &mut [u8; 12]) -> [u8; 4] {
|
||||||
|
let mut random = [0; 4];
|
||||||
|
rand::thread_rng().fill_bytes(&mut random);
|
||||||
|
gen_nonce(tag, &random);
|
||||||
|
random
|
||||||
|
}
|
||||||
|
|||||||
+22
-30
@@ -1,40 +1,32 @@
|
|||||||
#[cfg(feature = "aes_cbc")]
|
|
||||||
mod aes_cbc;
|
|
||||||
#[cfg(feature = "aes_ecb")]
|
|
||||||
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
|
|
||||||
mod aes_ecb;
|
|
||||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
|
||||||
#[cfg(not(feature = "ring-cipher"))]
|
|
||||||
mod aes_gcm_cipher;
|
|
||||||
mod cipher;
|
mod cipher;
|
||||||
#[cfg(any(
|
#[cfg(cipher)]
|
||||||
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")]
|
|
||||||
mod ring_aes_gcm_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(
|
#[cfg(cipher)]
|
||||||
feature = "aes_gcm",
|
|
||||||
feature = "server_encrypt",
|
|
||||||
feature = "aes_cbc",
|
|
||||||
feature = "aes_ecb",
|
|
||||||
feature = "sm4_cbc"
|
|
||||||
))]
|
|
||||||
pub use finger::Finger;
|
pub use finger::Finger;
|
||||||
#[cfg(feature = "server_encrypt")]
|
#[cfg(feature = "server_encrypt")]
|
||||||
mod rsa_cipher;
|
mod rsa_cipher;
|
||||||
#[cfg(feature = "server_encrypt")]
|
#[cfg(feature = "server_encrypt")]
|
||||||
pub use rsa_cipher::RsaCipher;
|
pub use rsa_cipher::RsaCipher;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||||
|
mod aes_gcm;
|
||||||
|
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
mod chacha20;
|
||||||
|
#[cfg(feature = "chacha20_poly1305")]
|
||||||
|
mod chacha20_poly1305;
|
||||||
|
|
||||||
|
#[cfg(feature = "aes_ecb")]
|
||||||
|
mod aes_ecb;
|
||||||
|
|
||||||
|
#[cfg(feature = "aes_cbc")]
|
||||||
|
mod aes_cbc;
|
||||||
|
|
||||||
|
#[cfg(feature = "sm4_cbc")]
|
||||||
|
mod sm4_cbc;
|
||||||
|
|
||||||
|
mod xor;
|
||||||
|
pub use xor::simple_hash;
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
mod rs_sm4_cbc;
|
||||||
|
pub use rs_sm4_cbc::*;
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
use crate::cipher::Finger;
|
use crate::cipher::Finger;
|
||||||
use crate::protocol::{NetPacket, HEAD_LEN};
|
use crate::protocol::{NetPacket, HEAD_LEN};
|
||||||
|
use anyhow::anyhow;
|
||||||
use libsm::sm4::cipher_mode::CipherMode;
|
use libsm::sm4::cipher_mode::CipherMode;
|
||||||
use libsm::sm4::Sm4CipherMode;
|
use libsm::sm4::Sm4CipherMode;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use std::io;
|
|
||||||
|
|
||||||
pub struct Sm4CbcCipher {
|
pub struct Sm4CbcCipher {
|
||||||
key: [u8; 16],
|
key: [u8; 16],
|
||||||
@@ -41,28 +41,22 @@ impl Sm4CbcCipher {
|
|||||||
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
net_packet: &mut NetPacket<B>,
|
net_packet: &mut NetPacket<B>,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if !net_packet.is_encrypt() {
|
if !net_packet.is_encrypt() {
|
||||||
//未加密的数据直接丢弃
|
//未加密的数据直接丢弃
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
|
return Err(anyhow!("not encrypt"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(finger) = &self.finger {
|
if let Some(finger) = &self.finger {
|
||||||
let mut nonce_raw = [0; 12];
|
let nonce_raw = net_packet.head_tag();
|
||||||
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();
|
let len = net_packet.payload().len();
|
||||||
if len < 12 {
|
if len < 12 {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "payload len <12"));
|
return Err(anyhow!("payload len <12"));
|
||||||
}
|
}
|
||||||
let secret_body = &net_packet.payload()[..len - 12];
|
let secret_body = &net_packet.payload()[..len - 12];
|
||||||
let finger = finger.calculate_finger(&nonce_raw, secret_body);
|
let finger = finger.calculate_finger(&nonce_raw, secret_body);
|
||||||
if &finger != &net_packet.payload()[len - 12..] {
|
if &finger != &net_packet.payload()[len - 12..] {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
|
return Err(anyhow!("finger err"));
|
||||||
}
|
}
|
||||||
net_packet.set_data_len(net_packet.data_len() - finger.len())?;
|
net_packet.set_data_len(net_packet.data_len() - finger.len())?;
|
||||||
}
|
}
|
||||||
@@ -70,7 +64,7 @@ impl Sm4CbcCipher {
|
|||||||
let len = payload.len();
|
let len = payload.len();
|
||||||
if len < 16 || len > 1024 * 4 {
|
if len < 16 || len > 1024 * 4 {
|
||||||
log::error!("数据异常,长度{}小于16或大于4096", len);
|
log::error!("数据异常,长度{}小于16或大于4096", len);
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
let mut out = [0u8; 1024 * 4];
|
let mut out = [0u8; 1024 * 4];
|
||||||
let data = &payload[..len - 16];
|
let data = &payload[..len - 16];
|
||||||
@@ -79,32 +73,29 @@ impl Sm4CbcCipher {
|
|||||||
Ok(len) => {
|
Ok(len) => {
|
||||||
let src_net_packet = NetPacket::new(&out[..len])?;
|
let src_net_packet = NetPacket::new(&out[..len])?;
|
||||||
if src_net_packet.source() != net_packet.source() {
|
if src_net_packet.source() != net_packet.source() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.destination() != net_packet.destination() {
|
if src_net_packet.destination() != net_packet.destination() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.protocol() != net_packet.protocol() {
|
if src_net_packet.protocol() != net_packet.protocol() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.transport_protocol() != net_packet.transport_protocol() {
|
if src_net_packet.transport_protocol() != net_packet.transport_protocol() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.is_gateway() != net_packet.is_gateway() {
|
if src_net_packet.is_gateway() != net_packet.is_gateway() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
if src_net_packet.source_ttl() != net_packet.source_ttl() {
|
if src_net_packet.source_ttl() != net_packet.source_ttl() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
net_packet.set_data_len(len)?;
|
net_packet.set_data_len(len)?;
|
||||||
net_packet.set_payload(src_net_packet.payload())?;
|
net_packet.set_payload(src_net_packet.payload())?;
|
||||||
net_packet.set_encrypt_flag(false);
|
net_packet.set_encrypt_flag(false);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => Err(io::Error::new(
|
Err(e) => Err(anyhow!("sm4_cbc解密失败:{}", e)),
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("sm4_cbc解密失败:{}", e),
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// net_packet 必须预留足够长度
|
/// net_packet 必须预留足够长度
|
||||||
@@ -112,7 +103,7 @@ impl Sm4CbcCipher {
|
|||||||
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<()> {
|
) -> anyhow::Result<()> {
|
||||||
let mut out = [0u8; 1024 * 4];
|
let mut out = [0u8; 1024 * 4];
|
||||||
let mut iv = [0u8; 16];
|
let mut iv = [0u8; 16];
|
||||||
rand::thread_rng().fill_bytes(&mut iv);
|
rand::thread_rng().fill_bytes(&mut iv);
|
||||||
@@ -121,7 +112,7 @@ impl Sm4CbcCipher {
|
|||||||
"数据异常,长度{}大于1024 * 4 - 32",
|
"数据异常,长度{}大于1024 * 4 - 32",
|
||||||
net_packet.buffer().len()
|
net_packet.buffer().len()
|
||||||
);
|
);
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
|
return Err(anyhow!("data err"));
|
||||||
}
|
}
|
||||||
match self.cipher.encrypt(net_packet.buffer(), &iv, &mut out) {
|
match self.cipher.encrypt(net_packet.buffer(), &iv, &mut out) {
|
||||||
Ok(len) => {
|
Ok(len) => {
|
||||||
@@ -129,13 +120,7 @@ impl Sm4CbcCipher {
|
|||||||
net_packet.payload_mut()[..len].copy_from_slice(&out[..len]);
|
net_packet.payload_mut()[..len].copy_from_slice(&out[..len]);
|
||||||
net_packet.payload_mut()[len..].copy_from_slice(&iv);
|
net_packet.payload_mut()[len..].copy_from_slice(&iv);
|
||||||
if let Some(finger) = &self.finger {
|
if let Some(finger) = &self.finger {
|
||||||
let mut nonce_raw = [0; 12];
|
let nonce_raw = net_packet.head_tag();
|
||||||
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 finger = finger.calculate_finger(&nonce_raw, net_packet.payload());
|
||||||
let src_data_len = net_packet.data_len();
|
let src_data_len = net_packet.data_len();
|
||||||
//设置实际长度
|
//设置实际长度
|
||||||
@@ -146,10 +131,7 @@ impl Sm4CbcCipher {
|
|||||||
net_packet.set_encrypt_flag(true);
|
net_packet.set_encrypt_flag(true);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => Err(io::Error::new(
|
Err(e) => Err(anyhow!("sm4_cbc加密失败:{}", e)),
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("sm4_cbc加密失败:{}", e),
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
mod xor;
|
||||||
|
pub use xor::*;
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
use anyhow::anyhow;
|
||||||
|
|
||||||
|
use crate::protocol::NetPacket;
|
||||||
|
|
||||||
|
pub fn simple_hash(input: &str) -> [u8; 32] {
|
||||||
|
let mut result = [0u8; 32];
|
||||||
|
let bytes = input.as_bytes();
|
||||||
|
for (index, v) in result.iter_mut().enumerate() {
|
||||||
|
*v = bytes[index % bytes.len()];
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut state = 0u8;
|
||||||
|
|
||||||
|
for (i, &byte) in bytes.iter().enumerate() {
|
||||||
|
let combined = byte.wrapping_add(state).rotate_left((i % 8) as u32);
|
||||||
|
result[i % 32] ^= combined;
|
||||||
|
state = state.wrapping_add(byte).rotate_left(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..32 {
|
||||||
|
result[i] = result[i]
|
||||||
|
.rotate_left((result[(i + 1) % 32] % 8) as u32)
|
||||||
|
.wrapping_add(state);
|
||||||
|
state = state.wrapping_add(result[i]).rotate_left(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct XORCipher {
|
||||||
|
key: [u8; 32],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XORCipher {
|
||||||
|
pub fn new_256(key: [u8; 32]) -> Self {
|
||||||
|
Self { key }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XORCipher {
|
||||||
|
pub fn key(&self) -> &[u8] {
|
||||||
|
&self.key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XORCipher {
|
||||||
|
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
net_packet: &mut NetPacket<B>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
if !net_packet.is_encrypt() {
|
||||||
|
//未加密的数据直接丢弃
|
||||||
|
return Err(anyhow!("not encrypt"));
|
||||||
|
}
|
||||||
|
let key = &self.key;
|
||||||
|
for (i, byte) in net_packet.payload_mut().iter_mut().enumerate() {
|
||||||
|
*byte ^= key[i & 31];
|
||||||
|
}
|
||||||
|
net_packet.set_encrypt_flag(false);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
net_packet: &mut NetPacket<B>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
net_packet.set_encrypt_flag(true);
|
||||||
|
let key = &self.key;
|
||||||
|
for (i, byte) in net_packet.payload_mut().iter_mut().enumerate() {
|
||||||
|
*byte ^= key[i & 31];
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_xor() {
|
||||||
|
let d = XORCipher::new_256(simple_hash("password"));
|
||||||
|
let mut p = NetPacket::new_encrypt([0; 1000]).unwrap();
|
||||||
|
let src = p.buffer().to_vec();
|
||||||
|
d.encrypt_ipv4(&mut p).unwrap();
|
||||||
|
d.decrypt_ipv4(&mut p).unwrap();
|
||||||
|
assert_eq!(p.buffer(), &src)
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
use anyhow::anyhow;
|
||||||
|
|
||||||
|
use crate::protocol::NetPacket;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Lz4Compressor;
|
||||||
|
|
||||||
|
impl Lz4Compressor {
|
||||||
|
pub fn compress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
in_net_packet: &NetPacket<I>,
|
||||||
|
out: &mut NetPacket<O>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
out.set_data_len_max();
|
||||||
|
let len = match lz4_flex::compress_into(in_net_packet.payload(), out.payload_mut()) {
|
||||||
|
Ok(len) => len,
|
||||||
|
Err(e) => Err(anyhow!("Lz4 compress {}", e))?,
|
||||||
|
};
|
||||||
|
out.set_payload_len(len)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn decompress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
in_net_packet: &NetPacket<I>,
|
||||||
|
out: &mut NetPacket<O>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
out.set_data_len_max();
|
||||||
|
let len = match lz4_flex::decompress_into(in_net_packet.payload(), out.payload_mut()) {
|
||||||
|
Ok(len) => len,
|
||||||
|
Err(e) => Err(anyhow!("Lz4 decompress {}", e))?,
|
||||||
|
};
|
||||||
|
out.set_payload_len(len)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
|
|
||||||
|
#[cfg(feature = "lz4_compress")]
|
||||||
|
use crate::compression::lz4_compress::Lz4Compressor;
|
||||||
|
#[cfg(feature = "zstd_compress")]
|
||||||
|
use crate::compression::zstd_compress::ZstdCompressor;
|
||||||
|
use crate::protocol::extension::CompressionAlgorithm;
|
||||||
|
#[cfg(feature = "zstd_compress")]
|
||||||
|
use zstd::zstd_safe::CompressionLevel;
|
||||||
|
|
||||||
|
use crate::protocol::NetPacket;
|
||||||
|
|
||||||
|
#[cfg(feature = "lz4_compress")]
|
||||||
|
mod lz4_compress;
|
||||||
|
#[cfg(feature = "zstd_compress")]
|
||||||
|
mod zstd_compress;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum Compressor {
|
||||||
|
#[cfg(feature = "lz4_compress")]
|
||||||
|
Lz4,
|
||||||
|
#[cfg(feature = "zstd_compress")]
|
||||||
|
Zstd(CompressionLevel),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Compressor {
|
||||||
|
type Err = String;
|
||||||
|
#[cfg(not(any(feature = "lz4_compress", feature = "zstd_compress")))]
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Err(format!("not match '{}', Compression not supported", s))
|
||||||
|
}
|
||||||
|
#[cfg(any(feature = "lz4_compress", feature = "zstd_compress"))]
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let str = s.trim().to_lowercase();
|
||||||
|
match str.as_str() {
|
||||||
|
#[cfg(feature = "lz4_compress")]
|
||||||
|
"lz4" => Ok(Compressor::Lz4),
|
||||||
|
#[cfg(feature = "zstd_compress")]
|
||||||
|
"zstd" => Ok(Compressor::Zstd(9)),
|
||||||
|
"none" => Ok(Compressor::None),
|
||||||
|
_ => {
|
||||||
|
#[cfg(feature = "zstd_compress")]
|
||||||
|
{
|
||||||
|
let string_array: Vec<String> = str.split(',').map(|s| s.to_string()).collect();
|
||||||
|
if string_array.len() != 2 || string_array[0] != "zstd" {
|
||||||
|
return Err(format!("not match '{}', exp: zstd,10", s));
|
||||||
|
}
|
||||||
|
return match CompressionLevel::from_str(&string_array[1]) {
|
||||||
|
Ok(level) => Ok(Compressor::Zstd(level)),
|
||||||
|
Err(_) => Err(format!("not match '{}', exp: zstd,10", s)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "zstd_compress"))]
|
||||||
|
#[cfg(feature = "lz4_compress")]
|
||||||
|
return Err(format!("not match '{}', exp: lz4", s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(feature = "lz4_compress", feature = "zstd_compress")))]
|
||||||
|
impl Compressor {
|
||||||
|
pub fn compress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
_in_net_packet: &NetPacket<I>,
|
||||||
|
_out: &mut NetPacket<O>,
|
||||||
|
) -> anyhow::Result<bool> {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
pub fn decompress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
_algorithm: CompressionAlgorithm,
|
||||||
|
_in_net_packet: &NetPacket<I>,
|
||||||
|
_out: &mut NetPacket<O>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
Err(anyhow!("Unsupported decompress"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "lz4_compress", feature = "zstd_compress"))]
|
||||||
|
impl Compressor {
|
||||||
|
pub fn compress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
&self,
|
||||||
|
in_net_packet: &NetPacket<I>,
|
||||||
|
out: &mut NetPacket<O>,
|
||||||
|
) -> anyhow::Result<bool> {
|
||||||
|
match self {
|
||||||
|
#[cfg(feature = "lz4_compress")]
|
||||||
|
Compressor::Lz4 => {
|
||||||
|
if in_net_packet.data_len() < 128 {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
Lz4Compressor::compress(in_net_packet, out)?;
|
||||||
|
let mut compression_extension_tail = out.append_compression_extension_tail()?;
|
||||||
|
compression_extension_tail.set_algorithm(CompressionAlgorithm::Lz4);
|
||||||
|
//压缩没效果,则放弃压缩
|
||||||
|
if out.data_len() >= in_net_packet.data_len() - 16 {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
#[cfg(feature = "zstd_compress")]
|
||||||
|
Compressor::Zstd(level) => {
|
||||||
|
if in_net_packet.data_len() < 128 {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
ZstdCompressor::compress(*level, in_net_packet, out)?;
|
||||||
|
let mut compression_extension_tail = out.append_compression_extension_tail()?;
|
||||||
|
compression_extension_tail.set_algorithm(CompressionAlgorithm::Zstd);
|
||||||
|
//压缩没效果,则放弃压缩
|
||||||
|
if out.data_len() >= in_net_packet.data_len() - 16 {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
Compressor::None => {}
|
||||||
|
}
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
pub fn decompress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
algorithm: CompressionAlgorithm,
|
||||||
|
in_net_packet: &NetPacket<I>,
|
||||||
|
out: &mut NetPacket<O>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
match algorithm {
|
||||||
|
#[cfg(feature = "lz4_compress")]
|
||||||
|
CompressionAlgorithm::Lz4 => Lz4Compressor::decompress(in_net_packet, out),
|
||||||
|
#[cfg(feature = "zstd_compress")]
|
||||||
|
CompressionAlgorithm::Zstd => ZstdCompressor::decompress(in_net_packet, out),
|
||||||
|
_ => Err(anyhow!("Unknown decompress {:?}", algorithm)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "zstd_compress")]
|
||||||
|
fn test_lz4() {
|
||||||
|
use crate::protocol::extension::{CompressionAlgorithm, ExtensionTailPacket};
|
||||||
|
let lz4 = Compressor::Lz4;
|
||||||
|
let in_packet = NetPacket::new([
|
||||||
|
65, 108, 105, 99, 101, 32, 119, 97, 116, 32, 98, 101, 103, 105, 110, 110, 105, 110, 103,
|
||||||
|
32, 116, 111, 32, 103, 101, 116, 32, 118, 101, 114, 121, 32, 116, 105, 114, 101, 100, 32,
|
||||||
|
111, 102, 32, 115, 105, 116, 116, 105, 110, 103, 32, 98, 121, 32, 104, 101, 114, 32, 115,
|
||||||
|
105, 115, 116, 101, 114, 32, 111, 110, 32, 116, 104, 101, 32, 98, 97, 110, 107, 44, 32, 97,
|
||||||
|
110, 100, 32, 111, 102, 32, 104, 97, 118, 105, 110, 103, 32, 110, 111, 116, 104, 105, 110,
|
||||||
|
103, 32, 116, 111, 32, 100, 111, 58, 32, 111, 110, 99, 101, 32, 111, 114, 32, 116, 119,
|
||||||
|
105, 99, 101, 32, 115, 104, 101, 32, 104, 97, 100, 32, 112, 101, 101, 112, 101, 100, 32,
|
||||||
|
105, 110, 116, 111, 32, 116, 104, 101, 32, 98, 111, 111, 107, 32, 104, 101, 114, 32, 115,
|
||||||
|
105, 115, 116, 101, 114, 32, 119, 97, 115, 32, 114, 101, 97, 100, 105, 110, 103, 44, 32,
|
||||||
|
98, 117, 116, 32, 105, 116, 32, 104, 97, 100, 32, 110, 111, 32, 112, 105, 99, 116, 117,
|
||||||
|
114, 101, 115, 32, 111, 114, 32, 99, 111, 110, 118, 101, 114, 115, 97, 116, 105,
|
||||||
|
])
|
||||||
|
.unwrap();
|
||||||
|
let mut out_packet = NetPacket::new([0; 1000]).unwrap();
|
||||||
|
let mut src_out_packet = NetPacket::new([0; 1000]).unwrap();
|
||||||
|
lz4.compress(&in_packet, &mut out_packet).unwrap();
|
||||||
|
let tail = out_packet.split_tail_packet().unwrap();
|
||||||
|
match tail {
|
||||||
|
ExtensionTailPacket::Compression(c) => match c.algorithm() {
|
||||||
|
CompressionAlgorithm::Lz4 => {
|
||||||
|
Compressor::decompress(CompressionAlgorithm::Lz4, &out_packet, &mut src_out_packet)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert!(!out_packet.is_extension());
|
||||||
|
assert_eq!(in_packet.payload(), src_out_packet.payload())
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "zstd_compress")]
|
||||||
|
fn test_zstd() {
|
||||||
|
use crate::protocol::extension::{CompressionAlgorithm, ExtensionTailPacket};
|
||||||
|
let zstd = Compressor::Zstd(22);
|
||||||
|
let in_packet = NetPacket::new([
|
||||||
|
65, 108, 105, 99, 101, 32, 119, 97, 115, 32, 98, 101, 103, 105, 110, 110, 105, 110, 103,
|
||||||
|
32, 116, 111, 32, 103, 101, 116, 32, 118, 101, 114, 121, 32, 116, 105, 114, 101, 100, 32,
|
||||||
|
111, 102, 32, 115, 105, 116, 116, 105, 110, 103, 32, 98, 121, 32, 104, 101, 114, 32, 115,
|
||||||
|
105, 115, 116, 101, 114, 32, 111, 110, 32, 116, 104, 101, 32, 98, 97, 110, 107, 44, 32, 97,
|
||||||
|
110, 100, 32, 111, 102, 32, 104, 97, 118, 105, 110, 103, 32, 110, 111, 116, 104, 105, 110,
|
||||||
|
103, 32, 116, 111, 32, 100, 111, 58, 32, 111, 110, 99, 101, 32, 111, 114, 32, 116, 119,
|
||||||
|
105, 99, 101, 32, 115, 104, 101, 32, 104, 97, 100, 32, 112, 101, 101, 112, 101, 100, 32,
|
||||||
|
105, 110, 116, 111, 32, 116, 104, 101, 32, 98, 111, 111, 107, 32, 104, 101, 114, 32, 115,
|
||||||
|
105, 115, 116, 101, 114, 32, 119, 97, 115, 32, 114, 101, 97, 100, 105, 110, 103, 44, 32,
|
||||||
|
98, 117, 116, 32, 105, 116, 32, 104, 97, 100, 32, 110, 111, 32, 112, 105, 99, 116, 117,
|
||||||
|
114, 101, 115, 32, 111, 114, 32, 99, 111, 110, 118, 101, 114, 115, 97, 116, 105,
|
||||||
|
])
|
||||||
|
.unwrap();
|
||||||
|
let mut out_packet = NetPacket::new([0; 1000]).unwrap();
|
||||||
|
let mut src_out_packet = NetPacket::new([0; 1000]).unwrap();
|
||||||
|
zstd.compress(&in_packet, &mut out_packet).unwrap();
|
||||||
|
let tail = out_packet.split_tail_packet().unwrap();
|
||||||
|
match tail {
|
||||||
|
ExtensionTailPacket::Compression(c) => match c.algorithm() {
|
||||||
|
CompressionAlgorithm::Zstd => {
|
||||||
|
Compressor::decompress(
|
||||||
|
CompressionAlgorithm::Zstd,
|
||||||
|
&out_packet,
|
||||||
|
&mut src_out_packet,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert!(!out_packet.is_extension());
|
||||||
|
assert_eq!(in_packet.payload(), src_out_packet.payload())
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
use crate::protocol::NetPacket;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use zstd::zstd_safe::CompressionLevel;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ZstdCompressor;
|
||||||
|
|
||||||
|
impl ZstdCompressor {
|
||||||
|
pub fn compress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
compression_level: CompressionLevel,
|
||||||
|
in_net_packet: &NetPacket<I>,
|
||||||
|
out: &mut NetPacket<O>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
out.set_data_len_max();
|
||||||
|
let len = match zstd::zstd_safe::compress(
|
||||||
|
out.payload_mut(),
|
||||||
|
in_net_packet.payload(),
|
||||||
|
compression_level,
|
||||||
|
) {
|
||||||
|
Ok(len) => len,
|
||||||
|
Err(e) => Err(anyhow!("zstd compress {}", e))?,
|
||||||
|
};
|
||||||
|
out.set_payload_len(len)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn decompress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
in_net_packet: &NetPacket<I>,
|
||||||
|
out: &mut NetPacket<O>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
out.set_data_len_max();
|
||||||
|
let len = match zstd::zstd_safe::decompress(out.payload_mut(), in_net_packet.payload()) {
|
||||||
|
Ok(len) => len,
|
||||||
|
Err(e) => Err(anyhow!("zstd decompress {}", e))?,
|
||||||
|
};
|
||||||
|
out.set_payload_len(len)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
+32
-19
@@ -1,3 +1,4 @@
|
|||||||
|
use anyhow::Context;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -6,7 +7,6 @@ use std::time::Duration;
|
|||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use rsa::signature::digest::Digest;
|
|
||||||
#[cfg(not(target_os = "android"))]
|
#[cfg(not(target_os = "android"))]
|
||||||
use tun::device::IFace;
|
use tun::device::IFace;
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ pub struct Vnt {
|
|||||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
nat_test: NatTest,
|
nat_test: NatTest,
|
||||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||||
context: ChannelContext,
|
context: Arc<Mutex<Option<ChannelContext>>>,
|
||||||
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
|
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
|
||||||
down_count_watcher: WatchU64Adder,
|
down_count_watcher: WatchU64Adder,
|
||||||
up_count_watcher: WatchSingleU64Adder,
|
up_count_watcher: WatchSingleU64Adder,
|
||||||
@@ -48,7 +48,7 @@ pub struct Vnt {
|
|||||||
|
|
||||||
impl Vnt {
|
impl Vnt {
|
||||||
pub fn new<Call: VntCallback>(config: Config, callback: Call) -> anyhow::Result<Self> {
|
pub fn new<Call: VntCallback>(config: Config, callback: Call) -> anyhow::Result<Self> {
|
||||||
log::info!("config:{:?}", config);
|
log::info!("config.toml:{:?}", config);
|
||||||
//服务端非对称加密
|
//服务端非对称加密
|
||||||
#[cfg(feature = "server_encrypt")]
|
#[cfg(feature = "server_encrypt")]
|
||||||
let rsa_cipher: Arc<Mutex<Option<RsaCipher>>> = Arc::new(Mutex::new(None));
|
let rsa_cipher: Arc<Mutex<Option<RsaCipher>>> = Arc::new(Mutex::new(None));
|
||||||
@@ -67,7 +67,7 @@ impl Vnt {
|
|||||||
};
|
};
|
||||||
//客户端对称加密
|
//客户端对称加密
|
||||||
let client_cipher =
|
let client_cipher =
|
||||||
Cipher::new_password(config.cipher_model, config.password.clone(), finger);
|
Cipher::new_password(config.cipher_model, config.password.clone(), finger)?;
|
||||||
//当前设备信息
|
//当前设备信息
|
||||||
let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new0(
|
let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new0(
|
||||||
config.server_address,
|
config.server_address,
|
||||||
@@ -80,14 +80,7 @@ impl Vnt {
|
|||||||
config.name.clone(),
|
config.name.clone(),
|
||||||
config.token.clone(),
|
config.token.clone(),
|
||||||
config.ip,
|
config.ip,
|
||||||
config.password.as_ref().map(|v| {
|
config.password_hash(),
|
||||||
let mut hasher = sha2::Sha256::new();
|
|
||||||
hasher.update(config.cipher_model.to_string().as_bytes());
|
|
||||||
hasher.update(v.as_bytes());
|
|
||||||
hasher.update(config.token.as_bytes());
|
|
||||||
let key: [u8; 32] = hasher.finalize().into();
|
|
||||||
key[16..].try_into().unwrap()
|
|
||||||
}),
|
|
||||||
config.server_encrypt,
|
config.server_encrypt,
|
||||||
config.device_id.clone(),
|
config.device_id.clone(),
|
||||||
config.server_address_str.clone(),
|
config.server_address_str.clone(),
|
||||||
@@ -140,8 +133,14 @@ impl Vnt {
|
|||||||
// pc上先创建虚拟网卡
|
// pc上先创建虚拟网卡
|
||||||
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
let device = {
|
let device = {
|
||||||
let device = tun_tap_device::create_device(&config)?;
|
log::info!("开始创建tun");
|
||||||
let tun_info = DeviceInfo::new(device.name()?, device.version()?);
|
let device = tun_tap_device::create_device(&config).context("create tun failed")?;
|
||||||
|
log::info!("创建tun成功");
|
||||||
|
let tun_info = DeviceInfo::new(
|
||||||
|
device.name().unwrap_or("unknown".into()),
|
||||||
|
device.version().unwrap_or("unknown".into()),
|
||||||
|
);
|
||||||
|
log::info!("tun信息{:?}", tun_info);
|
||||||
callback.create_tun(tun_info);
|
callback.create_tun(tun_info);
|
||||||
device
|
device
|
||||||
};
|
};
|
||||||
@@ -167,7 +166,10 @@ impl Vnt {
|
|||||||
let down_counter =
|
let down_counter =
|
||||||
U64Adder::with_capacity(config.ports.as_ref().map(|v| v.len()).unwrap_or_default() + 8);
|
U64Adder::with_capacity(config.ports.as_ref().map(|v| v.len()).unwrap_or_default() + 8);
|
||||||
let down_count_watcher = down_counter.watch();
|
let down_count_watcher = down_counter.watch();
|
||||||
let handshake = Handshake::new(rsa_cipher.clone());
|
let handshake = Handshake::new(
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
|
rsa_cipher.clone(),
|
||||||
|
);
|
||||||
let up_counter = SingleU64Adder::new();
|
let up_counter = SingleU64Adder::new();
|
||||||
let up_count_watcher = up_counter.watch();
|
let up_count_watcher = up_counter.watch();
|
||||||
let tun_helper = TunDeviceHelper::new(
|
let tun_helper = TunDeviceHelper::new(
|
||||||
@@ -182,6 +184,7 @@ impl Vnt {
|
|||||||
config.parallel,
|
config.parallel,
|
||||||
up_counter,
|
up_counter,
|
||||||
device_list.clone(),
|
device_list.clone(),
|
||||||
|
config.compressor,
|
||||||
);
|
);
|
||||||
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
let device_adapter = DeviceAdapter::new(device.clone());
|
let device_adapter = DeviceAdapter::new(device.clone());
|
||||||
@@ -278,7 +281,7 @@ impl Vnt {
|
|||||||
current_device,
|
current_device,
|
||||||
nat_test,
|
nat_test,
|
||||||
device_list,
|
device_list,
|
||||||
context,
|
context: Arc::new(Mutex::new(Some(context))),
|
||||||
peer_nat_info_map,
|
peer_nat_info_map,
|
||||||
down_count_watcher,
|
down_count_watcher,
|
||||||
up_count_watcher,
|
up_count_watcher,
|
||||||
@@ -395,16 +398,24 @@ impl Vnt {
|
|||||||
device_list
|
device_list
|
||||||
}
|
}
|
||||||
pub fn route(&self, ip: &Ipv4Addr) -> Option<Route> {
|
pub fn route(&self, ip: &Ipv4Addr) -> Option<Route> {
|
||||||
self.context.route_table.route_one(ip)
|
self.context.lock().as_ref()?.route_table.route_one(ip)
|
||||||
}
|
}
|
||||||
pub fn is_gateway(&self, ip: &Ipv4Addr) -> bool {
|
pub fn is_gateway(&self, ip: &Ipv4Addr) -> bool {
|
||||||
self.current_device.load().is_gateway(ip)
|
self.current_device.load().is_gateway(ip)
|
||||||
}
|
}
|
||||||
pub fn route_key(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
|
pub fn route_key(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
|
||||||
self.context.route_table.route_to_id(route_key)
|
self.context
|
||||||
|
.lock()
|
||||||
|
.as_ref()?
|
||||||
|
.route_table
|
||||||
|
.route_to_id(route_key)
|
||||||
}
|
}
|
||||||
pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec<Route>)> {
|
pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec<Route>)> {
|
||||||
self.context.route_table.route_table()
|
if let Some(context) = self.context.lock().as_ref() {
|
||||||
|
context.route_table.route_table()
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn up_stream(&self) -> u64 {
|
pub fn up_stream(&self) -> u64 {
|
||||||
self.up_count_watcher.get()
|
self.up_count_watcher.get()
|
||||||
@@ -413,6 +424,8 @@ impl Vnt {
|
|||||||
self.down_count_watcher.get()
|
self.down_count_watcher.get()
|
||||||
}
|
}
|
||||||
pub fn stop(&self) {
|
pub fn stop(&self) {
|
||||||
|
//退出协助回收资源
|
||||||
|
let _ = self.context.lock().take();
|
||||||
self.stop_manager.stop()
|
self.stop_manager.stop()
|
||||||
}
|
}
|
||||||
pub fn wait(&self) {
|
pub fn wait(&self) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ pub use conn::Vnt;
|
|||||||
use crate::channel::punch::PunchModel;
|
use crate::channel::punch::PunchModel;
|
||||||
use crate::channel::UseChannelType;
|
use crate::channel::UseChannelType;
|
||||||
use crate::cipher::CipherModel;
|
use crate::cipher::CipherModel;
|
||||||
|
use crate::compression::Compressor;
|
||||||
use crate::util::{address_choose, dns_query_all};
|
use crate::util::{address_choose, dns_query_all};
|
||||||
|
|
||||||
mod conn;
|
mod conn;
|
||||||
@@ -46,6 +47,7 @@ pub struct Config {
|
|||||||
// 端口映射
|
// 端口映射
|
||||||
#[cfg(feature = "port_mapping")]
|
#[cfg(feature = "port_mapping")]
|
||||||
pub port_mapping_list: Vec<(bool, SocketAddr, String)>,
|
pub port_mapping_list: Vec<(bool, SocketAddr, String)>,
|
||||||
|
pub compressor: Compressor,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
@@ -77,6 +79,7 @@ impl Config {
|
|||||||
packet_delay: u32,
|
packet_delay: u32,
|
||||||
// 例如 [udp:127.0.0.1:80->10.26.0.10:8080,tcp:127.0.0.1:80->10.26.0.10:8080]
|
// 例如 [udp:127.0.0.1:80->10.26.0.10:8080,tcp:127.0.0.1:80->10.26.0.10:8080]
|
||||||
#[cfg(feature = "port_mapping")] port_mapping_list: Vec<String>,
|
#[cfg(feature = "port_mapping")] port_mapping_list: Vec<String>,
|
||||||
|
compressor: Compressor,
|
||||||
) -> anyhow::Result<Self> {
|
) -> anyhow::Result<Self> {
|
||||||
for x in stun_server.iter_mut() {
|
for x in stun_server.iter_mut() {
|
||||||
if !x.contains(":") {
|
if !x.contains(":") {
|
||||||
@@ -140,6 +143,33 @@ impl Config {
|
|||||||
packet_delay,
|
packet_delay,
|
||||||
#[cfg(feature = "port_mapping")]
|
#[cfg(feature = "port_mapping")]
|
||||||
port_mapping_list,
|
port_mapping_list,
|
||||||
|
compressor,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn password_hash(&self) -> Option<[u8; 16]> {
|
||||||
|
if let Some(p) = self.password.as_ref() {
|
||||||
|
match self.cipher_model {
|
||||||
|
CipherModel::Xor => {
|
||||||
|
let key = crate::cipher::simple_hash(&format!("Xor{}{}", p, self.token));
|
||||||
|
Some(key[16..].try_into().unwrap())
|
||||||
|
}
|
||||||
|
CipherModel::None => None,
|
||||||
|
#[cfg(cipher)]
|
||||||
|
_ => {
|
||||||
|
use sha2::Digest;
|
||||||
|
let mut hasher = sha2::Sha256::new();
|
||||||
|
hasher.update(self.cipher_model.to_string().as_bytes());
|
||||||
|
hasher.update(p.as_bytes());
|
||||||
|
hasher.update(self.token.as_bytes());
|
||||||
|
let key: [u8; 32] = hasher.finalize().into();
|
||||||
|
Some(key[16..].try_into().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
use crate::compression::Compressor;
|
||||||
|
use crate::protocol::extension::ExtensionTailPacket;
|
||||||
|
use crate::protocol::NetPacket;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
|
||||||
|
pub fn handle_extension_tail<I: AsRef<[u8]> + AsMut<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
|
||||||
|
in_net_packet: &mut NetPacket<I>,
|
||||||
|
out: &mut NetPacket<O>,
|
||||||
|
) -> anyhow::Result<bool> {
|
||||||
|
if in_net_packet.is_extension() {
|
||||||
|
let tail_packet = in_net_packet.split_tail_packet()?;
|
||||||
|
match tail_packet {
|
||||||
|
ExtensionTailPacket::Compression(extension) => {
|
||||||
|
let compression_algorithm = extension.algorithm();
|
||||||
|
Compressor::decompress(compression_algorithm, &in_net_packet, out)?;
|
||||||
|
out.head_mut().copy_from_slice(in_net_packet.head());
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
ExtensionTailPacket::Unknown => Err(anyhow!("Unknown decompress")),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ use std::sync::Arc;
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use protobuf::Message;
|
use protobuf::Message;
|
||||||
|
|
||||||
@@ -28,12 +29,16 @@ pub enum HandshakeEnum {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Handshake {
|
pub struct Handshake {
|
||||||
time: Arc<AtomicCell<Instant>>,
|
time: Arc<AtomicCell<Instant>>,
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
rsa_cipher: Arc<Mutex<Option<RsaCipher>>>,
|
rsa_cipher: Arc<Mutex<Option<RsaCipher>>>,
|
||||||
}
|
}
|
||||||
impl Handshake {
|
impl Handshake {
|
||||||
pub fn new(rsa_cipher: Arc<Mutex<Option<RsaCipher>>>) -> Self {
|
pub fn new(
|
||||||
|
#[cfg(feature = "server_encrypt")] rsa_cipher: Arc<Mutex<Option<RsaCipher>>>,
|
||||||
|
) -> Self {
|
||||||
Handshake {
|
Handshake {
|
||||||
time: Arc::new(AtomicCell::new(Instant::now() - Duration::from_secs(60))),
|
time: Arc::new(AtomicCell::new(Instant::now() - Duration::from_secs(60))),
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
rsa_cipher,
|
rsa_cipher,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,6 +59,7 @@ impl Handshake {
|
|||||||
let mut request = HandshakeRequest::new();
|
let mut request = HandshakeRequest::new();
|
||||||
request.secret = secret;
|
request.secret = secret;
|
||||||
request.version = crate::VNT_VERSION.to_string();
|
request.version = crate::VNT_VERSION.to_string();
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
if let Some(finger) = self.rsa_cipher.lock().as_ref().map(|v| v.finger().clone()) {
|
if let Some(finger) = self.rsa_cipher.lock().as_ref().map(|v| v.finger().clone()) {
|
||||||
request.key_finger = finger;
|
request.key_finger = finger;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use std::io;
|
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -167,7 +166,7 @@ fn client_relay0(
|
|||||||
current_device: &CurrentDeviceInfo,
|
current_device: &CurrentDeviceInfo,
|
||||||
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
|
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
|
||||||
client_cipher: &Cipher,
|
client_cipher: &Cipher,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
// 离线了不再探测
|
// 离线了不再探测
|
||||||
if current_device.status.offline() {
|
if current_device.status.offline() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -211,7 +210,7 @@ fn client_relay0(
|
|||||||
fn heartbeat_packet(
|
fn heartbeat_packet(
|
||||||
src: Ipv4Addr,
|
src: Ipv4Addr,
|
||||||
dest: Ipv4Addr,
|
dest: Ipv4Addr,
|
||||||
) -> io::Result<NetPacket<[u8; 12 + 4 + ENCRYPTION_RESERVED]>> {
|
) -> anyhow::Result<NetPacket<[u8; 12 + 4 + ENCRYPTION_RESERVED]>> {
|
||||||
let mut net_packet = NetPacket::new_encrypt([0u8; 12 + 4 + ENCRYPTION_RESERVED])?;
|
let mut net_packet = NetPacket::new_encrypt([0u8; 12 + 4 + ENCRYPTION_RESERVED])?;
|
||||||
net_packet.set_default_version();
|
net_packet.set_default_version();
|
||||||
net_packet.set_protocol(Protocol::Control);
|
net_packet.set_protocol(Protocol::Control);
|
||||||
@@ -228,7 +227,7 @@ fn heartbeat_packet_client(
|
|||||||
client_cipher: &Cipher,
|
client_cipher: &Cipher,
|
||||||
src: Ipv4Addr,
|
src: Ipv4Addr,
|
||||||
dest: Ipv4Addr,
|
dest: Ipv4Addr,
|
||||||
) -> io::Result<NetPacket<[u8; 12 + 4 + ENCRYPTION_RESERVED]>> {
|
) -> anyhow::Result<NetPacket<[u8; 12 + 4 + ENCRYPTION_RESERVED]>> {
|
||||||
let mut net_packet = heartbeat_packet(src, dest)?;
|
let mut net_packet = heartbeat_packet(src, dest)?;
|
||||||
client_cipher.encrypt_ipv4(&mut net_packet)?;
|
client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||||
Ok(net_packet)
|
Ok(net_packet)
|
||||||
@@ -239,7 +238,7 @@ fn heartbeat_packet_server(
|
|||||||
server_cipher: &Cipher,
|
server_cipher: &Cipher,
|
||||||
src: Ipv4Addr,
|
src: Ipv4Addr,
|
||||||
dest: Ipv4Addr,
|
dest: Ipv4Addr,
|
||||||
) -> io::Result<NetPacket<[u8; 12 + 4 + ENCRYPTION_RESERVED]>> {
|
) -> anyhow::Result<NetPacket<[u8; 12 + 4 + ENCRYPTION_RESERVED]>> {
|
||||||
let mut net_packet = heartbeat_packet(src, dest)?;
|
let mut net_packet = heartbeat_packet(src, dest)?;
|
||||||
let mut ping = PingPacket::new(net_packet.payload_mut())?;
|
let mut ping = PingPacket::new(net_packet.payload_mut())?;
|
||||||
ping.set_epoch(device_list.lock().0);
|
ping.set_epoch(device_list.lock().0);
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ use std::collections::HashMap;
|
|||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{io, thread};
|
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use protobuf::Message;
|
use protobuf::Message;
|
||||||
@@ -222,7 +223,7 @@ fn punch0(
|
|||||||
punch_record: &Mutex<HashMap<Ipv4Addr, usize>>,
|
punch_record: &Mutex<HashMap<Ipv4Addr, usize>>,
|
||||||
last_punch_record: &mut HashMap<Ipv4Addr, usize>,
|
last_punch_record: &mut HashMap<Ipv4Addr, usize>,
|
||||||
total_count: usize,
|
total_count: usize,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let nat_info = nat_test.nat_info();
|
let nat_info = nat_test.nat_info();
|
||||||
if total_count < 10
|
if total_count < 10
|
||||||
&& (nat_info.public_ips.is_empty()
|
&& (nat_info.public_ips.is_empty()
|
||||||
@@ -297,7 +298,7 @@ fn punch_packet(
|
|||||||
virtual_ip: Ipv4Addr,
|
virtual_ip: Ipv4Addr,
|
||||||
nat_info: &NatInfo,
|
nat_info: &NatInfo,
|
||||||
dest: Ipv4Addr,
|
dest: Ipv4Addr,
|
||||||
) -> io::Result<NetPacket<Vec<u8>>> {
|
) -> anyhow::Result<NetPacket<Vec<u8>>> {
|
||||||
let mut punch_reply = PunchInfo::new();
|
let mut punch_reply = PunchInfo::new();
|
||||||
punch_reply.reply = false;
|
punch_reply.reply = false;
|
||||||
punch_reply.public_ip_list = nat_info
|
punch_reply.public_ip_list = nat_info
|
||||||
@@ -320,7 +321,7 @@ fn punch_packet(
|
|||||||
log::info!("请求打洞={:?}", punch_reply);
|
log::info!("请求打洞={:?}", punch_reply);
|
||||||
let bytes = punch_reply
|
let bytes = punch_reply
|
||||||
.write_to_bytes()
|
.write_to_bytes()
|
||||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("punch_packet {:?}", e)))?;
|
.map_err(|e| anyhow!("punch_packet {:?}", e))?;
|
||||||
let mut net_packet = NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?;
|
let mut net_packet = NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?;
|
||||||
net_packet.set_default_version();
|
net_packet.set_default_version();
|
||||||
net_packet.set_protocol(Protocol::OtherTurn);
|
net_packet.set_protocol(Protocol::OtherTurn);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use crossbeam_utils::atomic::AtomicCell;
|
|||||||
use std::net::{Ipv4Addr, SocketAddr};
|
use std::net::{Ipv4Addr, SocketAddr};
|
||||||
|
|
||||||
pub mod callback;
|
pub mod callback;
|
||||||
|
mod extension;
|
||||||
pub mod handshaker;
|
pub mod handshaker;
|
||||||
pub mod maintain;
|
pub mod maintain;
|
||||||
pub mod recv_data;
|
pub mod recv_data;
|
||||||
|
|||||||
@@ -1,19 +1,23 @@
|
|||||||
use parking_lot::RwLock;
|
use anyhow::anyhow;
|
||||||
use protobuf::Message;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io;
|
|
||||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
use protobuf::Message;
|
||||||
|
|
||||||
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;
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
|
use tun::device::IFace;
|
||||||
|
|
||||||
use crate::channel::context::ChannelContext;
|
use crate::channel::context::ChannelContext;
|
||||||
use crate::channel::punch::NatInfo;
|
use crate::channel::punch::NatInfo;
|
||||||
use crate::channel::{Route, RouteKey};
|
use crate::channel::{Route, RouteKey};
|
||||||
use crate::cipher::Cipher;
|
use crate::cipher::Cipher;
|
||||||
use crate::external_route::AllowExternalRoute;
|
use crate::external_route::AllowExternalRoute;
|
||||||
|
use crate::handle::extension::handle_extension_tail;
|
||||||
use crate::handle::maintain::PunchSender;
|
use crate::handle::maintain::PunchSender;
|
||||||
use crate::handle::recv_data::PacketHandler;
|
use crate::handle::recv_data::PacketHandler;
|
||||||
use crate::handle::CurrentDeviceInfo;
|
use crate::handle::CurrentDeviceInfo;
|
||||||
@@ -27,8 +31,6 @@ use crate::protocol::{
|
|||||||
control_packet, ip_turn_packet, other_turn_packet, NetPacket, Protocol, MAX_TTL,
|
control_packet, ip_turn_packet, other_turn_packet, NetPacket, Protocol, MAX_TTL,
|
||||||
};
|
};
|
||||||
use crate::tun_tap_device::tun_create_helper::DeviceAdapter;
|
use crate::tun_tap_device::tun_create_helper::DeviceAdapter;
|
||||||
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
|
||||||
use tun::device::IFace;
|
|
||||||
|
|
||||||
/// 处理来源于客户端的包
|
/// 处理来源于客户端的包
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -70,14 +72,26 @@ impl PacketHandler for ClientPacketHandler {
|
|||||||
fn handle(
|
fn handle(
|
||||||
&self,
|
&self,
|
||||||
mut net_packet: NetPacket<&mut [u8]>,
|
mut net_packet: NetPacket<&mut [u8]>,
|
||||||
|
mut extend: NetPacket<&mut [u8]>,
|
||||||
route_key: RouteKey,
|
route_key: RouteKey,
|
||||||
context: &ChannelContext,
|
context: &ChannelContext,
|
||||||
current_device: &CurrentDeviceInfo,
|
current_device: &CurrentDeviceInfo,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
self.client_cipher.decrypt_ipv4(&mut net_packet)?;
|
self.client_cipher.decrypt_ipv4(&mut net_packet)?;
|
||||||
context
|
context
|
||||||
.route_table
|
.route_table
|
||||||
.update_read_time(&net_packet.source(), &route_key);
|
.update_read_time(&net_packet.source(), &route_key);
|
||||||
|
//处理扩展
|
||||||
|
let net_packet = if net_packet.is_extension() {
|
||||||
|
//这样重用数组,减少一次数据拷贝
|
||||||
|
if handle_extension_tail(&mut net_packet, &mut extend)? {
|
||||||
|
extend
|
||||||
|
} else {
|
||||||
|
net_packet
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
net_packet
|
||||||
|
};
|
||||||
match net_packet.protocol() {
|
match net_packet.protocol() {
|
||||||
Protocol::Service => {}
|
Protocol::Service => {}
|
||||||
Protocol::Error => {}
|
Protocol::Error => {}
|
||||||
@@ -103,7 +117,7 @@ impl ClientPacketHandler {
|
|||||||
context: &ChannelContext,
|
context: &ChannelContext,
|
||||||
current_device: &CurrentDeviceInfo,
|
current_device: &CurrentDeviceInfo,
|
||||||
route_key: RouteKey,
|
route_key: RouteKey,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let destination = net_packet.destination();
|
let destination = net_packet.destination();
|
||||||
let source = net_packet.source();
|
let source = net_packet.source();
|
||||||
match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) {
|
match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||||
@@ -190,7 +204,7 @@ impl ClientPacketHandler {
|
|||||||
current_device: &CurrentDeviceInfo,
|
current_device: &CurrentDeviceInfo,
|
||||||
mut net_packet: NetPacket<&mut [u8]>,
|
mut net_packet: NetPacket<&mut [u8]>,
|
||||||
route_key: RouteKey,
|
route_key: RouteKey,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
|
let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
|
||||||
let source = net_packet.source();
|
let source = net_packet.source();
|
||||||
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
|
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
|
||||||
@@ -278,17 +292,15 @@ impl ClientPacketHandler {
|
|||||||
current_device: &CurrentDeviceInfo,
|
current_device: &CurrentDeviceInfo,
|
||||||
net_packet: NetPacket<&mut [u8]>,
|
net_packet: NetPacket<&mut [u8]>,
|
||||||
route_key: RouteKey,
|
route_key: RouteKey,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if context.use_channel_type().is_only_relay() {
|
if context.use_channel_type().is_only_relay() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let source = net_packet.source();
|
let source = net_packet.source();
|
||||||
match other_turn_packet::Protocol::from(net_packet.transport_protocol()) {
|
match other_turn_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||||
other_turn_packet::Protocol::Punch => {
|
other_turn_packet::Protocol::Punch => {
|
||||||
let mut punch_info =
|
let mut punch_info = PunchInfo::parse_from_bytes(net_packet.payload())
|
||||||
PunchInfo::parse_from_bytes(net_packet.payload()).map_err(|e| {
|
.map_err(|e| anyhow!("PunchInfo {:?}", e))?;
|
||||||
io::Error::new(io::ErrorKind::Other, format!("PunchInfo {:?}", e))
|
|
||||||
})?;
|
|
||||||
let public_ips = punch_info
|
let public_ips = punch_info
|
||||||
.public_ip_list
|
.public_ip_list
|
||||||
.iter()
|
.iter()
|
||||||
@@ -348,9 +360,9 @@ impl ClientPacketHandler {
|
|||||||
punch_reply.ipv6 = ipv6.octets().to_vec();
|
punch_reply.ipv6 = ipv6.octets().to_vec();
|
||||||
punch_reply.ipv6_port = nat_info.udp_ports[0] as u32;
|
punch_reply.ipv6_port = nat_info.udp_ports[0] as u32;
|
||||||
}
|
}
|
||||||
let bytes = punch_reply.write_to_bytes().map_err(|e| {
|
let bytes = punch_reply
|
||||||
io::Error::new(io::ErrorKind::Other, format!("punch_reply {:?}", e))
|
.write_to_bytes()
|
||||||
})?;
|
.map_err(|e| anyhow!("punch_reply {:?}", e))?;
|
||||||
let mut punch_packet =
|
let mut punch_packet =
|
||||||
NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?;
|
NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?;
|
||||||
punch_packet.set_default_version();
|
punch_packet.set_default_version();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{io, thread};
|
use std::thread;
|
||||||
|
|
||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
@@ -24,7 +24,7 @@ use crate::handle::{BaseConfigInfo, CurrentDeviceInfo, PeerDeviceInfo, SELF_IP};
|
|||||||
#[cfg(feature = "ip_proxy")]
|
#[cfg(feature = "ip_proxy")]
|
||||||
use crate::ip_proxy::IpProxyMap;
|
use crate::ip_proxy::IpProxyMap;
|
||||||
use crate::nat::NatTest;
|
use crate::nat::NatTest;
|
||||||
use crate::protocol::NetPacket;
|
use crate::protocol::{NetPacket, HEAD_LEN};
|
||||||
use crate::tun_tap_device::tun_create_helper::DeviceAdapter;
|
use crate::tun_tap_device::tun_create_helper::DeviceAdapter;
|
||||||
use crate::util::U64Adder;
|
use crate::util::U64Adder;
|
||||||
|
|
||||||
@@ -43,7 +43,16 @@ pub struct RecvDataHandler<Call> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<Call: VntCallback> RecvChannelHandler for RecvDataHandler<Call> {
|
impl<Call: VntCallback> RecvChannelHandler for RecvDataHandler<Call> {
|
||||||
fn handle(&mut self, buf: &mut [u8], route_key: RouteKey, context: &ChannelContext) {
|
fn handle(
|
||||||
|
&mut self,
|
||||||
|
buf: &mut [u8],
|
||||||
|
extend: &mut [u8],
|
||||||
|
route_key: RouteKey,
|
||||||
|
context: &ChannelContext,
|
||||||
|
) {
|
||||||
|
if buf.len() < HEAD_LEN {
|
||||||
|
return;
|
||||||
|
}
|
||||||
//判断stun响应包
|
//判断stun响应包
|
||||||
if !route_key.is_tcp() {
|
if !route_key.is_tcp() {
|
||||||
if let Ok(rs) = self
|
if let Ok(rs) = self
|
||||||
@@ -55,8 +64,13 @@ impl<Call: VntCallback> RecvChannelHandler for RecvDataHandler<Call> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Err(e) = self.handle0(buf, route_key, context) {
|
if let Err(e) = self.handle0(buf, extend, route_key, context) {
|
||||||
log::error!("[{}]-{:?}", thread::current().name().unwrap_or(""), e);
|
log::error!(
|
||||||
|
"[{}]-{:?}-{:?}",
|
||||||
|
thread::current().name().unwrap_or(""),
|
||||||
|
route_key.addr,
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,14 +130,16 @@ impl<Call: VntCallback> RecvDataHandler<Call> {
|
|||||||
fn handle0(
|
fn handle0(
|
||||||
&mut self,
|
&mut self,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
|
extend: &mut [u8],
|
||||||
route_key: RouteKey,
|
route_key: RouteKey,
|
||||||
context: &ChannelContext,
|
context: &ChannelContext,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
// 统计流量
|
// 统计流量
|
||||||
self.counter.add(buf.len() as _);
|
self.counter.add(buf.len() as _);
|
||||||
let net_packet = NetPacket::new(buf)?;
|
let net_packet = NetPacket::new(buf)?;
|
||||||
|
let extend = NetPacket::unchecked(extend);
|
||||||
if net_packet.ttl() == 0 || net_packet.source_ttl() < net_packet.ttl() {
|
if net_packet.ttl() == 0 || net_packet.source_ttl() < net_packet.ttl() {
|
||||||
log::warn!("丢弃过时包:{:?}", net_packet.head());
|
log::warn!("丢弃过时包:{:?} {}", net_packet.head(), route_key.addr);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let current_device = self.current_device.load();
|
let current_device = self.current_device.load();
|
||||||
@@ -139,16 +155,16 @@ impl<Call: VntCallback> RecvDataHandler<Call> {
|
|||||||
if net_packet.is_gateway() {
|
if net_packet.is_gateway() {
|
||||||
//服务端-客户端包
|
//服务端-客户端包
|
||||||
self.server
|
self.server
|
||||||
.handle(net_packet, route_key, context, ¤t_device)
|
.handle(net_packet, extend, route_key, context, ¤t_device)
|
||||||
} else {
|
} else {
|
||||||
//客户端-客户端包
|
//客户端-客户端包
|
||||||
self.client
|
self.client
|
||||||
.handle(net_packet, route_key, context, ¤t_device)
|
.handle(net_packet, extend, route_key, context, ¤t_device)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//转发包
|
//转发包
|
||||||
self.turn
|
self.turn
|
||||||
.handle(net_packet, route_key, context, ¤t_device)
|
.handle(net_packet, extend, route_key, context, ¤t_device)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,8 +173,9 @@ pub trait PacketHandler {
|
|||||||
fn handle(
|
fn handle(
|
||||||
&self,
|
&self,
|
||||||
net_packet: NetPacket<&mut [u8]>,
|
net_packet: NetPacket<&mut [u8]>,
|
||||||
|
extend: NetPacket<&mut [u8]>,
|
||||||
route_key: RouteKey,
|
route_key: RouteKey,
|
||||||
context: &ChannelContext,
|
context: &ChannelContext,
|
||||||
current_device: &CurrentDeviceInfo,
|
current_device: &CurrentDeviceInfo,
|
||||||
) -> io::Result<()>;
|
) -> anyhow::Result<()>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use anyhow::anyhow;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -11,6 +12,8 @@ use protobuf::Message;
|
|||||||
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;
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
|
use tun::device::IFace;
|
||||||
|
|
||||||
use crate::channel::context::ChannelContext;
|
use crate::channel::context::ChannelContext;
|
||||||
use crate::channel::{Route, RouteKey};
|
use crate::channel::{Route, RouteKey};
|
||||||
@@ -34,8 +37,6 @@ use crate::protocol::error_packet::InErrorPacket;
|
|||||||
use crate::protocol::{ip_turn_packet, service_packet, NetPacket, Protocol, MAX_TTL};
|
use crate::protocol::{ip_turn_packet, service_packet, NetPacket, Protocol, MAX_TTL};
|
||||||
use crate::tun_tap_device::tun_create_helper::DeviceAdapter;
|
use crate::tun_tap_device::tun_create_helper::DeviceAdapter;
|
||||||
use crate::{proto, PeerClientInfo};
|
use crate::{proto, PeerClientInfo};
|
||||||
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
|
||||||
use tun::device::IFace;
|
|
||||||
|
|
||||||
/// 处理来源于服务端的包
|
/// 处理来源于服务端的包
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -94,10 +95,11 @@ impl<Call: VntCallback> PacketHandler for ServerPacketHandler<Call> {
|
|||||||
fn handle(
|
fn handle(
|
||||||
&self,
|
&self,
|
||||||
mut net_packet: NetPacket<&mut [u8]>,
|
mut net_packet: NetPacket<&mut [u8]>,
|
||||||
|
_extend: NetPacket<&mut [u8]>,
|
||||||
route_key: RouteKey,
|
route_key: RouteKey,
|
||||||
context: &ChannelContext,
|
context: &ChannelContext,
|
||||||
current_device: &CurrentDeviceInfo,
|
current_device: &CurrentDeviceInfo,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
context
|
context
|
||||||
.route_table
|
.route_table
|
||||||
.update_read_time(&net_packet.source(), &route_key);
|
.update_read_time(&net_packet.source(), &route_key);
|
||||||
@@ -135,10 +137,8 @@ impl<Call: VntCallback> PacketHandler for ServerPacketHandler<Call> {
|
|||||||
} else if net_packet.protocol() == Protocol::Service
|
} else if net_packet.protocol() == Protocol::Service
|
||||||
&& net_packet.transport_protocol() == service_packet::Protocol::HandshakeResponse.into()
|
&& net_packet.transport_protocol() == service_packet::Protocol::HandshakeResponse.into()
|
||||||
{
|
{
|
||||||
let response =
|
let response = HandshakeResponse::parse_from_bytes(net_packet.payload())
|
||||||
HandshakeResponse::parse_from_bytes(net_packet.payload()).map_err(|e| {
|
.map_err(|e| anyhow!("HandshakeResponse {:?}", e))?;
|
||||||
io::Error::new(io::ErrorKind::Other, format!("HandshakeResponse {:?}", e))
|
|
||||||
})?;
|
|
||||||
log::info!("握手响应:{:?},{}", route_key, response);
|
log::info!("握手响应:{:?},{}", route_key, response);
|
||||||
//如果开启了加密,则发送加密握手请求
|
//如果开启了加密,则发送加密握手请求
|
||||||
#[cfg(feature = "server_encrypt")]
|
#[cfg(feature = "server_encrypt")]
|
||||||
@@ -193,6 +193,7 @@ impl<Call: VntCallback> PacketHandler for ServerPacketHandler<Call> {
|
|||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "server_encrypt")]
|
||||||
if let Ok(rsa_cipher) = RsaCipher::new(&response.public_key) {
|
if let Ok(rsa_cipher) = RsaCipher::new(&response.public_key) {
|
||||||
self.rsa_cipher.lock().replace(rsa_cipher);
|
self.rsa_cipher.lock().replace(rsa_cipher);
|
||||||
}
|
}
|
||||||
@@ -252,7 +253,7 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
|
|||||||
current_device: &CurrentDeviceInfo,
|
current_device: &CurrentDeviceInfo,
|
||||||
net_packet: NetPacket<&mut [u8]>,
|
net_packet: NetPacket<&mut [u8]>,
|
||||||
route_key: RouteKey,
|
route_key: RouteKey,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
match service_packet::Protocol::from(net_packet.transport_protocol()) {
|
match service_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||||
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())
|
||||||
@@ -438,7 +439,7 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
|
|||||||
&self,
|
&self,
|
||||||
current_device: &CurrentDeviceInfo,
|
current_device: &CurrentDeviceInfo,
|
||||||
context: &ChannelContext,
|
context: &ChannelContext,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if current_device.status.online() {
|
if current_device.status.online() {
|
||||||
log::info!("已连接的不需要注册,{:?}", self.config_info);
|
log::info!("已连接的不需要注册,{:?}", self.config_info);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -467,7 +468,8 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
|
|||||||
)?;
|
)?;
|
||||||
log::info!("发送注册请求,{:?}", self.config_info);
|
log::info!("发送注册请求,{:?}", self.config_info);
|
||||||
//注册请求只发送到默认通道
|
//注册请求只发送到默认通道
|
||||||
context.send_default(response.buffer(), current_device.connect_server)
|
context.send_default(response.buffer(), current_device.connect_server)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
fn error(
|
fn error(
|
||||||
&self,
|
&self,
|
||||||
@@ -525,7 +527,7 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
|
|||||||
current_device: &CurrentDeviceInfo,
|
current_device: &CurrentDeviceInfo,
|
||||||
net_packet: NetPacket<&mut [u8]>,
|
net_packet: NetPacket<&mut [u8]>,
|
||||||
route_key: RouteKey,
|
route_key: RouteKey,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
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 current_time = crate::handle::now_time() as u16;
|
let current_time = crate::handle::now_time() as u16;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use crate::channel::RouteKey;
|
|||||||
use crate::handle::recv_data::PacketHandler;
|
use crate::handle::recv_data::PacketHandler;
|
||||||
use crate::handle::CurrentDeviceInfo;
|
use crate::handle::CurrentDeviceInfo;
|
||||||
use crate::protocol::NetPacket;
|
use crate::protocol::NetPacket;
|
||||||
|
use anyhow::Context;
|
||||||
|
|
||||||
/// 处理客户端中转包
|
/// 处理客户端中转包
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -18,10 +19,11 @@ impl PacketHandler for TurnPacketHandler {
|
|||||||
fn handle(
|
fn handle(
|
||||||
&self,
|
&self,
|
||||||
mut net_packet: NetPacket<&mut [u8]>,
|
mut net_packet: NetPacket<&mut [u8]>,
|
||||||
|
_extend: NetPacket<&mut [u8]>,
|
||||||
route_key: RouteKey,
|
route_key: RouteKey,
|
||||||
context: &ChannelContext,
|
context: &ChannelContext,
|
||||||
_current_device: &CurrentDeviceInfo,
|
_current_device: &CurrentDeviceInfo,
|
||||||
) -> std::io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
// ttl减一
|
// ttl减一
|
||||||
let ttl = net_packet.incr_ttl();
|
let ttl = net_packet.incr_ttl();
|
||||||
if ttl > 0 {
|
if ttl > 0 {
|
||||||
@@ -33,7 +35,9 @@ impl PacketHandler for TurnPacketHandler {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if route.metric <= ttl {
|
if route.metric <= ttl {
|
||||||
return context.send_by_key(net_packet.buffer(), route.route_key());
|
return context
|
||||||
|
.send_by_key(net_packet.buffer(), route.route_key())
|
||||||
|
.context("转发失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//其他没有路由的不转发
|
//其他没有路由的不转发
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::io;
|
use anyhow::anyhow;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
use protobuf::Message;
|
use protobuf::Message;
|
||||||
@@ -19,7 +19,7 @@ pub fn registration_request_packet(
|
|||||||
is_fast: bool,
|
is_fast: bool,
|
||||||
allow_ip_change: bool,
|
allow_ip_change: bool,
|
||||||
client_secret_hash: Option<&[u8]>,
|
client_secret_hash: Option<&[u8]>,
|
||||||
) -> io::Result<NetPacket<Vec<u8>>> {
|
) -> anyhow::Result<NetPacket<Vec<u8>>> {
|
||||||
let mut request = RegistrationRequest::new();
|
let mut request = RegistrationRequest::new();
|
||||||
request.token = token;
|
request.token = token;
|
||||||
request.device_id = device_id;
|
request.device_id = device_id;
|
||||||
@@ -36,9 +36,9 @@ pub fn registration_request_packet(
|
|||||||
.client_secret_hash
|
.client_secret_hash
|
||||||
.extend_from_slice(client_secret_hash);
|
.extend_from_slice(client_secret_hash);
|
||||||
}
|
}
|
||||||
let bytes = request.write_to_bytes().map_err(|e| {
|
let bytes = request
|
||||||
io::Error::new(io::ErrorKind::Other, format!("RegistrationRequest {:?}", e))
|
.write_to_bytes()
|
||||||
})?;
|
.map_err(|e| anyhow!("RegistrationRequest {:?}", e))?;
|
||||||
let buf = vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED];
|
let buf = vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED];
|
||||||
let mut net_packet = NetPacket::new_encrypt(buf)?;
|
let mut net_packet = NetPacket::new_encrypt(buf)?;
|
||||||
net_packet.set_destination(GATEWAY_IP);
|
net_packet.set_destination(GATEWAY_IP);
|
||||||
|
|||||||
@@ -13,12 +13,15 @@ use tun::device::IFace;
|
|||||||
use tun::Device;
|
use tun::Device;
|
||||||
|
|
||||||
use crate::channel::context::ChannelContext;
|
use crate::channel::context::ChannelContext;
|
||||||
|
use crate::channel::BUFFER_SIZE;
|
||||||
use crate::cipher::Cipher;
|
use crate::cipher::Cipher;
|
||||||
|
use crate::compression::Compressor;
|
||||||
use crate::external_route::ExternalRoute;
|
use crate::external_route::ExternalRoute;
|
||||||
use crate::handle::tun_tap::channel_group::channel_group;
|
use crate::handle::tun_tap::channel_group::channel_group;
|
||||||
use crate::handle::{check_dest, CurrentDeviceInfo, PeerDeviceInfo};
|
use crate::handle::{check_dest, CurrentDeviceInfo, PeerDeviceInfo};
|
||||||
#[cfg(feature = "ip_proxy")]
|
#[cfg(feature = "ip_proxy")]
|
||||||
use crate::ip_proxy::IpProxyMap;
|
use crate::ip_proxy::IpProxyMap;
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
use crate::ip_proxy::ProxyHandler;
|
use crate::ip_proxy::ProxyHandler;
|
||||||
use crate::protocol;
|
use crate::protocol;
|
||||||
use crate::protocol::body::ENCRYPTION_RESERVED;
|
use crate::protocol::body::ENCRYPTION_RESERVED;
|
||||||
@@ -26,7 +29,7 @@ use crate::protocol::ip_turn_packet::BroadcastPacket;
|
|||||||
use crate::protocol::{ip_turn_packet, NetPacket, MAX_TTL};
|
use crate::protocol::{ip_turn_packet, NetPacket, MAX_TTL};
|
||||||
use crate::util::{SingleU64Adder, StopManager};
|
use crate::util::{SingleU64Adder, StopManager};
|
||||||
|
|
||||||
fn icmp(device_writer: &Device, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> io::Result<()> {
|
fn icmp(device_writer: &Device, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> anyhow::Result<()> {
|
||||||
if ipv4_packet.protocol() == Protocol::Icmp {
|
if ipv4_packet.protocol() == Protocol::Icmp {
|
||||||
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
|
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
|
||||||
if icmp.kind() == Kind::EchoRequest {
|
if icmp.kind() == Kind::EchoRequest {
|
||||||
@@ -42,43 +45,6 @@ fn icmp(device_writer: &Device, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> io::R
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 接收tun数据,并且转发到udp上
|
|
||||||
pub(crate) fn handle(
|
|
||||||
context: &ChannelContext,
|
|
||||||
data: &mut [u8],
|
|
||||||
len: usize,
|
|
||||||
device_writer: &Device,
|
|
||||||
current_device: CurrentDeviceInfo,
|
|
||||||
ip_route: &ExternalRoute,
|
|
||||||
#[cfg(feature = "ip_proxy")] proxy_map: &Option<IpProxyMap>,
|
|
||||||
client_cipher: &Cipher,
|
|
||||||
server_cipher: &Cipher,
|
|
||||||
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
|
|
||||||
) -> io::Result<()> {
|
|
||||||
//忽略掉结构不对的情况(ipv6数据、win tap会读到空数据),不然日志打印太多了
|
|
||||||
let ipv4_packet = match IpV4Packet::new(&mut data[12..len]) {
|
|
||||||
Ok(packet) => packet,
|
|
||||||
Err(_) => return Ok(()),
|
|
||||||
};
|
|
||||||
let src_ip = ipv4_packet.source_ip();
|
|
||||||
let dest_ip = ipv4_packet.destination_ip();
|
|
||||||
if src_ip == dest_ip {
|
|
||||||
return icmp(&device_writer, ipv4_packet);
|
|
||||||
}
|
|
||||||
return base_handle(
|
|
||||||
context,
|
|
||||||
data,
|
|
||||||
len,
|
|
||||||
current_device,
|
|
||||||
ip_route,
|
|
||||||
#[cfg(feature = "ip_proxy")]
|
|
||||||
proxy_map,
|
|
||||||
client_cipher,
|
|
||||||
server_cipher,
|
|
||||||
device_list,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start(
|
pub fn start(
|
||||||
stop_manager: StopManager,
|
stop_manager: StopManager,
|
||||||
context: ChannelContext,
|
context: ChannelContext,
|
||||||
@@ -91,6 +57,7 @@ pub fn start(
|
|||||||
parallel: usize,
|
parallel: usize,
|
||||||
mut up_counter: SingleU64Adder,
|
mut up_counter: SingleU64Adder,
|
||||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||||
|
compressor: Compressor,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
if parallel > 1 {
|
if parallel > 1 {
|
||||||
let (sender, receivers) = channel_group::<(Vec<u8>, usize)>(parallel, 16);
|
let (sender, receivers) = channel_group::<(Vec<u8>, usize)>(parallel, 16);
|
||||||
@@ -107,6 +74,7 @@ pub fn start(
|
|||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
.name(format!("tunHandler-{}", index))
|
.name(format!("tunHandler-{}", index))
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
|
let mut extend = [0; BUFFER_SIZE];
|
||||||
while let Ok((mut buf, len)) = receiver.recv() {
|
while let Ok((mut buf, len)) = receiver.recv() {
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
let start = 0;
|
let start = 0;
|
||||||
@@ -116,6 +84,7 @@ pub fn start(
|
|||||||
&context,
|
&context,
|
||||||
&mut buf[start..],
|
&mut buf[start..],
|
||||||
len,
|
len,
|
||||||
|
&mut extend,
|
||||||
&device,
|
&device,
|
||||||
current_device.load(),
|
current_device.load(),
|
||||||
&ip_route,
|
&ip_route,
|
||||||
@@ -124,6 +93,7 @@ pub fn start(
|
|||||||
&client_cipher,
|
&client_cipher,
|
||||||
&server_cipher,
|
&server_cipher,
|
||||||
&device_list,
|
&device_list,
|
||||||
|
&compressor,
|
||||||
) {
|
) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -161,6 +131,7 @@ pub fn start(
|
|||||||
server_cipher,
|
server_cipher,
|
||||||
&mut up_counter,
|
&mut up_counter,
|
||||||
device_list,
|
device_list,
|
||||||
|
compressor,
|
||||||
) {
|
) {
|
||||||
log::warn!("stop:{}", e);
|
log::warn!("stop:{}", e);
|
||||||
}
|
}
|
||||||
@@ -175,7 +146,7 @@ fn broadcast(
|
|||||||
net_packet: &mut NetPacket<&mut [u8]>,
|
net_packet: &mut NetPacket<&mut [u8]>,
|
||||||
current_device: &CurrentDeviceInfo,
|
current_device: &CurrentDeviceInfo,
|
||||||
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
|
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let list: Vec<Ipv4Addr> = device_list
|
let list: Vec<Ipv4Addr> = device_list
|
||||||
.lock()
|
.lock()
|
||||||
.1
|
.1
|
||||||
@@ -249,29 +220,43 @@ fn broadcast(
|
|||||||
broadcast.set_address(&p2p_ips)?;
|
broadcast.set_address(&p2p_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.send_default(server_packet.buffer(), current_device.connect_server)
|
sender.send_default(server_packet.buffer(), current_device.connect_server)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 接收tun数据,并且转发到udp上
|
||||||
/// 实现一个原地发送,必须保证是如下结构
|
/// 实现一个原地发送,必须保证是如下结构
|
||||||
/// |12字节开头|ip报文|至少1024字节结尾|
|
/// |12字节开头|ip报文|至少1024字节结尾|
|
||||||
///
|
///
|
||||||
#[inline]
|
pub(crate) fn handle(
|
||||||
fn base_handle(
|
|
||||||
context: &ChannelContext,
|
context: &ChannelContext,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
data_len: usize, //数据总长度=12+ip包长度
|
data_len: usize, //数据总长度=12+ip包长度
|
||||||
|
extend: &mut [u8],
|
||||||
|
device_writer: &Device,
|
||||||
current_device: CurrentDeviceInfo,
|
current_device: CurrentDeviceInfo,
|
||||||
ip_route: &ExternalRoute,
|
ip_route: &ExternalRoute,
|
||||||
#[cfg(feature = "ip_proxy")] proxy_map: &Option<IpProxyMap>,
|
#[cfg(feature = "ip_proxy")] proxy_map: &Option<IpProxyMap>,
|
||||||
client_cipher: &Cipher,
|
client_cipher: &Cipher,
|
||||||
server_cipher: &Cipher,
|
server_cipher: &Cipher,
|
||||||
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
|
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
|
||||||
) -> io::Result<()> {
|
compressor: &Compressor,
|
||||||
let ipv4_packet = IpV4Packet::new(&buf[12..data_len])?;
|
) -> anyhow::Result<()> {
|
||||||
|
//忽略掉结构不对的情况(ipv6数据、win tap会读到空数据),不然日志打印太多了
|
||||||
|
let ipv4_packet = match IpV4Packet::new(&mut buf[12..data_len]) {
|
||||||
|
Ok(packet) => packet,
|
||||||
|
Err(_) => return Ok(()),
|
||||||
|
};
|
||||||
|
let src_ip = ipv4_packet.source_ip();
|
||||||
|
let dest_ip = ipv4_packet.destination_ip();
|
||||||
|
if src_ip == dest_ip {
|
||||||
|
return icmp(&device_writer, ipv4_packet);
|
||||||
|
}
|
||||||
let protocol = ipv4_packet.protocol();
|
let protocol = ipv4_packet.protocol();
|
||||||
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)?;
|
||||||
|
let mut out = NetPacket::unchecked(extend);
|
||||||
net_packet.set_default_version();
|
net_packet.set_default_version();
|
||||||
net_packet.set_protocol(protocol::Protocol::IpTurn);
|
net_packet.set_protocol(protocol::Protocol::IpTurn);
|
||||||
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4.into());
|
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4.into());
|
||||||
@@ -287,11 +272,49 @@ fn base_handle(
|
|||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
if !dest_ip.is_multicast() && !dest_ip.is_broadcast() && current_device.broadcast_ip != dest_ip
|
||||||
|
{
|
||||||
|
if !check_dest(
|
||||||
|
dest_ip,
|
||||||
|
current_device.virtual_netmask,
|
||||||
|
current_device.virtual_network,
|
||||||
|
) {
|
||||||
|
if let Some(r_dest_ip) = ip_route.route(&dest_ip) {
|
||||||
|
//路由的目标不能是自己
|
||||||
|
if r_dest_ip == src_ip {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
//需要修改目的地址
|
||||||
|
dest_ip = r_dest_ip;
|
||||||
|
net_packet.set_destination(r_dest_ip);
|
||||||
|
} else {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
|
if let Some(proxy_map) = proxy_map {
|
||||||
|
let mut ipv4_packet = IpV4Packet::new(net_packet.payload_mut())?;
|
||||||
|
proxy_map.send_handle(&mut ipv4_packet)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if dest_ip.is_multicast() {
|
if dest_ip.is_multicast() {
|
||||||
//当作广播处理
|
//当作广播处理
|
||||||
dest_ip = Ipv4Addr::BROADCAST;
|
dest_ip = Ipv4Addr::BROADCAST;
|
||||||
net_packet.set_destination(Ipv4Addr::BROADCAST);
|
net_packet.set_destination(Ipv4Addr::BROADCAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut net_packet = if compressor.compress(&net_packet, &mut out)? {
|
||||||
|
out.set_default_version();
|
||||||
|
out.set_protocol(protocol::Protocol::IpTurn);
|
||||||
|
out.set_transport_protocol(ip_turn_packet::Protocol::Ipv4.into());
|
||||||
|
out.first_set_ttl(6);
|
||||||
|
out.set_source(src_ip);
|
||||||
|
out.set_destination(dest_ip);
|
||||||
|
out
|
||||||
|
} else {
|
||||||
|
net_packet
|
||||||
|
};
|
||||||
if dest_ip.is_broadcast() || current_device.broadcast_ip == dest_ip {
|
if dest_ip.is_broadcast() || current_device.broadcast_ip == dest_ip {
|
||||||
// 广播 发送到直连目标
|
// 广播 发送到直连目标
|
||||||
client_cipher.encrypt_ipv4(&mut net_packet)?;
|
client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||||
@@ -304,33 +327,13 @@ fn base_handle(
|
|||||||
)?;
|
)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if !check_dest(
|
|
||||||
dest_ip,
|
|
||||||
current_device.virtual_netmask,
|
|
||||||
current_device.virtual_network,
|
|
||||||
) {
|
|
||||||
if let Some(r_dest_ip) = ip_route.route(&dest_ip) {
|
|
||||||
//路由的目标不能是自己
|
|
||||||
if r_dest_ip == src_ip {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
//需要修改目的地址
|
|
||||||
dest_ip = r_dest_ip;
|
|
||||||
net_packet.set_destination(r_dest_ip);
|
|
||||||
} else {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(feature = "ip_proxy")]
|
|
||||||
if let Some(proxy_map) = proxy_map {
|
|
||||||
let mut ipv4_packet = IpV4Packet::new(net_packet.payload_mut())?;
|
|
||||||
proxy_map.send_handle(&mut ipv4_packet)?;
|
|
||||||
}
|
|
||||||
client_cipher.encrypt_ipv4(&mut net_packet)?;
|
client_cipher.encrypt_ipv4(&mut net_packet)?;
|
||||||
context.send_ipv4_by_id(
|
context.send_ipv4_by_id(
|
||||||
net_packet.buffer(),
|
net_packet.buffer(),
|
||||||
&dest_ip,
|
&dest_ip,
|
||||||
current_device.connect_server,
|
current_device.connect_server,
|
||||||
current_device.status.online(),
|
current_device.status.online(),
|
||||||
)
|
)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
use crate::channel::context::ChannelContext;
|
use crate::channel::context::ChannelContext;
|
||||||
|
use crate::channel::BUFFER_SIZE;
|
||||||
use crate::cipher::Cipher;
|
use crate::cipher::Cipher;
|
||||||
|
use crate::compression::Compressor;
|
||||||
use crate::external_route::ExternalRoute;
|
use crate::external_route::ExternalRoute;
|
||||||
use crate::handle::tun_tap::channel_group::GroupSyncSender;
|
use crate::handle::tun_tap::channel_group::GroupSyncSender;
|
||||||
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
|
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
use crate::ip_proxy::IpProxyMap;
|
use crate::ip_proxy::IpProxyMap;
|
||||||
use crate::util::{SingleU64Adder, StopManager};
|
use crate::util::{SingleU64Adder, StopManager};
|
||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
@@ -29,7 +32,8 @@ pub(crate) fn start_simple(
|
|||||||
server_cipher: Cipher,
|
server_cipher: Cipher,
|
||||||
up_counter: &mut SingleU64Adder,
|
up_counter: &mut SingleU64Adder,
|
||||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||||
) -> io::Result<()> {
|
compressor: Compressor,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
let poll = Poll::new()?;
|
let poll = Poll::new()?;
|
||||||
let waker = Arc::new(Waker::new(poll.registry(), STOP)?);
|
let waker = Arc::new(Waker::new(poll.registry(), STOP)?);
|
||||||
let _waker = waker.clone();
|
let _waker = waker.clone();
|
||||||
@@ -48,6 +52,7 @@ pub(crate) fn start_simple(
|
|||||||
server_cipher,
|
server_cipher,
|
||||||
up_counter,
|
up_counter,
|
||||||
device_list,
|
device_list,
|
||||||
|
compressor,
|
||||||
) {
|
) {
|
||||||
log::error!("{:?}", e);
|
log::error!("{:?}", e);
|
||||||
};
|
};
|
||||||
@@ -67,19 +72,24 @@ fn start_simple0(
|
|||||||
server_cipher: Cipher,
|
server_cipher: Cipher,
|
||||||
up_counter: &mut SingleU64Adder,
|
up_counter: &mut SingleU64Adder,
|
||||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||||
) -> io::Result<()> {
|
compressor: Compressor,
|
||||||
let mut buf = [0; 1024 * 16];
|
) -> anyhow::Result<()> {
|
||||||
|
let mut buf = [0; BUFFER_SIZE];
|
||||||
|
let mut extend = [0; BUFFER_SIZE];
|
||||||
let fd = device.as_tun_fd();
|
let fd = device.as_tun_fd();
|
||||||
fd.set_nonblock()?;
|
fd.set_nonblock()?;
|
||||||
SourceFd(&fd.as_raw_fd()).register(poll.registry(), FD, Interest::READABLE)?;
|
SourceFd(&fd.as_raw_fd()).register(poll.registry(), FD, Interest::READABLE)?;
|
||||||
let mut evnets = Events::with_capacity(4);
|
let mut events = Events::with_capacity(4);
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
let start = 12;
|
let start = 12;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
let start = 12 - 4;
|
let start = 12 - 4;
|
||||||
loop {
|
loop {
|
||||||
poll.poll(&mut evnets, None)?;
|
if let Err(e) = poll.poll(&mut events, None) {
|
||||||
for event in evnets.iter() {
|
crate::ignore_io_interrupted(e)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for event in events.iter() {
|
||||||
if event.token() == STOP {
|
if event.token() == STOP {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -101,6 +111,7 @@ fn start_simple0(
|
|||||||
context,
|
context,
|
||||||
&mut buf,
|
&mut buf,
|
||||||
len,
|
len,
|
||||||
|
&mut extend,
|
||||||
&device,
|
&device,
|
||||||
current_device.load(),
|
current_device.load(),
|
||||||
&ip_route,
|
&ip_route,
|
||||||
@@ -109,6 +120,7 @@ fn start_simple0(
|
|||||||
&client_cipher,
|
&client_cipher,
|
||||||
&server_cipher,
|
&server_cipher,
|
||||||
&device_list,
|
&device_list,
|
||||||
|
&compressor,
|
||||||
) {
|
) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -125,7 +137,7 @@ pub(crate) fn start_multi(
|
|||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
group_sync_sender: GroupSyncSender<(Vec<u8>, usize)>,
|
group_sync_sender: GroupSyncSender<(Vec<u8>, usize)>,
|
||||||
up_counter: &mut SingleU64Adder,
|
up_counter: &mut SingleU64Adder,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let poll = Poll::new()?;
|
let poll = Poll::new()?;
|
||||||
let waker = Arc::new(Waker::new(poll.registry(), STOP)?);
|
let waker = Arc::new(Waker::new(poll.registry(), STOP)?);
|
||||||
let _waker = waker.clone();
|
let _waker = waker.clone();
|
||||||
@@ -145,7 +157,7 @@ fn start_multi0(
|
|||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
mut group_sync_sender: GroupSyncSender<(Vec<u8>, usize)>,
|
mut group_sync_sender: GroupSyncSender<(Vec<u8>, usize)>,
|
||||||
up_counter: &mut SingleU64Adder,
|
up_counter: &mut SingleU64Adder,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let fd = device.as_tun_fd();
|
let fd = device.as_tun_fd();
|
||||||
fd.set_nonblock()?;
|
fd.set_nonblock()?;
|
||||||
SourceFd(&fd.as_raw_fd()).register(poll.registry(), FD, Interest::READABLE)?;
|
SourceFd(&fd.as_raw_fd()).register(poll.registry(), FD, Interest::READABLE)?;
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
use crate::channel::context::ChannelContext;
|
use crate::channel::context::ChannelContext;
|
||||||
|
use crate::channel::BUFFER_SIZE;
|
||||||
use crate::cipher::Cipher;
|
use crate::cipher::Cipher;
|
||||||
|
use crate::compression::Compressor;
|
||||||
use crate::external_route::ExternalRoute;
|
use crate::external_route::ExternalRoute;
|
||||||
use crate::handle::tun_tap::channel_group::GroupSyncSender;
|
use crate::handle::tun_tap::channel_group::GroupSyncSender;
|
||||||
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
|
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
use crate::ip_proxy::IpProxyMap;
|
use crate::ip_proxy::IpProxyMap;
|
||||||
use crate::util::{SingleU64Adder, StopManager};
|
use crate::util::{SingleU64Adder, StopManager};
|
||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::io;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tun::device::IFace;
|
use tun::device::IFace;
|
||||||
use tun::Device;
|
use tun::Device;
|
||||||
@@ -23,7 +25,8 @@ pub(crate) fn start_simple(
|
|||||||
server_cipher: Cipher,
|
server_cipher: Cipher,
|
||||||
up_counter: &mut SingleU64Adder,
|
up_counter: &mut SingleU64Adder,
|
||||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||||
) -> io::Result<()> {
|
compressor: Compressor,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
let worker = {
|
let worker = {
|
||||||
let device = device.clone();
|
let device = device.clone();
|
||||||
stop_manager.add_listener("tun_device".into(), move || {
|
stop_manager.add_listener("tun_device".into(), move || {
|
||||||
@@ -43,6 +46,7 @@ pub(crate) fn start_simple(
|
|||||||
server_cipher,
|
server_cipher,
|
||||||
up_counter,
|
up_counter,
|
||||||
device_list,
|
device_list,
|
||||||
|
compressor,
|
||||||
) {
|
) {
|
||||||
log::error!("{:?}", e);
|
log::error!("{:?}", e);
|
||||||
}
|
}
|
||||||
@@ -59,8 +63,10 @@ fn start_simple0(
|
|||||||
server_cipher: Cipher,
|
server_cipher: Cipher,
|
||||||
up_counter: &mut SingleU64Adder,
|
up_counter: &mut SingleU64Adder,
|
||||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||||
) -> io::Result<()> {
|
compressor: Compressor,
|
||||||
let mut buf = [0; 1024 * 16];
|
) -> anyhow::Result<()> {
|
||||||
|
let mut buf = [0; BUFFER_SIZE];
|
||||||
|
let mut extend = [0; BUFFER_SIZE];
|
||||||
loop {
|
loop {
|
||||||
let len = device.read(&mut buf[12..])? + 12;
|
let len = device.read(&mut buf[12..])? + 12;
|
||||||
//单线程的
|
//单线程的
|
||||||
@@ -71,6 +77,7 @@ fn start_simple0(
|
|||||||
context,
|
context,
|
||||||
&mut buf,
|
&mut buf,
|
||||||
len,
|
len,
|
||||||
|
&mut extend,
|
||||||
&device,
|
&device,
|
||||||
current_device.load(),
|
current_device.load(),
|
||||||
&ip_route,
|
&ip_route,
|
||||||
@@ -79,6 +86,7 @@ fn start_simple0(
|
|||||||
&client_cipher,
|
&client_cipher,
|
||||||
&server_cipher,
|
&server_cipher,
|
||||||
&device_list,
|
&device_list,
|
||||||
|
&compressor,
|
||||||
) {
|
) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -92,7 +100,7 @@ pub(crate) fn start_multi(
|
|||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
group_sync_sender: GroupSyncSender<(Vec<u8>, usize)>,
|
group_sync_sender: GroupSyncSender<(Vec<u8>, usize)>,
|
||||||
up_counter: &mut SingleU64Adder,
|
up_counter: &mut SingleU64Adder,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let worker = {
|
let worker = {
|
||||||
let device = device.clone();
|
let device = device.clone();
|
||||||
stop_manager.add_listener("tun_device_multi".into(), move || {
|
stop_manager.add_listener("tun_device_multi".into(), move || {
|
||||||
@@ -111,7 +119,7 @@ fn start_multi0(
|
|||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
mut group_sync_sender: GroupSyncSender<(Vec<u8>, usize)>,
|
mut group_sync_sender: GroupSyncSender<(Vec<u8>, usize)>,
|
||||||
up_counter: &mut SingleU64Adder,
|
up_counter: &mut SingleU64Adder,
|
||||||
) -> io::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
loop {
|
loop {
|
||||||
let mut buf = vec![0; 1024 * 16];
|
let mut buf = vec![0; 1024 * 16];
|
||||||
let len = device.read(&mut buf[12..])? + 12;
|
let len = device.read(&mut buf[12..])? + 12;
|
||||||
|
|||||||
@@ -87,38 +87,36 @@ async fn icmp_proxy(
|
|||||||
client_cipher: Cipher,
|
client_cipher: Cipher,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
let mut buf = [0u8; 65535 - 20 - 8];
|
let mut buf = [0u8; 65535 - 20 - 8];
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
|
let start = 12;
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
let start = 12 + 20;
|
||||||
loop {
|
loop {
|
||||||
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
let (len, addr) = icmp_socket.recv_from(&mut buf[start..]).await?;
|
||||||
let start = 12;
|
if let IpAddr::V4(peer_ip) = addr.ip() {
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
let start = 12 + 20;
|
{
|
||||||
loop {
|
let buf = &mut buf[12..];
|
||||||
let (len, addr) = icmp_socket.recv_from(&mut buf[start..]).await?;
|
// ipv4 头部20字节
|
||||||
if let IpAddr::V4(peer_ip) = addr.ip() {
|
buf[0] = 0b0100_0110;
|
||||||
#[cfg(target_os = "android")]
|
//写入总长度
|
||||||
{
|
buf[2..4].copy_from_slice(&((20 + len) as u16).to_be_bytes());
|
||||||
let buf = &mut buf[12..];
|
|
||||||
// ipv4 头部20字节
|
|
||||||
buf[0] = 0b0100_0110;
|
|
||||||
//写入总长度
|
|
||||||
buf[2..4].copy_from_slice(&((20 + len) as u16).to_be_bytes());
|
|
||||||
|
|
||||||
let mut ipv4 = IpV4Packet::unchecked(buf);
|
let mut ipv4 = IpV4Packet::unchecked(buf);
|
||||||
ipv4.set_flags(2);
|
ipv4.set_flags(2);
|
||||||
ipv4.set_ttl(1);
|
ipv4.set_ttl(1);
|
||||||
ipv4.set_protocol(packet::ip::ipv4::protocol::Protocol::Icmp);
|
ipv4.set_protocol(packet::ip::ipv4::protocol::Protocol::Icmp);
|
||||||
ipv4.set_source_ip(peer_ip);
|
ipv4.set_source_ip(peer_ip);
|
||||||
}
|
|
||||||
recv_handle(
|
|
||||||
&mut buf,
|
|
||||||
start + len,
|
|
||||||
peer_ip,
|
|
||||||
&nat_map,
|
|
||||||
&context,
|
|
||||||
¤t_device,
|
|
||||||
&client_cipher,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
recv_handle(
|
||||||
|
&mut buf,
|
||||||
|
start + len,
|
||||||
|
peer_ip,
|
||||||
|
&nat_map,
|
||||||
|
&context,
|
||||||
|
¤t_device,
|
||||||
|
&client_cipher,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,7 +165,7 @@ fn recv_handle(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
h => {
|
h => {
|
||||||
log::warn!("不支持的icmp代理 {:?},{:?}", peer_ip, h)
|
log::debug!("不支持的icmp代理 {:?},{:?}", peer_ip, h)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|||||||
+11
-4
@@ -10,11 +10,13 @@ use packet::ip::ipv4::packet::IpV4Packet;
|
|||||||
use crate::channel::context::ChannelContext;
|
use crate::channel::context::ChannelContext;
|
||||||
use crate::cipher::Cipher;
|
use crate::cipher::Cipher;
|
||||||
use crate::handle::CurrentDeviceInfo;
|
use crate::handle::CurrentDeviceInfo;
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
use crate::ip_proxy::icmp_proxy::IcmpProxy;
|
use crate::ip_proxy::icmp_proxy::IcmpProxy;
|
||||||
use crate::ip_proxy::tcp_proxy::TcpProxy;
|
use crate::ip_proxy::tcp_proxy::TcpProxy;
|
||||||
use crate::ip_proxy::udp_proxy::UdpProxy;
|
use crate::ip_proxy::udp_proxy::UdpProxy;
|
||||||
use crate::util::StopManager;
|
use crate::util::StopManager;
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
pub mod icmp_proxy;
|
pub mod icmp_proxy;
|
||||||
pub mod tcp_proxy;
|
pub mod tcp_proxy;
|
||||||
pub mod udp_proxy;
|
pub mod udp_proxy;
|
||||||
@@ -31,6 +33,7 @@ pub trait ProxyHandler {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct IpProxyMap {
|
pub struct IpProxyMap {
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
icmp_proxy: IcmpProxy,
|
icmp_proxy: IcmpProxy,
|
||||||
tcp_proxy: TcpProxy,
|
tcp_proxy: TcpProxy,
|
||||||
udp_proxy: UdpProxy,
|
udp_proxy: UdpProxy,
|
||||||
@@ -65,15 +68,17 @@ pub fn init_proxy(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn init_proxy0(
|
async fn init_proxy0(
|
||||||
context: ChannelContext,
|
_context: ChannelContext,
|
||||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
_current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
client_cipher: Cipher,
|
_client_cipher: Cipher,
|
||||||
) -> anyhow::Result<IpProxyMap> {
|
) -> anyhow::Result<IpProxyMap> {
|
||||||
let icmp_proxy = IcmpProxy::new(context, current_device, client_cipher).await?;
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
|
let icmp_proxy = IcmpProxy::new(_context, _current_device, _client_cipher).await?;
|
||||||
let tcp_proxy = TcpProxy::new().await?;
|
let tcp_proxy = TcpProxy::new().await?;
|
||||||
let udp_proxy = UdpProxy::new().await?;
|
let udp_proxy = UdpProxy::new().await?;
|
||||||
|
|
||||||
Ok(IpProxyMap {
|
Ok(IpProxyMap {
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
icmp_proxy,
|
icmp_proxy,
|
||||||
tcp_proxy,
|
tcp_proxy,
|
||||||
udp_proxy,
|
udp_proxy,
|
||||||
@@ -90,6 +95,7 @@ impl ProxyHandler for IpProxyMap {
|
|||||||
match ipv4.protocol() {
|
match ipv4.protocol() {
|
||||||
ipv4::protocol::Protocol::Tcp => self.tcp_proxy.recv_handle(ipv4, source, destination),
|
ipv4::protocol::Protocol::Tcp => self.tcp_proxy.recv_handle(ipv4, source, destination),
|
||||||
ipv4::protocol::Protocol::Udp => self.udp_proxy.recv_handle(ipv4, source, destination),
|
ipv4::protocol::Protocol::Udp => self.udp_proxy.recv_handle(ipv4, source, destination),
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
ipv4::protocol::Protocol::Icmp => {
|
ipv4::protocol::Protocol::Icmp => {
|
||||||
self.icmp_proxy.recv_handle(ipv4, source, destination)
|
self.icmp_proxy.recv_handle(ipv4, source, destination)
|
||||||
}
|
}
|
||||||
@@ -110,6 +116,7 @@ impl ProxyHandler for IpProxyMap {
|
|||||||
match ipv4.protocol() {
|
match ipv4.protocol() {
|
||||||
ipv4::protocol::Protocol::Tcp => self.tcp_proxy.send_handle(ipv4),
|
ipv4::protocol::Protocol::Tcp => self.tcp_proxy.send_handle(ipv4),
|
||||||
ipv4::protocol::Protocol::Udp => self.udp_proxy.send_handle(ipv4),
|
ipv4::protocol::Protocol::Udp => self.udp_proxy.send_handle(ipv4),
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
ipv4::protocol::Protocol::Icmp => self.icmp_proxy.send_handle(ipv4),
|
ipv4::protocol::Protocol::Icmp => self.icmp_proxy.send_handle(ipv4),
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,3 +16,14 @@ pub mod tun_tap_device;
|
|||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
pub use handle::callback::*;
|
pub use handle::callback::*;
|
||||||
|
|
||||||
|
pub mod compression;
|
||||||
|
|
||||||
|
pub(crate) fn ignore_io_interrupted(e: std::io::Error) -> std::io::Result<()> {
|
||||||
|
if e.kind() == std::io::ErrorKind::Interrupted {
|
||||||
|
log::warn!("ignore_io_interrupted");
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+40
-27
@@ -224,34 +224,48 @@ impl NatTest {
|
|||||||
source_addr: SocketAddr,
|
source_addr: SocketAddr,
|
||||||
buf: &[u8],
|
buf: &[u8],
|
||||||
) -> anyhow::Result<bool> {
|
) -> anyhow::Result<bool> {
|
||||||
if let Some(addr) = stun::recv_stun_response(buf) {
|
if buf[0] == 0x01 && buf[1] == 0x01 {
|
||||||
if let SocketAddr::V4(addr) = addr {
|
if let Some(addr) = stun::recv_stun_response(buf) {
|
||||||
let mut check_fail = true;
|
if let Err(e) = self.recv_data_(index, source_addr, addr) {
|
||||||
let source_ip = match source_addr.ip() {
|
log::warn!("{:?}", e);
|
||||||
IpAddr::V4(ip) => ip,
|
}
|
||||||
IpAddr::V6(ip) => {
|
}
|
||||||
if let Some(ip) = ip.to_ipv4_mapped() {
|
Ok(true)
|
||||||
ip
|
} else {
|
||||||
} else {
|
Ok(false)
|
||||||
return Ok(false);
|
}
|
||||||
}
|
}
|
||||||
}
|
fn recv_data_(
|
||||||
};
|
&self,
|
||||||
'a: for stun_server in &self.stun_server {
|
index: usize,
|
||||||
for x in stun_server.to_socket_addrs()? {
|
source_addr: SocketAddr,
|
||||||
if source_addr.port() == x.port() {
|
addr: SocketAddr,
|
||||||
if let IpAddr::V4(ip) = x.ip() {
|
) -> anyhow::Result<()> {
|
||||||
if ip == source_ip {
|
if let SocketAddr::V4(addr) = addr {
|
||||||
check_fail = false;
|
let mut check_fail = true;
|
||||||
break 'a;
|
let source_ip = match source_addr.ip() {
|
||||||
}
|
IpAddr::V4(ip) => ip,
|
||||||
};
|
IpAddr::V6(ip) => {
|
||||||
}
|
if let Some(ip) = ip.to_ipv4_mapped() {
|
||||||
|
ip
|
||||||
|
} else {
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if check_fail {
|
};
|
||||||
return Ok(false);
|
'a: for stun_server in &self.stun_server {
|
||||||
|
for x in stun_server.to_socket_addrs()? {
|
||||||
|
if source_addr.port() == x.port() {
|
||||||
|
if let IpAddr::V4(ip) = x.ip() {
|
||||||
|
if ip == source_ip {
|
||||||
|
check_fail = false;
|
||||||
|
break 'a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if !check_fail {
|
||||||
let ip = addr.ip();
|
let ip = addr.ip();
|
||||||
if !ip.is_multicast()
|
if !ip.is_multicast()
|
||||||
&& !ip.is_broadcast()
|
&& !ip.is_broadcast()
|
||||||
@@ -260,10 +274,9 @@ impl NatTest {
|
|||||||
&& !ip.is_private()
|
&& !ip.is_private()
|
||||||
{
|
{
|
||||||
self.update_addr(index, *addr.ip(), addr.port());
|
self.update_addr(index, *addr.ip(), addr.port());
|
||||||
return Ok(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok(false);
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-8
@@ -71,11 +71,15 @@ pub fn stun_test_nat0(stun_servers: Vec<String>) -> io::Result<(NatType, Vec<Ipv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok((
|
if hash_set.is_empty() {
|
||||||
nat_type,
|
Ok((nat_type, vec![], 0))
|
||||||
hash_set.into_iter().collect(),
|
} else {
|
||||||
max_port - min_port,
|
Ok((
|
||||||
))
|
nat_type,
|
||||||
|
hash_set.into_iter().collect(),
|
||||||
|
max_port - min_port,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_nat(udp: &UdpSocket, stun_server: &String) -> io::Result<HashSet<SocketAddr>> {
|
fn test_nat(udp: &UdpSocket, stun_server: &String) -> io::Result<HashSet<SocketAddr>> {
|
||||||
@@ -194,9 +198,6 @@ pub fn send_stun_request() -> Vec<u8> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_stun_response(buf: &[u8]) -> Option<SocketAddr> {
|
pub fn recv_stun_response(buf: &[u8]) -> Option<SocketAddr> {
|
||||||
if buf[0] != 0x01 && buf[1] != 0x01 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let msg = stun_format::Msg::from(buf);
|
let msg = stun_format::Msg::from(buf);
|
||||||
if let Some(tid) = msg.tid() {
|
if let Some(tid) = msg.tid() {
|
||||||
if tid & TAG != TAG {
|
if tid & TAG != TAG {
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ pub async fn tcp_mapping(bind_addr: SocketAddr, destination: String) -> anyhow::
|
|||||||
let tcp_listener = TcpListener::bind(bind_addr)
|
let tcp_listener = TcpListener::bind(bind_addr)
|
||||||
.await
|
.await
|
||||||
.with_context(|| format!("TCP binding {:?} failed", bind_addr))?;
|
.with_context(|| format!("TCP binding {:?} failed", bind_addr))?;
|
||||||
tokio::spawn(tcp_mapping_(bind_addr, tcp_listener, destination));
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = tcp_mapping_(bind_addr, tcp_listener, destination).await {
|
||||||
|
log::warn!("tcp_mapping {:?}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,261 @@ pub const ENCRYPTION_RESERVED: usize = 16 + 32 + 12;
|
|||||||
pub const AES_GCM_ENCRYPTION_RESERVED: usize = 32;
|
pub const AES_GCM_ENCRYPTION_RESERVED: usize = 32;
|
||||||
pub const RSA_ENCRYPTION_RESERVED: usize = 32;
|
pub const RSA_ENCRYPTION_RESERVED: usize = 32;
|
||||||
|
|
||||||
|
pub const RANDOM_RESERVED: usize = 4;
|
||||||
|
pub const FINGER_RESERVED: usize = 12;
|
||||||
|
pub const TAG_RESERVED: usize = 16;
|
||||||
|
|
||||||
|
/*
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| random(32) |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| finger(32) |
|
||||||
|
| finger(32) |
|
||||||
|
| finger(32) |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
*/
|
||||||
|
pub trait SecretTail {
|
||||||
|
fn buffer(&self) -> &[u8];
|
||||||
|
fn exist_finger(&self) -> bool;
|
||||||
|
fn random_buf(&self) -> &[u8] {
|
||||||
|
let buf = self.buffer();
|
||||||
|
let mut end = buf.len();
|
||||||
|
if self.exist_finger() {
|
||||||
|
end -= FINGER_RESERVED;
|
||||||
|
}
|
||||||
|
&buf[end - RANDOM_RESERVED..end]
|
||||||
|
}
|
||||||
|
fn finger(&self) -> &[u8] {
|
||||||
|
if self.exist_finger() {
|
||||||
|
let buf = self.buffer();
|
||||||
|
let end = buf.len();
|
||||||
|
&buf[end - FINGER_RESERVED..end]
|
||||||
|
} else {
|
||||||
|
&[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait SecretTailMut: SecretTail {
|
||||||
|
fn buffer_mut(&mut self) -> &mut [u8];
|
||||||
|
fn set_random(&mut self, random: &[u8]) {
|
||||||
|
let f = self.exist_finger();
|
||||||
|
let buf = self.buffer_mut();
|
||||||
|
let mut end = buf.len();
|
||||||
|
if f {
|
||||||
|
end -= FINGER_RESERVED;
|
||||||
|
}
|
||||||
|
buf[end - RANDOM_RESERVED..end].copy_from_slice(random);
|
||||||
|
}
|
||||||
|
fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> {
|
||||||
|
if self.exist_finger() {
|
||||||
|
if finger.len() != FINGER_RESERVED {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidData,
|
||||||
|
"finger.len != 12",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let buf = self.buffer_mut();
|
||||||
|
let end = buf.len();
|
||||||
|
buf[end - FINGER_RESERVED..end].copy_from_slice(finger);
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidData,
|
||||||
|
"not exist finger",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* aead加密数据体
|
||||||
|
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
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| 数据体 |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| tag(32) |
|
||||||
|
| tag(32) |
|
||||||
|
| tag(32) |
|
||||||
|
| tag(32) |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| random(32) |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| finger(32) |
|
||||||
|
| finger(32) |
|
||||||
|
| finger(32) |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
注:finger用于快速校验数据是否被修改,上层可使用token、协议头参与计算finger,
|
||||||
|
确保服务端和客户端都能感知修改(服务端不能解密也能校验指纹)
|
||||||
|
*/
|
||||||
|
pub struct AEADSecretBody<B> {
|
||||||
|
buffer: B,
|
||||||
|
exist_finger: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: AsRef<[u8]>> AEADSecretBody<B> {
|
||||||
|
pub fn new(buffer: B, exist_finger: bool) -> io::Result<AEADSecretBody<B>> {
|
||||||
|
let len = buffer.as_ref().len();
|
||||||
|
let min_len = if exist_finger {
|
||||||
|
TAG_RESERVED + RANDOM_RESERVED + FINGER_RESERVED
|
||||||
|
} else {
|
||||||
|
TAG_RESERVED + RANDOM_RESERVED
|
||||||
|
};
|
||||||
|
// 不能大于udp最大载荷长度
|
||||||
|
if len < min_len || len > 65535 - 20 - 8 - 12 {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidData,
|
||||||
|
format!("AEADSecretBody length overflow {}", len),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(AEADSecretBody {
|
||||||
|
buffer,
|
||||||
|
exist_finger,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn data(&self) -> &[u8] {
|
||||||
|
let mut end = self.buffer.as_ref().len() - TAG_RESERVED - RANDOM_RESERVED;
|
||||||
|
if self.exist_finger {
|
||||||
|
end -= FINGER_RESERVED;
|
||||||
|
}
|
||||||
|
&self.buffer.as_ref()[..end]
|
||||||
|
}
|
||||||
|
pub fn tag(&self) -> &[u8] {
|
||||||
|
let mut end = self.buffer.as_ref().len() - RANDOM_RESERVED;
|
||||||
|
if self.exist_finger {
|
||||||
|
end -= FINGER_RESERVED;
|
||||||
|
}
|
||||||
|
&self.buffer.as_ref()[end - TAG_RESERVED..end]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: AsRef<[u8]>> SecretTail for AEADSecretBody<B> {
|
||||||
|
#[inline]
|
||||||
|
fn buffer(&self) -> &[u8] {
|
||||||
|
self.buffer.as_ref()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn exist_finger(&self) -> bool {
|
||||||
|
self.exist_finger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: AsRef<[u8]> + AsMut<[u8]>> SecretTailMut for AEADSecretBody<B> {
|
||||||
|
#[inline]
|
||||||
|
fn buffer_mut(&mut self) -> &mut [u8] {
|
||||||
|
self.buffer.as_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: AsRef<[u8]> + AsMut<[u8]>> AEADSecretBody<B> {
|
||||||
|
/// 数据部分
|
||||||
|
pub fn data_mut(&mut self) -> &mut [u8] {
|
||||||
|
let mut end = self.buffer.as_ref().len() - RANDOM_RESERVED - TAG_RESERVED;
|
||||||
|
if self.exist_finger {
|
||||||
|
end -= FINGER_RESERVED;
|
||||||
|
}
|
||||||
|
&mut self.buffer.as_mut()[..end]
|
||||||
|
}
|
||||||
|
/// 数据和tag部分
|
||||||
|
pub fn data_tag_mut(&mut self) -> &mut [u8] {
|
||||||
|
let mut end = self.buffer.as_ref().len() - RANDOM_RESERVED;
|
||||||
|
if self.exist_finger {
|
||||||
|
end -= FINGER_RESERVED;
|
||||||
|
}
|
||||||
|
&mut self.buffer.as_mut()[..end]
|
||||||
|
}
|
||||||
|
pub fn set_tag(&mut self, tag: &[u8]) -> io::Result<()> {
|
||||||
|
if tag.len() != 16 {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::InvalidData, "tag.len != 16"));
|
||||||
|
}
|
||||||
|
let mut end = self.buffer.as_ref().len() - RANDOM_RESERVED;
|
||||||
|
if self.exist_finger {
|
||||||
|
end -= FINGER_RESERVED;
|
||||||
|
}
|
||||||
|
self.buffer.as_mut()[end - TAG_RESERVED..end].copy_from_slice(tag);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 带随机数的加密数据体
|
||||||
|
0 15 31
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| 数据体 |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| random(32) |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| finger(32) |
|
||||||
|
| finger(32) |
|
||||||
|
| finger(32) |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
注:finger用于快速校验数据是否被修改,上层可使用token、协议头参与计算finger,
|
||||||
|
确保服务端和客户端都能感知修改(服务端不能解密也能校验指纹)
|
||||||
|
*/
|
||||||
|
pub struct IVSecretBody<B> {
|
||||||
|
buffer: B,
|
||||||
|
exist_finger: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: AsRef<[u8]>> IVSecretBody<B> {
|
||||||
|
pub fn new(buffer: B, exist_finger: bool) -> io::Result<IVSecretBody<B>> {
|
||||||
|
let len = buffer.as_ref().len();
|
||||||
|
let min_len = if exist_finger {
|
||||||
|
FINGER_RESERVED + RANDOM_RESERVED
|
||||||
|
} else {
|
||||||
|
RANDOM_RESERVED
|
||||||
|
};
|
||||||
|
// 不能大于udp最大载荷长度
|
||||||
|
if len < min_len || len > 65535 - 20 - 8 - 12 {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidData,
|
||||||
|
format!("IVSecretBody length overflow {}", len),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(IVSecretBody {
|
||||||
|
buffer,
|
||||||
|
exist_finger,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn data(&self) -> &[u8] {
|
||||||
|
let mut end = self.buffer.as_ref().len() - RANDOM_RESERVED;
|
||||||
|
if self.exist_finger {
|
||||||
|
end -= FINGER_RESERVED;
|
||||||
|
}
|
||||||
|
&self.buffer.as_ref()[..end]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: AsRef<[u8]> + AsMut<[u8]>> IVSecretBody<B> {
|
||||||
|
pub fn data_mut(&mut self) -> &mut [u8] {
|
||||||
|
let mut end = self.buffer.as_ref().len() - RANDOM_RESERVED;
|
||||||
|
if self.exist_finger {
|
||||||
|
end -= FINGER_RESERVED;
|
||||||
|
}
|
||||||
|
&mut self.buffer.as_mut()[..end]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: AsRef<[u8]>> SecretTail for IVSecretBody<B> {
|
||||||
|
#[inline]
|
||||||
|
fn buffer(&self) -> &[u8] {
|
||||||
|
self.buffer.as_ref()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn exist_finger(&self) -> bool {
|
||||||
|
self.exist_finger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: AsRef<[u8]> + AsMut<[u8]>> SecretTailMut for IVSecretBody<B> {
|
||||||
|
#[inline]
|
||||||
|
fn buffer_mut(&mut self) -> &mut [u8] {
|
||||||
|
self.buffer.as_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 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
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
/* 扩展协议
|
||||||
|
0 15 31
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| 扩展数据(n) |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| 扩展数据(n) | type(8) |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
注:扩展数据的长度由type决定
|
||||||
|
*/
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use crate::protocol::NetPacket;
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
||||||
|
pub enum ExtensionTailType {
|
||||||
|
Compression,
|
||||||
|
Unknown(u8),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for ExtensionTailType {
|
||||||
|
fn from(value: u8) -> Self {
|
||||||
|
if value == 0 {
|
||||||
|
ExtensionTailType::Compression
|
||||||
|
} else {
|
||||||
|
ExtensionTailType::Unknown(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ExtensionTailPacket<B> {
|
||||||
|
Compression(CompressionExtensionTail<B>),
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
||||||
|
/// 分离尾部数据
|
||||||
|
pub fn split_tail_packet(&mut self) -> anyhow::Result<ExtensionTailPacket<&[u8]>> {
|
||||||
|
if self.is_extension() {
|
||||||
|
let payload = self.payload();
|
||||||
|
if let Some(v) = payload.last() {
|
||||||
|
return match ExtensionTailType::from(*v) {
|
||||||
|
ExtensionTailType::Compression => {
|
||||||
|
let data_len = self.data_len - 4;
|
||||||
|
self.set_data_len(data_len)?;
|
||||||
|
self.set_extension_flag(false);
|
||||||
|
Ok(ExtensionTailPacket::Compression(
|
||||||
|
CompressionExtensionTail::new(
|
||||||
|
&self.raw_buffer()[data_len..data_len + 4],
|
||||||
|
),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
ExtensionTailType::Unknown(e) => Err(anyhow!("unknown extension {}", e)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(anyhow!("not extension"))
|
||||||
|
}
|
||||||
|
/// 追加压缩扩展
|
||||||
|
pub fn append_compression_extension_tail(
|
||||||
|
&mut self,
|
||||||
|
) -> io::Result<CompressionExtensionTail<&mut [u8]>> {
|
||||||
|
let len = self.data_len;
|
||||||
|
//增加数据长度
|
||||||
|
self.set_data_len(self.data_len + 4)?;
|
||||||
|
self.set_extension_flag(true);
|
||||||
|
let mut tail = CompressionExtensionTail::new(&mut self.buffer_mut()[len..]);
|
||||||
|
tail.init();
|
||||||
|
return Ok(tail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 扩展协议
|
||||||
|
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
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| algorithm(8) | | type(8) |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
注:扩展数据的长度由type决定
|
||||||
|
*/
|
||||||
|
/// 压缩扩展
|
||||||
|
pub struct CompressionExtensionTail<B> {
|
||||||
|
buffer: B,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: AsRef<[u8]>> CompressionExtensionTail<B> {
|
||||||
|
pub fn new(buffer: B) -> CompressionExtensionTail<B> {
|
||||||
|
assert_eq!(buffer.as_ref().len(), 4);
|
||||||
|
CompressionExtensionTail { buffer }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: AsRef<[u8]>> CompressionExtensionTail<B> {
|
||||||
|
pub fn algorithm(&self) -> CompressionAlgorithm {
|
||||||
|
self.buffer.as_ref()[0].into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: AsRef<[u8]> + AsMut<[u8]>> CompressionExtensionTail<B> {
|
||||||
|
pub fn init(&mut self) {
|
||||||
|
self.buffer.as_mut().fill(0);
|
||||||
|
}
|
||||||
|
pub fn set_algorithm(&mut self, algorithm: CompressionAlgorithm) {
|
||||||
|
self.buffer.as_mut()[0] = algorithm.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
||||||
|
pub enum CompressionAlgorithm {
|
||||||
|
#[cfg(feature = "lz4_compress")]
|
||||||
|
Lz4,
|
||||||
|
#[cfg(feature = "zstd_compress")]
|
||||||
|
Zstd,
|
||||||
|
Unknown(u8),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for CompressionAlgorithm {
|
||||||
|
fn from(value: u8) -> Self {
|
||||||
|
match value {
|
||||||
|
#[cfg(feature = "lz4_compress")]
|
||||||
|
1 => CompressionAlgorithm::Lz4,
|
||||||
|
#[cfg(feature = "zstd_compress")]
|
||||||
|
2 => CompressionAlgorithm::Zstd,
|
||||||
|
v => CompressionAlgorithm::Unknown(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CompressionAlgorithm> for u8 {
|
||||||
|
fn from(value: CompressionAlgorithm) -> Self {
|
||||||
|
match value {
|
||||||
|
#[cfg(feature = "lz4_compress")]
|
||||||
|
CompressionAlgorithm::Lz4 => 1,
|
||||||
|
#[cfg(feature = "zstd_compress")]
|
||||||
|
CompressionAlgorithm::Zstd => 2,
|
||||||
|
CompressionAlgorithm::Unknown(val) => val,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
-2
@@ -6,7 +6,7 @@ use std::{fmt, io};
|
|||||||
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
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|e |s |u |u| 版本(4) | 协议(8) | 上层协议(8) | 初始ttl(4) | 生存时间(4) |
|
|e |s |x |u| 版本(4) | 协议(8) | 上层协议(8) | 初始ttl(4) | 生存时间(4) |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
| 源ip地址(32) |
|
| 源ip地址(32) |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
@@ -14,13 +14,14 @@ use std::{fmt, io};
|
|||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
| 数据体 |
|
| 数据体 |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
注:e为是否加密标志,s为服务端通信包标志,u未使用
|
注:e为是否加密标志,s为服务端通信包标志,x扩展标志,u未使用
|
||||||
*/
|
*/
|
||||||
pub const HEAD_LEN: usize = 12;
|
pub const HEAD_LEN: usize = 12;
|
||||||
|
|
||||||
pub mod body;
|
pub mod body;
|
||||||
pub mod control_packet;
|
pub mod control_packet;
|
||||||
pub mod error_packet;
|
pub mod error_packet;
|
||||||
|
pub mod extension;
|
||||||
pub mod ip_turn_packet;
|
pub mod ip_turn_packet;
|
||||||
pub mod other_turn_packet;
|
pub mod other_turn_packet;
|
||||||
pub mod service_packet;
|
pub mod service_packet;
|
||||||
@@ -101,6 +102,10 @@ pub struct NetPacket<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<B: AsRef<[u8]>> NetPacket<B> {
|
impl<B: AsRef<[u8]>> NetPacket<B> {
|
||||||
|
pub fn unchecked(buffer: B) -> Self {
|
||||||
|
let data_len = buffer.as_ref().len();
|
||||||
|
Self { data_len, buffer }
|
||||||
|
}
|
||||||
pub fn new(buffer: B) -> io::Result<NetPacket<B>> {
|
pub fn new(buffer: B) -> io::Result<NetPacket<B>> {
|
||||||
let data_len = buffer.as_ref().len();
|
let data_len = buffer.as_ref().len();
|
||||||
Self::new0(data_len, buffer)
|
Self::new0(data_len, buffer)
|
||||||
@@ -132,6 +137,7 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
|
|||||||
}
|
}
|
||||||
Ok(NetPacket { data_len, buffer })
|
Ok(NetPacket { data_len, buffer })
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
pub fn buffer(&self) -> &[u8] {
|
pub fn buffer(&self) -> &[u8] {
|
||||||
&self.buffer.as_ref()[..self.data_len]
|
&self.buffer.as_ref()[..self.data_len]
|
||||||
}
|
}
|
||||||
@@ -158,6 +164,10 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
|
|||||||
pub fn is_gateway(&self) -> bool {
|
pub fn is_gateway(&self) -> bool {
|
||||||
self.buffer.as_ref()[0] & 0x40 == 0x40
|
self.buffer.as_ref()[0] & 0x40 == 0x40
|
||||||
}
|
}
|
||||||
|
/// 扩展协议
|
||||||
|
pub fn is_extension(&self) -> bool {
|
||||||
|
self.buffer.as_ref()[0] & 0x20 == 0x20
|
||||||
|
}
|
||||||
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)
|
||||||
}
|
}
|
||||||
@@ -190,6 +200,9 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
||||||
|
pub fn head_mut(&mut self) -> &mut [u8] {
|
||||||
|
&mut self.buffer.as_mut()[..12]
|
||||||
|
}
|
||||||
pub fn buffer_mut(&mut self) -> &mut [u8] {
|
pub fn buffer_mut(&mut self) -> &mut [u8] {
|
||||||
&mut self.buffer.as_mut()[..self.data_len]
|
&mut self.buffer.as_mut()[..self.data_len]
|
||||||
}
|
}
|
||||||
@@ -208,6 +221,13 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
|||||||
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF
|
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
pub fn set_extension_flag(&mut self, is_extension: bool) {
|
||||||
|
if is_extension {
|
||||||
|
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x20
|
||||||
|
} else {
|
||||||
|
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xDF
|
||||||
|
};
|
||||||
|
}
|
||||||
pub fn set_default_version(&mut self) {
|
pub fn set_default_version(&mut self) {
|
||||||
let v: u8 = Version::V2.into();
|
let v: u8 = Version::V2.into();
|
||||||
self.buffer.as_mut()[0] = (self.buffer.as_ref()[0] & 0xF0) | (0x0F & v);
|
self.buffer.as_mut()[0] = (self.buffer.as_ref()[0] & 0xF0) | (0x0F & v);
|
||||||
@@ -264,6 +284,10 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
|||||||
self.data_len = data_len;
|
self.data_len = data_len;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
pub fn set_payload_len(&mut self, payload_len: usize) -> io::Result<()> {
|
||||||
|
let data_len = HEAD_LEN + payload_len;
|
||||||
|
self.set_data_len(data_len)
|
||||||
|
}
|
||||||
pub fn set_data_len_max(&mut self) {
|
pub fn set_data_len_max(&mut self) {
|
||||||
self.data_len = self.buffer.as_ref().len();
|
self.data_len = self.buffer.as_ref().len();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ use tun::Device;
|
|||||||
|
|
||||||
use crate::channel::context::ChannelContext;
|
use crate::channel::context::ChannelContext;
|
||||||
use crate::cipher::Cipher;
|
use crate::cipher::Cipher;
|
||||||
|
use crate::compression::Compressor;
|
||||||
use crate::external_route::ExternalRoute;
|
use crate::external_route::ExternalRoute;
|
||||||
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
|
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
use crate::ip_proxy::IpProxyMap;
|
use crate::ip_proxy::IpProxyMap;
|
||||||
use crate::util::{SingleU64Adder, StopManager};
|
use crate::util::{SingleU64Adder, StopManager};
|
||||||
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
@@ -77,6 +79,7 @@ struct TunDeviceHelperInner {
|
|||||||
parallel: usize,
|
parallel: usize,
|
||||||
up_counter: SingleU64Adder,
|
up_counter: SingleU64Adder,
|
||||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||||
|
compressor: Compressor,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TunDeviceHelper {
|
impl TunDeviceHelper {
|
||||||
@@ -91,6 +94,7 @@ impl TunDeviceHelper {
|
|||||||
parallel: usize,
|
parallel: usize,
|
||||||
up_counter: SingleU64Adder,
|
up_counter: SingleU64Adder,
|
||||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||||
|
compressor: Compressor,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Arc::new(AtomicCell::new(Some(TunDeviceHelperInner {
|
inner: Arc::new(AtomicCell::new(Some(TunDeviceHelperInner {
|
||||||
@@ -98,12 +102,14 @@ impl TunDeviceHelper {
|
|||||||
context,
|
context,
|
||||||
current_device,
|
current_device,
|
||||||
ip_route,
|
ip_route,
|
||||||
|
#[cfg(feature = "ip_proxy")]
|
||||||
ip_proxy_map,
|
ip_proxy_map,
|
||||||
client_cipher,
|
client_cipher,
|
||||||
server_cipher,
|
server_cipher,
|
||||||
parallel,
|
parallel,
|
||||||
up_counter,
|
up_counter,
|
||||||
device_list,
|
device_list,
|
||||||
|
compressor,
|
||||||
}))),
|
}))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,6 +128,7 @@ impl TunDeviceHelper {
|
|||||||
inner.parallel,
|
inner.parallel,
|
||||||
inner.up_counter,
|
inner.up_counter,
|
||||||
inner.device_list,
|
inner.device_list,
|
||||||
|
inner.compressor,
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+12
-12
@@ -41,9 +41,10 @@ pub fn address_choose(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
|
|||||||
/// 后续实现选择延迟最低的可用地址,需要服务端配合
|
/// 后续实现选择延迟最低的可用地址,需要服务端配合
|
||||||
/// 现在是选择第一个地址,优先ipv6
|
/// 现在是选择第一个地址,优先ipv6
|
||||||
fn address_choose0(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
|
fn address_choose0(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
|
||||||
let v4: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv4()).map(|v| *v).collect();
|
let v4: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv4()).copied().collect();
|
||||||
let v6: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv6()).map(|v| *v).collect();
|
let v6: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv6()).copied().collect();
|
||||||
let check_addr = |addrs: &Vec<SocketAddr>| -> anyhow::Result<SocketAddr> {
|
let check_addr = |addrs: &Vec<SocketAddr>| -> anyhow::Result<SocketAddr> {
|
||||||
|
let mut err = Vec::new();
|
||||||
if !addrs.is_empty() {
|
if !addrs.is_empty() {
|
||||||
let udp = if addrs[0].is_ipv6() {
|
let udp = if addrs[0].is_ipv6() {
|
||||||
UdpSocket::bind("[::]:0")?
|
UdpSocket::bind("[::]:0")?
|
||||||
@@ -51,12 +52,14 @@ fn address_choose0(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
|
|||||||
UdpSocket::bind("0.0.0.0:0")?
|
UdpSocket::bind("0.0.0.0:0")?
|
||||||
};
|
};
|
||||||
for addr in addrs {
|
for addr in addrs {
|
||||||
if udp.connect(addr).is_ok() {
|
if let Err(e) = udp.connect(addr) {
|
||||||
|
err.push((*addr, e));
|
||||||
|
} else {
|
||||||
return Ok(*addr);
|
return Ok(*addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(anyhow::anyhow!("Unable to connect to address {:?}", addrs))
|
Err(anyhow::anyhow!("Unable to connect to address {:?}", err))
|
||||||
};
|
};
|
||||||
if v6.is_empty() {
|
if v6.is_empty() {
|
||||||
return check_addr(&v4);
|
return check_addr(&v4);
|
||||||
@@ -78,9 +81,7 @@ pub fn dns_query_all(
|
|||||||
mut name_servers: Vec<String>,
|
mut name_servers: Vec<String>,
|
||||||
) -> anyhow::Result<Vec<SocketAddr>> {
|
) -> anyhow::Result<Vec<SocketAddr>> {
|
||||||
match SocketAddr::from_str(domain) {
|
match SocketAddr::from_str(domain) {
|
||||||
Ok(addr) => {
|
Ok(addr) => Ok(vec![addr]),
|
||||||
return Ok(vec![addr]);
|
|
||||||
}
|
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let txt_domain = domain
|
let txt_domain = domain
|
||||||
.to_lowercase()
|
.to_lowercase()
|
||||||
@@ -94,7 +95,6 @@ pub fn dns_query_all(
|
|||||||
return Ok(domain
|
return Ok(domain
|
||||||
.to_socket_addrs()
|
.to_socket_addrs()
|
||||||
.with_context(|| format!("DNS query failed {:?}", domain))?
|
.with_context(|| format!("DNS query failed {:?}", domain))?
|
||||||
.into_iter()
|
|
||||||
.collect());
|
.collect());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ pub fn dns_query_all(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let end_index = domain
|
let end_index = domain
|
||||||
.rfind(":")
|
.rfind(':')
|
||||||
.with_context(|| format!("{:?} not port", domain))?;
|
.with_context(|| format!("{:?} not port", domain))?;
|
||||||
let host = &domain[..end_index];
|
let host = &domain[..end_index];
|
||||||
let port = u16::from_str(&domain[end_index + 1..])
|
let port = u16::from_str(&domain[end_index + 1..])
|
||||||
@@ -219,7 +219,7 @@ fn query<'a>(
|
|||||||
domain
|
domain
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if pkt.answers.len() == 0 {
|
if pkt.answers.is_empty() {
|
||||||
return Err(anyhow::anyhow!(
|
return Err(anyhow::anyhow!(
|
||||||
"No records received DNS {:?} domain {:?}",
|
"No records received DNS {:?} domain {:?}",
|
||||||
name_server,
|
name_server,
|
||||||
@@ -240,8 +240,8 @@ pub fn txt_dns(domain: &str, name_server: String) -> anyhow::Result<Vec<SocketAd
|
|||||||
if let RData::TXT(txt) = record.data {
|
if let RData::TXT(txt) = record.data {
|
||||||
for x in txt.iter() {
|
for x in txt.iter() {
|
||||||
let txt = std::str::from_utf8(x).context("record type txt is not string")?;
|
let txt = std::str::from_utf8(x).context("record type txt is not string")?;
|
||||||
let addr = SocketAddr::from_str(&txt.to_string())
|
let addr =
|
||||||
.context("record type txt is not SocketAddr")?;
|
SocketAddr::from_str(txt).context("record type txt is not SocketAddr")?;
|
||||||
rs.push(addr);
|
rs.push(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::thread;
|
||||||
use std::thread::Thread;
|
use std::thread::Thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{io, thread};
|
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -20,7 +21,7 @@ impl StopManager {
|
|||||||
inner: Arc::new(StopManagerInner::new(f)),
|
inner: Arc::new(StopManagerInner::new(f)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn add_listener<F>(&self, name: String, f: F) -> io::Result<Worker>
|
pub fn add_listener<F>(&self, name: String, f: F) -> anyhow::Result<Worker>
|
||||||
where
|
where
|
||||||
F: FnOnce() + Send + 'static,
|
F: FnOnce() + Send + 'static,
|
||||||
{
|
{
|
||||||
@@ -61,23 +62,20 @@ impl StopManagerInner {
|
|||||||
stop_call: Mutex::new(Some(Box::new(f))),
|
stop_call: Mutex::new(Some(Box::new(f))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn add_listener<F>(self: &Arc<Self>, name: String, f: F) -> io::Result<Worker>
|
fn add_listener<F>(self: &Arc<Self>, name: String, f: F) -> anyhow::Result<Worker>
|
||||||
where
|
where
|
||||||
F: FnOnce() + Send + 'static,
|
F: FnOnce() + Send + 'static,
|
||||||
{
|
{
|
||||||
if name.is_empty() {
|
if name.is_empty() {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "name cannot be empty"));
|
return Err(anyhow!("name cannot be empty"));
|
||||||
}
|
}
|
||||||
let mut guard = self.listeners.lock();
|
let mut guard = self.listeners.lock();
|
||||||
if guard.0 {
|
if guard.0 {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "stopped"));
|
return Err(anyhow!("stopped"));
|
||||||
}
|
}
|
||||||
for (n, _) in &guard.1 {
|
for (n, _) in &guard.1 {
|
||||||
if &name == n {
|
if &name == n {
|
||||||
return Err(io::Error::new(
|
return Err(anyhow!("stop add_listener {:?} name already exists", name));
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("stop add_listener {:?} name already exists", name),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
guard.1.push((name.clone(), Box::new(f)));
|
guard.1.push((name.clone(), Box::new(f)));
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ use crate::util::StopManager;
|
|||||||
use std::collections::BinaryHeap;
|
use std::collections::BinaryHeap;
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
io,
|
|
||||||
sync::mpsc::{sync_channel, Receiver, SyncSender},
|
sync::mpsc::{sync_channel, Receiver, SyncSender},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
@@ -36,7 +35,7 @@ pub struct Scheduler {
|
|||||||
sender: SyncSender<Op>,
|
sender: SyncSender<Op>,
|
||||||
}
|
}
|
||||||
impl Scheduler {
|
impl Scheduler {
|
||||||
pub fn new(stop_manager: StopManager) -> io::Result<Self> {
|
pub fn new(stop_manager: StopManager) -> anyhow::Result<Self> {
|
||||||
let (sender, receiver) = sync_channel::<Op>(32);
|
let (sender, receiver) = sync_channel::<Op>(32);
|
||||||
let s = Self { sender };
|
let s = Self { sender };
|
||||||
let s_inner = s.clone();
|
let s_inner = s.clone();
|
||||||
|
|||||||
Reference in New Issue
Block a user