Compare commits

...
48 Commits
Author SHA1 Message Date
lubeilin b9fe5e0fe2 支持aes_cbc加密算法 2023-08-28 23:13:46 +08:00
lubeilin c3368481ad 1.修改默认任务数
2.修改指纹生成方式
2023-08-28 20:34:23 +08:00
lubeilin cdf5c3a508 parallel为1时不另起任务 2023-08-27 22:55:40 +08:00
lubeilin f9217625e1 增加参数说明 2023-08-27 21:40:03 +08:00
lubeilin 323f6c9221 1.增加缓冲池
2.线程数、任务数配置
2023-08-27 21:15:34 +08:00
lubeilin 2e507f1a9d 修复不加密不能打洞的问题 2023-08-27 17:51:42 +08:00
lubeilin e611d69a25 调整任务数 2023-08-27 17:05:24 +08:00
lubeilin 45d8c6717d 弃用SkipMap 2023-08-27 16:29:44 +08:00
lubeilin 756539c3bd 修改版本号 2023-08-27 15:11:47 +08:00
lubeilin 3d4fcdbc96 支持新版本 2023-08-27 15:11:08 +08:00
lubeilin 3cd19dbc1f 调整mtu 2023-08-27 14:09:09 +08:00
lubeilin 7b770a1bb0 完善tcp通道 2023-08-27 14:07:35 +08:00
lubeilin 0472b1590e 增加服务端加密、完善客户端加密 2023-08-27 11:58:32 +08:00
lbl8603 81764433d8 Merge pull request #12 from Droid-MAX/main
Fixed an output issue when displaying all devices
2023-08-24 20:18:17 +08:00
Droid-MAX 9ee6e101c4 Fixed an output issue when displaying all devices 2023-08-10 11:36:35 +08:00
lbl8603 565e80b994 Update README.md 2023-08-03 23:35:42 +08:00
lbl8603 7ccc4535e4 Update README.md 2023-08-03 21:27:11 +08:00
lubeilin d1bde297d6 支持stun协议 2023-08-03 21:05:15 +08:00
lubeilin c5398a51e8 调整路由超时时间 2023-07-31 23:20:29 +08:00
lubeilin fddb59992b 处理默认路由 2023-07-31 19:15:58 +08:00
lbl8603 665e25b1a3 Update README.md 2023-07-31 19:03:59 +08:00
lbl8603 fdb4bb1155 Update README.md 2023-07-31 19:02:05 +08:00
lubeilin f104e191ed 修复route next显示问题 2023-07-30 10:54:37 +08:00
lubeilin 6311d75ac0 去除-o的ip指定 2023-07-30 10:52:07 +08:00
lubeilin c3f134e332 -o 使用默认网卡 2023-07-29 23:25:39 +08:00
lubeilin 5bccdf3bbe 修改版本,修改帮助信息 2023-07-29 23:03:52 +08:00
lubeilin 9e881eeecd 增加-o默认ip 2023-07-29 21:31:34 +08:00
lubeilin fbe01d8cbf 修复--route命令显示异常的问题 2023-07-29 21:14:31 +08:00
lbl8603 d336d938a9 Update README.md 2023-07-29 20:31:39 +08:00
lbl8603 598923c95a Update README.md 2023-07-29 20:29:38 +08:00
lbl8603 0afe4c4417 Update README.md 2023-07-29 20:02:44 +08:00
lubeilin dff51caf35 增加条件编译 2023-07-29 18:19:53 +08:00
lubeilin 7c30f2691a 增加条件编译 2023-07-29 18:09:15 +08:00
lubeilin c6aca2c2dc 添加编译依赖 2023-07-28 00:28:44 +08:00
lubeilin 28ac8cf88e 优化加解密速度 2023-07-26 21:32:10 +08:00
lubeilin 62b2af54a2 展示客户端中继状态 2023-07-26 21:31:34 +08:00
lubeilin a2d45da44d 修复校验和计算异常 2023-07-26 21:31:07 +08:00
lubeilin d937f392d3 修复代理icmp异常 2023-07-26 21:30:19 +08:00
lbl8603 2c9abf314a Update README.md 2023-07-25 23:15:09 +08:00
lbl8603 ab7abd0c1f Update README.md 2023-07-25 21:56:52 +08:00
lubeilin 71a2e3c592 去除控制台输出 2023-07-24 23:52:27 +08:00
lubeilin aa6d3a6843 修复tcp模式下的p2p问题 2023-07-24 21:37:19 +08:00
lubeilin 9b42c5d092 支持自定义ip、服务端tcp通道、可选择禁止p2p 2023-07-24 00:42:27 +08:00
lbl8603 2f7817ce5b Update README.md 2023-07-19 21:24:15 +08:00
lbl8603 e7c6bcf9a9 Update README.md 2023-07-19 17:42:42 +08:00
lbl8603 b6b8971b12 Update README.md 2023-07-19 11:35:42 +08:00
lbl8603 ba4a0e008b Update README.md 2023-07-19 10:08:06 +08:00
lbl8603 4baccc5047 Update README.md 2023-07-19 09:52:53 +08:00
165 changed files with 5268 additions and 3460 deletions
+47 -5
View File
@@ -40,34 +40,53 @@ jobs:
include:
- TARGET: i686-unknown-linux-musl # test in an alpine container on a mac
OS: ubuntu-latest
FEATURES: normal
- TARGET: x86_64-unknown-linux-gnu # tested in a debian container on a mac
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: x86_64-unknown-linux-musl # test in an alpine container on a mac
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: aarch64-unknown-linux-gnu # tested on aws t4g.nano
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: aarch64-unknown-linux-musl # tested on aws t4g.nano in alpine container
OS: ubuntu-latest
FEATURES: normal
- TARGET: armv7-unknown-linux-gnueabihf # raspberry pi 2-3-4, not tested
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested
OS: ubuntu-latest
FEATURES: normal
- TARGET: arm-unknown-linux-gnueabihf # raspberry pi 0-1, not tested
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested
OS: ubuntu-latest
FEATURES: normal
- TARGET: x86_64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
OS: macos-latest
FEATURES: ring-cipher
- TARGET: aarch64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
OS: macos-latest
FEATURES: ring-cipher
- TARGET: i686-pc-windows-msvc # tested on a windows machine
OS: windows-latest
FEATURES: ring-cipher
- TARGET: x86_64-pc-windows-msvc # tested on a windows machine
OS: windows-latest
FEATURES: ring-cipher
- TARGET: mipsel-unknown-linux-musl # openwrt
OS: ubuntu-latest
FEATURES: normal
# needs: test
runs-on: ${{ matrix.OS }}
env:
NAME: switch-cmd # change with the name of your project
NAME: vnt-cli # change with the name of your project
TARGET: ${{ matrix.TARGET }}
OS: ${{ matrix.OS }}
FEATURES: ${{ matrix.FEATURES }}
steps:
- uses: actions/checkout@v2
- name: Init submodules
@@ -86,27 +105,50 @@ jobs:
# dependencies are only needed on ubuntu as that's the only place where
# we make cross-compilation
if [[ $OS =~ ^ubuntu.*$ ]]; then
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools gcc-mipsel-linux-gnu
fi
# some additional configuration for cross-compilation on linux
cat >>~/.cargo/config <<EOF
[target.x86_64-unknown-linux-musl]
rustflags = ["-C", "target-feature=+crt-static"]
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-gnu-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.armv7-unknown-linux-musleabihf]
linker = "arm-linux-gnueabihf-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.arm-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.arm-unknown-linux-musleabihf]
linker = "arm-linux-gnueabihf-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.mipsel-unknown-linux-musl]
linker = "mipsel-linux-gnu-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]
[target.i686-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]
[target.x86_64-apple-darwin]
rustflags = ["-C", "target-feature=+crt-static"]
[target.aarch64-apple-darwin]
rustflags = ["-C", "target-feature=+crt-static"]
[target.i686-unknown-linux-musl]
rustflags = ["-C", "target-feature=+crt-static"]
[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "target-feature=+crt-static"]
EOF
- name: Install rust target
run: rustup target add $TARGET
- name: Run build
run: cargo build --package switch-cmd --release --verbose --target $TARGET
run: cargo build --package vnt-cli --release --verbose --target $TARGET --features $FEATURES
- name: List target
run: find ./target
- name: Compress
@@ -128,7 +170,7 @@ jobs:
- name: Archive artifact
uses: actions/upload-artifact@v2
with:
name: switch-cmd
name: vnt-cli
path: |
./artifacts
# deploys to github releases on tag
@@ -140,7 +182,7 @@ jobs:
- name: Download artifacts
uses: actions/download-artifact@v2
with:
name: switch-cmd
name: vnt-cli
path: ./artifacts
- name: List
run: find ./artifacts
+1 -1
View File
@@ -1,5 +1,5 @@
[workspace]
members = ["switch","common","switch-desktop","switch-cmd","switch-jni"]
members = ["vnt","common","vnt-cli","vnt-jni"]
[profile.release]
opt-level = 'z'
+48 -18
View File
@@ -1,23 +1,23 @@
# switch
# Vnt
A virtual network tool (VPN)
将不同网络下的多个设备虚拟到一个局域网下
### switch-cmd参数详解 [参数说明](https://github.com/lbl8603/switch/blob/main/switch-cmd/README.md)
### vnt-cli参数详解 [参数说明](https://github.com/lbl8603/vnt/blob/main/vnt-cli/README.md)
### 快速使用:
1. 指定一个token,在多台设备上运行该程序,例如:
```shell
# linux上
root@DESKTOP-0BCHNIO:/opt# ./switch-cmd -k 123456
root@DESKTOP-0BCHNIO:/opt# ./vnt-cli -k 123456
# 在另一台linux上使用nohup后台运行
root@izj6cemne76ykdzkataftfz switch# nohup ./switch-cmd -k 123456 &
root@izj6cemne76ykdzkataftfz vnt# nohup ./vnt-cli -k 123456 &
# windows上
D:\switch\bin_v1>switch-cmd.exe -k 123456
D:\vnt\bin_v1>vnt-cli.exe -k 123456
```
2. 可以执行info命令查看当前设备的虚拟ip
```shell
root@DESKTOP-0BCHNIO:/opt# ./switch-cmd --info
root@DESKTOP-0BCHNIO:/opt# ./vnt-cli --info
Name: Ubuntu 18.04 (bionic) [64-bit]
Virtual ip: 10.26.0.2
Virtual gateway: 10.26.0.1
@@ -30,37 +30,38 @@ A virtual network tool (VPN)
```
3. 也可以执行list命令查看其他设备的虚拟ip
```shell
root@DESKTOP-0BCHNIO:/opt# ./switch-cmd --list
root@DESKTOP-0BCHNIO:/opt# ./vnt-cli --list
Name Virtual Ip P2P/Relay Rt Status
Windows 10.0.22621 (Windows 11 Professional) [64-bit] 10.26.0.3 p2p 2 Online
CentOS 7.9.2009 (Core) [64-bit] 10.26.0.4 p2p 35 Online
```
4. 最后可以用虚拟ip实现设备间相互访问
<img width="506" alt="ssh" src="https://raw.githubusercontent.com/lbl8603/switch/dev/documents/img/ssh.jpg">
<img width="506" alt="ssh" src="https://raw.githubusercontent.com/lbl8603/vnt/dev/documents/img/ssh.jpg">
5. 帮助,使用-h命令查看
### 更多玩法
1. 和远程桌面(如mstsc)搭配,超低延迟的体验
2. 安装samba服务,共享磁盘
3. 搭配公网服务器nginx反向代理,在公网访问本地文件
3. 搭配公网服务器nginx反向代理,在公网访问内网文件或服务
4. 点对网,访问内网其他机器、IP代理(结合启动参数'-i'和'-o')
### 使用须知
- token的作用是标识一个虚拟局域网,当使用公共服务器时,建议使用一个唯一值当token(比如uuid),否则有可能连接到其他人创建的虚拟局域网中
- 默认使用公共服务器,目前的配置是2核4G 4Mbps,有需要再扩展~
- 默认使用公共服务器做注册和中继,目前的配置是2核4G 4Mbps,有需要再扩展~
- 需要root/管理员权限
- switch-cmd需要使用命令行运行
- Mac和Linux下需要加可执行权限(例如:chmod +x ./switch-cmd)
- 可以自己搭注册和中继服务器([server](https://github.com/lbl8603/switch-server))
- vnt-cli需要使用命令行运行
- Mac和Linux下需要加可执行权限(例如:chmod +x ./vnt-cli)
- 可以自己搭注册和中继服务器([server](https://github.com/lbl8603/vnts))
- vnt使用stun服务器探测网络NAT类型,默认使用谷歌和腾讯的stun服务器,也可自己搭建(-e参数指定)
### 编译
前提条件:安装rust编译环境([install rust](https://www.rust-lang.org/zh-CN/tools/install))
到项目根目录下执行 cargo build -p switch-cmd
到项目根目录下执行 cargo build -p vnt-cli
### 支持平台
@@ -84,22 +85,51 @@ A virtual network tool (VPN)
- IP代理
- p2p组播/广播
- 客户端数据加密
- 服务端数据加密
### Todo
- 服务端数据加密
- 桌面UI(测试中)
- 支持Ipv6
### 常见问题
<details> <summary>展开</summary>
#### 问题1: 设置网络地址失败
##### 可能原因:
switch默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突
vnt默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突
##### 解决方法:
1. 方法一:找到冲突的IP,将其改成别的
2. 方法二:自建服务器,指定其他不会冲突的网段
3. 方法三:增加参数-d <device-id> ,设置不同的id会让switch-server分配不同的IP,从而绕开有冲突的IP
3. 方法三:增加参数-d <device-id> ,设置不同的id会让服务端分配不同的IP,从而绕开有冲突的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
### 其他
可使用社区小伙伴搭建的中继服务器
1. -s vnt.8443.eu.org:29871
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "common"
version = "1.1.0"
version = "1.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+38 -9
View File
@@ -35,16 +35,45 @@ pub fn ips_parse(ips: &Vec<String>) -> Result<Vec<(u32, u32, Ipv4Addr)>, String>
} else {
return Err("not ipv4".to_string());
};
let mask = if let Ok(m) = mask.parse::<u32>() {
let mut mask = 0 as u32;
for i in 0..m {
mask = mask | (1 << (31 - i));
}
mask
} else {
return Err("not netmask".to_string());
};
let mask = to_ip(mask)?;
in_ips_c.push((u32::from_be_bytes(dest.octets()), mask, ip));
}
Ok(in_ips_c)
}
pub fn out_ips_parse(ips: &Vec<String>) -> Result<Vec<(u32, u32)>, String> {
let mut in_ips_c = vec![];
for x in ips {
let mut split = x.split("/");
let dest = if let Some(dest) = split.next() {
dest
} else {
return Err("no ipv4/mask".to_string());
};
let mask = if let Some(mask) = split.next() {
mask
} else {
return Err("no netmask".to_string());
};
let dest = if let Ok(dest) = dest.parse::<Ipv4Addr>() {
dest
} else {
return Err("not ipv4".to_string());
};
let mask = to_ip(mask)?;
in_ips_c.push((u32::from_be_bytes(dest.octets()), mask));
}
Ok(in_ips_c)
}
pub fn to_ip(mask: &str) -> Result<u32, String> {
if let Ok(m) = mask.parse::<u32>() {
let mut mask = 0 as u32;
for i in 0..m {
mask = mask | (1 << (31 - i));
}
Ok(mask)
} else {
Err("not netmask".to_string())
}
}
-1
View File
@@ -38,7 +38,6 @@ pub fn get_unique_identifier() -> Option<String> {
let identifier = result
.lines()
.find(|line| line.contains("IOPlatformUUID"))
.and_then(|line| line.split('"').nth(4))
.unwrap_or("").trim();
if identifier.is_empty() {
None
-40
View File
@@ -1,40 +0,0 @@
## 模块介绍
体积小,可以在服务器、路由器等环境使用
## 详细参数说明
### -k
一个虚拟局域网的标识,在同一服务器下,相同token的设备会组建一个局域网
### -n
设备名称,方便区分不同设备
### -d
设备id,每台设备的唯一标识,注意不要重复
### -c
关闭控制台交互式命令,后台运行时可以加此参数
### -s
注册和中继服务器地址,注册和转发数据
### -e
探测客户端NAT类型,不同类型有不同的打洞策略
### -a
加了此参数表示使用tap网卡,默认使用tun网卡,tun网卡效率更高
### -i、-o
配置点对网(IP代理)时使用,例如A(虚拟ip:10.26.0.2)通过B(虚拟ip:10.26.0.3,本地出口ip:192.168.0.10)访问C(目标网段192.168.0.0/24)
则在A配置 **-i 192.168.10.0/24,10.26.0.3** ,表示将192.168.10.0/24网段的数据都转发到10.26.0.3节点
在B配置 **-o 192.168.10.0/24,192.168.0.10** ,表示允许将192.168.10.0/24的数据从网卡192.168.0.10转发出去
### -w
提升通信安全性,使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密。使用相同密码的客户端才能通信
### -m
模拟组播,高频使用组播通信时,可以尝试开启此参数,默认情况下会把组播当作广播发给所有节点
默认情况(组播当广播发送):稳定性好,使用组播频率低时更省流量
模拟组播:高频使用组播时防止广播泛洪,客户端和中继服务器会维护组播成员等信息,注意使用此选项时,虚拟网内所有成员都需要开启此选项
### -u
设置虚拟网卡的mtu值,大多数情况下使用默认值效率会更高,也可根据实际情况微调这个值,默认值为1430
-274
View File
@@ -1,274 +0,0 @@
use std::net::ToSocketAddrs;
use std::str::FromStr;
#[cfg(not(feature = "mini"))]
use console::style;
use getopts::Options;
use tokio::io::{AsyncBufReadExt, BufReader};
use common::args_parse::ips_parse;
use switch::core::{Config, SwitchUtil};
use switch::handle::registration_handler::ReqEnum;
mod command;
mod console_out;
mod root_check;
#[tokio::main]
async fn main() {
let args: Vec<String> = std::env::args().collect();
let program = args[0].clone();
let mut opts = Options::new();
opts.long_only(false);
opts.optopt("k", "", &format!("{}", green("使用相同的token,就能组建一个局域网络".to_string())), "<token>");
opts.optopt("n", "", "给设备一个名字", "<name>");
opts.optopt("d", "", "设备唯一标识符,凭id分配ip", "<id>");
#[cfg(not(feature = "mini"))]
opts.optflag("c", "", "关闭交互式命令");
opts.optopt("s", "", "注册和中继服务器地址", "<server>");
opts.optopt("e", "", "NAT探测服务器地址,使用逗号分隔", "<addr1,addr2>");
opts.optflag("a", "", "使用tap模式,默认使用tun模式");
opts.optmulti("i", "", "配置点对网(IP代理)时使用,-i 192.168.10.0/24,10.26.0.3,表示允许接收网段192.168.10.0/24的数据并转发到10.26.0.3", "<in-ip>");
opts.optmulti("o", "", "配置点对网时使用,-o 192.168.10.0/24,192.168.1.10,表示允许目标为192.168.10.0/24的数据从网卡192.168.1.10转发出去", "<out-ip>");
opts.optopt("w", "", "使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信", "<password>");
opts.optflag("m", "", "模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送");
opts.optopt("u", "", "虚拟网卡mtu值", "<mtu>");
//"后台运行时,查看其他设备列表"
opts.optflag("", "list", &format!("{}", yellow("后台运行时,查看其他设备列表".to_string())));
opts.optflag("", "all", &format!("{}", yellow("后台运行时,查看其他设备完整信息".to_string())));
opts.optflag("", "info", &format!("{}", yellow("后台运行时,查看当前设备信息".to_string())));
opts.optflag("", "route", &format!("{}", yellow("后台运行时,查看数据转发路径".to_string())));
opts.optflag("", "stop", &format!("{}", yellow("停止后台运行".to_string())));
opts.optflag("h", "help", "帮助");
let matches = match opts.parse(&args[1..]) {
Ok(m) => { m }
Err(f) => {
print_usage(&program, opts);
println!("{}", f.to_string());
return;
}
};
if matches.opt_present("h") || args.len() == 1 {
print_usage(&program, opts);
return;
}
if !root_check::is_app_elevated() {
println!("Please run it with administrator or root privileges");
return;
}
if matches.opt_present("list") {
command::command(command::CommandEnum::List);
return;
} else if matches.opt_present("info") {
command::command(command::CommandEnum::Info);
return;
} else if matches.opt_present("stop") {
command::command(command::CommandEnum::Stop);
return;
} else if matches.opt_present("route") {
command::command(command::CommandEnum::Route);
return;
} else if matches.opt_present("all") {
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();
#[cfg(not(feature = "mini"))]
let device_id = if device_id.is_empty() {
common::identifier::get_unique_identifier().unwrap_or(String::new())
} 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:29871".to_string()).unwrap();
let server_address = server_address_str.to_socket_addrs().unwrap().next().unwrap();
let nat_test_server = matches.opt_get_default("e",
"nat1.wherewego.top:35061,nat1.wherewego.top:35062,nat2.wherewego.top:35061,nat2.wherewego.top:35062".to_string()).unwrap();
let nat_test_server = nat_test_server.split(",").flat_map(|a| a.to_socket_addrs()).flatten()
.collect::<Vec<_>>();
let 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 {}", e);
return;
}
};
let out_ip = matches.opt_strs("o");
let out_ip = match ips_parse(&out_ip) {
Ok(out_ip) => { out_ip }
Err(e) => {
print_usage(&program, opts);
println!();
println!("-o {}", e);
return;
}
};
let password: Option<String> = matches.opt_get("w").unwrap();
let simulate_multicast = matches.opt_present("m");
#[cfg(feature = "mini")]
let unused_cmd = true;
#[cfg(not(feature = "mini"))]
let unused_cmd = matches.opt_present("c");
let mtu: Option<String> = matches.opt_get("u").unwrap();
let mtu = if let Some(mtu) = mtu {
match u16::from_str(&mtu) {
Ok(mtu) => {
Some(mtu)
}
Err(e) => {
print_usage(&program, opts);
println!();
println!("-u {}", e);
return;
}
}
} else {
None
};
let config = Config::new(tap,
token, device_id, name,
server_address, server_address_str,
nat_test_server, in_ip,
out_ip, password, simulate_multicast, mtu);
let mut switch_util = SwitchUtil::new(config).await.unwrap();
let response = loop {
match switch_util.connect().await {
Ok(response) => {
break response;
}
Err(e) => {
match e {
ReqEnum::TokenError => {
println!("token error");
}
ReqEnum::AddressExhausted => {
println!("address exhausted");
}
ReqEnum::Timeout => {
println!("timeout...");
continue;
}
ReqEnum::ServerError(str) => {
println!("error:{}", str);
}
ReqEnum::Other(str) => {
println!("error:{}", str);
}
}
return;
}
}
};
println!(" ====== Connect Successfully ====== ");
println!("virtual_gateway:{}", response.virtual_gateway);
println!("virtual_ip:{}", green(response.virtual_ip.to_string()));
let driver_info = switch_util.create_iface().unwrap();
println!(" ====== Create Network Interface Successfully ====== ");
println!("name:{}", driver_info.name);
println!("version:{}", driver_info.version);
let mut switch = match switch_util.build().await {
Ok(switch) => {
switch
}
Err(e) => {
println!("error:{}", e);
return;
}
};
println!(" ====== Start Successfully ====== ");
let switch_s = switch.clone();
tokio::spawn(async {
if let Err(e) = command::server::CommandServer::new().start(switch_s).await {
println!("command error :{}", e);
}
});
if unused_cmd {
switch.wait_stop().await;
} else {
#[cfg(not(feature = "mini"))]
{
let stdin = tokio::io::stdin();
let mut cmd = String::new();
let mut reader = BufReader::new(stdin);
loop {
cmd.clear();
println!("input:list,info,route,all,stop");
tokio::select! {
_ = switch.wait_stop()=>{
break;
}
rs = reader.read_line(&mut cmd)=>{
match rs {
Ok(len) => {
if len ==0 {
break;
}
match cmd[..len].to_lowercase().trim() {
"list" => {
let list = command::command_list(&switch);
console_out::console_device_list(list);
}
"info"=>{
let info = command::command_info(&switch);
console_out::console_info(info);
}
"route" =>{
let route = command::command_route(&switch);
console_out::console_route_table(route);
}
"all" =>{
let list = command::command_list(&switch);
console_out::console_device_list_all(list);
}
"stop" =>{
let _ = switch.stop();
break;
}
_ => {
}
}
println!();
}
Err(e) => {
println!("input err:{}",e);
break;
}
}
}
}
}
switch.wait_stop().await;
}
}
std::process::exit(0);
}
fn print_usage(program: &str, opts: Options) {
let brief = format!("Usage: {} [options]", program);
println!("version:1.1.0");
println!("{}", opts.usage(&brief));
}
fn green(str: String) -> impl std::fmt::Display {
style(str).green()
}
fn yellow(str: String) -> impl std::fmt::Display {
style(str).yellow()
}
-37
View File
@@ -1,37 +0,0 @@
[package]
name = "switch-desktop"
version = "1.1.0"
description = "switch desktop"
authors = ["lubeilin"]
license = ""
repository = ""
default-run = "switch-desktop"
edition = "2021"
rust-version = "1.60"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
tauri-build = { version = "1.4.0", features = [] }
embed-resource = "2.2"
[dependencies]
switch = {path="../switch"}
common = {path="../common"}
dirs = "4.0.0"
os_info = "3.7.0"
lazy_static = "1.4.0"
parking_lot = "0.12.1"
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.4.0", features = [] }
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = [] }
[features]
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
# DO NOT REMOVE!!
custom-protocol = [ "tauri/custom-protocol" ]
View File
-21
View File
@@ -1,21 +0,0 @@
fn main() {
if std::env::var_os("CARGO_CFG_WINDOWS").is_some() {
let mut windows = tauri_build::WindowsAttributes::new();
windows = windows.app_manifest(r#"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
"#);
let attrs = tauri_build::Attributes::new().windows_attributes(windows);
tauri_build::try_build(attrs).expect("failed to run build script");
} else {
tauri_build::build();
}
}
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

-9
View File
@@ -1,9 +0,0 @@
use std::path::PathBuf;
pub fn get_home() -> PathBuf {
let home = dirs::home_dir().unwrap().join(".switch_desktop");
if !home.exists() {
std::fs::create_dir(&home).unwrap();
}
home
}
-27
View File
@@ -1,27 +0,0 @@
use std::fs::File;
use std::io;
use std::io::Write;
use std::os::windows::ffi::OsStrExt;
use crate::config::get_home;
const DLL_FILE: &'static [u8] = include_bytes!("../../dll/amd64/wintun.dll");
pub fn load_tun_dll() -> io::Result<()> {
let lib_path = get_home().join("lib");
if !lib_path.exists() {
std::fs::create_dir(&lib_path).unwrap();
}
let dll_path = lib_path.join("wintun.dll");
if !dll_path.exists() {
let mut f = File::create(&dll_path)?;
f.write_all(DLL_FILE)?;
f.sync_data()?;
}
let dll_directory = lib_path.as_os_str();
let dll_directory_wide: Vec<u16> = dll_directory.encode_wide().chain(Some(0)).collect();
unsafe {
winapi::um::winbase::SetDllDirectoryW(dll_directory_wide.as_ptr());
}
Ok(())
}
-225
View File
@@ -1,225 +0,0 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use std::net::{Ipv4Addr, ToSocketAddrs};
use lazy_static::lazy_static;
use parking_lot::Mutex;
use common::args_parse::ips_parse;
use switch::core::Config;
use switch::core::{Switch, SwitchUtil};
use switch::handle::registration_handler::ReqEnum;
#[cfg(windows)]
mod load_dll;
#[cfg(windows)]
mod config;
lazy_static! {
static ref SWITCH:Mutex<Option<Switch>> = Mutex::new(None);
}
fn main() {
#[cfg(windows)]
{
load_dll::load_tun_dll().unwrap();
}
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![default_value_name,default_value_device_id,connect,close,list])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
#[tauri::command]
fn default_value_name() -> String {
os_info::get().to_string()
}
#[tauri::command]
fn default_value_device_id() -> String {
common::identifier::get_unique_identifier().unwrap_or(String::new())
}
#[tauri::command]
async fn connect(config: ConnectConfig) -> Result<ConnectRegResponse, String> {
let tap = config.tap;
let token = config.token;
let device_id = config.device_id;
let name = config.name;
let server_address_str = config.server_address;
let server_address = match server_address_str.to_socket_addrs() {
Ok(mut addr) => {
if let Some(addr) = addr.next() {
addr
} else {
return Err(String::from("server"));
}
}
Err(e) => {
return Err(format!("server err:{}", e));
}
};
let nat_test_server = config.nat_test_server.split(&[',', ' '][..]).flat_map(|a| a.to_socket_addrs()).flatten()
.collect::<Vec<_>>();
let in_ips = config.in_ips.split(" ").into_iter().filter(|e| !e.is_empty()).map(|e| e.to_string()).collect();
let in_ips = match ips_parse(&in_ips) {
Ok(in_ips) => { in_ips }
Err(e) => {
return Err(format!("inIps err:{}", e));
}
};
let out_ips = config.out_ips.split(" ").into_iter().filter(|e| !e.is_empty()).map(|e| e.to_string()).collect();
let out_ips = match ips_parse(&out_ips) {
Ok(out_ips) => { out_ips }
Err(e) => {
return Err(format!("inIps err:{}", e));
}
};
let password = if config.key.is_empty() {
None
} else {
Some(config.key)
};
let simulate_multicast = config.simulate_multicast;
let config = Config::new(tap, token, device_id, name, server_address, server_address_str,
nat_test_server, in_ips, out_ips,
password, simulate_multicast, None);
let mut switch_util = SwitchUtil::new(config).await.unwrap();
let mut count = 0;
let response = loop {
match switch_util.connect().await {
Ok(response) => {
break response;
}
Err(e) => {
match e {
ReqEnum::TokenError => {
return Err("token error".to_string());
}
ReqEnum::AddressExhausted => {
return Err("address exhausted".to_string());
}
ReqEnum::Timeout => {
count += 1;
if count > 3 {
return Err("connect timeout".to_string());
}
continue;
}
ReqEnum::ServerError(str) => {
return Err(format!("error:{}", str));
}
ReqEnum::Other(str) => {
return Err(format!("error:{}", str));
}
}
}
}
};
match switch_util.create_iface() {
Ok(_) => {}
Err(e) => {
return Err(format!("create net interface error:{}", e));
}
}
match switch_util.build().await {
Ok(switch) => {
let _ = SWITCH.lock().insert(switch);
}
Err(e) => {
return Err(format!("build switch error:{}", e));
}
}
Ok(ConnectRegResponse {
virtual_ip: response.virtual_ip,
virtual_gateway: response.virtual_gateway,
virtual_netmask: response.virtual_netmask,
})
}
#[tauri::command]
fn list() -> Vec<SwitchPeerItem> {
let mut peer_list = Vec::new();
let mut guard = SWITCH.lock();
match &mut *guard {
None => {}
Some(switch) => {
let mut list = switch.device_list();
let current_device = switch.current_device();
list.sort_unstable_by_key(|v| { (v.status, v.virtual_ip) });
for x in list {
let item = if let Some(route) = switch.route(&x.virtual_ip) {
let connect = if route.is_p2p() {
"p2p".to_string()
} else if route.addr == current_device.connect_server {
"server relay".to_string()
} else {
"client relay".to_string()
};
SwitchPeerItem {
name: x.name,
virtual_ip: x.virtual_ip,
status: format!("{:?}", x.status),
connect,
rt: route.rt.to_string(),
addr: route.addr.to_string(),
}
} else {
SwitchPeerItem {
name: x.name,
virtual_ip: x.virtual_ip,
status: format!("{:?}", x.status),
connect: "".to_string(),
rt: "".to_string(),
addr: "".to_string(),
}
};
peer_list.push(item);
}
}
}
peer_list
}
#[tauri::command]
async fn close() {
let switch = SWITCH.lock().take();
match switch {
None => {}
Some(mut switch) => {
switch.stop().unwrap();
switch.wait_stop().await;
}
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct ConnectConfig {
pub tap: bool,
pub token: String,
pub device_id: String,
pub name: String,
pub server_address: String,
pub nat_test_server: String,
pub in_ips: String,
pub out_ips: String,
pub key: String,
pub simulate_multicast: bool,
}
#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct ConnectRegResponse {
pub virtual_ip: Ipv4Addr,
pub virtual_gateway: Ipv4Addr,
pub virtual_netmask: Ipv4Addr,
}
#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct SwitchPeerItem {
pub name: String,
pub virtual_ip: Ipv4Addr,
pub status: String,
pub connect: String,
pub rt: String,
pub addr: String,
}
-69
View File
@@ -1,69 +0,0 @@
{
"build": {
"withGlobalTauri": true,
"beforeBuildCommand": "",
"beforeDevCommand": "",
"devPath": "./ui",
"distDir": "./ui"
},
"package": {
"productName": "switch-desktop",
"version": "1.1.0"
},
"tauri": {
"allowlist": {
"all": false
},
"bundle": {
"active": true,
"category": "DeveloperTool",
"copyright": "",
"deb": {
"depends": []
},
"externalBin": [],
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/[email protected]",
"icons/icon.icns",
"icons/icon.ico"
],
"identifier": "top.wherewego.switch",
"longDescription": "",
"macOS": {
"entitlements": null,
"exceptionDomain": "",
"frameworks": [],
"providerShortName": null,
"signingIdentity": null
},
"resources": [],
"shortDescription": "",
"targets": "all",
"windows": {
"certificateThumbprint": null,
"digestAlgorithm": "sha256",
"timestampUrl": ""
}
},
"security": {
"csp": null
},
"updater": {
"active": false
},
"windows": [
{
"fullscreen": false,
"height": 600,
"resizable": true,
"title": "Switch Desktop",
"width": 892,
"minWidth": 892,
"minHeight": 600,
"center": true
}
]
}
}
-681
View File
@@ -1,681 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Switch Desktop</title>
<script src="js/jquery-3.7.0.min.js"></script>
<style>
html {
background-color: #f1f1f1;
}
.add {
position: relative;
width: 100px;
height: 100px;
transition: color 1s;
border: 1px solid #616161;
border-radius: 5px;
cursor: pointer;
margin: 14px;
}
.add:before {
content: "";
position: absolute;
top: 10px;
left: 42px;
width: 16px;
border-top: 80px solid #666;
}
.add:after {
content: "";
position: absolute;
height: 16px;
left: 10px;
top: 42px;
border-left: 80px solid #666;
}
.add:hover {
border: 1px solid #4CAF50;
}
.form-row, .form-row-save {
display: flex;
flex-direction: row;
margin-bottom: 10px;
}
.form-row-save {
margin-top: 20px;
}
.form-row label {
width: 140px;
text-align: right;
margin-right: 10px;
}
.form-row input {
flex: 1;
min-height: 20px;
}
.form-row-save .reset, .save {
width: 100px;
height: 36px;
border-radius: 5px;
cursor: pointer;
border: none;
font-size: 16px;
}
.form-row-save .reset {
margin-right: 10px;
background-color: #a1a1a1;
}
.form-row-save .save {
margin-left: auto;
background-color: #4CAF50;
color: white;
}
#add-div {
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.5);
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: none;
}
#add-div-in {
padding: 30px;
height: 410px;
width: 580px;
position: relative;
background-color: #fff;
margin: 50px auto;
border-radius: 10px;
}
.data-item {
display: flex;
align-items: center;
margin-top: 5px;
border-bottom: 1px solid #b1b1b1;
font-size: 10px;
}
span {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.label {
font-weight: bold;
margin-right: 5px;
}
.item {
padding: 10px;
border: 1px solid #666;
border-radius: 5px;
width: 260px;
height: 120px;
cursor: pointer;
margin: 5px;
position: relative;
}
.item:hover {
border: 1px solid #4CAF50;
background-color: #e1e1e1;
}
.list {
min-width: 880px;
width: 100%;
height: 100%;
}
.left-float {
float: left;
}
.menu {
position: absolute;
display: none;
border: 1px solid #f1f1f1;
background-color: #fff;
box-shadow: 1px 1px 10px 5px rgba(0, 0, 0, 0.2);
border-radius: 6px;
overflow: hidden;
z-index: 999;
}
.menu-items {
list-style-type: none;
padding: 0;
margin: 0;
width: 90px;
background-color: #fff;
text-align: center;
cursor: pointer;
}
.menu-items li::after {
content: '';
position: absolute;
bottom: 0;
left: 10px;
width: 70px;
height: 1px;
background-color: #e1e1e1;
}
.menu-items li {
position: relative;
padding: 5px;
}
.menu-items li:hover {
background-color: #f0f0f0;
}
#connect-body {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #f1f1f1;
display: none;
}
#connect-body .top {
position: relative;
margin: 10px;
}
#connect-body .bottom {
position: relative;
}
.peer-item {
padding: 10px;
border: 1px solid #666;
border-radius: 5px;
width: 260px;
height: 120px;
cursor: pointer;
margin: 5px;
position: relative;
overflow: hidden;
}
.peer-item > div {
display: flex;
align-items: center;
margin-top: 5px;
border-bottom: 1px solid #b1b1b1;
font-size: 14px;
}
/*#connect-body .bottom span {*/
/* width: 140px;*/
/*}*/
.connect-ip {
color: #4CAF50;
margin-right: 20px;
}
.connect-close {
text-align: center;
width: 80px;
height: 30px;
font-size: 20px;
position: absolute;
top: 10px;
right: 10px;
border-radius: 5px;
cursor: pointer;
background-color: chocolate;
color: floralwhite;
}
#alert-box {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #ffffff;
padding: 20px;
border-radius: 10px;
overflow: hidden;
transition: opacity 0.5s ease-in-out;
}
.hidden {
opacity: 0;
pointer-events: none;
}
#loader {
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.5);
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: none;
}
#loader div {
position: relative;
margin: 100px auto;
border: 5px solid #f3f3f3;
border-top: 5px solid #555;
border-radius: 50%;
width: 50px;
height: 50px;
/*display: inline-block;*/
animation: spin 2s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.Online {
border: 1px solid #4CAF50;
background-color: #e1e1e1;
}
.Online .peer-ip{
color: #4CAF50;
}
.Offline{
color: #555;
}
.p2p {
color: #4CAF50;
}
</style>
</head>
<body>
<div class="list">
<div id="list-in">
</div>
<div id="add-button" class="add left-float"></div>
</div>
<div id="add-div">
<div id="add-div-in">
<form id="add-form">
<div class="form-row">
<label for="token">Token:</label>
<input type="text" id="token" name="token" required>
</div>
<div class="form-row">
<label for="name">Name:</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-row">
<label for="deviceId">DeviceId:</label>
<input type="text" id="deviceId" name="device-id" required>
</div>
<div class="form-row">
<label for="password">Password:</label>
<input type="password" id="password" name="password">
</div>
<div class="form-row">
<label for="inIps">InIps:</label>
<input type="text" id="inIps" name="inIps"
placeholder="192.168.10.0/24,10.26.0.3 192.168.8.0/24,10.26.0.4">
</div>
<div class="form-row">
<label for="outIps">OutIps:</label>
<input type="text" id="outIps" name="outIps"
placeholder="192.168.10.0/24,192.168.1.10 192.168.8.0/24,192.168.1.10">
</div>
<div class="form-row">
<label for="server">ServerAddress:</label>
<input type="text" id="server" name="server" required value="nat1.wherewego.top:29871">
</div>
<div class="form-row">
<label for="natServer">NatServerAddress:</label>
<input type="text" id="natServer" name="natServer" required
value="nat1.wherewego.top:35061,nat1.wherewego.top:35062,nat2.wherewego.top:35061,nat2.wherewego.top:35062">
</div>
<div class="form-row">
<label for="simulateMulticast">SimulateMulticast:</label>
<select id="simulateMulticast" name="simulateMulticast">
<option value="false">false</option>
<option value="true">true</option>
</select>
</div>
<div class="form-row">
<label for="tunTap">Tun/Tap:</label>
<select id="tunTap" name="tunTap">
<option value="tun">tun</option>
<option value="tap">tap</option>
</select>
</div>
<div class="form-row-save">
<input class="reset" type="reset" value="cancel">
<input class="save" type="submit" value="save">
</div>
</form>
</div>
</div>
<div id="context-menu" class="menu">
<ul class="menu-items">
<li id="menu-connect">connect</li>
<li id="menu-edit">edit</li>
<li id="menu-remove">remove</li>
</ul>
</div>
<div id="connect-body">
<div class="top">
<div>
<label class="label">Server:</label>
<span class="connect-server"></span>
</div>
<div>
<label class="label">Token:</label>
<span class="connect-token"></span>
</div>
<div>
<label class="label">Name:</label>
<span class="connect-name"></span>
</div>
<div>
<label class="label">IP:</label>
<span class="connect-ip"></span>
<label class="label">Gateway:</label>
<span class="connect-gateway"></span>
<label class="label">Netmask:</label>
<span class="connect-netmask"></span>
</div>
<hr>
<div class="connect-close">
close
</div>
</div>
<div class="bottom">
</div>
</div>
<div id="alert-box" class="hidden">
<span id="alert-message"></span>
</div>
<div id="loader">
<div></div>
</div>
<script type="text/javascript">
const invoke = window.__TAURI__.invoke
let nameDefault;
let deviceIdDefault;
invoke('default_value_name').then((name) => {
$('#name').val(name);
nameDefault = name;
});
invoke('default_value_device_id').then((device_id) => {
$('#deviceId').val(device_id);
deviceIdDefault = device_id;
});
</script>
<script type="text/javascript">
let configList = [];
$('html').contextmenu(function (event) {
event.preventDefault();
})
$('html').click(function () {
$('#context-menu').css('display', 'none');
})
$('#connect-body .connect-close').click(function () {
invoke('close').then(() => {
stopFlushPeerList();
$('#connect-body').css('display', 'none');
});
})
let showAlertTimeout;
function showAlert(message, duration) {
if (showAlertTimeout != null) {
clearTimeout(showAlertTimeout);
}
$('#alert-message').text(message);
$('#alert-box').removeClass('hidden');
showAlertTimeout = setTimeout(function () {
$('#alert-box').addClass('hidden');
}, duration);
}
function loadPeerList() {
invoke('list').then((res) => {
let html = '';
for (let index = 0; index < res.length; index++) {
let item = res[index];
html += ' <div class="peer-item left-float ' + item.status + '">\n' +
' <div>\n' +
' <label class="label">name:</label>\n' +
' <span>' + item.name + '</span>\n' +
' </div>\n' +
' <div>\n' +
' <label class="label">ip:</label>\n' +
' <span class="peer-ip">' + item.virtual_ip + '</span>\n' +
' </div>\n' +
' <div>\n' +
' <label class="label">status:</label>\n' +
' <span>' + item.status + '</span>\n' +
' </div>\n' +
' <div>\n' +
' <label class="label">rt:</label>\n' +
' <span>' + item.rt + '</span>\n' +
' </div>\n' +
' <div>\n' +
' <label class="label">connect type:</label>\n' +
' <span class="' + item.connect + '">' + item.connect + '</span>\n' +
' </div>\n' +
' </div>'
}
$('#connect-body .bottom').html(html);
})
}
let flushPeerListTimeout;
function flushPeerList(duration) {
stopFlushPeerList();
flushPeerListTimeout = setInterval(function () {
loadPeerList();
}, duration);
}
function stopFlushPeerList() {
if (flushPeerListTimeout != null) {
clearInterval(flushPeerListTimeout);
}
}
let listLoad = function () {
let html = '';
for (let index = 0; index < configList.length; index++) {
let item = configList[index];
html += ' <div class="item left-float" index="' + index + '" title="connect">' +
' <div>' +
' <div class="data-item">' +
' <label class="label">Name:</label>' +
' <span>' + item.name + '</span>' +
' </div>' +
' <div class="data-item">' +
' <label class="label">Server:</label>' +
' <span>' + item.server_address + '</span>' +
' </div>' +
' <div class="data-item">' +
' <label class="label">Token:</label>' +
' <span>' + item.token + '</span>' +
' </div>' +
// ' <div class="connect">···</div>' +
' </div>' +
' </div>'
}
$('#list-in').html(html);
$('#list-in .item').mousedown(function (e) {
if (3 == e.which) {
let posX = e.clientX;
let posY = e.clientY;
$('#context-menu').attr('index', $(this).attr('index'));
$('#context-menu').css('left', posX + 'px');
$('#context-menu').css('top', posY + 'px');
$('#context-menu').css('display', 'block');
}
})
$('#list-in .item').click(function () {
let index = parseInt($(this).attr('index'));
let config = configList[index];
connect(config);
})
}
let connect = function (config) {
$('#loader').css('display', 'block');
invoke('connect', {'config': config}).then((res) => {
$('#connect-body .connect-server').html(config.server_address);
$('#connect-body .connect-token').html(config.token);
$('#connect-body .connect-name').html(config.name);
$('#connect-body .connect-ip').html(res.virtual_ip);
$('#connect-body .connect-gateway').html(res.virtual_gateway);
$('#connect-body .connect-netmask').html(res.virtual_netmask);
$('#connect-body').css('display', 'block');
$('#loader').css('display', 'none');
loadPeerList();
flushPeerList(2000);
}).catch((error) => {
$('#loader').css('display', 'none');
showAlert(error, 2000);
})
}
$('#menu-connect').click(function () {
let index = parseInt($('#context-menu').attr('index'));
let config = configList[index];
connect(config);
})
$('#menu-remove').click(function () {
let index = parseInt($('#context-menu').attr('index'));
configList.splice(index, 1);
localStorage.setItem('configList', JSON.stringify(configList));
listLoad();
})
let editIndex = -1;
$('#menu-edit').click(function () {
let index = parseInt($('#context-menu').attr('index'));
editIndex = index;
$('#index').val(index);
$('#name').val(configList[index].name);
$('#deviceId').val(configList[index].device_id);
$('#token').val(configList[index].token);
$('#password').val(configList[index].key);
$('#inIps').val(configList[index].in_ips);
$('#inIps').val(configList[index].out_ips);
$('#server').val(configList[index].server_address);
$('#natServer').val(configList[index].nat_test_server);
if (configList[index].simulate_multicast) {
$('#simulateMulticast').val('true');
} else {
$('#simulateMulticast').val('false');
}
if (configList[index].tap) {
$('#tunTap').val('tap');
} else {
$('#tunTap').val('tun');
}
$('#add-div').css('display', 'block');
})
let tmp = localStorage.getItem('configList');
if (tmp != null) {
configList = JSON.parse(tmp);
listLoad();
}
$('#add-button').click(function () {
editIndex = -1;
$('#name').val(nameDefault);
$('#deviceId').val(deviceIdDefault);
$('#add-div').css('display', 'block');
})
$('.reset').click(function () {
$('#add-div').css('display', 'none');
})
$('#add-form').submit(function () {
let token = $('#token').val();
let name = $('#name').val();
let deviceId = $('#deviceId').val();
let password = $('#password').val();
let inIps = $('#inIps').val();
let outIps = $('#outIps').val();
let server = $('#server').val();
let natServer = $('#natServer').val();
let simulateMulticast = $('#simulateMulticast').val();
let tunTap = $('#tunTap').val();
let config = {
'token': token,
'name': name,
'device_id': deviceId,
'in_ips': inIps,
'out_ips': outIps,
'server_address': server,
'nat_test_server': natServer,
'key': password,
'simulate_multicast': 'true' === simulateMulticast,
'tap': 'tap' === tunTap,
'time': Date.now()
}
if (editIndex===-1) {
let isPush = true;
for (let index = 0; index < configList.length; index++) {
let item = configList[index];
if (item.token == token && item.server_address == server) {
configList[index] = config;
isPush = false;
break;
}
}
if (isPush) {
configList.push(config);
}
} else {
configList[editIndex] = config;
}
configList.sort(function (a, b) {
return b.time - a.time;
});
listLoad();
localStorage.setItem('configList', JSON.stringify(configList));
$('#add-form')[0].reset();
$('#add-div').css('display', 'none');
return false;
})
</script>
</body>
</html>
File diff suppressed because one or more lines are too long
-2
View File
@@ -1,2 +0,0 @@
pub mod switch_util;
pub mod switch;
-406
View File
@@ -1,406 +0,0 @@
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Instant;
use crossbeam_skiplist::SkipMap;
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::Mutex;
use tokio::net::UdpSocket;
use tokio::sync::watch::{channel, Receiver, Sender};
use crate::channel::{Route, RouteKey, Status};
use crate::channel::punch::NatType;
use crate::core::status::SwitchWorker;
use crate::handle::recv_handler::ChannelDataHandler;
pub struct ContextInner {
pub(crate) lock: Mutex<()>,
pub(crate) count: AtomicUsize,
pub(crate) main_channel: Arc<UdpSocket>,
pub(crate) route_table: SkipMap<Ipv4Addr, Vec<Route>>,
pub(crate) route_table_time: SkipMap<(RouteKey, Ipv4Addr), AtomicCell<Instant>>,
pub(crate) status_receiver: Receiver<Status>,
pub(crate) status_sender: Sender<Status>,
pub(crate) udp_map: SkipMap<usize, Arc<UdpSocket>>,
pub(crate) channel_num: usize,
}
#[derive(Clone)]
pub struct Context {
pub(crate) inner: Arc<ContextInner>,
}
impl Context {
pub fn new(main_channel: Arc<UdpSocket>, _channel_num: usize) -> Self {
//当前版本只支持一个通道
let channel_num = 1;
let (status_sender, status_receiver) = channel(Status::Cone);
let inner = Arc::new(ContextInner {
lock: Mutex::new(()),
count: AtomicUsize::new(0),
main_channel,
route_table: SkipMap::new(),
route_table_time: SkipMap::new(),
status_receiver,
status_sender,
udp_map: SkipMap::new(),
channel_num,
});
Self {
inner
}
}
}
impl Context {
pub fn is_close(&self) -> bool {
*self.inner.status_receiver.borrow() == Status::Close
}
pub fn is_cone(&self) -> bool {
*self.inner.status_receiver.borrow() == Status::Cone
}
pub fn close(&self) {
let _ = self.inner.status_sender.send(Status::Close);
}
pub fn switch(&self, nat_type: NatType) {
match nat_type {
NatType::Symmetric => {
self.switch_to_symmetric();
}
NatType::Cone => {
self.switch_to_cone();
}
}
}
pub fn switch_to_cone(&self) {
let _ = self.inner.status_sender.send(Status::Cone);
}
pub fn switch_to_symmetric(&self) {
let _ = self.inner.status_sender.send(Status::Symmetric);
}
pub fn main_local_port(&self) -> io::Result<u16> {
self.inner.main_channel.local_addr().map(|k| k.port())
}
pub async fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
self.inner.main_channel.send_to(buf, addr).await
}
pub(crate) async fn send_all(&self, buf: &[u8], addr: SocketAddr) -> io::Result<()> {
for udp in self.inner.udp_map.iter() {
udp.value().send_to(buf, addr).await?;
}
Ok(())
}
pub fn try_send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
self.inner.main_channel.try_send_to(buf, addr)
}
pub async fn send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> {
if let Some(v) = self.inner.route_table.get(id) {
let route = match v.value().len() {
0 => {
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
}
1 => v.value()[0],
len => v.value()[self.inner.count.fetch_add(1, Ordering::Relaxed) % len]
};
drop(v);
if let Some(udp) = self.inner.udp_map.get(&route.index) {
return udp.value().send_to(buf, route.addr).await;
}
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub fn try_send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> {
if let Some(v) = self.inner.route_table.get(id) {
if v.value().is_empty() {
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
}
let route = v.value()[self.inner.count.fetch_add(1, Ordering::Relaxed) % v.value().len()];
drop(v);
if let Some(udp) = self.inner.udp_map.get(&route.index) {
return udp.value().try_send_to(buf, route.addr);
}
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub async fn send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
if let Some(udp) = self.inner.udp_map.get(&route_key.index) {
return udp.value().send_to(buf, route_key.addr).await;
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub fn try_send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
if let Some(udp) = self.inner.udp_map.get(&route_key.index) {
return udp.value().try_send_to(buf, route_key.addr);
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub fn add_route_if_absent(&self, id: Ipv4Addr, route: Route) {
self.add_route_(id, route, true)
}
pub fn add_route(&self, id: Ipv4Addr, route: Route) {
self.add_route_(id, route, false)
}
fn add_route_(&self, id: Ipv4Addr, route: Route, only_if_absent: bool) {
let key = route.route_key();
let guard = self.inner.lock.lock();
let mut list = if let Some(entry) = self.inner.route_table.get(&id) {
entry.value().clone()
} else {
Vec::with_capacity(4)
};
let mut exist = false;
for x in list.iter_mut() {
if x.metric < route.metric {
//不能比当前的路径更长
return;
}
if x.route_key() == key {
if only_if_absent {
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);
}
}
self.inner.route_table.insert(id, list);
self.inner.route_table_time.insert((key, id), AtomicCell::new(Instant::now()));
drop(guard);
}
pub fn route(&self, id: &Ipv4Addr) -> Option<Vec<Route>> {
if let Some(v) = self.inner.route_table.get(id) {
Some(v.value().clone())
} else {
None
}
}
pub fn route_one(&self, id: &Ipv4Addr) -> Option<Route> {
if let Some(v) = self.inner.route_table.get(id) {
v.value().iter().max_by_key(|k| k.sort_key()).map(|k| *k)
} else {
None
}
}
pub fn route_to_id(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
for x in self.inner.route_table_time.iter() {
if &x.key().0 == route_key {
return Some(x.key().1);
}
}
None
}
pub fn need_punch(&self, id: &Ipv4Addr) -> bool {
if let Some(v) = self.inner.route_table.get(id) {
if v.value().iter().filter(|k| k.is_p2p()).count() >= self.inner.channel_num {
return false;
}
}
true
}
pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec<Route>)> {
self.inner.route_table.iter().map(|k| (k.key().clone(), k.value().clone())).collect()
}
pub fn route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
let mut v = Vec::with_capacity(8);
for x in self.inner.route_table.iter() {
if let Some(route) = x.value().first() {
v.push((*x.key(), *route));
}
}
v
}
pub fn direct_route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
let mut v = Vec::with_capacity(8);
for x in self.inner.route_table.iter() {
if let Some(route) = x.value().first() {
if route.metric == 1 {
v.push((*x.key(), *route));
}
}
}
v
}
pub fn remove_route_all(&self, id: &Ipv4Addr) {
let guard = self.inner.lock.lock();
if let Some(v) = self.inner.route_table.remove(id) {
for x in v.value() {
self.inner.route_table_time.remove(&(x.route_key(), *id));
}
}
drop(guard);
}
pub fn remove_route(&self, id: &Ipv4Addr, route_key: RouteKey) {
let guard = self.inner.lock.lock();
if let Some(v) = self.inner.route_table.get(id) {
let mut routes = v.value().clone();
drop(v);
routes.retain(|x| x.route_key() != route_key);
self.inner.route_table.insert(*id, routes);
self.inner.route_table_time.remove(&(route_key, *id));
}
drop(guard);
}
pub fn update_read_time(&self, id: &Ipv4Addr, route_key: &RouteKey) {
if let Some(time) = self.inner.route_table_time.get(&(*route_key, *id)) {
time.value().store(Instant::now());
}
}
}
pub struct Channel {
context: Context,
handler: ChannelDataHandler,
}
impl Channel {
pub fn new(context: Context,
handler: ChannelDataHandler, ) -> Self {
Self {
context,
handler,
}
}
}
impl Channel {
async fn handle(handler: &mut ChannelDataHandler,
udp: &Arc<UdpSocket>,
context: &Context,
id: usize,
result: io::Result<(usize, SocketAddr)>,
buf: &mut [u8], start: usize) {
match result {
Ok((len, addr)) => {
handler.handle(buf, start, start + len, RouteKey::new(id, addr), &udp, context).await;
}
Err(e) => {
log::error!("{:?}",e)
}
}
}
pub async fn start(self,
mut worker: SwitchWorker,
head_reserve: usize,//头部预留字节
symmetric_channel_num: usize,//对称网络,则再加一组监听,提升打洞成功率
) {
let context = self.context;
let main_channel = context.inner.main_channel.clone();
let handler = self.handler.clone();
tokio::spawn(Self::start_(worker.worker("main_channel_1"), context.clone(), handler.clone(), main_channel.clone(), head_reserve, true));
tokio::spawn(Self::start_(worker.worker("main_channel_2"), context.clone(), handler, main_channel, head_reserve, true));
let mut cur_status = Status::Cone;
let mut status_receiver = context.inner.status_receiver.clone();
loop {
tokio::select! {
_=worker.stop_wait()=>{
break;
}
rs=status_receiver.changed()=>{
match rs {
Ok(_) => {
let s = status_receiver.borrow().clone();
match s {
Status::Cone => {
cur_status = Status::Cone;
}
Status::Symmetric => {
if cur_status == Status::Symmetric {
continue;
}
cur_status = Status::Symmetric;
for _ in 0..symmetric_channel_num {
match UdpSocket::bind("0.0.0.0:0").await {
Ok(udp) => {
let udp = Arc::new(udp);
let context = context.clone();
let handler = self.handler.clone();
tokio::spawn(Self::start_(worker.worker("symmetric_channel"),context, handler, udp, head_reserve, false));
}
Err(e) => {
log::error!("{}",e);
}
}
}
}
Status::Close => {
break;
}
}
}
Err(_) => {
break;
}
}
}
}
}
worker.stop_all();
}
async fn start_(mut worker: SwitchWorker, context: Context,
mut handler: ChannelDataHandler,
udp: Arc<UdpSocket>,
head_reserve: usize,
is_core: bool) {
let mut status_receiver = context.inner.status_receiver.clone();
#[cfg(target_os = "windows")]
use std::os::windows::io::AsRawSocket;
#[cfg(target_os = "windows")]
let id = udp.as_raw_socket() as usize;
#[cfg(any(unix))]
use std::os::fd::AsRawFd;
#[cfg(any(unix))]
let id = udp.as_raw_fd() as usize;
context.inner.udp_map.insert(id, udp.clone());
let mut buf = [0; 4096];
loop {
tokio::select! {
rs=udp.recv_from(&mut buf[head_reserve..])=>{
Self::handle(&mut handler,&udp,&context,id,rs,&mut buf,head_reserve).await;
}
changed=status_receiver.changed()=>{
match changed {
Ok(_) => {
match *status_receiver.borrow() {
Status::Cone => {
if !is_core{
break;
}
}
Status::Close=>{
break;
}
Status::Symmetric => {}
}
}
Err(_) => {
break;
}
}
}
_=worker.stop_wait()=>{
break;
}
}
}
context.inner.udp_map.remove(&id);
if is_core {
worker.stop_all();
}
}
}
-69
View File
@@ -1,69 +0,0 @@
use std::io;
use std::ops::Deref;
use std::time::Duration;
use tokio::runtime::Runtime;
use crate::core::{Config, Switch, SwitchUtil};
use crate::handle::registration_handler::{RegResponse, ReqEnum};
pub struct SwitchUtilSync {
switch_util: SwitchUtil,
runtime: Runtime,
}
pub struct SwitchSync {
switch: Switch,
runtime: Runtime,
}
impl SwitchUtilSync {
pub fn new(config: Config) -> io::Result<SwitchUtilSync> {
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();
let switch_util = runtime.block_on(SwitchUtil::new(config))?;
Ok(SwitchUtilSync {
switch_util,
runtime,
})
}
pub fn connect(&mut self) -> Result<RegResponse, ReqEnum> {
self.runtime.block_on(self.switch_util.connect())
}
#[cfg(any(target_os = "android"))]
pub fn create_iface(&mut self, vpn_fd: i32) {
self.switch_util.create_iface(vpn_fd)
}
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
pub fn create_iface(&mut self) -> io::Result<crate::tun_tap_device::DriverInfo> {
self.switch_util.create_iface()
}
pub fn build(self) -> crate::Result<SwitchSync> {
let runtime = self.runtime;
let switch = runtime.block_on(self.switch_util.build())?;
{
let mut switch = switch.clone();
std::thread::spawn(move || {
runtime.block_on(switch.wait_stop())
});
}
Ok(SwitchSync {
switch,
runtime: tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(),
})
}
}
impl SwitchSync {
pub fn wait_stop(&mut self) {
self.runtime.block_on(self.switch.wait_stop())
}
pub fn wait_stop_ms(&mut self, ms: u64) -> bool {
self.runtime.block_on(self.switch.wait_stop_ms(Duration::from_millis(ms)))
}
}
impl Deref for SwitchSync {
type Target = Switch;
fn deref(&self) -> &Self::Target {
&self.switch
}
}
-212
View File
@@ -1,212 +0,0 @@
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
use std::time::{Duration, Instant};
use crossbeam_utils::atomic::AtomicCell;
use protobuf::Message;
use tokio::net::UdpSocket;
use crate::channel::sender::ChannelSender;
use crate::handle::PeerDeviceInfo;
use crate::proto::message::{RegistrationRequest, RegistrationResponse};
use crate::protocol::error_packet::InErrorPacket;
use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL};
pub enum ReqEnum {
TokenError,
AddressExhausted,
Timeout,
ServerError(String),
Other(String),
}
#[derive(Clone, Debug)]
pub struct RegResponse {
pub virtual_ip: Ipv4Addr,
pub virtual_gateway: Ipv4Addr,
pub virtual_netmask: Ipv4Addr,
pub epoch: u16,
pub device_info_list: Vec<PeerDeviceInfo>,
pub public_ip: Ipv4Addr,
pub public_port: u16,
}
///向中继服务器注册,token标识一个虚拟网关,device_id防止多次注册时得到的ip不一致
pub async fn registration(
main_channel: &UdpSocket,
server_address: SocketAddr,
token: String,
device_id: String,
name: String,
) -> Result<RegResponse, ReqEnum> {
let request_packet =
registration_request_packet(token.clone(), device_id.clone(), name.clone(), false).unwrap();
let buf = request_packet.buffer();
let mut recv_buf = [0u8; 10240];
return match main_channel.send_to(buf, server_address).await {
Ok(_) => {
match tokio::time::timeout(Duration::from_millis(300), main_channel.recv_from(&mut recv_buf)).await {
Ok(rs) => {
match rs {
Ok((len, addr)) => {
if server_address == addr {
let net_packet = match NetPacket::new(&recv_buf[..len]) {
Ok(net_packet) => {
net_packet
}
Err(e) => {
return Err(ReqEnum::ServerError(format!("{}",e)))
}
};
match net_packet.protocol() {
Protocol::Service => {
match service_packet::Protocol::from(net_packet.transport_protocol()) {
service_packet::Protocol::RegistrationResponse => {
match RegistrationResponse::parse_from_bytes(net_packet.payload()) {
Ok(response) => {
let device_info_list: Vec<PeerDeviceInfo> = response
.device_info_list
.into_iter()
.map(|info| {
PeerDeviceInfo::new(
Ipv4Addr::from(info.virtual_ip),
info.name,
info.device_status as u8,
)
})
.collect();
Ok(RegResponse {
virtual_ip: Ipv4Addr::from(response.virtual_ip),
virtual_gateway: Ipv4Addr::from(response.virtual_gateway),
virtual_netmask: Ipv4Addr::from(response.virtual_netmask),
epoch: response.epoch as u16,
device_info_list,
public_ip: Ipv4Addr::from(response.public_ip),
public_port: response.public_port as u16,
})
}
Err(_) => {
Err(ReqEnum::ServerError("invalid data".to_string()))
}
}
}
_ => {
Err(ReqEnum::ServerError("invalid data".to_string()))
}
}
}
Protocol::Error => {
match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload()) {
Ok(e) => match e {
InErrorPacket::TokenError => Err(ReqEnum::TokenError),
InErrorPacket::Disconnect => {
Err(ReqEnum::ServerError("disconnect".to_string()))
}
InErrorPacket::AddressExhausted => {
Err(ReqEnum::AddressExhausted)
}
InErrorPacket::OtherError(e) => match e.message() {
Ok(str) => {
Err(ReqEnum::ServerError(str))
}
Err(e) => Err(ReqEnum::Other(format!("{}", e))),
},
},
Err(e) => Err(ReqEnum::Other(format!("{}", e))),
}
}
_ => Err(ReqEnum::ServerError("invalid data".to_string())),
}
} else {
Err(ReqEnum::Other(format!("invalid data,from {}", addr)))
}
}
Err(e) => {
Err(ReqEnum::Other(format!("receiver error:{}", e)))
}
}
}
Err(_) => {
Err(ReqEnum::Timeout)
}
}
}
Err(e) => {
Err(ReqEnum::Other(format!("send error:{}", e)))
}
};
}
fn registration_request_packet(
token: String,
device_id: String,
name: String,
is_fast: bool,
) -> crate::Result<NetPacket<Vec<u8>>> {
let mut request = RegistrationRequest::new();
request.token = token;
request.device_id = device_id;
request.name = name;
request.is_fast = is_fast;
request.version = "1.1.0".to_string();
let bytes = request.write_to_bytes()?;
let buf = vec![0u8; 12 + bytes.len()];
let mut net_packet = NetPacket::new(buf)?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Service);
net_packet.set_transport_protocol(service_packet::Protocol::RegistrationRequest.into());
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_payload(&bytes);
Ok(net_packet)
}
pub struct Register {
sender: ChannelSender,
server_address: SocketAddr,
token: String,
device_id: String,
name: String,
time: AtomicCell<Instant>,
}
impl Register {
pub fn new(
sender: ChannelSender,
server_address: SocketAddr,
token: String,
device_id: String,
name: String,
) -> Self {
Self {
sender,
server_address,
token,
device_id,
name,
time: AtomicCell::new(Instant::now()),
}
}
pub async fn fast_register(&self) -> io::Result<()> {
let last = self.time.load();
if last.elapsed() < Duration::from_secs(2)
|| self
.time
.compare_exchange(last, Instant::now())
.is_err()
{
//短时间不重复注册
return Ok(());
}
log::info!("重新连接");
let request_packet = registration_request_packet(
self.token.clone(),
self.device_id.clone(),
self.name.clone(),
false,
)
.unwrap();
let buf = request_packet.buffer();
self.sender.send_main(buf, self.server_address).await?;
Ok(())
}
}
-260
View File
@@ -1,260 +0,0 @@
use std::io;
use std::net::{Ipv4Addr, SocketAddrV4};
use aes_gcm::{AeadInPlace, Aes256Gcm, Nonce};
use aes_gcm::aead::consts::U12;
use aes_gcm::aead::generic_array::GenericArray;
use packet::ip::ipv4::packet::IpV4Packet;
use packet::ip::ipv4::protocol::Protocol;
use packet::tcp::tcp::TcpPacket;
use packet::udp::udp::UdpPacket;
use crate::channel::sender::ChannelSender;
use crate::external_route::ExternalRoute;
use crate::handle::{check_dest, CurrentDeviceInfo};
use crate::ip_proxy::IpProxyMap;
use crate::protocol::{ip_turn_packet, NetPacket, Version};
use crate::error::*;
use crate::igmp_server::IgmpServer;
use crate::protocol;
use crate::protocol::ip_turn_packet::BroadcastPacketEnd;
pub mod tun_handler;
#[cfg(any(target_os = "linux", target_os = "macos",target_os = "windows"))]
pub mod tap_handler;
async fn broadcast(sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]>, data_len: usize, current_device: &CurrentDeviceInfo) -> Result<()> {
let mut peer_ips = Vec::with_capacity(8);
let vec = sender.route_table_one();
let mut relay_count = 0;
const MAX_COUNT: usize = u8::MAX as usize;
for (peer_ip, route) in vec {
if peer_ip == current_device.virtual_gateway {
continue;
}
if peer_ips.len() == MAX_COUNT {
break;
}
if route.is_p2p()
&& sender.send_by_key(&net_packet.buffer()[..data_len], &route.route_key()).await.is_ok() {
peer_ips.push(peer_ip);
} else {
relay_count += 1;
}
}
if relay_count == 0 && !peer_ips.is_empty() && peer_ips.len() != MAX_COUNT {
//不需要转发
return Ok(());
}
if peer_ips.is_empty() {
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
} else {
let end_len = 1 + peer_ips.len() * 4;
//剩余的发送到服务端,需要告知哪些已发送过
//放在末尾可以减少复制次数
let mut broadcast = BroadcastPacketEnd::unchecked(&mut net_packet.buffer_mut()[data_len..data_len + end_len]);
broadcast.set_address(&peer_ips)?;
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4Broadcast.into());
sender.send_main(&net_packet.buffer()[..(data_len + end_len)], current_device.connect_server).await?;
}
Ok(())
}
async fn multicast(igmp_server: &IgmpServer, multicast_addr: Ipv4Addr, sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]>, data_len: usize, current_device: &CurrentDeviceInfo) -> Result<()> {
let mut peer_ips = Vec::with_capacity(8);
let vec = sender.route_table_one();
let mut relay_count = 0;
const MAX_COUNT: usize = u8::MAX as usize;
if let Some(members) = igmp_server.load(&multicast_addr) {
for (peer_ip, route) in vec {
if peer_ip == current_device.virtual_gateway {
continue;
}
let is_send = { members.read().is_send(&peer_ip) };
if is_send {
if peer_ips.len() == MAX_COUNT {
break;
}
if route.is_p2p()
&& sender.send_by_key(&net_packet.buffer()[..data_len], &route.route_key()).await.is_ok() {
peer_ips.push(peer_ip);
} else {
relay_count += 1;
}
}
}
}
if relay_count == 0 && !peer_ips.is_empty() && peer_ips.len() != MAX_COUNT {
//不需要转发
return Ok(());
}
if peer_ips.is_empty() {
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
} else {
let end_len = 1 + peer_ips.len() * 4;
//剩余的发送到服务端,需要告知哪些已发送过
//放在末尾可以减少复制次数
let mut broadcast = BroadcastPacketEnd::unchecked(&mut net_packet.buffer_mut()[data_len..data_len + end_len]);
broadcast.set_address(&peer_ips)?;
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4Broadcast.into());
sender.send_main(&net_packet.buffer()[..(data_len + end_len)], current_device.connect_server).await?;
}
Ok(())
}
/// 实现一个原地发送,必须保证是如下结构
/// |12字节开头|ip报文|至少1024字节+12字节结尾|
///
#[inline]
pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8],
mut data_len: usize,//数据总长度=ip长度+12
igmp_server: &Option<IgmpServer>,
current_device: CurrentDeviceInfo,
ip_route: &Option<ExternalRoute>, proxy_map: &Option<IpProxyMap>, cipher: &Option<Aes256Gcm>) -> 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;
let src_ip = ipv4_packet.source_ip();
let mut dest_ip = ipv4_packet.destination_ip();
let mut net_packet = NetPacket::new(buf)?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(protocol::Protocol::IpTurn);
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4.into());
net_packet.first_set_ttl(3);
net_packet.set_source(src_ip);
net_packet.set_destination(dest_ip);
if dest_ip == current_device.virtual_gateway {
if protocol == Protocol::Icmp {
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Icmp.into());
//发送到服务端的不加密
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
}
return Ok(());
}
if dest_ip.is_multicast() {
match protocol {
Protocol::Igmp => {
if igmp_server.is_some() {
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Igmp.into());
//发送到服务端
net_packet.set_destination(current_device.virtual_gateway);
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
}
return Ok(());
}
Protocol::Udp => {
if let Some(igmp_server) = igmp_server {
if let Some(cipher) = cipher {
//需要加密
encrypt(cipher, &mut data_len, &mut net_packet)?;
}
multicast(igmp_server, dest_ip, sender, &mut net_packet, data_len, &current_device).await?;
return Ok(());
} else {
//当广播
dest_ip = Ipv4Addr::BROADCAST;
net_packet.set_destination(dest_ip);
}
}
_ => {
return Ok(());
}
}
}
if dest_ip.is_broadcast() || current_device.broadcast_address == dest_ip {
// 广播 发送到直连目标
if Protocol::Udp == protocol {
if let Some(cipher) = cipher {
//需要加密
encrypt(cipher, &mut data_len, &mut net_packet)?;
}
broadcast(sender, &mut net_packet, data_len, &current_device).await?;
}
return Ok(());
}
if !check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) {
if let Some(ip_route) = ip_route {
if let Some(r_dest_ip) = ip_route.route(&dest_ip) {
//路由的目标不能是自己
if r_dest_ip == src_ip {
return Ok(());
}
//需要修改目的地址
dest_ip = r_dest_ip;
net_packet.set_destination(r_dest_ip);
} else {
return Ok(());
}
} 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.buffer_mut()[12 + ip_head_len..data_len])?;
SocketAddrV4::new(dest_ip, tcp_packet.destination_port())
};
if let Some(entry) = proxy_map.tcp_proxy_map.get(&dest_addr) {
let source_addr = entry.value().1;
let source_ip = *source_addr.ip();
let mut tcp_packet = TcpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?;
tcp_packet.set_source_port(source_addr.port());
tcp_packet.update_checksum();
let mut ipv4_packet = IpV4Packet::new(&mut net_packet.buffer_mut()[12..data_len])?;
ipv4_packet.set_source_ip(source_ip);
ipv4_packet.update_checksum();
}
}
Protocol::Udp => {
let dest_addr = {
let udp_packet = UdpPacket::new(src_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?;
SocketAddrV4::new(dest_ip, udp_packet.destination_port())
};
if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) {
let source_addr = entry.value().1;
let source_ip = *source_addr.ip();
let mut udp_packet = UdpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?;
udp_packet.set_source_port(source_addr.port());
udp_packet.update_checksum();
let mut ipv4_packet = IpV4Packet::new(&mut net_packet.buffer_mut()[12..data_len])?;
ipv4_packet.set_source_ip(source_ip);
ipv4_packet.update_checksum();
}
}
_ => {}
}
}
if let Some(cipher) = cipher {
//需要加密
encrypt(cipher, &mut data_len, &mut net_packet)?;
}
//优先发到直连到地址
if sender.send_by_id(&net_packet.buffer()[..data_len], &dest_ip).await.is_err() {
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
}
return Ok(());
}
fn encrypt(cipher: &Aes256Gcm, data_len: &mut usize, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result<()> {
let mut nonce = [0; 12];
nonce[0..4].copy_from_slice(&net_packet.source().octets());
nonce[4..8].copy_from_slice(&net_packet.destination().octets());
nonce[8] = protocol::Protocol::IpTurn.into();
nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce);
return match cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..*data_len - 12]) {
Ok(tag) => {
if tag.len() != 16 {
return Err(io::Error::new(io::ErrorKind::Other, format!("加密tag长度错误:{}", tag.len())));
}
net_packet.set_encrypt_flag(true);
net_packet.payload_mut()[*data_len - 12..*data_len - 12 + 16].copy_from_slice(tag.as_slice());
*data_len += 16;
Ok(())
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e)))
}
};
}
-101
View File
@@ -1,101 +0,0 @@
use std::{io, thread};
use std::sync::Arc;
use aes_gcm::Aes256Gcm;
use crossbeam_utils::atomic::AtomicCell;
use packet::icmp::Kind;
use packet::icmp::icmp::IcmpPacket;
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use crate::channel::sender::ChannelSender;
use crate::core::status::SwitchWorker;
use crate::error::*;
use crate::external_route::ExternalRoute;
use crate::handle::CurrentDeviceInfo;
use crate::igmp_server::IgmpServer;
use crate::ip_proxy::IpProxyMap;
use crate::tun_tap_device::{DeviceReader, DeviceWriter};
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())?;
if icmp.kind() == Kind::EchoRequest {
icmp.set_kind(Kind::EchoReply);
icmp.update_checksum();
let src = ipv4_packet.source_ip();
ipv4_packet.set_source_ip(ipv4_packet.destination_ip());
ipv4_packet.set_destination_ip(src);
ipv4_packet.update_checksum();
device_writer.write_ipv4_tun(ipv4_packet.buffer)?;
}
}
Ok(())
}
/// 接收tun数据,并且转发到udp上
#[inline]
async fn handle(sender: &ChannelSender, data: &mut [u8], len: usize, device_writer: &DeviceWriter, igmp_server: &Option<IgmpServer>, current_device: CurrentDeviceInfo,
ip_route: &Option<ExternalRoute>, proxy_map: &Option<IpProxyMap>, cipher: &Option<Aes256Gcm>) -> Result<()> {
let ipv4_packet = if let Ok(ipv4_packet) = IpV4Packet::new(&mut data[12..len]) {
ipv4_packet
} else {
return Ok(());
};
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);
}
return crate::handle::tun_tap::base_handle(sender, data, len, igmp_server, current_device, ip_route, proxy_map, cipher).await;
}
pub fn start(worker: SwitchWorker, sender: ChannelSender,
device_reader: DeviceReader,
device_writer: DeviceWriter,
igmp_server: Option<IgmpServer>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: Option<ExternalRoute>,
ip_proxy_map: Option<IpProxyMap>,
cipher: Option<Aes256Gcm>) {
thread::Builder::new().name("tun_handler".into()).spawn(move || {
tokio::runtime::Builder::new_current_thread()
.enable_all().build().unwrap()
.block_on(async move {
if let Err(e) = start_(sender, device_reader, &device_writer, igmp_server, current_device, ip_route, ip_proxy_map, cipher).await {
log::warn!("stop:{}",e);
}
let _ = device_writer.close();
worker.stop_all();
})
}).unwrap();
}
async fn start_(sender: ChannelSender,
device_reader: DeviceReader,
device_writer: &DeviceWriter,
igmp_server: Option<IgmpServer>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: Option<ExternalRoute>,
ip_proxy_map: Option<IpProxyMap>,
cipher: Option<Aes256Gcm>) -> io::Result<()> {
let mut buf = [0; 4096];
loop {
if sender.is_close() {
return Ok(());
}
let len = device_reader.read(&mut buf[12..])? + 12;
#[cfg(any(target_os = "macos"))]
let mut buf = &mut buf[4..];
match handle(&sender, &mut buf, len, device_writer, &igmp_server, current_device.load(), &ip_route, &ip_proxy_map, &cipher).await {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
}
}
-77
View File
@@ -1,77 +0,0 @@
use std::{io, thread};
use std::collections::HashMap;
use std::net::{Ipv4Addr, SocketAddrV4};
use std::sync::Arc;
use crossbeam_utils::atomic::AtomicCell;
use crossbeam_skiplist::SkipMap;
use socket2::{SockAddr, Socket};
use tokio::net::{TcpListener, UdpSocket};
use crate::channel::sender::ChannelSender;
use crate::handle::CurrentDeviceInfo;
use crate::ip_proxy::icmp_proxy::IcmpProxy;
use crate::ip_proxy::tcp_proxy::TcpProxy;
use crate::ip_proxy::udp_proxy::UdpProxy;
pub mod icmp_proxy;
pub mod tcp_proxy;
pub mod udp_proxy;
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)]
pub enum Protocol {
Icmp,
Tcp,
Udp,
}
#[derive(Clone)]
pub struct IpProxyMap {
pub(crate) tcp_proxy_port: u16,
pub(crate) udp_proxy_port: u16,
//真实源地址 -> (绑定地址,目的地址)
pub(crate) tcp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
pub(crate) udp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
// icmp用Identifier来区分,没有Identifier的一律不转发
pub(crate) icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
icmp_sockets: HashMap<Ipv4Addr, Arc<Socket>>,
}
impl IpProxyMap {
pub fn send_icmp(&self, buf: &[u8], src: &Ipv4Addr, dest: &Ipv4Addr) -> io::Result<usize> {
if let Some(socket) = self.icmp_sockets.get(src) {
socket.send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0)))
} else {
Err(io::Error::new(io::ErrorKind::Other, format!("not found src:{},dest:{}", src, dest)))
}
}
}
pub async fn init_proxy(sender: ChannelSender, bind_ips: Vec<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> {
let mut icmp_sockets = HashMap::new();
let tcp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>> = Arc::new(SkipMap::new());
let udp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>> = Arc::new(SkipMap::new());
let icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>> = Arc::new(SkipMap::new());
let tcp_listener = TcpListener::bind("0.0.0.0:0").await?;
let udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
let tcp_proxy_port = tcp_listener.local_addr()?.port();
let udp_proxy_port = udp_socket.local_addr()?.port();
let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map.clone());
let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map.clone());
for ip in bind_ips {
let addr = SocketAddrV4::new(ip, 0);
let icmp_proxy_map = icmp_proxy_map.clone();
let icmp_proxy = IcmpProxy::new(addr, icmp_proxy_map, sender.clone(), current_device.clone())?;
icmp_sockets.insert(ip, icmp_proxy.icmp_socket());
thread::spawn(move || {
icmp_proxy.start();
});
}
Ok((tcp_proxy, udp_proxy, IpProxyMap {
tcp_proxy_port,
udp_proxy_port,
tcp_proxy_map,
udp_proxy_map,
icmp_proxy_map,
icmp_sockets,
}))
}
-155
View File
@@ -1,155 +0,0 @@
use std::collections::HashSet;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
use std::time::Duration;
use std::{io, thread};
use crate::channel::punch::NatType;
/// 返回所有公网ip和端口变化范围
pub fn public_ip_list(addrs: &Vec<SocketAddr>) -> io::Result<(NatType, Vec<Ipv4Addr>, u16)> {
let mut hash_set = HashSet::new();
let mut max_port_range = 0;
let mut nat_type = NatType::Cone;
let mut port = 88;
for _ in 0..3 {
let udp = loop {
match UdpSocket::bind(SocketAddr::new(IpAddr::from(Ipv4Addr::from(0)), port)) {
Ok(udp) => {
break udp;
}
Err(e) => {
if e.kind() == io::ErrorKind::AddrInUse {
port += 1;
continue;
}
return Err(e);
}
}
};
let (set, min_port, max_port) = public_ip_list_(&udp, addrs)?;
drop(udp);
let port_range = max_port - min_port;
//有多个ip或者端口有变化,说明是对称nat
if nat_type == NatType::Cone && (set.len() > 1 || port_range != 0) {
nat_type = NatType::Symmetric;
}
if max_port_range < port_range {
max_port_range = port_range;
}
for x in set {
hash_set.insert(x);
}
thread::sleep(Duration::from_micros(5));
}
Ok((nat_type, hash_set.into_iter().collect(), max_port_range))
}
/// 测试样本较少,可能不对
///
/// - 移动宽带:锥形网络、一个ip、端口和局域网端口不相同
/// - 电信宽带:锥形网络、一个ip,端口和局域网端口不相同
/// - 联调宽带:对称网络、端口不变ip轮流用
/// - 移动4g:对称网络、ip端口都变 使用小的端口变化量小
/// - 联通4g:对称网络、只有一个ip 端口变化大
/// - 电信4g:对称网络只有一个ip 公网端口比较连续
/// - 综上:客户端使用小端口,针对对称网络 尝试所有ip 公网端口+-变化量的范围
/// - 打通概率 移动宽带=电信宽带>联调宽带>电信4g>移动4g>>联调4g
pub fn public_ip_list_(
udp: &UdpSocket,
addrs: &Vec<SocketAddr>,
) -> io::Result<(HashSet<Ipv4Addr>, u16, u16)> {
udp.set_read_timeout(Some(Duration::from_millis(300)))?;
let mut buf = [0u8; 128];
for addr in addrs {
let _ = udp.send_to(b"NatTest", addr)?;
}
let mut hash_set = HashSet::new();
let mut count = 0;
let mut min_port = 65535;
let mut max_port = 0;
for _ in 0..addrs.len() {
if let Ok(len) = udp.recv(&mut buf) {
if len != 16 || &buf[..10] != &b"NatType213"[..] {
continue;
}
let port = u16::from_be_bytes([buf[14], buf[15]]);
if min_port > port {
min_port = port;
}
if max_port < port {
max_port = port;
}
let ip = Ipv4Addr::new(buf[10], buf[11], buf[12], buf[13]);
hash_set.insert(ip);
count += 1;
}
}
if count <= 1 {
return Err(io::Error::from(io::ErrorKind::TimedOut));
}
Ok((hash_set, min_port, max_port))
}
/// 返回nat类型
pub fn nat_test() -> io::Result<NatType> {
for _ in 0..3 {
if NatType::Symmetric == nat_test_()? {
return Ok(NatType::Symmetric);
}
thread::sleep(Duration::from_micros(5));
}
Ok(NatType::Cone)
}
pub fn nat_test_() -> io::Result<NatType> {
let udp = UdpSocket::bind("0.0.0.0:0")?;
udp.set_read_timeout(Some(Duration::from_millis(300)))?;
let mut buf = [0u8; 128];
let _ = udp.send_to(b"NatTest", "nat1.wherewego.top:35061")?;
let _ = udp.send_to(b"NatTest", "nat1.wherewego.top:35062")?;
let _ = udp.send_to(b"NatTest", "nat2.wherewego.top:35061")?;
let _ = udp.send_to(b"NatTest", "nat2.wherewego.top:35062")?;
let mut tmp_ip_port: Option<[u8; 6]> = None;
let mut count = 0;
for _ in 0..4 {
if let Ok(len) = udp.recv(&mut buf) {
if len != 16 || &buf[..10] != &b"NatType213"[..] {
continue;
}
count += 1;
let mut ip_port = [0u8; 6];
ip_port.copy_from_slice(&buf[10..16]);
if let Some(tmp_ip_port) = &tmp_ip_port {
if tmp_ip_port != &ip_port {
return Ok(NatType::Symmetric);
}
} else {
tmp_ip_port = Some(ip_port);
}
}
}
if count <= 1 {
return Err(io::Error::from(io::ErrorKind::TimedOut));
}
Ok(NatType::Cone)
}
#[test]
fn nat_test_run() {
let udp = UdpSocket::bind("0.0.0.0:101").unwrap();
use std::net::{IpAddr, Ipv4Addr, SocketAddr, ToSocketAddrs, UdpSocket};
let addrs = vec![
"nat1.wherewego.top:35062"
.to_socket_addrs()
.unwrap()
.next()
.unwrap(),
"nat2.wherewego.top:35062"
.to_socket_addrs()
.unwrap()
.next()
.unwrap(),
];
let print = public_ip_list_(&udp, &addrs).unwrap();
println!("{:?}", print);
}
+18 -6
View File
@@ -1,13 +1,13 @@
[package]
name = "switch-cmd"
version = "1.1.0"
name = "vnt-cli"
version = "1.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
switch = {path="../switch"}
common = {path="../common"}
vnt = { path = "../vnt", package = "vnt", optional = true }
common = { path = "../common" }
tokio = { version = "1.28.1", features = ["full"] }
getopts = "0.2.21"
console = "0.15.2"
@@ -16,12 +16,24 @@ dirs = "4.0.0"
serde = "1.0"
serde_json = "1.0.94"
log = "0.4.17"
log4rs = "1.2.0"
[dependencies.uuid]
version = "1.4.1"
features = [
"v4", # Lets you generate random UUIDs
]
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
sudo = "0.6.0"
[target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] }
[features]
default = []
mini = []
default = ["normal"]
normal = ["vnt"]
ring-cipher = ["vnt/ring-cipher"]
[build-dependencies]
embed-manifest = "1.4.0"
+67
View File
@@ -0,0 +1,67 @@
## 模块介绍
体积小,可以在服务器、路由器等环境使用
## 详细参数说明
### -k `<token>`
一个虚拟局域网的标识,在同一服务器下,相同token的设备会组建一个局域网
### -n `<name>`
设备名称,方便区分不同设备
### -d `<id>`
设备id,每台设备的唯一标识,注意不要重复
### -c
关闭控制台交互式命令,后台运行时可以加此参数
### -s `<server>`
注册和中继服务器地址,注册和转发数据
### -e `<stun-server>`
使用stun服务探测客户端NAT类型,不同类型有不同的打洞策略
### -a
加了此参数表示使用tap网卡,默认使用tun网卡,tun网卡效率更高
### -i `<in-ip>`、-o `<out-ip>`
配置点对网(IP代理)时使用,例如A(虚拟ip:10.26.0.2)通过B(虚拟ip:10.26.0.3,本地出口ip:192.168.0.10)访问C(目标网段192.168.0.0/24)
则在A配置 **-i 192.168.0.0/24,10.26.0.3** ,表示将192.168.0.0/24网段的数据都转发到10.26.0.3节点
在B配置 **-o 192.168.0.0/24** ,表示允许将数据转发到 192.168.0.0/24
### -w `<password>`
提升通信安全性,使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密(包括中继数据)。使用相同密码的客户端才能通信
| 密码位数 | 加密算法 |
|---------|-------|
| 小于8 | AES128-GCM
| 大于等于8 | AES256-GCM |
### -W
开启和服务端通信加密,可以避免中间人攻击
### -m
模拟组播,高频使用组播通信时,可以尝试开启此参数,默认情况下会把组播当作广播发给所有节点
默认情况(组播当广播发送):稳定性好,使用组播频率低时更省流量
模拟组播:高频使用组播时防止广播泛洪,客户端和中继服务器会维护组播成员等信息,注意使用此选项时,虚拟网内所有成员都需要开启此选项
### -u `<mtu>`
设置虚拟网卡的mtu值,大多数情况下使用默认值效率会更高,也可根据实际情况微调这个值,不加密默认为1430,加密默认为1410
### --tcp
和服务端使用tcp通信。有些网络提供商对UDP限制比较大,这个时候可以选择使用TCP模式,提高稳定性。一般来说udp延迟和消耗更低
### --ip `<IP>`
指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配
### --par `<parallel>`
任务并行度(必须为正整数),默认值为2,该值表示处理网卡读写的任务数,组网设备数较多、处理延迟较大时可适当调大此值
### --thread `<thread>`
线程数(必须为正整数),默认为核心数乘2,该值表示处理网络读写、ip代理、打洞等用到的线程数,组网设备数较多、处理延迟较大时可适当调大此值
### --relay
禁用p2p,在网络环境很差时,只使用服务器中转效果可能更好(可以配合--tcp参数一起使用)
### --list
在后台运行时,查看其他设备列表
### --all
在后台运行时,查看其他设备完整信息
### --info
在后台运行时,查看当前设备信息
### --route
在后台运行时,查看数据转发路径
### --stop
停止后台运行
+10
View File
@@ -0,0 +1,10 @@
// use embed_manifest::{embed_manifest, new_manifest};
// use embed_manifest::manifest::ExecutionLevel;
fn main() {
////强制用管理员运行貌似体验更差了
// if std::env::var_os("CARGO_CFG_WINDOWS").is_some() {
// embed_manifest(new_manifest("vnt")
// .requested_execution_level(ExecutionLevel::RequireAdministrator)).expect("unable to embed manifest file");
// }
}
@@ -11,7 +11,7 @@ pub struct CommandClient {
impl CommandClient {
pub fn new() -> io::Result<Self> {
let path_buf = dirs::home_dir().unwrap().join(".switch_desktop").join("command-port");
let path_buf = crate::app_home()?.join("command-port");
if !path_buf.exists() {
return Err(io::Error::new(io::ErrorKind::Other, "not started"));
}
@@ -31,4 +31,6 @@ pub struct DeviceItem {
pub nat_traversal_type: String,
pub rt: String,
pub status: String,
pub client_secret: bool,
pub current_client_secret:bool,
}
@@ -1,5 +1,5 @@
use std::io;
use switch::core::Switch;
use vnt::core::Vnt;
use crate::command::entity::{DeviceItem, RouteItem, Info};
use crate::console_out;
@@ -47,11 +47,11 @@ fn command_(cmd: CommandEnum) -> io::Result<()> {
Ok(())
}
pub fn command_route(switch: &Switch) -> Vec<RouteItem> {
let route_table = switch.route_table();
pub fn command_route(vnt: &Vnt) -> Vec<RouteItem> {
let route_table = vnt.route_table();
let mut route_list = Vec::with_capacity(route_table.len());
for (destination, route) in route_table {
let next_hop = switch.route_key(&route.route_key()).map_or(String::new(), |v| v.to_string());
let next_hop = vnt.route_key(&route.route_key()).map_or(String::new(), |v| v.to_string());
let metric = route.metric.to_string();
let rt = if route.rt < 0 {
"".to_string()
@@ -71,13 +71,15 @@ pub fn command_route(switch: &Switch) -> Vec<RouteItem> {
route_list
}
pub fn command_list(switch: &Switch) -> Vec<DeviceItem> {
let device_list = switch.device_list();
pub fn command_list(vnt: &Vnt) -> Vec<DeviceItem> {
let info = vnt.current_device();
let device_list = vnt.device_list();
let mut list = Vec::new();
let current_client_secret = vnt.client_encrypt();
for peer in device_list {
let name = peer.name;
let virtual_ip = peer.virtual_ip.to_string();
let (nat_type, public_ips, local_ip) = if let Some(nat_info) = switch.peer_nat_info(&peer.virtual_ip) {
let (nat_type, public_ips, local_ip) = if let Some(nat_info) = vnt.peer_nat_info(&peer.virtual_ip) {
let nat_type = format!("{:?}", nat_info.nat_type);
let public_ips: Vec<String> = nat_info.public_ips.iter().map(|v| v.to_string()).collect();
let public_ips = public_ips.join(",");
@@ -86,8 +88,14 @@ pub fn command_list(switch: &Switch) -> Vec<DeviceItem> {
} else {
("".to_string(), "".to_string(), "".to_string())
};
let (nat_traversal_type, rt) = if let Some(route) = switch.route(&peer.virtual_ip) {
let nat_traversal_type = if route.metric == 1 { "p2p" } else { "relay" }.to_string();
let (nat_traversal_type, rt) = if let Some(route) = vnt.route(&peer.virtual_ip) {
let nat_traversal_type = if route.metric == 1 {
"p2p"
} else if route.addr == info.connect_server {
"server-relay"
} else {
"client-relay"
}.to_string();
let rt = if route.rt < 0 {
"".to_string()
} else {
@@ -98,6 +106,7 @@ pub fn command_list(switch: &Switch) -> Vec<DeviceItem> {
("relay".to_string(), "".to_string())
};
let status = format!("{:?}", peer.status);
let client_secret = peer.client_secret;
let item = DeviceItem {
name,
virtual_ip,
@@ -107,20 +116,22 @@ pub fn command_list(switch: &Switch) -> Vec<DeviceItem> {
nat_traversal_type,
rt,
status,
client_secret,
current_client_secret,
};
list.push(item);
}
list
}
pub fn command_info(switch: &Switch) -> Info {
let current_device = switch.current_device();
let nat_info = switch.nat_info();
let name = switch.name().to_string();
pub fn command_info(vnt: &Vnt) -> Info {
let current_device = vnt.current_device();
let nat_info = vnt.nat_info();
let name = vnt.name().to_string();
let virtual_ip = current_device.virtual_ip().to_string();
let virtual_gateway = current_device.virtual_gateway().to_string();
let virtual_netmask = current_device.virtual_netmask.to_string();
let connect_status = format!("{:?}", switch.connection_status());
let connect_status = format!("{:?}", vnt.connection_status());
let relay_server = current_device.connect_server.to_string();
let nat_type = format!("{:?}", nat_info.nat_type);
let public_ips: Vec<String> = nat_info.public_ips.iter().map(|v| v.to_string()).collect();
@@ -1,8 +1,8 @@
use std::io;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::io::Write;
use tokio::net::UdpSocket;
use switch::core::Switch;
use vnt::core::Vnt;
pub struct CommandServer {}
@@ -14,40 +14,21 @@ impl CommandServer {
}
impl CommandServer {
pub async fn start(self, switch: Switch) -> io::Result<()> {
let mut port = 21637 as u16;
let udp = loop {
match UdpSocket::bind(SocketAddr::V4(SocketAddrV4::new(
Ipv4Addr::new(127, 0, 0, 1),
port,
))).await {
Ok(udp) => {
break udp;
}
Err(e) => {
if e.kind() == io::ErrorKind::AddrInUse {
port += 1;
} else {
log::error!("创建udp失败 {:?}", e);
return Err(e);
}
}
}
};
let path_buf = dirs::home_dir().unwrap().join(".switch_desktop").join("command-port");
if !path_buf.parent().unwrap().exists() {
std::fs::create_dir_all(path_buf.parent().unwrap())?;
}
std::fs::write(path_buf,udp.local_addr()?.port().to_string())?;
pub async fn start(self, vnt: Vnt) -> io::Result<()> {
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())?;
file.sync_all()?;
let mut buf = [0u8; 64];
loop {
let (len, addr) = udp.recv_from(&mut buf).await?;
match std::str::from_utf8(&buf[..len]) {
Ok(cmd) => {
if let Ok(out) = command(cmd, &switch) {
if let Ok(out) = command(cmd, &vnt) {
let _ = udp.send_to(out.as_bytes(), addr).await;
if "stopped" == &out {
break;
break;
}
}
}
@@ -61,10 +42,10 @@ impl CommandServer {
}
fn command(cmd: &str, switch: &Switch) -> io::Result<String> {
fn command(cmd: &str, vnt: &Vnt) -> io::Result<String> {
let out_str = match cmd {
"route" => {
match serde_json::to_string(&crate::command::command_route(switch)) {
match serde_json::to_string(&crate::command::command_route(vnt)) {
Ok(str) => {
str
}
@@ -74,7 +55,7 @@ fn command(cmd: &str, switch: &Switch) -> io::Result<String> {
}
}
"list" => {
match serde_json::to_string(&crate::command::command_list(switch)) {
match serde_json::to_string(&crate::command::command_list(vnt)) {
Ok(str) => {
str
}
@@ -84,7 +65,7 @@ fn command(cmd: &str, switch: &Switch) -> io::Result<String> {
}
}
"info" => {
match serde_json::to_string(&crate::command::command_info(switch)) {
match serde_json::to_string(&crate::command::command_info(vnt)) {
Ok(str) => {
str
}
@@ -94,7 +75,7 @@ fn command(cmd: &str, switch: &Switch) -> io::Result<String> {
}
}
"stop" => {
switch.stop()?;
vnt.stop()?;
"stopped".to_string()
}
_ => {
@@ -56,18 +56,27 @@ pub fn console_device_list(mut list: Vec<DeviceItem>) {
("Rt".to_string(), Style::new())]);
for item in list {
if &item.status == "Online" {
if &item.nat_traversal_type == "p2p" {
out_list.push(vec![(item.name, Style::new().green()),
(item.virtual_ip, Style::new().green()),
(item.status, Style::new().green()),
(item.nat_traversal_type, Style::new().green()),
(item.rt, Style::new().green())]);
if item.client_secret != item.current_client_secret {
//加密状态不一致,无法通信的
out_list.push(vec![(item.name, Style::new().red()),
(item.virtual_ip, Style::new().red()),
(item.status, Style::new().red()),
("".to_string(), Style::new().red()),
("".to_string(), Style::new().red())]);
} else {
out_list.push(vec![(item.name, Style::new().yellow()),
(item.virtual_ip, Style::new().yellow()),
(item.status, Style::new().yellow()),
(item.nat_traversal_type, Style::new().yellow()),
(item.rt, Style::new().yellow())]);
if &item.nat_traversal_type == "p2p" {
out_list.push(vec![(item.name, Style::new().green()),
(item.virtual_ip, Style::new().green()),
(item.status, Style::new().green()),
(item.nat_traversal_type, Style::new().green()),
(item.rt, Style::new().green())]);
} else {
out_list.push(vec![(item.name, Style::new().yellow()),
(item.virtual_ip, Style::new().yellow()),
(item.status, Style::new().yellow()),
(item.nat_traversal_type, Style::new().yellow()),
(item.rt, Style::new().yellow())]);
}
}
} else {
out_list.push(vec![(item.name, Style::new().color256(102)),
@@ -92,11 +101,11 @@ pub fn console_device_list_all(mut list: Vec<DeviceItem>) {
out_list.push(vec![("Name".to_string(), Style::new()),
("Virtual Ip".to_string(), Style::new()),
("Status".to_string(), Style::new()),
("P2P/Relay".to_string(), Style::new()),
("Rt".to_string(), Style::new()),
("NAT Type".to_string(), Style::new()),
("Public Ips".to_string(), Style::new()),
("Local Ip".to_string(), Style::new()),
("P2P/Relay".to_string(), Style::new()),
("Rt".to_string(), Style::new())]);
("Local Ip".to_string(), Style::new())]);
for item in list {
if &item.status == "Online" {
if &item.nat_traversal_type == "p2p" {
@@ -7,7 +7,7 @@ pub fn println_table(table: Vec<Vec<(String, Style)>>) {
let mut width_list = vec![0; table[0].len()];
for in_list in table.iter() {
for (index, (item, _)) in in_list.iter().enumerate() {
let width = console::measure_text_width(item) + 6;
let width = console::measure_text_width(item) + 4;
if width_list[index] < width {
width_list[index] = width;
}
+477
View File
@@ -0,0 +1,477 @@
use std::io;
use std::net::{Ipv4Addr, ToSocketAddrs};
use std::path::PathBuf;
use std::str::FromStr;
use console::style;
use getopts::Options;
use tokio::io::{AsyncBufReadExt, BufReader};
use tokio::signal;
#[cfg(unix)]
use tokio::signal::unix::{signal, SignalKind};
use common::args_parse::{ips_parse, out_ips_parse};
use vnt::cipher::CipherModel;
use vnt::core::{Config, Vnt, VntUtil};
use vnt::handle::handshake_handler::HandshakeEnum;
use vnt::handle::registration_handler::ReqEnum;
mod command;
mod console_out;
mod root_check;
pub fn app_home() -> io::Result<PathBuf> {
let path = dirs::home_dir().ok_or(io::Error::new(io::ErrorKind::Other, "not home"))?.join(".vnt-cli");
if !path.exists() {
std::fs::create_dir_all(&path)?;
}
Ok(path)
}
fn main() {
let _ = log4rs::init_file("log4rs.yaml", Default::default());
let args: Vec<String> = std::env::args().collect();
let program = args[0].clone();
let mut opts = Options::new();
opts.optopt("k", "", "组网标识", "<token>");
opts.optopt("n", "", "设备名称", "<name>");
opts.optopt("d", "", "设备标识", "<id>");
opts.optflag("c", "", "关闭交互式命令");
opts.optopt("s", "", "注册和中继服务器地址", "<server>");
opts.optmulti("e", "", "stun服务器", "<stun-server>");
opts.optflag("a", "", "使用tap模式");
opts.optmulti("i", "", "配置点对网(IP代理)入站时使用", "<in-ip>");
opts.optmulti("o", "", "配置点对网出站时使用", "<out-ip>");
opts.optopt("w", "", "客户端加密", "<password>");
opts.optflag("W", "", "服务端加密");
opts.optflag("m", "", "模拟组播");
opts.optopt("u", "", "自定义mtu(默认为1430)", "<mtu>");
opts.optflag("", "tcp", "tcp");
opts.optopt("", "ip", "指定虚拟ip", "<ip>");
opts.optflag("", "relay", "仅使用服务器转发");
opts.optopt("", "par", "任务并行度(必须为正整数)", "<parallel>");
opts.optopt("", "thread", "线程数(必须为正整数)", "<thread>");
opts.optopt("", "model", "加密模式", "<model>");
//"后台运行时,查看其他设备列表"
opts.optflag("", "list", "后台运行时,查看其他设备列表");
opts.optflag("", "all", "后台运行时,查看其他设备完整信息");
opts.optflag("", "info", "后台运行时,查看当前设备信息");
opts.optflag("", "route", "后台运行时,查看数据转发路径");
opts.optflag("", "stop", "停止后台运行");
opts.optflag("h", "help", "帮助");
let matches = match opts.parse(&args[1..]) {
Ok(m) => { m }
Err(f) => {
print_usage(&program, opts);
println!("{}", f.to_string());
return;
}
};
if matches.opt_present("h") || args.len() == 1 {
print_usage(&program, opts);
return;
}
if !root_check::is_app_elevated() {
println!("Please run it with administrator or root privileges");
#[cfg(any(target_os = "linux", target_os = "macos"))]
sudo::escalate_if_needed().unwrap();
return;
}
if matches.opt_present("list") {
command::command(command::CommandEnum::List);
return;
} else if matches.opt_present("info") {
command::command(command::CommandEnum::Info);
return;
} else if matches.opt_present("stop") {
command::command(command::CommandEnum::Stop);
return;
} else if matches.opt_present("route") {
command::command(command::CommandEnum::Route);
return;
} else if matches.opt_present("all") {
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 .");
return;
}
}
Err(e) => {
println!("parameter -s error {}.", 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 {}", e);
println!("example: -i 192.168.0.0/24,10.26.0.3");
return;
}
};
let out_ip = matches.opt_strs("o");
let out_ip = match out_ips_parse(&out_ip) {
Ok(out_ip) => { out_ip }
Err(e) => {
print_usage(&program, opts);
println!();
println!("-o {}", e);
println!("example: -o 0.0.0.0/0");
return;
}
};
let password: Option<String> = matches.opt_get("w").unwrap();
let server_encrypt = matches.opt_present("W");
let simulate_multicast = matches.opt_present("m");
let unused_cmd = matches.opt_present("c");
let mtu: Option<String> = matches.opt_get("u").unwrap();
let mtu = if let Some(mtu) = mtu {
match u16::from_str(&mtu) {
Ok(mtu) => {
Some(mtu)
}
Err(e) => {
print_usage(&program, opts);
println!();
println!("-u {}", 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("--ip error"));
if let Some(virtual_ip) = virtual_ip {
if virtual_ip.is_unspecified() || virtual_ip.is_broadcast() || virtual_ip.is_multicast() {
println!("--ip invalid");
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");
return;
}
let thread_num = matches.opt_get::<usize>("thread").unwrap().unwrap_or(std::thread::available_parallelism().unwrap().get() * 2);
let cipher_model = matches.opt_get::<CipherModel>("model").unwrap().unwrap_or(CipherModel::AesGcm);
if thread_num == 0 {
println!("--thread invalid");
return;
}
println!("version 1.2.0");
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);
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().worker_threads(thread_num).build().unwrap();
runtime.block_on(main0(config, !unused_cmd));
std::process::exit(0);
}
async fn main0(config: Config, show_cmd: bool) {
let server_encrypt = config.server_encrypt;
let mut vnt_util = VntUtil::new(config).await.unwrap();
let mut conn_count = 0;
let response = loop {
if conn_count > 0 {
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
}
conn_count += 1;
if let Err(e) = vnt_util.connect().await {
println!("connect server failed {}", e);
return;
}
match vnt_util.handshake().await {
Ok(response) => {
if server_encrypt {
let finger = response.unwrap().finger().unwrap();
println!("{}{}", green("server fingerprint:".to_string()), finger);
match vnt_util.secret_handshake().await {
Ok(_) => {}
Err(e) => {
match e {
HandshakeEnum::NotSecret => {}
HandshakeEnum::KeyError => {}
HandshakeEnum::Timeout => {
println!("handshake timeout")
}
HandshakeEnum::ServerError(str) => {
println!("error:{}", str);
}
HandshakeEnum::Other(str) => {
println!("error:{}", str);
}
}
continue;
}
}
}
match vnt_util.register().await {
Ok(response) => {
break response;
}
Err(e) => {
match e {
ReqEnum::TokenError => {
println!("token error");
return;
}
ReqEnum::AddressExhausted => {
println!("address exhausted");
return;
}
ReqEnum::Timeout => {
println!("timeout...");
}
ReqEnum::ServerError(str) => {
println!("error:{}", str);
}
ReqEnum::Other(str) => {
println!("error:{}", str);
}
ReqEnum::IpAlreadyExists => {
println!("ip already exists");
return;
}
ReqEnum::InvalidIp => {
println!("invalid ip");
return;
}
}
}
}
}
Err(e) => {
match e {
HandshakeEnum::NotSecret => {
println!("The server does not support encryption");
return;
}
HandshakeEnum::KeyError => {}
HandshakeEnum::Timeout => {
println!("handshake timeout")
}
HandshakeEnum::ServerError(str) => {
println!("error:{}", str);
}
HandshakeEnum::Other(str) => {
println!("error:{}", str);
}
}
}
}
};
println!(" ====== Connect Successfully ====== ");
println!("virtual_gateway:{}", response.virtual_gateway);
println!("virtual_ip:{}", green(response.virtual_ip.to_string()));
let driver_info = vnt_util.create_iface().unwrap();
println!(" ====== Create Network Interface Successfully ====== ");
println!("name:{}", driver_info.name);
println!("version:{}", driver_info.version);
let mut vnt = match vnt_util.build().await {
Ok(vnt) => {
vnt
}
Err(e) => {
println!("error:{}", e);
return;
}
};
println!(" ====== Start Successfully ====== ");
let vnt_c = vnt.clone();
tokio::spawn(async {
if let Err(e) = command::server::CommandServer::new().start(vnt_c).await {
println!("command error :{}", e);
}
});
if show_cmd {
let stdin = tokio::io::stdin();
let mut cmd = String::new();
let mut reader = BufReader::new(stdin);
#[cfg(unix)]
let mut sigterm = signal(SignalKind::terminate()).expect("Error setting SIGTERM handler");
loop {
cmd.clear();
println!("input:list,info,route,all,stop");
#[cfg(unix)]
tokio::select! {
_ = vnt.wait_stop()=>{
break;
}
_ = signal::ctrl_c()=>{
let _ = vnt.stop();
vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await;
return;
}
_ = sigterm.recv()=>{
let _ = vnt.stop();
vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await;
return;
}
rs = reader.read_line(&mut cmd)=>{
match rs {
Ok(len) => {
if !command(&cmd[..len],&vnt){
break;
}
}
Err(e) => {
println!("input err:{}",e);
break;
}
}
}
}
#[cfg(windows)]
tokio::select! {
_ = vnt.wait_stop()=>{
break;
}
_ = signal::ctrl_c()=>{
let _ = vnt.stop();
vnt.wait_stop_ms(std::time::Duration::from_secs(3)).await;
return;
}
rs = reader.read_line(&mut cmd)=>{
match rs {
Ok(len) => {
if !command(&cmd[..len],&vnt){
break;
}
}
Err(e) => {
println!("input err:{}",e);
break;
}
}
}
}
}
}
vnt.wait_stop().await;
}
fn command(cmd: &str, vnt: &Vnt) -> bool {
if cmd.is_empty() {
return false;
}
match cmd.to_lowercase().trim() {
"list" => {
let list = command::command_list(&vnt);
console_out::console_device_list(list);
}
"info" => {
let info = command::command_info(&vnt);
console_out::console_info(info);
}
"route" => {
let route = command::command_route(&vnt);
console_out::console_route_table(route);
}
"all" => {
let list = command::command_list(&vnt);
console_out::console_device_list_all(list);
}
"stop" => {
let _ = vnt.stop();
return false;
}
_ => {}
}
println!();
return true;
}
fn print_usage(program: &str, _opts: Options) {
println!("Usage: {} [options]", program);
println!("version:1.2.0");
println!("Options:");
println!(" -k <token> {}", green("必选,使用相同的token,就能组建一个局域网络".to_string()));
println!(" -n <name> 给设备一个名字,便于区分不同设备,默认使用系统版本");
println!(" -d <id> 设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip");
println!(" -c 关闭交互式命令,使用此参数禁用控制台输入");
println!(" -s <server> 注册和中继服务器地址");
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可多次指定,如-e addr1 -e addr2");
println!(" -a 使用tap模式,默认使用tun模式");
println!(" -i <in-ip> 配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据");
println!(" 并转发到10.26.0.3,可指定多个网段");
println!(" -o <out-ip> 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段");
println!(" -w <password> 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信");
println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确");
println!(" -m 模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送");
println!(" -u <mtu> 自定义mtu(不加密默认为1430,加密默认为1410)");
println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp");
println!(" --ip <ip> 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配");
println!(" --relay 仅使用服务器转发,不使用p2p,默认情况允许使用p2p");
println!(" --par <parallel> 任务并行度(必须为正整数),默认值为1");
println!(" --thread <thread> 线程数(必须为正整数),默认为核心数乘2");
println!(" --model <model> 加密模式,可选值 aes_gcm/aes_cbc,默认使用aes_gcm,通常情况使用aes_cbc性能更好");
println!();
println!(" --list {}", yellow("后台运行时,查看其他设备列表".to_string()));
println!(" --all {}", yellow("后台运行时,查看其他设备完整信息".to_string()));
println!(" --info {}", yellow("后台运行时,查看当前设备信息".to_string()));
println!(" --route {}", yellow("后台运行时,查看数据转发路径".to_string()));
println!(" --stop {}", yellow("停止后台运行".to_string()));
println!(" -h, --help 帮助");
}
fn green(str: String) -> impl std::fmt::Display {
style(str).green()
}
fn yellow(str: String) -> impl std::fmt::Display {
style(str).yellow()
}
+3 -3
View File
@@ -1,12 +1,12 @@
[package]
name = "switch-jni"
version = "0.1.0"
name = "vnt-jni"
version = "1.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
switch = {path="../switch"}
vnt = {path="../vnt"}
jni = { version = "0.21.1", default-features = false }
[lib]
+2
View File
@@ -0,0 +1,2 @@
pub mod vnt_util;
pub mod vnt;
+29 -29
View File
@@ -3,39 +3,39 @@ use jni::errors::Error;
use jni::JNIEnv;
use jni::objects::{JClass, JObject, JValue};
use jni::sys::{jboolean, jbyte, jint, jlong, jobject, jobjectArray, jsize};
use switch::channel::Route;
use switch::core::sync::SwitchSync;
use switch::handle::PeerDeviceInfo;
use vnt::channel::Route;
use vnt::core::sync::VntSync;
use vnt::handle::PeerDeviceInfo;
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_stop0(
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_stop0(
_env: JNIEnv,
_class: JClass,
raw_switch: jlong,
raw_vnt: jlong,
) {
let switch = raw_switch as *mut SwitchSync;
let _ = (&*switch).stop();
let vnt = raw_vnt as *mut VntSync;
let _ = (&*vnt).stop();
}
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_waitStop0(
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_waitStop0(
_env: JNIEnv,
_class: JClass,
raw_switch: jlong,
raw_vnt: jlong,
) {
let switch = raw_switch as *mut SwitchSync;
let _ = (&mut *switch).wait_stop();
let vnt = raw_vnt as *mut VntSync;
let _ = (&mut *vnt).wait_stop();
}
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_waitStopMs0(
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_waitStopMs0(
_env: JNIEnv,
_class: JClass,
raw_switch: jlong,
raw_vnt: jlong,
ms: jlong,
) -> jboolean {
let switch = raw_switch as *mut SwitchSync;
if (&mut *switch).wait_stop_ms(ms as _) {
let vnt = raw_vnt as *mut VntSync;
if (&mut *vnt).wait_stop_ms(ms as _) {
jni::sys::JNI_TRUE
} else {
jni::sys::JNI_FALSE
@@ -43,28 +43,28 @@ pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_waitStopMs0(
}
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_drop0(
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_drop0(
_env: JNIEnv,
_class: JClass,
raw_switch: jlong,
raw_vnt: jlong,
) {
let switch = raw_switch as *mut SwitchSync;
let _ = Box::from_raw(switch).stop();
let vnt = raw_vnt as *mut VntSync;
let _ = Box::from_raw(vnt).stop();
}
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_list0(
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_list0(
mut env: JNIEnv,
_class: JClass,
raw_switch: jlong,
raw_vnt: jlong,
) -> jobjectArray {
let switch = raw_switch as *mut SwitchSync;
let switch = &mut *switch;
let list = switch.device_list();
let vnt = raw_vnt as *mut VntSync;
let vnt = &mut *vnt;
let list = vnt.device_list();
let arr = match env.new_object_array(
list.len() as jsize,
"top/wherewego/switchjni/PeerDeviceInfo",
"top/wherewego/vnt/jni/PeerDeviceInfo",
JObject::null(),
) {
Ok(arr) => { arr }
@@ -75,7 +75,7 @@ pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_list0(
}
};
for (index, peer) in list.into_iter().enumerate() {
let route = if let Some(route) = switch.route(&peer.virtual_ip) {
let route = if let Some(route) = vnt.route(&peer.virtual_ip) {
match route_parse(&mut env, route) {
Ok(route) => {
JObject::from_raw(route)
@@ -113,7 +113,7 @@ fn route_parse(env: &mut JNIEnv, route: Route) -> Result<jobject, Error> {
let metric = route.metric;
let rt = route.rt;
let rs = env.new_object(
"top/wherewego/switchjni/Route",
"top/wherewego/vnt/jni/Route",
"(Ljava/lang/String;BI)V",
&[JValue::Object(&env.new_string(address)?.into()),
JValue::Byte(metric as jbyte),
@@ -127,8 +127,8 @@ fn peer_device_info_parse(env: &mut JNIEnv, peer: PeerDeviceInfo, route: JObject
let name = peer.name.to_string();
let status = format!("{:?}", peer.status);
let rs = env.new_object(
"top/wherewego/switchjni/PeerDeviceInfo",
"(ILjava/lang/String;Ljava/lang/String;Ltop/wherewego/switchjni/Route;)V",
"top/wherewego/vnt/jni/PeerDeviceInfo",
"(ILjava/lang/String;Ljava/lang/String;Ltop/wherewego/vnt/jni/Route;)V",
&[JValue::Int(virtual_ip as jint),
JValue::Object(&env.new_string(name)?.into()),
JValue::Object(&env.new_string(status)?.into()),
@@ -7,11 +7,12 @@ use jni::objects::{JClass, JObject, JString, JValue};
use jni::sys::jboolean;
use jni::sys::{jint, jlong, jobject};
use jni::JNIEnv;
use switch::core::Config;
use switch::core::sync::SwitchUtilSync;
use switch::handle::registration_handler::{RegResponse, ReqEnum};
use vnt::cipher::CipherModel;
use vnt::core::Config;
use vnt::core::sync::VntUtilSync;
use vnt::handle::registration_handler::{RegResponse, ReqEnum};
#[cfg(not(target_os = "android"))]
use switch::tun_tap_device::DriverInfo;
use vnt::tun_tap_device::DriverInfo;
fn to_string_not_null(env: &mut JNIEnv, config: &JObject, name: &'static str) -> Result<String, Error> {
let value = env.get_field(config, name, "Ljava/lang/String;")?.l()?;
@@ -49,13 +50,13 @@ fn to_string(env: &mut JNIEnv, config: &JObject, name: &str) -> Result<Option<St
}
}
fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<SwitchUtilSync, Error> {
fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
let token = to_string_not_null(env, &config, "token")?;
let name = to_string_not_null(env, &config, "name")?;
let device_id = to_string_not_null(env, &config, "deviceId")?;
let password = to_string(env, &config, "password")?;
let server_address_str = to_string_not_null(env, &config, "server")?;
let nat_test_server = to_string_not_null(env, &config, "natTestServer")?;
// let nat_test_server = to_string_not_null(env, &config, "natTestServer")?;
let server_address = match server_address_str.to_socket_addrs() {
Ok(mut rs) => {
if let Some(addr) = rs.next() {
@@ -72,19 +73,21 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<SwitchUtilSync, Error>
return Err(Error::JavaException);
}
};
let nat_test_server = nat_test_server.split(",").flat_map(|a| a.trim().to_socket_addrs()).flatten()
.collect::<Vec<_>>();
let mut stun_server = Vec::new();
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 config = Config::new(false,
token, device_id, name,
server_address, server_address_str,
nat_test_server, vec![],
vec![], password, false, None);
match SwitchUtilSync::new(config) {
Ok(switch_util) => {
Ok(switch_util)
stun_server, vec![],
vec![], password, false, None, false, None, false,false,1,CipherModel::AesGcm);
match VntUtilSync::new(config) {
Ok(vnt_util) => {
Ok(vnt_util)
}
Err(e) => {
env.throw_new("Ljava/lang/RuntimeException", format!("switch start error {}", e))
env.throw_new("Ljava/lang/RuntimeException", format!("vnt start error {}", e))
.expect("throw");
return Err(Error::JavaException);
}
@@ -92,59 +95,82 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<SwitchUtilSync, Error>
}
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_new0(
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_new0(
mut env: JNIEnv,
_class: JClass,
config: JObject,
) -> jlong {
match new_sync(&mut env, config) {
Ok(switch_util) => {
let ptr = Box::into_raw(Box::new(switch_util));
Ok(vnt_util) => {
let ptr = Box::into_raw(Box::new(vnt_util));
return ptr as jlong;
}
Err(_) => {}
}
return 0;
}
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_connect0(
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_connect0(
mut env: JNIEnv,
_class: JClass,
raw_switch_util: jlong,
raw_vnt_util: jlong,
) {
let raw_vnt_util = raw_vnt_util as *mut VntUtilSync;
match (&mut *raw_vnt_util).connect() {
Ok(_) => {}
Err(e) => {
env.throw_new("java/lang/RuntimeException", format!("vnt connect error {}", e))
.expect("throw");
}
}
}
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_register0(
mut env: JNIEnv,
_class: JClass,
raw_vnt_util: jlong,
) -> jobject {
let raw_switch_util = raw_switch_util as *mut SwitchUtilSync;
match (&mut *raw_switch_util).connect() {
let raw_vnt_util = raw_vnt_util as *mut VntUtilSync;
match (&mut *raw_vnt_util).register() {
Ok(response) => {
match reg_response(&mut env, response) {
Ok(res) => {
return res;
}
Err(e) => {
env.throw(format!("switch connect error {}", e)).expect("throw");
env.throw(format!("vnt register error {}", e)).expect("throw");
}
}
}
Err(e) => {
match e {
ReqEnum::TokenError => {
env.throw_new("top/wherewego/switchjni/exception/TokenErrorException", "TokenError")
env.throw_new("top/wherewego/vnt/jni/exception/TokenErrorException", "TokenError")
.expect("throw");
}
ReqEnum::AddressExhausted => {
env.throw_new("top/wherewego/switchjni/exception/AddressExhaustedException", "AddressExhausted")
env.throw_new("top/wherewego/vnt/jni/exception/AddressExhaustedException", "AddressExhausted")
.expect("throw");
}
ReqEnum::Timeout => {
env.throw_new("top/wherewego/switchjni/exception/TimeoutException", "Timeout")
env.throw_new("top/wherewego/vnt/jni/exception/TimeoutException", "Timeout")
.expect("throw");
}
ReqEnum::ServerError(str) => {
env.throw_new("java/lang/RuntimeException", format!("switch connect error {}", str))
env.throw_new("java/lang/RuntimeException", format!("vnt register error {}", str))
.expect("throw");
}
ReqEnum::Other(str) => {
env.throw_new("java/lang/RuntimeException", format!("switch connect error {}", str))
env.throw_new("java/lang/RuntimeException", format!("vnt register error {}", str))
.expect("throw");
}
ReqEnum::IpAlreadyExists => {
env.throw_new("top/wherewego/vnt/jni/exception/IpAlreadyExistsException", "IpAlreadyExists")
.expect("throw");
}
ReqEnum::InvalidIp => {
env.throw_new("top/wherewego/vnt/jni/exception/InvalidIpException", "InvalidIp")
.expect("throw");
}
}
@@ -155,27 +181,26 @@ pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_connect0(
#[cfg(target_os = "android")]
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_createIface0(
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_createIface0(
_env: JNIEnv,
_class: JClass,
raw_switch_util: jlong,
raw_vnt_util: jlong,
fd: jint,
) {
let raw_switch_util = raw_switch_util as *mut SwitchUtilSync;
let raw_vnt_util = raw_vnt_util as *mut VntUtilSync;
(&mut *raw_switch_util).create_iface(fd as i32);
(&mut *raw_vnt_util).create_iface(fd as i32);
}
#[cfg(not(target_os = "android"))]
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_createIface0(
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_createIface0(
mut env: JNIEnv,
_class: JClass,
raw_switch_util: jlong,
raw_vnt_util: jlong,
) -> jobject {
let raw_switch_util = raw_switch_util as *mut SwitchUtilSync;
#[cfg(not(target_os = "android"))]
let rs = (&mut *raw_switch_util).create_iface();
let raw_vnt_util = raw_vnt_util as *mut VntUtilSync;
let rs = (&mut *raw_vnt_util).create_iface();
match rs {
Ok(driver_info) => {
match driver_info_e(&mut env, driver_info) {
@@ -183,12 +208,12 @@ pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_createIface0(
return res;
}
Err(e) => {
env.throw(format!("switch create iface error {}", e)).expect("throw");
env.throw(format!("vnt create iface error {}", e)).expect("throw");
}
}
}
Err(e) => {
env.throw_new("java/lang/RuntimeException", format!("switch create iface error {}", e))
env.throw_new("java/lang/RuntimeException", format!("vnt create iface error {}", e))
.expect("throw");
}
}
@@ -196,18 +221,18 @@ pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_createIface0(
}
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_build0(
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_build0(
mut env: JNIEnv,
_class: JClass,
raw_switch_util: jlong,
raw_vnt_util: jlong,
) -> jlong {
let raw_switch_util = Box::from_raw(raw_switch_util as *mut SwitchUtilSync);
match raw_switch_util.build() {
let raw_vnt_util = Box::from_raw(raw_vnt_util as *mut VntUtilSync);
match raw_vnt_util.build() {
Ok(rs) => {
return Box::into_raw(Box::new(rs)) as jlong;
}
Err(e) => {
env.throw_new("java/lang/RuntimeException", format!("switch start error:{:?}", e))
env.throw_new("java/lang/RuntimeException", format!("vnt start error:{:?}", e))
.expect("throw");
}
}
@@ -219,7 +244,7 @@ fn reg_response(env: &mut JNIEnv, response: RegResponse) -> Result<jobject, Erro
let virtual_gateway = u32::from(response.virtual_gateway);
let virtual_netmask = u32::from(response.virtual_netmask);
let response = env.new_object(
"top/wherewego/switchjni/RegResponse",
"top/wherewego/vnt/jni/RegResponse",
"(III)V",
&[JValue::Int(virtual_ip as jint),
JValue::Int(virtual_gateway as jint),
@@ -235,7 +260,7 @@ fn driver_info_e(env: &mut JNIEnv, driver_info: DriverInfo) -> Result<jobject, E
let version = driver_info.version;
let mac = driver_info.mac.unwrap_or(String::new());
let response = env.new_object(
"top/wherewego/switchjni/DriverInfo",
"top/wherewego/vnt/jni/DriverInfo",
"(ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
&[JValue::Bool(is_tun as jboolean),
JValue::Object(&env.new_string(name)?.into()),
+18 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "switch"
version = "1.1.0"
name = "vnt"
version = "1.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -11,16 +11,24 @@ bytes = "1.3.0"
log = "0.4.17"
libc = "0.2.137"
crossbeam-utils = "0.8"
crossbeam-skiplist = "0.1"
dashmap = "5.5.1"
parking_lot = "0.12.1"
byte-pool = "0.2.4"
lazy_static = "1.4.0"
rand = "0.8.5"
sha2 = { version = "0.10.6", features = ["oid"] }
aes-gcm = "0.10.2"
thiserror = "1.0.37"
protobuf = "3.2.0"
socket2 ={ version = "0.5.2", features = ["all"] }
tokio = { version = "1.28.1", features = ["full"] }
aes-gcm = {version="0.10.2", optional = true}
ring = {version="0.16.20", optional = true}
cbc = "0.1.2"
aes = "0.8.3"
stun-format = {version="1.0.1",features=["fmt","rfc3489"]}
rsa = {version="0.7.2", features = [] }
spki = {version="0.6.0",features=["fingerprint","alloc"]}
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
tun = { path = "./rust-tun" }
@@ -33,3 +41,8 @@ libloading = "0.7.4"
protobuf-codegen = "3.2.0"
protoc-bin-vendored = "3.0.0"
[features]
default=["aes-gcm"]
ring-cipher=["ring"]
View File
View File
@@ -103,9 +103,9 @@ pub fn ipv4_cal_checksum(
src_ip: &Ipv4Addr,
dest_ip: &Ipv4Addr,
protocol: u8,
length: u16,
) -> u16 {
use std::io::Cursor;
let length = buffer.len();
let mut sum = 0;
let src_ip = src_ip.octets();
sum += u32c(src_ip[0], src_ip[1]);
@@ -134,7 +134,6 @@ impl<B: AsRef<[u8]>> TcpPacket<B> {
&self.source_ip,
&self.destination_ip,
6,
self.buffer.as_ref().len() as u16,
)
}
pub fn urgent_pointer(&self) -> u16 {
@@ -102,7 +102,6 @@ impl<B: AsRef<[u8]>> UdpPacket<B> {
&self.source_ip,
&self.destination_ip,
17,
self.length(),
)
}
}
@@ -1,10 +1,27 @@
syntax = "proto3";
message HandshakeRequest{
string version = 1;
bool secret = 2;
}
message HandshakeResponse{
string version = 1;
bool secret = 2;
bytes public_key = 3;
string key_finger = 4;
}
message SecretHandshakeRequest{
string token = 1;
bytes key = 2;
}
message RegistrationRequest{
string token = 1;
string device_id = 2;
string name = 3;
bool is_fast = 4;
string version = 5;
fixed32 virtual_ip = 6;
bool allow_ip_change = 7;
bool client_secret = 8;
}
message RegistrationResponse{
@@ -15,11 +32,13 @@ message RegistrationResponse{
repeated DeviceInfo device_info_list = 5;
fixed32 public_ip = 6;
uint32 public_port = 7;
bytes public_ipv6 = 8;
}
message DeviceInfo{
string name = 1;
fixed32 virtual_ip = 2;
uint32 device_status = 3;
bool client_secret = 4;
}
message DeviceList{
@@ -35,6 +54,7 @@ message PunchInfo{
bool reply = 6;
fixed32 local_ip = 7;
uint32 local_port = 8;
repeated bytes public_ipv6_list = 9;
}
enum PunchNatType{
Symmetric = 0;
+626
View File
@@ -0,0 +1,626 @@
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
use std::sync::Arc;
use std::time::{Duration, Instant};
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpStream, UdpSocket};
use tokio::net::tcp::OwnedReadHalf;
use tokio::sync::watch::{channel, Receiver, Sender};
use crate::channel::{Route, RouteKey, Status};
use crate::channel::punch::NatType;
use crate::core::status::VntWorker;
use crate::handle::CurrentDeviceInfo;
use crate::handle::recv_handler::ChannelDataHandler;
use byte_pool::{Block, BytePool};
lazy_static::lazy_static! {
static ref POOL:BytePool = BytePool::new();
}
pub struct ContextInner {
//udp用于打洞、服务端通信(可选)
pub(crate) main_channel: Arc<UdpSocket>,
//在udp的基础上,可以选择使用tcp和服务端通信
pub(crate) main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>,
pub(crate) route_table: DashMap<Ipv4Addr, Vec<Route>>,
pub(crate) route_table_time: DashMap<(RouteKey, Ipv4Addr), AtomicCell<Instant>>,
pub(crate) status_receiver: Receiver<Status>,
pub(crate) status_sender: Sender<Status>,
pub(crate) udp_map: DashMap<usize, Arc<UdpSocket>>,
pub(crate) channel_num: usize,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
}
#[derive(Clone)]
pub struct Context {
pub(crate) inner: Arc<ContextInner>,
}
impl Context {
pub fn new(main_channel: Arc<UdpSocket>, main_tcp_channel: Option<tokio::sync::mpsc::Sender<Vec<u8>>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>, _channel_num: usize) -> Self {
//当前版本只支持一个通道
let channel_num = 1;
let (status_sender, status_receiver) = channel(Status::Cone);
let inner = Arc::new(ContextInner {
main_channel,
main_tcp_channel,
route_table: DashMap::with_capacity(16),
route_table_time: DashMap::with_capacity(16),
status_receiver,
status_sender,
udp_map: DashMap::new(),
channel_num,
current_device,
});
Self {
inner
}
}
}
impl Context {
pub fn is_close(&self) -> bool {
*self.inner.status_receiver.borrow() == Status::Close
}
pub fn is_cone(&self) -> bool {
*self.inner.status_receiver.borrow() == Status::Cone
}
pub fn close(&self) {
let _ = self.inner.status_sender.send(Status::Close);
}
pub fn is_main_tcp(&self) -> bool {
self.inner.main_tcp_channel.is_some()
}
pub fn switch(&self, nat_type: NatType) {
match nat_type {
NatType::Symmetric => {
self.switch_to_symmetric();
}
NatType::Cone => {
self.switch_to_cone();
}
}
}
pub fn switch_to_cone(&self) {
let _ = self.inner.status_sender.send(Status::Cone);
}
pub fn switch_to_symmetric(&self) {
let _ = self.inner.status_sender.send(Status::Symmetric);
}
pub fn main_local_port(&self) -> io::Result<u16> {
self.inner.main_channel.local_addr().map(|k| k.port())
}
pub async fn send_main_udp(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
self.inner.main_channel.send_to(buf, addr).await
}
pub async fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
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_main err"))
}
} else {
self.inner.main_channel.send_to(buf, addr).await
}
}
pub fn try_send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
if let Some(sender) = &self.inner.main_tcp_channel {
if sender.try_send(buf.to_vec()).is_ok() {
Ok(buf.len())
} else {
Err(io::Error::new(io::ErrorKind::Other, "try_send_main err"))
}
} else {
self.inner.main_channel.try_send_to(buf, addr)
}
}
pub(crate) async fn send_all(&self, buf: &[u8], addr: SocketAddr) -> io::Result<()> {
for udp_ref in self.inner.udp_map.iter() {
let udp = udp_ref.clone();
drop(udp_ref);
udp.send_to(buf, addr).await?;
}
Ok(())
}
pub async fn send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> {
if let Some(v) = self.inner.route_table.get(id) {
if v.value().is_empty() {
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
}
let route = v.value()[0];
drop(v);
if !route.is_p2p() {
if let Some(time) = self.inner.route_table_time.get(&(route.route_key(), *id)) {
//借道传输时,长时间不通信的通道不使用
if time.value().load().elapsed() > Duration::from_secs(6) {
return Err(io::Error::new(io::ErrorKind::NotFound, "route time out"));
}
}
}
if let Some(udp_ref) = self.inner.udp_map.get(&route.index) {
let udp = udp_ref.value().clone();
drop(udp_ref);
return udp.send_to(buf, route.addr).await;
}
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub fn try_send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> {
if let Some(v) = self.inner.route_table.get(id) {
if v.value().is_empty() {
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
}
let route = v.value()[0];
drop(v);
if let Some(udp) = self.inner.udp_map.get(&route.index) {
return udp.value().try_send_to(buf, route.addr);
}
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub async fn send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
if route_key.index == 0 {
if let Some(sender) = &self.inner.main_tcp_channel {
let mut vec = vec![0; 4 + buf.len()];
vec[4..].copy_from_slice(buf);
return if sender.send(vec).await.is_ok() {
Ok(buf.len())
} else {
Err(io::Error::new(io::ErrorKind::Other, "send_by_key err"))
};
}
}
if let Some(udp_ref) = self.inner.udp_map.get(&route_key.index) {
let udp = udp_ref.value().clone();
drop(udp_ref);
return udp.send_to(buf, route_key.addr).await;
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub fn try_send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
if route_key.index == 0 {
if let Some(sender) = &self.inner.main_tcp_channel {
let mut vec = vec![0; 4 + buf.len()];
vec[4..].copy_from_slice(buf);
return if sender.try_send(vec).is_ok() {
Ok(buf.len())
} else {
Err(io::Error::new(io::ErrorKind::Other, "try_send_by_key err"))
};
}
}
if let Some(udp) = self.inner.udp_map.get(&route_key.index) {
return udp.value().try_send_to(buf, route_key.addr);
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub fn add_route_if_absent(&self, id: Ipv4Addr, route: Route) {
self.add_route_(id, route, true)
}
pub fn add_route(&self, id: Ipv4Addr, route: Route) {
self.add_route_(id, route, false)
}
fn add_route_(&self, id: Ipv4Addr, route: Route, only_if_absent: bool) {
let key = route.route_key();
let mut list = self.inner.route_table.entry(id).or_insert_with(|| Vec::with_capacity(4));
let mut exist = false;
for x in list.iter_mut() {
if x.metric < route.metric {
//不能比当前的路径更长
return;
}
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);
}
}
self.inner.route_table_time.insert((key, id), AtomicCell::new(Instant::now()));
}
pub fn route(&self, id: &Ipv4Addr) -> Option<Vec<Route>> {
if let Some(v) = self.inner.route_table.get(id) {
Some(v.value().clone())
} else {
None
}
}
pub fn route_one(&self, id: &Ipv4Addr) -> Option<Route> {
if let Some(v) = self.inner.route_table.get(id) {
v.value().first().map(|v| *v)
} else {
None
}
}
pub fn route_to_id(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
for x in self.inner.route_table.iter() {
for route in x.value() {
if &route.route_key() == route_key && route.is_p2p() {
return Some(*x.key());
}
}
}
None
}
pub fn need_punch(&self, id: &Ipv4Addr) -> bool {
if let Some(v) = self.inner.route_table.get(id) {
if v.value().iter().filter(|k| k.is_p2p()).count() >= self.inner.channel_num {
return false;
}
}
true
}
pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec<Route>)> {
self.inner.route_table.iter().map(|k| (k.key().clone(), k.value().clone())).collect()
}
pub fn route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
let mut v = Vec::with_capacity(8);
for x in self.inner.route_table.iter() {
if let Some(route) = x.value().first() {
v.push((*x.key(), *route));
}
}
v
}
pub fn direct_route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
let mut v = Vec::with_capacity(8);
for x in self.inner.route_table.iter() {
if let Some(route) = x.value().first() {
if route.metric == 1 {
v.push((*x.key(), *route));
}
}
}
v
}
pub fn remove_route_all(&self, id: &Ipv4Addr) {
if let Some((_, routes)) = self.inner.route_table.remove(id) {
for x in routes {
self.inner.route_table_time.remove(&(x.route_key(), *id));
}
}
}
pub fn remove_route(&self, id: &Ipv4Addr, route_key: RouteKey) {
if let Some(v) = self.inner.route_table.get(id) {
let mut routes = v.value().clone();
drop(v);
routes.retain(|x| x.route_key() != route_key);
self.inner.route_table.insert(*id, routes);
}
self.inner.route_table_time.remove(&(route_key, *id));
}
pub fn update_read_time(&self, id: &Ipv4Addr, route_key: &RouteKey) {
if let Some(time) = self.inner.route_table_time.get(&(*route_key, *id)) {
time.value().store(Instant::now());
}
}
}
pub struct Channel {
context: Context,
handler: ChannelDataHandler,
}
impl Channel {
pub fn new(context: Context,
handler: ChannelDataHandler, ) -> Self {
Self {
context,
handler,
}
}
}
#[derive(Clone)]
struct BufSenderGroup(usize, Vec<tokio::sync::mpsc::Sender<(Block<'static>, usize, usize, RouteKey)>>);
struct BufReceiverGroup(Vec<tokio::sync::mpsc::Receiver<(Block<'static>, usize, usize, RouteKey)>>);
impl BufSenderGroup {
pub async fn send(&mut self, val: (Block<'static>, usize, usize, RouteKey)) -> bool {
let index = self.0 % self.1.len();
self.0 = self.0.wrapping_add(1);
self.1[index].send(val).await.is_ok()
}
}
fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) {
let mut buf_sender_group = Vec::with_capacity(size);
let mut buf_receiver_group = Vec::with_capacity(size);
for _ in 0..size {
let (buf_sender, buf_receiver) = tokio::sync::mpsc::channel::<(Block<'static, Vec<u8>>, usize, usize, RouteKey)>(10);
buf_sender_group.push(buf_sender);
buf_receiver_group.push(buf_receiver);
}
(BufSenderGroup(0, buf_sender_group), BufReceiverGroup(buf_receiver_group))
}
impl Channel {
async fn tcp_handle(mut tcp_r: OwnedReadHalf, mut buf_sender: BufSenderGroup, head_reserve: usize) -> io::Result<()> {
let mut head = [0; 4];
let addr = tcp_r.peer_addr()?;
let key = RouteKey::new(0, addr);
loop {
let mut buf = POOL.alloc(4096);
tcp_r.read_exact(&mut head).await?;
let len = (((head[2] as u16) << 8) | head[3] as u16) as usize;
if len < 12 || len > buf.len() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"length overflow",
));
}
tcp_r.read_exact(&mut buf[head_reserve..head_reserve + len]).await?;
if !buf_sender.send((buf, head_reserve, head_reserve + len, key)).await {
return Err(io::Error::new(io::ErrorKind::Other, "buf_sender发送数据失败"));
}
}
}
async fn start_tcp(mut worker: VntWorker, tcp_stream: TcpStream, mut receiver: tokio::sync::mpsc::Receiver<Vec<u8>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
buf_sender: BufSenderGroup, head_reserve: usize) {
let (tcp_r, mut tcp_w) = tcp_stream.into_split();
{
let buf_sender = buf_sender.clone();
tokio::spawn(async move {
if let Err(e) = Self::tcp_handle(tcp_r, buf_sender, head_reserve).await {
log::info!("tcp链接断开:{:?}",e);
}
});
}
let mut head = [0; 4];
loop {
tokio::select! {
_=worker.stop_wait()=>{
break;
}
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 buf_sender = buf_sender.clone();
tokio::spawn(async move {
if let Err(e) = Self::tcp_handle(r, buf_sender, head_reserve).await {
log::info!("tcp 链接断开:{:?}",e);
}
});
}
Err(e) => {
log::info!("重连失败:{:?}",e);
}
};
}
}else{
break;
}
}
}
}
worker.stop_all();
}
pub async fn start(self,
mut worker: VntWorker,
tcp: Option<(TcpStream, tokio::sync::mpsc::Receiver<Vec<u8>>)>,
head_reserve: usize,//头部预留字节
symmetric_channel_num: usize,//对称网络,则再加一组监听,提升打洞成功率
relay: bool,
parallel: usize,
) {
let handler = self.handler.clone();
let context = self.context;
let main_channel = context.inner.main_channel.clone();
let buf_sender = if parallel > 1 || tcp.is_some() {
let (buf_sender, buf_receiver) = buf_channel_group(parallel);
for mut buf_receiver in buf_receiver.0 {
let context = context.clone();
let handler = handler.clone();
tokio::spawn(async move {
while let Some((mut buf, start, end, route_key)) = buf_receiver.recv().await {
handler.handle(&mut buf, start, end, route_key, &context).await;
}
});
}
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(), buf_sender.clone().unwrap(), head_reserve));
}
tokio::spawn(Self::start_(worker.worker("main_channel_1"), context.clone(), main_channel.clone(), handler.clone(), buf_sender.clone(), head_reserve, true));
if relay {
worker.stop_wait().await;
return;
}
let mut cur_status = Status::Cone;
let mut status_receiver = context.inner.status_receiver.clone();
loop {
tokio::select! {
_=worker.stop_wait()=>{
break;
}
rs=status_receiver.changed()=>{
match rs {
Ok(_) => {
let s = status_receiver.borrow().clone();
match s {
Status::Cone => {
cur_status = Status::Cone;
}
Status::Symmetric => {
if cur_status == Status::Symmetric {
continue;
}
cur_status = Status::Symmetric;
for _ in 0..symmetric_channel_num {
match UdpSocket::bind("0.0.0.0:0").await {
Ok(udp) => {
let udp = Arc::new(udp);
let context = context.clone();
tokio::spawn(Self::start_(worker.worker("symmetric_channel"),context, udp,handler.clone(),buf_sender.clone(), head_reserve, false));
}
Err(e) => {
log::error!("{}",e);
}
}
}
}
Status::Close => {
break;
}
}
}
Err(_) => {
break;
}
}
}
}
}
worker.stop_all();
}
async fn start_(mut worker: VntWorker, context: Context,
udp: Arc<UdpSocket>,
handler: ChannelDataHandler,
buf_sender: Option<BufSenderGroup>,
head_reserve: usize,
is_core: bool) {
let mut status_receiver = context.inner.status_receiver.clone();
#[cfg(target_os = "windows")]
use std::os::windows::io::AsRawSocket;
#[cfg(target_os = "windows")]
let id = 1 + udp.as_raw_socket() as usize;
#[cfg(any(unix))]
use std::os::fd::AsRawFd;
#[cfg(any(unix))]
let id = 1 + udp.as_raw_fd() as usize;
context.inner.udp_map.insert(id, udp.clone());
match buf_sender {
None => {
let mut buf = [0; 4096];
loop {
tokio::select! {
rs=udp.recv_from(&mut buf[head_reserve..])=>{
match rs {
Ok((len, addr)) => {
handler.handle(&mut buf, head_reserve, head_reserve + len, RouteKey::new(id, addr), &context).await;
}
Err(e) => {
log::error!("{:?}",e)
}
}
}
changed=status_receiver.changed()=>{
match changed {
Ok(_) => {
match *status_receiver.borrow() {
Status::Cone => {
if !is_core{
break;
}
}
Status::Close=>{
break;
}
Status::Symmetric => {}
}
}
Err(_) => {
break;
}
}
}
_=worker.stop_wait()=>{
break;
}
}
}
}
Some(mut buf_sender) => {
loop {
let mut buf = POOL.alloc(4096);
tokio::select! {
rs=udp.recv_from(&mut buf[head_reserve..])=>{
match rs {
Ok((len, addr)) => {
if !buf_sender.send((buf,head_reserve,head_reserve+len,RouteKey::new(id, addr))).await{
log::error!("udp buf_sender发送数据失败");
break;
}
}
Err(e) => {
log::error!("{:?}",e)
}
}
}
changed=status_receiver.changed()=>{
match changed {
Ok(_) => {
match *status_receiver.borrow() {
Status::Cone => {
if !is_core{
break;
}
}
Status::Close=>{
break;
}
Status::Symmetric => {}
}
}
Err(_) => {
break;
}
}
}
_=worker.stop_wait()=>{
break;
}
}
}
}
}
context.inner.udp_map.remove(&id);
if is_core {
worker.stop_all();
}
}
}
@@ -25,7 +25,7 @@ impl Idle {
/// 获取空闲路由
pub async fn next_idle(&self) -> io::Result<(Ipv4Addr, RouteKey)> {
loop {
let mut max = Duration::from_secs(10);
let mut max = Duration::from_secs(0);
for entry in self.context.inner.route_table_time.iter() {
let last_read = entry.value().load().elapsed();
if last_read >= self.read_idle {
@@ -36,8 +36,10 @@ impl Idle {
}
}
}
let sleep_time = self.read_idle - max;
tokio::time::sleep(sleep_time).await;
if self.read_idle > max {
let sleep_time = self.read_idle - max;
tokio::time::sleep(sleep_time).await;
}
if self.context.is_close() {
return Err(Error::new(ErrorKind::Other, "closed"));
}
@@ -24,12 +24,15 @@ pub enum NatType {
}
impl NatInfo {
pub fn new(public_ips: Vec<Ipv4Addr>,
pub fn new(mut public_ips: Vec<Ipv4Addr>,
public_port: u16,
public_port_range: u16,
local_ip: Ipv4Addr,
local_port: u16,
nat_type: NatType, ) -> Self {
public_ips.retain(|ip| {
!ip.is_loopback() && !ip.is_private()
});
Self {
public_ips,
public_port,
@@ -68,7 +71,7 @@ impl Punch {
return Ok(());
}
if !nat_info.local_ip.is_unspecified() || nat_info.local_port != 0 {
let _ = self.context.send_main(buf, SocketAddr::V4(SocketAddrV4::new(nat_info.local_ip, nat_info.local_port))).await;
let _ = self.context.send_main_udp(buf, SocketAddr::V4(SocketAddrV4::new(nat_info.local_ip, nat_info.local_port))).await;
}
match nat_info.nat_type {
NatType::Symmetric => {
@@ -122,7 +125,7 @@ impl Punch {
for ip in nat_info.public_ips {
let addr = SocketAddr::V4(SocketAddrV4::new(ip, nat_info.public_port));
if is_cone {
self.context.send_main(buf, addr).await?;
self.context.send_main_udp(buf, addr).await?;
} else {
//只有一方是对称,则对称方要使用全部端口发送数据,符合上述计算的概率
self.context.send_all(buf, addr).await?;
@@ -143,7 +146,7 @@ impl Punch {
return Ok(());
}
let addr = SocketAddr::V4(SocketAddrV4::new(*pub_ip, *port));
self.context.send_main(buf, addr).await?;
self.context.send_main_udp(buf, addr).await?;
tokio::time::sleep(Duration::from_millis(2)).await;
}
}
+128
View File
@@ -0,0 +1,128 @@
use std::io;
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyIvInit};
use rand::RngCore;
use crate::cipher::Finger;
use crate::protocol::body::AesCbcSecretBody;
use crate::protocol::{HEAD_LEN, NetPacket};
type Aes128CbcEnc = cbc::Encryptor<aes::Aes128>;
type Aes128CbcDec = cbc::Decryptor<aes::Aes128>;
type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
#[derive(Clone)]
pub struct AesCbcCipher {
pub(crate) cipher: AesCbcEnum,
pub(crate) finger: Finger,
}
#[derive(Clone)]
pub enum AesCbcEnum {
AES128CBC([u8; 16]),
AES256CBC([u8; 32]),
}
impl AesCbcCipher {
pub fn key(&self) -> &[u8] {
match &self.cipher {
AesCbcEnum::AES128CBC(key) => { key }
AesCbcEnum::AES256CBC(key) => { key }
}
}
}
impl AesCbcCipher {
pub fn new_128(key: [u8; 16], finger: Finger) -> Self {
Self {
cipher: AesCbcEnum::AES128CBC(key),
finger,
}
}
pub fn new_256(key: [u8; 32], finger: Finger) -> Self {
Self {
cipher: AesCbcEnum::AES256CBC(key),
finger,
}
}
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> io::Result<()> {
if !net_packet.is_encrypt() {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if net_packet.payload().len() < 12 + 16 {
log::error!("数据异常,长度{}小于{}",net_packet.payload().len(),12+16);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let mut iv = [0; 16];
iv[0..4].copy_from_slice(&net_packet.source().octets());
iv[4..8].copy_from_slice(&net_packet.destination().octets());
iv[8] = net_packet.protocol().into();
iv[9] = net_packet.transport_protocol();
iv[10] = net_packet.is_gateway() as u8;
iv[11] = net_packet.source_ttl();
iv[12..16].copy_from_slice(&self.finger.hash[0..4]);
let mut secret_body = AesCbcSecretBody::new(net_packet.payload_mut())?;
let finger = self.finger.calculate_finger(&iv[..12], secret_body.en_body());
if &finger != secret_body.finger() {
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
}
let rs = match &self.cipher {
AesCbcEnum::AES128CBC(key) => { Aes128CbcDec::new(&(*key).into(), &iv.into()).decrypt_padded_mut::<Pkcs7>(secret_body.en_body_mut()) }
AesCbcEnum::AES256CBC(key) => { Aes256CbcDec::new(&(*key).into(), &iv.into()).decrypt_padded_mut::<Pkcs7>(secret_body.en_body_mut()) }
};
match rs {
Ok(buf) => {
let len = buf.len();
net_packet.set_encrypt_flag(false);
//减去末尾的随机数
net_packet.set_data_len(HEAD_LEN + len - 4)?;
Ok(())
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e)))
}
}
}
/// net_packet 必须预留足够长度
/// data_len是有效载荷的长度
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> io::Result<()> {
let mut iv = [0; 16];
iv[0..4].copy_from_slice(&net_packet.source().octets());
iv[4..8].copy_from_slice(&net_packet.destination().octets());
iv[8] = net_packet.protocol().into();
iv[9] = net_packet.transport_protocol();
iv[10] = net_packet.is_gateway() as u8;
iv[11] = net_packet.source_ttl();
iv[12..16].copy_from_slice(&self.finger.hash[0..4]);
//先扩充随机数
let data_len = net_packet.data_len();
net_packet.set_data_len(data_len + 16)?;
let mut secret_body = AesCbcSecretBody::new(net_packet.payload_mut())?;
secret_body.set_random(rand::thread_rng().next_u32());
let p_len = secret_body.en_body().len();
net_packet.set_data_len_max();
let rs = match &self.cipher {
AesCbcEnum::AES128CBC(key) => { Aes128CbcEnc::new(&(*key).into(), &iv.into()).encrypt_padded_mut::<Pkcs7>(net_packet.payload_mut(), p_len) }
AesCbcEnum::AES256CBC(key) => { Aes256CbcEnc::new(&(*key).into(), &iv.into()).encrypt_padded_mut::<Pkcs7>(net_packet.payload_mut(), p_len) }
};
return match rs {
Ok(buf) => {
let len = buf.len();
let finger = self.finger.calculate_finger(&iv[..12], buf);
//设置实际长度
net_packet.set_data_len(HEAD_LEN + len + finger.len())?;
let mut secret_body = AesCbcSecretBody::new(net_packet.payload_mut())?;
secret_body.set_finger(&finger)?;
net_packet.set_encrypt_flag(true);
Ok(())
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e)))
}
};
}
}
+112
View File
@@ -0,0 +1,112 @@
use std::io;
use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, KeyInit, Nonce, Tag};
use aes_gcm::aead::consts::{U12, U16};
use aes_gcm::aead::generic_array::GenericArray;
use rand::RngCore;
use crate::cipher::finger::Finger;
use crate::protocol::{body::ENCRYPTION_RESERVED, body::SecretBody, NetPacket};
#[derive(Clone)]
pub struct AesGcmCipher {
pub(crate) cipher: AesGcmEnum,
pub(crate) finger: Finger,
}
#[derive(Clone)]
pub enum AesGcmEnum {
AES128GCM(Aes128Gcm),
AES256GCM(Aes256Gcm),
}
impl AesGcmCipher {
pub fn new_128(key: [u8; 16], finger: Finger) -> Self {
let key: &Key<Aes128Gcm> = &key.into();
Self {
cipher: AesGcmEnum::AES128GCM(Aes128Gcm::new(key)),
finger,
}
}
pub fn new_256(key: [u8; 32], finger: Finger) -> Self {
let key: &Key<Aes256Gcm> = &key.into();
Self {
cipher: AesGcmEnum::AES256GCM(Aes256Gcm::new(key)),
finger,
}
}
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> io::Result<()> {
if !net_packet.is_encrypt() {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if net_packet.payload().len() < ENCRYPTION_RESERVED {
log::error!("数据异常,长度小于{}",ENCRYPTION_RESERVED);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
let mut secret_body = SecretBody::new(net_packet.payload_mut())?;
let tag = secret_body.tag();
let finger = self.finger.calculate_finger(&nonce_raw, secret_body.en_body());
if &finger != secret_body.finger() {
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
}
let tag: GenericArray<u8, U16> = Tag::clone_from_slice(tag);
let rs = match &self.cipher {
AesGcmEnum::AES128GCM(aes_gcm) => { aes_gcm.decrypt_in_place_detached(nonce, &[], secret_body.body_mut(), &tag) }
AesGcmEnum::AES256GCM(aes_gcm) => { aes_gcm.decrypt_in_place_detached(nonce, &[], secret_body.body_mut(), &tag) }
};
if let Err(e) = rs {
return Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e)));
}
net_packet.set_encrypt_flag(false);
net_packet.set_data_len(net_packet.data_len() - ENCRYPTION_RESERVED)?;
return Ok(());
}
/// net_packet 必须预留足够长度
/// data_len是有效载荷的长度
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> io::Result<()> {
if net_packet.reserve() < ENCRYPTION_RESERVED {
return Err(io::Error::new(io::ErrorKind::Other, "too short"));
}
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
let data_len = net_packet.data_len() + ENCRYPTION_RESERVED;
net_packet.set_data_len(data_len)?;
let mut secret_body = SecretBody::new(net_packet.payload_mut())?;
secret_body.set_random(rand::thread_rng().next_u32());
let rs = match &self.cipher {
AesGcmEnum::AES128GCM(aes_gcm) => { aes_gcm.encrypt_in_place_detached(nonce, &[], secret_body.body_mut()) }
AesGcmEnum::AES256GCM(aes_gcm) => { aes_gcm.encrypt_in_place_detached(nonce, &[], secret_body.body_mut()) }
};
return match rs {
Ok(tag) => {
secret_body.set_tag(tag.as_slice())?;
let finger = self.finger.calculate_finger(&nonce_raw, secret_body.en_body());
secret_body.set_finger(&finger)?;
net_packet.set_encrypt_flag(true);
Ok(())
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e)))
}
};
}
}
+145
View File
@@ -0,0 +1,145 @@
use std::io;
use std::str::FromStr;
use crate::cipher::{aes_cbc, Finger};
use crate::protocol::NetPacket;
use sha2::Digest;
#[cfg(feature = "ring-cipher")]
use crate::cipher::ring_aes_gcm_cipher::AesGcmCipher;
#[cfg(not(feature = "ring-cipher"))]
use crate::cipher::aes_gcm_cipher::AesGcmCipher;
use aes_cbc::AesCbcCipher;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum CipherModel {
AesGcm,
AesCbc,
}
impl FromStr for CipherModel {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"aes_gcm" => {
Ok(CipherModel::AesGcm)
}
"aes_cbc" => { Ok(CipherModel::AesCbc) }
_ => {
Err(format!("not match '{}'", s))
}
}
}
}
#[derive(Clone)]
pub enum Cipher {
AesGcm((AesGcmCipher, Vec<u8>)),
AesCbc(AesCbcCipher),
None,
}
impl Cipher {
pub fn new_password(model: CipherModel, password: Option<String>, token: String) -> Self {
let finger = Finger::new(&token);
if let Some(password) = password {
let mut hasher = sha2::Sha256::new();
hasher.update(password.as_bytes());
let key: [u8; 32] = hasher.finalize().into();
match model {
CipherModel::AesGcm => {
if password.len() < 8 {
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
Cipher::AesGcm((aes, key[..16].to_vec()))
} else {
let aes = AesGcmCipher::new_256(key, finger);
Cipher::AesGcm((aes, key.to_vec()))
}
}
CipherModel::AesCbc => {
if password.len() < 8 {
let aes = AesCbcCipher::new_128(key[..16].try_into().unwrap(), finger);
Cipher::AesCbc(aes)
} else {
let aes = AesCbcCipher::new_256(key, finger);
Cipher::AesCbc(aes)
}
}
}
} else {
Cipher::None
}
}
pub fn new_key(key: [u8; 32], token: String) -> io::Result<Self> {
let finger = Finger::new(&token);
match key.len() {
16 => {
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
Ok(Cipher::AesGcm((aes, key[..16].to_vec())))
}
32 => {
let aes = AesGcmCipher::new_256(key, finger);
Ok(Cipher::AesGcm((aes, key.to_vec())))
}
_ => {
Err(io::Error::new(io::ErrorKind::Other, "key error"))
}
}
}
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> io::Result<()> {
match self {
Cipher::AesGcm((aes_gcm, _)) => {
aes_gcm.decrypt_ipv4(net_packet)
}
Cipher::AesCbc(aes_cbc) => {
aes_cbc.decrypt_ipv4(net_packet).unwrap();
Ok(())
}
Cipher::None => {
if net_packet.is_encrypt() {
return Err(io::Error::new(io::ErrorKind::Other, "not key"));
}
Ok(())
}
}
}
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> io::Result<()> {
match self {
Cipher::AesGcm((aes_gcm, _)) => {
aes_gcm.encrypt_ipv4(net_packet)
}
Cipher::AesCbc(aes_cbc) => {
aes_cbc.encrypt_ipv4(net_packet).unwrap();
Ok(())
}
Cipher::None => {
Ok(())
}
}
}
pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> io::Result<()> {
match self {
Cipher::AesGcm((aes_gcm, _)) => {
aes_gcm.finger.check_finger(net_packet)
}
Cipher::AesCbc(aes_cbc) => {
aes_cbc.finger.check_finger(net_packet)
}
Cipher::None => {
Ok(())
}
}
}
pub fn key(&self) -> Option<&[u8]> {
match self {
Cipher::AesGcm((_, key)) => {
Some(key)
}
Cipher::AesCbc(aes_cbc) => {
Some(aes_cbc.key())
}
Cipher::None => {
None
}
}
}
}
+51
View File
@@ -0,0 +1,51 @@
use std::io;
use sha2::Digest;
use crate::protocol::NetPacket;
#[derive(Clone)]
pub struct Finger {
pub(crate) hash: [u8; 32],
}
impl Finger {
pub fn new(str: &str) -> Self {
let mut hasher = sha2::Sha256::new();
hasher.update(str.as_bytes());
let hash: [u8; 32] = hasher.finalize().into();
Finger { hash }
}
pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> io::Result<()> {
if !net_packet.is_encrypt() {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
let payload_len = net_packet.payload().len();
if payload_len < 12 {
log::error!("数据异常,长度小于{}",12);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let payload = net_packet.payload();
let finger = self.calculate_finger(&nonce_raw, &payload[..payload_len - 12]);
if &finger[..] != &payload[payload_len - 12..] {
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
}
Ok(())
}
pub fn calculate_finger(&self, nonce: &[u8], secret_body: &[u8]) -> [u8; 12] {
let mut hasher = sha2::Sha256::new();
hasher.update(nonce);
hasher.update(secret_body);
hasher.update(&self.hash);
let key: [u8; 32] = hasher.finalize().into();
return key[20..].try_into().unwrap();
}
}
+14
View File
@@ -0,0 +1,14 @@
#[cfg(feature = "ring-cipher")]
mod ring_aes_gcm_cipher;
#[cfg(not(feature = "ring-cipher"))]
mod aes_gcm_cipher;
mod rsa_cipher;
mod aes_cbc;
mod finger;
mod cipher;
pub use cipher::Cipher;
pub use finger::Finger;
pub use rsa_cipher::RsaCipher;
pub use cipher::CipherModel;
+132
View File
@@ -0,0 +1,132 @@
use std::io;
use rand::RngCore;
use ring::aead;
use ring::aead::{LessSafeKey, UnboundKey};
use crate::cipher::Finger;
use crate::protocol::NetPacket;
use crate::protocol::body::{ENCRYPTION_RESERVED, SecretBody};
#[derive(Clone)]
pub struct AesGcmCipher {
pub(crate) cipher: AesGcmEnum,
pub(crate) finger: Finger,
}
pub enum AesGcmEnum {
AesGCM128(LessSafeKey, [u8; 16]),
AesGCM256(LessSafeKey, [u8; 32]),
}
impl Clone for AesGcmEnum {
fn clone(&self) -> Self {
match &self {
AesGcmEnum::AesGCM128(_, key) => {
let c = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, key.as_slice()).unwrap());
AesGcmEnum::AesGCM128(c, *key)
}
AesGcmEnum::AesGCM256(_, key) => {
let c = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, key.as_slice()).unwrap());
AesGcmEnum::AesGCM256(c, *key)
}
}
}
}
impl AesGcmCipher {
pub fn new_128(key: [u8; 16], finger: Finger) -> Self {
let cipher = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, &key).unwrap());
Self {
cipher: AesGcmEnum::AesGCM128(cipher, key),
finger,
}
}
pub fn new_256(key: [u8; 32], finger: Finger) -> Self {
let cipher = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, &key).unwrap());
Self {
cipher: AesGcmEnum::AesGCM256(cipher, key),
finger,
}
}
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> io::Result<()> {
if !net_packet.is_encrypt() {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if net_packet.payload().len() < ENCRYPTION_RESERVED {
log::error!("数据异常,长度小于{}",ENCRYPTION_RESERVED);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
let mut secret_body = SecretBody::new(net_packet.payload_mut())?;
let tag = secret_body.tag();
let finger = self.finger.calculate_finger(&nonce_raw, secret_body.en_body());
if &finger != secret_body.finger() {
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
}
let rs = match &self.cipher {
AesGcmEnum::AesGCM128(cipher, _) => {
cipher.open_in_place(nonce, aead::Aad::empty(), secret_body.en_body_mut())
}
AesGcmEnum::AesGCM256(cipher, _) => {
cipher.open_in_place(nonce, aead::Aad::empty(), secret_body.en_body_mut())
}
};
if let Err(e) = rs {
return Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e)));
}
net_packet.set_encrypt_flag(false);
net_packet.set_data_len(net_packet.data_len() - ENCRYPTION_RESERVED)?;
return Ok(());
}
/// net_packet 必须预留足够长度
/// data_len是有效载荷的长度
/// 返回加密后载荷的长度
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> io::Result<()> {
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
let data_len = net_packet.data_len() + ENCRYPTION_RESERVED;
net_packet.set_data_len(data_len)?;
let mut secret_body = SecretBody::new(net_packet.payload_mut())?;
secret_body.set_random(rand::thread_rng().next_u32());
let rs = match &self.cipher {
AesGcmEnum::AesGCM128(cipher, _) => {
cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), secret_body.body_mut())
}
AesGcmEnum::AesGCM256(cipher, _) => {
cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), secret_body.body_mut())
}
};
return match rs {
Ok(tag) => {
let tag = tag.as_ref();
if tag.len() != 16 {
return Err(io::Error::new(io::ErrorKind::Other, format!("加密tag长度错误:{}", tag.len())));
}
secret_body.set_tag(tag)?;
let finger = self.finger.calculate_finger(&nonce_raw, secret_body.en_body());
secret_body.set_finger(&finger)?;
net_packet.set_encrypt_flag(true);
Ok(())
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e)))
}
};
}
}
+99
View File
@@ -0,0 +1,99 @@
use std::io;
use rand::Rng;
use rsa::pkcs8::der::Decode;
use rsa::{PublicKey, RsaPublicKey};
use spki::{DecodePublicKey, EncodePublicKey};
use crate::protocol::body::{ENCRYPTION_RESERVED, RsaSecretBody};
use crate::protocol::NetPacket;
use sha2::Digest;
#[derive(Clone)]
pub struct RsaCipher {
inner: Inner,
}
#[derive(Clone)]
struct Inner {
public_key: RsaPublicKey,
}
impl RsaCipher {
pub fn new(der: &[u8]) -> io::Result<Self> {
match RsaPublicKey::from_public_key_der(der) {
Ok(public_key) => {
let inner = Inner {
public_key,
};
Ok(Self {
inner
})
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("from_public_key_der failed {}", e)))
}
}
}
pub fn finger(&self) -> io::Result<String> {
match self.inner.public_key.to_public_key_der() {
Ok(der) => {
match rsa::pkcs8::SubjectPublicKeyInfo::from_der(der.as_bytes()) {
Ok(spki) => {
match spki.fingerprint_base64() {
Ok(finger) => {
Ok(finger)
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("fingerprint_base64 error {}", e)))
}
}
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("from_der error {}", e)))
}
}
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("to_public_key_der error {}", e)))
}
}
}
}
impl RsaCipher {
/// net_packet 必须预留足够长度
pub fn encrypt<B: AsRef<[u8]> + AsMut<[u8]>>(&self, net_packet: &mut NetPacket<B>) -> io::Result<NetPacket<Vec<u8>>> {
if net_packet.reserve() < ENCRYPTION_RESERVED {
return Err(io::Error::new(io::ErrorKind::Other, "too short"));
}
let data_len = net_packet.data_len() + ENCRYPTION_RESERVED;
net_packet.set_data_len(data_len)?;
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let mut secret_body = RsaSecretBody::new(net_packet.payload_mut())?;
let mut rng = rand::thread_rng();
rng.fill(secret_body.random_mut());
let mut hasher = sha2::Sha256::new();
hasher.update(secret_body.body());
hasher.update(nonce_raw);
let key: [u8; 32] = hasher.finalize().into();
secret_body.set_finger(&key[16..])?;
match self.inner.public_key.encrypt(&mut rng, rsa::PaddingScheme::PKCS1v15Encrypt, secret_body.buffer()) {
Ok(enc_data) => {
let mut net_packet_e = NetPacket::new(vec![0; 12 + enc_data.len()])?;
net_packet_e.buffer_mut()[..12].copy_from_slice(&net_packet.buffer()[..12]);
net_packet_e.set_payload(&enc_data)?;
Ok(net_packet_e)
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("encrypt failed {}", e)))
}
}
}
}
+157 -87
View File
@@ -3,12 +3,11 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::sync::Arc;
use std::time::Duration;
use aes_gcm::{Aes256Gcm, Key, KeyInit};
use crossbeam_skiplist::SkipMap;
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap;
use parking_lot::Mutex;
use sha2::Digest;
use tokio::net::UdpSocket;
use rand::Rng;
use tokio::net::{TcpStream, UdpSocket};
use tokio::sync::mpsc::channel;
use crate::channel::{Route, RouteKey};
@@ -16,10 +15,12 @@ use crate::channel::channel::{Channel, Context};
use crate::channel::idle::Idle;
use crate::channel::punch::{NatInfo, Punch};
use crate::channel::sender::ChannelSender;
use crate::core::status::SwitchStatusManger;
use crate::cipher::{Cipher, CipherModel, RsaCipher};
use crate::core::status::VntStatusManger;
use crate::error::Error;
use crate::external_route::ExternalRoute;
use crate::handle::{ConnectStatus, CurrentDeviceInfo, heartbeat_handler, PeerDeviceInfo, punch_handler, registration_handler};
use crate::external_route::{AllowExternalRoute, ExternalRoute};
use crate::handle::{ConnectStatus, CurrentDeviceInfo, handshake_handler, heartbeat_handler, PeerDeviceInfo, punch_handler, registration_handler};
use crate::handle::handshake_handler::HandshakeEnum;
use crate::handle::recv_handler::ChannelDataHandler;
use crate::handle::registration_handler::{RegResponse, ReqEnum};
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
@@ -35,11 +36,11 @@ pub mod sync;
#[derive(Clone)]
pub struct Switch {
name: String,
pub struct Vnt {
config: Config,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
context: Context,
switch_status_manager: SwitchStatusManger,
vnt_status_manager: VntStatusManger,
device_writer: DeviceWriter,
/// 0. 机器纪元,每一次上线或者下线都会增1,用于感知网络中机器变化
/// 服务端和客户端的不一致,则服务端会推送新的设备列表
@@ -47,30 +48,63 @@ pub struct Switch {
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
nat_test: NatTest,
connect_status: Arc<AtomicCell<ConnectStatus>>,
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>>,
}
pub struct SwitchUtil {
pub struct VntUtil {
config: Config,
main_channel: Arc<UdpSocket>,
main_channel: UdpSocket,
main_tcp_channel: Option<TcpStream>,
response: Option<RegResponse>,
iface: Option<(DeviceWriter, DeviceReader)>,
server_cipher: Cipher,
rsa_cipher: Option<RsaCipher>,
}
impl SwitchUtil {
pub async fn new(config: Config) -> io::Result<SwitchUtil> {
let main_channel = Arc::new(UdpSocket::bind("0.0.0.0:0").await?);
Ok(SwitchUtil {
impl VntUtil {
pub async fn new(config: Config) -> io::Result<VntUtil> {
let main_channel = UdpSocket::bind("0.0.0.0:0").await?;
let server_cipher = if config.server_encrypt {
let mut key = [0 as u8; 32];
rand::thread_rng().fill(&mut key);
Cipher::new_key(key, config.token.clone())?
} else {
Cipher::None
};
Ok(VntUtil {
config,
main_channel,
main_tcp_channel: None,
response: None,
iface: None,
server_cipher,
rsa_cipher: None,
})
}
pub async fn connect(&mut self) -> Result<RegResponse, ReqEnum> {
match registration_handler::registration(&self.main_channel, self.config.server_address,
///链接
pub async fn connect(&mut self) -> io::Result<()> {
if self.config.tcp {
let tcp = TcpStream::connect(self.config.server_address).await?;
let _ = self.main_tcp_channel.insert(tcp);
}
Ok(())
}
///握手 用于获取公钥
pub async fn handshake(&mut self) -> Result<Option<RsaCipher>, HandshakeEnum> {
let rsa_cipher = handshake_handler::handshake(&self.main_channel, self.main_tcp_channel.as_mut(), self.config.server_address, self.config.server_encrypt).await?;
self.rsa_cipher = rsa_cipher.clone();
Ok(rsa_cipher)
}
/// 加密握手 用于同步密钥
pub async fn secret_handshake(&mut self) -> Result<(), HandshakeEnum> {
handshake_handler::secret_handshake(&self.main_channel, self.main_tcp_channel.as_mut(), self.config.server_address, self.rsa_cipher.as_ref().unwrap(), &self.server_cipher, self.config.token.clone()).await
}
/// 注册
pub async fn register(&mut self) -> Result<RegResponse, ReqEnum> {
match registration_handler::registration(&self.main_channel, self.main_tcp_channel.as_mut(), &self.server_cipher, self.config.server_address,
self.config.token.clone(), self.config.device_id.clone(),
self.config.name.clone()).await {
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)
@@ -101,19 +135,30 @@ impl SwitchUtil {
let device_type = if self.config.tap {
#[cfg(windows)]
{
//删除switch的tun网卡避免ip冲突,因为非正常退出会保留网卡
//删除tun网卡避免ip冲突,因为非正常退出会保留网卡
tun_tap_device::delete_device(tun_tap_device::DeviceType::Tun);
}
tun_tap_device::DeviceType::Tap
} else {
#[cfg(windows)]
{
//删除switch的tap网卡避免ip冲突,非正常退出会保留网卡
//删除tap网卡避免ip冲突,非正常退出会保留网卡
tun_tap_device::delete_device(tun_tap_device::DeviceType::Tap);
}
tun_tap_device::DeviceType::Tun
};
let mtu = self.config.mtu.unwrap_or(1430);
let mtu = match self.config.mtu {
None => {
if self.config.password.is_none() {
1430
} else {
1410
}
}
Some(mtu) => {
mtu
}
};
let in_ips = self.config.in_ips.iter().map(|(dest, mask, _)| { (Ipv4Addr::from(*dest & *mask), Ipv4Addr::from(*mask)) }).collect::<Vec<(Ipv4Addr, Ipv4Addr)>>();
let (device_writer, device_reader, driver_info) = tun_tap_device::create_device(device_type, response.virtual_ip,
@@ -121,7 +166,7 @@ impl SwitchUtil {
let _ = self.iface.insert((device_writer, device_reader));
Ok(driver_info)
}
pub async fn build(self) -> crate::Result<Switch> {
pub async fn build(self) -> crate::Result<Vnt> {
let response = match self.response {
None => {
return Err(Error::Stop("response None".to_string()));
@@ -138,50 +183,51 @@ impl SwitchUtil {
res
}
};
let config = self.config;
let switch_status_manager = SwitchStatusManger::new();
let cipher = if let Some(key) = &config.key {
let key: &Key<Aes256Gcm> = key.into();
Some(Aes256Gcm::new(&key))
} else {
None
};
let config = self.config.clone();
let vnt_status_manager = VntStatusManger::new();
let client_cipher = Cipher::new_password(config.cipher_model, config.password.clone(), config.token.clone());
let virtual_ip = response.virtual_ip;
let virtual_gateway = response.virtual_gateway;
let virtual_netmask = response.virtual_netmask;
let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, config.server_address)));
let (cone_sender, cone_receiver) = channel(3);
let (symmetric_sender, symmetric_receiver) = channel(2);
let context = Context::new(self.main_channel, 1);
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)))
} else {
(None, None)
};
let context = Context::new(Arc::new(self.main_channel), tcp_sender, current_device.clone(), 1);
let punch = Punch::new(context.clone());
let idle = Idle::new(Duration::from_secs(16), context.clone());
let channel_sender = ChannelSender::new(context.clone());
let register = Arc::new(registration_handler::Register::new(channel_sender.clone(),
let register = Arc::new(registration_handler::Register::new(self.server_cipher.clone(), channel_sender.clone(),
config.server_address, config.token.clone(),
config.device_id.clone(), config.name.clone()));
config.device_id.clone(), config.name.clone(), config.password.is_some()));
let device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>> = Arc::new(Mutex::new((response.epoch, response.device_info_list)));
let peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>> = Arc::new(SkipMap::new());
let peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>> = Arc::new(DashMap::new());
let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected));
let virtual_ip = response.virtual_ip;
let virtual_gateway = response.virtual_gateway;
let virtual_netmask = response.virtual_netmask;
let local_ip = crate::nat::local_ip()?;
let local_port = context.main_local_port()?;
// NAT检测
let nat_test = NatTest::new(config.nat_test_server.clone(), response.public_ip, response.public_port, local_ip, local_port);
let out_ips = config.out_ips.iter().map(|(_, _, ip)| *ip).collect::<Vec<Ipv4Addr>>();
let out_external_route = ExternalRoute::new(config.out_ips);
let nat_test = NatTest::new(config.stun_server.clone(), response.public_ip, response.public_port, local_ip, local_port).await;
let in_external_route = if config.in_ips.is_empty() {
None
} else {
Some(ExternalRoute::new(config.in_ips))
};
let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, config.server_address)));
let (tcp_proxy, udp_proxy, ip_proxy_map) = if out_ips.is_empty() {
let (tcp_proxy, udp_proxy, ip_proxy_map) = if config.out_ips.is_empty() {
(None, None, None)
} else {
let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(channel_sender.clone(), out_ips, current_device.clone()).await?;
let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(channel_sender.clone(), current_device.clone(), client_cipher.clone()).await?;
(Some(tcp_proxy), Some(udp_proxy), Some(ip_proxy_map))
};
let out_external_route = AllowExternalRoute::new(config.out_ips);
let igmp_server = if config.simulate_multicast {
Some(IgmpServer::new(device_writer.clone()))
@@ -190,25 +236,29 @@ impl SwitchUtil {
};
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
if config.tap {
tap_handler::start(switch_status_manager.worker("tap_handler"), channel_sender.clone(), device_reader, device_writer.clone(),
igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone());
tap_handler::start(vnt_status_manager.worker("tap_handler"), channel_sender.clone(), device_reader, device_writer.clone(),
igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(),
client_cipher.clone(), self.server_cipher.clone(), config.parallel);
} else {
tun_handler::start(switch_status_manager.worker("tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(),
igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone());
tun_handler::start(vnt_status_manager.worker("tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(),
igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(),
client_cipher.clone(), self.server_cipher.clone(), config.parallel).await;
}
#[cfg(any(target_os = "android"))]
tun_handler::start(switch_status_manager.worker("android tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(),
igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone());
tun_handler::start(vnt_status_manager.worker("android tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(),
igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone(), config.parallel).await;
//外部数据接收处理
let channel_recv_handler = ChannelDataHandler::new(current_device.clone(), device_list.clone(),
register.clone(), nat_test.clone(), igmp_server,
device_writer.clone(), connect_status.clone(),
peer_nat_info_map.clone(), ip_proxy_map, out_external_route,
cone_sender, symmetric_sender, cipher);
cone_sender, symmetric_sender, client_cipher.clone(),
self.server_cipher.clone(), self.rsa_cipher.clone(), config.relay, config.token.clone());
{
let channel = Channel::new(context.clone(), channel_recv_handler);
let channel_worker = switch_status_manager.worker("channel_worker");
let channel_worker = vnt_status_manager.worker("channel_worker");
let relay = config.relay;
if let Some(tcp_proxy) = tcp_proxy {
tokio::spawn(tcp_proxy.start());
}
@@ -216,30 +266,33 @@ impl SwitchUtil {
tokio::spawn(udp_proxy.start());
}
tokio::spawn(async move {
channel.start(channel_worker, 14, 65).await
channel.start(channel_worker, tcp, 14, 65, relay, config.parallel).await
});
}
{
let other_worker = switch_status_manager.worker("punch_handler");
let other_worker = vnt_status_manager.worker("punch_handler");
let nat_test = nat_test.clone();
let device_list = device_list.clone();
let current_device = current_device.clone();
// 定时心跳
heartbeat_handler::start_heartbeat(other_worker.worker("heartbeat"), channel_sender.clone(), device_list.clone(), current_device.clone(), config.server_address_str);
heartbeat_handler::start_heartbeat(other_worker.worker("heartbeat"), channel_sender.clone(), device_list.clone(),
current_device.clone(), config.server_address_str, client_cipher.clone(), self.server_cipher.clone());
// 空闲检查
heartbeat_handler::start_idle(other_worker.worker("idle"), idle, channel_sender.clone());
// 打洞处理
punch_handler::start(other_worker.worker("cone_receiver"), cone_receiver, punch.clone(), current_device.clone());
punch_handler::start(other_worker.worker("symmetric_receiver"), symmetric_receiver, punch, current_device.clone());
tokio::spawn(punch_handler::start_punch(other_worker, nat_test,
device_list, channel_sender, current_device));
if !config.relay {
// 打洞处理
punch_handler::start(other_worker.worker("cone_receiver"), cone_receiver, punch.clone(), current_device.clone(), client_cipher.clone());
punch_handler::start(other_worker.worker("symmetric_receiver"), symmetric_receiver, punch, current_device.clone(), client_cipher.clone());
tokio::spawn(punch_handler::start_punch(other_worker, nat_test,
device_list, channel_sender, current_device, client_cipher.clone()));
}
}
context.switch(nat_test.nat_info().nat_type);
Ok(Switch {
name: config.name,
Ok(Vnt {
config: self.config,
current_device,
context,
switch_status_manager,
vnt_status_manager,
device_writer,
nat_test,
device_list,
@@ -249,9 +302,15 @@ impl SwitchUtil {
}
}
impl Switch {
impl Vnt {
pub fn name(&self) -> &str {
&self.name
&self.config.name
}
pub fn server_encrypt(&self) -> bool {
self.config.server_encrypt
}
pub fn client_encrypt(&self) -> bool {
self.config.password.is_some()
}
pub fn current_device(&self) -> CurrentDeviceInfo {
self.current_device.load()
@@ -282,7 +341,7 @@ impl Switch {
}
pub fn stop(&self) -> io::Result<()> {
self.context.close();
self.switch_status_manager.stop_all();
self.vnt_status_manager.stop_all();
self.device_writer.close()?;
let virtual_gateway = self.current_device.load().virtual_gateway;
let _ = std::net::UdpSocket::bind("0.0.0.0:0")?.send_to(&[0],
@@ -290,12 +349,12 @@ impl Switch {
Ok(())
}
pub async fn wait_stop(&mut self) {
self.switch_status_manager.wait().await;
self.vnt_status_manager.wait().await;
let _ = self.stop();
}
pub async fn wait_stop_ms(&mut self, ms: Duration) -> bool {
tokio::select! {
_=self.switch_status_manager.wait()=>{
_=self.vnt_status_manager.wait()=>{
let _ = self.stop();
return true;
}
@@ -306,7 +365,7 @@ impl Switch {
}
}
impl Drop for Switch {
impl Drop for Vnt {
fn drop(&mut self) {
let _ = self.stop();
}
@@ -320,12 +379,18 @@ pub struct Config {
pub name: String,
pub server_address: SocketAddr,
pub server_address_str: String,
pub nat_test_server: Vec<SocketAddr>,
pub stun_server: Vec<String>,
pub in_ips: Vec<(u32, u32, Ipv4Addr)>,
pub out_ips: Vec<(u32, u32, Ipv4Addr)>,
pub key: Option<[u8; 32]>,
pub out_ips: Vec<(u32, u32)>,
pub password: Option<String>,
pub simulate_multicast: bool,
pub mtu: Option<u16>,
pub tcp: bool,
pub ip: Option<Ipv4Addr>,
pub relay: bool,
pub server_encrypt: bool,
pub parallel: usize,
pub cipher_model: CipherModel,
}
@@ -335,17 +400,16 @@ impl Config {
name: String,
server_address: SocketAddr,
server_address_str: String,
nat_test_server: Vec<SocketAddr>,
in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32, Ipv4Addr)>,
password: Option<String>, simulate_multicast: bool, mtu: Option<u16>, ) -> Self {
let key = if let Some(password) = password {
let mut hasher = sha2::Sha256::new();
hasher.update(password.as_bytes());
let key: [u8; 32] = hasher.finalize().into();
Some(key)
} else {
None
};
mut stun_server: Vec<String>,
in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32)>,
password: Option<String>, simulate_multicast: bool, mtu: Option<u16>, tcp: bool,
ip: Option<Ipv4Addr>,
relay: bool, server_encrypt: bool, parallel: usize, cipher_model: CipherModel) -> Self {
for x in stun_server.iter_mut() {
if !x.contains(":") {
x.push_str(":3478");
}
}
Self {
tap,
token,
@@ -353,12 +417,18 @@ impl Config {
name,
server_address,
server_address_str,
nat_test_server,
stun_server,
in_ips,
out_ips,
key,
password,
simulate_multicast,
mtu,
tcp,
ip,
relay,
server_encrypt,
parallel,
cipher_model,
}
}
}
@@ -4,22 +4,22 @@ use tokio::sync::watch::{Receiver, Sender};
use crate::util::wait::WaitGroup;
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum SwitchStatus {
pub enum VntStatus {
Starting,
Stopping,
}
pub struct SwitchWorker {
pub struct VntWorker {
_name: String,
wg: WaitGroup,
status_s: Arc<Sender<SwitchStatus>>,
status_r: Receiver<SwitchStatus>,
status_s: Arc<Sender<VntStatus>>,
status_r: Receiver<VntStatus>,
}
impl SwitchWorker {
impl VntWorker {
pub fn worker(&self, name: &str) -> Self {
self.wg.add();
SwitchWorker {
VntWorker {
_name: name.to_string(),
wg: self.wg.clone(),
status_s: self.status_s.clone(),
@@ -28,24 +28,24 @@ impl SwitchWorker {
}
}
impl Drop for SwitchWorker {
impl Drop for VntWorker {
fn drop(&mut self) {
self.wg.done();
}
}
impl SwitchWorker {
impl VntWorker {
pub fn stop_all(&self) {
let _ = self.status_s.send(SwitchStatus::Stopping);
let _ = self.status_s.send(VntStatus::Stopping);
}
pub async fn stop_wait(&mut self) {
loop {
if *self.status_r.borrow() == SwitchStatus::Stopping {
if *self.status_r.borrow() == VntStatus::Stopping {
return;
}
match self.status_r.changed().await {
Ok(_) => {
if *self.status_r.borrow() == SwitchStatus::Stopping {
if *self.status_r.borrow() == VntStatus::Stopping {
return;
}
}
@@ -56,15 +56,15 @@ impl SwitchWorker {
}
#[derive(Clone)]
pub struct SwitchStatusManger {
pub struct VntStatusManger {
wg: WaitGroup,
status_s: Arc<Sender<SwitchStatus>>,
status_r: Receiver<SwitchStatus>,
status_s: Arc<Sender<VntStatus>>,
status_r: Receiver<VntStatus>,
}
impl SwitchStatusManger {
impl VntStatusManger {
pub fn new() -> Self {
let (status_s, status_r) = watch::channel(SwitchStatus::Starting);
let (status_s, status_r) = watch::channel(VntStatus::Starting);
Self {
wg: WaitGroup::new(),
status_s: Arc::new(status_s),
@@ -72,14 +72,14 @@ impl SwitchStatusManger {
}
}
pub fn stop_all(&self) {
let _ = self.status_s.send(SwitchStatus::Stopping);
let _ = self.status_s.send(VntStatus::Stopping);
}
pub async fn wait(&mut self) {
self.wg.wait().await
}
pub fn worker(&self, name: &str) -> SwitchWorker {
pub fn worker(&self, name: &str) -> VntWorker {
self.wg.add();
SwitchWorker {
VntWorker {
_name: name.to_string(),
wg: self.wg.clone(),
status_s: self.status_s.clone(),
+80
View File
@@ -0,0 +1,80 @@
use std::io;
use std::ops::Deref;
use std::time::Duration;
use tokio::runtime::Runtime;
use crate::cipher::RsaCipher;
use crate::core::{Config, Vnt, VntUtil};
use crate::handle::handshake_handler::HandshakeEnum;
use crate::handle::registration_handler::{RegResponse, ReqEnum};
pub struct VntUtilSync {
vnt_util: VntUtil,
runtime: Runtime,
}
pub struct VntSync {
vnt: Vnt,
runtime: Runtime,
}
impl VntUtilSync {
pub fn new(config: Config) -> io::Result<VntUtilSync> {
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();
let vnt_util = runtime.block_on(VntUtil::new(config))?;
Ok(VntUtilSync {
vnt_util,
runtime,
})
}
pub fn connect(&mut self) -> io::Result<()> {
self.runtime.block_on(self.vnt_util.connect())
}
pub fn handshake(&mut self) -> Result<Option<RsaCipher>, HandshakeEnum> {
self.runtime.block_on(self.vnt_util.handshake())
}
pub fn secret_handshake(&mut self) -> Result<(), HandshakeEnum> {
self.runtime.block_on(self.vnt_util.secret_handshake())
}
pub fn register(&mut self) -> Result<RegResponse, ReqEnum> {
self.runtime.block_on(self.vnt_util.register())
}
#[cfg(any(target_os = "android"))]
pub fn create_iface(&mut self, vpn_fd: i32) {
self.vnt_util.create_iface(vpn_fd)
}
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
pub fn create_iface(&mut self) -> io::Result<crate::tun_tap_device::DriverInfo> {
self.vnt_util.create_iface()
}
pub fn build(self) -> crate::Result<VntSync> {
let runtime = self.runtime;
let vnt = runtime.block_on(self.vnt_util.build())?;
{
let mut vnt = vnt.clone();
std::thread::spawn(move || {
runtime.block_on(vnt.wait_stop())
});
}
Ok(VntSync {
vnt,
runtime: tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(),
})
}
}
impl VntSync {
pub fn wait_stop(&mut self) {
self.runtime.block_on(self.vnt.wait_stop())
}
pub fn wait_stop_ms(&mut self, ms: u64) -> bool {
self.runtime.block_on(self.vnt.wait_stop_ms(Duration::from_millis(ms)))
}
}
impl Deref for VntSync {
type Target = Vnt;
fn deref(&self) -> &Self::Target {
&self.vnt
}
}
@@ -11,7 +11,7 @@ pub struct ExternalRoute {
impl ExternalRoute {
pub fn new(route_table: Vec<(u32, u32, Ipv4Addr)>) -> Self {
Self {
route_table:Arc::new(route_table)
route_table: Arc::new(route_table)
}
}
pub fn route(&self, ip: &Ipv4Addr) -> Option<Ipv4Addr> {
@@ -23,4 +23,26 @@ impl ExternalRoute {
}
None
}
}
#[derive(Clone)]
pub struct AllowExternalRoute {
route_table: Arc<Vec<(u32, u32)>>,
}
impl AllowExternalRoute {
pub fn new(route_table: Vec<(u32, u32)>) -> Self {
Self {
route_table: Arc::new(route_table)
}
}
pub fn allow(&self, ip: &Ipv4Addr) -> bool {
let ip = u32::from_be_bytes(ip.octets());
for (dest, mask) in self.route_table.iter() {
if *mask & ip == *mask & *dest {
return true;
}
}
false
}
}
+214
View File
@@ -0,0 +1,214 @@
use std::net::SocketAddr;
use std::time::Duration;
use protobuf::Message;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpStream, UdpSocket};
use crate::channel::channel::Context;
use crate::cipher::{Cipher, RsaCipher};
use crate::proto::message::{HandshakeRequest, HandshakeResponse, SecretHandshakeRequest};
use crate::protocol::{MAX_TTL, NetPacket, Protocol, service_packet, Version};
use crate::protocol::body::ENCRYPTION_RESERVED;
const VERSION: &'static str = "1.2.0";
pub enum HandshakeEnum {
NotSecret,
KeyError,
Timeout,
ServerError(String),
Other(String),
}
fn handshake_request_packet(secret: bool) -> crate::Result<NetPacket<Vec<u8>>> {
let mut request = HandshakeRequest::new();
request.secret = secret;
request.version = VERSION.to_string();
let bytes = request.write_to_bytes()?;
let buf = vec![0u8; 12 + bytes.len()];
let mut net_packet = NetPacket::new(buf)?;
net_packet.set_version(Version::V1);
net_packet.set_gateway_flag(true);
net_packet.set_protocol(Protocol::Service);
net_packet.set_transport_protocol(service_packet::Protocol::HandshakeRequest.into());
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_payload(&bytes)?;
Ok(net_packet)
}
fn secret_handshake_request_packet(rsa_cipher: &RsaCipher, token: String, key: &[u8]) -> crate::Result<NetPacket<Vec<u8>>> {
let mut request = SecretHandshakeRequest::new();
request.token = token;
request.key = key.to_vec();
let bytes = request.write_to_bytes()?;
let mut net_packet = NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?;
net_packet.set_version(Version::V1);
net_packet.set_gateway_flag(true);
net_packet.set_protocol(Protocol::Service);
net_packet.set_transport_protocol(service_packet::Protocol::SecretHandshakeRequest.into());
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_payload(&bytes)?;
Ok(rsa_cipher.encrypt(&mut net_packet)?)
}
/// 第一次握手,拿到公钥
pub async fn handshake(main_channel: &UdpSocket, main_tcp_channel: Option<&mut TcpStream>,
server_address: SocketAddr, secret: bool) -> Result<Option<RsaCipher>, HandshakeEnum> {
let request_packet = handshake_request_packet(secret).unwrap();
let send_buf = request_packet.buffer();
let mut recv_buf = [0u8; 10240];
let len = send_recv(main_channel, main_tcp_channel, server_address, send_buf, &mut recv_buf).await?;
let net_packet = match NetPacket::new(&recv_buf[..len]) {
Ok(net_packet) => {
net_packet
}
Err(e) => {
return Err(HandshakeEnum::Other(format!("net_packet {}", e)));
}
};
match net_packet.protocol() {
Protocol::Service => {
match service_packet::Protocol::from(net_packet.transport_protocol()) {
service_packet::Protocol::HandshakeResponse => {
match HandshakeResponse::parse_from_bytes(net_packet.payload()) {
Ok(response) => {
if !response.secret && secret {
//客户端要加密,服务端不支持加密
return Err(HandshakeEnum::NotSecret);
}
if secret {
//转换公钥
match RsaCipher::new(&response.public_key) {
Ok(rsa) => {
match rsa.finger() {
Ok(finger) => {
if finger != response.key_finger {
return Err(HandshakeEnum::Other("finger error".to_string()));
}
}
Err(e) => {
return Err(HandshakeEnum::Other(format!("finger {}", e)));
}
}
Ok(Some(rsa))
}
Err(e) => {
return Err(HandshakeEnum::Other(format!("RsaCipher {}", e)));
}
}
} else {
Ok(None)
}
}
Err(e) => {
return Err(HandshakeEnum::Other(format!("parse_from_bytes {}", e)));
}
}
}
_ => {
return Err(HandshakeEnum::Other("not match".to_string()));
}
}
}
_ => {
return Err(HandshakeEnum::Other("not match".to_string()));
}
}
}
async fn send_recv(main_channel: &UdpSocket, main_tcp_channel: Option<&mut TcpStream>,
server_address: SocketAddr, send_buf: &[u8], recv_buf: &mut [u8]) -> Result<usize, HandshakeEnum> {
if let Some(main_tcp_channel) = main_tcp_channel {
let mut head = [0; 4];
let len = send_buf.len();
head[2] = (len >> 8) as u8;
head[3] = (len & 0xFF) as u8;
if let Err(e) = main_tcp_channel.write_all(&head).await {
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
}
if let Err(e) = main_tcp_channel.write_all(send_buf).await {
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
}
if let Err(e) = main_tcp_channel.read_exact(&mut head).await {
return Err(HandshakeEnum::Other(format!("read error:{}", e)));
}
let len = (((head[2] as u16) << 8) | head[3] as u16) as usize;
if len > recv_buf.len() {
return Err(HandshakeEnum::Other("too long".to_string()));
}
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[..len]).await {
return Err(HandshakeEnum::Other(format!("read error:{}", e)));
}
Ok(len)
} else {
if let Err(e) = main_channel.send_to(send_buf, server_address).await {
return Err(HandshakeEnum::Other(format!("send error:{}", e)));
}
match tokio::time::timeout(Duration::from_millis(300), main_channel.recv_from(recv_buf)).await {
Ok(rs) => {
match rs {
Ok((len, addr)) => {
if server_address != addr {
return Err(HandshakeEnum::Other(format!("invalid data,from {}", addr)));
}
Ok(len)
}
Err(e) => {
return Err(HandshakeEnum::Other(format!("receiver error:{}", e)));
}
}
}
Err(_) => {
return Err(HandshakeEnum::Timeout);
}
}
}
}
/// 第二次握手,同步对称密钥,后续将使用对称加密
pub async fn secret_handshake(main_channel: &UdpSocket, main_tcp_channel: Option<&mut TcpStream>,
server_address: SocketAddr, rsa_cipher: &RsaCipher, server_cipher: &Cipher, token: String)
-> Result<(), HandshakeEnum> {
let secret_packet = match secret_handshake_request_packet(rsa_cipher, token, server_cipher.key().unwrap()) {
Ok(secret_packet) => {
secret_packet
}
Err(e) => {
return Err(HandshakeEnum::Other(format!("secret_handshake_request_packet {}", e)));
}
};
let send_buf = secret_packet.buffer();
let mut recv_buf = [0u8; 10240];
let len = send_recv(main_channel, main_tcp_channel, server_address, send_buf, &mut recv_buf).await?;
let mut net_packet = match NetPacket::new(&mut recv_buf[..len]) {
Ok(net_packet) => { net_packet }
Err(e) => {
return Err(HandshakeEnum::Other(format!("secret_net_packet {}", e)));
}
};
match server_cipher.decrypt_ipv4(&mut net_packet) {
Ok(_) => {
if net_packet.is_gateway() && net_packet.protocol() == Protocol::Service
&& service_packet::Protocol::from(net_packet.transport_protocol()) ==
service_packet::Protocol::SecretHandshakeResponse {
Ok(())
} else {
Err(HandshakeEnum::Other("not match".to_string()))
}
}
Err(e) => {
Err(HandshakeEnum::Other(format!("decrypt_ipv4 {}", e)))
}
}
}
pub async fn secret_handshake_req(context: &Context,
server_address: SocketAddr, rsa_cipher: &RsaCipher, server_cipher: &Cipher, token: String, ) -> crate::Result<()> {
let secret_packet = secret_handshake_request_packet(rsa_cipher, token, server_cipher.key().unwrap())?;
context.send_main(secret_packet.buffer(), server_address).await?;
if context.is_main_tcp(){
context.send_main_udp(secret_packet.buffer(),server_address).await?;
}
Ok(())
}
@@ -9,14 +9,16 @@ use rand::prelude::SliceRandom;
use crate::channel::idle::Idle;
use crate::channel::Route;
use crate::channel::sender::ChannelSender;
use crate::core::status::SwitchWorker;
use crate::cipher::Cipher;
use crate::core::status::VntWorker;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
use crate::protocol::control_packet::PingPacket;
use crate::protocol::{control_packet, NetPacket, Protocol, Version};
use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, Version};
use crate::protocol::body::ENCRYPTION_RESERVED;
pub fn start_idle(mut worker: SwitchWorker, idle: Idle, sender: ChannelSender) {
pub fn start_idle(mut worker: VntWorker, idle: Idle, sender: ChannelSender) {
tokio::spawn(async move {
tokio::select! {
_=worker.stop_wait()=>{
@@ -45,18 +47,20 @@ async fn start_idle_(idle: Idle, sender: ChannelSender) -> io::Result<()> {
}
pub fn start_heartbeat(
mut worker: SwitchWorker,
mut worker: VntWorker,
sender: ChannelSender,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
server_address_str: String,
client_cipher: Cipher,
server_cipher: Cipher,
) {
tokio::spawn(async move {
tokio::select! {
_=worker.stop_wait()=>{
return;
}
rs=start_heartbeat_(sender, device_list, current_device,server_address_str)=>{
rs=start_heartbeat_(sender, device_list, current_device,server_address_str,client_cipher,server_cipher)=>{
if let Err(e) = rs {
log::warn!("心跳任务停止:{:?}", e);
}
@@ -66,11 +70,29 @@ pub fn start_heartbeat(
});
}
fn set_now_time(packet: &mut NetPacket<[u8; 16]>) -> io::Result<()> {
let current_time = crate::handle::now_time() as u16;
let mut ping = PingPacket::new(packet.payload_mut())?;
ping.set_time(current_time);
Ok(())
fn heartbeat_packet(device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>, client_cipher: &Cipher, server_cipher: &Cipher, gateway: bool, src: Ipv4Addr, dest: Ipv4Addr) -> NetPacket<[u8; 48]> {
let mut net_packet = NetPacket::new_encrypt([0u8; 12 + 4 + ENCRYPTION_RESERVED]).unwrap();
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Control);
net_packet.set_transport_protocol(control_packet::Protocol::Ping.into());
//只寻找两跳以内能到的目标
net_packet.first_set_ttl(2);
net_packet.set_source(src);
net_packet.set_destination(dest);
{
let mut ping = PingPacket::new(net_packet.payload_mut()).unwrap();
let epoch = { device_list.lock().0 };
ping.set_epoch(epoch);
ping.set_time(crate::handle::now_time() as u16);
}
if gateway {
net_packet.set_gateway_flag(true);
server_cipher.encrypt_ipv4(&mut net_packet).unwrap();
} else {
client_cipher.encrypt_ipv4(&mut net_packet).unwrap();
}
net_packet
}
async fn start_heartbeat_(
@@ -78,20 +100,31 @@ async fn start_heartbeat_(
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
server_address_str: String,
client_cipher: Cipher,
server_cipher: Cipher,
) -> io::Result<()> {
let mut net_packet = NetPacket::new([0u8; 16])?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Control);
net_packet.set_transport_protocol(control_packet::Protocol::Ping.into());
//只寻找两跳以内能到的目标
net_packet.first_set_ttl(2);
let mut count = 0;
loop {
if sender.is_close() {
return Ok(());
}
let mut current_dev = current_device.load();
if count % 6 == 0 {
//如果和服务端使用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).await;
}
if count % 20 == 19 {
if let Ok(mut addr) = server_address_str.to_socket_addrs() {
if let Some(addr) = addr.next() {
if addr != current_dev.connect_server {
@@ -104,15 +137,9 @@ async fn start_heartbeat_(
}
}
}
net_packet.set_source(current_dev.virtual_ip());
{
let mut ping = PingPacket::new(net_packet.payload_mut())?;
let epoch = { device_list.lock().0 };
ping.set_epoch(epoch);
}
set_now_time(&mut net_packet)?;
net_packet.set_destination(current_dev.virtual_gateway());
if let Err(e) = sender.send_main(net_packet.buffer(), current_dev.connect_server).await
let src = current_dev.virtual_ip();
let server_packet = heartbeat_packet(&device_list, &client_cipher, &server_cipher, true, src, current_dev.virtual_gateway);
if let Err(e) = sender.send_main(server_packet.buffer(), current_dev.connect_server).await
{
log::warn!(
"connect_server:{:?},e:{:?}",
@@ -127,17 +154,15 @@ async fn start_heartbeat_(
if peer.virtual_ip == current_dev.virtual_ip {
continue;
}
set_now_time(&mut net_packet)?;
net_packet.set_destination(peer.virtual_ip);
let client_packet = heartbeat_packet(&device_list, &client_cipher, &server_cipher, false, src, peer.virtual_ip);
if let Some(route) = sender.route_one(&peer.virtual_ip) {
let _ = sender.send_by_key(net_packet.buffer(), &route.route_key()).await;
let _ = sender.send_by_key(client_packet.buffer(), &route.route_key()).await;
if route.is_p2p() {
continue;
}
} else {
//没有直连路由则发送到网关
let _ = sender.send_main(net_packet.buffer(), current_dev.connect_server).await;
continue;
let _ = sender.send_main(client_packet.buffer(), current_dev.connect_server).await;
}
//再随机发送到其他地址,看有没有客户端符合转发条件
@@ -150,12 +175,11 @@ async fn start_heartbeat_(
'a: for (peer_ip, route_list) in route_list.iter() {
for route in route_list {
if peer_ip != &peer.virtual_ip && route.is_p2p() {
set_now_time(&mut net_packet)?;
let _ = sender.try_send_by_key(net_packet.buffer(), &route.route_key());
let _ = sender.try_send_by_key(client_packet.buffer(), &route.route_key());
num += 1;
break;
}
if num >= 3 {
if num >= 2 {
break 'a;
}
}
@@ -164,10 +188,12 @@ async fn start_heartbeat_(
}
} else {
for (peer_ip, route_list) in sender.route_table().iter() {
set_now_time(&mut net_packet)?;
net_packet.set_destination(*peer_ip);
if peer_ip == &current_dev.virtual_gateway {
continue;
}
let client_packet = heartbeat_packet(&device_list, &client_cipher, &server_cipher, false, src, *peer_ip);
for route in route_list {
if let Err(e) = sender.send_by_key(net_packet.buffer(), &route.route_key()).await {
if let Err(e) = sender.send_by_key(client_packet.buffer(), &route.route_key()).await {
log::warn!("peer_ip:{:?},route:{:?},e:{:?}", peer_ip, route, e);
}
tokio::time::sleep(Duration::from_millis(2)).await;
@@ -1,5 +1,6 @@
use std::net::{Ipv4Addr, SocketAddr};
pub mod handshake_handler;
pub mod heartbeat_handler;
pub mod punch_handler;
pub mod recv_handler;
@@ -26,14 +27,16 @@ pub struct PeerDeviceInfo {
pub virtual_ip: Ipv4Addr,
pub name: String,
pub status: PeerDeviceStatus,
pub client_secret: bool,
}
impl PeerDeviceInfo {
pub fn new(virtual_ip: Ipv4Addr, name: String, status: u8) -> Self {
pub fn new(virtual_ip: Ipv4Addr, name: String, status: u8,client_secret: bool) -> Self {
Self {
virtual_ip,
name,
status: PeerDeviceStatus::from(status),
client_secret
}
}
}
@@ -13,12 +13,16 @@ use std::io;
use tokio::sync::mpsc::Receiver;
use crate::channel::punch::{NatInfo, Punch};
use crate::channel::sender::ChannelSender;
use crate::core::status::SwitchWorker;
use crate::cipher::Cipher;
use crate::core::status::VntWorker;
use crate::protocol::body::ENCRYPTION_RESERVED;
pub fn start(mut worker: SwitchWorker, receiver: Receiver<(Ipv4Addr, NatInfo)>, punch: Punch, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
pub fn start(mut worker: VntWorker, receiver: Receiver<(Ipv4Addr, NatInfo)>,
punch: Punch, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
client_cipher: Cipher, ) {
tokio::spawn(async move {
tokio::select! {
_=start0(receiver, punch, current_device)=>{}
_=start0(receiver, punch, current_device,client_cipher)=>{}
_=worker.stop_wait()=>{
return;
}
@@ -27,21 +31,24 @@ pub fn start(mut worker: SwitchWorker, receiver: Receiver<(Ipv4Addr, NatInfo)>,
});
}
pub async fn start0(mut receiver: Receiver<(Ipv4Addr, NatInfo)>, mut punch: Punch, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
pub async fn start0(mut receiver: Receiver<(Ipv4Addr, NatInfo)>,
mut punch: Punch, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
client_cipher: Cipher, ) {
while let Some((peer_ip, nat_info)) = receiver.recv().await {
if let Err(e) = start_(&mut punch, &current_device, peer_ip, nat_info).await {
if let Err(e) = start_(&client_cipher, &mut punch, &current_device, peer_ip, nat_info).await {
log::warn!("网络打洞异常 {:?}", e);
}
}
}
async fn start_(
client_cipher: &Cipher,
punch: &mut Punch,
current_device: &Arc<AtomicCell<CurrentDeviceInfo>>,
peer_ip: Ipv4Addr,
nat_info: NatInfo,
) -> io::Result<()> {
let mut packet = NetPacket::new([0u8; 12])?;
let mut packet = NetPacket::new_encrypt([0u8; 12 + ENCRYPTION_RESERVED])?;
packet.set_version(Version::V1);
packet.first_set_ttl(1);
packet.set_protocol(Protocol::Control);
@@ -49,16 +56,17 @@ async fn start_(
packet.set_source(current_device.load().virtual_ip());
packet.set_destination(peer_ip);
log::info!("发起打洞,目标:{:?},{:?}", peer_ip, nat_info);
client_cipher.encrypt_ipv4(&mut packet)?;
punch.punch(packet.buffer(), peer_ip, nat_info).await
}
pub async fn start_punch(
mut worker: SwitchWorker,
mut worker: VntWorker,
nat_test: NatTest,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
sender: ChannelSender,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
client_cipher: Cipher,
) {
let mut num = 0;
let sleep_time = [3, 5, 7, 11, 13, 17, 19, 23, 29];
@@ -67,7 +75,8 @@ pub async fn start_punch(
break;
}
tokio::select! {
rs= start_punch_(Duration::from_secs(sleep_time[num % sleep_time.len()]),&nat_test, &device_list, &sender, &current_device)=>{
rs= start_punch_(Duration::from_secs(sleep_time[num % sleep_time.len()]),&nat_test, &device_list,
&sender, &current_device,&client_cipher)=>{
if let Err(e) = rs {
log::warn!("打洞处理任务异常 {:?}", e);
}
@@ -86,6 +95,7 @@ async fn start_punch_(
device_list: &Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
sender: &ChannelSender,
current_device: &Arc<AtomicCell<CurrentDeviceInfo>>,
client_cipher: &Cipher,
) -> crate::Result<()> {
let current_device = current_device.load();
let nat_info = nat_test.nat_info();
@@ -103,18 +113,19 @@ async fn start_punch_(
if count > 2 {
break;
}
let buf = punch_packet(current_device.virtual_ip(), &nat_info, info.virtual_ip)?;
let _ = sender.send_main(&buf, current_device.connect_server).await;
let packet = punch_packet(client_cipher, current_device.virtual_ip(), &nat_info, info.virtual_ip)?;
let _ = sender.send_main(packet.buffer(), current_device.connect_server).await;
}
tokio::time::sleep(sleep_time).await;
Ok(())
}
pub fn punch_packet(
client_cipher: &Cipher,
virtual_ip: Ipv4Addr,
nat_info: &NatInfo,
dest: Ipv4Addr,
) -> crate::Result<Vec<u8>> {
) -> crate::Result<NetPacket<Vec<u8>>> {
let mut punch_reply = PunchInfo::new();
punch_reply.reply = false;
punch_reply.public_ip_list = nat_info
@@ -128,13 +139,14 @@ pub fn punch_packet(
punch_reply.local_port = nat_info.local_port as u32;
punch_reply.nat_type = protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type));
let bytes = punch_reply.write_to_bytes()?;
let mut net_packet = NetPacket::new(vec![0u8; 12 + bytes.len()])?;
let mut net_packet = NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::OtherTurn);
net_packet.set_transport_protocol(other_turn_packet::Protocol::Punch.into());
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_source(virtual_ip);
net_packet.set_destination(dest);
net_packet.set_payload(&bytes);
Ok(net_packet.into_buffer())
net_packet.set_payload(&bytes)?;
client_cipher.encrypt_ipv4(&mut net_packet)?;
Ok(net_packet)
}
@@ -1,34 +1,33 @@
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::sync::Arc;
use aes_gcm::{AeadInPlace, Aes256Gcm, Nonce, Tag};
use aes_gcm::aead::consts::{U12, U16};
use aes_gcm::aead::generic_array::GenericArray;
use crossbeam_utils::atomic::AtomicCell;
use crossbeam_skiplist::SkipMap;
use dashmap::DashMap;
use parking_lot::Mutex;
use protobuf::Message;
use tokio::net::UdpSocket;
use tokio::sync::mpsc::Sender;
use packet::icmp::{icmp, Kind};
use packet::icmp::icmp::HeaderOther;
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use crate::channel::{Route, RouteKey};
use crate::channel::channel::Context;
use crate::channel::punch::{NatInfo, NatType};
use crate::channel::{Route, RouteKey};
use crate::cipher::{Cipher, RsaCipher};
use crate::error::Error;
use crate::external_route::ExternalRoute;
use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo, PeerDeviceStatus};
use crate::external_route::AllowExternalRoute;
use crate::handle::{ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo, PeerDeviceStatus};
use crate::handle::handshake_handler::secret_handshake_req;
use crate::handle::registration_handler::Register;
use crate::igmp_server::IgmpServer;
use crate::ip_proxy::IpProxyMap;
use crate::nat;
use crate::nat::NatTest;
use crate::proto::message::{DeviceList, PunchInfo, PunchNatType, RegistrationResponse};
use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, service_packet, other_turn_packet, Version, ip_turn_packet};
use crate::protocol::{control_packet, ip_turn_packet, MAX_TTL, NetPacket, other_turn_packet, Protocol, service_packet, Version};
use crate::protocol::body::ENCRYPTION_RESERVED;
use crate::protocol::control_packet::ControlPacket;
use crate::protocol::error_packet::InErrorPacket;
use crate::tun_tap_device::DeviceWriter;
@@ -42,12 +41,16 @@ pub struct ChannelDataHandler {
igmp_server: Option<IgmpServer>,
device_writer: DeviceWriter,
connect_status: Arc<AtomicCell<ConnectStatus>>,
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>>,
ip_proxy_map: Option<IpProxyMap>,
out_external_route: ExternalRoute,
out_external_route: AllowExternalRoute,
cone_sender: Sender<(Ipv4Addr, NatInfo)>,
symmetric_sender: Sender<(Ipv4Addr, NatInfo)>,
cipher: Option<Aes256Gcm>,
client_cipher: Cipher,
server_cipher: Cipher,
rsa_cipher: Option<RsaCipher>,
relay: bool,
token: String,
}
impl ChannelDataHandler {
@@ -58,12 +61,15 @@ impl ChannelDataHandler {
igmp_server: Option<IgmpServer>,
device_writer: DeviceWriter,
connect_status: Arc<AtomicCell<ConnectStatus>>,
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
peer_nat_info_map: Arc<DashMap<Ipv4Addr, NatInfo>>,
ip_proxy_map: Option<IpProxyMap>,
out_external_route: ExternalRoute,
out_external_route: AllowExternalRoute,
cone_sender: Sender<(Ipv4Addr, NatInfo)>,
symmetric_sender: Sender<(Ipv4Addr, NatInfo)>,
cipher: Option<Aes256Gcm>, ) -> Self {
client_cipher: Cipher,
server_cipher: Cipher,
rsa_cipher: Option<RsaCipher>,
relay: bool, token: String, ) -> Self {
Self {
current_device,
device_list,
@@ -77,43 +83,40 @@ impl ChannelDataHandler {
out_external_route,
cone_sender,
symmetric_sender,
cipher,
client_cipher,
server_cipher,
rsa_cipher,
relay,
token,
}
}
}
impl ChannelDataHandler {
pub async fn handle(&mut self, buf: &mut [u8], start: usize, end: usize, route_key: RouteKey, _udp: &Arc<UdpSocket>,
context: &Context, ) {
pub async fn handle(&self, buf: &mut [u8], start: usize, end: usize, route_key: RouteKey, context: &Context) {
assert_eq!(start, 14);
match self.handle0(&mut buf[..end], &route_key, context).await {
Ok(_) => {}
Err(e) => {
log::error!("{:?}",e);
log::warn!("{:?}",e);
}
}
}
async fn handle0(&self, buf: &mut [u8], route_key: &RouteKey, context: &Context) -> crate::Result<()> {
let mut net_packet = NetPacket::new(&mut buf[14..])?;
if net_packet.ttl() == 0 {
if net_packet.ttl() == 0 || net_packet.source_ttl() < net_packet.ttl() {
return Ok(());
}
let source = net_packet.source();
context.update_read_time(&source, route_key);
let current_device = self.current_device.load();
let destination = net_packet.destination();
let not_broadcast = !destination.is_broadcast() && !destination.is_multicast() && destination != current_device.broadcast_address;
if current_device.virtual_ip() != destination
&& not_broadcast
&& self.connect_status.load() == ConnectStatus::Connected {
if !check_dest(source, current_device.virtual_netmask, current_device.virtual_network) {
log::warn!("转发数据,源地址错误:{:?},当前网络:{:?},route_key:{:?}",source,current_device.virtual_network,route_key);
return Ok(());
}
if !check_dest(destination, current_device.virtual_netmask, current_device.virtual_network) {
log::warn!("转发数据,目的地址错误:{:?},当前网络:{:?},route_key:{:?}",destination,current_device.virtual_network,route_key);
return Ok(());
}
&& not_broadcast && !destination.is_unspecified() {
//校验指纹,不需要解密
self.client_cipher.check_finger(&net_packet)?;
net_packet.set_ttl(net_packet.ttl() - 1);
let ttl = net_packet.ttl();
if ttl > 0 {
@@ -130,56 +133,25 @@ impl ChannelDataHandler {
}
return Ok(());
}
if net_packet.is_gateway() {
if net_packet.protocol() == Protocol::Error && net_packet.transport_protocol() == crate::protocol::error_packet::Protocol::NoKey.into() {
if let Some(rsa_cipher) = &self.rsa_cipher {
secret_handshake_req(context, current_device.connect_server, rsa_cipher, &self.server_cipher, self.token.clone()).await?;
}
} else {
//服务端解密
self.server_cipher.decrypt_ipv4(&mut net_packet)?;
let data_len = net_packet.data_len();
self.server_packet_handle(context, current_device, buf, data_len, route_key).await?;
}
return Ok(());
}
self.client_cipher.decrypt_ipv4(&mut net_packet)?;
match net_packet.protocol() {
Protocol::IpTurn => {
match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) {
ip_turn_packet::Protocol::Icmp => {
let ipv4 = IpV4Packet::new(net_packet.payload())?;
if ipv4.protocol() == ipv4::protocol::Protocol::Icmp {
self.device_writer.write_ipv4(&mut buf[12..])?;
return Ok(());
}
}
ip_turn_packet::Protocol::Igmp => {
if let Some(igmp_server) = &self.igmp_server {
let ipv4 = IpV4Packet::new(net_packet.payload())?;
if ipv4.protocol() == ipv4::protocol::Protocol::Igmp {
igmp_server.handle(ipv4.payload(), source)?;
}
}
return Ok(());
}
ip_turn_packet::Protocol::Ipv4 => {
let data = if let Some(cipher) = &self.cipher {
if !net_packet.is_encrypt() {
//未加密的数据之间丢弃
return Ok(());
}
if net_packet.payload().len() < 16 {
log::error!("数据异常,长度小于16");
return Ok(());
}
//需要解密
let mut nonce = [0; 12];
nonce[0..4].copy_from_slice(&source.octets());
nonce[4..8].copy_from_slice(&destination.octets());
nonce[8] = Protocol::IpTurn.into();
nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce);
let data_len = net_packet.payload().len() - 16;
let tag: GenericArray<u8, U16> = Tag::clone_from_slice(&net_packet.payload()[data_len..]);
match cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..data_len], &tag) {
Ok(_) => {}
Err(e) => {
log::error!("数据解密异常:{}",e);
return Ok(());
}
}
&mut net_packet.payload_mut()[..data_len]
} else {
net_packet.payload_mut()
};
let mut ipv4 = IpV4Packet::new(data)?;
let mut ipv4 = IpV4Packet::new(net_packet.payload_mut())?;
match ipv4.protocol() {
ipv4::protocol::Protocol::Igmp => {
if let Some(igmp_server) = &self.igmp_server {
@@ -199,30 +171,8 @@ impl ChannelDataHandler {
ipv4.update_checksum();
net_packet.set_source(destination);
net_packet.set_destination(source);
if let Some(cipher) = &self.cipher {
//需要加密
let mut nonce = [0; 12];
nonce[0..4].copy_from_slice(&destination.octets());
nonce[4..8].copy_from_slice(&source.octets());
nonce[8] = Protocol::IpTurn.into();
nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce);
let data_len = net_packet.payload().len() - 16;
match cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..data_len]) {
Ok(tag) => {
if tag.len() != 16 {
log::error!("加密tag长度错误:{}",tag.len());
return Ok(());
}
net_packet.set_encrypt_flag(true);
net_packet.payload_mut()[data_len..data_len + 16].copy_from_slice(tag.as_slice());
}
Err(e) => {
log::error!("加密失败:{}",e);
return Ok(());
}
}
}
//不管加不加密,和接收到的数据长度都一致
self.client_cipher.encrypt_ipv4(&mut net_packet)?;
context.send_by_key(net_packet.buffer(), route_key).await?;
return Ok(());
}
@@ -232,7 +182,7 @@ impl ChannelDataHandler {
}
if not_broadcast && ipv4.destination_ip() != destination {
if let Some(ip_proxy_map) = &self.ip_proxy_map {
if let Some(gate_way) = self.out_external_route.route(&ipv4.destination_ip()) {
if self.out_external_route.allow(&ipv4.destination_ip()) {
match ipv4.protocol() {
ipv4::protocol::Protocol::Tcp => {
let dest_ip = ipv4.destination_ip();
@@ -244,8 +194,9 @@ impl ChannelDataHandler {
tcp_packet.update_checksum();
ipv4.set_destination_ip(destination);
ipv4.update_checksum();
ip_proxy_map.tcp_proxy_map.insert(SocketAddrV4::new(source, source_port),
(SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port)));
let key = SocketAddrV4::new(source, source_port);
//https://github.com/crossbeam-rs/crossbeam/issues/1023
ip_proxy_map.tcp_proxy_map.insert(key, SocketAddrV4::new(dest_ip, dest_port));
}
ipv4::protocol::Protocol::Udp => {
let dest_ip = ipv4.destination_ip();
@@ -257,8 +208,8 @@ impl ChannelDataHandler {
udp_packet.update_checksum();
ipv4.set_destination_ip(destination);
ipv4.update_checksum();
ip_proxy_map.udp_proxy_map.insert(SocketAddrV4::new(source, source_port),
(SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port)));
let key = SocketAddrV4::new(source, source_port);
ip_proxy_map.udp_proxy_map.insert(key, SocketAddrV4::new(dest_ip, dest_port));
}
ipv4::protocol::Protocol::Icmp => {
let dest_ip = ipv4.destination_ip();
@@ -267,18 +218,26 @@ impl ChannelDataHandler {
match icmp_packet.header_other() {
HeaderOther::Identifier(id, seq) => {
ip_proxy_map.icmp_proxy_map.insert((dest_ip, id, seq), source);
ip_proxy_map.send_icmp(ipv4.payload(), &gate_way, &dest_ip)?;
ip_proxy_map.send_icmp(ipv4.payload(), &dest_ip)?;
}
_ => {
return Ok(());
log::warn!("不支持的ip代理Icmp协议:{}",destination);
return Err(Error::Warn("不支持的ip代理Icmp协议".to_string()));
}
}
}
_ => {
return Ok(());
log::warn!("不支持的ip代理ipv4协议:{}",destination);
return Err(Error::Warn("不支持的ip代理ipv4协议".to_string()));
}
}
} else {
log::warn!("没有ip代理规则:{}",destination);
return Err(Error::Warn("没有ip代理规则".to_string()));
}
} else {
log::warn!("不支持ip代理:{}",destination);
return Err(Error::Warn("不支持ip代理".to_string()));
}
}
@@ -292,12 +251,8 @@ impl ChannelDataHandler {
ip_turn_packet::Protocol::Unknown(_) => {}
}
}
Protocol::Service => {
self.service(context, current_device, source, net_packet, route_key).await?;
}
Protocol::Error => {
self.error(context, current_device, source, net_packet, route_key).await?;
}
Protocol::Service => {}
Protocol::Error => {}
Protocol::Control => {
self.control(context, current_device, source, net_packet, route_key).await?;
}
@@ -310,11 +265,249 @@ impl ChannelDataHandler {
}
Ok(())
}
async fn service(&self, context: &Context, current_device: CurrentDeviceInfo, _source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
//todo 校验来源
if route_key.addr != current_device.connect_server {
async fn pong_packet(&self, gateway: bool, metric: u8, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, pong_packet: control_packet::PongPacket<&[u8]>, route_key: &RouteKey) -> crate::Result<()> {
let current_time = crate::handle::now_time() as u16;
if current_time < pong_packet.time() {
return Ok(());
}
let rt = (current_time - pong_packet.time()) as i64;
let route = Route::from(*route_key, metric, rt);
context.add_route(source, route);
if gateway {
let epoch = self.device_list.lock().0;
if pong_packet.epoch() != epoch {
let mut poll_device = NetPacket::new_encrypt([0; 12 + ENCRYPTION_RESERVED])?;
poll_device.set_source(current_device.virtual_ip());
poll_device.set_destination(source);
poll_device.set_version(Version::V1);
poll_device.set_gateway_flag(true);
poll_device.first_set_ttl(MAX_TTL);
poll_device.set_protocol(Protocol::Service);
poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into());
self.server_cipher.encrypt_ipv4(&mut poll_device)?;
context.send_main(poll_device.buffer(), current_device.connect_server).await?;
}
}
Ok(())
}
async fn control(&self, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, mut net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
ControlPacket::PingPacket(_) => {
net_packet.set_transport_protocol(control_packet::Protocol::Pong.into());
net_packet.set_source(current_device.virtual_ip());
net_packet.set_destination(source);
net_packet.first_set_ttl(MAX_TTL);
self.client_cipher.encrypt_ipv4(&mut net_packet)?;
context.send_by_key(net_packet.buffer(), route_key).await?;
let route = Route::from(*route_key, metric, 199);
context.add_route_if_absent(source, route);
}
ControlPacket::PongPacket(pong_packet) => {
self.pong_packet(false, metric, context, current_device, source, pong_packet, route_key).await?;
}
ControlPacket::PunchRequest => {
if self.relay {
return Ok(());
}
//回应
net_packet.set_transport_protocol(control_packet::Protocol::PunchResponse.into());
net_packet.set_source(current_device.virtual_ip());
net_packet.set_destination(source);
net_packet.first_set_ttl(1);
self.client_cipher.encrypt_ipv4(&mut net_packet)?;
context.send_by_key(net_packet.buffer(), route_key).await?;
let route = Route::from(*route_key, 1, 199);
context.add_route_if_absent(source, route);
}
ControlPacket::PunchResponse => {
if self.relay {
return Ok(());
}
let route = Route::from(*route_key, 1, 199);
context.add_route_if_absent(source, route);
}
ControlPacket::AddrRequest => {
match route_key.addr.ip() {
std::net::IpAddr::V4(ipv4) => {
let mut packet = NetPacket::new_encrypt([0; 12 + 6 + ENCRYPTION_RESERVED])?;
packet.set_version(Version::V1);
packet.set_protocol(Protocol::Control);
packet.set_transport_protocol(
control_packet::Protocol::AddrResponse.into(),
);
packet.first_set_ttl(MAX_TTL);
packet.set_source(current_device.virtual_ip());
packet.set_destination(source);
let mut addr_packet = control_packet::AddrPacket::new(packet.payload_mut())?;
addr_packet.set_ipv4(ipv4);
addr_packet.set_port(route_key.addr.port());
self.client_cipher.encrypt_ipv4(&mut packet)?;
context.send_by_key(packet.buffer(), route_key).await?;
}
std::net::IpAddr::V6(_) => {}
}
}
ControlPacket::AddrResponse(addr_packet) => {
if !addr_packet.ipv4().is_multicast()
&& !addr_packet.ipv4().is_broadcast()
&& !addr_packet.ipv4().is_unspecified()
&& !addr_packet.ipv4().is_loopback()
&& !addr_packet.ipv4().is_private() && addr_packet.port() != 0 {
self.nat_test.update_addr(addr_packet.ipv4(), addr_packet.port())
}
}
}
Ok(())
}
async fn other_turn(&self, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
if self.relay {
return Ok(());
}
match other_turn_packet::Protocol::from(net_packet.transport_protocol()) {
other_turn_packet::Protocol::Punch => {
let punch_info = PunchInfo::parse_from_bytes(net_packet.payload())?;
let public_ips = punch_info.public_ip_list.
iter().map(|v| { Ipv4Addr::from(v.to_be_bytes()) }).collect();
let peer_nat_info = NatInfo::new(public_ips,
punch_info.public_port as u16,
punch_info.public_port_range as u16,
Ipv4Addr::from(punch_info.local_ip.to_be_bytes()),
punch_info.local_port as u16,
punch_info.nat_type.enum_value_or_default().into());
self.peer_nat_info_map.insert(source, peer_nat_info.clone());
if !punch_info.reply {
let mut punch_reply = PunchInfo::new();
punch_reply.reply = true;
let nat_info = self.nat_test.nat_info();
punch_reply.public_ip_list = nat_info.public_ips.iter().map(|ip| u32::from_be_bytes(ip.octets())).collect();
punch_reply.public_port = nat_info.public_port as u32;
punch_reply.public_port_range = nat_info.public_port_range as u32;
punch_reply.nat_type =
protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type));
punch_reply.local_ip = u32::from_be_bytes(nat_info.local_ip.octets());
punch_reply.local_port = nat_info.local_port as u32;
let bytes = punch_reply.write_to_bytes()?;
let mut punch_packet =
NetPacket::new_encrypt(vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED])?;
punch_packet.set_version(Version::V1);
punch_packet.set_protocol(Protocol::OtherTurn);
punch_packet.set_transport_protocol(
other_turn_packet::Protocol::Punch.into(),
);
punch_packet.first_set_ttl(MAX_TTL);
punch_packet.set_source(current_device.virtual_ip());
punch_packet.set_destination(source);
punch_packet.set_payload(&bytes)?;
if !peer_nat_info.local_ip.is_unspecified() && peer_nat_info.local_port != 0 {
let mut packet = NetPacket::new_encrypt([0u8; 12 + ENCRYPTION_RESERVED])?;
packet.set_version(Version::V1);
packet.first_set_ttl(1);
packet.set_protocol(Protocol::Control);
packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
packet.set_source(current_device.virtual_ip());
packet.set_destination(source);
self.client_cipher.encrypt_ipv4(&mut packet)?;
let _ = context.send_main(packet.buffer(), SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port))).await;
}
if self.punch(source, peer_nat_info).await {
self.client_cipher.encrypt_ipv4(&mut punch_packet)?;
context.send_by_key(punch_packet.buffer(), route_key).await?;
}
} else {
self.punch(source, peer_nat_info).await;
}
}
other_turn_packet::Protocol::Unknown(e) => {
log::warn!("不支持的转发协议 {:?},source:{:?}",e,source);
}
}
Ok(())
}
async fn punch(&self, peer_ip: Ipv4Addr, peer_nat_info: NatInfo) -> bool {
match peer_nat_info.nat_type {
NatType::Symmetric => {
self.symmetric_sender.try_send((peer_ip, peer_nat_info)).is_ok()
}
NatType::Cone => {
self.cone_sender.try_send((peer_ip, peer_nat_info)).is_ok()
}
}
}
}
/// 处理服务端数据
impl ChannelDataHandler {
async fn server_packet_handle(&self, context: &Context, current_device: CurrentDeviceInfo, buf: &mut [u8], data_len: usize, route_key: &RouteKey) -> crate::Result<()> {
let net_packet = NetPacket::new0(data_len, &buf[14..])?;
let source = net_packet.source();
match net_packet.protocol() {
Protocol::Service => {
self.service(context, current_device, net_packet, route_key).await?;
}
Protocol::Error => {
self.error(context, current_device, source, net_packet, route_key).await?;
}
Protocol::Control => {
self.control_gateway(context, current_device, net_packet, route_key).await?;
}
Protocol::IpTurn => {
match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) {
ip_turn_packet::Protocol::Ipv4 => {
let ipv4 = IpV4Packet::new(net_packet.payload())?;
match ipv4.protocol() {
ipv4::protocol::Protocol::Igmp => {
if let Some(igmp_server) = &self.igmp_server {
igmp_server.handle(ipv4.payload(), source)?;
}
return Ok(());
}
ipv4::protocol::Protocol::Icmp => {
if ipv4.destination_ip() == current_device.virtual_ip {
let icmp_packet = icmp::IcmpPacket::new(ipv4.payload())?;
if icmp_packet.kind() == Kind::EchoReply {
self.device_writer.write_ipv4(&mut buf[12..])?;
return Ok(());
}
}
}
_ => {}
}
}
ip_turn_packet::Protocol::Ipv4Broadcast => {}
ip_turn_packet::Protocol::Unknown(_) => {}
}
}
Protocol::OtherTurn => {}
Protocol::UnKnow(_) => {}
}
return Ok(());
}
async fn control_gateway(&self, context: &Context, current_device: CurrentDeviceInfo, net_packet: NetPacket<&[u8]>, route_key: &RouteKey) -> crate::Result<()> {
if net_packet.source() != current_device.virtual_gateway {
return Ok(());
}
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
ControlPacket::PongPacket(pong_packet) => {
let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
self.pong_packet(true, metric, context, current_device, net_packet.source(), pong_packet, route_key).await?;
}
ControlPacket::AddrResponse(addr_packet) => {
if addr_packet.port() != 0
&& !addr_packet.ipv4().is_multicast()
&& !addr_packet.ipv4().is_broadcast()
&& !addr_packet.ipv4().is_unspecified()
&& !addr_packet.ipv4().is_loopback()
&& !addr_packet.ipv4().is_private() {
self.nat_test.update_addr(addr_packet.ipv4(), addr_packet.port())
}
}
_ => {}
}
Ok(())
}
async fn service(&self, context: &Context, current_device: CurrentDeviceInfo, net_packet: NetPacket<&[u8]>, route_key: &RouteKey) -> crate::Result<()> {
match service_packet::Protocol::from(net_packet.transport_protocol()) {
service_packet::Protocol::RegistrationRequest => {}
service_packet::Protocol::RegistrationResponse => {
@@ -322,7 +515,7 @@ impl ChannelDataHandler {
let local_port = context.main_local_port()?;
let local_ip = nat::local_ip()?;
let nat_info = self.nat_test.re_test(Ipv4Addr::from(response.public_ip),
response.public_port as u16, local_ip, local_port);
response.public_port as u16, local_ip, local_port).await;
context.switch(nat_info.nat_type);
let new_ip = Ipv4Addr::from(response.virtual_ip);
let current_ip = current_device.virtual_ip();
@@ -357,6 +550,7 @@ impl ChannelDataHandler {
Ipv4Addr::from(info.virtual_ip),
info.name,
info.device_status as u8,
info.client_secret,
)
})
.collect();
@@ -375,13 +569,12 @@ impl ChannelDataHandler {
service_packet::Protocol::Unknown(u) => {
log::warn!("未知服务协议:{}",u);
}
_ => {}
}
Ok(())
}
async fn error(&self, _context: &Context, current_device: CurrentDeviceInfo, _source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
if route_key.addr != current_device.connect_server {
return Ok(());
}
async fn error(&self, _context: &Context, current_device: CurrentDeviceInfo, _source: Ipv4Addr, net_packet: NetPacket<&[u8]>, _route_key: &RouteKey) -> crate::Result<()> {
log::info!("current_device:{:?}",current_device);
match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
InErrorPacket::TokenError => {
return Err(Error::Stop("Token error".to_string()));
@@ -394,7 +587,7 @@ impl ChannelDataHandler {
}
self.connect_status.store(ConnectStatus::Connecting);
self.register.fast_register().await?;
self.register.fast_register(current_device.virtual_ip).await?;
}
InErrorPacket::AddressExhausted => {
//地址用尽
@@ -403,130 +596,14 @@ impl ChannelDataHandler {
InErrorPacket::OtherError(e) => {
log::error!("OtherError {:?}", e.message());
}
InErrorPacket::IpAlreadyExists => {
log::error!("IpAlreadyExists");
}
InErrorPacket::InvalidIp => {
log::error!("InvalidIp");
}
InErrorPacket::NoKey => {}
}
Ok(())
}
async fn control(&self, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, mut net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
ControlPacket::PingPacket(_) => {
context.update_read_time(&source, route_key);
net_packet.set_transport_protocol(control_packet::Protocol::Pong.into());
net_packet.set_source(current_device.virtual_ip());
net_packet.set_destination(source);
net_packet.first_set_ttl(MAX_TTL);
context.send_by_key(net_packet.buffer(), route_key).await?;
let route = Route::from(*route_key, metric, 99);
context.add_route_if_absent(source, route);
}
ControlPacket::PongPacket(pong_packet) => {
context.update_read_time(&source, route_key);
let current_time = crate::handle::now_time() as u16;
if current_time < pong_packet.time() {
return Ok(());
}
let rt = (current_time - pong_packet.time()) as i64;
let route = Route::from(*route_key, metric, rt);
context.add_route(source, route);
if route_key.addr == current_device.connect_server && source == current_device.virtual_gateway() {
let epoch = self.device_list.lock().0;
if pong_packet.epoch() != epoch {
let mut poll_device = NetPacket::new([0; 12])?;
poll_device.set_source(current_device.virtual_ip());
poll_device.set_destination(source);
poll_device.set_version(Version::V1);
poll_device.first_set_ttl(MAX_TTL);
poll_device.set_protocol(Protocol::Service);
poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into());
context.send_by_key(poll_device.buffer(), route_key).await?;
}
}
}
ControlPacket::PunchRequest => {
//回应
net_packet.set_transport_protocol(control_packet::Protocol::PunchResponse.into());
net_packet.set_source(current_device.virtual_ip());
net_packet.set_destination(source);
net_packet.first_set_ttl(1);
context.send_by_key(net_packet.buffer(), route_key).await?;
let route = Route::from(*route_key, metric, 99);
context.add_route_if_absent(source, route);
}
ControlPacket::PunchResponse => {
// log::info!("PunchResponse route_key:{:?}",route_key);
let route = Route::from(*route_key, metric, 99);
context.add_route_if_absent(source, route);
}
}
Ok(())
}
async fn other_turn(&self, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
match other_turn_packet::Protocol::from(net_packet.transport_protocol()) {
other_turn_packet::Protocol::Punch => {
let punch_info = PunchInfo::parse_from_bytes(net_packet.payload())?;
let public_ips = punch_info.public_ip_list.
iter().map(|v| { Ipv4Addr::from(v.to_be_bytes()) }).collect();
let peer_nat_info = NatInfo::new(public_ips,
punch_info.public_port as u16,
punch_info.public_port_range as u16,
Ipv4Addr::from(punch_info.local_ip.to_be_bytes()),
punch_info.local_port as u16,
punch_info.nat_type.enum_value_or_default().into());
self.peer_nat_info_map.insert(source, peer_nat_info.clone());
if !punch_info.reply {
let mut punch_reply = PunchInfo::new();
punch_reply.reply = true;
let nat_info = self.nat_test.nat_info();
punch_reply.public_ip_list = nat_info.public_ips.iter().map(|ip| u32::from_be_bytes(ip.octets())).collect();
punch_reply.public_port = nat_info.public_port as u32;
punch_reply.public_port_range = nat_info.public_port_range as u32;
punch_reply.nat_type =
protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type));
punch_reply.local_ip = u32::from_be_bytes(nat_info.local_ip.octets());
punch_reply.local_port = nat_info.local_port as u32;
let bytes = punch_reply.write_to_bytes()?;
let mut net_packet =
NetPacket::new(vec![0u8; 12 + bytes.len()])?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::OtherTurn);
net_packet.set_transport_protocol(
other_turn_packet::Protocol::Punch.into(),
);
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_source(current_device.virtual_ip());
net_packet.set_destination(source);
net_packet.set_payload(&bytes);
if !peer_nat_info.local_ip.is_unspecified() && peer_nat_info.local_port != 0 {
let mut packet = NetPacket::new([0u8; 12])?;
packet.set_version(Version::V1);
packet.first_set_ttl(1);
packet.set_protocol(Protocol::Control);
packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
packet.set_source(current_device.virtual_ip());
packet.set_destination(source);
let _ = context.send_main(packet.buffer(), SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port))).await;
}
if self.punch(source, peer_nat_info).await {
context.send_by_key(net_packet.buffer(), route_key).await?;
}
} else {
self.punch(source, peer_nat_info).await;
}
}
other_turn_packet::Protocol::Unknown(e) => {
log::warn!("不支持的转发协议 {:?},source:{:?}",e,source);
}
}
Ok(())
}
async fn punch(&self, peer_ip: Ipv4Addr, peer_nat_info: NatInfo) -> bool {
match peer_nat_info.nat_type {
NatType::Symmetric => {
self.symmetric_sender.try_send((peer_ip, peer_nat_info)).is_ok()
}
NatType::Cone => {
self.cone_sender.try_send((peer_ip, peer_nat_info)).is_ok()
}
}
}
}
+269
View File
@@ -0,0 +1,269 @@
use std::net::{Ipv4Addr, SocketAddr};
use std::time::{Duration, Instant};
use crossbeam_utils::atomic::AtomicCell;
use protobuf::Message;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpStream, UdpSocket};
use crate::channel::sender::ChannelSender;
use crate::cipher::Cipher;
use crate::handle::PeerDeviceInfo;
use crate::proto::message::{RegistrationRequest, RegistrationResponse};
use crate::protocol::error_packet::InErrorPacket;
use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL};
use crate::protocol::body::ENCRYPTION_RESERVED;
pub enum ReqEnum {
TokenError,
AddressExhausted,
IpAlreadyExists,
InvalidIp,
Timeout,
ServerError(String),
Other(String),
}
#[derive(Clone, Debug)]
pub struct RegResponse {
pub virtual_ip: Ipv4Addr,
pub virtual_gateway: Ipv4Addr,
pub virtual_netmask: Ipv4Addr,
pub epoch: u16,
pub device_info_list: Vec<PeerDeviceInfo>,
pub public_ip: Ipv4Addr,
pub public_port: u16,
}
///向中继服务器注册,token标识一个虚拟网关,device_id防止多次注册时得到的ip不一致
pub async fn registration(
main_channel: &UdpSocket,
main_tcp_channel: Option<&mut TcpStream>,
server_cipher: &Cipher,
server_address: SocketAddr,
token: String,
device_id: String,
name: String,
ip: Ipv4Addr,
client_secret: bool,
) -> Result<RegResponse, ReqEnum> {
let request_packet =
registration_request_packet(server_cipher, token.clone(), device_id.clone(), name.clone(), ip, false, false, client_secret).unwrap();
let buf = request_packet.buffer();
let mut recv_buf = [0u8; 10240];
let recv_buf = if let Some(main_tcp_channel) = main_tcp_channel {
let mut vec = vec![0; 4 + buf.len()];
let len = buf.len();
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 {
return Err(ReqEnum::Other(format!("send error:{}", e)));
}
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[..4]).await {
return Err(ReqEnum::Other(format!("read error:{}", e)));
}
let len = 4 + (((recv_buf[2] as u16) << 8) | recv_buf[3] as u16) as usize;
if len > recv_buf.len() {
return Err(ReqEnum::Other("too long".to_string()));
}
if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[4..len]).await {
return Err(ReqEnum::Other(format!("read error:{}", e)));
}
&mut recv_buf[4..len]
} else {
if let Err(e) = main_channel.send_to(buf, server_address).await {
return Err(ReqEnum::Other(format!("send error:{}", e)));
}
match tokio::time::timeout(Duration::from_millis(300), main_channel.recv_from(&mut recv_buf)).await {
Ok(rs) => {
match rs {
Ok((len, addr)) => {
if server_address != addr {
return Err(ReqEnum::Other(format!("invalid data,from {}", addr)));
}
&mut recv_buf[..len]
}
Err(e) => {
return Err(ReqEnum::Other(format!("receiver error:{}", e)));
}
}
}
Err(_) => {
return Err(ReqEnum::Timeout);
}
}
};
let mut net_packet = match NetPacket::new(recv_buf) {
Ok(net_packet) => {
net_packet
}
Err(e) => {
return Err(ReqEnum::ServerError(format!("{}", e)));
}
};
if let Err(e) = server_cipher.decrypt_ipv4(&mut net_packet) {
return Err(ReqEnum::ServerError(format!("decrypt_ipv4 {}", e)));
}
match net_packet.protocol() {
Protocol::Service => {
match service_packet::Protocol::from(net_packet.transport_protocol()) {
service_packet::Protocol::RegistrationResponse => {
match RegistrationResponse::parse_from_bytes(net_packet.payload()) {
Ok(response) => {
let device_info_list: Vec<PeerDeviceInfo> = response
.device_info_list
.into_iter()
.map(|info| {
PeerDeviceInfo::new(
Ipv4Addr::from(info.virtual_ip),
info.name,
info.device_status as u8,
info.client_secret,
)
})
.collect();
Ok(RegResponse {
virtual_ip: Ipv4Addr::from(response.virtual_ip),
virtual_gateway: Ipv4Addr::from(response.virtual_gateway),
virtual_netmask: Ipv4Addr::from(response.virtual_netmask),
epoch: response.epoch as u16,
device_info_list,
public_ip: Ipv4Addr::from(response.public_ip),
public_port: response.public_port as u16,
})
}
Err(_) => {
Err(ReqEnum::ServerError("invalid data".to_string()))
}
}
}
_ => {
Err(ReqEnum::ServerError("invalid data".to_string()))
}
}
}
Protocol::Error => {
match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload()) {
Ok(e) => match e {
InErrorPacket::TokenError => Err(ReqEnum::TokenError),
InErrorPacket::Disconnect => {
Err(ReqEnum::ServerError("disconnect".to_string()))
}
InErrorPacket::AddressExhausted => {
Err(ReqEnum::AddressExhausted)
}
InErrorPacket::OtherError(e) => match e.message() {
Ok(str) => {
Err(ReqEnum::ServerError(str))
}
Err(e) => Err(ReqEnum::Other(format!("{}", e))),
},
InErrorPacket::IpAlreadyExists => {
Err(ReqEnum::IpAlreadyExists)
}
InErrorPacket::InvalidIp => {
Err(ReqEnum::InvalidIp)
}
InErrorPacket::NoKey => {
Err(ReqEnum::ServerError("no key".to_string()))
}
},
Err(e) => Err(ReqEnum::Other(format!("{}", e))),
}
}
_ => Err(ReqEnum::ServerError("invalid data".to_string())),
}
}
fn registration_request_packet(
server_cipher: &Cipher,
token: String,
device_id: String,
name: String,
ip: Ipv4Addr,
is_fast: bool,
allow_ip_change: bool,
client_secret: bool,
) -> crate::Result<NetPacket<Vec<u8>>> {
let mut request = RegistrationRequest::new();
request.token = token;
request.device_id = device_id;
request.name = name;
request.virtual_ip = ip.into();
request.allow_ip_change = allow_ip_change;
request.is_fast = is_fast;
request.version = "1.2.0".to_string();
request.client_secret = client_secret;
let bytes = request.write_to_bytes()?;
let buf = vec![0u8; 12 + bytes.len() + ENCRYPTION_RESERVED];
let mut net_packet = NetPacket::new_encrypt(buf)?;
net_packet.set_version(Version::V1);
net_packet.set_gateway_flag(true);
net_packet.set_protocol(Protocol::Service);
net_packet.set_transport_protocol(service_packet::Protocol::RegistrationRequest.into());
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_payload(&bytes)?;
server_cipher.encrypt_ipv4(&mut net_packet)?;
Ok(net_packet)
}
pub struct Register {
server_cipher: Cipher,
sender: ChannelSender,
server_address: SocketAddr,
token: String,
device_id: String,
name: String,
time: AtomicCell<Instant>,
client_secret: bool,
}
impl Register {
pub fn new(
server_cipher: Cipher,
sender: ChannelSender,
server_address: SocketAddr,
token: String,
device_id: String,
name: String,
client_secret: bool,
) -> Self {
Self {
server_cipher,
sender,
server_address,
token,
device_id,
name,
time: AtomicCell::new(Instant::now()),
client_secret,
}
}
pub async fn fast_register(&self, ip: Ipv4Addr) -> crate::Result<()> {
let last = self.time.load();
if last.elapsed() < Duration::from_secs(2)
|| self
.time
.compare_exchange(last, Instant::now())
.is_err()
{
//短时间不重复注册
return Ok(());
}
log::info!("重新连接");
let request_packet = registration_request_packet(
&self.server_cipher,
self.token.clone(),
self.device_id.clone(),
self.name.clone(),
ip,
false,
true,
self.client_secret,
)?;
let buf = request_packet.buffer();
self.sender.send_main(buf, self.server_address).await?;
Ok(())
}
}
+25
View File
@@ -0,0 +1,25 @@
use byte_pool::Block;
#[derive(Clone)]
pub struct BufSenderGroup(usize, Vec<tokio::sync::mpsc::Sender<(Block<'static>, usize, usize)>>);
pub struct BufReceiverGroup(pub Vec<tokio::sync::mpsc::Receiver<(Block<'static>, usize, usize)>>);
impl BufSenderGroup {
pub async fn send(&mut self, val: (Block<'static>, usize, usize)) -> bool {
let index = self.0 % self.1.len();
self.0 = self.0.wrapping_add(1);
self.1[index].send(val).await.is_ok()
}
}
pub fn buf_channel_group(size: usize) -> (BufSenderGroup, BufReceiverGroup) {
let mut buf_sender_group = Vec::with_capacity(size);
let mut buf_receiver_group = Vec::with_capacity(size);
for _ in 0..size {
let (buf_sender, buf_receiver) = tokio::sync::mpsc::channel::<(Block<'static>, usize, usize)>(10);
buf_sender_group.push(buf_sender);
buf_receiver_group.push(buf_receiver);
}
(BufSenderGroup(0, buf_sender_group), BufReceiverGroup(buf_receiver_group))
}
+207
View File
@@ -0,0 +1,207 @@
use std::io;
use std::net::SocketAddrV4;
use std::sync::Arc;
use parking_lot::RwLock;
use packet::ip::ipv4::packet::IpV4Packet;
use packet::ip::ipv4::protocol::Protocol;
use packet::tcp::tcp::TcpPacket;
use packet::udp::udp::UdpPacket;
use crate::channel::sender::ChannelSender;
use crate::cipher::Cipher;
use crate::external_route::ExternalRoute;
use crate::handle::{check_dest, CurrentDeviceInfo};
use crate::ip_proxy::IpProxyMap;
use crate::protocol::{ip_turn_packet, MAX_TTL, NetPacket, Version};
use crate::error::*;
use crate::igmp_server::{IgmpServer, Multicast};
use crate::protocol;
use crate::protocol::body::ENCRYPTION_RESERVED;
use crate::protocol::ip_turn_packet::BroadcastPacket;
pub mod channel_group;
pub mod tun_handler;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
pub mod tap_handler;
async fn broadcast(server_cipher: &Cipher, multicast_members: Option<Arc<RwLock<Multicast>>>, sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]>, current_device: &CurrentDeviceInfo) -> Result<()> {
let mut peer_ips = Vec::with_capacity(8);
let vec = sender.route_table_one();
let mut relay_count = 0;
const MAX_COUNT: usize = 8;
for (peer_ip, route) in vec {
if peer_ip == current_device.virtual_gateway {
continue;
}
if peer_ips.len() == MAX_COUNT {
break;
}
if let Some(members) = &multicast_members {
if !members.read().is_send(&peer_ip) {
continue;
}
}
if route.is_p2p()
&& sender.send_by_key(net_packet.buffer(), &route.route_key()).await.is_ok() {
peer_ips.push(peer_ip);
} else {
relay_count += 1;
}
}
if relay_count == 0 && !peer_ips.is_empty() && peer_ips.len() != MAX_COUNT {
//不需要转发
return Ok(());
}
//转发到服务端的可选择广播,还要进行服务端加密
if peer_ips.is_empty() {
sender.send_main(net_packet.buffer(), current_device.connect_server).await?;
} else {
let buf = vec![0 as u8; 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);
server_packet.set_gateway_flag(true);
server_packet.first_set_ttl(MAX_TTL);
server_packet.set_source(net_packet.source());
server_packet.set_destination(current_device.virtual_gateway);
server_packet.set_protocol(protocol::Protocol::IpTurn);
server_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4Broadcast.into());
let mut broadcast = BroadcastPacket::unchecked(server_packet.payload_mut());
broadcast.set_address(&peer_ips)?;
broadcast.set_data(net_packet.buffer())?;
server_cipher.encrypt_ipv4(&mut server_packet)?;
sender.send_main(server_packet.buffer(), current_device.connect_server).await?;
}
Ok(())
}
/// 实现一个原地发送,必须保证是如下结构
/// |12字节开头|ip报文|至少1024字节结尾|
///
#[inline]
pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8],
data_len: usize,//数据总长度=12+ip包长度
igmp_server: &Option<IgmpServer>,
current_device: CurrentDeviceInfo,
ip_route: &Option<ExternalRoute>,
proxy_map: &Option<IpProxyMap>,
client_cipher: &Cipher,
server_cipher: &Cipher) -> Result<()> {
let ipv4_packet = IpV4Packet::new(&buf[12..data_len])?;
let protocol = ipv4_packet.protocol();
let ip_head_len = ipv4_packet.header_len() as usize * 4;
if 12 + ip_head_len >= data_len {
Err(io::Error::new(io::ErrorKind::Other, "ip_head_len err"))?
}
let src_ip = ipv4_packet.source_ip();
let mut dest_ip = ipv4_packet.destination_ip();
let mut net_packet = NetPacket::new0(data_len, buf)?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(protocol::Protocol::IpTurn);
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4.into());
net_packet.first_set_ttl(3);
net_packet.set_source(src_ip);
net_packet.set_destination(dest_ip);
if dest_ip == current_device.virtual_gateway {
if protocol == Protocol::Icmp {
net_packet.set_gateway_flag(true);
server_cipher.encrypt_ipv4(&mut net_packet)?;
sender.send_main(net_packet.buffer(), current_device.connect_server).await?;
}
return Ok(());
}
if dest_ip.is_multicast() {
match protocol {
Protocol::Igmp => {
if igmp_server.is_some() {
//发送到服务端
net_packet.set_destination(current_device.virtual_gateway);
net_packet.set_gateway_flag(true);
server_cipher.encrypt_ipv4(&mut net_packet)?;
sender.send_main(net_packet.buffer(), current_device.connect_server).await?;
}
}
Protocol::Udp => {
client_cipher.encrypt_ipv4(&mut net_packet)?;
let multicast_members = if let Some(igmp_server) = igmp_server {
igmp_server.load(&dest_ip)
} else {
None
};
broadcast(server_cipher, multicast_members, sender, &mut net_packet, &current_device).await?;
}
_ => {}
}
return Ok(());
}
if dest_ip.is_broadcast() || current_device.broadcast_address == dest_ip {
// 广播 发送到直连目标
client_cipher.encrypt_ipv4(&mut net_packet)?;
broadcast(server_cipher, None, sender, &mut net_packet, &current_device).await?;
return Ok(());
}
if !check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) {
if let Some(ip_route) = ip_route {
if let Some(r_dest_ip) = ip_route.route(&dest_ip) {
//路由的目标不能是自己
if r_dest_ip == src_ip {
return Ok(());
}
//需要修改目的地址
dest_ip = r_dest_ip;
net_packet.set_destination(r_dest_ip);
} else {
return Ok(());
}
} 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();
}else{
log::warn!("不存在接口 {:?}",dest_addr);
}
}
Protocol::Udp => {
let dest_addr = {
let udp_packet = UdpPacket::new(src_ip, dest_ip,
&mut net_packet.payload_mut()[ip_head_len..])?;
SocketAddrV4::new(dest_ip, udp_packet.destination_port())
};
if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) {
let source_addr = entry.value();
let source_ip = *source_addr.ip();
let mut udp_packet = UdpPacket::new(source_ip, dest_ip,
&mut net_packet.payload_mut()[ip_head_len..])?;
udp_packet.set_source_port(source_addr.port());
udp_packet.update_checksum();
let mut ipv4_packet = IpV4Packet::new(net_packet.payload_mut())?;
ipv4_packet.set_source_ip(source_ip);
ipv4_packet.update_checksum();
}
}
_ => {}
}
}
client_cipher.encrypt_ipv4(&mut net_packet)?;
//优先发到直连到地址
if sender.send_by_id(net_packet.buffer(), &dest_ip).await.is_err() {
sender.send_main(net_packet.buffer(), current_device.connect_server).await?;
}
return Ok(());
}
@@ -1,7 +1,10 @@
use std::sync::Arc;
use std::{io, thread};
use aes_gcm::Aes256Gcm;
use std::sync::Arc;
use byte_pool::BytePool;
use crossbeam_utils::atomic::AtomicCell;
use lazy_static::lazy_static;
use packet::arp::arp::ArpPacket;
use packet::ethernet;
use packet::ethernet::packet::EthernetPacket;
@@ -9,56 +12,113 @@ use packet::icmp::icmp::IcmpPacket;
use packet::icmp::Kind;
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use crate::channel::sender::ChannelSender;
use crate::core::status::SwitchWorker;
use crate::cipher::Cipher;
use crate::core::status::VntWorker;
use crate::external_route::ExternalRoute;
use crate::handle::CurrentDeviceInfo;
use crate::handle::tun_tap::channel_group::{buf_channel_group, BufSenderGroup};
use crate::igmp_server::IgmpServer;
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: SwitchWorker, sender: ChannelSender,
pub fn start(worker: VntWorker, sender: ChannelSender,
device_reader: DeviceReader,
device_writer: DeviceWriter,
igmp_server: Option<IgmpServer>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: Option<ExternalRoute>,
ip_proxy_map: Option<IpProxyMap>,
cipher: Option<Aes256Gcm>) {
thread::Builder::new().name("tap_handler".into()).spawn(move || {
tokio::runtime::Builder::new_current_thread()
.enable_all().build().unwrap()
.block_on(async move {
if let Err(e) = start_(sender, device_reader,
device_writer, igmp_server,
current_device, ip_route, ip_proxy_map, cipher).await {
log::warn!("tap:{:?}",e);
client_cipher: Cipher, server_cipher: Cipher, parallel: usize) {
if parallel == 1 {
thread::Builder::new().name("tap_handler".into()).spawn(move || {
tokio::runtime::Builder::new_current_thread()
.enable_all().build().unwrap()
.block_on(async move {
if let Err(e) = start_simple(sender, device_reader,
device_writer, igmp_server,
current_device, ip_route, ip_proxy_map, client_cipher, server_cipher).await {
log::warn!("tap:{:?}",e);
}
worker.stop_all();
});
}).unwrap();
} else {
let (buf_sender, buf_receiver) = buf_channel_group(parallel);
for mut buf_receiver in buf_receiver.0 {
let sender = sender.clone();
let device_writer = device_writer.clone();
let igmp_server = igmp_server.clone();
let current_device = current_device.clone();
let ip_route = ip_route.clone();
let ip_proxy_map = ip_proxy_map.clone();
let client_cipher = client_cipher.clone();
let server_cipher = server_cipher.clone();
tokio::spawn(async move {
while let Some((mut buf, _, len)) = buf_receiver.recv().await {
match handle(&mut buf, len, &igmp_server, &current_device, &device_writer, &sender,
&ip_route, &ip_proxy_map, &client_cipher, &server_cipher).await {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
}
worker.stop_all();
});
}).unwrap();
}
thread::Builder::new().name("tap_handler".into()).spawn(move || {
tokio::runtime::Builder::new_current_thread()
.enable_all().build().unwrap()
.block_on(async move {
if let Err(e) = start_(sender, device_reader, buf_sender).await {
log::warn!("tap:{:?}",e);
}
worker.stop_all();
});
}).unwrap();
}
}
async fn start_(sender: ChannelSender,
device_reader: DeviceReader,
device_writer: DeviceWriter,
igmp_server: Option<IgmpServer>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: Option<ExternalRoute>,
ip_proxy_map: Option<IpProxyMap>,
cipher: Option<Aes256Gcm>) -> io::Result<()> {
mut buf_sender: BufSenderGroup) -> io::Result<()> {
loop {
let mut buf = POOL.alloc(4096);
if sender.is_close() {
return Ok(());
}
let start = 0;
let len = device_reader.read(&mut buf)?;
if !buf_sender.send((buf, start, len)).await {
return Err(io::Error::new(io::ErrorKind::Other, "tap buf_sender发送失败"));
}
}
}
async fn start_simple(sender: ChannelSender,
device_reader: DeviceReader,
device_writer: DeviceWriter,
igmp_server: Option<IgmpServer>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: Option<ExternalRoute>,
ip_proxy_map: Option<IpProxyMap>,
client_cipher: Cipher, server_cipher: Cipher) -> io::Result<()> {
let mut buf = [0; 4096];
loop {
//ip拆包了会直接丢弃?
let len = device_reader.read(&mut buf)?;
if let Err(e) = handle(&mut buf, len, &igmp_server, &current_device, &device_writer, &sender, &ip_route, &ip_proxy_map, &cipher).await {
if let Err(e) = handle(&mut buf, len, &igmp_server, &current_device, &device_writer, &sender, &ip_route, &ip_proxy_map, &client_cipher, &server_cipher).await {
log::warn!("tap handle{:?}",e);
}
}
}
async fn handle(buf: &mut [u8], len: usize, igmp_server: &Option<IgmpServer>, current_device: &AtomicCell<CurrentDeviceInfo>,
device_writer: &DeviceWriter, sender: &ChannelSender, ip_route: &Option<ExternalRoute>, proxy_map: &Option<IpProxyMap>, cipher: &Option<Aes256Gcm>) -> crate::Result<()> {
device_writer: &DeviceWriter, sender: &ChannelSender, ip_route: &Option<ExternalRoute>,
proxy_map: &Option<IpProxyMap>, client_cipher: &Cipher, server_cipher: &Cipher) -> crate::Result<()> {
let mut ethernet_packet = EthernetPacket::new(&mut buf[..len])?;
let current_device = current_device.load();
match ethernet_packet.protocol() {
@@ -110,7 +170,7 @@ async fn handle(buf: &mut [u8], len: usize, igmp_server: &Option<IgmpServer>, cu
}
// 以太网帧头部14字节,预留12字节
return crate::handle::tun_tap::base_handle(sender, &mut buf[2..], len - 2, igmp_server, current_device,
ip_route, proxy_map, cipher).await;
ip_route, proxy_map, client_cipher, server_cipher).await;
}
_ => {
// log::warn!("不支持的二层协议:{:?}",p)
+163
View File
@@ -0,0 +1,163 @@
use std::{io, thread};
use std::sync::Arc;
use byte_pool::BytePool;
use crossbeam_utils::atomic::AtomicCell;
use packet::icmp::Kind;
use packet::icmp::icmp::IcmpPacket;
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use crate::channel::sender::ChannelSender;
use crate::cipher::Cipher;
use crate::core::status::VntWorker;
use crate::error::*;
use crate::external_route::ExternalRoute;
use crate::handle::CurrentDeviceInfo;
use crate::handle::tun_tap::channel_group::{buf_channel_group, BufSenderGroup};
use crate::igmp_server::IgmpServer;
use crate::ip_proxy::IpProxyMap;
use crate::tun_tap_device::{DeviceReader, DeviceWriter};
lazy_static::lazy_static! {
static ref POOL:BytePool<Vec<u8>> = BytePool::<Vec<u8>>::new();
}
fn icmp(device_writer: &DeviceWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Result<()> {
if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp {
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
if icmp.kind() == Kind::EchoRequest {
icmp.set_kind(Kind::EchoReply);
icmp.update_checksum();
let src = ipv4_packet.source_ip();
ipv4_packet.set_source_ip(ipv4_packet.destination_ip());
ipv4_packet.set_destination_ip(src);
ipv4_packet.update_checksum();
device_writer.write_ipv4_tun(ipv4_packet.buffer)?;
}
}
Ok(())
}
/// 接收tun数据,并且转发到udp上
#[inline]
async fn handle(sender: &ChannelSender, data: &mut [u8], len: usize, device_writer: &DeviceWriter,
igmp_server: &Option<IgmpServer>, current_device: CurrentDeviceInfo,
ip_route: &Option<ExternalRoute>, proxy_map: &Option<IpProxyMap>,
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 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);
}
return crate::handle::tun_tap::base_handle(sender, data, len, igmp_server,
current_device, ip_route, proxy_map, client_cipher, server_cipher).await;
}
pub async fn start(worker: VntWorker, sender: ChannelSender,
device_reader: DeviceReader,
device_writer: DeviceWriter,
igmp_server: Option<IgmpServer>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: Option<ExternalRoute>,
ip_proxy_map: Option<IpProxyMap>,
client_cipher: Cipher, server_cipher: Cipher, parallel: usize) {
if parallel == 1 {
thread::Builder::new().name("tun_handler".into()).spawn(move || {
tokio::runtime::Builder::new_current_thread()
.enable_all().build().unwrap()
.block_on(async move {
if let Err(e) = start_simple(sender, device_reader, &device_writer, igmp_server, current_device, ip_route, ip_proxy_map, client_cipher, server_cipher).await {
log::warn!("stop:{}",e);
}
let _ = device_writer.close();
worker.stop_all();
})
}).unwrap();
} else {
let (buf_sender, buf_receiver) = buf_channel_group(parallel);
for mut buf_receiver in buf_receiver.0 {
let sender = sender.clone();
let device_writer = device_writer.clone();
let igmp_server = igmp_server.clone();
let current_device = current_device.clone();
let ip_route = ip_route.clone();
let ip_proxy_map = ip_proxy_map.clone();
let client_cipher = client_cipher.clone();
let server_cipher = server_cipher.clone();
tokio::spawn(async move {
while let Some((mut buf, start, len)) = buf_receiver.recv().await {
match handle(&sender, &mut buf[start..], len, &device_writer, &igmp_server, current_device.load(),
&ip_route, &ip_proxy_map, &client_cipher, &server_cipher).await {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
}
});
}
thread::Builder::new().name("tun_handler".into()).spawn(move || {
tokio::runtime::Builder::new_current_thread()
.enable_all().build().unwrap()
.block_on(async move {
if let Err(e) = start_(sender, device_reader, buf_sender).await {
log::warn!("stop:{}",e);
}
let _ = device_writer.close();
worker.stop_all();
})
}).unwrap();
}
}
async fn start_(sender: ChannelSender, device_reader: DeviceReader, mut buf_sender: BufSenderGroup) -> io::Result<()> {
loop {
let mut buf = POOL.alloc(4096);
buf[..12].fill(0);
if sender.is_close() {
return Ok(());
}
let start = 0;
let len = device_reader.read(&mut buf[12..])? + 12;
#[cfg(any(target_os = "macos"))]
let start = 4;
if !buf_sender.send((buf, start, len)).await {
return Err(io::Error::new(io::ErrorKind::Other, "tun buf_sender发送失败"));
}
}
}
async fn start_simple(sender: ChannelSender,
device_reader: DeviceReader,
device_writer: &DeviceWriter,
igmp_server: Option<IgmpServer>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: Option<ExternalRoute>,
ip_proxy_map: Option<IpProxyMap>,
client_cipher: Cipher, server_cipher: Cipher) -> io::Result<()> {
let mut buf = [0; 4096];
loop {
if sender.is_close() {
return Ok(());
}
buf[..12].fill(0);
let len = device_reader.read(&mut buf[12..])? + 12;
#[cfg(any(target_os = "macos"))]
let mut buf = &mut buf[4..];
match handle(&sender, &mut buf, len, device_writer, &igmp_server, current_device.load(), &ip_route, &ip_proxy_map, &client_cipher, &server_cipher).await {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
}
}
@@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet};
use std::net::Ipv4Addr;
use std::sync::Arc;
use std::time::{Duration, Instant};
use crossbeam_skiplist::SkipMap;
use dashmap::DashMap;
use parking_lot::RwLock;
use packet::igmp::igmp_v2::IgmpV2Packet;
use packet::igmp::igmp_v3::{IgmpV3QueryPacket, IgmpV3RecordType, IgmpV3ReportPacket};
@@ -47,12 +47,12 @@ impl Multicast {
#[derive(Clone)]
pub struct IgmpServer {
multicast: Arc<SkipMap<Ipv4Addr, Arc<RwLock<Multicast>>>>,
multicast: Arc<DashMap<Ipv4Addr, Arc<RwLock<Multicast>>>>,
}
impl IgmpServer {
pub fn new(device_writer: DeviceWriter) -> Self {
let multicast: Arc<SkipMap<Ipv4Addr, Arc<RwLock<Multicast>>>> = Arc::new(SkipMap::new());
let multicast: Arc<DashMap<Ipv4Addr, Arc<RwLock<Multicast>>>> = Arc::new(DashMap::new());
std::thread::spawn(move || {
//预留以太网帧头和ip头
let mut buf = [0; 14 + 24 + 12];
@@ -124,10 +124,12 @@ impl IgmpServer {
if !multicast_addr.is_multicast() {
return Ok(());
}
let multi = self.multicast.get_or_insert_with(multicast_addr, || {
Arc::new(RwLock::new(Multicast::new()))
});
let mut guard = multi.value().write();
let multi = {
self.multicast.entry(multicast_addr).or_insert_with(|| {
Arc::new(RwLock::new(Multicast::new()))
}).value().clone()
};
let mut guard = multi.write();
guard.members.insert(source, Instant::now());
}
IgmpType::LeaveV2 => {
@@ -151,10 +153,10 @@ impl IgmpServer {
if !multicast_addr.is_multicast() {
return Ok(());
}
let multi = self.multicast.get_or_insert_with(multicast_addr, || {
let multi = self.multicast.entry(multicast_addr).or_insert_with(|| {
Arc::new(RwLock::new(Multicast::new()))
});
let mut guard = multi.value().write();
}).value().clone();
let mut guard = multi.write();
match group_record.record_type() {
IgmpV3RecordType::ModeIsInclude | IgmpV3RecordType::ChangeToIncludeMode => {
@@ -3,72 +3,49 @@ use std::mem::MaybeUninit;
use std::net::{IpAddr, Ipv4Addr, SocketAddrV4};
use std::sync::Arc;
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap;
use crossbeam_skiplist::SkipMap;
use socket2::{Domain, SockAddr, Socket, Type};
use packet::icmp::icmp;
use packet::icmp::icmp::HeaderOther;
use packet::ip::ipv4;
use crate::channel::sender::ChannelSender;
use crate::cipher::Cipher;
use crate::handle::CurrentDeviceInfo;
use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version};
use crate::protocol::body::ENCRYPTION_RESERVED;
pub struct IcmpProxy {
icmp_socket: Arc<Socket>,
// 对端-> 真实来源
icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
sender: ChannelSender,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
client_cipher: Cipher,
}
impl IcmpProxy {
pub fn new(addr: SocketAddrV4, icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>, sender: ChannelSender, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<IcmpProxy> {
pub fn new(addr: SocketAddrV4, icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
sender: ChannelSender, current_device: Arc<AtomicCell<CurrentDeviceInfo>>, client_cipher: Cipher) -> io::Result<IcmpProxy> {
let icmp_socket = Arc::new(Socket::new(Domain::IPV4, Type::RAW, Some(socket2::Protocol::ICMPV4))?);
icmp_socket.bind(&SockAddr::from(addr))?;
// // 设置 SIO_RCVALL 参数
// #[cfg(windows)]
// {
// use std::os::windows::io::AsRawSocket;
// let raw_fd = icmp_socket.as_raw_socket();
// let mut rcvall: winapi::shared::minwindef::DWORD = 1;
// let mut bytes_returned: winapi::shared::minwindef::DWORD = 0;
// let result = unsafe {
// winapi::um::winsock2::WSAIoctl(
// raw_fd as _,
// winapi::shared::mstcpip::SIO_RCVALL,
// &mut rcvall as *mut winapi::shared::minwindef::DWORD as *mut std::ffi::c_void,
// std::mem::size_of::<winapi::shared::minwindef::DWORD>() as winapi::shared::minwindef::DWORD,
// std::ptr::null_mut(),
// 0,
// &mut bytes_returned as winapi::shared::minwindef::LPDWORD,
// std::ptr::null_mut(),
// None,
// )
// };
// if result != 0 {
// return Err(io::Error::from_raw_os_error(unsafe { winapi::um::winsock2::WSAGetLastError() }));
// }
// }
Ok(IcmpProxy {
icmp_socket,
icmp_proxy_map,
sender,
current_device,
client_cipher,
})
}
pub fn icmp_socket(&self) ->Arc<Socket>{
pub fn icmp_socket(&self) -> Arc<Socket> {
self.icmp_socket.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 net_packet = NetPacket::new([0u8; 4 + 8 + 1500]).unwrap();
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::IpTurn);
net_packet.set_transport_protocol(ipv4::protocol::Protocol::Icmp.into());
net_packet.first_set_ttl(MAX_TTL);
loop {
match self.recv(data) {
Ok((len, peer_ip)) => {
@@ -83,14 +60,27 @@ impl IcmpProxy {
if let Some(entry) = self.icmp_proxy_map.get(&(peer_ip, id, seq)) {
//将数据发送到真实的来源
let dest_ip = *entry.value();
drop(entry);
ipv4_packet.set_destination_ip(dest_ip);
ipv4_packet.update_checksum();
let virtual_ip = self.current_device.load().virtual_ip();
let current_device = self.current_device.load();
let virtual_ip = current_device.virtual_ip();
let connect_server = current_device.connect_server;
let mut net_packet = NetPacket::new_encrypt(vec![0u8; 12 + len + ENCRYPTION_RESERVED]).unwrap();
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::IpTurn);
net_packet.set_transport_protocol(crate::protocol::ip_turn_packet::Protocol::Ipv4.into());
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_source(virtual_ip);
net_packet.set_destination(dest_ip);
let data_len = ipv4_packet.buffer.len();
net_packet.set_payload(ipv4_packet.buffer);
let _ = self.sender.try_send_by_id(&net_packet.buffer()[..(12 + data_len)], &dest_ip);
net_packet.set_payload(ipv4_packet.buffer).unwrap();
if let Err(e) = self.client_cipher.encrypt_ipv4(&mut net_packet) {
log::warn!("加密失败:{}",e);
continue;
}
if self.sender.try_send_by_id(net_packet.buffer(), &dest_ip).is_err() {
let _ = self.sender.try_send_main(net_packet.buffer(), connect_server);
}
}
}
_ => {
+70
View File
@@ -0,0 +1,70 @@
use std::{io, thread};
use std::net::{Ipv4Addr, SocketAddrV4};
use std::sync::Arc;
use crossbeam_utils::atomic::AtomicCell;
use dashmap::DashMap;
use socket2::{SockAddr, Socket};
use tokio::net::{TcpListener, UdpSocket};
use crate::channel::sender::ChannelSender;
use crate::cipher::Cipher;
use crate::handle::CurrentDeviceInfo;
use crate::ip_proxy::icmp_proxy::IcmpProxy;
use crate::ip_proxy::tcp_proxy::TcpProxy;
use crate::ip_proxy::udp_proxy::UdpProxy;
pub mod icmp_proxy;
pub mod tcp_proxy;
pub mod udp_proxy;
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)]
pub enum Protocol {
Icmp,
Tcp,
Udp,
}
#[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的一律不转发
pub(crate) icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
icmp_socket: Arc<Socket>,
}
impl IpProxyMap {
pub fn send_icmp(&self, buf: &[u8], dest: &Ipv4Addr) -> io::Result<usize> {
self.icmp_socket.send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0)))
}
}
pub async fn init_proxy(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::new());
let udp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>> = Arc::new(DashMap::new());
let icmp_proxy_map: Arc<DashMap<(Ipv4Addr, u16, u16), Ipv4Addr>> = Arc::new(DashMap::new());
let tcp_listener = TcpListener::bind("0.0.0.0:0").await?;
let udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
let tcp_proxy_port = tcp_listener.local_addr()?.port();
let udp_proxy_port = udp_socket.local_addr()?.port();
let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map.clone());
let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map.clone());
let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0);
let icmp_proxy = IcmpProxy::new(addr, icmp_proxy_map.clone(),
sender.clone(), current_device.clone(),client_cipher)?;
let icmp_socket = icmp_proxy.icmp_socket();
thread::spawn(move || {
icmp_proxy.start();
});
Ok((tcp_proxy, udp_proxy, IpProxyMap {
tcp_proxy_port,
udp_proxy_port,
tcp_proxy_map,
udp_proxy_map,
icmp_proxy_map,
icmp_socket,
}))
}
@@ -1,59 +1,54 @@
use std::io;
use std::net::{SocketAddr, SocketAddrV4};
use std::sync::Arc;
use crossbeam_skiplist::SkipMap;
use dashmap::DashMap;
use tokio::net::{TcpListener, TcpStream};
pub struct TcpProxy {
tcp_listener: TcpListener,
map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
}
impl TcpProxy {
pub fn new(tcp_listener: TcpListener, map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>) -> Self {
pub fn new(tcp_listener: TcpListener, tcp_proxy_map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>) -> Self {
Self {
tcp_listener,
map,
tcp_proxy_map,
}
}
pub async fn start(self) {
pub async fn start(self) {
let tcp_listener = self.tcp_listener;
let map = self.map;
let tcp_proxy_map = self.tcp_proxy_map;
loop {
match tcp_listener.accept().await {
Ok((tcp_stream, sender_addr)) => {
match sender_addr {
SocketAddr::V4(sender_addr) => {
if let Some(entry) = map.get(&sender_addr) {
let (src_addr, dest_addr) = *entry.value();
if let Some(entry) = tcp_proxy_map.get(&sender_addr) {
let dest_addr = *entry.value();
drop(entry);
let peer_tcp_stream = match TcpStream::connect(dest_addr).await {
Ok(peer_tcp_stream) => {peer_tcp_stream}
Ok(peer_tcp_stream) => { peer_tcp_stream }
Err(e) => {
log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,sender_addr,dest_addr);
continue;
}
};
let map = map.clone();
tokio::spawn(async move {
match proxy(tcp_stream, peer_tcp_stream).await {
Ok(_) => {}
Err(e) => {
log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
}
if let Err(e) = proxy(tcp_stream, peer_tcp_stream).await {
log::warn!("{}->{},{}",sender_addr,dest_addr,e);
}
map.remove(&sender_addr);
});
}
}
SocketAddr::V6(_) => {}
}
}
Err(e) => {
log::warn!("tcp代理监听:{:?}",e);
}
}
}
}
}
@@ -65,7 +60,8 @@ async fn proxy(mut client: TcpStream, mut server: TcpStream) -> io::Result<()> {
let client_to_server = tokio::io::copy(&mut client_reader, &mut server_writer);
let server_to_client = tokio::io::copy(&mut server_reader, &mut client_writer);
tokio::try_join!(client_to_server, server_to_client)?;
let (r1, r2) = tokio::join!(client_to_server, server_to_client);
r1?;
r2?;
Ok(())
}
}
@@ -2,17 +2,17 @@ use std::io;
use std::net::{SocketAddr, SocketAddrV4};
use std::sync::Arc;
use std::time::Duration;
use crossbeam_skiplist::SkipMap;
use dashmap::DashMap;
use tokio::net::UdpSocket;
/// 一个udp代理,作用是利用系统协议栈,将udp数据报解析出来再转发到目的地址
pub struct UdpProxy {
udp_socket: Arc<UdpSocket>,
map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>,
}
impl UdpProxy {
pub fn new(udp_socket: UdpSocket, map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>) -> Self {
pub fn new(udp_socket: UdpSocket, map: Arc<DashMap<SocketAddrV4, SocketAddrV4>>) -> Self {
let udp_socket = Arc::new(udp_socket);
Self {
udp_socket,
@@ -23,7 +23,7 @@ impl UdpProxy {
let map = self.map;
let udp_socket = self.udp_socket;
let mut buf = [0u8; 65536];
let inner_map: Arc<SkipMap<SocketAddrV4, Arc<UdpSocket>>> = Arc::new(SkipMap::new());
let inner_map: Arc<DashMap<SocketAddrV4, Arc<UdpSocket>>> = Arc::new(DashMap::new());
loop {
match udp_socket.recv_from(&mut buf).await {
@@ -48,11 +48,14 @@ impl UdpProxy {
}
}
async fn start0(buf: &[u8], sender_addr: SocketAddrV4, inner_map: &Arc<SkipMap<SocketAddrV4, Arc<UdpSocket>>>, map: &Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>, udp_socket: &Arc<UdpSocket>) -> io::Result<()> {
async fn start0(buf: &[u8], sender_addr: SocketAddrV4, inner_map: &Arc<DashMap<SocketAddrV4, Arc<UdpSocket>>>, map: &Arc<DashMap<SocketAddrV4, SocketAddrV4>>, udp_socket: &Arc<UdpSocket>) -> io::Result<()> {
if let Some(entry) = inner_map.get(&sender_addr) {
entry.value().send(buf).await?;
let udp = entry.value().clone();
drop(entry);
udp.send(buf).await?;
} else if let Some(entry) = map.get(&sender_addr) {
let (src_addr, dest_addr) = *entry.value();
let dest_addr = *entry.value();
drop(entry);
let peer_udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
peer_udp_socket.connect(dest_addr).await?;
peer_udp_socket.send(buf).await?;
@@ -71,20 +74,20 @@ async fn start0(buf: &[u8], sender_addr: SocketAddrV4, inner_map: &Arc<SkipMap<S
match udp_socket.send_to(&buf[..len], sender_addr).await {
Ok(_) => {}
Err(e) => {
log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,sender_addr,dest_addr);
break;
}
}
}
Err(e) => {
log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,sender_addr,dest_addr);
break;
}
}
}
Err(_) => {
//超时关闭
log::warn!("udp代理超时关闭,来源:{},目标:{}",src_addr,dest_addr);
log::warn!("udp代理超时关闭,来源:{},目标:{}",sender_addr,dest_addr);
break;
}
}
+1
View File
@@ -14,3 +14,4 @@ pub mod tun_tap_device;
pub mod core;
pub mod channel;
pub mod util;
pub mod cipher;
+27 -17
View File
@@ -1,13 +1,14 @@
use crate::proto::message::PunchNatType;
use parking_lot::Mutex;
use std::io;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::net::{IpAddr, Ipv4Addr};
use std::net::UdpSocket;
use std::sync::Arc;
pub mod check;
use parking_lot::Mutex;
use std::net::UdpSocket;
use crate::channel::punch::{NatInfo, NatType};
use crate::proto::message::PunchNatType;
mod stun_test;
pub fn local_ip() -> io::Result<Ipv4Addr> {
let socket = UdpSocket::bind("0.0.0.0:0")?;
@@ -25,7 +26,7 @@ pub fn local_ip() -> io::Result<Ipv4Addr> {
#[derive(Clone)]
pub struct NatTest {
nat_test_server: Arc<Vec<SocketAddr>>,
stun_server: Vec<String>,
info: Arc<Mutex<NatInfo>>,
}
@@ -48,29 +49,38 @@ impl Into<NatType> for PunchNatType {
}
impl NatTest {
pub fn new(
nat_test_server: Vec<SocketAddr>,
pub async fn new(
mut stun_server: Vec<String>,
public_ip: Ipv4Addr,
public_port: u16,
local_ip: Ipv4Addr,
local_port: u16,
) -> NatTest {
let server = stun_server[0].clone();
stun_server.resize(3, server);
let info = NatTest::re_test_(
&nat_test_server,
&stun_server,
public_ip,
public_port,
local_ip,
local_port,
);
).await;
NatTest {
nat_test_server: Arc::new(nat_test_server),
stun_server,
info: Arc::new(Mutex::new(info)),
}
}
pub fn nat_info(&self) -> NatInfo {
self.info.lock().clone()
}
pub fn re_test(
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);
}
}
pub async fn re_test(
&self,
public_ip: Ipv4Addr,
public_port: u16,
@@ -78,23 +88,23 @@ impl NatTest {
local_port: u16,
) -> NatInfo {
let info = NatTest::re_test_(
&self.nat_test_server,
&self.stun_server,
public_ip,
public_port,
local_ip,
local_port,
);
).await;
*self.info.lock() = info.clone();
info
}
fn re_test_(
nat_test_server: &Vec<SocketAddr>,
async fn re_test_(
stun_server: &Vec<String>,
public_ip: Ipv4Addr,
public_port: u16,
local_ip: Ipv4Addr,
local_port: u16,
) -> NatInfo {
return match check::public_ip_list(nat_test_server) {
return match stun_test::stun_test_nat(stun_server.clone()).await {
Ok((nat_type, ips, port_range)) => {
let mut public_ips = Vec::new();
public_ips.push(Ipv4Addr::from(public_ip));
+129
View File
@@ -0,0 +1,129 @@
use std::collections::HashSet;
use std::io;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::time::Duration;
use stun_format::Attr;
use tokio::net::UdpSocket;
use crate::channel::punch::NatType;
pub async fn stun_test_nat(stun_servers: Vec<String>) -> io::Result<(NatType, Vec<Ipv4Addr>, u16)> {
let mut h = Vec::new();
for x in stun_servers {
let handle = tokio::spawn(test_nat(x));
h.push(handle);
}
let mut nat_type = NatType::Cone;
let mut port_range = 0;
let mut hash_set = HashSet::new();
for x in h {
if let Ok(rs) = x.await {
if let Ok((nat_type_t, ip_list_t, port_range_t)) = rs {
if nat_type_t == NatType::Symmetric {
nat_type = NatType::Symmetric;
}
for x in ip_list_t {
hash_set.insert(x);
}
if port_range < port_range_t {
port_range = port_range_t;
}
}
}
}
Ok((nat_type, hash_set.into_iter().collect(), port_range))
}
async fn test_nat(stun_server: String) -> io::Result<(NatType, Vec<Ipv4Addr>, u16)> {
let udp = UdpSocket::bind("0.0.0.0:0").await?;
udp.connect(stun_server).await?;
let mut nat_type = NatType::Cone;
let mut port_range = 0;
let mut hash_set = HashSet::new();
match test_nat_(&udp, true, true).await {
Ok((mapped_addr1, changed_addr1)) => {
match mapped_addr1.ip() {
IpAddr::V4(ip) => {
hash_set.insert(ip);
}
IpAddr::V6(_) => {}
}
if udp.connect(changed_addr1).await.is_ok() {
if let Ok((mapped_addr2, _)) = test_nat_(&udp, false, false).await {
match mapped_addr2.ip() {
IpAddr::V4(ip) => {
hash_set.insert(ip);
}
IpAddr::V6(_) => {}
}
port_range = mapped_addr2.port().abs_diff(mapped_addr1.port());
if mapped_addr1 != mapped_addr2 {
nat_type = NatType::Symmetric;
}
}
}
}
Err(_) => {}
}
Ok((nat_type, hash_set.into_iter().collect(), port_range))
}
async fn test_nat_(udp: &UdpSocket, change_ip: bool, change_port: bool) -> io::Result<(SocketAddr, SocketAddr)> {
for _ in 0..2 {
let mut buf = [0u8; 28];
let mut msg = stun_format::MsgBuilder::from(buf.as_mut_slice());
msg.typ(stun_format::MsgType::BindingRequest).unwrap();
msg.tid(1).unwrap();
msg.add_attr(Attr::ChangeRequest { change_ip, change_port }).unwrap();
udp.send(msg.as_bytes()).await?;
let mut buf = [0; 10240];
let (len, addr) = match tokio::time::timeout(Duration::from_millis(300), udp.recv_from(&mut buf)).await {
Ok(rs) => { rs? }
Err(_) => {
continue;
}
};
let msg = stun_format::Msg::from(&buf[..len]);
let mut mapped_addr = None;
let mut changed_addr = None;
for x in msg.attrs_iter() {
match x {
Attr::MappedAddress(addr) => {
if mapped_addr.is_none() {
let _ = mapped_addr.insert(stun_addr(addr));
}
}
Attr::ChangedAddress(addr) => {
if changed_addr.is_none() {
let _ = changed_addr.insert(stun_addr(addr));
}
}
Attr::XorMappedAddress(addr) => {
if mapped_addr.is_none() {
let _ = mapped_addr.insert(stun_addr(addr));
}
}
_ => {}
}
if changed_addr.is_some() && mapped_addr.is_some() {
return Ok((mapped_addr.unwrap(), changed_addr.unwrap()));
}
}
if mapped_addr.is_some() {
return Ok((mapped_addr.unwrap(), changed_addr.unwrap_or(addr)));
}
}
Err(io::Error::new(io::ErrorKind::Other, "stun response err"))
}
fn stun_addr(addr: stun_format::SocketAddr) -> SocketAddr {
match addr {
stun_format::SocketAddr::V4(ip, port) => {
SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from(ip), port))
}
stun_format::SocketAddr::V6(ip, port) => {
SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from(ip), port, 0, 0))
}
}
}
@@ -25,6 +25,462 @@
/// of protobuf runtime.
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_2_0;
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:HandshakeRequest)
pub struct HandshakeRequest {
// message fields
// @@protoc_insertion_point(field:HandshakeRequest.version)
pub version: ::std::string::String,
// @@protoc_insertion_point(field:HandshakeRequest.secret)
pub secret: bool,
// special fields
// @@protoc_insertion_point(special_field:HandshakeRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a HandshakeRequest {
fn default() -> &'a HandshakeRequest {
<HandshakeRequest as ::protobuf::Message>::default_instance()
}
}
impl HandshakeRequest {
pub fn new() -> HandshakeRequest {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(2);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"version",
|m: &HandshakeRequest| { &m.version },
|m: &mut HandshakeRequest| { &mut m.version },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"secret",
|m: &HandshakeRequest| { &m.secret },
|m: &mut HandshakeRequest| { &mut m.secret },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<HandshakeRequest>(
"HandshakeRequest",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for HandshakeRequest {
const NAME: &'static str = "HandshakeRequest";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
10 => {
self.version = is.read_string()?;
},
16 => {
self.secret = is.read_bool()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if !self.version.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.version);
}
if self.secret != false {
my_size += 1 + 1;
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if !self.version.is_empty() {
os.write_string(1, &self.version)?;
}
if self.secret != false {
os.write_bool(2, self.secret)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> HandshakeRequest {
HandshakeRequest::new()
}
fn clear(&mut self) {
self.version.clear();
self.secret = false;
self.special_fields.clear();
}
fn default_instance() -> &'static HandshakeRequest {
static instance: HandshakeRequest = HandshakeRequest {
version: ::std::string::String::new(),
secret: false,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for HandshakeRequest {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("HandshakeRequest").unwrap()).clone()
}
}
impl ::std::fmt::Display for HandshakeRequest {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for HandshakeRequest {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:HandshakeResponse)
pub struct HandshakeResponse {
// message fields
// @@protoc_insertion_point(field:HandshakeResponse.version)
pub version: ::std::string::String,
// @@protoc_insertion_point(field:HandshakeResponse.secret)
pub secret: bool,
// @@protoc_insertion_point(field:HandshakeResponse.public_key)
pub public_key: ::std::vec::Vec<u8>,
// @@protoc_insertion_point(field:HandshakeResponse.key_finger)
pub key_finger: ::std::string::String,
// special fields
// @@protoc_insertion_point(special_field:HandshakeResponse.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a HandshakeResponse {
fn default() -> &'a HandshakeResponse {
<HandshakeResponse as ::protobuf::Message>::default_instance()
}
}
impl HandshakeResponse {
pub fn new() -> HandshakeResponse {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(4);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"version",
|m: &HandshakeResponse| { &m.version },
|m: &mut HandshakeResponse| { &mut m.version },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"secret",
|m: &HandshakeResponse| { &m.secret },
|m: &mut HandshakeResponse| { &mut m.secret },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_key",
|m: &HandshakeResponse| { &m.public_key },
|m: &mut HandshakeResponse| { &mut m.public_key },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"key_finger",
|m: &HandshakeResponse| { &m.key_finger },
|m: &mut HandshakeResponse| { &mut m.key_finger },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<HandshakeResponse>(
"HandshakeResponse",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for HandshakeResponse {
const NAME: &'static str = "HandshakeResponse";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
10 => {
self.version = is.read_string()?;
},
16 => {
self.secret = is.read_bool()?;
},
26 => {
self.public_key = is.read_bytes()?;
},
34 => {
self.key_finger = is.read_string()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if !self.version.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.version);
}
if self.secret != false {
my_size += 1 + 1;
}
if !self.public_key.is_empty() {
my_size += ::protobuf::rt::bytes_size(3, &self.public_key);
}
if !self.key_finger.is_empty() {
my_size += ::protobuf::rt::string_size(4, &self.key_finger);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if !self.version.is_empty() {
os.write_string(1, &self.version)?;
}
if self.secret != false {
os.write_bool(2, self.secret)?;
}
if !self.public_key.is_empty() {
os.write_bytes(3, &self.public_key)?;
}
if !self.key_finger.is_empty() {
os.write_string(4, &self.key_finger)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> HandshakeResponse {
HandshakeResponse::new()
}
fn clear(&mut self) {
self.version.clear();
self.secret = false;
self.public_key.clear();
self.key_finger.clear();
self.special_fields.clear();
}
fn default_instance() -> &'static HandshakeResponse {
static instance: HandshakeResponse = HandshakeResponse {
version: ::std::string::String::new(),
secret: false,
public_key: ::std::vec::Vec::new(),
key_finger: ::std::string::String::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for HandshakeResponse {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("HandshakeResponse").unwrap()).clone()
}
}
impl ::std::fmt::Display for HandshakeResponse {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for HandshakeResponse {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:SecretHandshakeRequest)
pub struct SecretHandshakeRequest {
// message fields
// @@protoc_insertion_point(field:SecretHandshakeRequest.token)
pub token: ::std::string::String,
// @@protoc_insertion_point(field:SecretHandshakeRequest.key)
pub key: ::std::vec::Vec<u8>,
// special fields
// @@protoc_insertion_point(special_field:SecretHandshakeRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a SecretHandshakeRequest {
fn default() -> &'a SecretHandshakeRequest {
<SecretHandshakeRequest as ::protobuf::Message>::default_instance()
}
}
impl SecretHandshakeRequest {
pub fn new() -> SecretHandshakeRequest {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(2);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"token",
|m: &SecretHandshakeRequest| { &m.token },
|m: &mut SecretHandshakeRequest| { &mut m.token },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"key",
|m: &SecretHandshakeRequest| { &m.key },
|m: &mut SecretHandshakeRequest| { &mut m.key },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<SecretHandshakeRequest>(
"SecretHandshakeRequest",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for SecretHandshakeRequest {
const NAME: &'static str = "SecretHandshakeRequest";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
10 => {
self.token = is.read_string()?;
},
18 => {
self.key = is.read_bytes()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if !self.token.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.token);
}
if !self.key.is_empty() {
my_size += ::protobuf::rt::bytes_size(2, &self.key);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if !self.token.is_empty() {
os.write_string(1, &self.token)?;
}
if !self.key.is_empty() {
os.write_bytes(2, &self.key)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> SecretHandshakeRequest {
SecretHandshakeRequest::new()
}
fn clear(&mut self) {
self.token.clear();
self.key.clear();
self.special_fields.clear();
}
fn default_instance() -> &'static SecretHandshakeRequest {
static instance: SecretHandshakeRequest = SecretHandshakeRequest {
token: ::std::string::String::new(),
key: ::std::vec::Vec::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for SecretHandshakeRequest {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("SecretHandshakeRequest").unwrap()).clone()
}
}
impl ::std::fmt::Display for SecretHandshakeRequest {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for SecretHandshakeRequest {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:RegistrationRequest)
pub struct RegistrationRequest {
@@ -39,6 +495,12 @@ pub struct RegistrationRequest {
pub is_fast: bool,
// @@protoc_insertion_point(field:RegistrationRequest.version)
pub version: ::std::string::String,
// @@protoc_insertion_point(field:RegistrationRequest.virtual_ip)
pub virtual_ip: u32,
// @@protoc_insertion_point(field:RegistrationRequest.allow_ip_change)
pub allow_ip_change: bool,
// @@protoc_insertion_point(field:RegistrationRequest.client_secret)
pub client_secret: bool,
// special fields
// @@protoc_insertion_point(special_field:RegistrationRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
@@ -56,7 +518,7 @@ impl RegistrationRequest {
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(5);
let mut fields = ::std::vec::Vec::with_capacity(8);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"token",
@@ -83,6 +545,21 @@ impl RegistrationRequest {
|m: &RegistrationRequest| { &m.version },
|m: &mut RegistrationRequest| { &mut m.version },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"virtual_ip",
|m: &RegistrationRequest| { &m.virtual_ip },
|m: &mut RegistrationRequest| { &mut m.virtual_ip },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"allow_ip_change",
|m: &RegistrationRequest| { &m.allow_ip_change },
|m: &mut RegistrationRequest| { &mut m.allow_ip_change },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"client_secret",
|m: &RegistrationRequest| { &m.client_secret },
|m: &mut RegistrationRequest| { &mut m.client_secret },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<RegistrationRequest>(
"RegistrationRequest",
fields,
@@ -116,6 +593,15 @@ impl ::protobuf::Message for RegistrationRequest {
42 => {
self.version = is.read_string()?;
},
53 => {
self.virtual_ip = is.read_fixed32()?;
},
56 => {
self.allow_ip_change = is.read_bool()?;
},
64 => {
self.client_secret = is.read_bool()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
@@ -143,6 +629,15 @@ impl ::protobuf::Message for RegistrationRequest {
if !self.version.is_empty() {
my_size += ::protobuf::rt::string_size(5, &self.version);
}
if self.virtual_ip != 0 {
my_size += 1 + 4;
}
if self.allow_ip_change != false {
my_size += 1 + 1;
}
if self.client_secret != false {
my_size += 1 + 1;
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
@@ -164,6 +659,15 @@ impl ::protobuf::Message for RegistrationRequest {
if !self.version.is_empty() {
os.write_string(5, &self.version)?;
}
if self.virtual_ip != 0 {
os.write_fixed32(6, self.virtual_ip)?;
}
if self.allow_ip_change != false {
os.write_bool(7, self.allow_ip_change)?;
}
if self.client_secret != false {
os.write_bool(8, self.client_secret)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
@@ -186,6 +690,9 @@ impl ::protobuf::Message for RegistrationRequest {
self.name.clear();
self.is_fast = false;
self.version.clear();
self.virtual_ip = 0;
self.allow_ip_change = false;
self.client_secret = false;
self.special_fields.clear();
}
@@ -196,6 +703,9 @@ impl ::protobuf::Message for RegistrationRequest {
name: ::std::string::String::new(),
is_fast: false,
version: ::std::string::String::new(),
virtual_ip: 0,
allow_ip_change: false,
client_secret: false,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
@@ -237,6 +747,8 @@ pub struct RegistrationResponse {
pub public_ip: u32,
// @@protoc_insertion_point(field:RegistrationResponse.public_port)
pub public_port: u32,
// @@protoc_insertion_point(field:RegistrationResponse.public_ipv6)
pub public_ipv6: ::std::vec::Vec<u8>,
// special fields
// @@protoc_insertion_point(special_field:RegistrationResponse.special_fields)
pub special_fields: ::protobuf::SpecialFields,
@@ -254,7 +766,7 @@ impl RegistrationResponse {
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(7);
let mut fields = ::std::vec::Vec::with_capacity(8);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"virtual_ip",
@@ -291,6 +803,11 @@ impl RegistrationResponse {
|m: &RegistrationResponse| { &m.public_port },
|m: &mut RegistrationResponse| { &mut m.public_port },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_ipv6",
|m: &RegistrationResponse| { &m.public_ipv6 },
|m: &mut RegistrationResponse| { &mut m.public_ipv6 },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<RegistrationResponse>(
"RegistrationResponse",
fields,
@@ -330,6 +847,9 @@ impl ::protobuf::Message for RegistrationResponse {
56 => {
self.public_port = is.read_uint32()?;
},
66 => {
self.public_ipv6 = is.read_bytes()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
@@ -364,6 +884,9 @@ impl ::protobuf::Message for RegistrationResponse {
if self.public_port != 0 {
my_size += ::protobuf::rt::uint32_size(7, self.public_port);
}
if !self.public_ipv6.is_empty() {
my_size += ::protobuf::rt::bytes_size(8, &self.public_ipv6);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
@@ -391,6 +914,9 @@ impl ::protobuf::Message for RegistrationResponse {
if self.public_port != 0 {
os.write_uint32(7, self.public_port)?;
}
if !self.public_ipv6.is_empty() {
os.write_bytes(8, &self.public_ipv6)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
@@ -415,6 +941,7 @@ impl ::protobuf::Message for RegistrationResponse {
self.device_info_list.clear();
self.public_ip = 0;
self.public_port = 0;
self.public_ipv6.clear();
self.special_fields.clear();
}
@@ -427,6 +954,7 @@ impl ::protobuf::Message for RegistrationResponse {
device_info_list: ::std::vec::Vec::new(),
public_ip: 0,
public_port: 0,
public_ipv6: ::std::vec::Vec::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
@@ -460,6 +988,8 @@ pub struct DeviceInfo {
pub virtual_ip: u32,
// @@protoc_insertion_point(field:DeviceInfo.device_status)
pub device_status: u32,
// @@protoc_insertion_point(field:DeviceInfo.client_secret)
pub client_secret: bool,
// special fields
// @@protoc_insertion_point(special_field:DeviceInfo.special_fields)
pub special_fields: ::protobuf::SpecialFields,
@@ -477,7 +1007,7 @@ impl DeviceInfo {
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(3);
let mut fields = ::std::vec::Vec::with_capacity(4);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"name",
@@ -494,6 +1024,11 @@ impl DeviceInfo {
|m: &DeviceInfo| { &m.device_status },
|m: &mut DeviceInfo| { &mut m.device_status },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"client_secret",
|m: &DeviceInfo| { &m.client_secret },
|m: &mut DeviceInfo| { &mut m.client_secret },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<DeviceInfo>(
"DeviceInfo",
fields,
@@ -521,6 +1056,9 @@ impl ::protobuf::Message for DeviceInfo {
24 => {
self.device_status = is.read_uint32()?;
},
32 => {
self.client_secret = is.read_bool()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
@@ -542,6 +1080,9 @@ impl ::protobuf::Message for DeviceInfo {
if self.device_status != 0 {
my_size += ::protobuf::rt::uint32_size(3, self.device_status);
}
if self.client_secret != false {
my_size += 1 + 1;
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
@@ -557,6 +1098,9 @@ impl ::protobuf::Message for DeviceInfo {
if self.device_status != 0 {
os.write_uint32(3, self.device_status)?;
}
if self.client_secret != false {
os.write_bool(4, self.client_secret)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
@@ -577,6 +1121,7 @@ impl ::protobuf::Message for DeviceInfo {
self.name.clear();
self.virtual_ip = 0;
self.device_status = 0;
self.client_secret = false;
self.special_fields.clear();
}
@@ -585,6 +1130,7 @@ impl ::protobuf::Message for DeviceInfo {
name: ::std::string::String::new(),
virtual_ip: 0,
device_status: 0,
client_secret: false,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
@@ -767,6 +1313,8 @@ pub struct PunchInfo {
pub local_ip: u32,
// @@protoc_insertion_point(field:PunchInfo.local_port)
pub local_port: u32,
// @@protoc_insertion_point(field:PunchInfo.public_ipv6_list)
pub public_ipv6_list: ::std::vec::Vec<::std::vec::Vec<u8>>,
// special fields
// @@protoc_insertion_point(special_field:PunchInfo.special_fields)
pub special_fields: ::protobuf::SpecialFields,
@@ -784,7 +1332,7 @@ impl PunchInfo {
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(7);
let mut fields = ::std::vec::Vec::with_capacity(8);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"public_ip_list",
@@ -821,6 +1369,11 @@ impl PunchInfo {
|m: &PunchInfo| { &m.local_port },
|m: &mut PunchInfo| { &mut m.local_port },
));
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"public_ipv6_list",
|m: &PunchInfo| { &m.public_ipv6_list },
|m: &mut PunchInfo| { &mut m.public_ipv6_list },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<PunchInfo>(
"PunchInfo",
fields,
@@ -863,6 +1416,9 @@ impl ::protobuf::Message for PunchInfo {
64 => {
self.local_port = is.read_uint32()?;
},
74 => {
self.public_ipv6_list.push(is.read_bytes()?);
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
@@ -894,6 +1450,9 @@ impl ::protobuf::Message for PunchInfo {
if self.local_port != 0 {
my_size += ::protobuf::rt::uint32_size(8, self.local_port);
}
for value in &self.public_ipv6_list {
my_size += ::protobuf::rt::bytes_size(9, &value);
};
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
@@ -921,6 +1480,9 @@ impl ::protobuf::Message for PunchInfo {
if self.local_port != 0 {
os.write_uint32(8, self.local_port)?;
}
for v in &self.public_ipv6_list {
os.write_bytes(9, &v)?;
};
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
@@ -945,6 +1507,7 @@ impl ::protobuf::Message for PunchInfo {
self.reply = false;
self.local_ip = 0;
self.local_port = 0;
self.public_ipv6_list.clear();
self.special_fields.clear();
}
@@ -957,6 +1520,7 @@ impl ::protobuf::Message for PunchInfo {
reply: false,
local_ip: 0,
local_port: 0,
public_ipv6_list: ::std::vec::Vec::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
@@ -1035,29 +1599,41 @@ impl PunchNatType {
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\rmessage.proto\"\x8f\x01\n\x13RegistrationRequest\x12\x14\n\x05token\
\x18\x01\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\tR\
\x08deviceId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\x07\
is_fast\x18\x04\x20\x01(\x08R\x06isFast\x12\x18\n\x07version\x18\x05\x20\
\x01(\tR\x07version\"\x92\x02\n\x14RegistrationResponse\x12\x1d\n\nvirtu\
al_ip\x18\x01\x20\x01(\x07R\tvirtualIp\x12'\n\x0fvirtual_gateway\x18\x02\
\x20\x01(\x07R\x0evirtualGateway\x12'\n\x0fvirtual_netmask\x18\x03\x20\
\x01(\x07R\x0evirtualNetmask\x12\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05e\
poch\x125\n\x10device_info_list\x18\x05\x20\x03(\x0b2\x0b.DeviceInfoR\
\x0edeviceInfoList\x12\x1b\n\tpublic_ip\x18\x06\x20\x01(\x07R\x08publicI\
p\x12\x1f\n\x0bpublic_port\x18\x07\x20\x01(\rR\npublicPort\"d\n\nDeviceI\
nfo\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\x12\x1d\n\nvirtual_ip\
\x18\x02\x20\x01(\x07R\tvirtualIp\x12#\n\rdevice_status\x18\x03\x20\x01(\
\rR\x0cdeviceStatus\"Y\n\nDeviceList\x12\x14\n\x05epoch\x18\x01\x20\x01(\
\rR\x05epoch\x125\n\x10device_info_list\x18\x02\x20\x03(\x0b2\x0b.Device\
InfoR\x0edeviceInfoList\"\xf8\x01\n\tPunchInfo\x12$\n\x0epublic_ip_list\
\x18\x02\x20\x03(\x07R\x0cpublicIpList\x12\x1f\n\x0bpublic_port\x18\x03\
\x20\x01(\rR\npublicPort\x12*\n\x11public_port_range\x18\x04\x20\x01(\rR\
\x0fpublicPortRange\x12(\n\x08nat_type\x18\x05\x20\x01(\x0e2\r.PunchNatT\
ypeR\x07natType\x12\x14\n\x05reply\x18\x06\x20\x01(\x08R\x05reply\x12\
\x19\n\x08local_ip\x18\x07\x20\x01(\x07R\x07localIp\x12\x1d\n\nlocal_por\
t\x18\x08\x20\x01(\rR\tlocalPort*'\n\x0cPunchNatType\x12\r\n\tSymmetric\
\x10\0\x12\x08\n\x04Cone\x10\x01b\x06proto3\
\n\rmessage.proto\"D\n\x10HandshakeRequest\x12\x18\n\x07version\x18\x01\
\x20\x01(\tR\x07version\x12\x16\n\x06secret\x18\x02\x20\x01(\x08R\x06sec\
ret\"\x83\x01\n\x11HandshakeResponse\x12\x18\n\x07version\x18\x01\x20\
\x01(\tR\x07version\x12\x16\n\x06secret\x18\x02\x20\x01(\x08R\x06secret\
\x12\x1d\n\npublic_key\x18\x03\x20\x01(\x0cR\tpublicKey\x12\x1d\n\nkey_f\
inger\x18\x04\x20\x01(\tR\tkeyFinger\"@\n\x16SecretHandshakeRequest\x12\
\x14\n\x05token\x18\x01\x20\x01(\tR\x05token\x12\x10\n\x03key\x18\x02\
\x20\x01(\x0cR\x03key\"\xfb\x01\n\x13RegistrationRequest\x12\x14\n\x05to\
ken\x18\x01\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\t\
R\x08deviceId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\
\x07is_fast\x18\x04\x20\x01(\x08R\x06isFast\x12\x18\n\x07version\x18\x05\
\x20\x01(\tR\x07version\x12\x1d\n\nvirtual_ip\x18\x06\x20\x01(\x07R\tvir\
tualIp\x12&\n\x0fallow_ip_change\x18\x07\x20\x01(\x08R\rallowIpChange\
\x12#\n\rclient_secret\x18\x08\x20\x01(\x08R\x0cclientSecret\"\xb3\x02\n\
\x14RegistrationResponse\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tvi\
rtualIp\x12'\n\x0fvirtual_gateway\x18\x02\x20\x01(\x07R\x0evirtualGatewa\
y\x12'\n\x0fvirtual_netmask\x18\x03\x20\x01(\x07R\x0evirtualNetmask\x12\
\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\
\x18\x05\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\x12\x1b\n\tpubl\
ic_ip\x18\x06\x20\x01(\x07R\x08publicIp\x12\x1f\n\x0bpublic_port\x18\x07\
\x20\x01(\rR\npublicPort\x12\x1f\n\x0bpublic_ipv6\x18\x08\x20\x01(\x0cR\
\npublicIpv6\"\x89\x01\n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\x01(\
\tR\x04name\x12\x1d\n\nvirtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\x12#\
\n\rdevice_status\x18\x03\x20\x01(\rR\x0cdeviceStatus\x12#\n\rclient_sec\
ret\x18\x04\x20\x01(\x08R\x0cclientSecret\"Y\n\nDeviceList\x12\x14\n\x05\
epoch\x18\x01\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x02\
\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xa2\x02\n\tPunchInfo\
\x12$\n\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIpList\x12\x1f\
\n\x0bpublic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11public_port_\
range\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12(\n\x08nat_type\x18\x05\
\x20\x01(\x0e2\r.PunchNatTypeR\x07natType\x12\x14\n\x05reply\x18\x06\x20\
\x01(\x08R\x05reply\x12\x19\n\x08local_ip\x18\x07\x20\x01(\x07R\x07local\
Ip\x12\x1d\n\nlocal_port\x18\x08\x20\x01(\rR\tlocalPort\x12(\n\x10public\
_ipv6_list\x18\t\x20\x03(\x0cR\x0epublicIpv6List*'\n\x0cPunchNatType\x12\
\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\x10\x01b\x06proto3\
";
/// `FileDescriptorProto` object which was a source for this generated file
@@ -1075,7 +1651,10 @@ pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor {
file_descriptor.get(|| {
let generated_file_descriptor = generated_file_descriptor_lazy.get(|| {
let mut deps = ::std::vec::Vec::with_capacity(0);
let mut messages = ::std::vec::Vec::with_capacity(5);
let mut messages = ::std::vec::Vec::with_capacity(8);
messages.push(HandshakeRequest::generated_message_descriptor_data());
messages.push(HandshakeResponse::generated_message_descriptor_data());
messages.push(SecretHandshakeRequest::generated_message_descriptor_data());
messages.push(RegistrationRequest::generated_message_descriptor_data());
messages.push(RegistrationResponse::generated_message_descriptor_data());
messages.push(DeviceInfo::generated_message_descriptor_data());
+268
View File
@@ -0,0 +1,268 @@
use std::{fmt, io};
pub const ENCRYPTION_RESERVED: usize = 32;
/* aes_gcm加密数据体
0 15 31
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据体 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| random(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| tag(32) |
| tag(32) |
| tag(32) |
| tag(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| finger(32) |
| finger(32) |
| finger(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
注:finger用于快速校验数据是否被修改,上层可使用token、协议头参与计算finger
确保服务端和客户端都能感知修改(服务端不能解密也能校验指纹)
*/
pub struct SecretBody<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> SecretBody<B> {
pub fn new(buffer: B) -> io::Result<SecretBody<B>> {
let len = buffer.as_ref().len();
// 不能大于udp最大载荷长度
if len < 32 || len > 65535 - 20 - 8 - 12 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"length overflow",
));
}
Ok(SecretBody { buffer })
}
pub fn data(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 32;
&self.buffer.as_ref()[..end]
}
pub fn random(&self) -> u32 {
let end = self.buffer.as_ref().len() - 16 - 12;
u32::from_be_bytes(self.buffer.as_ref()[end - 4..end].try_into().unwrap())
}
pub fn body(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 16 - 12;
&self.buffer.as_ref()[..end]
}
pub fn tag(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 12;
&self.buffer.as_ref()[end - 16..end]
}
/// 数据部分+tag部分
pub fn en_body(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 12;
&self.buffer.as_ref()[..end]
}
pub fn finger(&self) -> &[u8] {
let end = self.buffer.as_ref().len();
&self.buffer.as_ref()[end - 12..end]
}
pub fn buffer(&self) -> &[u8] {
self.buffer.as_ref()
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> SecretBody<B> {
pub fn set_data(&mut self, data: &[u8]) -> io::Result<()> {
let end = self.buffer.as_ref().len() - 32;
if end - 4 != data.len() {
return Err(io::Error::new(io::ErrorKind::InvalidData, "end-4 != data.len"));
}
self.buffer.as_mut()[..end].copy_from_slice(data);
Ok(())
}
pub fn set_random(&mut self, random: u32) {
let end = self.buffer.as_ref().len() - 16 - 12;
self.buffer.as_mut()[end - 4..end].copy_from_slice(&random.to_be_bytes());
}
pub fn set_tag(&mut self, tag: &[u8]) -> io::Result<()> {
if tag.len() != 16 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "tag.len != 16"));
}
let end = self.buffer.as_ref().len() - 12;
self.buffer.as_mut()[end - 16..end].copy_from_slice(tag);
Ok(())
}
pub fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> {
if finger.len() != 12 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "finger.len != 12"));
}
let end = self.buffer.as_ref().len();
self.buffer.as_mut()[end - 12..end].copy_from_slice(finger);
Ok(())
}
pub fn data_mut(&mut self) -> &mut [u8] {
let end = self.buffer.as_ref().len() - 32;
&mut self.buffer.as_mut()[..end]
}
/// 数据部分
pub fn body_mut(&mut self) -> &mut [u8] {
let end = self.buffer.as_ref().len() - 12 - 16;
&mut self.buffer.as_mut()[..end]
}
pub fn tag_mut(&mut self) -> &mut [u8] {
let end = self.buffer.as_ref().len() - 12;
&mut self.buffer.as_mut()[end - 16..end]
}
/// 数据部分+tag部分
pub fn en_body_mut(&mut self) -> &mut [u8] {
let end = self.buffer.as_ref().len() - 12;
&mut self.buffer.as_mut()[..end]
}
pub fn buffer_mut(&mut self) -> &mut [u8] {
self.buffer.as_mut()
}
}
impl<B: AsRef<[u8]>> fmt::Debug for SecretBody<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SecretBody")
.field("random", &self.random())
.field("body", &self.body())
.field("tag", &self.tag())
.finish()
}
}
/* aes_cbc加密数据体
0 15 31
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据体 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| random(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| finger(32) |
| finger(32) |
| finger(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
注:finger用于快速校验数据是否被修改,上层可使用token、协议头参与计算finger
确保服务端和客户端都能感知修改(服务端不能解密也能校验指纹)
*/
pub struct AesCbcSecretBody<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> AesCbcSecretBody<B> {
pub fn new(buffer: B) -> io::Result<AesCbcSecretBody<B>> {
let len = buffer.as_ref().len();
// 不能大于udp最大载荷长度
if len < 16 || len > 65535 - 20 - 8 - 12 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"length overflow",
));
}
Ok(AesCbcSecretBody { buffer })
}
pub fn en_body(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 12;
&self.buffer.as_ref()[..end]
}
pub fn finger(&self) -> &[u8] {
let end = self.buffer.as_ref().len();
&self.buffer.as_ref()[end - 12..end]
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> AesCbcSecretBody<B> {
pub fn set_random(&mut self, random: u32) {
let end = self.buffer.as_ref().len() - 12;
self.buffer.as_mut()[end - 4..end].copy_from_slice(&random.to_be_bytes());
}
pub fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> {
if finger.len() != 12 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "finger.len != 12"));
}
let end = self.buffer.as_ref().len();
self.buffer.as_mut()[end - 12..end].copy_from_slice(finger);
Ok(())
}
pub fn en_body_mut(&mut self) -> &mut [u8] {
let end = self.buffer.as_ref().len() - 12;
&mut self.buffer.as_mut()[..end]
}
}
/* rsa加密数据体
0 15 31
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据体(n) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| random(32) |
| random(32) |
| random(32) |
| random(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| finger(32) |
| finger(32) |
| finger(32) |
| finger(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
pub struct RsaSecretBody<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> RsaSecretBody<B> {
pub fn new(buffer: B) -> io::Result<RsaSecretBody<B>> {
let len = buffer.as_ref().len();
// 不能大于udp最大载荷长度
if len < 32 || len > 65535 - 20 - 8 - 12 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"length overflow",
));
}
Ok(RsaSecretBody { buffer })
}
pub fn data(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 32;
&self.buffer.as_ref()[..end]
}
pub fn random(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 16;
&self.buffer.as_ref()[end - 16..end]
}
pub fn body(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 16;
&self.buffer.as_ref()[..end]
}
pub fn finger(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 16;
&self.buffer.as_ref()[end..]
}
pub fn buffer(&self) -> &[u8] {
&self.buffer.as_ref()
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> RsaSecretBody<B> {
pub fn set_random(&mut self, random: &[u8]) -> io::Result<()> {
if random.len() != 16 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "random.len != 16"));
}
let end = self.buffer.as_ref().len() - 16;
self.buffer.as_mut()[end - 16..end].copy_from_slice(random);
Ok(())
}
pub fn random_mut(&mut self) -> &mut [u8] {
let end = self.buffer.as_ref().len() - 16;
&mut self.buffer.as_mut()[end - 16..end]
}
pub fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> {
if finger.len() != 16 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "finger.len != 16"));
}
let end = self.buffer.as_ref().len();
self.buffer.as_mut()[end - 16..end].copy_from_slice(finger);
Ok(())
}
}
@@ -1,4 +1,5 @@
use std::{fmt, io};
use std::net::Ipv4Addr;
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Protocol {
@@ -17,6 +18,9 @@ pub enum Protocol {
PunchRequest,
/// 打洞响应
PunchResponse,
///获取对端看到的地址
AddrRequest,
AddrResponse,
Unknown(u8),
}
@@ -27,6 +31,8 @@ impl From<u8> for Protocol {
2 => Protocol::Pong,
3 => Protocol::PunchRequest,
4 => Protocol::PunchResponse,
5 => Protocol::AddrRequest,
6 => Protocol::AddrResponse,
val => Protocol::Unknown(val),
}
}
@@ -39,6 +45,8 @@ impl Into<u8> for Protocol {
Protocol::Pong => 2,
Protocol::PunchRequest => 3,
Protocol::PunchResponse => 4,
Protocol::AddrRequest => 5,
Protocol::AddrResponse => 6,
Protocol::Unknown(val) => val,
}
}
@@ -49,6 +57,8 @@ pub enum ControlPacket<B> {
PongPacket(PongPacket<B>),
PunchRequest,
PunchResponse,
AddrRequest,
AddrResponse(AddrPacket<B>),
}
impl<B: AsRef<[u8]>> ControlPacket<B> {
@@ -58,6 +68,8 @@ impl<B: AsRef<[u8]>> ControlPacket<B> {
Protocol::Pong => Ok(ControlPacket::PongPacket(PongPacket::new(buffer)?)),
Protocol::PunchRequest => Ok(ControlPacket::PunchRequest),
Protocol::PunchResponse => Ok(ControlPacket::PunchResponse),
Protocol::AddrRequest => Ok(ControlPacket::AddrRequest),
Protocol::AddrResponse => Ok(ControlPacket::AddrResponse(AddrPacket::new(buffer)?)),
Protocol::Unknown(_) => Err(io::Error::new(io::ErrorKind::InvalidData, "Unsupported")),
}
}
@@ -106,3 +118,42 @@ impl<B: AsRef<[u8]>> fmt::Debug for PingPacket<B> {
.finish()
}
}
pub struct AddrPacket<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> AddrPacket<B> {
pub fn new(buffer: B) -> io::Result<AddrPacket<B>> {
let len = buffer.as_ref().len();
if len != 6 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "len != 6"));
}
Ok(AddrPacket { buffer })
}
pub fn ipv4(&self) -> Ipv4Addr {
let buf = self.buffer.as_ref();
Ipv4Addr::new(buf[0], buf[1], buf[2], buf[3])
}
pub fn port(&self) -> u16 {
u16::from_be_bytes(self.buffer.as_ref()[4..6].try_into().unwrap())
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> AddrPacket<B> {
pub fn set_ipv4(&mut self, ip: Ipv4Addr) {
self.buffer.as_mut()[..4].copy_from_slice(&ip.octets())
}
pub fn set_port(&mut self, port: u16) {
self.buffer.as_mut()[4..6].copy_from_slice(&port.to_be_bytes())
}
}
impl<B: AsRef<[u8]>> fmt::Debug for AddrPacket<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("AddrPacket")
.field("ipv4", &self.ipv4())
.field("port", &self.port())
.finish()
}
}
@@ -5,6 +5,9 @@ pub enum Protocol {
TokenError,
Disconnect,
AddressExhausted,
IpAlreadyExists,
InvalidIp,
NoKey,
Other(u8),
}
@@ -14,6 +17,9 @@ impl From<u8> for Protocol {
1 => Self::TokenError,
2 => Self::Disconnect,
3 => Self::AddressExhausted,
4 => Self::IpAlreadyExists,
5 => Self::InvalidIp,
6 => Self::NoKey,
val => Self::Other(val),
}
}
@@ -25,6 +31,9 @@ impl Into<u8> for Protocol {
Protocol::TokenError => 1,
Protocol::Disconnect => 2,
Protocol::AddressExhausted => 3,
Protocol::IpAlreadyExists => 4,
Protocol::InvalidIp => 5,
Protocol::NoKey => 6,
Protocol::Other(val) => val,
}
}
@@ -34,6 +43,9 @@ pub enum InErrorPacket<B> {
TokenError,
Disconnect,
AddressExhausted,
IpAlreadyExists,
InvalidIp,
NoKey,
OtherError(ErrorPacket<B>),
}
@@ -43,6 +55,9 @@ impl<B: AsRef<[u8]>> InErrorPacket<B> {
Protocol::TokenError => Ok(InErrorPacket::TokenError),
Protocol::Disconnect => Ok(InErrorPacket::Disconnect),
Protocol::AddressExhausted => Ok(InErrorPacket::AddressExhausted),
Protocol::IpAlreadyExists => Ok(InErrorPacket::IpAlreadyExists),
Protocol::InvalidIp => Ok(InErrorPacket::InvalidIp),
Protocol::NoKey => Ok(InErrorPacket::NoKey),
Protocol::Other(_) => Ok(InErrorPacket::OtherError(ErrorPacket::new(buffer)?)),
}
}
@@ -3,8 +3,6 @@ use std::net::Ipv4Addr;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Protocol {
Icmp,
Igmp,
Ipv4,
Ipv4Broadcast,
Unknown(u8),
@@ -13,8 +11,6 @@ pub enum Protocol {
impl From<u8> for Protocol {
fn from(value: u8) -> Self {
match value {
1 => Protocol::Icmp,
2 => Protocol::Igmp,
4 => Protocol::Ipv4,
201 => Protocol::Ipv4Broadcast,
val => Protocol::Unknown(val),
@@ -25,8 +21,6 @@ impl From<u8> for Protocol {
impl Into<u8> for Protocol {
fn into(self) -> u8 {
match self {
Protocol::Icmp => 1,
Protocol::Igmp => 2,
Protocol::Ipv4 => 4,
Protocol::Ipv4Broadcast => 201,
Protocol::Unknown(val) => val,
@@ -34,18 +28,18 @@ impl Into<u8> for Protocol {
}
}
pub struct BroadcastPacketEnd<B> {
pub struct BroadcastPacket<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
impl<B: AsRef<[u8]>> BroadcastPacket<B> {
pub fn unchecked(buffer: B) -> Self {
Self { buffer }
}
pub fn new(buffer: B) -> io::Result<Self> {
let len = buffer.as_ref().len();
let packet = Self::unchecked(buffer);
if len < 1 || packet.len() != len {
if len < 2 + 4 || packet.addr_num() == 0 {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"InvalidData",
@@ -56,31 +50,36 @@ impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
}
}
impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
pub fn len(&self) -> usize {
1 + self.num() as usize * 4
}
pub fn num(&self) -> u8 {
let len = self.buffer.as_ref().len();
self.buffer.as_ref()[len - 1]
impl<B: AsRef<[u8]>> BroadcastPacket<B> {
pub fn addr_num(&self) -> u8 {
self.buffer.as_ref()[1]
}
/// 已经发送给了这些地址
/// 从尾往头拿
pub fn addresses(&self) -> Vec<Ipv4Addr> {
let num = self.num() as usize;
let num = self.addr_num() as usize;
let mut list = Vec::with_capacity(num);
let buf = self.buffer.as_ref();
let mut offset = buf.len() + 4 - 2;
let mut offset = 1;
for _ in 0..num {
offset -= 4;
list.push(Ipv4Addr::new(buf[offset - 3], buf[offset - 2], buf[offset - 1], buf[offset]));
list.push(Ipv4Addr::new(buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3]));
offset += 4;
}
list
}
pub fn data(&self) -> io::Result<&[u8]> {
let start = 1 + self.addr_num() as usize * 4;
if start > self.buffer.as_ref().len() {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"InvalidData",
))
} else {
Ok(&self.buffer.as_ref()[start..])
}
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> BroadcastPacketEnd<B> {
/// 从头往尾放
impl<B: AsRef<[u8]> + AsMut<[u8]>> BroadcastPacket<B> {
pub fn set_address(&mut self, addr: &[Ipv4Addr]) -> io::Result<()> {
let buf = self.buffer.as_mut();
if buf.len() < 1 + addr.len() * 4 || addr.len() > u8::MAX as usize {
@@ -89,15 +88,28 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> BroadcastPacketEnd<B> {
"InvalidData",
))
} else {
let mut offset = 0;
buf[0] = addr.len() as u8;
let mut offset = 1;
for ip in addr {
buf[offset..offset + 4].copy_from_slice(&ip.octets());
offset += 4;
}
self.buffer.as_mut()[offset] = addr.len() as u8;
Ok(())
}
}
pub fn set_data(&mut self, data: &[u8]) -> io::Result<()> {
let num = self.addr_num() as usize;
let start = 1 + 4 * num;
let buf = self.buffer.as_mut();
if start > buf.len() || start + data.len() != buf.len() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"InvalidData",
));
}
buf[start..].copy_from_slice(data);
Ok(())
}
}
@@ -1,11 +1,12 @@
use std::net::Ipv4Addr;
use std::{fmt, io};
use std::net::Ipv4Addr;
use crate::protocol::body::ENCRYPTION_RESERVED;
/*
0 15 31
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| p|unused| (4) | (8) | (8) | ttl(4) | (4) |
|e |s |u |u| (4) | (8) | (8) | ttl(4) | (4) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ip地址(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -13,8 +14,11 @@ use std::{fmt, io};
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
e为是否加密标志s为服务端通信包标志u未使用
*/
pub const HEAD_LEN: usize = 12;
pub mod body;
pub mod control_packet;
pub mod error_packet;
pub mod service_packet;
@@ -91,33 +95,68 @@ pub const MAX_SOURCE: u8 = 0b11110000;
#[derive(Copy, Clone)]
pub struct NetPacket<B> {
data_len: usize,
buffer: B,
}
impl<B: AsRef<[u8]>> NetPacket<B> {
pub fn new(buffer: B) -> io::Result<NetPacket<B>> {
let len = buffer.as_ref().len();
// 不能大于udp最大载荷长度
if len < 12 || len > 65535 - 20 - 8 {
let data_len = buffer.as_ref().len();
Self::new0(data_len, buffer)
}
pub fn new_encrypt(buffer: B) -> io::Result<NetPacket<B>> {
if 12 + ENCRYPTION_RESERVED > buffer.as_ref().len() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"length overflow",
));
}
Ok(NetPacket { buffer })
//加密需要预留32字节
let data_len = buffer.as_ref().len() - ENCRYPTION_RESERVED;
Self::new0(data_len, buffer)
}
pub fn new0(data_len: usize, buffer: B) -> io::Result<NetPacket<B>> {
if data_len > buffer.as_ref().len() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"length overflow",
));
}
// 不能大于udp最大载荷长度
if data_len < 12 || buffer.as_ref().len() > 65535 - 20 - 8 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"length overflow",
));
}
Ok(NetPacket { data_len, buffer })
}
pub fn buffer(&self) -> &[u8] {
&self.buffer.as_ref()[..self.data_len]
}
pub fn raw_buffer(&self) -> &[u8] {
self.buffer.as_ref()
}
pub fn data_len(&self) -> usize {
self.data_len
}
pub fn reserve(&self) -> usize {
self.buffer.as_ref().len() - self.data_len
}
pub fn into_buffer(self) -> B {
self.buffer
}
}
impl<B: AsRef<[u8]>> NetPacket<B> {
/// 数据加密
pub fn is_encrypt(&self) -> bool {
self.buffer.as_ref()[0] & 0x80 == 0x80
}
/// 网关通信的标识
pub fn is_gateway(&self) -> bool {
self.buffer.as_ref()[0] & 0x50 == 0x50
}
pub fn version(&self) -> Version {
Version::from(self.buffer.as_ref()[0] & 0x0F)
}
@@ -142,7 +181,7 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
Ipv4Addr::from(tmp)
}
pub fn payload(&self) -> &[u8] {
&self.buffer.as_ref()[12..]
&self.buffer.as_ref()[12..self.data_len]
}
}
@@ -157,6 +196,13 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0x7F
};
}
pub fn set_gateway_flag(&mut self, is_gateway: bool) {
if is_gateway {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x50
} else {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF
};
}
pub fn set_version(&mut self, version: Version) {
let v: u8 = version.into();
self.buffer.as_mut()[0] = (self.buffer.as_ref()[0] & 0xF0) | (0x0F & v);
@@ -182,11 +228,25 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
pub fn set_destination(&mut self, destination: Ipv4Addr) {
self.buffer.as_mut()[8..12].copy_from_slice(&destination.octets());
}
pub fn set_payload(&mut self, payload: &[u8]) {
self.buffer.as_mut()[12..payload.len() + 12].copy_from_slice(payload);
pub fn set_payload(&mut self, payload: &[u8]) -> io::Result<()> {
if self.data_len - 12 != payload.len() {
return Err(io::Error::new(io::ErrorKind::InvalidData, "data_len - 12 != payload.len"));
}
self.buffer.as_mut()[12..self.data_len].copy_from_slice(payload);
Ok(())
}
pub fn payload_mut(&mut self) -> &mut [u8] {
&mut self.buffer.as_mut()[12..]
&mut self.buffer.as_mut()[12..self.data_len]
}
pub fn set_data_len(&mut self, data_len: usize) -> io::Result<()> {
if data_len > self.buffer.as_ref().len() || data_len < 12 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "data_len invalid"));
}
self.data_len = data_len;
Ok(())
}
pub fn set_data_len_max(&mut self) {
self.data_len = self.buffer.as_ref().len();
}
}
@@ -194,6 +254,8 @@ impl<B: AsRef<[u8]>> fmt::Debug for NetPacket<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NetPacket")
.field("version", &self.version())
.field("gateway", &self.is_gateway())
.field("encrypt", &self.is_encrypt())
.field("protocol", &self.protocol())
.field("transport_protocol", &self.transport_protocol())
.field("ttl", &self.ttl())
@@ -8,6 +8,11 @@ pub enum Protocol {
PollDeviceList,
/// 推送设备列表
PushDeviceList,
/// 和服务端握手
HandshakeRequest,
HandshakeResponse,
SecretHandshakeRequest,
SecretHandshakeResponse,
Unknown(u8),
}
@@ -18,6 +23,10 @@ impl From<u8> for Protocol {
2 => Self::RegistrationResponse,
3 => Self::PollDeviceList,
4 => Self::PushDeviceList,
5 => Self::HandshakeRequest,
6 => Self::HandshakeResponse,
7 => Self::SecretHandshakeRequest,
8 => Self::SecretHandshakeResponse,
val => Self::Unknown(val),
}
}
@@ -30,6 +39,10 @@ impl Into<u8> for Protocol {
Self::RegistrationResponse => 2,
Self::PollDeviceList => 3,
Self::PushDeviceList => 4,
Self::HandshakeRequest => 5,
Self::HandshakeResponse => 6,
Self::SecretHandshakeRequest => 7,
Self::SecretHandshakeResponse => 8,
Self::Unknown(val) => val,
}
}
@@ -11,10 +11,14 @@ impl DeviceWriter {
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> {
let mut config = tun::Configuration::default();
let broadcast_address = (!u32::from_be_bytes(netmask.octets()))
| u32::from_be_bytes(gateway.octets());
let broadcast_address = Ipv4Addr::from(broadcast_address);
config
.destination(gateway)
.address(address)
.netmask(netmask)
.broadcast(broadcast_address)
// .queues(2)
.up();
let mut dev = self.lock.lock();
@@ -58,12 +62,15 @@ pub fn create_device(device_type: DeviceType,
mtu: u16,
) -> io::Result<(DeviceWriter, DeviceReader,DriverInfo)> {
let mut config = tun::Configuration::default();
let broadcast_address = (!u32::from_be_bytes(netmask.octets()))
| u32::from_be_bytes(gateway.octets());
let broadcast_address = Ipv4Addr::from(broadcast_address);
config
.destination(gateway)
.address(address)
.netmask(netmask)
.mtu(mtu.into())
.broadcast(broadcast_address)
// .queues(2) 用多个队列有兼容性问题
.up();
match device_type {
@@ -10,9 +10,9 @@ use packet::ethernet::packet::EthernetPacket;
use win_tun_tap::{IFace, TapDevice, TunDevice};
use crate::tun_tap_device::{DriverInfo, DeviceType};
pub const TUN_INTERFACE_NAME: &str = "Switch-Tun-V1";
pub const TUN_POOL_NAME: &str = "Switch-Tun-V1";
pub const TAP_INTERFACE_NAME: &str = "Switch-Tap-V1";
pub const TUN_INTERFACE_NAME: &str = "Vnt-Tun-V1";
pub const TUN_POOL_NAME: &str = "Vnt-Tun-V1";
pub const TAP_INTERFACE_NAME: &str = "Vnt-Tap-V1";
pub enum Device {
Tun(TunDevice),