Compare commits

..
18 Commits
Author SHA1 Message Date
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
26 changed files with 463 additions and 222 deletions
+16 -2
View File
@@ -40,36 +40,50 @@ jobs:
include: include:
- TARGET: i686-unknown-linux-musl # test in an alpine container on a mac - TARGET: i686-unknown-linux-musl # test in an alpine container on a mac
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: normal
- TARGET: x86_64-unknown-linux-gnu # tested in a debian container on a mac - TARGET: x86_64-unknown-linux-gnu # tested in a debian container on a mac
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: x86_64-unknown-linux-musl # test in an alpine container on a mac - TARGET: x86_64-unknown-linux-musl # test in an alpine container on a mac
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: aarch64-unknown-linux-gnu # tested on aws t4g.nano - TARGET: aarch64-unknown-linux-gnu # tested on aws t4g.nano
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: aarch64-unknown-linux-musl # tested on aws t4g.nano in alpine container - TARGET: aarch64-unknown-linux-musl # tested on aws t4g.nano in alpine container
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: normal
- TARGET: armv7-unknown-linux-gnueabihf # raspberry pi 2-3-4, not tested - TARGET: armv7-unknown-linux-gnueabihf # raspberry pi 2-3-4, not tested
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested - TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: normal
- TARGET: arm-unknown-linux-gnueabihf # raspberry pi 0-1, not tested - TARGET: arm-unknown-linux-gnueabihf # raspberry pi 0-1, not tested
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested - TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested
OS: ubuntu-latest OS: ubuntu-latest
FEATURES: normal
- TARGET: x86_64-apple-darwin # tested on a mac, is not properly signed so there are security warnings - TARGET: x86_64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
OS: macos-latest OS: macos-latest
FEATURES: ring-cipher
- TARGET: aarch64-apple-darwin # tested on a mac, is not properly signed so there are security warnings - TARGET: aarch64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
OS: macos-latest OS: macos-latest
FEATURES: ring-cipher
- TARGET: i686-pc-windows-msvc # tested on a windows machine - TARGET: i686-pc-windows-msvc # tested on a windows machine
OS: windows-latest OS: windows-latest
FEATURES: ring-cipher
- TARGET: x86_64-pc-windows-msvc # tested on a windows machine - TARGET: x86_64-pc-windows-msvc # tested on a windows machine
OS: windows-latest OS: windows-latest
FEATURES: ring-cipher
# needs: test # needs: test
runs-on: ${{ matrix.OS }} runs-on: ${{ matrix.OS }}
env: env:
NAME: vnt-cli # change with the name of your project NAME: vnt-cli # change with the name of your project
TARGET: ${{ matrix.TARGET }} TARGET: ${{ matrix.TARGET }}
OS: ${{ matrix.OS }} OS: ${{ matrix.OS }}
FEATURES: ${{ matrix.FEATURES }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Init submodules - name: Init submodules
@@ -88,7 +102,7 @@ jobs:
# dependencies are only needed on ubuntu as that's the only place where # dependencies are only needed on ubuntu as that's the only place where
# we make cross-compilation # we make cross-compilation
if [[ $OS =~ ^ubuntu.*$ ]]; then if [[ $OS =~ ^ubuntu.*$ ]]; then
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools
fi fi
# some additional configuration for cross-compilation on linux # some additional configuration for cross-compilation on linux
cat >>~/.cargo/config <<EOF cat >>~/.cargo/config <<EOF
@@ -108,7 +122,7 @@ jobs:
- name: Install rust target - name: Install rust target
run: rustup target add $TARGET run: rustup target add $TARGET
- name: Run build - name: Run build
run: cargo build --package vnt-cli --release --verbose --target $TARGET run: cargo build --package vnt-cli --release --verbose --target $TARGET --features $FEATURES
- name: List target - name: List target
run: find ./target run: find ./target
- name: Compress - name: Compress
+10
View File
@@ -116,9 +116,19 @@ vnt默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突
3. 将对应的wintun.dll放到和vnt-cli同目录下(或者放到C盘Windows目录下) 3. 将对应的wintun.dll放到和vnt-cli同目录下(或者放到C盘Windows目录下)
4. 再次启动vnt-cli 4. 再次启动vnt-cli
#### 问题3: 丢包严重,或是不能正常组网通信
##### 可能原因:
某些宽带下(比如广电宽带)UDP丢包严重
##### 解决方法:
1. 使用TCP模式中继转发(vnt-cli增加--tcp参数)
2. 如果p2p后效果很差,可以选择禁用p2p(vnt-cli增加--relay参数)
</details> </details>
### 交流群 ### 交流群
QQ:1034868233 QQ:1034868233
### 其他
可使用社区小伙伴搭建的中继服务器
1. -s vnt.8443.eu.org:29871
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "common" name = "common"
version = "1.1.1" version = "1.1.2"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+38 -9
View File
@@ -35,16 +35,45 @@ pub fn ips_parse(ips: &Vec<String>) -> Result<Vec<(u32, u32, Ipv4Addr)>, String>
} else { } else {
return Err("not ipv4".to_string()); return Err("not ipv4".to_string());
}; };
let mask = if let Ok(m) = mask.parse::<u32>() { let mask = to_ip(mask)?;
let mut mask = 0 as u32;
for i in 0..m {
mask = mask | (1 << (31 - i));
}
mask
} else {
return Err("not netmask".to_string());
};
in_ips_c.push((u32::from_be_bytes(dest.octets()), mask, ip)); in_ips_c.push((u32::from_be_bytes(dest.octets()), mask, ip));
} }
Ok(in_ips_c) 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())
}
}
+7 -4
View File
@@ -1,12 +1,12 @@
[package] [package]
name = "vnt-cli" name = "vnt-cli"
version = "1.1.1" version = "1.1.2"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
vnt = {path="../vnt"} vnt = { path = "../vnt", package = "vnt", optional = true }
common = { path = "../common" } common = { path = "../common" }
tokio = { version = "1.28.1", features = ["full"] } tokio = { version = "1.28.1", features = ["full"] }
getopts = "0.2.21" getopts = "0.2.21"
@@ -27,9 +27,12 @@ sudo = "0.6.0"
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] } winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] }
[features] [features]
default = [] default = ["normal"]
mini = [] normal = ["vnt"]
ring-cipher = ["vnt/ring-cipher"]
[build-dependencies] [build-dependencies]
embed-manifest = "1.4.0" embed-manifest = "1.4.0"
+32 -9
View File
@@ -1,21 +1,21 @@
## 模块介绍 ## 模块介绍
体积小,可以在服务器、路由器等环境使用 体积小,可以在服务器、路由器等环境使用
## 详细参数说明 ## 详细参数说明
### -k ### -k `<token>`
一个虚拟局域网的标识,在同一服务器下,相同token的设备会组建一个局域网 一个虚拟局域网的标识,在同一服务器下,相同token的设备会组建一个局域网
### -n ### -n `<name>`
设备名称,方便区分不同设备 设备名称,方便区分不同设备
### -d ### -d `<id>`
设备id,每台设备的唯一标识,注意不要重复 设备id,每台设备的唯一标识,注意不要重复
### -c ### -c
关闭控制台交互式命令,后台运行时可以加此参数 关闭控制台交互式命令,后台运行时可以加此参数
### -s ### -s `<server>`
注册和中继服务器地址,注册和转发数据 注册和中继服务器地址,注册和转发数据
### -e ### -e `<addr1,addr2>`
探测客户端NAT类型,不同类型有不同的打洞策略 探测客户端NAT类型,不同类型有不同的打洞策略
### -a ### -a
加了此参数表示使用tap网卡,默认使用tun网卡,tun网卡效率更高 加了此参数表示使用tap网卡,默认使用tun网卡,tun网卡效率更高
### -i、-o ### -i `<in-ip>`、-o `<out-ip>`
配置点对网(IP代理)时使用,例如A(虚拟ip:10.26.0.2)通过B(虚拟ip:10.26.0.3,本地出口ip:192.168.0.10)访问C(目标网段192.168.0.0/24) 配置点对网(IP代理)时使用,例如A(虚拟ip:10.26.0.2)通过B(虚拟ip:10.26.0.3,本地出口ip:192.168.0.10)访问C(目标网段192.168.0.0/24)
@@ -23,9 +23,17 @@
在B配置 **-o 192.168.0.0/24,192.168.0.10** ,表示允许将192.168.0.0/24的数据从网卡192.168.0.10转发出去 在B配置 **-o 192.168.0.0/24,192.168.0.10** ,表示允许将192.168.0.0/24的数据从网卡192.168.0.10转发出去
### -w 注:-o 可以不配置出口ip,如直接使用 **-o 192.168.0.0/24** , 这将使用默认ip转发
### -w `<password>`
提升通信安全性,使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密。使用相同密码的客户端才能通信 提升通信安全性,使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密。使用相同密码的客户端才能通信
| 密码位数 | 加密算法 |
|---------|-------|
| 小于8 | AES128-GCM
| 大于等于8 | AES256-GCM |
### -m ### -m
模拟组播,高频使用组播通信时,可以尝试开启此参数,默认情况下会把组播当作广播发给所有节点 模拟组播,高频使用组播通信时,可以尝试开启此参数,默认情况下会把组播当作广播发给所有节点
@@ -33,8 +41,23 @@
模拟组播:高频使用组播时防止广播泛洪,客户端和中继服务器会维护组播成员等信息,注意使用此选项时,虚拟网内所有成员都需要开启此选项 模拟组播:高频使用组播时防止广播泛洪,客户端和中继服务器会维护组播成员等信息,注意使用此选项时,虚拟网内所有成员都需要开启此选项
### -u ### -u `<mtu>`
设置虚拟网卡的mtu值,大多数情况下使用默认值效率会更高,也可根据实际情况微调这个值,默认值为1430 设置虚拟网卡的mtu值,大多数情况下使用默认值效率会更高,也可根据实际情况微调这个值,默认值为1430
### --tcp
和服务端使用tcp通信。有些网络提供商对UDP限制比较大,这个时候可以选择使用TCP模式,提高稳定性。一般来说udp延迟和消耗更低
### --ip `<IP>`
指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配
### --relay
禁用p2p,在网络环境很差时,只使用服务器中转效果可能更好(可以配合--tcp参数一起使用)
### --list
在后台运行时,查看其他设备列表
### --all
在后台运行时,查看其他设备完整信息
### --info
在后台运行时,查看当前设备信息
### --route
在后台运行时,查看数据转发路径
### --stop
停止后台运行
+8 -1
View File
@@ -72,6 +72,7 @@ pub fn command_route(vnt: &Vnt) -> Vec<RouteItem> {
} }
pub fn command_list(vnt: &Vnt) -> Vec<DeviceItem> { pub fn command_list(vnt: &Vnt) -> Vec<DeviceItem> {
let info = vnt.current_device();
let device_list = vnt.device_list(); let device_list = vnt.device_list();
let mut list = Vec::new(); let mut list = Vec::new();
for peer in device_list { for peer in device_list {
@@ -87,7 +88,13 @@ pub fn command_list(vnt: &Vnt) -> Vec<DeviceItem> {
("".to_string(), "".to_string(), "".to_string()) ("".to_string(), "".to_string(), "".to_string())
}; };
let (nat_traversal_type, rt) = if let Some(route) = vnt.route(&peer.virtual_ip) { let (nat_traversal_type, rt) = if let Some(route) = vnt.route(&peer.virtual_ip) {
let nat_traversal_type = if route.metric == 1 { "p2p" } else { "relay" }.to_string(); let nat_traversal_type = if route.metric == 1 {
"p2p"
} else if route.addr == info.connect_server {
"server-relay"
} else {
"client-relay"
}.to_string();
let rt = if route.rt < 0 { let rt = if route.rt < 0 {
"".to_string() "".to_string()
} else { } else {
+9 -8
View File
@@ -5,7 +5,7 @@ use std::str::FromStr;
use console::style; use console::style;
use getopts::Options; use getopts::Options;
use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::io::{AsyncBufReadExt, BufReader};
use common::args_parse::ips_parse; use common::args_parse::{ips_parse, out_ips_parse};
use vnt::core::{Config, VntUtil}; use vnt::core::{Config, VntUtil};
use vnt::handle::registration_handler::ReqEnum; use vnt::handle::registration_handler::ReqEnum;
@@ -31,19 +31,18 @@ async fn main0() {
let args: Vec<String> = std::env::args().collect(); let args: Vec<String> = std::env::args().collect();
let program = args[0].clone(); let program = args[0].clone();
let mut opts = Options::new(); let mut opts = Options::new();
opts.long_only(false);
opts.optopt("k", "", &format!("{}", green("必选,使用相同的token,就能组建一个局域网络".to_string())), "<token>"); opts.optopt("k", "", &format!("{}", green("必选,使用相同的token,就能组建一个局域网络".to_string())), "<token>");
opts.optopt("n", "", "给设备一个名字,默认使用系统版本", "<name>"); opts.optopt("n", "", "给设备一个名字,默认使用系统版本", "<name>");
opts.optopt("d", "", "设备唯一标识符,不使用--ip参数时,服务端凭此参数分配ip", "<id>"); opts.optopt("d", "", "设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip", "<id>");
opts.optflag("c", "", "关闭交互式命令,使用此参数禁用控制台输入"); opts.optflag("c", "", "关闭交互式命令,使用此参数禁用控制台输入");
opts.optopt("s", "", "注册和中继服务器地址", "<server>"); opts.optopt("s", "", "注册和中继服务器地址", "<server>");
opts.optopt("e", "", "NAT探测服务器地址,使用逗号分隔", "<addr1,addr2>"); opts.optopt("e", "", "NAT探测服务器地址,使用逗号分隔", "<addr1,addr2>");
opts.optflag("a", "", "使用tap模式,默认使用tun模式"); opts.optflag("a", "", "使用tap模式,默认使用tun模式");
opts.optmulti("i", "", "配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据并转发到10.26.0.3", "<in-ip>"); opts.optmulti("i", "", "配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3 \n表示允许接收网段192.168.0.0/24的数据并转发到10.26.0.3", "<in-ip>");
opts.optmulti("o", "", "配置点对网时使用,-o 192.168.0.0/24,192.168.0.10表示允许目标为192.168.0.0/24的数据从网卡192.168.0.10转发出去", "<out-ip>"); opts.optmulti("o", "", "配置点对网时使用,-o 192.168.0.0/24 \n表示允许目标为192.168.0.0/24的数据转发出去", "<out-ip>");
opts.optopt("w", "", "使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信", "<password>"); opts.optopt("w", "", "使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信", "<password>");
opts.optflag("m", "", "模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送"); opts.optflag("m", "", "模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送");
opts.optopt("u", "", "虚拟网卡mtu值", "<mtu>"); opts.optopt("u", "", "自定义mtu(默认为1430)", "<mtu>");
opts.optflag("", "tcp", "和服务端使用tcp通信,默认使用udp,一般来说udp延迟和消耗更低"); opts.optflag("", "tcp", "和服务端使用tcp通信,默认使用udp,一般来说udp延迟和消耗更低");
opts.optopt("", "ip", "指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配", "<IP>"); opts.optopt("", "ip", "指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配", "<IP>");
opts.optflag("", "relay", "仅使用服务器转发,不使用p2p,默认情况允许使用p2p"); opts.optflag("", "relay", "仅使用服务器转发,不使用p2p,默认情况允许使用p2p");
@@ -146,16 +145,18 @@ async fn main0() {
print_usage(&program, opts); print_usage(&program, opts);
println!(); println!();
println!("-i {}", e); println!("-i {}", e);
println!("example: -i 192.168.0.0/24,10.26.0.3");
return; return;
} }
}; };
let out_ip = matches.opt_strs("o"); let out_ip = matches.opt_strs("o");
let out_ip = match ips_parse(&out_ip) { let out_ip = match out_ips_parse(&out_ip) {
Ok(out_ip) => { out_ip } Ok(out_ip) => { out_ip }
Err(e) => { Err(e) => {
print_usage(&program, opts); print_usage(&program, opts);
println!(); println!();
println!("-o {}", e); println!("-o {}", e);
println!("example: -o 0.0.0.0/0");
return; return;
} }
}; };
@@ -310,7 +311,7 @@ async fn main0() {
fn print_usage(program: &str, opts: Options) { fn print_usage(program: &str, opts: Options) {
let brief = format!("Usage: {} [options]", program); let brief = format!("Usage: {} [options]", program);
println!("version:1.1.1"); println!("version:1.1.2");
println!("{}", opts.usage(&brief)); println!("{}", opts.usage(&brief));
} }
+8 -3
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "vnt" name = "vnt"
version = "1.1.1" version = "1.1.2"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -15,12 +15,12 @@ crossbeam-skiplist = "0.1"
parking_lot = "0.12.1" parking_lot = "0.12.1"
rand = "0.8.5" rand = "0.8.5"
sha2 = { version = "0.10.6", features = ["oid"] } sha2 = { version = "0.10.6", features = ["oid"] }
aes-gcm = "0.10.2"
thiserror = "1.0.37" thiserror = "1.0.37"
protobuf = "3.2.0" protobuf = "3.2.0"
socket2 ={ version = "0.5.2", features = ["all"] } socket2 ={ version = "0.5.2", features = ["all"] }
tokio = { version = "1.28.1", features = ["full"] } tokio = { version = "1.28.1", features = ["full"] }
aes-gcm = {version="0.10.2", optional = true}
ring = {version="0.16.20", optional = true}
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies] [target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
tun = { path = "./rust-tun" } tun = { path = "./rust-tun" }
@@ -33,3 +33,8 @@ libloading = "0.7.4"
protobuf-codegen = "3.2.0" protobuf-codegen = "3.2.0"
protoc-bin-vendored = "3.0.0" protoc-bin-vendored = "3.0.0"
[features]
default=["aes-gcm"]
ring-cipher=["ring"]
+1 -1
View File
@@ -103,9 +103,9 @@ pub fn ipv4_cal_checksum(
src_ip: &Ipv4Addr, src_ip: &Ipv4Addr,
dest_ip: &Ipv4Addr, dest_ip: &Ipv4Addr,
protocol: u8, protocol: u8,
length: u16,
) -> u16 { ) -> u16 {
use std::io::Cursor; use std::io::Cursor;
let length = buffer.len();
let mut sum = 0; let mut sum = 0;
let src_ip = src_ip.octets(); let src_ip = src_ip.octets();
sum += u32c(src_ip[0], src_ip[1]); sum += u32c(src_ip[0], src_ip[1]);
-1
View File
@@ -134,7 +134,6 @@ impl<B: AsRef<[u8]>> TcpPacket<B> {
&self.source_ip, &self.source_ip,
&self.destination_ip, &self.destination_ip,
6, 6,
self.buffer.as_ref().len() as u16,
) )
} }
pub fn urgent_pointer(&self) -> u16 { pub fn urgent_pointer(&self) -> u16 {
-1
View File
@@ -102,7 +102,6 @@ impl<B: AsRef<[u8]>> UdpPacket<B> {
&self.source_ip, &self.source_ip,
&self.destination_ip, &self.destination_ip,
17, 17,
self.length(),
) )
} }
} }
+6 -4
View File
@@ -257,9 +257,11 @@ impl Context {
} }
} }
pub fn route_to_id(&self, route_key: &RouteKey) -> Option<Ipv4Addr> { pub fn route_to_id(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
for x in self.inner.route_table_time.iter() { for x in self.inner.route_table.iter() {
if &x.key().0 == route_key { for route in x.value() {
return Some(x.key().1); if &route.route_key() == route_key && route.is_p2p() {
return Some(*x.key());
}
} }
} }
None None
@@ -311,8 +313,8 @@ impl Context {
drop(v); drop(v);
routes.retain(|x| x.route_key() != route_key); routes.retain(|x| x.route_key() != route_key);
self.inner.route_table.insert(*id, routes); self.inner.route_table.insert(*id, routes);
self.inner.route_table_time.remove(&(route_key, *id));
} }
self.inner.route_table_time.remove(&(route_key, *id));
drop(guard); drop(guard);
} }
pub fn update_read_time(&self, id: &Ipv4Addr, route_key: &RouteKey) { pub fn update_read_time(&self, id: &Ipv4Addr, route_key: &RouteKey) {
+1
View File
@@ -29,6 +29,7 @@ impl Idle {
for entry in self.context.inner.route_table_time.iter() { for entry in self.context.inner.route_table_time.iter() {
let last_read = entry.value().load().elapsed(); let last_read = entry.value().load().elapsed();
if last_read >= self.read_idle { if last_read >= self.read_idle {
entry.remove();
return Ok((entry.key().1.clone(), entry.key().0.clone())); return Ok((entry.key().1.clone(), entry.key().0.clone()));
} else { } else {
if max < last_read { if max < last_read {
+115
View File
@@ -0,0 +1,115 @@
use std::io;
use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, Nonce, Tag,KeyInit};
use aes_gcm::aead::consts::{U12, U16};
use aes_gcm::aead::generic_array::GenericArray;
use sha2::Digest;
use crate::protocol;
use crate::protocol::{ip_turn_packet, NetPacket};
#[derive(Clone)]
pub enum Cipher {
AesGCM128(Aes128Gcm),
AesGCM256(Aes256Gcm),
None,
}
impl Cipher {
pub fn new(password: Option<String>) -> Self {
if let Some(password) = password {
let mut hasher = sha2::Sha256::new();
hasher.update(password.as_bytes());
let key: [u8; 32] = hasher.finalize().into();
if password.len() < 8 {
let key: &Key<Aes128Gcm> = key[..16].into();
Cipher::AesGCM128(Aes128Gcm::new(&key))
} else {
let key: &Key<Aes256Gcm> = &key.into();
Cipher::AesGCM256(Aes256Gcm::new(&key))
}
} else {
Cipher::None
}
}
pub fn decrypt_ipv4(&self, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result<Option<usize>> {
match &self {
Cipher::None => {
return Ok(None);
}
_ => {}
}
if !net_packet.is_encrypt() {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if net_packet.payload().len() < 16 {
log::error!("数据异常,长度小于16");
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let mut nonce = [0; 12];
nonce[0..4].copy_from_slice(&net_packet.source().octets());
nonce[4..8].copy_from_slice(&net_packet.destination().octets());
nonce[8] = protocol::Protocol::IpTurn.into();
nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce);
let payload_len = net_packet.payload().len() - 16;
let tag: GenericArray<u8, U16> = Tag::clone_from_slice(&net_packet.payload()[payload_len..]);
let rs = match &self {
Cipher::AesGCM128(cipher) => {
cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len], &tag)
}
Cipher::AesGCM256(cipher) => {
cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len], &tag)
}
Cipher::None => {
return Ok(None);
}
};
if let Err(e) = rs {
return Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e)));
}
return Ok(Some(payload_len));
}
/// net_packet 必须预留足够长度
/// data_len是有效载荷的长度
/// 返回加密后载荷的长度
pub fn encrypt_ipv4(&self, payload_len: usize, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result<Option<usize>> {
match &self {
Cipher::None => {
return Ok(None);
}
_ => {}
}
let mut nonce = [0; 12];
nonce[0..4].copy_from_slice(&net_packet.source().octets());
nonce[4..8].copy_from_slice(&net_packet.destination().octets());
nonce[8] = protocol::Protocol::IpTurn.into();
nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce);
let rs = match &self {
Cipher::AesGCM128(cipher) => {
cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len])
}
Cipher::AesGCM256(cipher) => {
cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len])
}
Cipher::None => {
return Ok(None);
}
};
return match rs {
Ok(tag) => {
if tag.len() != 16 {
return Err(io::Error::new(io::ErrorKind::Other, format!("加密tag长度错误:{}", tag.len())));
}
net_packet.set_encrypt_flag(true);
net_packet.payload_mut()[payload_len..payload_len + 16].copy_from_slice(tag.as_slice());
Ok(Some(payload_len + 16))
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e)))
}
};
}
}
+8 -115
View File
@@ -1,115 +1,8 @@
use std::io; #[cfg(feature = "ring-cipher")]
mod ring_cipher;
use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, Nonce, Tag,KeyInit}; #[cfg(feature = "ring-cipher")]
use aes_gcm::aead::consts::{U12, U16}; pub use ring_cipher::Cipher;
use aes_gcm::aead::generic_array::GenericArray; #[cfg(not(feature = "ring-cipher"))]
use sha2::Digest; mod aes_gcm_cipher;
#[cfg(not(feature = "ring-cipher"))]
use crate::protocol; pub use aes_gcm_cipher::Cipher;
use crate::protocol::{ip_turn_packet, NetPacket};
#[derive(Clone)]
pub enum Cipher {
AesGCM128(Aes128Gcm),
AesGCM256(Aes256Gcm),
None,
}
impl Cipher {
pub fn new(password: Option<String>) -> Self {
if let Some(password) = password {
let mut hasher = sha2::Sha256::new();
hasher.update(password.as_bytes());
let key: [u8; 32] = hasher.finalize().into();
if password.len() < 8 {
let key: &Key<Aes128Gcm> = key[..16].into();
Cipher::AesGCM128(Aes128Gcm::new(&key))
} else {
let key: &Key<Aes256Gcm> = &key.into();
Cipher::AesGCM256(Aes256Gcm::new(&key))
}
} else {
Cipher::None
}
}
pub fn decrypt_ipv4(&self, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result<Option<usize>> {
match &self {
Cipher::None => {
return Ok(None);
}
_ => {}
}
if !net_packet.is_encrypt() {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if net_packet.payload().len() < 16 {
log::error!("数据异常,长度小于16");
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let mut nonce = [0; 12];
nonce[0..4].copy_from_slice(&net_packet.source().octets());
nonce[4..8].copy_from_slice(&net_packet.destination().octets());
nonce[8] = protocol::Protocol::IpTurn.into();
nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce);
let payload_len = net_packet.payload().len() - 16;
let tag: GenericArray<u8, U16> = Tag::clone_from_slice(&net_packet.payload()[payload_len..]);
let rs = match &self {
Cipher::AesGCM128(cipher) => {
cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len], &tag)
}
Cipher::AesGCM256(cipher) => {
cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len], &tag)
}
Cipher::None => {
return Ok(None);
}
};
if let Err(e) = rs {
return Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e)));
}
return Ok(Some(payload_len));
}
/// net_packet 必须预留足够长度
/// data_len是有效载荷的长度
/// 返回加密后载荷的长度
pub fn encrypt_ipv4(&self, payload_len: usize, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result<Option<usize>> {
match &self {
Cipher::None => {
return Ok(None);
}
_ => {}
}
let mut nonce = [0; 12];
nonce[0..4].copy_from_slice(&net_packet.source().octets());
nonce[4..8].copy_from_slice(&net_packet.destination().octets());
nonce[8] = protocol::Protocol::IpTurn.into();
nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce);
let rs = match &self {
Cipher::AesGCM128(cipher) => {
cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len])
}
Cipher::AesGCM256(cipher) => {
cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len])
}
Cipher::None => {
return Ok(None);
}
};
return match rs {
Ok(tag) => {
if tag.len() != 16 {
return Err(io::Error::new(io::ErrorKind::Other, format!("加密tag长度错误:{}", tag.len())));
}
net_packet.set_encrypt_flag(true);
net_packet.payload_mut()[payload_len..payload_len + 16].copy_from_slice(tag.as_slice());
Ok(Some(payload_len + 16))
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e)))
}
};
}
}
+132
View File
@@ -0,0 +1,132 @@
use std::io;
use ring::aead;
use ring::aead::{LessSafeKey, UnboundKey};
use sha2::Digest;
use crate::protocol;
use crate::protocol::{ip_turn_packet, NetPacket};
pub enum Cipher {
AesGCM128(LessSafeKey, [u8; 16]),
AesGCM256(LessSafeKey, [u8; 32]),
None,
}
impl Clone for Cipher {
fn clone(&self) -> Self {
match &self {
Cipher::AesGCM128(_, key) => {
let c = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, key.as_slice()).unwrap());
Cipher::AesGCM128(c, *key)
}
Cipher::AesGCM256(_, key) => {
let c = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, key.as_slice()).unwrap());
Cipher::AesGCM256(c, *key)
}
Cipher::None => {
Cipher::None
}
}
}
}
impl Cipher {
pub fn new(password: Option<String>) -> Self {
if let Some(password) = password {
let mut hasher = sha2::Sha256::new();
hasher.update(password.as_bytes());
let key: [u8; 32] = hasher.finalize().into();
if password.len() < 8 {
let c = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, &key[..16]).unwrap());
Cipher::AesGCM128(c, key[..16].try_into().unwrap())
} else {
let c = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, &key).unwrap());
Cipher::AesGCM256(c, key)
}
} else {
Cipher::None
}
}
pub fn decrypt_ipv4(&self, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result<Option<usize>> {
match &self {
Cipher::None => {
return Ok(None);
}
_ => {}
}
if !net_packet.is_encrypt() {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if net_packet.payload().len() < 16 {
log::error!("数据异常,长度小于16");
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let mut nonce = [0; 12];
nonce[0..4].copy_from_slice(&net_packet.source().octets());
nonce[4..8].copy_from_slice(&net_packet.destination().octets());
nonce[8] = protocol::Protocol::IpTurn.into();
nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
let nonce = aead::Nonce::assume_unique_for_key(nonce);
let payload_len = net_packet.payload().len() - 16;
let rs = match &self {
Cipher::AesGCM128(cipher, _) => {
cipher.open_in_place(nonce, aead::Aad::empty(), net_packet.payload_mut())
}
Cipher::AesGCM256(cipher, _) => {
cipher.open_in_place(nonce, aead::Aad::empty(), net_packet.payload_mut())
}
Cipher::None => {
return Ok(None);
}
};
if let Err(e) = rs {
return Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e)));
}
return Ok(Some(payload_len));
}
/// net_packet 必须预留足够长度
/// data_len是有效载荷的长度
/// 返回加密后载荷的长度
pub fn encrypt_ipv4(&self, payload_len: usize, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result<Option<usize>> {
match &self {
Cipher::None => {
return Ok(None);
}
_ => {}
}
let mut nonce = [0; 12];
nonce[0..4].copy_from_slice(&net_packet.source().octets());
nonce[4..8].copy_from_slice(&net_packet.destination().octets());
nonce[8] = protocol::Protocol::IpTurn.into();
nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
let nonce = aead::Nonce::assume_unique_for_key(nonce);
let rs = match &self {
Cipher::AesGCM128(cipher, _) => {
cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), &mut net_packet.payload_mut()[..payload_len])
}
Cipher::AesGCM256(cipher, _) => {
cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), &mut net_packet.payload_mut()[..payload_len])
}
Cipher::None => {
return Ok(None);
}
};
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())));
}
net_packet.set_encrypt_flag(true);
net_packet.payload_mut()[payload_len..payload_len + 16].copy_from_slice(tag);
Ok(Some(payload_len + 16))
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e)))
}
};
}
}
+6 -8
View File
@@ -17,7 +17,7 @@ use crate::channel::sender::ChannelSender;
use crate::cipher::Cipher; use crate::cipher::Cipher;
use crate::core::status::VntStatusManger; use crate::core::status::VntStatusManger;
use crate::error::Error; use crate::error::Error;
use crate::external_route::ExternalRoute; use crate::external_route::{AllowExternalRoute, ExternalRoute};
use crate::handle::{ConnectStatus, CurrentDeviceInfo, heartbeat_handler, PeerDeviceInfo, punch_handler, registration_handler}; use crate::handle::{ConnectStatus, CurrentDeviceInfo, heartbeat_handler, PeerDeviceInfo, punch_handler, registration_handler};
use crate::handle::recv_handler::ChannelDataHandler; use crate::handle::recv_handler::ChannelDataHandler;
use crate::handle::registration_handler::{RegResponse, ReqEnum}; use crate::handle::registration_handler::{RegResponse, ReqEnum};
@@ -182,20 +182,18 @@ impl VntUtil {
let local_port = context.main_local_port()?; let local_port = context.main_local_port()?;
// NAT检测 // NAT检测
let nat_test = NatTest::new(config.nat_test_server.clone(), response.public_ip, response.public_port, local_ip, local_port); 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 in_external_route = if config.in_ips.is_empty() { let in_external_route = if config.in_ips.is_empty() {
None None
} else { } else {
Some(ExternalRoute::new(config.in_ips)) Some(ExternalRoute::new(config.in_ips))
}; };
let (tcp_proxy, udp_proxy, ip_proxy_map) = if out_ips.is_empty() { let (tcp_proxy, udp_proxy, ip_proxy_map) = if config.out_ips.is_empty() {
(None, None, None) (None, None, None)
} else { } 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()).await?;
(Some(tcp_proxy), Some(udp_proxy), Some(ip_proxy_map)) (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 { let igmp_server = if config.simulate_multicast {
Some(IgmpServer::new(device_writer.clone())) Some(IgmpServer::new(device_writer.clone()))
@@ -339,7 +337,7 @@ pub struct Config {
pub server_address_str: String, pub server_address_str: String,
pub nat_test_server: Vec<SocketAddr>, pub nat_test_server: Vec<SocketAddr>,
pub in_ips: Vec<(u32, u32, Ipv4Addr)>, pub in_ips: Vec<(u32, u32, Ipv4Addr)>,
pub out_ips: Vec<(u32, u32, Ipv4Addr)>, pub out_ips: Vec<(u32, u32)>,
pub password: Option<String>, pub password: Option<String>,
pub simulate_multicast: bool, pub simulate_multicast: bool,
pub mtu: Option<u16>, pub mtu: Option<u16>,
@@ -356,7 +354,7 @@ impl Config {
server_address: SocketAddr, server_address: SocketAddr,
server_address_str: String, server_address_str: String,
nat_test_server: Vec<SocketAddr>, nat_test_server: Vec<SocketAddr>,
in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32, Ipv4Addr)>, in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32)>,
password: Option<String>, simulate_multicast: bool, mtu: Option<u16>, tcp: bool, password: Option<String>, simulate_multicast: bool, mtu: Option<u16>, tcp: bool,
ip: Option<Ipv4Addr>, ip: Option<Ipv4Addr>,
relay: bool, ) -> Self { relay: bool, ) -> Self {
+22
View File
@@ -24,3 +24,25 @@ impl ExternalRoute {
None 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
}
}
+1 -2
View File
@@ -149,7 +149,6 @@ async fn start_heartbeat_(
} else { } else {
//没有直连路由则发送到网关 //没有直连路由则发送到网关
let _ = sender.send_main(net_packet.buffer(), current_dev.connect_server).await; let _ = sender.send_main(net_packet.buffer(), current_dev.connect_server).await;
continue;
} }
//再随机发送到其他地址,看有没有客户端符合转发条件 //再随机发送到其他地址,看有没有客户端符合转发条件
@@ -167,7 +166,7 @@ async fn start_heartbeat_(
num += 1; num += 1;
break; break;
} }
if num >= 3 { if num >= 2 {
break 'a; break 'a;
} }
} }
+7 -9
View File
@@ -17,7 +17,7 @@ use crate::channel::{Route, RouteKey};
use crate::cipher::Cipher; use crate::cipher::Cipher;
use crate::error::Error; use crate::error::Error;
use crate::external_route::ExternalRoute; use crate::external_route::AllowExternalRoute;
use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo, PeerDeviceStatus}; use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo, PeerDeviceStatus};
use crate::handle::registration_handler::Register; use crate::handle::registration_handler::Register;
use crate::igmp_server::IgmpServer; use crate::igmp_server::IgmpServer;
@@ -41,7 +41,7 @@ pub struct ChannelDataHandler {
connect_status: Arc<AtomicCell<ConnectStatus>>, connect_status: Arc<AtomicCell<ConnectStatus>>,
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>, peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
ip_proxy_map: Option<IpProxyMap>, ip_proxy_map: Option<IpProxyMap>,
out_external_route: ExternalRoute, out_external_route: AllowExternalRoute,
cone_sender: Sender<(Ipv4Addr, NatInfo)>, cone_sender: Sender<(Ipv4Addr, NatInfo)>,
symmetric_sender: Sender<(Ipv4Addr, NatInfo)>, symmetric_sender: Sender<(Ipv4Addr, NatInfo)>,
cipher: Cipher, cipher: Cipher,
@@ -58,7 +58,7 @@ impl ChannelDataHandler {
connect_status: Arc<AtomicCell<ConnectStatus>>, connect_status: Arc<AtomicCell<ConnectStatus>>,
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>, peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
ip_proxy_map: Option<IpProxyMap>, ip_proxy_map: Option<IpProxyMap>,
out_external_route: ExternalRoute, out_external_route: AllowExternalRoute,
cone_sender: Sender<(Ipv4Addr, NatInfo)>, cone_sender: Sender<(Ipv4Addr, NatInfo)>,
symmetric_sender: Sender<(Ipv4Addr, NatInfo)>, symmetric_sender: Sender<(Ipv4Addr, NatInfo)>,
cipher: Cipher, cipher: Cipher,
@@ -185,7 +185,7 @@ impl ChannelDataHandler {
} }
if not_broadcast && ipv4.destination_ip() != destination { if not_broadcast && ipv4.destination_ip() != destination {
if let Some(ip_proxy_map) = &self.ip_proxy_map { if 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() { match ipv4.protocol() {
ipv4::protocol::Protocol::Tcp => { ipv4::protocol::Protocol::Tcp => {
let dest_ip = ipv4.destination_ip(); let dest_ip = ipv4.destination_ip();
@@ -197,8 +197,7 @@ impl ChannelDataHandler {
tcp_packet.update_checksum(); tcp_packet.update_checksum();
ipv4.set_destination_ip(destination); ipv4.set_destination_ip(destination);
ipv4.update_checksum(); ipv4.update_checksum();
ip_proxy_map.tcp_proxy_map.insert(SocketAddrV4::new(source, source_port), ip_proxy_map.tcp_proxy_map.insert(SocketAddrV4::new(source, source_port), SocketAddrV4::new(dest_ip, dest_port));
(SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port)));
} }
ipv4::protocol::Protocol::Udp => { ipv4::protocol::Protocol::Udp => {
let dest_ip = ipv4.destination_ip(); let dest_ip = ipv4.destination_ip();
@@ -210,8 +209,7 @@ impl ChannelDataHandler {
udp_packet.update_checksum(); udp_packet.update_checksum();
ipv4.set_destination_ip(destination); ipv4.set_destination_ip(destination);
ipv4.update_checksum(); ipv4.update_checksum();
ip_proxy_map.udp_proxy_map.insert(SocketAddrV4::new(source, source_port), ip_proxy_map.udp_proxy_map.insert(SocketAddrV4::new(source, source_port), SocketAddrV4::new(dest_ip, dest_port));
(SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port)));
} }
ipv4::protocol::Protocol::Icmp => { ipv4::protocol::Protocol::Icmp => {
let dest_ip = ipv4.destination_ip(); let dest_ip = ipv4.destination_ip();
@@ -220,7 +218,7 @@ impl ChannelDataHandler {
match icmp_packet.header_other() { match icmp_packet.header_other() {
HeaderOther::Identifier(id, seq) => { HeaderOther::Identifier(id, seq) => {
ip_proxy_map.icmp_proxy_map.insert((dest_ip, id, seq), source); 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(()); return Ok(());
+1 -1
View File
@@ -178,7 +178,7 @@ fn registration_request_packet(
request.virtual_ip = ip.into(); request.virtual_ip = ip.into();
request.allow_ip_change = allow_ip_change; request.allow_ip_change = allow_ip_change;
request.is_fast = is_fast; request.is_fast = is_fast;
request.version = "1.1.1".to_string(); request.version = "1.1.2".to_string();
let bytes = request.write_to_bytes()?; let bytes = request.write_to_bytes()?;
let buf = vec![0u8; 12 + bytes.len()]; let buf = vec![0u8; 12 + bytes.len()];
let mut net_packet = NetPacket::new(buf)?; let mut net_packet = NetPacket::new(buf)?;
+2 -2
View File
@@ -190,7 +190,7 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8],
SocketAddrV4::new(dest_ip, tcp_packet.destination_port()) SocketAddrV4::new(dest_ip, tcp_packet.destination_port())
}; };
if let Some(entry) = proxy_map.tcp_proxy_map.get(&dest_addr) { if let Some(entry) = proxy_map.tcp_proxy_map.get(&dest_addr) {
let source_addr = entry.value().1; let source_addr = entry.value();
let source_ip = *source_addr.ip(); let source_ip = *source_addr.ip();
let mut tcp_packet = TcpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?; let mut tcp_packet = TcpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?;
tcp_packet.set_source_port(source_addr.port()); tcp_packet.set_source_port(source_addr.port());
@@ -206,7 +206,7 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8],
SocketAddrV4::new(dest_ip, udp_packet.destination_port()) SocketAddrV4::new(dest_ip, udp_packet.destination_port())
}; };
if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) { if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) {
let source_addr = entry.value().1; let source_addr = entry.value();
let source_ip = *source_addr.ip(); let source_ip = *source_addr.ip();
let mut udp_packet = UdpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?; let mut udp_packet = UdpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?;
udp_packet.set_source_port(source_addr.port()); udp_packet.set_source_port(source_addr.port());
+13 -22
View File
@@ -1,5 +1,4 @@
use std::{io, thread}; use std::{io, thread};
use std::collections::HashMap;
use std::net::{Ipv4Addr, SocketAddrV4}; use std::net::{Ipv4Addr, SocketAddrV4};
use std::sync::Arc; use std::sync::Arc;
use crossbeam_utils::atomic::AtomicCell; use crossbeam_utils::atomic::AtomicCell;
@@ -27,28 +26,23 @@ pub enum Protocol {
pub struct IpProxyMap { pub struct IpProxyMap {
pub(crate) tcp_proxy_port: u16, pub(crate) tcp_proxy_port: u16,
pub(crate) udp_proxy_port: u16, pub(crate) udp_proxy_port: u16,
//真实源地址 -> (绑定地址,目的地址) //真实源地址 -> 目的地址
pub(crate) tcp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>, pub(crate) tcp_proxy_map: Arc<SkipMap<SocketAddrV4, SocketAddrV4>>,
pub(crate) udp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>, pub(crate) udp_proxy_map: Arc<SkipMap<SocketAddrV4, SocketAddrV4>>,
// icmp用Identifier来区分,没有Identifier的一律不转发 // icmp用Identifier来区分,没有Identifier的一律不转发
pub(crate) icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>, pub(crate) icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
icmp_sockets: HashMap<Ipv4Addr, Arc<Socket>>, icmp_socket: Arc<Socket>,
} }
impl IpProxyMap { impl IpProxyMap {
pub fn send_icmp(&self, buf: &[u8], src: &Ipv4Addr, dest: &Ipv4Addr) -> io::Result<usize> { pub fn send_icmp(&self, buf: &[u8], dest: &Ipv4Addr) -> io::Result<usize> {
if let Some(socket) = self.icmp_sockets.get(src) { self.icmp_socket.send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0)))
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)> { pub async fn init_proxy(sender: ChannelSender, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> {
let mut icmp_sockets = HashMap::new(); let tcp_proxy_map: Arc<SkipMap<SocketAddrV4, SocketAddrV4>> = Arc::new(SkipMap::new());
let tcp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>> = Arc::new(SkipMap::new()); let udp_proxy_map: Arc<SkipMap<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 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 tcp_listener = TcpListener::bind("0.0.0.0:0").await?;
let udp_socket = UdpSocket::bind("0.0.0.0:0").await?; let udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
@@ -56,15 +50,12 @@ pub async fn init_proxy(sender: ChannelSender, bind_ips: Vec<Ipv4Addr>, current_
let udp_proxy_port = udp_socket.local_addr()?.port(); let udp_proxy_port = udp_socket.local_addr()?.port();
let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map.clone()); let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map.clone());
let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map.clone()); let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map.clone());
for ip in bind_ips { let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0);
let addr = SocketAddrV4::new(ip, 0); let icmp_proxy = IcmpProxy::new(addr, icmp_proxy_map.clone(), sender.clone(), current_device.clone())?;
let icmp_proxy_map = icmp_proxy_map.clone(); let icmp_socket = icmp_proxy.icmp_socket();
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 || { thread::spawn(move || {
icmp_proxy.start(); icmp_proxy.start();
}); });
}
Ok((tcp_proxy, udp_proxy, IpProxyMap { Ok((tcp_proxy, udp_proxy, IpProxyMap {
tcp_proxy_port, tcp_proxy_port,
@@ -72,6 +63,6 @@ pub async fn init_proxy(sender: ChannelSender, bind_ips: Vec<Ipv4Addr>, current_
tcp_proxy_map, tcp_proxy_map,
udp_proxy_map, udp_proxy_map,
icmp_proxy_map, icmp_proxy_map,
icmp_sockets, icmp_socket,
})) }))
} }
+5 -5
View File
@@ -6,11 +6,11 @@ use tokio::net::{TcpListener, TcpStream};
pub struct TcpProxy { pub struct TcpProxy {
tcp_listener: TcpListener, tcp_listener: TcpListener,
map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>, map: Arc<SkipMap<SocketAddrV4, SocketAddrV4>>,
} }
impl TcpProxy { impl TcpProxy {
pub fn new(tcp_listener: TcpListener, map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>) -> Self { pub fn new(tcp_listener: TcpListener, map: Arc<SkipMap<SocketAddrV4, SocketAddrV4>>) -> Self {
Self { Self {
tcp_listener, tcp_listener,
map, map,
@@ -25,11 +25,11 @@ impl TcpProxy {
match sender_addr { match sender_addr {
SocketAddr::V4(sender_addr) => { SocketAddr::V4(sender_addr) => {
if let Some(entry) = map.get(&sender_addr) { if let Some(entry) = map.get(&sender_addr) {
let (src_addr, dest_addr) = *entry.value(); let dest_addr = *entry.value();
let peer_tcp_stream = match TcpStream::connect(dest_addr).await { 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) => { Err(e) => {
log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr); log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,sender_addr,dest_addr);
continue; continue;
} }
}; };
@@ -38,7 +38,7 @@ impl TcpProxy {
match proxy(tcp_stream, peer_tcp_stream).await { match proxy(tcp_stream, peer_tcp_stream).await {
Ok(_) => {} Ok(_) => {}
Err(e) => { Err(e) => {
log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr); log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,sender_addr,dest_addr);
} }
} }
map.remove(&sender_addr); map.remove(&sender_addr);
+7 -7
View File
@@ -8,11 +8,11 @@ use tokio::net::UdpSocket;
/// 一个udp代理,作用是利用系统协议栈,将udp数据报解析出来再转发到目的地址 /// 一个udp代理,作用是利用系统协议栈,将udp数据报解析出来再转发到目的地址
pub struct UdpProxy { pub struct UdpProxy {
udp_socket: Arc<UdpSocket>, udp_socket: Arc<UdpSocket>,
map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>, map: Arc<SkipMap<SocketAddrV4, SocketAddrV4>>,
} }
impl UdpProxy { impl UdpProxy {
pub fn new(udp_socket: UdpSocket, map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>) -> Self { pub fn new(udp_socket: UdpSocket, map: Arc<SkipMap<SocketAddrV4, SocketAddrV4>>) -> Self {
let udp_socket = Arc::new(udp_socket); let udp_socket = Arc::new(udp_socket);
Self { Self {
udp_socket, udp_socket,
@@ -48,11 +48,11 @@ 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<SkipMap<SocketAddrV4, Arc<UdpSocket>>>, map: &Arc<SkipMap<SocketAddrV4, SocketAddrV4>>, udp_socket: &Arc<UdpSocket>) -> io::Result<()> {
if let Some(entry) = inner_map.get(&sender_addr) { if let Some(entry) = inner_map.get(&sender_addr) {
entry.value().send(buf).await?; entry.value().send(buf).await?;
} else if let Some(entry) = map.get(&sender_addr) { } else if let Some(entry) = map.get(&sender_addr) {
let (src_addr, dest_addr) = *entry.value(); let dest_addr = *entry.value();
let peer_udp_socket = UdpSocket::bind("0.0.0.0:0").await?; let peer_udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
peer_udp_socket.connect(dest_addr).await?; peer_udp_socket.connect(dest_addr).await?;
peer_udp_socket.send(buf).await?; peer_udp_socket.send(buf).await?;
@@ -71,20 +71,20 @@ async fn start0(buf: &[u8], sender_addr: SocketAddrV4, inner_map: &Arc<SkipMap<S
match udp_socket.send_to(&buf[..len], sender_addr).await { match udp_socket.send_to(&buf[..len], sender_addr).await {
Ok(_) => {} Ok(_) => {}
Err(e) => { Err(e) => {
log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr); log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,sender_addr,dest_addr);
break; break;
} }
} }
} }
Err(e) => { Err(e) => {
log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr); log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,sender_addr,dest_addr);
break; break;
} }
} }
} }
Err(_) => { Err(_) => {
//超时关闭 //超时关闭
log::warn!("udp代理超时关闭,来源:{},目标:{}",src_addr,dest_addr); log::warn!("udp代理超时关闭,来源:{},目标:{}",sender_addr,dest_addr);
break; break;
} }
} }