Compare commits

...
75 Commits
Author SHA1 Message Date
lubeilin 858ca9bbe7 去除udp通道的arc包装 2023-12-30 22:15:48 +08:00
lubeilin cbc4a7378c 优化tcp通道 2023-12-30 21:39:53 +08:00
lubeilin ee34f525e6 nat地址判断 2023-12-30 13:07:54 +08:00
lubeilin 698e2531e8 增加参数校验 2023-12-30 12:00:47 +08:00
lubeilin 16f833ec72 优化延迟优先参数 2023-12-28 23:18:57 +08:00
lubeilin 94d6caef7e 修复连接tcp地址的问题 2023-12-26 22:27:16 +08:00
lubeilin 364012f9dd fmt 2023-12-26 21:47:01 +08:00
lubeilin cf4b1f418f 忽略地址校验 2023-12-26 21:46:41 +08:00
lubeilin c6465977ef 将ipv4转换成ipv6 2023-12-26 21:46:23 +08:00
lubeilin c577e6381f 将ipv4转换成ipv6 2023-12-25 23:06:47 +08:00
lubeilin 134e31f563 fmt 2023-12-24 13:42:41 +08:00
lubeilin 0580b89f48 升级版本号 2023-12-24 12:22:34 +08:00
lubeilin 37080af275 支持ipv6服务端 2023-12-24 12:00:44 +08:00
lubeilin 26d68ac059 版本改为1.2.7 2023-10-31 20:49:25 +08:00
lubeilin 6292c1c381 去除溢出检查 2023-10-31 20:49:16 +08:00
lubeilin b0c3f25a29 使用读写锁简化操作,增加延迟优先选项 2023-10-31 20:48:38 +08:00
lubeilin d2e09d3da5 增加配置文件的参数说明 2023-10-11 20:46:39 +08:00
lbl8603 293c5b90a4 Merge pull request #22 from taotieren/contrib
Update README.md
2023-10-11 09:19:37 +08:00
taotieren e2323361f9 Update README.md 2023-10-10 23:23:25 +08:00
lbl8603 d05cff99ee Merge pull request #21 from taotieren/aur
Update README.md
2023-10-10 22:52:30 +08:00
taotieren e9b1b2ef3b Update README.md 2023-10-10 22:31:38 +08:00
lbl8603 a8ea2c14fc Merge pull request #20 from taotieren/aur
Add AUR vnt-git
2023-10-10 22:22:10 +08:00
taotieren 0688cb4515 Add AUR vnt-git 2023-10-10 22:18:37 +08:00
lubeilin c3261d7a57 修改版本为1.2.6 2023-10-09 21:20:10 +08:00
lubeilin ef8d13f61b 编译features增加ring 2023-10-09 20:56:58 +08:00
lubeilin fc104d5dee 增加参数关闭ip代理 2023-10-09 20:56:04 +08:00
lubeilin 9ad0525216 减少复制 2023-10-08 20:52:12 +08:00
lubeilin 3ea1250b53 完善编译和参数说明 2023-10-08 20:03:14 +08:00
lubeilin 9df34207f7 解决不同features编译时告警的问题 2023-10-08 17:46:31 +08:00
lubeilin dacce892ff 可选ip代理,关闭后可使用外部命令来进行ip转发 2023-10-08 17:16:02 +08:00
lubeilin a9495f1d30 升级tap相关依赖 2023-10-06 22:44:02 +08:00
lubeilin 0892c6eee9 修复进程异常退出的问题 2023-10-06 22:25:30 +08:00
lubeilin f746eadcf1 fmt 2023-10-06 22:22:35 +08:00
lubeilin da2371541c 修改依赖版本 2023-10-06 22:22:22 +08:00
lubeilin cca91d4331 tcp改为使用同步方法 2023-10-06 22:21:29 +08:00
lubeilin 11aa3b1d2c 修改features说明 2023-09-28 10:35:50 +08:00
lubeilin d0b0c61a03 Merge remote-tracking branch 'origin/main' 2023-09-28 10:27:10 +08:00
lubeilin b0501db4e5 修改features说明 2023-09-28 10:26:38 +08:00
lubeilin 465a5c75ae 修改默认features 2023-09-28 10:05:52 +08:00
lbl8603 978460aca8 更新 README.md 2023-09-27 23:51:52 +08:00
lubeilin 4b86752c79 去除不必要的features 2023-09-27 19:59:50 +08:00
lubeilin bd61cad7b6 加密算法可选 2023-09-27 19:51:23 +08:00
lubeilin 40cbd2e26b 更新参数说明 2023-09-26 21:56:04 +08:00
lubeilin 2cab580b4e 更新版本 2023-09-26 21:53:55 +08:00
lubeilin 3d243fb01d 支持读取配置文件和自定义端口 2023-09-26 21:53:41 +08:00
lubeilin ca4e8d14f0 支持sm4-cbc加密 2023-09-26 21:53:07 +08:00
lubeilin 9c098c55c9 调整长度判断 2023-09-26 21:51:56 +08:00
lubeilin 707b07b8d3 ipv6改为完整地址 2023-09-24 15:42:19 +08:00
lubeilin de5a6971f0 更新读取时间不需要再插入 2023-09-24 14:58:03 +08:00
lubeilin 056036c4d2 减少注册和探测nat的频率 2023-09-24 14:53:37 +08:00
lubeilin 1cfb188845 去除多余依赖 2023-09-24 13:45:47 +08:00
lubeilin 73a2c31854 连接通过关闭同时关闭tap 2023-09-24 13:42:09 +08:00
lubeilin 92eea536f8 删除多余依赖 2023-09-24 12:57:49 +08:00
lubeilin 00936a923e 避免直接关闭网卡 2023-09-24 12:55:42 +08:00
lubeilin ba69ba78af 增加线程名称 2023-09-23 23:09:37 +08:00
lubeilin 17b206bace 1.2.4.3 2023-09-23 21:38:31 +08:00
lubeilin 58d5a4f5da 增加wintun日志 2023-09-23 21:38:20 +08:00
lubeilin 2438d14175 避免短时间重复上传服务端密钥 2023-09-23 21:33:00 +08:00
lubeilin 99f8526799 去除tap广播路由 2023-09-22 22:49:05 +08:00
lubeilin 56fcbd64ed 增加日志 2023-09-22 22:43:23 +08:00
lubeilin 3766b2b7c1 修改命令超时时间 2023-09-22 22:43:02 +08:00
lubeilin baf0698fe4 去除广播路由 2023-09-22 22:17:13 +08:00
lubeilin 301938b9fc 增加小版本 2023-09-22 18:19:13 +08:00
lubeilin 16a37c713a 增加日志 2023-09-22 18:18:29 +08:00
lubeilin d412a769dd fmt 2023-09-22 18:18:10 +08:00
lubeilin c8eecc87fd 调整心跳间隔,服务端和客户端心跳分离 2023-09-22 18:17:12 +08:00
lubeilin 6a11db70c8 调整代理超时时间 2023-09-22 18:16:06 +08:00
lubeilin d7c121a756 commit:
1.去除缓冲池
2.数据处理改为同步方法
3.fmt
2023-09-20 19:54:49 +08:00
lubeilin 3429ee8bd6 增加提示 2023-09-20 16:03:25 +08:00
lubeilin 4422f9f8b7 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	vnt/src/ip_proxy/tcp_proxy.rs
2023-09-20 15:39:54 +08:00
lubeilin 57ed454c93 修复内网ip断线问题 2023-09-20 11:11:31 +08:00
lubeilin 236205c0f3 修复内网ip断线问题 2023-09-19 18:25:14 +08:00
lubeilin 99b4bf0041 Merge remote-tracking branch 'origin/main' 2023-09-18 21:51:17 +08:00
lubeilin 9495e39700 优化nat校验 2023-09-18 21:51:08 +08:00
lbl8603 75e244e3a8 Update README.md 2023-09-18 11:17:21 +08:00
52 changed files with 2182 additions and 1283 deletions
+3 -3
View File
@@ -47,13 +47,13 @@ jobs:
FEATURES: ring-cipher,openssl-vendored
- TARGET: aarch64-unknown-linux-musl # tested on aws t4g.nano in alpine container
OS: ubuntu-latest
FEATURES: default
FEATURES: ring-cipher,openssl-vendored
- TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested
OS: ubuntu-latest
FEATURES: openssl-vendored
- TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested
OS: ubuntu-latest
FEATURES: openssl-vendored
FEATURES: ring-cipher,openssl-vendored
- TARGET: x86_64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
OS: macos-latest
FEATURES: ring-cipher,openssl-vendored
@@ -68,7 +68,7 @@ jobs:
FEATURES: ring-cipher,openssl-vendored
- TARGET: mipsel-unknown-linux-musl # openwrt
OS: ubuntu-latest
FEATURES: openssl-vendored
FEATURES: openssl-vendored,ring-cipher
- TARGET: mips-unknown-linux-musl # openwrt
OS: ubuntu-latest
FEATURES: openssl-vendored
-1
View File
@@ -6,7 +6,6 @@ opt-level = 'z'
debug = 0
debug-assertions = false
strip= "debuginfo"
overflow-checks = true
lto = true
panic = 'abort'
incremental = false
+116 -6
View File
@@ -3,7 +3,9 @@
A virtual network tool (VPN)
将不同网络下的多个设备虚拟到一个局域网下
### vnt-cli参数详解 [参数说明](https://github.com/lbl8603/vnt/blob/main/vnt-cli/README.md)
### 快速使用:
1. 指定一个token,在多台设备上运行该程序,例如:
@@ -61,14 +63,104 @@ A virtual network tool (VPN)
前提条件:安装rust编译环境([install rust](https://www.rust-lang.org/zh-CN/tools/install))
```
到项目根目录下执行 cargo build -p vnt-cli
也可按需编译,将得到更小的二进制文件,使用--no-default-features排除默认features
cargo build -p vnt-cli --no-default-features
```
features说明
| feature | 说明 | 是否默认 |
|------------------|----------------------|------|
| openssl | 使用openssl中的aes_ecb算法 | 否 |
| openssl-vendored | 从源码编译openssl | 否 |
| ring-cipher | 使用ring中的aes_gcm算法 | 否 |
| aes_cbc | 支持aes_cbc加密 | 是 |
| aes_ecb | 支持aes_ecb加密 | 是 |
| aes_gcm | 支持aes_gcm加密 | 是 |
| sm4_cbc | 支持sm4_cbc加密 | 是 |
| server_encrypt | 支持服务端加密 | 是 |
| ip_proxy | 内置ip代理 | 是 |
如果编译时去除了内置的ip代理(或使用--no-proxy关闭了代理),则可以使用网卡NAT转发来实现点对网,
一般来说使用网卡NAT转发会比内置的ip代理性能更好
<details> <summary>NAT配置可参考如下示例,点击展开</summary>
### 在出口一端做如下配置
注意原有的-i(入口)和-o(出口)的参数不能少
### windows
参考 https://learn.microsoft.com/zh-cn/virtualization/hyper-v-on-windows/user-guide/setup-nat-network
```shell
#设置nat,名字可以自己取,网段是vnt的网段
New-NetNat -Name vntnat -InternalIPInterfaceAddressPrefix 10.26.0.0/24
#查看设置
Get-NetNat
```
### linux
```shell
# 开启ip转发
sudo sysctl -w net.ipv4.ip_forward=1
# 开启nat转发 表示来源10.26.0.0/24的数据通过nat映射后再从vnt-tun以外的其他网卡发出去
sudo iptables -t nat -A POSTROUTING ! -o vnt-tun -s 10.26.0.0/24 -j MASQUERADE
# 或者这样 表示来源10.26.0.0/24的数据通过nat映射后再从eth0网卡发出去
sudo iptables -t nat -A POSTROUTING -o eth0 -s 10.26.0.0/24 -j MASQUERADE
# 查看设置
iptables -vnL -t nat
```
### Arch Linux
[![Packaging status](https://repology.org/badge/vertical-allrepos/vnt.svg)](https://repology.org/project/vnt/versions)
- 通过 AUR 安装 [vnt-git](https://aur.archlinux.org/packages/vnt-git)
```bash
yay -Syu vnt
```
- 通过 `systemd` 设置开机自启及配置
```bash
sudo systemctl enable --now vnt-cli@
sudo systemctl status vnt-cli@
```
- 启用内置 `IPv4` 转发规则
```bash
sudo sysctl --system
```
- 通过内置防火墙文件配置防火墙转发规则
```bash
sudo cat /etc/vnt/iptables-vnt.rules >> /etc/iptables/iptables.rules
sudo iptables-restore iptables.rules
```
### macos
```shell
# 开启ip转发
sudo sysctl -w net.ipv4.ip_forward=1
# 配置NAT转发规则
# 在/etc/pf.conf文件中添加以下规则,en0是出口网卡,10.26.0.0/24是来源网段
nat on en0 from 10.26.0.0/24 to any -> (en0)
# 加载规则
sudo pfctl -f /etc/pf.conf -e
```
</details>
### 支持平台
- Mac
- Linux
- Arch Linux `yay -Syu vnt`
- 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)
- Android
- [VntApp](https://github.com/lbl8603/VntApp)
@@ -86,9 +178,11 @@ A virtual network tool (VPN)
- p2p组播/广播
- 客户端数据加密
- 服务端数据加密
### 结构
<details> <summary>展开</summary>
<pre>
0 15 31
@@ -121,8 +215,9 @@ A virtual network tool (VPN)
- 支持Ipv6(1.2.2已支持客户端之间的ipv6,待支持客户端和服务端之间的ipv6通信)
### 常见问题
<details> <summary>展开</summary>
#### 问题1: 设置网络地址失败
##### 可能原因:
@@ -138,26 +233,41 @@ vnt默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突
#### 问题2: windows系统上wintun.dll加载失败
##### 可能原因:
没有下载wintun.dll 或者使用的wintun.dll有问题
##### 解决方法:
1. 下载最新版的wintun.dll [下载链接](https://www.wintun.net/builds/wintun-0.14.1.zip)
2. 解压后找到对应架构的目录,通常是amd64
3. 将对应的wintun.dll放到和vnt-cli同目录下(或者放到C盘Windows目录下)
4. 再次启动vnt-cli
#### 问题3: 丢包严重,或是不能正常组网通信
##### 可能原因:
某些宽带下(比如广电宽带)UDP丢包严重
##### 解决方法:
1. 使用TCP模式中继转发(vnt-cli增加--tcp参数)
2. 如果p2p后效果很差,可以选择禁用p2p(vnt-cli增加--relay参数)
</details>
### 交流群
QQ:1034868233
QQ: 1034868233
### 其他
可使用社区小伙伴搭建的中继服务器
1. -s vnt.8443.eu.org:29871
### 参与贡献
<a href="https://github.com/lbl8603/vnt/graphs/contributors">
<img src="https://contrib.rocks/image?repo=lbl8603/vnt" />
</a>
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "common"
version = "1.2.3"
version = "1.2.8"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+11 -6
View File
@@ -1,20 +1,21 @@
[package]
name = "vnt-cli"
version = "1.2.3"
version = "1.2.8"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
vnt = { path = "../vnt", package = "vnt", optional = true }
vnt = { path = "../vnt", package = "vnt",default-features = false }
common = { path = "../common" }
tokio = { version = "1.32.0", features = ["full"] }
getopts = "0.2.21"
console = "0.15.2"
os_info = "3.7.0"
dirs = "4.0.0"
dirs = "5.0.1"
serde = "1.0"
serde_json = "1.0.94"
serde_yaml = "0.8.26"
log = "0.4.17"
log4rs = "1.2.0"
[dependencies.uuid]
@@ -30,11 +31,15 @@ sudo = "0.6.0"
winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] }
[features]
default = ["vnt"]
default = ["server_encrypt","aes_gcm","aes_cbc","aes_ecb","sm4_cbc","ip_proxy"]
openssl = ["vnt/openssl"]
openssl-vendored = ["vnt/openssl-vendored"]
ring-cipher = ["vnt/ring-cipher"]
aes_cbc=["vnt/aes_cbc"]
aes_ecb=["vnt/aes_ecb"]
sm4_cbc=["vnt/sm4_cbc"]
aes_gcm=["vnt/aes_gcm"]
server_encrypt=["vnt/server_encrypt"]
ip_proxy=["vnt/ip_proxy"]
[build-dependencies]
embed-manifest = "1.4.0"
+64 -5
View File
@@ -29,13 +29,18 @@
提升通信安全性,使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密(包括中继数据)。使用相同密码的客户端才能通信
| 密码位数 | 加密算法 |
|---------|-------|
| 小于8 | AES128-GCM
| 大于等于8 | AES256-GCM |
| 密码位数 | 加密算法 |
|-------|------------|
| 小于8 | AES128-GCM |
| 大于等于8 | AES256-GCM |
### -W
开启和服务端通信的数据加密,采用rsa+aes256gcm加密客户端和服务端之间通信的数据,可以避免token泄漏、中间人攻击
注意:
1. -w `<password>`是用于客户端-客户端之间的加密,password不会传递到服务端,只添加这个参数不会加密客户端-服务端通信的数据
2. -W 用于开启客户端-服务端之间的加密
### -m
模拟组播,高频使用组播通信时,可以尝试开启此参数,默认情况下会把组播当作广播发给所有节点
@@ -54,7 +59,8 @@
### --par `<parallel>`
任务并行度(必须为正整数),默认值为1,该值表示处理网卡读写的任务数,组网设备数较多、处理延迟较大时可适当调大此值
### --model `<model>`
加密模式,可选值 aes_gcm/aes_cbc/aes_ecb,默认使用aes_gcm,通常情况aes_gcm安全性高、aes_ecb性能更好
加密模式,可选值 aes_gcm/aes_cbc/aes_ecb/sm4_cbc,默认使用aes_gcm,通常情况aes_gcm安全性高、aes_ecb性能更好,但是在低性能设备上sm4_cbc也许速度会更快;
| 密码位数 | model | 加密算法 |
|-------|---------|------------|
@@ -64,9 +70,62 @@
| `>=`8 | aes_cbc | AES256-CBC |
| 1~8位 | aes_ecb | AES128-ECB |
| `>=`8 | aes_ecb | AES256-ECB |
| `>0` | sm4_cbc | SM4-CBC |
### --finger
开启数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启,开启会损耗一部分性能
注意:默认情况下服务端不会对中转的数据做校验,如果要对中转的数据做校验,则需要客户端、服务端都开启此参数
### --punch `<punch>`
取值ipv4/ipv6,选择只使用ipv4打洞或者只使用ipv6打洞,默认两则都会使用
### --port `<port>`
取值0~65535,指定本地监听的端口,默认取随机端口
### --cmd
开启交互式命令,开启后可以直接在窗口下输入命令,如需后台运行请勿开启
### --first_latency
优先使用低延迟通道,默认情况下优先使用p2p通道,某些情况下可能p2p比客户端中继延迟更高,可使用此参数进行优化传输
### --no-proxy
关闭内置的ip代理,内置的代理较为简单,而且一般来说直接使用网卡NAT转发性能会更高,
有需要可以自行配置NAT转发,[可参考‘编译’小节中的NAT配置](https://github.com/lbl8603/vnt#%E7%BC%96%E8%AF%91)
### -f `<conf>`
指定配置文件
配置文件采用yaml格式,可参考:
```yaml
# 全部参数
tap: false #是否使用tap
token: xxx #组网token
device_id: xxx #当前设备id
name: windows 11 #当前设备名称
server_address: ip:port #注册和中继服务器
stun_server: #stun服务器
- stun1.l.google.com:19302
- stun2.l.google.com:19302
in_ips: #代理ip入站
- 192.168.1.0/24,10.26.0.3
out_ips: #代理ip出站
- 0.0.0.0/0
password: xxx #密码
simulate_multicast: false #模拟组播
mtu: 1420 #mtu
tcp: false #tcp模式
ip: 10.26.0.2 #指定虚拟ip
relay: false #中继模式
server_encrypt: true #服务端加密
parallel: 1 #任务并行度
cipher_model: aes_gcm #客户端加密算法
finger: false #关闭数据指纹
punch_model: ipv4 #打洞模式
port: 0 #使用随机端口
cmd: false #关闭控制台输入
no_proxy: false #是否关闭内置代理,true为关闭
first_latency: false #是否优先低延迟通道,默认为false,表示优先使用p2p通道
```
或者需要哪个配置就加哪个,当然token是必须的
```yaml
# 部分参数
token: xxx #组网token
```
### --relay
禁用p2p,在网络环境很差时,只使用服务器中转效果可能更好(可以配合--tcp参数一起使用)
### --list
+1 -1
View File
@@ -26,7 +26,7 @@ impl CommandClient {
}
};
let udp = UdpSocket::bind("127.0.0.1:0")?;
udp.set_read_timeout(Some(Duration::from_secs(2)))?;
udp.set_read_timeout(Some(Duration::from_secs(5)))?;
udp.connect(SocketAddr::V4(SocketAddrV4::new(
Ipv4Addr::new(127, 0, 0, 1),
port,
+1 -1
View File
@@ -17,7 +17,7 @@ pub enum CommandEnum {
pub fn command(cmd: CommandEnum) {
if let Err(e) = command_(cmd) {
println!("cmd: {}", e);
println!("cmd: {:?}", e);
}
}
+7 -2
View File
@@ -17,15 +17,20 @@ impl CommandServer {
let udp = UdpSocket::bind("127.0.0.1:0").await?;
let path_buf = crate::app_home()?.join("command-port");
let mut file = std::fs::File::create(path_buf)?;
file.write_all(udp.local_addr()?.port().to_string().as_bytes())?;
let addr = udp.local_addr()?;
file.write_all(addr.port().to_string().as_bytes())?;
file.sync_all()?;
log::info!("启动后台cmd:{:?}", addr);
let mut buf = [0u8; 64];
loop {
let (len, addr) = udp.recv_from(&mut buf).await?;
match std::str::from_utf8(&buf[..len]) {
Ok(cmd) => {
log::info!("收到cmd={:?}", cmd);
if let Ok(out) = command(cmd, &vnt) {
let _ = udp.send_to(out.as_bytes(), addr).await;
if let Err(e) = udp.send_to(out.as_bytes(), addr).await {
log::warn!("cmd={},err={:?}", cmd, e);
}
if "stopped" == &out {
break;
}
+179
View File
@@ -0,0 +1,179 @@
use std::io;
use std::net::{Ipv4Addr, ToSocketAddrs};
use std::str::FromStr;
use serde::{Deserialize, Serialize};
use vnt::channel::punch::PunchModel;
use vnt::cipher::CipherModel;
use vnt::core::Config;
#[derive(Serialize, Deserialize, Debug)]
#[serde(default)]
pub struct FileConfig {
pub tap: bool,
pub token: String,
pub device_id: String,
pub name: String,
pub server_address: String,
pub stun_server: Vec<String>,
pub in_ips: Vec<String>,
pub out_ips: Vec<String>,
pub password: Option<String>,
pub simulate_multicast: bool,
pub mtu: Option<u16>,
pub tcp: bool,
pub ip: Option<String>,
pub relay: bool,
pub no_proxy: bool,
pub server_encrypt: bool,
pub parallel: usize,
pub cipher_model: String,
pub finger: bool,
pub punch_model: String,
pub port: u16,
pub cmd: bool,
pub first_latency: bool,
}
impl Default for FileConfig {
fn default() -> Self {
Self {
tap: false,
token: "".to_string(),
device_id: get_device_id(),
name: os_info::get().to_string(),
server_address: "nat1.wherewego.top:29872".to_string(),
stun_server: vec![
"stun1.l.google.com:19302".to_string(),
"stun2.l.google.com:19302".to_string(),
"stun.qq.com:3478".to_string(),
],
in_ips: vec![],
out_ips: vec![],
password: None,
simulate_multicast: false,
mtu: None,
tcp: false,
ip: None,
relay: false,
no_proxy: false,
server_encrypt: false,
parallel: 1,
cipher_model: "aes_gcm".to_string(),
finger: false,
punch_model: "".to_string(),
port: 0,
cmd: false,
first_latency: false,
}
}
}
pub fn read_config(file_path: &str) -> io::Result<(Config, bool)> {
let conf = std::fs::read_to_string(file_path)?;
let file_conf = match serde_yaml::from_str::<FileConfig>(&conf) {
Ok(val) => val,
Err(e) => {
log::error!("{:?}", e);
return Err(io::Error::new(io::ErrorKind::Other, format!("{}", e)));
}
};
if file_conf.token.is_empty() {
return Err(io::Error::new(io::ErrorKind::Other, "token is_empty"));
}
let server_address = match file_conf.server_address.to_socket_addrs() {
Ok(mut addr) => {
if let Some(addr) = addr.next() {
addr
} else {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("server_address {:?} error", &file_conf.server_address),
));
}
}
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("server_address {:?} error:{}", &file_conf.server_address, e),
));
}
};
let in_ips = match common::args_parse::ips_parse(&file_conf.in_ips) {
Ok(in_ips) => in_ips,
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("in_ips {:?} error:{}", &file_conf.in_ips, e),
));
}
};
let out_ips = match common::args_parse::out_ips_parse(&file_conf.out_ips) {
Ok(out_ips) => out_ips,
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("out_ips {:?} error:{}", &file_conf.out_ips, e),
));
}
};
let virtual_ip = match file_conf.ip.clone().map(|v| Ipv4Addr::from_str(&v)) {
None => None,
Some(r) => Some(r.map_err(|e| {
io::Error::new(
io::ErrorKind::Other,
format!("ip {:?} error:{}", &file_conf.ip, e),
)
})?),
};
let cipher_model = CipherModel::from_str(&file_conf.cipher_model)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
let punch_model = PunchModel::from_str(&file_conf.punch_model)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
let config = Config::new(
file_conf.tap,
file_conf.token,
file_conf.device_id,
file_conf.name,
server_address,
file_conf.server_address,
file_conf.stun_server,
in_ips,
out_ips,
file_conf.password,
file_conf.simulate_multicast,
file_conf.mtu,
file_conf.tcp,
virtual_ip,
file_conf.relay,
#[cfg(feature = "ip_proxy")]
file_conf.no_proxy,
file_conf.server_encrypt,
file_conf.parallel,
cipher_model,
file_conf.finger,
punch_model,
file_conf.port,
file_conf.first_latency,
)
.unwrap();
Ok((config, file_conf.cmd))
}
pub fn get_device_id() -> String {
if let Some(id) = common::identifier::get_unique_identifier() {
id
} else {
let path_buf = crate::app_home().unwrap().join("device-id");
if let Ok(id) = std::fs::read_to_string(path_buf.as_path()) {
id
} else {
let id = uuid::Uuid::new_v4().to_string();
let _ = std::fs::write(path_buf, &id);
id
}
}
}
+237 -146
View File
@@ -16,6 +16,7 @@ use vnt::handle::handshake_handler::HandshakeEnum;
use vnt::handle::registration_handler::ReqEnum;
mod command;
mod config;
mod console_out;
mod root_check;
@@ -54,12 +55,12 @@ fn main() {
opts.optopt("", "thread", "线程数(必须为正整数)", "<thread>");
opts.optopt("", "model", "加密模式", "<model>");
opts.optflag("", "finger", "指纹校验");
opts.optopt(
"",
"punch",
"取值ipv4/ipv6,表示仅使用ipv4或ipv6打洞",
"<punch>",
);
opts.optopt("", "punch", "取值ipv4/ipv6", "<punch>");
opts.optopt("", "port", "监听的端口", "<port>");
opts.optflag("", "cmd", "开启窗口输入");
opts.optflag("", "no-proxy", "关闭内置代理");
opts.optflag("", "first-latency", "优先延迟");
opts.optopt("f", "", "配置文件", "<conf>");
//"后台运行时,查看其他设备列表"
opts.optflag("", "list", "后台运行时,查看其他设备列表");
opts.optflag("", "all", "后台运行时,查看其他设备完整信息");
@@ -101,175 +102,222 @@ fn main() {
command::command(command::CommandEnum::All);
return;
}
if !matches.opt_present("k") {
print_usage(&program, opts);
println!("parameter -k not found .");
return;
}
let tap = matches.opt_present("a");
let token: String = matches.opt_get("k").unwrap().unwrap();
let device_id = matches.opt_get_default("d", String::new()).unwrap();
let device_id = if device_id.is_empty() {
if let Some(id) = common::identifier::get_unique_identifier() {
id
} else {
let path_buf = app_home().unwrap().join("device-id");
if let Ok(id) = std::fs::read_to_string(path_buf.as_path()) {
id
} else {
let id = uuid::Uuid::new_v4().to_string();
let _ = std::fs::write(path_buf, &id);
id
}
}
} else {
device_id
};
if device_id.is_empty() {
print_usage(&program, opts);
println!("parameter -d not found .");
return;
}
let name = matches
.opt_get_default("n", os_info::get().to_string())
.unwrap();
let server_address_str = matches
.opt_get_default("s", "nat1.wherewego.top:29872".to_string())
.unwrap();
let server_address = match server_address_str.to_socket_addrs() {
Ok(mut addr) => {
if let Some(addr) = addr.next() {
addr
} else {
println!("parameter '-s {}' error .", server_address_str);
let conf = matches.opt_str("f");
let (config, cmd) = if conf.is_some() {
match config::read_config(&conf.unwrap()) {
Ok(c) => c,
Err(e) => {
println!("conf err {}", e);
return;
}
}
Err(e) => {
println!("parameter '-s {}' error {}.", server_address_str, e);
} else {
if !matches.opt_present("k") {
print_usage(&program, opts);
println!("parameter -k not found .");
return;
}
};
let mut stun_server = matches.opt_strs("e");
if stun_server.is_empty() {
stun_server.push("stun1.l.google.com:19302".to_string());
stun_server.push("stun2.l.google.com:19302".to_string());
stun_server.push("stun.qq.com:3478".to_string());
}
let tap = matches.opt_present("a");
let token: String = matches.opt_get("k").unwrap().unwrap();
let device_id = matches.opt_get_default("d", String::new()).unwrap();
let device_id = if device_id.is_empty() {
config::get_device_id()
} else {
device_id
};
if device_id.is_empty() {
print_usage(&program, opts);
println!("parameter -d not found .");
return;
}
let name = matches
.opt_get_default("n", os_info::get().to_string())
.unwrap();
let server_address_str = matches
.opt_get_default("s", "nat1.wherewego.top:29872".to_string())
.unwrap();
let server_address = match server_address_str.to_socket_addrs() {
Ok(mut addr) => {
if let Some(addr) = addr.next() {
addr
} else {
println!("parameter '-s {}' error .", server_address_str);
return;
}
}
Err(e) => {
println!("parameter '-s {}' error {}.", server_address_str, e);
return;
}
};
let mut stun_server = matches.opt_strs("e");
if stun_server.is_empty() {
stun_server.push("stun1.l.google.com:19302".to_string());
stun_server.push("stun2.l.google.com:19302".to_string());
stun_server.push("stun.qq.com:3478".to_string());
}
let in_ip = matches.opt_strs("i");
let in_ip = match ips_parse(&in_ip) {
Ok(in_ip) => in_ip,
Err(e) => {
print_usage(&program, opts);
println!();
println!("-i: {:?} {}", in_ip, e);
println!("example: -i 192.168.0.0/24,10.26.0.3");
return;
}
};
let out_ip = matches.opt_strs("o");
let out_ip = match out_ips_parse(&out_ip) {
Ok(out_ip) => out_ip,
Err(e) => {
print_usage(&program, opts);
println!();
println!("-o: {:?} {}", out_ip, e);
println!("example: -o 0.0.0.0/0");
return;
}
};
let password: Option<String> = matches.opt_get("w").unwrap();
let server_encrypt = matches.opt_present("W");
let simulate_multicast = matches.opt_present("m");
let unused_cmd = matches.opt_present("c");
let mtu: Option<String> = matches.opt_get("u").unwrap();
let mtu = if let Some(mtu) = mtu {
match u16::from_str(&mtu) {
Ok(mtu) => Some(mtu),
let in_ip = matches.opt_strs("i");
let in_ip = match ips_parse(&in_ip) {
Ok(in_ip) => in_ip,
Err(e) => {
print_usage(&program, opts);
println!();
println!("'-u {}' {}", mtu, e);
println!("-i: {:?} {}", in_ip, e);
println!("example: -i 192.168.0.0/24,10.26.0.3");
return;
}
};
let out_ip = matches.opt_strs("o");
let out_ip = match out_ips_parse(&out_ip) {
Ok(out_ip) => out_ip,
Err(e) => {
print_usage(&program, opts);
println!();
println!("-o: {:?} {}", out_ip, e);
println!("example: -o 0.0.0.0/0");
return;
}
};
let password: Option<String> = matches.opt_get("w").unwrap();
let server_encrypt = matches.opt_present("W");
#[cfg(not(feature = "server_encrypt"))]
{
if server_encrypt {
println!("Server encryption not supported");
return;
}
}
} else {
None
};
let virtual_ip: Option<String> = matches.opt_get("ip").unwrap();
let virtual_ip =
virtual_ip.map(|v| Ipv4Addr::from_str(&v).expect(&format!("'--ip {}' error", v)));
if let Some(virtual_ip) = virtual_ip {
if virtual_ip.is_unspecified() || virtual_ip.is_broadcast() || virtual_ip.is_multicast() {
println!("'--ip {}' invalid", virtual_ip);
let simulate_multicast = matches.opt_present("m");
let mtu: Option<String> = matches.opt_get("u").unwrap();
let mtu = if let Some(mtu) = mtu {
match u16::from_str(&mtu) {
Ok(mtu) => Some(mtu),
Err(e) => {
print_usage(&program, opts);
println!();
println!("'-u {}' {}", mtu, e);
return;
}
}
} else {
None
};
let virtual_ip: Option<String> = matches.opt_get("ip").unwrap();
let virtual_ip =
virtual_ip.map(|v| Ipv4Addr::from_str(&v).expect(&format!("'--ip {}' error", v)));
if let Some(virtual_ip) = virtual_ip {
if virtual_ip.is_unspecified() || virtual_ip.is_broadcast() || virtual_ip.is_multicast()
{
println!("'--ip {}' invalid", virtual_ip);
return;
}
}
let tcp_channel = matches.opt_present("tcp");
let relay = matches.opt_present("relay");
let parallel = matches.opt_get::<usize>("par").unwrap().unwrap_or(1);
if parallel == 0 {
println!("'--par {}' invalid", parallel);
return;
}
}
let tcp_channel = matches.opt_present("tcp");
let relay = matches.opt_present("relay");
let parallel = matches.opt_get::<usize>("par").unwrap().unwrap_or(1);
if parallel == 0 {
println!("'--par {}' invalid", parallel);
return;
}
let cipher_model = matches
.opt_get::<CipherModel>("model")
.unwrap()
.unwrap_or(CipherModel::AesGcm);
let cipher_model = match matches.opt_get::<CipherModel>("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")))]
{
if password.is_some() && model.is_none() {
println!("'--model ' undefined");
return;
}
model.unwrap_or(CipherModel::None)
}
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
model.unwrap_or(CipherModel::AesGcm)
}
Err(e) => {
println!("'--model ' invalid,{}", e);
return;
}
};
let finger = matches.opt_present("finger");
let punch_model = matches
.opt_get::<PunchModel>("punch")
.unwrap()
.unwrap_or(PunchModel::All);
let finger = matches.opt_present("finger");
let punch_model = matches
.opt_get::<PunchModel>("punch")
.unwrap()
.unwrap_or(PunchModel::All);
let port = matches.opt_get::<u16>("port").unwrap_or(None).unwrap_or(0);
let cmd = matches.opt_present("cmd");
#[cfg(feature = "ip_proxy")]
let no_proxy = matches.opt_present("no-proxy");
let first_latency = matches.opt_present("first-latency");
let config = Config::new(
tap,
token,
device_id,
name,
server_address,
server_address_str,
stun_server,
in_ip,
out_ip,
password,
simulate_multicast,
mtu,
tcp_channel,
virtual_ip,
relay,
#[cfg(feature = "ip_proxy")]
no_proxy,
server_encrypt,
parallel,
cipher_model,
finger,
punch_model,
port,
first_latency,
)
.unwrap();
(config, cmd)
};
println!("version {}", vnt::VNT_VERSION);
let config = Config::new(
tap,
token,
device_id,
name,
server_address,
server_address_str,
stun_server,
in_ip,
out_ip,
password,
simulate_multicast,
mtu,
tcp_channel,
virtual_ip,
relay,
server_encrypt,
parallel,
cipher_model,
finger,
punch_model,
);
main0(config, !unused_cmd);
main0(config, cmd);
std::process::exit(0);
}
#[tokio::main]
async fn main0(config: Config, show_cmd: bool) {
let server_encrypt = config.server_encrypt;
let mut vnt_util = VntUtil::new(config).await.unwrap();
let mut vnt_util = VntUtil::new(config).unwrap();
let mut conn_count = 0;
let response = loop {
if conn_count > 0 {
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
}
conn_count += 1;
if let Err(e) = vnt_util.connect().await {
if let Err(e) = vnt_util.connect() {
println!("connect server failed {}", e);
return;
}
match vnt_util.handshake().await {
match vnt_util.handshake() {
Ok(response) => {
if server_encrypt {
let finger = response.unwrap().finger().unwrap();
println!("{}{}", green("server fingerprint:".to_string()), finger);
match vnt_util.secret_handshake().await {
match vnt_util.secret_handshake() {
Ok(_) => {}
Err(e) => {
match e {
@@ -289,7 +337,7 @@ async fn main0(config: Config, show_cmd: bool) {
}
}
}
match vnt_util.register().await {
match vnt_util.register() {
Ok(response) => {
break response;
}
@@ -358,6 +406,7 @@ async fn main0(config: Config, show_cmd: bool) {
let vnt_c = vnt.clone();
tokio::spawn(async {
if let Err(e) = command::server::CommandServer::new().start(vnt_c).await {
log::warn!("cmd:{:?}", e);
println!("command error :{}", e);
}
});
@@ -433,28 +482,70 @@ fn print_usage(program: &str, _opts: Options) {
println!("Options:");
println!(
" -k <token> {}",
green("必选,使用相同的token,就能组建一个局域网络".to_string())
green("使用相同的token,就能组建一个局域网络".to_string())
);
println!(" -n <name> 给设备一个名字,便于区分不同设备,默认使用系统版本");
println!(" -d <id> 设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip");
println!(" -c 关闭交互式命令,使用此参数禁用控制台输入");
println!(" -s <server> 注册和中继服务器地址");
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可多次指定,如-e addr1 -e addr2");
println!(" -a 使用tap模式,默认使用tun模式");
println!(" -i <in-ip> 配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据");
println!(" 并转发到10.26.0.3,可指定多个网段");
println!(" -o <out-ip> 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段");
println!(" -w <password> 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信");
#[cfg(not(feature = "ip_proxy"))]
println!(" 注意需要在系统配置ip转发才可正常使用");
#[cfg(not(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
)))]
let enums = String::new();
#[cfg(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
))]
let mut enums = String::new();
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
enums.push_str("/aes_gcm");
#[cfg(feature = "aes_cbc")]
enums.push_str("/aes_cbc");
#[cfg(feature = "aes_ecb")]
enums.push_str("/aes_ecb");
#[cfg(feature = "sm4_cbc")]
enums.push_str("/sm4_cbc");
if !enums.is_empty() {
println!(" -w <password> 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信");
}
#[cfg(feature = "server_encrypt")]
println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确");
println!(" -m 模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送");
println!(" -u <mtu> 自定义mtu(不加密默认为1450,加密默认为1410)");
println!(" -f <conf_file> 读取配置文件中的配置");
println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp");
println!(" --ip <ip> 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配");
println!(" --relay 仅使用服务器转发,不使用p2p,默认情况允许使用p2p");
println!(" --par <parallel> 任务并行度(必须为正整数),默认值为1");
println!(" --model <model> 加密模式(默认aes_gcm),可选值aes_gcm/aes_cbc/aes_ecb,一般来说性能:aes_ecb>aes_cbc>aes_gcm");
println!(" --finger 增加数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启");
if !enums.is_empty() {
println!(
" --model <model> 加密模式(默认aes_gcm),可选值{}",
&enums[1..]
);
}
if !enums.is_empty() {
println!(" --finger 增加数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启");
}
println!(" --punch <punch> 取值ipv4/ipv6ipv4表示仅使用ipv4打洞");
println!(" --port <port> 取值0~65535,指定本地监听的端口,默认取随机端口");
println!(" --cmd 开启交互式命令,使用此参数开启控制台输入");
#[cfg(feature = "ip_proxy")]
println!(" --no-proxy 关闭内置代理,如需点对网则需要配置网卡NAT转发");
println!(" --first-latency 优先低延迟的通道,默认情况优先使用p2p通道");
println!();
println!(
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "vnt-jni"
version = "1.2.3"
version = "1.2.8"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+17 -2
View File
@@ -66,8 +66,10 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
let cipher_model = to_string_not_null(env, &config, "cipherModel")?;
let tcp = env.get_field(&config, "tcp", "Z")?.z()?;
let finger = env.get_field(&config, "finger", "Z")?.z()?;
let first_latency = env.get_field(&config, "firstLatency", "Z")?.z()?;
let in_ips = to_string(env, &config, "inIps")?;
let out_ips = to_string(env, &config, "outIps")?;
let port = env.get_field(&config, "port", "I")?.i()? as u16;
let in_ips = if let Some(in_ips) = in_ips {
let in_ips: Vec<&str> = in_ips.split("\n").collect();
let in_ips = in_ips.iter().map(|v| v.to_string()).collect();
@@ -128,7 +130,7 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
for addr in stun_server_str.split(",") {
stun_server.push(addr.trim().to_string());
}
let config = Config::new(
let config = match Config::new(
false,
token,
device_id,
@@ -145,11 +147,24 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
None,
false,
false,
false,
1,
cipher_model,
finger,
PunchModel::All,
);
port,
first_latency,
) {
Ok(config) => config,
Err(e) => {
env.throw_new(
"java/lang/RuntimeException",
format!("vnt start error {}", e),
)
.expect("throw");
return Err(Error::JavaException);
}
};
match VntUtilSync::new(config) {
Ok(vnt_util) => Ok(vnt_util),
Err(e) => {
+18 -16
View File
@@ -1,44 +1,42 @@
[package]
name = "vnt"
version = "1.2.3"
version = "1.2.8"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
packet = { path = "./packet" }
bytes = "1.3.0"
bytes = "1.5.0"
log = "0.4.17"
libc = "0.2.137"
crossbeam-utils = "0.8"
crossbeam-epoch = "0.9.15"
dashmap = "5.5.1"
dashmap = {version = "5.5.3",optional = true}
parking_lot = "0.12.1"
byte-pool = "0.2.4"
lazy_static = "1.4.0"
rand = "0.8.5"
sha2 = { version = "0.10.6", features = ["oid"] }
thiserror = "1.0.37"
protobuf = "3.2.0"
socket2 = { version = "0.5.2", features = ["all"] }
tokio = { version = "1.32.0", features = ["full"] }
aes-gcm = { version = "0.10.2" }
ring = { version = "0.16.20", optional = true }
cbc = "0.1.2"
ecb = "0.1.2"
aes-gcm = { version = "0.10.2",optional = true }
ring = { version = "0.17.0", optional = true }
cbc = {version = "0.1.2",optional = true}
ecb = {version = "0.1.2",optional = true}
aes = "0.8.3"
stun-format = { version = "1.0.1", features = ["fmt", "rfc3489"] }
rsa = { version = "0.7.2", features = [] }
spki = { version = "0.6.0", features = ["fingerprint", "alloc"] }
rsa = { version = "0.9.2", features = [] ,optional = true}
spki = { version = "0.7.2", features = ["fingerprint", "alloc","base64"] ,optional = true}
openssl-sys = { git = "https://github.com/lbl8603/rust-openssl" ,optional = true}
libsm = {git="https://github.com/lbl8603/libsm" ,optional = true}
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
tun = { path = "./rust-tun" }
[target.'cfg(target_os = "windows")'.dependencies]
win-tun-tap = { path = "./win-tun-tap" }
libloading = "0.7.4"
libloading = "0.8.0"
[build-dependencies]
@@ -46,10 +44,14 @@ protobuf-codegen = "3.2.0"
protoc-bin-vendored = "3.0.0"
[features]
default = []
default = ["server_encrypt","aes_gcm","aes_cbc","aes_ecb","sm4_cbc","ip_proxy"]
openssl = ["openssl-sys"]
# 从源码编译
openssl-vendored = ["openssl-sys/vendored"]
ring-cipher = ["ring"]
aes_cbc=["cbc"]
aes_ecb=["ecb"]
sm4_cbc=["libsm"]
aes_gcm=["aes-gcm"]
server_encrypt =["aes-gcm","rsa","spki"]
ip_proxy=["dashmap"]
+8 -1
View File
@@ -76,7 +76,14 @@ impl<B: AsRef<[u8]>> TcpPacket<B> {
Ok(packet)
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> TcpPacket<B> {
pub fn set_source_ip(&mut self, value: Ipv4Addr) {
self.source_ip = value;
}
pub fn set_destination_ip(&mut self, value: Ipv4Addr) {
self.destination_ip = value;
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> TcpPacket<B> {
fn set_checksum(&mut self, value: u16) {
self.buffer.as_mut()[16..18].copy_from_slice(&value.to_be_bytes())
+232 -453
View File
@@ -1,44 +1,35 @@
use std::collections::HashMap;
use std::io;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
use std::ops::Sub;
use std::sync::atomic::Ordering;
use std::io::{Read, Write};
use std::net::UdpSocket as StdUdpSocket;
use std::net::{Ipv4Addr, Shutdown, SocketAddr};
use std::net::{SocketAddrV6, TcpStream};
use std::sync::Arc;
use std::time::{Duration, Instant};
use std::{io, thread};
use byte_pool::{Block, BytePool};
use crossbeam_epoch::{Atomic, Owned};
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap;
use std::net::UdpSocket as StdUdpSocket;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::tcp::OwnedReadHalf;
use tokio::net::{TcpStream, UdpSocket};
use parking_lot::{Mutex, RwLock};
use tokio::net::UdpSocket;
use tokio::sync::watch::{channel, Receiver, Sender};
use crate::channel::punch::NatType;
use crate::channel::{Route, RouteKey, Status, TCP_ID, UDP_ID, UDP_V6_ID};
use crate::channel::{Route, RouteKey, Status, TCP_ID, UDP_ID};
use crate::core::status::VntWorker;
use crate::handle::recv_handler::ChannelDataHandler;
use crate::handle::CurrentDeviceInfo;
use crate::ip_proxy::DashMapNew;
lazy_static::lazy_static! {
static ref POOL:BytePool = BytePool::new();
}
pub struct ContextInner {
//udp用于打洞、服务端通信(可选)
pub(crate) main_channel: Arc<StdUdpSocket>,
pub(crate) main_channel_ipv6: Option<Arc<StdUdpSocket>>,
pub(crate) main_channel: StdUdpSocket,
//在udp的基础上,可以选择使用tcp和服务端通信
pub(crate) main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>,
pub(crate) route_table: Atomic<HashMap<Ipv4Addr, Vec<Route>>>,
pub(crate) route_table_time: DashMap<(RouteKey, Ipv4Addr), Instant>,
pub(crate) main_tcp_channel: Option<Mutex<TcpStream>>,
pub(crate) route_table: RwLock<HashMap<Ipv4Addr, Vec<(Route, AtomicCell<Instant>)>>>,
pub(crate) status_receiver: Receiver<Status>,
pub(crate) status_sender: Sender<Status>,
pub(crate) udp_map: Atomic<HashMap<usize, Arc<UdpSocket>>>,
pub(crate) udp_map: RwLock<HashMap<usize, Arc<UdpSocket>>>,
pub(crate) channel_num: usize,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
first_latency: bool,
}
#[derive(Clone)]
@@ -48,26 +39,26 @@ pub struct Context {
impl Context {
pub fn new(
main_channel: Arc<StdUdpSocket>,
main_channel_ipv6: Option<Arc<StdUdpSocket>>,
main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>,
main_channel: StdUdpSocket,
main_tcp_channel: Option<TcpStream>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
_channel_num: usize,
first_latency: bool,
) -> Self {
//当前版本只支持一个通道
let channel_num = 1;
let (status_sender, status_receiver) = channel(Status::Cone);
let main_tcp_channel = main_tcp_channel.map(|e| Mutex::new(e));
let inner = Arc::new(ContextInner {
main_channel,
main_channel_ipv6,
main_tcp_channel,
route_table: Atomic::new(HashMap::with_capacity(16)),
route_table_time: DashMap::new_cap(16),
route_table: RwLock::new(HashMap::with_capacity(16)),
status_receiver,
status_sender,
udp_map: Atomic::new(HashMap::with_capacity(16)),
udp_map: RwLock::new(HashMap::with_capacity(16)),
channel_num,
current_device,
first_latency,
});
Self { inner }
}
@@ -82,23 +73,23 @@ impl Context {
}
pub fn close(&self) -> io::Result<()> {
let _ = self.inner.status_sender.send(Status::Close);
if let Ok(port) = self.main_local_ipv4_port() {
if let Ok(port) = self.main_local_udp_port() {
let _ = StdUdpSocket::bind("127.0.0.1:0")?.send_to(
b"stop",
SocketAddr::V4(std::net::SocketAddrV4::new(Ipv4Addr::LOCALHOST, port)),
);
}
if let Ok(port) = self.main_local_ipv6_port() {
let _ = StdUdpSocket::bind("[::]:0")?.send_to(
b"stop",
SocketAddr::V6(std::net::SocketAddrV6::new(Ipv6Addr::LOCALHOST, port, 0, 0)),
);
if let Some(tcp) = &self.inner.main_tcp_channel {
tcp.lock().shutdown(Shutdown::Both)?;
}
Ok(())
}
pub fn is_main_tcp(&self) -> bool {
self.inner.main_tcp_channel.is_some()
}
pub fn is_first_latency(&self) -> bool {
self.inner.first_latency
}
pub fn switch(&self, nat_type: NatType) {
match nat_type {
NatType::Symmetric => {
@@ -115,92 +106,65 @@ impl Context {
pub fn switch_to_symmetric(&self) {
let _ = self.inner.status_sender.send(Status::Symmetric);
}
pub fn main_local_ipv4_port(&self) -> io::Result<u16> {
pub fn main_local_udp_port(&self) -> io::Result<u16> {
self.inner.main_channel.local_addr().map(|k| k.port())
}
pub fn main_local_ipv6_port(&self) -> io::Result<u16> {
if let Some(ipv6) = &self.inner.main_channel_ipv6 {
ipv6.local_addr().map(|k| k.port())
} else {
Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
}
}
fn insert_udp(&self, id: usize, udp: Arc<UdpSocket>) {
self.insert_udp_(id, Some(udp))
self.inner.udp_map.write().insert(id, udp);
}
fn remove_udp(&self, id: usize) {
self.insert_udp_(id, None)
self.inner.udp_map.write().remove(&id);
}
fn insert_udp_(&self, id: usize, udp: Option<Arc<UdpSocket>>) {
let guard = &crossbeam_epoch::pin();
let udp_map = &self.inner.udp_map;
let mut udp_map_shared = self.inner.udp_map.load(Ordering::Relaxed, guard);
loop {
let mut map = unsafe { udp_map_shared.as_ref().unwrap().clone() };
match udp.clone() {
None => {
map.remove(&id);
}
Some(udp) => {
map.insert(id, udp);
}
}
match udp_map.compare_exchange(
udp_map_shared,
Owned::new(map),
Ordering::Relaxed,
Ordering::Relaxed,
guard,
) {
Ok(p) => unsafe {
guard.defer_destroy(p);
return;
},
Err(e) => {
udp_map_shared = e.current;
}
}
#[inline]
pub fn send_main_udp(&self, buf: &[u8], mut addr: SocketAddr) -> io::Result<usize> {
if let SocketAddr::V4(ipv4) = addr {
addr = SocketAddr::V6(SocketAddrV6::new(
ipv4.ip().to_ipv6_mapped(),
ipv4.port(),
0,
0,
));
}
self.inner.main_channel.send_to(buf, addr)
}
pub fn send_main_udp(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
if addr.is_ipv6() {
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
udp_ipv6.send_to(buf, addr)
} else {
Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
}
#[inline]
pub fn send_main_tcp(&self, buf: &[u8]) -> io::Result<usize> {
if let Some(sender) = &self.inner.main_tcp_channel {
let mut stream = sender.lock();
let mut head = [0; 4];
let len = buf.len();
head[2] = (len >> 8) as u8;
head[3] = (len & 0xFF) as u8;
stream.write_all(&head)?;
stream.write_all(buf)?;
Ok(len)
} else {
self.inner.main_channel.send_to(buf, addr)
return Err(io::Error::new(io::ErrorKind::NotFound, "tcp not found"));
}
}
pub fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
if let Some(sender) = &self.inner.main_tcp_channel {
if sender.try_send(buf.to_vec()).is_ok() {
Ok(buf.len())
} else {
Err(io::Error::new(io::ErrorKind::Other, "send_main err"))
}
let mut stream = sender.lock();
let mut head = [0; 4];
let len = buf.len();
head[2] = (len >> 8) as u8;
head[3] = (len & 0xFF) as u8;
stream.write_all(&head)?;
stream.write_all(buf)?;
Ok(len)
} else {
self.send_main_udp(buf, addr)
}
}
pub(crate) fn try_send_all(&self, buf: &[u8], addr: SocketAddr) -> io::Result<()> {
let table = unsafe {
let guard = &crossbeam_epoch::pin();
self.inner
.udp_map
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
.clone()
};
let table = self.inner.udp_map.read();
if table.is_empty() {
log::error!("udp列表为空,addr={}", addr);
return Ok(());
}
for (_, udp) in table {
for (_, udp) in table.iter() {
//使用ipv6的udp发送ipv4报文会出错
if let Err(e) = udp.try_send_to(buf, addr) {
log::error!("{:?}", e);
@@ -218,57 +182,30 @@ impl Context {
self.try_send_by_key(buf, &route.route_key())
}
fn get_route_by_id(&self, id: &Ipv4Addr) -> io::Result<Route> {
let guard = &crossbeam_epoch::pin();
let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
if let Some(v) = table.get(id) {
if let Some(v) = self.inner.route_table.read().get(id) {
if v.is_empty() {
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
}
let route = v[0];
let (route, time) = &v[0];
if route.rt == 199 {
//这通常是刚加入路由,直接放弃使用,避免抖动
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
}
if !route.is_p2p() {
if let Some(time) = self.inner.route_table_time.get(&(route.route_key(), *id)) {
//借道传输时,长时间不通信的通道不使用
if time.value().elapsed() > Duration::from_secs(6) {
return Err(io::Error::new(io::ErrorKind::NotFound, "route time out"));
}
//借道传输时,长时间不通信的通道不使用
if time.load().elapsed() > Duration::from_secs(6) {
return Err(io::Error::new(io::ErrorKind::NotFound, "route time out"));
}
}
return Ok(route);
return Ok(*route);
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub async fn send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
match route_key.index {
TCP_ID => {
if let Some(sender) = &self.inner.main_tcp_channel {
if sender.send(buf.to_vec()).await.is_ok() {
Ok(buf.len())
} else {
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
}
} else {
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
}
}
UDP_ID => self.inner.main_channel.send_to(buf, route_key.addr),
UDP_V6_ID => {
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
udp_ipv6.send_to(buf, route_key.addr)
} else {
Err(io::Error::new(io::ErrorKind::Other, "not ipv6 udp"))
}
}
TCP_ID => self.send_main_tcp(buf),
UDP_ID => self.send_main_udp(buf, route_key.addr),
_ => {
if let Some(udp) = self.get_udp_by_route(route_key) {
return udp.send_to(buf, route_key.addr).await;
@@ -279,25 +216,8 @@ impl Context {
}
pub fn try_send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
match route_key.index {
TCP_ID => {
if let Some(sender) = &self.inner.main_tcp_channel {
if sender.try_send(buf.to_vec()).is_ok() {
Ok(buf.len())
} else {
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
}
} else {
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
}
}
UDP_ID => self.inner.main_channel.send_to(buf, route_key.addr),
UDP_V6_ID => {
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
udp_ipv6.send_to(buf, route_key.addr)
} else {
Err(io::Error::new(io::ErrorKind::Other, "not ipv6 udp"))
}
}
TCP_ID => self.send_main_tcp(buf),
UDP_ID => self.send_main_udp(buf, route_key.addr),
_ => {
if let Some(udp) = self.get_udp_by_route(route_key) {
return udp.try_send_to(buf, route_key.addr);
@@ -307,15 +227,7 @@ impl Context {
}
}
fn get_udp_by_route(&self, route_key: &RouteKey) -> Option<Arc<UdpSocket>> {
let guard = &crossbeam_epoch::pin();
let udp_map = unsafe {
self.inner
.udp_map
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
udp_map.get(&route_key.index).cloned()
self.inner.udp_map.read().get(&route_key.index).cloned()
}
pub fn add_route_if_absent(&self, id: Ipv4Addr, route: Route) {
@@ -326,105 +238,64 @@ impl Context {
}
fn add_route_(&self, id: Ipv4Addr, route: Route, only_if_absent: bool) {
let key = route.route_key();
let guard = &crossbeam_epoch::pin();
let route_table = &self.inner.route_table;
let mut table_share = route_table.load(Ordering::Relaxed, guard);
loop {
let mut table = unsafe { table_share.as_ref().unwrap().clone() };
let list = table.entry(id).or_insert_with(|| Vec::with_capacity(4));
let mut exist = false;
for x in list.iter_mut() {
if x.metric < route.metric {
//不能比当前的路径更长
let mut route_table = self.inner.route_table.write();
let list = route_table
.entry(id)
.or_insert_with(|| Vec::with_capacity(4));
let mut exist = false;
for (x, time) in list.iter_mut() {
if x.metric < route.metric && !self.inner.first_latency {
//非优先延迟的情况下 不能比当前的路径更长
return;
}
if x.route_key() == key {
if only_if_absent {
return;
}
if x.route_key() == key {
if only_if_absent {
return;
}
x.metric = route.metric;
x.rt = route.rt;
exist = true;
break;
}
}
if exist {
list.sort_by_key(|k| k.sort_key());
} else {
if route.metric == 1 {
//添加了直连的则排除非直连的
list.retain(|k| k.metric == 1);
}
list.push(route);
list.sort_by_key(|k| k.sort_key());
let max_len = self.inner.channel_num + 1;
if list.len() > max_len {
list.truncate(max_len);
}
}
match route_table.compare_exchange(
table_share,
Owned::new(table),
Ordering::Relaxed,
Ordering::Relaxed,
guard,
) {
Ok(p) => unsafe {
guard.defer_destroy(p);
break;
},
Err(e) => {
table_share = e.current;
}
x.metric = route.metric;
x.rt = route.rt;
exist = true;
time.store(Instant::now());
break;
}
}
self.inner
.route_table_time
.insert((key, id), Instant::now().sub(Duration::from_secs(10)));
if exist {
list.sort_by_key(|(k, _)| k.rt);
} else {
let max_len = if self.inner.first_latency {
self.inner.channel_num + 1
} else {
if route.metric == 1 {
//非优先延迟的情况下 添加了直连的则排除非直连的
list.retain(|(k, _)| k.metric == 1);
}
self.inner.channel_num
};
list.sort_by_key(|(k, _)| k.rt);
if list.len() > max_len {
list.truncate(max_len);
}
list.push((route, AtomicCell::new(Instant::now())));
}
}
pub fn route(&self, id: &Ipv4Addr) -> Option<Vec<Route>> {
let guard = &crossbeam_epoch::pin();
let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
if let Some(v) = table.get(id) {
Some(v.clone())
if let Some(v) = self.inner.route_table.read().get(id) {
Some(v.iter().map(|(i, _)| *i).collect())
} else {
None
}
}
pub fn route_one(&self, id: &Ipv4Addr) -> Option<Route> {
let guard = &crossbeam_epoch::pin();
let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
if let Some(v) = table.get(id) {
v.first().map(|v| *v)
if let Some(v) = self.inner.route_table.read().get(id) {
v.first().map(|(i, _)| *i)
} else {
None
}
}
pub fn route_to_id(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
let guard = &crossbeam_epoch::pin();
let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
let table = self.inner.route_table.read();
for (k, v) in table.iter() {
for route in v {
for (route, _) in v {
if &route.route_key() == route_key && route.is_p2p() {
return Some(*k);
}
@@ -433,44 +304,25 @@ impl Context {
None
}
pub fn need_punch(&self, id: &Ipv4Addr) -> bool {
let guard = &crossbeam_epoch::pin();
let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
if let Some(v) = table.get(id) {
if v.iter().filter(|k| k.is_p2p()).count() >= self.inner.channel_num {
if let Some(v) = self.inner.route_table.read().get(id) {
if v.iter().filter(|(k, _)| k.is_p2p()).count() >= self.inner.channel_num {
return false;
}
}
true
}
pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec<Route>)> {
let guard = &crossbeam_epoch::pin();
let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
table.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
let table = self.inner.route_table.read();
table
.iter()
.map(|(k, v)| (k.clone(), v.iter().map(|(i, _)| *i).collect()))
.collect()
}
pub fn route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
let mut list = Vec::with_capacity(8);
let guard = &crossbeam_epoch::pin();
let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
for (k, v) in table {
if let Some(route) = v.first() {
let table = self.inner.route_table.read();
for (k, v) in table.iter() {
if let Some((route, _)) = v.first() {
list.push((*k, *route));
}
}
@@ -478,16 +330,9 @@ impl Context {
}
pub fn direct_route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
let mut list = Vec::with_capacity(8);
let guard = &crossbeam_epoch::pin();
let table = unsafe {
self.inner
.route_table
.load(Ordering::Relaxed, guard)
.as_ref()
.unwrap()
};
for (k, v) in table {
if let Some(route) = v.first() {
let table = self.inner.route_table.read();
for (k, v) in table.iter() {
if let Some((route, _)) = v.first() {
if route.metric == 1 {
list.push((*k, *route));
}
@@ -497,35 +342,20 @@ impl Context {
}
pub fn remove_route(&self, id: &Ipv4Addr, route_key: RouteKey) {
let guard = &crossbeam_epoch::pin();
let route_table = &self.inner.route_table;
let mut table_share = route_table.load(Ordering::Relaxed, guard);
loop {
let mut table = unsafe { table_share.as_ref().unwrap().clone() };
if let Some(routes) = table.get_mut(id) {
routes.retain(|x| x.route_key() != route_key);
match route_table.compare_exchange(
table_share,
Owned::new(table),
Ordering::Relaxed,
Ordering::Relaxed,
guard,
) {
Ok(p) => unsafe {
guard.defer_destroy(p);
self.inner.route_table_time.remove(&(route_key, *id));
return;
},
Err(e) => {
table_share = e.current;
}
}
}
if let Some(routes) = self.inner.route_table.write().get_mut(id) {
routes.retain(|(x, _)| x.route_key() != route_key);
} else {
return;
}
}
pub fn update_read_time(&self, id: &Ipv4Addr, route_key: &RouteKey) {
if let Some(mut time) = self.inner.route_table_time.get_mut(&(*route_key, *id)) {
*time.value_mut() = Instant::now();
if let Some(routes) = self.inner.route_table.read().get(id) {
for (route, time) in routes {
if &route.route_key() == route_key {
time.store(Instant::now());
break;
}
}
}
}
}
@@ -544,13 +374,13 @@ impl Channel {
#[derive(Clone)]
struct BufSenderGroup(
usize,
Vec<std::sync::mpsc::SyncSender<(Block<'static>, usize, usize, RouteKey)>>,
Vec<std::sync::mpsc::SyncSender<(Vec<u8>, usize, usize, RouteKey)>>,
);
struct BufReceiverGroup(Vec<std::sync::mpsc::Receiver<(Block<'static>, usize, usize, RouteKey)>>);
struct BufReceiverGroup(Vec<std::sync::mpsc::Receiver<(Vec<u8>, usize, usize, RouteKey)>>);
impl BufSenderGroup {
pub fn send(&mut self, val: (Block<'static>, usize, usize, RouteKey)) -> bool {
pub fn send(&mut self, val: (Vec<u8>, usize, usize, RouteKey)) -> bool {
let index = self.0 % self.1.len();
self.0 = self.0.wrapping_add(1);
self.1[index].send(val).is_ok()
@@ -562,7 +392,7 @@ fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) {
let mut buf_receiver_group = Vec::with_capacity(size);
for _ in 0..size {
let (buf_sender, buf_receiver) =
std::sync::mpsc::sync_channel::<(Block<'static, Vec<u8>>, usize, usize, RouteKey)>(1);
std::sync::mpsc::sync_channel::<(Vec<u8>, usize, usize, RouteKey)>(1);
buf_sender_group.push(buf_sender);
buf_receiver_group.push(buf_receiver);
}
@@ -573,18 +403,21 @@ fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) {
}
impl Channel {
async fn tcp_handle(
mut tcp_r: OwnedReadHalf,
context: Context,
handler: ChannelDataHandler,
fn tcp_handle(
tcp_r: &mut TcpStream,
context: &Context,
handler: &ChannelDataHandler,
head_reserve: usize,
) -> io::Result<()> {
let mut head = [0; 4];
let addr = tcp_r.peer_addr()?;
let key = RouteKey::new(TCP_ID, addr);
loop {
if context.is_close() {
return Ok(());
}
let mut buf = [0; 4096];
tcp_r.read_exact(&mut head).await?;
tcp_r.read_exact(&mut head)?;
let len = (((head[2] as u16) << 8) | head[3] as u16) as usize;
if len < 12 || len > buf.len() {
return Err(io::Error::new(
@@ -592,84 +425,58 @@ impl Channel {
"length overflow",
));
}
tcp_r
.read_exact(&mut buf[head_reserve..head_reserve + len])
.await?;
handler
.handle(&mut buf, head_reserve, head_reserve + len, key, &context)
.await;
tcp_r.read_exact(&mut buf[head_reserve..head_reserve + len])?;
handler.handle(&mut buf, head_reserve, head_reserve + len, key, context);
}
}
async fn start_tcp(
mut worker: VntWorker,
tcp_stream: TcpStream,
mut receiver: tokio::sync::mpsc::Receiver<Vec<u8>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
fn start_tcp(
mut tcp_stream: TcpStream,
context: Context,
handler: ChannelDataHandler,
head_reserve: usize,
) {
let (tcp_r, mut tcp_w) = tcp_stream.into_split();
{
let context = context.clone();
let handler = handler.clone();
tokio::spawn(async move {
if let Err(e) = Self::tcp_handle(tcp_r, context, handler, head_reserve).await {
log::info!("tcp链接断开:{:?}", e);
}
});
}
let mut head = [0; 4];
let current_device = context.inner.current_device.clone();
loop {
tokio::select! {
_=worker.stop_wait()=>{
break;
if let Err(e) = tcp_stream.set_nodelay(true) {
log::info!("set_nodelay:{:?}", e);
}
if let Err(e) = tcp_stream.set_write_timeout(Some(Duration::from_secs(3))) {
log::info!("set_write_timeout:{:?}", e);
}
if let Err(e) = tcp_stream.set_read_timeout(Some(Duration::from_secs(10))) {
log::info!("set_read_timeout:{:?}", e);
}
if let Err(e) = Self::tcp_handle(&mut tcp_stream, &context, &handler, head_reserve) {
log::info!("tcp链接断开:{:?}", e);
}
if let Err(e) = tcp_stream.shutdown(Shutdown::Both) {
log::info!("tcp链接关闭异常:{:?}", e);
}
loop {
if context.is_close() {
return;
}
rs=receiver.recv()=>{
if let Some(data) = rs{
let len = data.len();
head[2] = (len >> 8) as u8;
head[3] = (len & 0xFF) as u8;
let mut err = false;
if let Err(e) = tcp_w.write_all(&head).await{
err = true;
log::info!("发送失败,需要重连:{:?}",e);
}else if let Err(e) = tcp_w.write_all(&data).await{
err = true;
log::info!("发送失败,需要重连:{:?}",e);
}
if err {
let _ = tcp_w.shutdown().await;
match TcpStream::connect(current_device.load().connect_server).await {
Ok(tcp_stream) => {
let (r, w) = tcp_stream.into_split();
tcp_w = w;
let context = context.clone();
let handler = handler.clone();
tokio::spawn(async move {
if let Err(e) = Self::tcp_handle(r, context,handler, head_reserve).await {
log::info!("tcp 链接断开:{:?}",e);
}
});
}
Err(e) => {
log::info!("重连失败:{:?}",e);
}
};
}
}else{
let device_info = current_device.load();
match TcpStream::connect(device_info.connect_server) {
Ok(tcp) => {
tcp_stream = tcp.try_clone().unwrap();
let mut guard = context.inner.main_tcp_channel.as_ref().unwrap().lock();
*guard = tcp;
break;
}
Err(e) => {
log::info!("重连失败,{},{:?}", device_info.connect_server, e);
thread::sleep(Duration::from_secs(3));
}
}
}
}
worker.stop_all();
}
pub async fn start(
self,
mut worker: VntWorker,
tcp: Option<(TcpStream, tokio::sync::mpsc::Receiver<Vec<u8>>)>,
tcp: Option<TcpStream>,
head_reserve: usize, //头部预留字节
symmetric_channel_num: usize, //对称网络,则再加一组监听,提升打洞成功率
relay: bool,
@@ -677,88 +484,61 @@ impl Channel {
) {
let handler = self.handler.clone();
let context = self.context;
let main_channel = context.inner.main_channel.clone();
let main_channel = context.inner.main_channel.try_clone().unwrap();
let buf_sender = if parallel > 1 {
let (buf_sender, buf_receiver) = buf_channel_group(parallel);
let mut num = 0;
for buf_receiver in buf_receiver.0 {
let context = context.clone();
let handler = handler.clone();
std::thread::spawn(move || {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
log::info!("启动异步处理");
runtime.block_on(async move {
thread::Builder::new()
.name(format!("recv-handler-{}", num))
.spawn(move || {
while let Ok((mut buf, start, end, route_key)) = buf_receiver.recv() {
handler
.handle(&mut buf, start, end, route_key, &context)
.await;
handler.handle(&mut buf, start, end, route_key, &context);
}
log::warn!("异步处理停止");
});
});
})
.unwrap();
num += 1;
}
Some(buf_sender)
} else {
None
};
if let Some((tcp_stream, receiver)) = tcp {
tokio::spawn(Self::start_tcp(
worker.worker("main_channel_tcp"),
tcp_stream,
receiver,
context.inner.current_device.clone(),
context.clone(),
handler.clone(),
head_reserve,
));
}
if let Some(main_channel_ipv6) = &context.inner.main_channel_ipv6 {
let worker = worker.worker("main_channel_ipv6");
if let Some(tcp_stream) = tcp {
let context = context.clone();
let main_channel_ipv6 = main_channel_ipv6.clone();
let handler = handler.clone();
let buf_sender = buf_sender.clone();
std::thread::spawn(move || {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
log::info!("启动udp v6");
runtime.block_on(Self::main_start_(
worker,
context,
UDP_V6_ID,
main_channel_ipv6,
handler,
buf_sender,
head_reserve,
));
});
let main_channel_tcp = worker.worker("main_channel_tcp");
thread::Builder::new()
.name("channel_tcp".into())
.spawn(move || {
Self::start_tcp(tcp_stream, context, handler, head_reserve);
drop(main_channel_tcp)
})
.unwrap();
}
{
let worker = worker.worker("main_channel_1");
let worker = worker.worker("main_channel_udp");
let context = context.clone();
let main_channel = main_channel.clone();
let main_channel = main_channel.try_clone().unwrap();
let handler = handler.clone();
let buf_sender = buf_sender.clone();
std::thread::spawn(move || {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
log::info!("启动udp v4");
runtime.block_on(Self::main_start_(
worker,
context,
UDP_ID,
main_channel,
handler,
buf_sender,
head_reserve,
));
});
thread::Builder::new()
.name("channel_udp".into())
.spawn(move || {
log::info!("启动udp v4");
Self::main_start_(
worker,
context,
UDP_ID,
main_channel,
handler,
buf_sender,
head_reserve,
)
})
.unwrap();
}
if relay {
worker.stop_wait().await;
@@ -766,6 +546,7 @@ impl Channel {
}
let mut cur_status = Status::Cone;
let mut status_receiver = context.inner.status_receiver.clone();
let channel_num = context.inner.channel_num;
loop {
tokio::select! {
_=worker.stop_wait()=>{
@@ -784,7 +565,7 @@ impl Channel {
continue;
}
cur_status = Status::Symmetric;
for _ in 0..symmetric_channel_num {
for _ in 0..symmetric_channel_num - channel_num {
match UdpSocket::bind("0.0.0.0:0").await {
Ok(udp) => {
let udp = Arc::new(udp);
@@ -811,11 +592,11 @@ impl Channel {
}
worker.stop_all();
}
async fn main_start_(
fn main_start_(
worker: VntWorker,
context: Context,
id: usize,
udp: Arc<StdUdpSocket>,
udp: StdUdpSocket,
handler: ChannelDataHandler,
buf_sender: Option<BufSenderGroup>,
head_reserve: usize,
@@ -832,15 +613,13 @@ impl Channel {
break;
}
}
handler
.handle(
&mut buf,
head_reserve,
end,
RouteKey::new(id, addr),
&context,
)
.await;
handler.handle(
&mut buf,
head_reserve,
end,
RouteKey::new(id, addr),
&context,
);
}
Err(e) => {
log::error!("udp :{:?}", e);
@@ -849,7 +628,7 @@ impl Channel {
}
}
Some(mut buf_sender) => loop {
let mut buf = POOL.alloc(4096);
let mut buf = vec![0; 4096];
match udp.recv_from(&mut buf[head_reserve..]) {
Ok((len, addr)) => {
let end = head_reserve + len;
@@ -897,7 +676,7 @@ impl Channel {
rs=udp.recv_from(&mut buf[head_reserve..])=>{
match rs {
Ok((len, addr)) => {
handler.handle(&mut buf, head_reserve, head_reserve + len, RouteKey::new(id, addr), &context).await;
handler.handle(&mut buf, head_reserve, head_reserve + len, RouteKey::new(id, addr), &context);
}
Err(e) => {
log::error!("{:?}",e)
@@ -931,7 +710,7 @@ impl Channel {
}
}
Some(mut buf_sender) => loop {
let mut buf = POOL.alloc(4096);
let mut buf = vec![0; 4096];
tokio::select! {
rs=udp.recv_from(&mut buf[head_reserve..])=>{
match rs {
+14 -9
View File
@@ -1,10 +1,11 @@
use crate::channel::channel::Context;
use crate::channel::RouteKey;
use std::io;
use std::io::{Error, ErrorKind};
use std::net::Ipv4Addr;
use std::time::Duration;
use crate::channel::channel::Context;
use crate::channel::RouteKey;
pub struct Idle {
read_idle: Duration,
context: Context,
@@ -21,13 +22,17 @@ impl Idle {
pub async fn next_idle(&self) -> io::Result<(Ipv4Addr, RouteKey)> {
loop {
let mut max = Duration::from_secs(0);
for entry in self.context.inner.route_table_time.iter() {
let last_read = entry.value().elapsed();
if last_read >= self.read_idle {
return Ok((entry.key().1.clone(), entry.key().0.clone()));
} else {
if max < last_read {
max = last_read;
{
for (ip, routes) in self.context.inner.route_table.read().iter() {
for (route, time) in routes {
let last_read = time.load().elapsed();
if last_read >= self.read_idle {
return Ok((*ip, route.route_key()));
} else {
if max < last_read {
max = last_read;
}
}
}
}
}
-1
View File
@@ -7,7 +7,6 @@ pub mod sender;
const TCP_ID: usize = 0;
const UDP_ID: usize = 1;
const UDP_V6_ID: usize = 2;
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Status {
+35 -10
View File
@@ -50,9 +50,18 @@ impl NatInfo {
public_port_range: u16,
local_ipv4_addr: SocketAddrV4,
ipv6_addr: SocketAddrV6,
nat_type: NatType,
mut nat_type: NatType,
) -> Self {
public_ips.retain(|ip| !ip.is_loopback() && !ip.is_private());
public_ips.retain(|ip| {
!ip.is_multicast()
&& !ip.is_broadcast()
&& !ip.is_unspecified()
&& !ip.is_loopback()
&& !ip.is_private()
});
if public_ips.len() > 1 {
nat_type = NatType::Symmetric;
}
Self {
public_ips,
public_port,
@@ -62,6 +71,20 @@ impl NatInfo {
nat_type,
}
}
pub fn update_addr(&mut self, ip: Ipv4Addr, port: u16) {
if !ip.is_multicast()
&& !ip.is_broadcast()
&& !ip.is_unspecified()
&& !ip.is_loopback()
&& !ip.is_private()
&& port != 0
{
self.public_port = port;
if !self.public_ips.contains(&ip) {
self.public_ips.push(ip);
}
}
}
}
#[derive(Clone)]
@@ -162,15 +185,17 @@ impl Punch {
self.port_index.insert(id, index);
}
NatType::Cone => {
let is_cone = self.context.is_cone();
for ip in nat_info.public_ips {
let addr = SocketAddr::V4(SocketAddrV4::new(ip, nat_info.public_port));
self.context.send_main_udp(buf, addr)?;
if !is_cone {
//只有一方是对称,则对称方要使用全部端口发送数据,符合上述计算的概率
self.context.try_send_all(buf, addr)?;
if nat_info.public_port != 0 {
let is_cone = self.context.is_cone();
for ip in nat_info.public_ips {
let addr = SocketAddr::V4(SocketAddrV4::new(ip, nat_info.public_port));
self.context.send_main_udp(buf, addr)?;
if !is_cone {
//只有一方是对称,则对称方要使用全部端口发送数据,符合上述计算的概率
self.context.try_send_all(buf, addr)?;
}
tokio::time::sleep(Duration::from_millis(2)).await;
}
tokio::time::sleep(Duration::from_millis(2)).await;
}
}
}
+8 -6
View File
@@ -51,10 +51,6 @@ impl AesEcbCipher {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if net_packet.payload().len() < 16 {
log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if let Some(finger) = &self.finger {
let mut nonce_raw = [0; 12];
@@ -75,6 +71,10 @@ impl AesEcbCipher {
}
net_packet.set_data_len(net_packet.data_len() - finger.len())?;
}
if net_packet.payload().len() < 16 {
log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let mut out = [0u8; 1024 * 5];
let rs = match self.key {
AesEcbEnum::AES128ECB(key) => Aes128EcbDec::new(&key.into())
@@ -111,7 +111,7 @@ impl AesEcbCipher {
}
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("解密失败:{}", e),
format!("aes_ecb解密失败:{}", e),
)),
}
}
@@ -154,7 +154,7 @@ impl AesEcbCipher {
}
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("加密失败:{}", e),
format!("aes_ecb加密失败:{}", e),
)),
};
}
@@ -164,6 +164,8 @@ impl AesEcbCipher {
fn test_aes_ecb() {
let d = AesEcbCipher::new_128([0; 16], Some(Finger::new("123")));
let mut p = NetPacket::new_encrypt([0; 100]).unwrap();
let src = p.buffer().to_vec();
d.encrypt_ipv4(&mut p).unwrap();
d.decrypt_ipv4(&mut p).unwrap();
assert_eq!(p.buffer(), &src)
}
+202 -14
View File
@@ -1,47 +1,136 @@
#[cfg(feature = "aes_ecb")]
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
use crate::cipher::aes_ecb::AesEcbCipher;
#[cfg(feature = "aes_cbc")]
use crate::cipher::aes_cbc::AesCbcCipher;
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
#[cfg(not(feature = "ring-cipher"))]
use crate::cipher::aes_gcm_cipher::AesGcmCipher;
#[cfg(feature = "aes_ecb")]
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
use crate::cipher::openssl_aes_ecb::AesEcbCipher;
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
#[cfg(feature = "ring-cipher")]
use crate::cipher::ring_aes_gcm_cipher::AesGcmCipher;
use crate::cipher::{aes_cbc, Finger};
#[cfg(feature = "sm4_cbc")]
use crate::cipher::sm4_cbc::Sm4CbcCipher;
#[cfg(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
))]
use crate::cipher::Finger;
use crate::protocol::NetPacket;
use aes_cbc::AesCbcCipher;
#[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)]
pub enum CipherModel {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
AesGcm,
#[cfg(feature = "aes_cbc")]
AesCbc,
#[cfg(feature = "aes_ecb")]
AesEcb,
#[cfg(feature = "sm4_cbc")]
Sm4Cbc,
None,
}
impl FromStr for CipherModel {
type Err = String;
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() {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
"aes_gcm" => Ok(CipherModel::AesGcm),
#[cfg(feature = "aes_cbc")]
"aes_cbc" => Ok(CipherModel::AesCbc),
#[cfg(feature = "aes_ecb")]
"aes_ecb" => Ok(CipherModel::AesEcb),
_ => Err(format!("not match '{}'", s)),
#[cfg(feature = "sm4_cbc")]
"sm4_cbc" => Ok(CipherModel::Sm4Cbc),
_ => {
let mut enums = String::new();
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
enums.push_str("/aes_gcm");
#[cfg(feature = "aes_cbc")]
enums.push_str("/aes_cbc");
#[cfg(feature = "aes_ecb")]
enums.push_str("/aes_ecb");
#[cfg(feature = "sm4_cbc")]
enums.push_str("/sm4_cbc");
let str = if enums.is_empty() {
"no encrypt"
} else {
&enums[1..]
};
Err(format!("not match '{}', enum:{}", s, str))
}
}
}
}
#[derive(Clone)]
pub enum Cipher {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
AesGcm((AesGcmCipher, Vec<u8>)),
#[cfg(feature = "aes_cbc")]
AesCbc(AesCbcCipher),
#[cfg(feature = "aes_ecb")]
AesEcb(AesEcbCipher),
#[cfg(feature = "sm4_cbc")]
Sm4Cbc(Sm4CbcCipher),
None,
}
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(
model: CipherModel,
password: Option<String>,
@@ -53,6 +142,7 @@ impl Cipher {
hasher.update(password.as_bytes());
let key: [u8; 32] = hasher.finalize().into();
match model {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
CipherModel::AesGcm => {
if password.len() < 8 {
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
@@ -62,6 +152,7 @@ impl Cipher {
Cipher::AesGcm((aes, key.to_vec()))
}
}
#[cfg(feature = "aes_cbc")]
CipherModel::AesCbc => {
if password.len() < 8 {
let aes = AesCbcCipher::new_128(key[..16].try_into().unwrap(), finger);
@@ -71,6 +162,7 @@ impl Cipher {
Cipher::AesCbc(aes)
}
}
#[cfg(feature = "aes_ecb")]
CipherModel::AesEcb => {
if password.len() < 8 {
let aes = AesEcbCipher::new_128(key[..16].try_into().unwrap(), finger);
@@ -80,18 +172,43 @@ impl Cipher {
Cipher::AesEcb(aes)
}
}
#[cfg(feature = "sm4_cbc")]
CipherModel::Sm4Cbc => {
let aes = Sm4CbcCipher::new_128(key[..16].try_into().unwrap(), finger);
Cipher::Sm4Cbc(aes)
}
CipherModel::None => Cipher::None,
}
} else {
Cipher::None
}
}
#[cfg(not(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
)))]
pub fn new_key(_key: [u8; 32], _token: String) -> io::Result<Self> {
Err(io::Error::new(io::ErrorKind::Other, "key error"))
}
#[cfg(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
))]
pub fn new_key(key: [u8; 32], token: String) -> io::Result<Self> {
let finger = Some(Finger::new(&token));
match key.len() {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
16 => {
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
Ok(Cipher::AesGcm((aes, key[..16].to_vec())))
}
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
32 => {
let aes = AesGcmCipher::new_256(key, finger);
Ok(Cipher::AesGcm((aes, key.to_vec())))
@@ -104,9 +221,14 @@ impl Cipher {
net_packet: &mut NetPacket<B>,
) -> io::Result<()> {
match self {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.decrypt_ipv4(net_packet),
#[cfg(feature = "aes_cbc")]
Cipher::AesCbc(aes_cbc) => aes_cbc.decrypt_ipv4(net_packet),
#[cfg(feature = "aes_ecb")]
Cipher::AesEcb(aes_ecb) => aes_ecb.decrypt_ipv4(net_packet),
#[cfg(feature = "sm4_cbc")]
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.decrypt_ipv4(net_packet),
Cipher::None => {
if net_packet.is_encrypt() {
return Err(io::Error::new(io::ErrorKind::Other, "not key"));
@@ -115,35 +237,101 @@ impl Cipher {
}
}
}
#[cfg(not(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
)))]
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
_net_packet: &mut NetPacket<B>,
) -> io::Result<()> {
Ok(())
}
#[cfg(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
))]
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
net_packet: &mut NetPacket<B>,
) -> io::Result<()> {
match self {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.encrypt_ipv4(net_packet),
#[cfg(feature = "aes_cbc")]
Cipher::AesCbc(aes_cbc) => aes_cbc.encrypt_ipv4(net_packet),
#[cfg(feature = "aes_ecb")]
Cipher::AesEcb(aes_ecb) => aes_ecb.encrypt_ipv4(net_packet),
#[cfg(feature = "sm4_cbc")]
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.encrypt_ipv4(net_packet),
Cipher::None => Ok(()),
}
}
#[cfg(not(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
)))]
pub fn check_finger<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
_net_packet: &NetPacket<B>,
) -> io::Result<()> {
Ok(())
}
#[cfg(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
))]
pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> io::Result<()> {
let finger = match self {
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.finger.as_ref(),
Cipher::AesCbc(aes_cbc) => aes_cbc.finger.as_ref(),
Cipher::AesEcb(aes_ecb) => aes_ecb.finger.as_ref(),
Cipher::None => None,
};
if let Some(finger) = finger {
finger.check_finger(net_packet)
} else {
Ok(())
match self {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
Cipher::AesGcm((aes_gcm, _)) => aes_gcm
.finger
.as_ref()
.map(|f| f.check_finger(net_packet))
.unwrap_or(Ok(())),
#[cfg(feature = "aes_cbc")]
Cipher::AesCbc(aes_cbc) => aes_cbc
.finger
.as_ref()
.map(|f| f.check_finger(net_packet))
.unwrap_or(Ok(())),
#[cfg(feature = "aes_ecb")]
Cipher::AesEcb(aes_ecb) => aes_ecb
.finger
.as_ref()
.map(|f| f.check_finger(net_packet))
.unwrap_or(Ok(())),
#[cfg(feature = "sm4_cbc")]
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc
.finger
.as_ref()
.map(|f| f.check_finger(net_packet))
.unwrap_or(Ok(())),
Cipher::None => Ok(()),
}
}
pub fn key(&self) -> Option<&[u8]> {
match self {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
Cipher::AesGcm((_, key)) => Some(key),
#[cfg(feature = "aes_cbc")]
Cipher::AesCbc(aes_cbc) => Some(aes_cbc.key()),
#[cfg(feature = "aes_ecb")]
Cipher::AesEcb(aes_ecb) => Some(aes_ecb.key()),
#[cfg(feature = "sm4_cbc")]
Cipher::Sm4Cbc(sm4_cbc) => Some(sm4_cbc.key()),
Cipher::None => None,
}
}
+23 -4
View File
@@ -1,18 +1,37 @@
#[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;
#[cfg(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
))]
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;
mod rsa_cipher;
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
mod openssl_aes_ecb;
#[cfg(feature = "sm4_cbc")]
mod sm4_cbc;
pub use cipher::Cipher;
pub use cipher::CipherModel;
#[cfg(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
))]
pub use finger::Finger;
pub use rsa_cipher::RsaCipher;
+4 -4
View File
@@ -105,10 +105,6 @@ impl AesEcbCipher {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if net_packet.payload().len() < 16 {
log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if let Some(finger) = &self.finger {
let mut nonce_raw = [0; 12];
@@ -129,6 +125,10 @@ impl AesEcbCipher {
}
net_packet.set_data_len(net_packet.data_len() - finger.len())?;
}
if net_packet.payload().len() < 16 {
log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let input = net_packet.payload();
let mut out = [0u8; 1024 * 5];
let mut out_len = 0;
+35 -9
View File
@@ -1,23 +1,32 @@
use crate::protocol::body::{RsaSecretBody, RSA_ENCRYPTION_RESERVED};
use crate::protocol::NetPacket;
use rand::Rng;
use rsa::pkcs8::der::Decode;
use rsa::{PublicKey, RsaPublicKey};
use sha2::Digest;
use spki::{DecodePublicKey, EncodePublicKey};
use std::io;
#[cfg(feature = "server_encrypt")]
use crate::protocol::body::{RsaSecretBody, RSA_ENCRYPTION_RESERVED};
#[cfg(feature = "server_encrypt")]
use rand::Rng;
#[cfg(feature = "server_encrypt")]
use rsa::pkcs8::der::Decode;
#[cfg(feature = "server_encrypt")]
use rsa::RsaPublicKey;
#[cfg(feature = "server_encrypt")]
use sha2::Digest;
#[cfg(feature = "server_encrypt")]
use spki::{DecodePublicKey, EncodePublicKey};
#[derive(Clone)]
pub struct RsaCipher {
#[cfg(feature = "server_encrypt")]
inner: Inner,
}
#[cfg(feature = "server_encrypt")]
#[derive(Clone)]
struct Inner {
public_key: RsaPublicKey,
}
impl RsaCipher {
#[cfg(feature = "server_encrypt")]
pub fn new(der: &[u8]) -> io::Result<Self> {
match RsaPublicKey::from_public_key_der(der) {
Ok(public_key) => {
@@ -30,9 +39,14 @@ impl RsaCipher {
)),
}
}
#[cfg(not(feature = "server_encrypt"))]
pub fn new(_der: &[u8]) -> io::Result<Self> {
unimplemented!()
}
#[cfg(feature = "server_encrypt")]
pub fn finger(&self) -> io::Result<String> {
match self.inner.public_key.to_public_key_der() {
Ok(der) => match rsa::pkcs8::SubjectPublicKeyInfo::from_der(der.as_bytes()) {
Ok(der) => match rsa::pkcs8::SubjectPublicKeyInfoRef::from_der(der.as_bytes()) {
Ok(spki) => match spki.fingerprint_base64() {
Ok(finger) => Ok(finger),
Err(e) => Err(io::Error::new(
@@ -51,9 +65,21 @@ impl RsaCipher {
)),
}
}
#[cfg(not(feature = "server_encrypt"))]
pub fn finger(&self) -> io::Result<String> {
unimplemented!()
}
}
impl RsaCipher {
#[cfg(not(feature = "server_encrypt"))]
pub fn encrypt<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
_net_packet: &mut NetPacket<B>,
) -> io::Result<NetPacket<Vec<u8>>> {
unimplemented!()
}
#[cfg(feature = "server_encrypt")]
/// net_packet 必须预留足够长度
pub fn encrypt<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
@@ -83,7 +109,7 @@ impl RsaCipher {
secret_body.set_finger(&key[16..])?;
match self.inner.public_key.encrypt(
&mut rng,
rsa::PaddingScheme::PKCS1v15Encrypt,
rsa::pkcs1v15::Pkcs1v15Encrypt,
secret_body.buffer(),
) {
Ok(enc_data) => {
+171
View File
@@ -0,0 +1,171 @@
use crate::cipher::Finger;
use crate::protocol::{NetPacket, HEAD_LEN};
use libsm::sm4::cipher_mode::CipherMode;
use libsm::sm4::Sm4CipherMode;
use rand::RngCore;
use std::io;
pub struct Sm4CbcCipher {
key: [u8; 16],
pub(crate) cipher: Sm4CipherMode,
pub(crate) finger: Option<Finger>,
}
impl Clone for Sm4CbcCipher {
fn clone(&self) -> Self {
let cipher = Sm4CipherMode::new(&self.key, CipherMode::Cbc).unwrap();
Self {
key: self.key,
cipher,
finger: self.finger.clone(),
}
}
}
impl Sm4CbcCipher {
pub fn key(&self) -> &[u8] {
&self.key
}
}
impl Sm4CbcCipher {
pub fn new_128(key: [u8; 16], finger: Option<Finger>) -> Self {
let cipher = Sm4CipherMode::new(&key, CipherMode::Cbc).unwrap();
Self {
key,
cipher,
finger,
}
}
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
net_packet: &mut NetPacket<B>,
) -> io::Result<()> {
if !net_packet.is_encrypt() {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if let Some(finger) = &self.finger {
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let len = net_packet.payload().len();
if len < 12 {
return Err(io::Error::new(io::ErrorKind::Other, "payload len <12"));
}
let secret_body = &net_packet.payload()[..len - 12];
let finger = finger.calculate_finger(&nonce_raw, secret_body);
if &finger != &net_packet.payload()[len - 12..] {
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
}
net_packet.set_data_len(net_packet.data_len() - finger.len())?;
}
let payload = net_packet.payload();
let len = payload.len();
if len < 16 || len > 1024 * 4 {
log::error!("数据异常,长度{}小于16或大于4096", len);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let mut out = [0u8; 1024 * 4];
let data = &payload[..len - 16];
let iv = &payload[len - 16..];
match self.cipher.decrypt(data, iv, &mut out) {
Ok(len) => {
let src_net_packet = NetPacket::new(&out[..len])?;
if src_net_packet.source() != net_packet.source() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.destination() != net_packet.destination() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.protocol() != net_packet.protocol() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.transport_protocol() != net_packet.transport_protocol() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.is_gateway() != net_packet.is_gateway() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
if src_net_packet.source_ttl() != net_packet.source_ttl() {
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
net_packet.set_data_len(len)?;
net_packet.set_payload(src_net_packet.payload())?;
net_packet.set_encrypt_flag(false);
Ok(())
}
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("sm4_cbc解密失败:{}", e),
)),
}
}
/// net_packet 必须预留足够长度
/// data_len是有效载荷的长度
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
net_packet: &mut NetPacket<B>,
) -> io::Result<()> {
let mut out = [0u8; 1024 * 4];
let mut iv = [0u8; 16];
rand::thread_rng().fill_bytes(&mut iv);
if net_packet.data_len() > 1024 * 4 - 32 {
log::error!(
"数据异常,长度{}大于1024 * 4 - 32",
net_packet.buffer().len()
);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
match self.cipher.encrypt(net_packet.buffer(), &iv, &mut out) {
Ok(len) => {
net_packet.set_data_len(HEAD_LEN + len + 16)?;
net_packet.payload_mut()[..len].copy_from_slice(&out[..len]);
net_packet.payload_mut()[len..].copy_from_slice(&iv);
if let Some(finger) = &self.finger {
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let finger = finger.calculate_finger(&nonce_raw, net_packet.payload());
let src_data_len = net_packet.data_len();
//设置实际长度
net_packet.set_data_len(src_data_len + finger.len())?;
net_packet.buffer_mut()[src_data_len..].copy_from_slice(&finger);
}
net_packet.set_encrypt_flag(true);
Ok(())
}
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("sm4_cbc加密失败:{}", e),
)),
}
}
}
#[test]
fn test_sm4_ecb() {
let d = Sm4CbcCipher::new_128([0; 16], Some(Finger::new("123")));
let mut p = NetPacket::new_encrypt([1; 1024]).unwrap();
let src = p.buffer().to_vec();
d.encrypt_ipv4(&mut p).unwrap();
d.decrypt_ipv4(&mut p).unwrap();
assert_eq!(p.buffer(), &src);
let d = Sm4CbcCipher::new_128([0; 16], None);
let mut p = NetPacket::new_encrypt([1; 102]).unwrap();
let src = p.buffer().to_vec();
d.encrypt_ipv4(&mut p).unwrap();
d.decrypt_ipv4(&mut p).unwrap();
assert_eq!(p.buffer(), &src)
}
+71 -52
View File
@@ -1,14 +1,14 @@
use std::collections::HashMap;
use std::io;
use std::net::TcpStream;
use std::net::UdpSocket;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::sync::Arc;
use std::time::Duration;
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap;
use parking_lot::Mutex;
use parking_lot::{Mutex, RwLock};
use rand::Rng;
use std::net::UdpSocket;
use tokio::net::TcpStream;
use tokio::sync::mpsc::channel;
use crate::channel::channel::{Channel, Context};
@@ -31,7 +31,6 @@ use crate::handle::{
CurrentDeviceInfo, PeerDeviceInfo,
};
use crate::igmp_server::IgmpServer;
use crate::ip_proxy::DashMapNew;
use crate::nat::NatTest;
use crate::tun_tap_device;
use crate::tun_tap_device::{DeviceReader, DeviceWriter};
@@ -52,13 +51,12 @@ pub struct Vnt {
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
nat_test: NatTest,
connect_status: Arc<AtomicCell<ConnectStatus>>,
peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>>,
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
}
pub struct VntUtil {
config: Config,
main_channel: UdpSocket,
main_channel_ipv6: Option<UdpSocket>,
main_tcp_channel: Option<TcpStream>,
response: Option<RegResponse>,
iface: Option<(DeviceWriter, DeviceReader)>,
@@ -67,27 +65,17 @@ pub struct VntUtil {
}
impl VntUtil {
pub async fn new(config: Config) -> io::Result<VntUtil> {
pub fn new(config: Config) -> io::Result<VntUtil> {
let address: SocketAddr = format!("[::]:{}", config.port).parse().unwrap();
//单个udp用同步的性能更好,但是代理和多端口监听用异步更方便,这里将两者结合起来
let main_channel = UdpSocket::bind("0.0.0.0:0")?;
let socket = socket2::Socket::new(socket2::Domain::IPV6, socket2::Type::DGRAM, None)?;
socket.set_only_v6(false)?;
socket.bind(&address.into())?;
let main_channel: UdpSocket = socket.into();
main_channel.set_write_timeout(Some(Duration::from_secs(5)))?;
main_channel.set_read_timeout(Some(Duration::from_secs(2)))?;
let main_channel_ipv6 = if config.punch_model != PunchModel::IPv4 {
match UdpSocket::bind("[::]:0") {
Ok(main_channel_ipv6) => {
main_channel_ipv6.set_write_timeout(Some(Duration::from_secs(5)))?;
Some(main_channel_ipv6)
}
Err(e) => {
log::warn!("绑定ipv6地址失败:{}", e);
None
}
}
} else {
None
};
let server_cipher = if config.server_encrypt {
let mut key = [0 as u8; 32];
let mut key = [0u8; 32];
rand::thread_rng().fill(&mut key);
Cipher::new_key(key, config.token.clone())?
} else {
@@ -96,7 +84,6 @@ impl VntUtil {
Ok(VntUtil {
config,
main_channel,
main_channel_ipv6,
main_tcp_channel: None,
response: None,
iface: None,
@@ -105,28 +92,28 @@ impl VntUtil {
})
}
///链接
pub async fn connect(&mut self) -> io::Result<()> {
pub fn connect(&mut self) -> io::Result<()> {
if self.config.tcp {
let tcp = TcpStream::connect(self.config.server_address).await?;
let tcp = TcpStream::connect(self.config.server_address)?;
tcp.set_read_timeout(Some(Duration::from_secs(10)))?;
let _ = self.main_tcp_channel.insert(tcp);
}
Ok(())
}
///握手 用于获取公钥
pub async fn handshake(&mut self) -> Result<Option<RsaCipher>, HandshakeEnum> {
pub fn handshake(&mut self) -> Result<Option<RsaCipher>, HandshakeEnum> {
let rsa_cipher = handshake_handler::handshake(
&self.main_channel,
self.main_tcp_channel.as_mut(),
self.config.server_address,
self.config.server_encrypt,
)
.await?;
)?;
self.rsa_cipher = rsa_cipher.clone();
Ok(rsa_cipher)
}
/// 加密握手 用于同步密钥
pub async fn secret_handshake(&mut self) -> Result<(), HandshakeEnum> {
pub fn secret_handshake(&mut self) -> Result<(), HandshakeEnum> {
handshake_handler::secret_handshake(
&self.main_channel,
self.main_tcp_channel.as_mut(),
@@ -135,10 +122,9 @@ impl VntUtil {
&self.server_cipher,
self.config.token.clone(),
)
.await
}
/// 注册
pub async fn register(&mut self) -> Result<RegResponse, ReqEnum> {
pub fn register(&mut self) -> Result<RegResponse, ReqEnum> {
match registration_handler::registration(
&self.main_channel,
self.main_tcp_channel.as_mut(),
@@ -149,9 +135,7 @@ impl VntUtil {
self.config.name.clone(),
self.config.ip.unwrap_or(Ipv4Addr::UNSPECIFIED),
self.config.password.is_some(),
)
.await
{
) {
Ok(res) => {
let _ = self.response.insert(res.clone());
Ok(res)
@@ -252,18 +236,17 @@ impl VntUtil {
let (cone_sender, cone_receiver) = channel(3);
let (symmetric_sender, symmetric_receiver) = channel(2);
let (tcp_sender, tcp) = if let Some(main_tcp_channel) = self.main_tcp_channel {
let (tcp_sender, tcp_receiver) = channel::<Vec<u8>>(100);
(Some(tcp_sender), Some((main_tcp_channel, tcp_receiver)))
let (tcp_sender, tcp_receiver) = if let Some(main_tcp_channel) = self.main_tcp_channel {
(Some(main_tcp_channel.try_clone()?), Some(main_tcp_channel))
} else {
(None, None)
};
let context = Context::new(
Arc::new(self.main_channel),
self.main_channel_ipv6.map(|v| Arc::new(v)),
self.main_channel,
tcp_sender,
current_device.clone(),
1,
config.first_latency,
);
let punch = Punch::new(context.clone(), config.punch_model);
let idle = Idle::new(Duration::from_secs(16), context.clone());
@@ -280,15 +263,15 @@ impl VntUtil {
));
let device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>> =
Arc::new(Mutex::new((response.epoch, response.device_info_list)));
let peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>> = Arc::new(DashMap::new0());
let peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>> =
Arc::new(RwLock::new(HashMap::with_capacity(16)));
let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected));
let public_ip = response.public_ip;
let public_port = response.public_port;
let local_port = context.main_local_ipv4_port().unwrap_or(0);
let local_port = context.main_local_udp_port().unwrap_or(0);
let local_ipv4_addr = crate::nat::local_ipv4_addr(local_port);
let ipv6_port = context.main_local_ipv6_port().unwrap_or(0);
let ipv6_addr = crate::nat::local_ipv6_addr(ipv6_port);
let ipv6_addr = crate::nat::local_ipv6_addr(local_port);
// NAT检测
let nat_test = NatTest::new(
config.stun_server.clone(),
@@ -302,7 +285,8 @@ impl VntUtil {
} else {
Some(ExternalRoute::new(config.in_ips))
};
let (tcp_proxy, udp_proxy, ip_proxy_map) = if config.out_ips.is_empty() {
#[cfg(feature = "ip_proxy")]
let (tcp_proxy, udp_proxy, ip_proxy_map) = if config.out_ips.is_empty() || config.no_proxy {
(None, None, None)
} else {
let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(
@@ -333,6 +317,7 @@ impl VntUtil {
igmp_server.clone(),
current_device.clone(),
in_external_route,
#[cfg(feature = "ip_proxy")]
ip_proxy_map.clone(),
client_cipher.clone(),
self.server_cipher.clone(),
@@ -347,6 +332,7 @@ impl VntUtil {
igmp_server.clone(),
current_device.clone(),
in_external_route,
#[cfg(feature = "ip_proxy")]
ip_proxy_map.clone(),
client_cipher.clone(),
self.server_cipher.clone(),
@@ -362,6 +348,7 @@ impl VntUtil {
igmp_server.clone(),
current_device.clone(),
in_external_route,
#[cfg(feature = "ip_proxy")]
ip_proxy_map.clone(),
client_cipher.clone(),
self.server_cipher.clone(),
@@ -378,6 +365,7 @@ impl VntUtil {
device_writer.clone(),
connect_status.clone(),
peer_nat_info_map.clone(),
#[cfg(feature = "ip_proxy")]
ip_proxy_map,
out_external_route,
cone_sender,
@@ -394,7 +382,7 @@ impl VntUtil {
let relay = config.relay;
tokio::spawn(async move {
channel
.start(channel_worker, tcp, 14, 65, relay, config.parallel)
.start(channel_worker, tcp_receiver, 14, 65, relay, config.parallel)
.await
});
}
@@ -403,12 +391,20 @@ impl VntUtil {
let device_list = device_list.clone();
let current_device = current_device.clone();
// 定时心跳
heartbeat_handler::start_heartbeat_main(
vnt_status_manager.worker("main-heartbeat"),
channel_sender.clone(),
device_list.clone(),
current_device.clone(),
config.server_address_str,
client_cipher.clone(),
self.server_cipher.clone(),
);
heartbeat_handler::start_heartbeat(
vnt_status_manager.worker("heartbeat"),
channel_sender.clone(),
device_list.clone(),
current_device.clone(),
config.server_address_str,
client_cipher.clone(),
self.server_cipher.clone(),
);
@@ -444,6 +440,7 @@ impl VntUtil {
));
}
}
#[cfg(feature = "ip_proxy")]
{
//代理
if let Some(tcp_proxy) = tcp_proxy {
@@ -452,6 +449,8 @@ impl VntUtil {
if let Some(udp_proxy) = udp_proxy {
tokio::spawn(udp_proxy.start());
}
}
{
let context = context.clone();
let nat_test = nat_test.clone();
tokio::spawn(async move {
@@ -489,7 +488,7 @@ impl Vnt {
self.current_device.load()
}
pub fn peer_nat_info(&self, ip: &Ipv4Addr) -> Option<NatInfo> {
self.peer_nat_info_map.get(ip).map(|e| e.value().clone())
self.peer_nat_info_map.read().get(ip).cloned()
}
pub fn connection_status(&self) -> ConnectStatus {
self.connect_status.load()
@@ -564,11 +563,15 @@ pub struct Config {
pub tcp: bool,
pub ip: Option<Ipv4Addr>,
pub relay: bool,
#[cfg(feature = "ip_proxy")]
pub no_proxy: bool,
pub server_encrypt: bool,
pub parallel: usize,
pub cipher_model: CipherModel,
pub finger: bool,
pub punch_model: PunchModel,
pub port: u16,
pub first_latency: bool,
}
impl Config {
@@ -588,18 +591,30 @@ impl Config {
tcp: bool,
ip: Option<Ipv4Addr>,
relay: bool,
#[cfg(feature = "ip_proxy")] no_proxy: bool,
server_encrypt: bool,
parallel: usize,
cipher_model: CipherModel,
finger: bool,
punch_model: PunchModel,
) -> Self {
port: u16,
first_latency: bool,
) -> Result<Self, Error> {
for x in stun_server.iter_mut() {
if !x.contains(":") {
x.push_str(":3478");
}
}
Self {
if token.is_empty() || token.len() > 128 {
return Err(Error::Stop(String::from("token too long")));
}
if device_id.is_empty() || device_id.len() > 128 {
return Err(Error::Stop(String::from("device_id too long")));
}
if name.is_empty() || name.len() > 128 {
return Err(Error::Stop(String::from("name too long")));
}
Ok(Self {
tap,
token,
device_id,
@@ -615,11 +630,15 @@ impl Config {
tcp,
ip,
relay,
#[cfg(feature = "ip_proxy")]
no_proxy,
server_encrypt,
parallel,
cipher_model,
finger,
punch_model,
}
port,
first_latency,
})
}
}
+5 -5
View File
@@ -22,20 +22,20 @@ impl VntUtilSync {
let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()?;
let vnt_util = runtime.block_on(VntUtil::new(config))?;
let vnt_util = VntUtil::new(config)?;
Ok(VntUtilSync { vnt_util, runtime })
}
pub fn connect(&mut self) -> io::Result<()> {
self.runtime.block_on(self.vnt_util.connect())
self.vnt_util.connect()
}
pub fn handshake(&mut self) -> Result<Option<RsaCipher>, HandshakeEnum> {
self.runtime.block_on(self.vnt_util.handshake())
self.vnt_util.handshake()
}
pub fn secret_handshake(&mut self) -> Result<(), HandshakeEnum> {
self.runtime.block_on(self.vnt_util.secret_handshake())
self.vnt_util.secret_handshake()
}
pub fn register(&mut self) -> Result<RegResponse, ReqEnum> {
self.runtime.block_on(self.vnt_util.register())
self.vnt_util.register()
}
#[cfg(any(target_os = "android"))]
pub fn create_iface(&mut self, vpn_fd: i32) {
+3
View File
@@ -37,6 +37,9 @@ impl AllowExternalRoute {
}
}
pub fn allow(&self, ip: &Ipv4Addr) -> bool {
if self.route_table.is_empty() {
return false;
}
let ip = u32::from_be_bytes(ip.octets());
for (dest, mask) in self.route_table.iter() {
if *mask & ip == *mask & *dest {
+26 -20
View File
@@ -1,9 +1,4 @@
use std::net::SocketAddr;
use protobuf::Message;
use std::net::UdpSocket;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
use std::net::{SocketAddr, SocketAddrV6};
use crate::channel::channel::Context;
use crate::channel::RouteKey;
@@ -11,6 +6,10 @@ use crate::cipher::{Cipher, RsaCipher};
use crate::proto::message::{HandshakeRequest, HandshakeResponse, SecretHandshakeRequest};
use crate::protocol::body::RSA_ENCRYPTION_RESERVED;
use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL};
use protobuf::Message;
use std::io::{Read, Write};
use std::net::TcpStream;
use std::net::UdpSocket;
pub enum HandshakeEnum {
NotSecret,
@@ -59,7 +58,7 @@ fn secret_handshake_request_packet(
}
/// 第一次握手,拿到公钥
pub async fn handshake(
pub fn handshake(
main_channel: &UdpSocket,
main_tcp_channel: Option<&mut TcpStream>,
server_address: SocketAddr,
@@ -74,8 +73,7 @@ pub async fn handshake(
server_address,
send_buf,
&mut recv_buf,
)
.await?;
)?;
let net_packet = match NetPacket::new(&recv_buf[..len]) {
Ok(net_packet) => net_packet,
Err(e) => {
@@ -140,7 +138,7 @@ pub async fn handshake(
}
}
async fn send_recv(
fn send_recv(
main_channel: &UdpSocket,
main_tcp_channel: Option<&mut TcpStream>,
server_address: SocketAddr,
@@ -152,34 +150,43 @@ async fn send_recv(
let len = send_buf.len();
head[2] = (len >> 8) as u8;
head[3] = (len & 0xFF) as u8;
if let Err(e) = main_tcp_channel.write_all(&head).await {
if let Err(e) = main_tcp_channel.write_all(&head) {
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
}
if let Err(e) = main_tcp_channel.write_all(send_buf).await {
if let Err(e) = main_tcp_channel.write_all(send_buf) {
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
}
if let Err(e) = main_tcp_channel.read_exact(&mut head).await {
if let Err(e) = main_tcp_channel.read_exact(&mut head) {
return Err(HandshakeEnum::Other(format!("read error:{}", e)));
}
let len = (((head[2] as u16) << 8) | head[3] as u16) as usize;
if len > recv_buf.len() {
return Err(HandshakeEnum::Other("too long".to_string()));
}
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[..len]).await {
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[..len]) {
return Err(HandshakeEnum::Other(format!("read error:{}", e)));
}
Ok(len)
} else {
let server_address = if let SocketAddr::V4(ipv4) = server_address {
SocketAddr::V6(SocketAddrV6::new(
ipv4.ip().to_ipv6_mapped(),
ipv4.port(),
0,
0,
))
} else {
server_address
};
if let Err(e) = main_channel.send_to(send_buf, server_address) {
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
}
match main_channel.recv_from(recv_buf) {
Ok((len, addr)) => {
if server_address != addr {
Err(HandshakeEnum::Other(format!("invalid data,from {}", addr)))
} else {
Ok(len)
log::warn!("请求{:?}和响应{:?}地址不一致", server_address, addr);
}
Ok(len)
}
Err(e) => Err(HandshakeEnum::Other(format!("receiver error:{}", e))),
}
@@ -187,7 +194,7 @@ async fn send_recv(
}
/// 第二次握手,同步对称密钥,后续将使用对称加密
pub async fn secret_handshake(
pub fn secret_handshake(
main_channel: &UdpSocket,
main_tcp_channel: Option<&mut TcpStream>,
server_address: SocketAddr,
@@ -213,8 +220,7 @@ pub async fn secret_handshake(
server_address,
send_buf,
&mut recv_buf,
)
.await?;
)?;
let mut net_packet = match NetPacket::new(&mut recv_buf[..len]) {
Ok(net_packet) => net_packet,
Err(e) => {
+72 -27
View File
@@ -3,15 +3,15 @@ use std::net::{Ipv4Addr, ToSocketAddrs};
use std::sync::Arc;
use std::time::Duration;
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::Mutex;
use rand::prelude::SliceRandom;
use crate::channel::idle::Idle;
use crate::channel::sender::ChannelSender;
use crate::channel::Route;
use crate::cipher::Cipher;
use crate::core::status::VntWorker;
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::Mutex;
use rand::prelude::SliceRandom;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
use crate::protocol::body::ENCRYPTION_RESERVED;
use crate::protocol::control_packet::PingPacket;
@@ -43,6 +43,29 @@ async fn start_idle_(idle: Idle, sender: ChannelSender) -> io::Result<()> {
}
pub fn start_heartbeat(
mut worker: VntWorker,
sender: ChannelSender,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
client_cipher: Cipher,
server_cipher: Cipher,
) {
tokio::spawn(async move {
tokio::select! {
_=worker.stop_wait()=>{
return;
}
rs=start_heartbeat_(sender, device_list, current_device,client_cipher,server_cipher)=>{
if let Err(e) = rs {
log::warn!("心跳任务停止:{:?}", e);
}
}
}
worker.stop_all();
});
}
pub fn start_heartbeat_main(
mut worker: VntWorker,
sender: ChannelSender,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
@@ -56,11 +79,11 @@ pub fn start_heartbeat(
_=worker.stop_wait()=>{
return;
}
rs=start_heartbeat_(sender, device_list, current_device,server_address_str,client_cipher,server_cipher)=>{
rs=start_heartbeat_main_(sender, device_list, current_device,server_address_str,client_cipher,server_cipher)=>{
if let Err(e) = rs {
log::warn!("心跳任务停止:{:?}", e);
log::warn!("心跳任务停止:{:?}", e);
}
}
}
}
worker.stop_all();
});
@@ -97,7 +120,7 @@ fn heartbeat_packet(
net_packet
}
async fn start_heartbeat_(
async fn start_heartbeat_main_(
sender: ChannelSender,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
@@ -106,26 +129,14 @@ async fn start_heartbeat_(
server_cipher: Cipher,
) -> io::Result<()> {
let mut count = 0;
log::info!("启动心跳任务");
log::info!("启动心跳任务");
loop {
if sender.is_close() {
return Ok(());
}
let mut current_dev = current_device.load();
//如果和服务端使用tcp连接,则维持udp洞的频率要更高些
if (sender.is_main_tcp() && count % 2 == 0) || (!sender.is_main_tcp() && count % 20 == 1) {
let mut packet = NetPacket::new_encrypt([0; 12 + ENCRYPTION_RESERVED])?;
packet.set_version(Version::V1);
packet.set_gateway_flag(true);
packet.set_protocol(Protocol::Control);
packet.set_transport_protocol(control_packet::Protocol::AddrRequest.into());
packet.first_set_ttl(MAX_TTL);
packet.set_source(current_dev.virtual_ip());
packet.set_destination(current_dev.virtual_gateway);
server_cipher.encrypt_ipv4(&mut packet)?;
let _ = sender.send_main_udp(packet.buffer(), current_dev.connect_server);
}
if count % 20 == 19 {
let src = current_dev.virtual_ip();
if count % 40 == 19 {
if let Ok(mut addr) = server_address_str.to_socket_addrs() {
if let Some(addr) = addr.next() {
if addr != current_dev.connect_server {
@@ -143,7 +154,6 @@ async fn start_heartbeat_(
}
}
}
let src = current_dev.virtual_ip();
let server_packet = heartbeat_packet(
MAX_TTL,
&device_list,
@@ -156,7 +166,42 @@ async fn start_heartbeat_(
if let Err(e) = sender.send_main(server_packet.buffer(), current_dev.connect_server) {
log::warn!("connect_server:{:?},e:{:?}", current_dev.connect_server, e);
}
if count < 7 || count % 7 == 0 {
count += 1;
tokio::time::sleep(Duration::from_millis(3000)).await;
}
}
async fn start_heartbeat_(
sender: ChannelSender,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
client_cipher: Cipher,
server_cipher: Cipher,
) -> io::Result<()> {
let mut count = 0;
log::info!("启动心跳任务");
loop {
if sender.is_close() {
return Ok(());
}
let current_dev = current_device.load();
//如果和服务端使用tcp连接,则维持udp洞的频率要更高些
if (sender.is_main_tcp() && count % 4 == 0) || (!sender.is_main_tcp() && count % 40 == 1) {
let mut packet = NetPacket::new_encrypt([0; 12 + ENCRYPTION_RESERVED])?;
packet.set_version(Version::V1);
packet.set_gateway_flag(true);
packet.set_protocol(Protocol::Control);
packet.set_transport_protocol(control_packet::Protocol::AddrRequest.into());
packet.first_set_ttl(MAX_TTL);
packet.set_source(current_dev.virtual_ip());
packet.set_destination(current_dev.virtual_gateway);
server_cipher.encrypt_ipv4(&mut packet)?;
let _ = sender.send_main_udp(packet.buffer(), current_dev.connect_server);
}
let src = current_dev.virtual_ip();
if count % 10 == 7 {
let mut route_list: Option<Vec<(Ipv4Addr, Vec<Route>)>> = None;
let peer_list = { device_list.lock().1.clone() };
for peer in peer_list {
@@ -178,7 +223,7 @@ async fn start_heartbeat_(
{
log::warn!("virtual_ip:{},route:{:?},e:{:?}", peer.virtual_ip, route, e);
}
if route.is_p2p() {
if route.is_p2p() && !sender.is_first_latency() {
continue;
}
} else {
@@ -251,6 +296,6 @@ async fn start_heartbeat_(
}
count += 1;
tokio::time::sleep(Duration::from_millis(5000)).await;
tokio::time::sleep(Duration::from_millis(3000)).await;
}
}
+85 -155
View File
@@ -1,9 +1,10 @@
use std::collections::HashMap;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
use std::sync::Arc;
use std::time::{Duration, Instant};
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap;
use parking_lot::Mutex;
use parking_lot::{Mutex, RwLock};
use protobuf::Message;
use tokio::sync::mpsc::Sender;
@@ -21,7 +22,8 @@ use crate::handle::handshake_handler::secret_handshake_req;
use crate::handle::registration_handler::Register;
use crate::handle::{ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo, PeerDeviceStatus};
use crate::igmp_server::IgmpServer;
use crate::ip_proxy::IpProxyMap;
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::{IpProxyMap, ProxyHandler};
use crate::nat;
use crate::nat::NatTest;
use crate::proto::message::{DeviceList, PunchInfo, PunchNatType, RegistrationResponse};
@@ -43,7 +45,8 @@ pub struct ChannelDataHandler {
igmp_server: Option<IgmpServer>,
device_writer: DeviceWriter,
connect_status: Arc<AtomicCell<ConnectStatus>>,
peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>>,
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
#[cfg(feature = "ip_proxy")]
ip_proxy_map: Option<IpProxyMap>,
out_external_route: AllowExternalRoute,
cone_sender: Sender<(Ipv4Addr, NatInfo)>,
@@ -53,6 +56,7 @@ pub struct ChannelDataHandler {
rsa_cipher: Option<RsaCipher>,
relay: bool,
token: String,
time: Arc<AtomicCell<Instant>>,
}
impl ChannelDataHandler {
@@ -64,8 +68,8 @@ impl ChannelDataHandler {
igmp_server: Option<IgmpServer>,
device_writer: DeviceWriter,
connect_status: Arc<AtomicCell<ConnectStatus>>,
peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>>,
ip_proxy_map: Option<IpProxyMap>,
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
out_external_route: AllowExternalRoute,
cone_sender: Sender<(Ipv4Addr, NatInfo)>,
symmetric_sender: Sender<(Ipv4Addr, NatInfo)>,
@@ -84,6 +88,7 @@ impl ChannelDataHandler {
device_writer,
connect_status,
peer_nat_info_map,
#[cfg(feature = "ip_proxy")]
ip_proxy_map,
out_external_route,
cone_sender,
@@ -93,12 +98,13 @@ impl ChannelDataHandler {
rsa_cipher,
relay,
token,
time: Arc::new(AtomicCell::new(Instant::now())),
}
}
}
impl ChannelDataHandler {
pub async fn handle(
pub fn handle(
&self,
buf: &mut [u8],
start: usize,
@@ -107,14 +113,14 @@ impl ChannelDataHandler {
context: &Context,
) {
assert_eq!(start, 14);
match self.handle0(&mut buf[..end], &route_key, context).await {
match self.handle0(&mut buf[..end], &route_key, context) {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e);
}
}
}
async fn handle0(
fn handle0(
&self,
buf: &mut [u8],
route_key: &RouteKey,
@@ -132,6 +138,7 @@ impl ChannelDataHandler {
&& !destination.is_multicast()
&& destination != current_device.broadcast_address;
if current_device.virtual_ip() != destination
&& !net_packet.is_gateway()
&& not_broadcast
&& !destination.is_unspecified()
{
@@ -160,6 +167,14 @@ impl ChannelDataHandler {
== crate::protocol::error_packet::Protocol::NoKey.into()
{
if let Some(rsa_cipher) = &self.rsa_cipher {
let last = self.time.load();
if last.elapsed() < Duration::from_secs(3)
|| self.time.compare_exchange(last, Instant::now()).is_err()
{
//短时间不重复上传服务端密钥
return Ok(());
}
log::warn!("上传服务端密钥");
secret_handshake_req(
context,
current_device.connect_server,
@@ -173,8 +188,7 @@ impl ChannelDataHandler {
//服务端解密
self.server_cipher.decrypt_ipv4(&mut net_packet)?;
let data_len = net_packet.data_len();
self.server_packet_handle(context, current_device, buf, data_len, route_key)
.await?;
self.server_packet_handle(context, current_device, buf, data_len, route_key)?;
}
return Ok(());
}
@@ -214,89 +228,22 @@ impl ChannelDataHandler {
_ => {}
}
if not_broadcast && ipv4.destination_ip() != destination {
if let Some(ip_proxy_map) = &self.ip_proxy_map {
if self.out_external_route.allow(&ipv4.destination_ip()) {
match ipv4.protocol() {
ipv4::protocol::Protocol::Tcp => {
let dest_ip = ipv4.destination_ip();
//转发到代理目标地址
let mut tcp_packet = packet::tcp::tcp::TcpPacket::new(
source,
destination,
ipv4.payload_mut(),
)?;
let source_port = tcp_packet.source_port();
let dest_port = tcp_packet.destination_port();
tcp_packet
.set_destination_port(ip_proxy_map.tcp_proxy_port);
tcp_packet.update_checksum();
ipv4.set_destination_ip(destination);
ipv4.update_checksum();
let key = SocketAddrV4::new(source, source_port);
//https://github.com/crossbeam-rs/crossbeam/issues/1023
ip_proxy_map
.tcp_proxy_map
.insert(key, SocketAddrV4::new(dest_ip, dest_port));
}
ipv4::protocol::Protocol::Udp => {
let dest_ip = ipv4.destination_ip();
//转发到代理目标地址
let mut udp_packet = packet::udp::udp::UdpPacket::new(
source,
destination,
ipv4.payload_mut(),
)?;
let source_port = udp_packet.source_port();
let dest_port = udp_packet.destination_port();
udp_packet
.set_destination_port(ip_proxy_map.udp_proxy_port);
udp_packet.update_checksum();
ipv4.set_destination_ip(destination);
ipv4.update_checksum();
let key = SocketAddrV4::new(source, source_port);
ip_proxy_map
.udp_proxy_map
.insert(key, SocketAddrV4::new(dest_ip, dest_port));
}
#[cfg(not(target_os = "android"))]
ipv4::protocol::Protocol::Icmp => {
let dest_ip = ipv4.destination_ip();
//转发到代理目标地址
let icmp_packet =
icmp::IcmpPacket::new(ipv4.payload())?;
match icmp_packet.header_other() {
icmp::HeaderOther::Identifier(id, seq) => {
ip_proxy_map
.icmp_proxy_map
.insert((dest_ip, id, seq), source);
ip_proxy_map
.send_icmp(ipv4.payload(), &dest_ip)?;
}
_ => {
log::warn!(
"不支持的ip代理Icmp协议:{}",
destination
);
return Err(Error::Warn(
"不支持的ip代理Icmp协议".to_string(),
));
}
}
}
_ => {
log::warn!("不支持的ip代理ipv4协议:{}", destination);
return Err(Error::Warn(
"不支持的ip代理ipv4协议".to_string(),
));
}
if self.out_external_route.allow(&ipv4.destination_ip()) {
#[cfg(feature = "ip_proxy")]
if let Some(ip_proxy_map) = &self.ip_proxy_map {
if ip_proxy_map.recv_handle(&mut ipv4, source, destination)? {
return Ok(());
}
} else {
log::warn!("没有ip代理规则:{}", destination);
return Err(Error::Warn("没有ip代理规则".to_string()));
}
} else {
log::warn!("不支持ip代理:{}", destination);
return Err(Error::Warn("不支持ip代理".to_string()));
log::warn!(
"没有ip代理规则{:?}:{}->{}->{}",
ipv4.protocol(),
source,
destination,
ipv4.destination_ip()
);
return Err(Error::Warn("没有ip代理规则".to_string()));
}
}
@@ -313,12 +260,10 @@ impl ChannelDataHandler {
Protocol::Service => {}
Protocol::Error => {}
Protocol::Control => {
self.control(context, current_device, source, net_packet, route_key)
.await?;
self.control(context, current_device, source, net_packet, route_key)?;
}
Protocol::OtherTurn => {
self.other_turn(context, current_device, source, net_packet, route_key)
.await?;
self.other_turn(context, current_device, source, net_packet, route_key)?;
}
Protocol::UnKnow(e) => {
log::info!("不支持的协议:{}", e);
@@ -327,7 +272,7 @@ impl ChannelDataHandler {
Ok(())
}
async fn pong_packet(
fn pong_packet(
&self,
gateway: bool,
metric: u8,
@@ -361,7 +306,7 @@ impl ChannelDataHandler {
}
Ok(())
}
async fn control(
fn control(
&self,
context: &Context,
current_device: CurrentDeviceInfo,
@@ -390,8 +335,7 @@ impl ChannelDataHandler {
source,
pong_packet,
route_key,
)
.await?;
)?;
}
ControlPacket::PunchRequest => {
if self.relay {
@@ -431,22 +375,13 @@ impl ChannelDataHandler {
}
std::net::IpAddr::V6(_) => {}
},
ControlPacket::AddrResponse(addr_packet) => {
if !addr_packet.ipv4().is_multicast()
&& !addr_packet.ipv4().is_broadcast()
&& !addr_packet.ipv4().is_unspecified()
&& !addr_packet.ipv4().is_loopback()
&& !addr_packet.ipv4().is_private()
&& addr_packet.port() != 0
{
self.nat_test
.update_addr(addr_packet.ipv4(), addr_packet.port())
}
}
ControlPacket::AddrResponse(addr_packet) => self
.nat_test
.update_addr(addr_packet.ipv4(), addr_packet.port()),
}
Ok(())
}
async fn other_turn(
fn other_turn(
&self,
context: &Context,
current_device: CurrentDeviceInfo,
@@ -484,7 +419,10 @@ impl ChannelDataHandler {
ipv6_addr,
punch_info.nat_type.enum_value_or_default().into(),
);
self.peer_nat_info_map.insert(source, peer_nat_info.clone());
{
let peer_nat_info = peer_nat_info.clone();
self.peer_nat_info_map.write().insert(source, peer_nat_info);
}
if !punch_info.reply {
let mut punch_reply = PunchInfo::new();
punch_reply.reply = true;
@@ -527,12 +465,12 @@ impl ChannelDataHandler {
// let _ = context.try_send_main_udp(packet.buffer(),
// SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port)));
// }
if self.punch(source, peer_nat_info).await {
if self.punch(source, peer_nat_info) {
self.client_cipher.encrypt_ipv4(&mut punch_packet)?;
context.try_send_by_key(punch_packet.buffer(), route_key)?;
}
} else {
self.punch(source, peer_nat_info).await;
self.punch(source, peer_nat_info);
}
}
other_turn_packet::Protocol::Unknown(e) => {
@@ -541,7 +479,7 @@ impl ChannelDataHandler {
}
Ok(())
}
async fn punch(&self, peer_ip: Ipv4Addr, peer_nat_info: NatInfo) -> bool {
fn punch(&self, peer_ip: Ipv4Addr, peer_nat_info: NatInfo) -> bool {
match peer_nat_info.nat_type {
NatType::Symmetric => self
.symmetric_sender
@@ -554,7 +492,7 @@ impl ChannelDataHandler {
/// 处理服务端数据
impl ChannelDataHandler {
async fn server_packet_handle(
fn server_packet_handle(
&self,
context: &Context,
current_device: CurrentDeviceInfo,
@@ -566,16 +504,13 @@ impl ChannelDataHandler {
let source = net_packet.source();
match net_packet.protocol() {
Protocol::Service => {
self.service(context, current_device, net_packet, route_key)
.await?;
self.service(context, current_device, net_packet, route_key)?;
}
Protocol::Error => {
self.error(context, current_device, source, net_packet, route_key)
.await?;
self.error(context, current_device, source, net_packet, route_key)?;
}
Protocol::Control => {
self.control_gateway(context, current_device, net_packet, route_key)
.await?;
self.control_gateway(context, current_device, net_packet, route_key)?;
}
Protocol::IpTurn => {
match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) {
@@ -609,7 +544,7 @@ impl ChannelDataHandler {
}
return Ok(());
}
async fn control_gateway(
fn control_gateway(
&self,
context: &Context,
current_device: CurrentDeviceInfo,
@@ -627,26 +562,16 @@ impl ChannelDataHandler {
net_packet.source(),
pong_packet,
route_key,
)
.await?;
}
ControlPacket::AddrResponse(addr_packet) => {
if addr_packet.port() != 0
&& !addr_packet.ipv4().is_multicast()
&& !addr_packet.ipv4().is_broadcast()
&& !addr_packet.ipv4().is_unspecified()
&& !addr_packet.ipv4().is_loopback()
&& !addr_packet.ipv4().is_private()
{
self.nat_test
.update_addr(addr_packet.ipv4(), addr_packet.port())
}
)?;
}
ControlPacket::AddrResponse(addr_packet) => self
.nat_test
.update_addr(addr_packet.ipv4(), addr_packet.port()),
_ => {}
}
Ok(())
}
async fn service(
fn service(
&self,
context: &Context,
current_device: CurrentDeviceInfo,
@@ -658,23 +583,28 @@ impl ChannelDataHandler {
service_packet::Protocol::RegistrationResponse => {
let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?;
{
if self.nat_test.can_update() {
let context = context.clone();
let nat_test = self.nat_test.clone();
tokio::spawn(async move {
let local_port = context.main_local_ipv4_port().unwrap_or(0);
let local_ipv4_addr = nat::local_ipv4_addr(local_port);
let local_port = context.main_local_ipv6_port().unwrap_or(0);
let ipv6_addr = nat::local_ipv6_addr(local_port);
let nat_info = nat_test
.re_test(
Ipv4Addr::from(response.public_ip),
response.public_port as u16,
local_ipv4_addr,
ipv6_addr,
)
.await;
context.switch(nat_info.nat_type);
std::thread::spawn(move || {
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(async move {
let local_port = context.main_local_udp_port().unwrap_or(0);
let local_ipv4_addr = nat::local_ipv4_addr(local_port);
let ipv6_addr = nat::local_ipv6_addr(local_port);
let nat_info = nat_test
.re_test(
Ipv4Addr::from(response.public_ip),
response.public_port as u16,
local_ipv4_addr,
ipv6_addr,
)
.await;
context.switch(nat_info.nat_type);
})
});
}
let new_ip = Ipv4Addr::from(response.virtual_ip);
@@ -746,7 +676,7 @@ impl ChannelDataHandler {
}
Ok(())
}
async fn error(
fn error(
&self,
_context: &Context,
current_device: CurrentDeviceInfo,
+18 -9
View File
@@ -1,14 +1,14 @@
use crossbeam_utils::atomic::AtomicCell;
use std::net::{Ipv4Addr, SocketAddr};
use std::io::{Read, Write};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV6};
use std::time::{Duration, Instant};
use crate::channel::sender::ChannelSender;
use crate::cipher::Cipher;
use crate::handle::PeerDeviceInfo;
use protobuf::Message;
use std::net::TcpStream;
use std::net::UdpSocket;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
use crate::proto::message::{RegistrationRequest, RegistrationResponse};
use crate::protocol::body::ENCRYPTION_RESERVED;
@@ -37,7 +37,7 @@ pub struct RegResponse {
}
///向中继服务器注册,token标识一个虚拟网关,device_id防止多次注册时得到的ip不一致
pub async fn registration(
pub fn registration(
main_channel: &UdpSocket,
main_tcp_channel: Option<&mut TcpStream>,
server_cipher: &Cipher,
@@ -67,28 +67,37 @@ pub async fn registration(
vec[2] = (len >> 8) as u8;
vec[3] = (len & 0xFF) as u8;
vec[4..].copy_from_slice(buf);
if let Err(e) = main_tcp_channel.write_all(&vec).await {
if let Err(e) = main_tcp_channel.write_all(&vec) {
return Err(ReqEnum::Other(format!("send error:{}", e)));
}
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[..4]).await {
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[..4]) {
return Err(ReqEnum::Other(format!("read error:{}", e)));
}
let len = 4 + (((recv_buf[2] as u16) << 8) | recv_buf[3] as u16) as usize;
if len > recv_buf.len() {
return Err(ReqEnum::Other("too long".to_string()));
}
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[4..len]).await {
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[4..len]) {
return Err(ReqEnum::Other(format!("read error:{}", e)));
}
&mut recv_buf[4..len]
} else {
let server_address = match server_address {
SocketAddr::V4(ipv4) => SocketAddr::V6(SocketAddrV6::new(
ipv4.ip().to_ipv6_mapped(),
ipv4.port(),
0,
0,
)),
SocketAddr::V6(_) => server_address,
};
if let Err(e) = main_channel.send_to(buf, server_address) {
return Err(ReqEnum::Other(format!("send error:{}", e)));
}
match main_channel.recv_from(&mut recv_buf) {
Ok((len, addr)) => {
if server_address != addr {
return Err(ReqEnum::Other(format!("invalid data,from {}", addr)));
log::warn!("请求{:?}和响应{:?}地址不一致", server_address, addr);
}
&mut recv_buf[..len]
}
@@ -229,7 +238,7 @@ impl Register {
}
pub fn fast_register(&self, ip: Ipv4Addr) -> crate::Result<()> {
let last = self.time.load();
if last.elapsed() < Duration::from_secs(2)
if last.elapsed() < Duration::from_secs(3)
|| self.time.compare_exchange(last, Instant::now()).is_err()
{
//短时间不重复注册
+4 -6
View File
@@ -1,15 +1,13 @@
use byte_pool::Block;
#[derive(Clone)]
pub struct BufSenderGroup(
usize,
Vec<std::sync::mpsc::SyncSender<(Block<'static>, usize, usize)>>,
Vec<std::sync::mpsc::SyncSender<(Vec<u8>, usize, usize)>>,
);
pub struct BufReceiverGroup(pub Vec<std::sync::mpsc::Receiver<(Block<'static>, usize, usize)>>);
pub struct BufReceiverGroup(pub Vec<std::sync::mpsc::Receiver<(Vec<u8>, usize, usize)>>);
impl BufSenderGroup {
pub fn send(&mut self, val: (Block<'static>, usize, usize)) -> bool {
pub fn send(&mut self, val: (Vec<u8>, usize, usize)) -> bool {
let index = self.0 % self.1.len();
self.0 = self.0.wrapping_add(1);
self.1[index].send(val).is_ok()
@@ -21,7 +19,7 @@ pub fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) {
let mut buf_receiver_group = Vec::with_capacity(size);
for _ in 0..size {
let (buf_sender, buf_receiver) =
std::sync::mpsc::sync_channel::<(Block<'static>, usize, usize)>(1);
std::sync::mpsc::sync_channel::<(Vec<u8>, usize, usize)>(1);
buf_sender_group.push(buf_sender);
buf_receiver_group.push(buf_receiver);
}
+18 -70
View File
@@ -1,22 +1,23 @@
use std::net::Ipv4Addr;
use std::sync::Arc;
use parking_lot::RwLock;
use packet::ip::ipv4::packet::IpV4Packet;
use packet::ip::ipv4::protocol::Protocol;
use crate::channel::sender::ChannelSender;
use crate::cipher::Cipher;
use crate::error::*;
use crate::external_route::ExternalRoute;
use crate::handle::{check_dest, CurrentDeviceInfo};
use crate::igmp_server::{IgmpServer, Multicast};
use crate::ip_proxy::IpProxyMap;
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::{IpProxyMap, ProxyHandler};
use crate::protocol;
use crate::protocol::body::ENCRYPTION_RESERVED;
use crate::protocol::ip_turn_packet::BroadcastPacket;
use crate::protocol::{ip_turn_packet, NetPacket, Version, MAX_TTL};
use packet::ip::ipv4::packet::IpV4Packet;
use packet::ip::ipv4::protocol::Protocol;
use packet::tcp::tcp::TcpPacket;
use packet::udp::udp::UdpPacket;
use parking_lot::RwLock;
use std::io;
use std::net::{Ipv4Addr, SocketAddrV4};
use std::sync::Arc;
pub mod channel_group;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
@@ -64,10 +65,8 @@ fn broadcast(
if peer_ips.is_empty() {
sender.send_main(net_packet.buffer(), current_device.connect_server)?;
} else {
let buf = vec![
0 as u8;
12 + 1 + peer_ips.len() * 4 + net_packet.data_len() + ENCRYPTION_RESERVED
];
let buf =
vec![0u8; 12 + 1 + peer_ips.len() * 4 + net_packet.data_len() + ENCRYPTION_RESERVED];
//剩余的发送到服务端,需要告知哪些已发送过
let mut server_packet = NetPacket::new_encrypt(buf)?;
server_packet.set_version(Version::V1);
@@ -99,16 +98,12 @@ pub fn base_handle(
igmp_server: &Option<IgmpServer>,
current_device: CurrentDeviceInfo,
ip_route: &Option<ExternalRoute>,
proxy_map: &Option<IpProxyMap>,
#[cfg(feature = "ip_proxy")] proxy_map: &Option<IpProxyMap>,
client_cipher: &Cipher,
server_cipher: &Cipher,
) -> Result<()> {
let ipv4_packet = IpV4Packet::new(&buf[12..data_len])?;
let protocol = ipv4_packet.protocol();
let ip_head_len = ipv4_packet.header_len() as usize * 4;
if 12 + ip_head_len >= data_len {
Err(io::Error::new(io::ErrorKind::Other, "ip_head_len err"))?
}
let src_ip = ipv4_packet.source_ip();
let mut dest_ip = ipv4_packet.destination_ip();
let mut net_packet = NetPacket::new0(data_len, buf)?;
@@ -190,58 +185,11 @@ pub fn base_handle(
} else {
return Ok(());
}
} else if let Some(proxy_map) = proxy_map {
match protocol {
Protocol::Tcp => {
let dest_addr = {
let tcp_packet = TcpPacket::new(
src_ip,
dest_ip,
&mut net_packet.payload_mut()[ip_head_len..],
)?;
SocketAddrV4::new(dest_ip, tcp_packet.destination_port())
};
if let Some(entry) = proxy_map.tcp_proxy_map.get(&dest_addr) {
let source_addr = entry.value();
let source_ip = *source_addr.ip();
let mut tcp_packet = TcpPacket::new(
source_ip,
dest_ip,
&mut net_packet.payload_mut()[ip_head_len..],
)?;
tcp_packet.set_source_port(source_addr.port());
tcp_packet.update_checksum();
let mut ipv4_packet = IpV4Packet::new(net_packet.payload_mut())?;
ipv4_packet.set_source_ip(source_ip);
ipv4_packet.update_checksum();
}
}
Protocol::Udp => {
let dest_addr = {
let udp_packet = UdpPacket::new(
src_ip,
dest_ip,
&mut net_packet.payload_mut()[ip_head_len..],
)?;
SocketAddrV4::new(dest_ip, udp_packet.destination_port())
};
if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) {
let source_addr = entry.value();
let source_ip = *source_addr.ip();
let mut udp_packet = UdpPacket::new(
source_ip,
dest_ip,
&mut net_packet.payload_mut()[ip_head_len..],
)?;
udp_packet.set_source_port(source_addr.port());
udp_packet.update_checksum();
let mut ipv4_packet = IpV4Packet::new(net_packet.payload_mut())?;
ipv4_packet.set_source_ip(source_ip);
ipv4_packet.update_checksum();
}
}
_ => {}
}
}
#[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)?;
//优先发到直连到地址
+13 -12
View File
@@ -1,9 +1,7 @@
use byte_pool::BytePool;
use std::sync::Arc;
use std::{io, thread};
use crossbeam_utils::atomic::AtomicCell;
use lazy_static::lazy_static;
use packet::arp::arp::ArpPacket;
use packet::ethernet;
@@ -20,11 +18,9 @@ use crate::external_route::ExternalRoute;
use crate::handle::tun_tap::channel_group::{buf_channel_group, BufSenderGroup};
use crate::handle::CurrentDeviceInfo;
use crate::igmp_server::IgmpServer;
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::IpProxyMap;
use crate::tun_tap_device::{DeviceReader, DeviceWriter};
lazy_static! {
static ref POOL: BytePool<Vec<u8>> = BytePool::<Vec<u8>>::new();
}
pub fn start(
worker: VntWorker,
@@ -34,7 +30,7 @@ pub fn start(
igmp_server: Option<IgmpServer>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: Option<ExternalRoute>,
ip_proxy_map: Option<IpProxyMap>,
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
client_cipher: Cipher,
server_cipher: Cipher,
parallel: usize,
@@ -50,6 +46,7 @@ pub fn start(
igmp_server,
current_device,
ip_route,
#[cfg(feature = "ip_proxy")]
ip_proxy_map,
client_cipher,
server_cipher,
@@ -69,6 +66,7 @@ pub fn start(
let igmp_server = igmp_server.clone();
let current_device = current_device.clone();
let ip_route = ip_route.clone();
#[cfg(feature = "ip_proxy")]
let ip_proxy_map = ip_proxy_map.clone();
let client_cipher = client_cipher.clone();
let server_cipher = server_cipher.clone();
@@ -82,6 +80,7 @@ pub fn start(
&device_writer,
&sender,
&ip_route,
#[cfg(feature = "ip_proxy")]
&ip_proxy_map,
&client_cipher,
&server_cipher,
@@ -116,7 +115,7 @@ fn start_(
mut buf_sender: BufSenderGroup,
) -> io::Result<()> {
loop {
let mut buf = POOL.alloc(4096);
let mut buf = vec![0; 4096];
if sender.is_close() {
return Ok(());
}
@@ -138,12 +137,15 @@ fn start_simple(
igmp_server: Option<IgmpServer>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: Option<ExternalRoute>,
ip_proxy_map: Option<IpProxyMap>,
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
client_cipher: Cipher,
server_cipher: Cipher,
) -> io::Result<()> {
let mut buf = [0; 4096];
loop {
if sender.is_close() {
return Ok(());
}
let len = device_reader.read(&mut buf)?;
if let Err(e) = handle(
&mut buf,
@@ -153,6 +155,7 @@ fn start_simple(
device_writer,
sender,
&ip_route,
#[cfg(feature = "ip_proxy")]
&ip_proxy_map,
&client_cipher,
&server_cipher,
@@ -170,7 +173,7 @@ fn handle(
device_writer: &DeviceWriter,
sender: &ChannelSender,
ip_route: &Option<ExternalRoute>,
proxy_map: &Option<IpProxyMap>,
#[cfg(feature = "ip_proxy")] proxy_map: &Option<IpProxyMap>,
client_cipher: &Cipher,
server_cipher: &Cipher,
) -> crate::Result<()> {
@@ -215,9 +218,6 @@ fn handle(
ethernet::protocol::Protocol::Ipv4 => {
let mut ipv4_packet = IpV4Packet::unchecked(ethernet_packet.payload_mut());
let src_ip = ipv4_packet.source_ip();
if src_ip != current_device.virtual_ip() {
return Ok(());
}
let dest_ip = ipv4_packet.destination_ip();
let protocol = ipv4_packet.protocol();
if src_ip == dest_ip {
@@ -246,6 +246,7 @@ fn handle(
igmp_server,
current_device,
ip_route,
#[cfg(feature = "ip_proxy")]
proxy_map,
client_cipher,
server_cipher,
+11 -16
View File
@@ -1,4 +1,3 @@
use byte_pool::BytePool;
use std::sync::Arc;
use std::{io, thread};
@@ -17,11 +16,9 @@ use crate::external_route::ExternalRoute;
use crate::handle::tun_tap::channel_group::{buf_channel_group, BufSenderGroup};
use crate::handle::CurrentDeviceInfo;
use crate::igmp_server::IgmpServer;
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::IpProxyMap;
use crate::tun_tap_device::{DeviceReader, DeviceWriter};
lazy_static::lazy_static! {
static ref POOL:BytePool<Vec<u8>> = BytePool::<Vec<u8>>::new();
}
fn icmp(device_writer: &DeviceWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Result<()> {
if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp {
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
@@ -48,20 +45,13 @@ fn handle(
igmp_server: &Option<IgmpServer>,
current_device: CurrentDeviceInfo,
ip_route: &Option<ExternalRoute>,
proxy_map: &Option<IpProxyMap>,
#[cfg(feature = "ip_proxy")] proxy_map: &Option<IpProxyMap>,
client_cipher: &Cipher,
server_cipher: &Cipher,
) -> Result<()> {
let ipv4_packet = if let Ok(ipv4_packet) = IpV4Packet::new(&mut data[12..len]) {
ipv4_packet
} else {
return Ok(());
};
let ipv4_packet = IpV4Packet::new(&mut data[12..len])?;
let src_ip = ipv4_packet.source_ip();
let dest_ip = ipv4_packet.destination_ip();
if src_ip != current_device.virtual_ip() {
return Ok(());
}
if src_ip == dest_ip {
return icmp(&device_writer, ipv4_packet);
}
@@ -72,6 +62,7 @@ fn handle(
igmp_server,
current_device,
ip_route,
#[cfg(feature = "ip_proxy")]
proxy_map,
client_cipher,
server_cipher,
@@ -86,7 +77,7 @@ pub fn start(
igmp_server: Option<IgmpServer>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: Option<ExternalRoute>,
ip_proxy_map: Option<IpProxyMap>,
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
client_cipher: Cipher,
server_cipher: Cipher,
parallel: usize,
@@ -102,6 +93,7 @@ pub fn start(
igmp_server,
current_device,
ip_route,
#[cfg(feature = "ip_proxy")]
ip_proxy_map,
client_cipher,
server_cipher,
@@ -121,6 +113,7 @@ pub fn start(
let igmp_server = igmp_server.clone();
let current_device = current_device.clone();
let ip_route = ip_route.clone();
#[cfg(feature = "ip_proxy")]
let ip_proxy_map = ip_proxy_map.clone();
let client_cipher = client_cipher.clone();
let server_cipher = server_cipher.clone();
@@ -134,6 +127,7 @@ pub fn start(
&igmp_server,
current_device.load(),
&ip_route,
#[cfg(feature = "ip_proxy")]
&ip_proxy_map,
&client_cipher,
&server_cipher,
@@ -169,7 +163,7 @@ fn start_(
mut buf_sender: BufSenderGroup,
) -> io::Result<()> {
loop {
let mut buf = POOL.alloc(4096);
let mut buf = vec![0; 4096];
buf[..12].fill(0);
if sender.is_close() {
return Ok(());
@@ -194,7 +188,7 @@ fn start_simple(
igmp_server: Option<IgmpServer>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: Option<ExternalRoute>,
ip_proxy_map: Option<IpProxyMap>,
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
client_cipher: Cipher,
server_cipher: Cipher,
) -> io::Result<()> {
@@ -215,6 +209,7 @@ fn start_simple(
&igmp_server,
current_device.load(),
&ip_route,
#[cfg(feature = "ip_proxy")]
&ip_proxy_map,
&client_cipher,
&server_cipher,
+16 -26
View File
@@ -3,7 +3,6 @@ use std::net::Ipv4Addr;
use std::sync::Arc;
use std::time::{Duration, Instant};
use dashmap::DashMap;
use parking_lot::RwLock;
use packet::igmp::igmp_v2::IgmpV2Packet;
@@ -11,7 +10,6 @@ use packet::igmp::igmp_v3::{IgmpV3QueryPacket, IgmpV3RecordType, IgmpV3ReportPac
use packet::igmp::IgmpType;
use packet::ip::ipv4::protocol::Protocol;
use crate::ip_proxy::DashMapNew;
use crate::tun_tap_device::DeviceWriter;
//1. 定时发送query,启动时20秒一次,连发3次,之后8分钟一次
@@ -51,12 +49,13 @@ impl Multicast {
#[derive(Clone)]
pub struct IgmpServer {
multicast: Arc<DashMap<Ipv4Addr, Arc<RwLock<Multicast>>>>,
multicast: Arc<RwLock<HashMap<Ipv4Addr, Arc<RwLock<Multicast>>>>>,
}
impl IgmpServer {
pub fn new(device_writer: DeviceWriter) -> Self {
let multicast: Arc<DashMap<Ipv4Addr, Arc<RwLock<Multicast>>>> = Arc::new(DashMap::new0());
let multicast: Arc<RwLock<HashMap<Ipv4Addr, Arc<RwLock<Multicast>>>>> =
Arc::new(RwLock::new(HashMap::with_capacity(16)));
std::thread::spawn(move || {
//预留以太网帧头和ip头
let mut buf = [0; 14 + 24 + 12];
@@ -97,16 +96,13 @@ impl IgmpServer {
Self { multicast }
}
pub fn load(&self, multicast_addr: &Ipv4Addr) -> Option<Arc<RwLock<Multicast>>> {
if let Some(entry) = self.multicast.get(multicast_addr) {
Some(entry.value().clone())
} else {
None
}
self.multicast.read().get(multicast_addr).cloned()
}
pub fn handle(&self, buf: &[u8], source: Ipv4Addr) -> crate::Result<()> {
for x in self.multicast.iter() {
let multicast = self.multicast.read();
for (_, v) in multicast.iter() {
let mut list = Vec::new();
let mut write_guard = x.value().write();
let mut write_guard = v.write();
for (ip, time) in &write_guard.members {
if time.elapsed() > Duration::from_secs(30) {
list.push(*ip);
@@ -126,13 +122,7 @@ impl IgmpServer {
if !multicast_addr.is_multicast() {
return Ok(());
}
let multi = {
self.multicast
.entry(multicast_addr)
.or_insert_with(|| Arc::new(RwLock::new(Multicast::new())))
.value()
.clone()
};
let multi = self.add_multicast(multicast_addr);
let mut guard = multi.write();
guard.members.insert(source, Instant::now());
}
@@ -143,8 +133,8 @@ impl IgmpServer {
if !multicast_addr.is_multicast() {
return Ok(());
}
if let Some(entry) = self.multicast.get(&multicast_addr) {
let mut guard = entry.value().write();
if let Some(entry) = self.load(&multicast_addr) {
let mut guard = entry.write();
guard.map.remove(&source);
guard.members.remove(&source);
}
@@ -157,12 +147,7 @@ impl IgmpServer {
if !multicast_addr.is_multicast() {
return Ok(());
}
let multi = self
.multicast
.entry(multicast_addr)
.or_insert_with(|| Arc::new(RwLock::new(Multicast::new())))
.value()
.clone();
let multi = self.add_multicast(multicast_addr);
let mut guard = multi.write();
match group_record.record_type() {
@@ -240,4 +225,9 @@ impl IgmpServer {
}
Ok(())
}
fn add_multicast(&self, multicast_addr: Ipv4Addr) -> Arc<RwLock<Multicast>> {
let value = Arc::new(RwLock::new(Multicast::new()));
self.multicast.write().insert(multicast_addr, value.clone());
value
}
}
+58 -56
View File
@@ -1,20 +1,20 @@
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap;
use std::io;
use std::mem::MaybeUninit;
use std::net::{IpAddr, Ipv4Addr, SocketAddrV4};
use std::sync::Arc;
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap;
use socket2::{Domain, SockAddr, Socket, Type};
use packet::icmp::icmp;
use packet::icmp::icmp::HeaderOther;
use packet::ip::ipv4::packet::IpV4Packet;
use crate::channel::sender::ChannelSender;
use crate::cipher::Cipher;
use crate::handle::CurrentDeviceInfo;
use crate::protocol::body::ENCRYPTION_RESERVED;
use crate::protocol::{NetPacket, Protocol, Version, MAX_TTL};
use packet::icmp::icmp;
use packet::icmp::icmp::HeaderOther;
use packet::ip::ipv4;
use crate::ip_proxy::{send, ProxyHandler};
pub struct IcmpProxy {
icmp_socket: Arc<Socket>,
@@ -47,19 +47,19 @@ impl IcmpProxy {
client_cipher,
})
}
pub fn icmp_socket(&self) -> Arc<Socket> {
self.icmp_socket.clone()
pub fn icmp_handler(&self) -> IcmpHandler {
IcmpHandler(self.icmp_socket.clone(), self.icmp_proxy_map.clone())
}
pub fn start(self) {
let mut buf = [0 as u8; 1500];
let data: &mut [MaybeUninit<u8>] = unsafe { std::mem::transmute(&mut buf[..]) };
let mut buf = [0u8; 4096];
let data: &mut [MaybeUninit<u8>] = unsafe { std::mem::transmute(&mut buf[12..]) };
loop {
match self.recv(data) {
Ok((len, peer_ip)) => {
match peer_ip {
IpAddr::V4(peer_ip) => {
match ipv4::packet::IpV4Packet::new(&mut buf[..len]) {
match IpV4Packet::new(&mut buf[12..12 + len]) {
Ok(mut ipv4_packet) => {
match icmp::IcmpPacket::new(ipv4_packet.payload()) {
Ok(icmp_packet) => {
@@ -73,47 +73,14 @@ impl IcmpProxy {
drop(entry);
ipv4_packet.set_destination_ip(dest_ip);
ipv4_packet.update_checksum();
let current_device =
self.current_device.load();
let virtual_ip =
current_device.virtual_ip();
let connect_server =
current_device.connect_server;
let mut net_packet =
NetPacket::new_encrypt(vec![
0u8;
12 + len + ENCRYPTION_RESERVED
])
.unwrap();
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::IpTurn);
net_packet.set_transport_protocol(crate::protocol::ip_turn_packet::Protocol::Ipv4.into());
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_source(virtual_ip);
net_packet.set_destination(dest_ip);
net_packet
.set_payload(ipv4_packet.buffer)
.unwrap();
if let Err(e) = self
.client_cipher
.encrypt_ipv4(&mut net_packet)
{
log::warn!("加密失败:{}", e);
continue;
}
if self
.sender
.try_send_by_id(
net_packet.buffer(),
&dest_ip,
)
.is_err()
{
let _ = self.sender.send_main(
net_packet.buffer(),
connect_server,
);
}
send(
&mut buf,
len,
dest_ip,
&self.sender,
&self.current_device,
&self.client_cipher,
);
}
}
_ => {
@@ -144,7 +111,42 @@ impl IcmpProxy {
};
Ok((size, addr))
}
// fn send_to(&self, buf: &[u8], addr: SocketAddrV4) -> io::Result<usize> {
// self.icmp_socket.send_to(buf, &SockAddr::from(addr))
// }
}
/// icmp用Identifier来区分,没有Identifier的一律不转发
#[derive(Clone)]
pub struct IcmpHandler(Arc<Socket>, Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>>);
impl ProxyHandler for IcmpHandler {
fn recv_handle(
&self,
ipv4: &mut IpV4Packet<&mut [u8]>,
source: Ipv4Addr,
destination: Ipv4Addr,
) -> io::Result<bool> {
let dest_ip = ipv4.destination_ip();
//转发到代理目标地址
let icmp_packet = icmp::IcmpPacket::new(ipv4.payload())?;
match icmp_packet.header_other() {
HeaderOther::Identifier(id, seq) => {
self.1.insert((dest_ip, id, seq), source);
self.0.send_to(
ipv4.payload(),
&SockAddr::from(SocketAddrV4::new(dest_ip, 0)),
)?;
}
_ => {
log::warn!(
"不支持的ip代理Icmp协议:{}->{}->{}",
source,
destination,
dest_ip
);
}
}
Ok(true)
}
fn send_handle(&self, _ipv4: &mut IpV4Packet<&mut [u8]>) -> io::Result<()> {
Ok(())
}
}
+142 -49
View File
@@ -1,14 +1,24 @@
use crate::ip_proxy::tcp_proxy::TcpProxy;
use crate::ip_proxy::udp_proxy::UdpProxy;
use dashmap::DashMap;
#[cfg(not(target_os = "android"))]
use socket2::{SockAddr, Socket};
#[cfg(not(target_os = "android"))]
use std::net::Ipv4Addr;
use std::net::SocketAddrV4;
use std::sync::Arc;
use std::{io, thread};
use tokio::net::{TcpListener, UdpSocket};
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap;
use packet::ip::ipv4;
use tokio::net::UdpSocket;
use packet::ip::ipv4::packet::IpV4Packet;
use crate::channel::sender::ChannelSender;
use crate::cipher::Cipher;
use crate::handle::CurrentDeviceInfo;
#[cfg(not(target_os = "android"))]
use crate::ip_proxy::icmp_proxy::IcmpHandler;
use crate::ip_proxy::tcp_proxy::{TcpHandler, TcpProxy};
use crate::ip_proxy::udp_proxy::{UdpHandler, UdpProxy};
use crate::protocol;
use crate::protocol::{NetPacket, Version, MAX_TTL};
#[cfg(not(target_os = "android"))]
pub mod icmp_proxy;
@@ -20,6 +30,16 @@ pub trait DashMapNew {
fn new_cap(capacity: usize) -> Self;
}
pub trait ProxyHandler {
fn recv_handle(
&self,
ipv4: &mut IpV4Packet<&mut [u8]>,
source: Ipv4Addr,
destination: Ipv4Addr,
) -> io::Result<bool>;
fn send_handle(&self, ipv4: &mut IpV4Packet<&mut [u8]>) -> io::Result<()>;
}
impl<'a, K: 'a + Eq + std::hash::Hash, V: 'a> DashMapNew for DashMap<K, V> {
fn new0() -> Self {
Self::new_cap(0)
@@ -52,72 +72,145 @@ pub enum Protocol {
#[derive(Clone)]
pub struct IpProxyMap {
pub(crate) tcp_proxy_port: u16,
pub(crate) udp_proxy_port: u16,
//真实源地址 -> 目的地址
pub(crate) tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
pub(crate) udp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
// icmp用Identifier来区分,没有Identifier的一律不转发
#[cfg(not(target_os = "android"))]
pub(crate) icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
#[cfg(not(target_os = "android"))]
icmp_socket: Arc<Socket>,
}
impl IpProxyMap {
#[cfg(not(target_os = "android"))]
pub fn send_icmp(&self, buf: &[u8], dest: &Ipv4Addr) -> io::Result<usize> {
self.icmp_socket
.send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0)))
}
pub(crate) icmp_handler: IcmpHandler,
pub(crate) tcp_handler: TcpHandler,
pub(crate) udp_handler: UdpHandler,
}
#[cfg(not(target_os = "android"))]
pub async fn init_proxy(
#[cfg(not(target_os = "android"))] sender: crate::channel::sender::ChannelSender,
#[cfg(not(target_os = "android"))] current_device: Arc<
crossbeam_utils::atomic::AtomicCell<crate::handle::CurrentDeviceInfo>,
>,
#[cfg(not(target_os = "android"))] client_cipher: crate::cipher::Cipher,
sender: ChannelSender,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
client_cipher: Cipher,
) -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> {
let tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new0());
let udp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new0());
#[cfg(not(target_os = "android"))]
let icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>> = Arc::new(DashMap::new0());
let tcp_listener = TcpListener::bind("0.0.0.0:0").await?;
let udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
let tcp_proxy_port = tcp_listener.local_addr()?.port();
let udp_proxy_port = udp_socket.local_addr()?.port();
let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map.clone());
let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map.clone());
#[cfg(not(target_os = "android"))]
let icmp_socket = {
let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0);
let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0);
let tcp_proxy = TcpProxy::new(addr, tcp_proxy_map.clone()).await?;
let tcp_handler = tcp_proxy.tcp_handler();
let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map.clone())?;
let udp_handler = udp_proxy.udp_handler();
let icmp_handler = {
let icmp_proxy = icmp_proxy::IcmpProxy::new(
addr,
icmp_proxy_map.clone(),
sender.clone(),
current_device.clone(),
client_cipher,
client_cipher.clone(),
)?;
let icmp_socket = icmp_proxy.icmp_socket();
let icmp_handler = icmp_proxy.icmp_handler();
thread::spawn(move || {
icmp_proxy.start();
});
icmp_socket
icmp_handler
};
Ok((
tcp_proxy,
udp_proxy,
IpProxyMap {
tcp_proxy_port,
udp_proxy_port,
tcp_proxy_map,
udp_proxy_map,
#[cfg(not(target_os = "android"))]
icmp_proxy_map,
#[cfg(not(target_os = "android"))]
icmp_socket,
tcp_handler,
udp_handler,
icmp_handler,
},
))
}
#[cfg(target_os = "android")]
pub async fn init_proxy() -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> {
let tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new0());
let udp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new0());
let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0);
let udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
let tcp_proxy = TcpProxy::new(addr, tcp_proxy_map.clone()).await?;
let tcp_handler = tcp_proxy.tcp_handler();
let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map.clone())?;
let udp_handler = udp_proxy.udp_handler();
Ok((
tcp_proxy,
udp_proxy,
IpProxyMap {
tcp_handler,
udp_handler,
},
))
}
pub fn send(
buf: &mut [u8],
data_len: usize,
dest_ip: Ipv4Addr,
sender: &ChannelSender,
current_device: &AtomicCell<CurrentDeviceInfo>,
client_cipher: &Cipher,
) {
let current_device = current_device.load();
let virtual_ip = current_device.virtual_ip();
let mut net_packet = NetPacket::new0(12 + data_len, buf).unwrap();
net_packet.set_version(Version::V1);
net_packet.set_protocol(protocol::Protocol::IpTurn);
net_packet.set_transport_protocol(protocol::ip_turn_packet::Protocol::Ipv4.into());
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_source(virtual_ip);
net_packet.set_destination(dest_ip);
if let Err(e) = client_cipher.encrypt_ipv4(&mut net_packet) {
log::warn!("加密失败:{}", e);
return;
}
if sender
.try_send_by_id(net_packet.buffer(), &dest_ip)
.is_err()
{
let connect_server = current_device.connect_server;
if let Err(e) = sender.send_main(net_packet.buffer(), connect_server) {
log::warn!("发送到目标失败:{},{}", e, connect_server);
}
}
}
impl ProxyHandler for IpProxyMap {
fn recv_handle(
&self,
ipv4: &mut IpV4Packet<&mut [u8]>,
source: Ipv4Addr,
destination: Ipv4Addr,
) -> io::Result<bool> {
match ipv4.protocol() {
ipv4::protocol::Protocol::Tcp => {
self.tcp_handler.recv_handle(ipv4, source, destination)
}
ipv4::protocol::Protocol::Udp => {
self.udp_handler.recv_handle(ipv4, source, destination)
}
#[cfg(not(target_os = "android"))]
ipv4::protocol::Protocol::Icmp => {
self.icmp_handler.recv_handle(ipv4, source, destination)
}
_ => {
log::warn!(
"不支持的ip代理ipv4协议{:?}:{}->{}->{}",
ipv4.protocol(),
source,
destination,
ipv4.destination_ip()
);
Ok(false)
}
}
}
fn send_handle(&self, ipv4: &mut IpV4Packet<&mut [u8]>) -> io::Result<()> {
match ipv4.protocol() {
ipv4::protocol::Protocol::Tcp => self.tcp_handler.send_handle(ipv4),
ipv4::protocol::Protocol::Udp => self.udp_handler.send_handle(ipv4),
_ => Ok(()),
}
}
}
+102 -17
View File
@@ -1,25 +1,38 @@
use crate::ip_proxy::ProxyHandler;
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap;
use packet::ip::ipv4::packet::IpV4Packet;
use packet::tcp::tcp::TcpPacket;
use std::io;
use std::net::{SocketAddr, SocketAddrV4};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::sync::Arc;
use std::time::Duration;
use std::time::{Duration, Instant};
use tokio::io::AsyncReadExt;
use tokio::io::AsyncWriteExt;
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
use tokio::net::{TcpListener, TcpStream};
pub struct TcpProxy {
tcp_proxy_port: u16,
tcp_listener: TcpListener,
//真实源地址 -> 目的地址
tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
}
impl TcpProxy {
pub fn new(
tcp_listener: TcpListener,
pub async fn new(
addr: SocketAddrV4,
tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
) -> Self {
Self {
) -> io::Result<Self> {
let tcp_listener = TcpListener::bind(addr).await?;
Ok(Self {
tcp_proxy_port: tcp_listener.local_addr()?.port(),
tcp_listener,
tcp_proxy_map,
}
})
}
pub fn tcp_handler(&self) -> TcpHandler {
TcpHandler(self.tcp_proxy_port, self.tcp_proxy_map.clone())
}
pub async fn start(self) {
let tcp_listener = self.tcp_listener;
@@ -37,7 +50,7 @@ impl TcpProxy {
Duration::from_secs(5),
TcpStream::connect(dest_addr),
)
.await
.await
{
Ok(peer_tcp_stream) => match peer_tcp_stream {
Ok(peer_tcp_stream) => peer_tcp_stream,
@@ -79,15 +92,87 @@ impl TcpProxy {
}
}
async fn proxy(mut client: TcpStream, mut server: TcpStream) -> io::Result<()> {
let (mut client_reader, mut client_writer) = client.split();
let (mut server_reader, mut server_writer) = server.split();
async fn proxy(client: TcpStream, server: TcpStream) -> io::Result<()> {
let (client_read, client_write) = client.into_split();
let (server_read, server_write) = server.into_split();
let time = Arc::new(AtomicCell::new(Instant::now()));
let time1 = time.clone();
tokio::spawn(async move {
if let Err(e) = copy(client_read, server_write, &time1).await {
log::warn!("{:?}", e);
}
});
copy(server_read, client_write, &time).await
}
let client_to_server = tokio::io::copy(&mut client_reader, &mut server_writer);
let server_to_client = tokio::io::copy(&mut server_reader, &mut client_writer);
tokio::select! {
_ = tokio::time::timeout(Duration::from_secs(10), client_to_server) =>{},
_ = tokio::time::timeout(Duration::from_secs(10), server_to_client) =>{},
async fn copy(
mut read: OwnedReadHalf,
mut write: OwnedWriteHalf,
time: &AtomicCell<Instant>,
) -> io::Result<()> {
let mut buf = [0; 10240];
loop {
tokio::select! {
result = read.read(&mut buf) =>{
let len = result?;
if len==0{
break;
}
write.write_all(&buf[..len]).await?;
time.store(Instant::now());
}
_ = tokio::time::sleep(Duration::from_secs(600)) =>{
if time.load().elapsed()>=Duration::from_secs(580){
//读写均超时再退出
break;
}
}
}
}
Ok(())
}
#[derive(Clone)]
pub struct TcpHandler(u16, Arc<DashMap<SocketAddrV4, SocketAddrV4>>);
impl ProxyHandler for TcpHandler {
fn recv_handle(
&self,
ipv4: &mut IpV4Packet<&mut [u8]>,
source: Ipv4Addr,
destination: Ipv4Addr,
) -> io::Result<bool> {
let dest_ip = ipv4.destination_ip();
//转发到代理目标地址
let mut tcp_packet = TcpPacket::new(source, destination, ipv4.payload_mut())?;
let source_port = tcp_packet.source_port();
let dest_port = tcp_packet.destination_port();
tcp_packet.set_destination_port(self.0);
tcp_packet.update_checksum();
ipv4.set_destination_ip(destination);
ipv4.update_checksum();
let key = SocketAddrV4::new(source, source_port);
//https://github.com/crossbeam-rs/crossbeam/issues/1023
self.1.insert(key, SocketAddrV4::new(dest_ip, dest_port));
Ok(false)
}
fn send_handle(&self, ipv4: &mut IpV4Packet<&mut [u8]>) -> io::Result<()> {
let src_ip = ipv4.source_ip();
let dest_ip = ipv4.destination_ip();
let dest_addr = {
let tcp_packet = TcpPacket::new(src_ip, dest_ip, ipv4.payload_mut())?;
SocketAddrV4::new(dest_ip, tcp_packet.destination_port())
};
if let Some(entry) = self.1.get(&dest_addr) {
let source_addr = entry.value();
let source_ip = *source_addr.ip();
let mut tcp_packet = TcpPacket::new(source_ip, dest_ip, ipv4.payload_mut())?;
tcp_packet.set_source_port(source_addr.port());
tcp_packet.update_checksum();
ipv4.set_source_ip(source_ip);
ipv4.update_checksum();
}
Ok(())
}
}
+83 -13
View File
@@ -1,28 +1,45 @@
use crate::ip_proxy::DashMapNew;
use crate::ip_proxy::{DashMapNew, ProxyHandler};
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap;
use packet::ip::ipv4::packet::IpV4Packet;
use packet::udp::udp::UdpPacket;
use std::io;
use std::net::{SocketAddr, SocketAddrV4};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::sync::Arc;
use std::time::Duration;
use tokio::net::UdpSocket;
use tokio::time::Instant;
/// 一个udp代理,作用是利用系统协议栈,将udp数据报解析出来再转发到目的地址
pub struct UdpProxy {
udp_proxy_port: u16,
udp_socket: Arc<UdpSocket>,
map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
}
impl UdpProxy {
pub fn new(udp_socket: UdpSocket, map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>) -> Self {
pub fn new(
udp_socket: UdpSocket,
map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
) -> io::Result<Self> {
let udp_socket = Arc::new(udp_socket);
Self { udp_socket, map }
let udp_proxy_port = udp_socket.local_addr()?.port();
Ok(Self {
udp_proxy_port,
udp_socket,
map,
})
}
pub fn udp_handler(&self) -> UdpHandler {
UdpHandler(self.udp_proxy_port, self.map.clone())
}
pub async fn start(self) {
let map = self.map;
let udp_socket = self.udp_socket;
let mut buf = [0u8; 65536];
let inner_map: Arc<DashMap<SocketAddrV4, Arc<UdpSocket>>> = Arc::new(DashMap::new0());
let inner_map: Arc<DashMap<SocketAddrV4, (Arc<UdpSocket>, Arc<AtomicCell<Instant>>)>> =
Arc::new(DashMap::new0());
loop {
match udp_socket.recv_from(&mut buf).await {
@@ -49,29 +66,36 @@ impl UdpProxy {
async fn start0(
buf: &[u8],
sender_addr: SocketAddrV4,
inner_map: &Arc<DashMap<SocketAddrV4, Arc<UdpSocket>>>,
inner_map: &Arc<DashMap<SocketAddrV4, (Arc<UdpSocket>, Arc<AtomicCell<Instant>>)>>,
map: &Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
udp_socket: &Arc<UdpSocket>,
) -> io::Result<()> {
if let Some(entry) = inner_map.get(&sender_addr) {
let udp = entry.value().clone();
entry.value().1.store(Instant::now());
let udp = entry.value().0.clone();
drop(entry);
udp.send(buf).await?;
} else if let Some(entry) = map.get(&sender_addr) {
let dest_addr = *entry.value();
drop(entry);
let peer_udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
//先使用相同的端口,冲突了再随机端口
let peer_udp_socket = match UdpSocket::bind(format!("0.0.0.0:{}", sender_addr.port())).await
{
Ok(udp) => udp,
Err(_) => UdpSocket::bind("0.0.0.0:0").await?,
};
peer_udp_socket.connect(dest_addr).await?;
peer_udp_socket.send(buf).await?;
let peer_udp_socket = Arc::new(peer_udp_socket);
let inner_map = inner_map.clone();
inner_map.insert(sender_addr, peer_udp_socket.clone());
let time = Arc::new(AtomicCell::new(Instant::now()));
inner_map.insert(sender_addr, (peer_udp_socket.clone(), time.clone()));
let udp_socket = udp_socket.clone();
let map = map.clone();
tokio::spawn(async move {
let mut buf = [0u8; 65536];
loop {
match tokio::time::timeout(Duration::from_secs(300), peer_udp_socket.recv(&mut buf))
match tokio::time::timeout(Duration::from_secs(600), peer_udp_socket.recv(&mut buf))
.await
{
Ok(rs) => match rs {
@@ -98,9 +122,11 @@ async fn start0(
}
},
Err(_) => {
//超时关闭
log::warn!("udp代理超时关闭,来源:{},目标:{}", sender_addr, dest_addr);
break;
if time.load().elapsed() > Duration::from_secs(580) {
//超时关闭
log::warn!("udp代理超时关闭,来源:{},目标:{}", sender_addr, dest_addr);
break;
}
}
}
}
@@ -110,3 +136,47 @@ async fn start0(
}
Ok(())
}
#[derive(Clone)]
pub struct UdpHandler(u16, Arc<DashMap<SocketAddrV4, SocketAddrV4>>);
impl ProxyHandler for UdpHandler {
fn recv_handle(
&self,
ipv4: &mut IpV4Packet<&mut [u8]>,
source: Ipv4Addr,
destination: Ipv4Addr,
) -> io::Result<bool> {
let dest_ip = ipv4.destination_ip();
//转发到代理目标地址
let mut udp_packet = UdpPacket::new(source, destination, ipv4.payload_mut())?;
let source_port = udp_packet.source_port();
let dest_port = udp_packet.destination_port();
udp_packet.set_destination_port(self.0);
udp_packet.update_checksum();
ipv4.set_destination_ip(destination);
ipv4.update_checksum();
let key = SocketAddrV4::new(source, source_port);
self.1.insert(key, SocketAddrV4::new(dest_ip, dest_port));
Ok(false)
}
fn send_handle(&self, ipv4: &mut IpV4Packet<&mut [u8]>) -> io::Result<()> {
let src_ip = ipv4.source_ip();
let dest_ip = ipv4.destination_ip();
let dest_addr = {
let udp_packet = UdpPacket::new(src_ip, dest_ip, ipv4.payload_mut())?;
SocketAddrV4::new(dest_ip, udp_packet.destination_port())
};
if let Some(entry) = self.1.get(&dest_addr) {
let source_addr = entry.value();
let source_ip = *source_addr.ip();
let mut udp_packet = UdpPacket::new(source_ip, dest_ip, ipv4.payload_mut())?;
udp_packet.set_source_port(source_addr.port());
udp_packet.update_checksum();
ipv4.set_source_ip(source_ip);
ipv4.update_checksum();
}
Ok(())
}
}
+2 -1
View File
@@ -1,5 +1,5 @@
use crate::error::Error;
pub const VNT_VERSION: &'static str = "1.2.3";
pub const VNT_VERSION: &'static str = "1.2.8";
pub type Result<T> = std::result::Result<T, Error>;
pub mod channel;
@@ -9,6 +9,7 @@ pub mod error;
pub mod external_route;
pub mod handle;
pub mod igmp_server;
#[cfg(feature = "ip_proxy")]
pub mod ip_proxy;
pub mod nat;
pub mod proto;
+19 -13
View File
@@ -1,7 +1,9 @@
use crossbeam_utils::atomic::AtomicCell;
use std::io;
use std::net::UdpSocket;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
use std::sync::Arc;
use std::time::{Duration, Instant};
use parking_lot::Mutex;
@@ -22,7 +24,7 @@ pub fn local_ipv4() -> io::Result<Ipv4Addr> {
pub fn local_ipv6() -> io::Result<Ipv6Addr> {
let socket = UdpSocket::bind("[::]:0")?;
socket.connect("[2001:4860:4860::8888]:80")?;
socket.connect("[2001:4860:4860:0000:0000:0000:0000:8888]:80")?;
let addr = socket.local_addr()?;
match addr.ip() {
IpAddr::V4(_) => Ok(Ipv6Addr::UNSPECIFIED),
@@ -54,6 +56,7 @@ pub fn local_ipv6_addr(port: u16) -> SocketAddrV6 {
pub struct NatTest {
stun_server: Vec<String>,
info: Arc<Mutex<NatInfo>>,
time: Arc<AtomicCell<Instant>>,
}
impl From<NatType> for PunchNatType {
@@ -93,17 +96,23 @@ impl NatTest {
NatType::Cone,
);
let info = Arc::new(Mutex::new(nat_info));
NatTest { stun_server, info }
NatTest {
stun_server,
info,
time: Arc::new(AtomicCell::new(Instant::now())),
}
}
pub fn can_update(&self) -> bool {
let last = self.time.load();
last.elapsed() > Duration::from_secs(10)
&& self.time.compare_exchange(last, Instant::now()).is_ok()
}
pub fn nat_info(&self) -> NatInfo {
self.info.lock().clone()
}
pub fn update_addr(&self, ip: Ipv4Addr, port: u16) {
let mut guard = self.info.lock();
guard.public_port = port;
if !guard.public_ips.contains(&ip) {
guard.public_ips.push(ip);
}
guard.update_addr(ip, port)
}
pub async fn re_test(
&self,
@@ -120,6 +129,7 @@ impl NatTest {
ipv6_addr,
)
.await;
log::info!("探测nat类型={:?}", info);
*self.info.lock() = info.clone();
info
}
@@ -131,13 +141,9 @@ impl NatTest {
ipv6_addr: SocketAddrV6,
) -> NatInfo {
return match stun_test::stun_test_nat(stun_server.clone()).await {
Ok((nat_type, ips, port_range)) => {
let mut public_ips = Vec::new();
public_ips.push(Ipv4Addr::from(public_ip));
for ip in ips {
if ip != public_ip {
public_ips.push(ip);
}
Ok((nat_type, mut public_ips, port_range)) => {
if !public_ips.contains(&public_ip) {
public_ips.push(public_ip)
}
NatInfo::new(
public_ips,
+1 -1
View File
@@ -1,6 +1,6 @@
use std::{fmt, io};
pub const ENCRYPTION_RESERVED: usize = 32 + 12;
pub const ENCRYPTION_RESERVED: usize = 16 + 32 + 12;
pub const AES_GCM_ENCRYPTION_RESERVED: usize = 32;
pub const RSA_ENCRYPTION_RESERVED: usize = 32;
+2 -1
View File
@@ -155,7 +155,7 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
}
/// 网关通信的标识
pub fn is_gateway(&self) -> bool {
self.buffer.as_ref()[0] & 0x50 == 0x50
self.buffer.as_ref()[0] & 0x40 == 0x40
}
pub fn version(&self) -> Version {
Version::from(self.buffer.as_ref()[0] & 0x0F)
@@ -198,6 +198,7 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
}
pub fn set_gateway_flag(&mut self, is_gateway: bool) {
if is_gateway {
// 后面的版本再改为0x40,改了之后不兼容1.2.5之前的版本
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x50
} else {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF
+11 -11
View File
@@ -5,7 +5,6 @@ use bytes::BufMut;
use packet::ethernet;
use parking_lot::Mutex;
use std::net::Ipv4Addr;
use std::os::unix::io::AsRawFd;
#[cfg(any(target_os = "linux"))]
use tun::platform::linux::Device;
#[cfg(any(target_os = "macos"))]
@@ -112,16 +111,17 @@ impl DeviceWriter {
}
}
pub fn close(&self) -> io::Result<()> {
unsafe {
match &self.writer {
DeviceW::Tun(writer) => {
libc::close(writer.as_raw_fd());
}
DeviceW::Tap((writer, _)) => {
libc::close(writer.as_raw_fd());
}
}
}
//早期使用close直接切断网卡,现在并不需要这么做也能正常关闭
// unsafe {
// match &self.writer {
// DeviceW::Tun(writer) => {
// libc::close(writer.as_raw_fd());
// }
// DeviceW::Tap((writer, _)) => {
// libc::close(writer.as_raw_fd());
// }
// }
// }
Ok(())
}
pub fn is_tun(&self) -> bool {
+4 -4
View File
@@ -117,7 +117,7 @@ impl DeviceWriter {
// 当前网段路由
dev.add_route(address, netmask, gateway, 1)?;
// 广播和组播路由
dev.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
// dev.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
dev.add_route(
Ipv4Addr::from([224, 0, 0, 0]),
Ipv4Addr::from([240, 0, 0, 0]),
@@ -230,8 +230,8 @@ fn create_tun(
}
// 当前网段路由
tun_device.add_route(address, netmask, gateway, 1)?;
// 广播和组播路由
tun_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
// 广播和组播路由 修改了广播路由会导致发不出广播
// tun_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
tun_device.add_route(
Ipv4Addr::from([224, 0, 0, 0]),
Ipv4Addr::from([240, 0, 0, 0]),
@@ -309,7 +309,7 @@ fn create_tap(
tap_device.add_route(*address, *netmask, gateway, 1)?;
}
// 广播和组播路由
tap_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
// tap_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
tap_device.add_route(
Ipv4Addr::from([224, 0, 0, 0]),
Ipv4Addr::from([240, 0, 0, 0]),
+9 -5
View File
@@ -7,12 +7,12 @@ edition = "2021"
[dependencies]
log = "0.4.17"
winreg = "0.7"
winreg = "0.51.0"
scopeguard = "1.1"
libloading = "0.7"
widestring = "0.4"
libloading = "0.8.0"
widestring = "1.0.2"
once_cell = "1.8"
itertools = "0.10.1"
itertools = "0.11.0"
rand = "0.8.5"
[dependencies.winapi]
version = "0.3"
@@ -29,5 +29,9 @@ features = [
"winerror",
"ipexport",
"iphlpapi",
"handleapi"
"handleapi",
"ifdef",
"minwinbase",
"basetsd",
"impl-default"
]
+5 -5
View File
@@ -119,14 +119,14 @@ pub fn create_interface() -> io::Result<NET_LUID> {
KEY_QUERY_VALUE | KEY_NOTIFY,
)?;
let key = RegKey::predef(key);
let key = RegKey::predef(key as _);
while let Err(_) = key.get_value::<DWORD, &str>("*IfType") {
ffi::notify_change_key_value(key.raw_handle(), TRUE, REG_NOTIFY_CHANGE_NAME, 2000)?;
ffi::notify_change_key_value(key.raw_handle() as _, TRUE, REG_NOTIFY_CHANGE_NAME, 2000)?;
}
while let Err(_) = key.get_value::<DWORD, &str>("NetLuidIndex") {
ffi::notify_change_key_value(key.raw_handle(), TRUE, REG_NOTIFY_CHANGE_NAME, 2000)?;
ffi::notify_change_key_value(key.raw_handle() as _, TRUE, REG_NOTIFY_CHANGE_NAME, 2000)?;
}
let if_type: DWORD = key.get_value("*IfType")?;
@@ -179,7 +179,7 @@ pub fn check_interface(luid: &NET_LUID) -> io::Result<()> {
DIREG_DRV,
KEY_QUERY_VALUE | KEY_NOTIFY,
) {
Ok(key) => RegKey::predef(key),
Ok(key) => RegKey::predef(key as _),
Err(_) => continue,
};
@@ -248,7 +248,7 @@ pub fn delete_interface(luid: &NET_LUID) -> io::Result<()> {
DIREG_DRV,
KEY_QUERY_VALUE | KEY_NOTIFY,
) {
Ok(key) => RegKey::predef(key),
Ok(key) => RegKey::predef(key as _),
Err(_) => continue,
};
+2 -1
View File
@@ -119,7 +119,8 @@ impl TapDevice {
}
pub fn delete(self) -> io::Result<()> {
iface::delete_interface(&self.luid)
// iface::delete_interface(&self.luid)
Ok(())
}
}
+12 -6
View File
@@ -1,12 +1,12 @@
use std::io;
use std::net::Ipv4Addr;
use winapi::um::{handleapi, synchapi, winbase, winnt};
use winapi::um::{synchapi, winbase, winnt};
use crate::{decode_utf16, encode_utf16, ffi, netsh, route, IFace};
use rand::Rng;
mod log;
pub mod packet;
mod wintun_log;
mod wintun_raw;
/// The maximum size of wintun's internal ring buffer (in bytes)
@@ -80,7 +80,7 @@ impl TunDevice {
let guid_struct: wintun_raw::GUID = unsafe { std::mem::transmute(guid) };
let guid_ptr = &guid_struct as *const wintun_raw::GUID;
log::set_default_logger_if_unset(&win_tun);
wintun_log::set_default_logger_if_unset(&win_tun);
//SAFETY: the function is loaded from the wintun dll properly, we are providing valid
//pointers, and all the strings are correct null terminated UTF-16. This safety rationale
@@ -88,6 +88,7 @@ impl TunDevice {
let adapter =
win_tun.WintunCreateAdapter(pool_utf16.as_ptr(), name_utf16.as_ptr(), guid_ptr);
if adapter.is_null() {
log::error!("adapter.is_null {:?}", io::Error::last_os_error());
return Err(io::Error::new(
io::ErrorKind::Other,
"Failed to crate adapter",
@@ -102,6 +103,7 @@ impl TunDevice {
// 开启session
let session = win_tun.WintunStartSession(adapter, 128 * 1024);
if session.is_null() {
log::error!("session.is_null {:?}", io::Error::last_os_error());
return Err(io::Error::new(
io::ErrorKind::Other,
"WintunStartSession failed",
@@ -138,10 +140,14 @@ impl TunDevice {
));
}
};
log::set_default_logger_if_unset(&win_tun);
wintun_log::set_default_logger_if_unset(&win_tun);
let name_utf16 = encode_utf16(name);
let adapter = win_tun.WintunOpenAdapter(name_utf16.as_ptr());
if adapter.is_null() {
log::error!(
"delete_for_name adapter.is_null {:?}",
io::Error::last_os_error()
);
return Err(io::Error::new(
io::ErrorKind::Other,
"Failed to open adapter",
@@ -187,8 +193,8 @@ pub struct Version {
impl IFace for TunDevice {
fn shutdown(&self) -> io::Result<()> {
let _ = unsafe { synchapi::SetEvent(self.shutdown_event) };
let _ = unsafe { handleapi::CloseHandle(self.shutdown_event) };
// let _ = unsafe { synchapi::SetEvent(self.shutdown_event) };
// let _ = unsafe { handleapi::CloseHandle(self.shutdown_event) };
Ok(())
}