Compare commits

..
1 Commits
Author SHA1 Message Date
lbl8603 4dca4c4f22 Merge pull request #38 from lbl8603/1.2.x
1.2.x
2024-05-11 09:21:57 +08:00
41 changed files with 330 additions and 1104 deletions
Generated
+4 -54
View File
@@ -195,10 +195,6 @@ name = "cc"
version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7"
dependencies = [
"jobserver",
"libc",
]
[[package]]
name = "cesu8"
@@ -248,7 +244,7 @@ dependencies = [
[[package]]
name = "common"
version = "1.2.10"
version = "1.2.9"
[[package]]
name = "console"
@@ -610,15 +606,6 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "jobserver"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
dependencies = [
"libc",
]
[[package]]
name = "js-sys"
version = "0.3.69"
@@ -733,12 +720,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "lz4_flex"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
[[package]]
name = "memchr"
version = "2.7.2"
@@ -1605,7 +1586,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "vnt"
version = "1.2.10"
version = "1.2.9"
dependencies = [
"aes",
"aes-gcm",
@@ -1621,7 +1602,6 @@ dependencies = [
"libloading",
"libsm",
"log",
"lz4_flex",
"mio",
"openssl-sys",
"packet",
@@ -1639,14 +1619,12 @@ dependencies = [
"thiserror",
"tokio",
"tun",
"zstd",
]
[[package]]
name = "vnt-cli"
version = "1.2.10"
version = "1.2.9"
dependencies = [
"anyhow",
"chrono",
"common",
"console",
@@ -1666,7 +1644,7 @@ dependencies = [
[[package]]
name = "vnt-jni"
version = "1.2.10"
version = "1.2.9"
dependencies = [
"android_logger",
"common",
@@ -2024,31 +2002,3 @@ name = "zeroize"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
[[package]]
name = "zstd"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "7.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a"
dependencies = [
"zstd-sys",
]
[[package]]
name = "zstd-sys"
version = "2.0.10+zstd.1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa"
dependencies = [
"cc",
"pkg-config",
]
+1 -20
View File
@@ -39,7 +39,7 @@ A virtual network tool (VPN)
```
4. 最后可以用虚拟ip实现设备间相互访问
<img width="506" alt="ssh" src="https://raw.githubusercontent.com/lbl8603/vnt/main/documents/img/ssh.jpg">
<img width="506" alt="ssh" src="https://raw.githubusercontent.com/lbl8603/vnt/dev/documents/img/ssh.jpg">
5. 帮助,使用-h命令查看
### 更多玩法
@@ -84,36 +84,24 @@ features说明
| sm4_cbc | 支持sm4_cbc加密 | 是 |
| server_encrypt | 支持服务端加密 | 是 |
| ip_proxy | 内置ip代理 | 是 |
| port_mapping | 端口映射 | 是 |
| log | 日志 | 是 |
| command | list、route等命令 | 是 |
| file_config | yaml配置文件 | 是 |
| lz4 | lz4压缩 | 是 |
| zstd | zstd压缩 | 否 |
### ip转发/代理
如果编译时去除了内置的ip代理(或使用--no-proxy关闭了代理),则可以使用网卡NAT转发来实现点对网,
一般来说使用网卡NAT转发会比内置的ip代理性能更好
<details> <summary>NAT配置可参考如下示例,点击展开</summary>
### 在出口一端做如下配置
注意原有的-i(入口)和-o(出口)的参数不能少
### windows
参考 https://learn.microsoft.com/zh-cn/virtualization/hyper-v-on-windows/user-guide/setup-nat-network
```shell
#设置nat,名字可以自己取,网段是vnt的网段
New-NetNat -Name vntnat -InternalIPInterfaceAddressPrefix 10.26.0.0/24
#查看设置
Get-NetNat
```
### linux
```shell
# 开启ip转发
sudo sysctl -w net.ipv4.ip_forward=1
@@ -156,7 +144,6 @@ sudo iptables-restore iptables.rules
```
### macos
```shell
# 开启ip转发
sudo sysctl -w net.ipv4.ip_forward=1
@@ -166,7 +153,6 @@ nat on en0 from 10.26.0.0/24 to any -> (en0)
# 加载规则
sudo pfctl -f /etc/pf.conf -e
```
</details>
### 支持平台
@@ -269,15 +255,10 @@ vnt默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突
2. 如果p2p后效果很差,可以选择禁用p2pvnt-cli增加--use-channel relay 参数)
#### 问题4:重启后虚拟IP发生变化,或指定了IP不能启动
##### 可能原因:
设备重启后程序自动获取的id值改变,导致注册时重新分配了新的IP,或是IP冲突
##### 解决方法:
1. 命令行启动增加-d参数(使用配置文件启动则在配置文件中增加device_id参数),要保证每个设备的值都不一样,取值可以任意64位以内字符串
</details>
### 交流群
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "common"
version = "1.2.10"
version = "1.2.9"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+3 -9
View File
@@ -1,6 +1,6 @@
[package]
name = "vnt-cli"
version = "1.2.10"
version = "1.2.9"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -14,8 +14,7 @@ os_info = "3.7.0"
serde = "1.0"
serde_yaml = "0.9.32"
log = "0.4.17"
log4rs = { version = "1.2.0", optional = true }
anyhow = "1.0.82"
log4rs = "1.2.0"
[dependencies.uuid]
version = "1.4.1"
features = [
@@ -29,7 +28,7 @@ sudo = "0.6.0"
winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] }
[features]
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "ip_proxy", "port_mapping", "log", "command", "file_config", "lz4"]
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "ip_proxy", "port_mapping"]
openssl = ["vnt/openssl"]
openssl-vendored = ["vnt/openssl-vendored"]
ring-cipher = ["vnt/ring-cipher"]
@@ -40,11 +39,6 @@ aes_gcm = ["vnt/aes_gcm"]
server_encrypt = ["vnt/server_encrypt"]
ip_proxy = ["vnt/ip_proxy"]
port_mapping = ["vnt/port_mapping"]
lz4 = ["vnt/lz4_compress"]
zstd = ["vnt/zstd_compress"]
log = ["log4rs"]
command = []
file_config = []
[build-dependencies]
embed-manifest = "1.4.0"
rand = "0.8.5"
-8
View File
@@ -95,14 +95,6 @@
### --mapping `<udp:0.0.0.0:80->10.26.0.10:80>`
端口映射,可以设置多个映射地址,例如 '--mapping udp:0.0.0.0:80->10.26.0.10:80 --mapping tcp:0.0.0.0:80->10.26.0.11:81'
表示将本地udp 80端口的数据转发到10.26.0.10:80,将本地tcp 80端口的数据转发到10.26.0.11:81,转发的目的地址可以使用域名+端口
### --compressor `<lz4>`
启用压缩,默认仅支持lz4压缩,开启压缩后,如果数据包长度大于等于128,则会使用压缩,否则还是会按原数据发送
也支持开启zstd压缩,但是需要自行编译,编译时加入参数--features zstd
如果宽度速度比较慢,可以考虑使用高级别的压缩
### -f `<conf>`
指定配置文件
配置文件采用yaml格式,可参考:
-3
View File
@@ -185,10 +185,7 @@ pub fn command_info(vnt: &Vnt) -> Info {
.unwrap_or("None".to_string());
let up = vnt.up_stream();
let down = vnt.down_stream();
#[cfg(feature = "port_mapping")]
let port_mapping_list = vnt.config().port_mapping_list.clone();
#[cfg(not(feature = "port_mapping"))]
let port_mapping_list = vec![];
let in_ips = vnt.config().in_ips.clone();
let out_ips = vnt.config().out_ips.clone();
Info {
-181
View File
@@ -1,181 +0,0 @@
use anyhow::anyhow;
use std::net::Ipv4Addr;
use std::str::FromStr;
use serde::{Deserialize, Serialize};
use crate::config::get_device_id;
use vnt::channel::punch::PunchModel;
use vnt::channel::UseChannelType;
use vnt::cipher::CipherModel;
use vnt::compression::Compressor;
use vnt::core::Config;
#[derive(Serialize, Deserialize, Debug)]
#[serde(default)]
pub struct FileConfig {
#[cfg(target_os = "windows")]
pub tap: bool,
pub token: String,
pub device_id: String,
pub name: String,
pub server_address: String,
pub stun_server: Vec<String>,
pub dns: Vec<String>,
pub in_ips: Vec<String>,
pub out_ips: Vec<String>,
pub password: Option<String>,
pub mtu: Option<u32>,
pub tcp: bool,
pub ip: Option<String>,
pub use_channel: String,
#[cfg(feature = "ip_proxy")]
pub no_proxy: bool,
pub server_encrypt: bool,
pub parallel: usize,
pub cipher_model: Option<String>,
pub finger: bool,
pub punch_model: String,
pub ports: Option<Vec<u16>>,
pub cmd: bool,
pub first_latency: bool,
pub device_name: Option<String>,
pub packet_loss: Option<f64>,
pub packet_delay: u32,
#[cfg(feature = "port_mapping")]
pub mapping: Vec<String>,
pub compressor: Option<String>,
}
impl Default for FileConfig {
fn default() -> Self {
Self {
#[cfg(target_os = "windows")]
tap: false,
token: "".to_string(),
device_id: get_device_id(),
name: os_info::get().to_string(),
server_address: "nat1.wherewego.top:29872".to_string(),
stun_server: vec![
"stun1.l.google.com:19302".to_string(),
"stun2.l.google.com:19302".to_string(),
"stun.miwifi.com:3478".to_string(),
],
dns: vec![],
in_ips: vec![],
out_ips: vec![],
password: None,
mtu: None,
tcp: false,
ip: None,
use_channel: "all".to_string(),
#[cfg(feature = "ip_proxy")]
no_proxy: false,
server_encrypt: false,
parallel: 1,
cipher_model: None,
finger: false,
punch_model: "all".to_string(),
ports: None,
cmd: false,
first_latency: false,
device_name: None,
packet_loss: None,
packet_delay: 0,
#[cfg(feature = "port_mapping")]
mapping: vec![],
compressor: None,
}
}
}
pub fn read_config(file_path: &str) -> anyhow::Result<(Config, bool)> {
let conf = std::fs::read_to_string(file_path)?;
let file_conf = match serde_yaml::from_str::<FileConfig>(&conf) {
Ok(val) => val,
Err(e) => {
log::error!("{:?}", e);
return Err(anyhow!("{}", e));
}
};
if file_conf.token.is_empty() {
return Err(anyhow!("token is_empty"));
}
let in_ips = match common::args_parse::ips_parse(&file_conf.in_ips) {
Ok(in_ips) => in_ips,
Err(e) => {
return Err(anyhow!("in_ips {:?} error:{}", &file_conf.in_ips, e));
}
};
let out_ips = match common::args_parse::out_ips_parse(&file_conf.out_ips) {
Ok(out_ips) => out_ips,
Err(e) => {
return Err(anyhow!("out_ips {:?} error:{}", &file_conf.out_ips, e));
}
};
let virtual_ip = match file_conf.ip.clone().map(|v| Ipv4Addr::from_str(&v)) {
None => None,
Some(r) => Some(r.map_err(|e| anyhow!("ip {:?} error:{}", &file_conf.ip, e))?),
};
let cipher_model = {
#[cfg(not(any(feature = "aes_gcm", feature = "server_encrypt")))]
if file_conf.password.is_some() && file_conf.cipher_model.is_none() {
Err(anyhow!("cipher_model undefined"))?
}
#[cfg(not(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
)))]
{
CipherModel::None
}
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
CipherModel::AesGcm
};
let punch_model = PunchModel::from_str(&file_conf.punch_model).map_err(|e| anyhow!("{}", e))?;
let use_channel_type =
UseChannelType::from_str(&file_conf.use_channel).map_err(|e| anyhow!("{}", e))?;
let compressor = if let Some(compressor) = file_conf.compressor.as_ref() {
Compressor::from_str(compressor).map_err(|e| anyhow!("{}", e))?
} else {
Compressor::None
};
let config = Config::new(
#[cfg(target_os = "windows")]
file_conf.tap,
file_conf.token,
file_conf.device_id,
file_conf.name,
file_conf.server_address,
file_conf.dns,
file_conf.stun_server,
in_ips,
out_ips,
file_conf.password,
file_conf.mtu,
file_conf.tcp,
virtual_ip,
#[cfg(feature = "ip_proxy")]
file_conf.no_proxy,
file_conf.server_encrypt,
file_conf.parallel,
cipher_model,
file_conf.finger,
punch_model,
file_conf.ports,
file_conf.first_latency,
file_conf.device_name,
use_channel_type,
file_conf.packet_loss,
file_conf.packet_delay,
#[cfg(feature = "port_mapping")]
file_conf.mapping,
compressor,
)?;
Ok((config, file_conf.cmd))
}
+166 -7
View File
@@ -1,12 +1,171 @@
#[cfg(feature = "file_config")]
mod file_config;
use std::io;
use std::net::Ipv4Addr;
use std::str::FromStr;
#[cfg(feature = "file_config")]
pub use file_config::read_config;
use serde::{Deserialize, Serialize};
#[cfg(not(feature = "file_config"))]
pub fn read_config(_file_path: &str) -> anyhow::Result<(vnt::core::Config, bool)> {
unimplemented!()
use vnt::channel::punch::PunchModel;
use vnt::channel::UseChannelType;
use vnt::cipher::CipherModel;
use vnt::core::Config;
#[derive(Serialize, Deserialize, Debug)]
#[serde(default)]
pub struct FileConfig {
#[cfg(target_os = "windows")]
pub tap: bool,
pub token: String,
pub device_id: String,
pub name: String,
pub server_address: String,
pub stun_server: Vec<String>,
pub dns: Vec<String>,
pub in_ips: Vec<String>,
pub out_ips: Vec<String>,
pub password: Option<String>,
pub mtu: Option<u32>,
pub tcp: bool,
pub ip: Option<String>,
pub use_channel: String,
#[cfg(feature = "ip_proxy")]
pub no_proxy: bool,
pub server_encrypt: bool,
pub parallel: usize,
pub cipher_model: String,
pub finger: bool,
pub punch_model: String,
pub ports: Option<Vec<u16>>,
pub cmd: bool,
pub first_latency: bool,
pub device_name: Option<String>,
pub packet_loss: Option<f64>,
pub packet_delay: u32,
#[cfg(feature = "port_mapping")]
pub mapping: Vec<String>,
}
impl Default for FileConfig {
fn default() -> Self {
Self {
#[cfg(target_os = "windows")]
tap: false,
token: "".to_string(),
device_id: get_device_id(),
name: os_info::get().to_string(),
server_address: "nat1.wherewego.top:29872".to_string(),
stun_server: vec![
"stun1.l.google.com:19302".to_string(),
"stun2.l.google.com:19302".to_string(),
"stun.miwifi.com:3478".to_string(),
],
dns: vec![],
in_ips: vec![],
out_ips: vec![],
password: None,
mtu: None,
tcp: false,
ip: None,
use_channel: "all".to_string(),
#[cfg(feature = "ip_proxy")]
no_proxy: false,
server_encrypt: false,
parallel: 1,
cipher_model: "aes_gcm".to_string(),
finger: false,
punch_model: "all".to_string(),
ports: None,
cmd: false,
first_latency: false,
device_name: None,
packet_loss: None,
packet_delay: 0,
#[cfg(feature = "port_mapping")]
mapping: vec![],
}
}
}
pub fn read_config(file_path: &str) -> io::Result<(Config, bool)> {
let conf = std::fs::read_to_string(file_path)?;
let file_conf = match serde_yaml::from_str::<FileConfig>(&conf) {
Ok(val) => val,
Err(e) => {
log::error!("{:?}", e);
return Err(io::Error::new(io::ErrorKind::Other, format!("{}", e)));
}
};
if file_conf.token.is_empty() {
return Err(io::Error::new(io::ErrorKind::Other, "token is_empty"));
}
let in_ips = match common::args_parse::ips_parse(&file_conf.in_ips) {
Ok(in_ips) => in_ips,
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("in_ips {:?} error:{}", &file_conf.in_ips, e),
));
}
};
let out_ips = match common::args_parse::out_ips_parse(&file_conf.out_ips) {
Ok(out_ips) => out_ips,
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("out_ips {:?} error:{}", &file_conf.out_ips, e),
));
}
};
let virtual_ip = match file_conf.ip.clone().map(|v| Ipv4Addr::from_str(&v)) {
None => None,
Some(r) => Some(r.map_err(|e| {
io::Error::new(
io::ErrorKind::Other,
format!("ip {:?} error:{}", &file_conf.ip, e),
)
})?),
};
let cipher_model = CipherModel::from_str(&file_conf.cipher_model)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
let punch_model = PunchModel::from_str(&file_conf.punch_model)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
let use_channel_type = UseChannelType::from_str(&file_conf.use_channel)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
let config = Config::new(
#[cfg(target_os = "windows")]
file_conf.tap,
file_conf.token,
file_conf.device_id,
file_conf.name,
file_conf.server_address,
file_conf.dns,
file_conf.stun_server,
in_ips,
out_ips,
file_conf.password,
file_conf.mtu,
file_conf.tcp,
virtual_ip,
#[cfg(feature = "ip_proxy")]
file_conf.no_proxy,
file_conf.server_encrypt,
file_conf.parallel,
cipher_model,
file_conf.finger,
punch_model,
file_conf.ports,
file_conf.first_latency,
file_conf.device_name,
use_channel_type,
file_conf.packet_loss,
file_conf.packet_delay,
#[cfg(feature = "port_mapping")]
file_conf.mapping,
)
.unwrap();
Ok((config, file_conf.cmd))
}
pub fn get_device_id() -> String {
+48 -81
View File
@@ -1,8 +1,7 @@
use anyhow::anyhow;
use std::io;
use std::net::Ipv4Addr;
use std::path::PathBuf;
use std::str::FromStr;
use std::{io, thread};
use console::style;
use getopts::Options;
@@ -11,13 +10,10 @@ use common::args_parse::{ips_parse, out_ips_parse};
use vnt::channel::punch::PunchModel;
use vnt::channel::UseChannelType;
use vnt::cipher::CipherModel;
use vnt::compression::Compressor;
use vnt::core::{Config, Vnt};
#[cfg(feature = "command")]
mod command;
mod config;
#[cfg(feature = "command")]
mod console_out;
mod generated_serial_number;
mod root_check;
@@ -45,7 +41,6 @@ pub fn app_home() -> io::Result<PathBuf> {
}
fn main() {
#[cfg(feature = "log")]
let _ = log4rs::init_file("log4rs.yaml", Default::default());
let args: Vec<String> = std::env::args().collect();
let program = args[0].clone();
@@ -80,7 +75,6 @@ fn main() {
opts.optmulti("", "dns", "dns", "<dns>");
opts.optmulti("", "mapping", "mapping", "<mapping>");
opts.optopt("f", "", "配置文件", "<conf>");
opts.optopt("", "compressor", "压缩算法", "<lz4>");
//"后台运行时,查看其他设备列表"
opts.optflag("", "list", "后台运行时,查看其他设备列表");
opts.optflag("", "all", "后台运行时,查看其他设备完整信息");
@@ -106,7 +100,6 @@ fn main() {
sudo::escalate_if_needed().unwrap();
return;
}
#[cfg(feature = "command")]
if matches.opt_present("list") {
command::command(command::CommandEnum::List);
return;
@@ -297,13 +290,6 @@ fn main() {
.unwrap_or(0);
#[cfg(feature = "port_mapping")]
let port_mapping_list = matches.opt_strs("mapping");
let compressor = if let Some(compressor) = matches.opt_str("compressor").as_ref() {
Compressor::from_str(compressor)
.map_err(|e| anyhow!("{}", e))
.unwrap()
} else {
Compressor::None
};
let config = match Config::new(
#[cfg(target_os = "windows")]
tap,
@@ -334,11 +320,10 @@ fn main() {
packet_delay,
#[cfg(feature = "port_mapping")]
port_mapping_list,
compressor,
) {
Ok(config) => config,
Err(e) => {
println!("config.toml error: {}", e);
println!("config error: {}", e);
return;
}
};
@@ -357,7 +342,7 @@ fn main() {
mod callback;
fn main0(config: Config, _show_cmd: bool) {
fn main0(config: Config, show_cmd: bool) {
#[cfg(feature = "port_mapping")]
for (is_tcp, addr, dest) in config.port_mapping_list.iter() {
if *is_tcp {
@@ -367,40 +352,36 @@ fn main0(config: Config, _show_cmd: bool) {
}
}
let vnt_util = Vnt::new(config, callback::VntHandler {}).unwrap();
#[cfg(feature = "command")]
{
let vnt_c = vnt_util.clone();
std::thread::Builder::new()
.name("CommandServer".into())
.spawn(move || {
if let Err(e) = command::server::CommandServer::new().start(vnt_c) {
log::warn!("cmd:{:?}", e);
}
})
.expect("CommandServer");
if _show_cmd {
let mut cmd = String::new();
loop {
cmd.clear();
println!("======== input:list,info,route,all,stop ========");
match io::stdin().read_line(&mut cmd) {
Ok(len) => {
if !command(&cmd[..len], &vnt_util) {
break;
}
}
Err(e) => {
println!("input err:{}", e);
let vnt_c = vnt_util.clone();
thread::Builder::new()
.name("CommandServer".into())
.spawn(move || {
if let Err(e) = command::server::CommandServer::new().start(vnt_c) {
log::warn!("cmd:{:?}", e);
}
})
.expect("CommandServer");
if show_cmd {
let mut cmd = String::new();
loop {
cmd.clear();
println!("======== input:list,info,route,all,stop ========");
match io::stdin().read_line(&mut cmd) {
Ok(len) => {
if !command(&cmd[..len], &vnt_util) {
break;
}
}
Err(e) => {
println!("input err:{}", e);
break;
}
}
}
}
vnt_util.wait()
}
#[cfg(feature = "command")]
fn command(cmd: &str, vnt: &Vnt) -> bool {
if cmd.is_empty() {
return false;
@@ -446,11 +427,10 @@ fn print_usage(program: &str, _opts: Options) {
println!(" -s <server> 注册和中继服务器地址,以'TXT:'开头表示解析TXT记录");
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可使用多个地址,如-e stun1.l.google.com -e stun2.l.google.com");
#[cfg(target_os = "windows")]
println!(
" -a 使用tap模式,默认使用tun模式,使用tap时需要配合'--nic'参数指定tap网卡"
);
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,可指定多个网段");
#[cfg(feature = "ip_proxy")]
println!(" -o <out-ip> 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段");
#[cfg(not(any(
feature = "aes_gcm",
@@ -482,7 +462,6 @@ fn print_usage(program: &str, _opts: Options) {
#[cfg(feature = "server_encrypt")]
println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确");
println!(" -u <mtu> 自定义mtu(不加密默认为1450,加密默认为1410)");
#[cfg(feature = "file_config")]
println!(" -f <conf_file> 读取配置文件中的配置");
println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp");
@@ -499,7 +478,6 @@ fn print_usage(program: &str, _opts: Options) {
}
println!(" --punch <punch> 取值ipv4/ipv6/all,ipv4表示仅使用ipv4打洞");
println!(" --ports <port,port> 取值0~65535,指定本地监听的一组端口,默认监听两个随机端口,使用过多端口会增加网络负担");
#[cfg(feature = "command")]
println!(" --cmd 开启交互式命令,使用此参数开启控制台输入");
#[cfg(feature = "ip_proxy")]
println!(" --no-proxy 关闭内置代理,如需点对网则需要配置网卡NAT转发");
@@ -513,38 +491,28 @@ fn print_usage(program: &str, _opts: Options) {
println!(" --dns <host:port> DNS服务器地址,可使用多个dns,不指定时使用系统解析");
#[cfg(feature = "port_mapping")]
println!(" --mapping <mapping> 端口映射,例如 --mapping udp:0.0.0.0:80->10.26.0.10:80 --mapping tcp:0.0.0.0:80->10.26.0.10:80");
#[cfg(all(feature = "lz4", feature = "zstd"))]
println!(" --compressor <lz4> 启用压缩,可选值lz4/zstd<,level>,level为压缩级别,例如 --compressor lz4 或--compressor zstd,10");
#[cfg(feature = "lz4")]
#[cfg(not(feature = "zstd"))]
println!(" --compressor <lz4> 启用压缩,可选值lz4,例如 --compressor lz4");
#[cfg(feature = "zstd")]
#[cfg(not(feature = "lz4"))]
println!(" --compressor <zstd> 启用压缩,可选值zstd<,level>,level为压缩级别,例如 --compressor zstd,10");
println!();
#[cfg(feature = "command")]
{
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!(
" --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 帮助");
}
@@ -552,7 +520,6 @@ fn green(str: String) -> impl std::fmt::Display {
style(str).green()
}
#[cfg(feature = "command")]
fn yellow(str: String) -> impl std::fmt::Display {
style(str).yellow()
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "vnt-jni"
version = "1.2.10"
version = "1.2.9"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-2
View File
@@ -7,7 +7,6 @@ use jni::JNIEnv;
use vnt::channel::punch::PunchModel;
use vnt::channel::UseChannelType;
use vnt::cipher::CipherModel;
use vnt::compression::Compressor;
use vnt::core::Config;
use crate::utils::*;
@@ -119,7 +118,6 @@ pub fn new_config(env: &mut JNIEnv, config: JObject) -> Result<Config, Error> {
packet_loss_rate,
packet_delay,
port_mapping,
Compressor::None,
) {
Ok(config) => config,
Err(e) => {
+4 -7
View File
@@ -1,6 +1,6 @@
[package]
name = "vnt"
version = "1.2.10"
version = "1.2.9"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -30,15 +30,14 @@ spki = { version = "0.7.2", features = ["fingerprint", "alloc", "base64"], optio
openssl-sys = { git = "https://github.com/lbl8603/rust-openssl", optional = true }
libsm = { git = "https://github.com/lbl8603/libsm", optional = true }
mio = { version = "0.8.10", features = ["os-poll", "net", "os-ext"] }
mio = { version = "0.8.10", features = ["os-poll", "net"] }
crossbeam-queue = "0.3.11"
anyhow = "1.0.82"
dns-parser = "0.8.0"
tokio = { version = "1.37.0", features = ["full"], optional = true }
lz4_flex = { version = "0.11", default-features = false, optional = true }
zstd = { version = "0.13.1", optional = true }
[target.'cfg(target_os = "windows")'.dependencies]
libloading = "0.8.0"
@@ -48,7 +47,7 @@ protobuf-codegen = "3.2.0"
protoc-bin-vendored = "3.0.0"
[features]
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "ip_proxy", "port_mapping", "lz4_compress","zstd_compress"]
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "ip_proxy", "port_mapping"]
openssl = ["openssl-sys"]
# 从源码编译
openssl-vendored = ["openssl-sys/vendored"]
@@ -60,5 +59,3 @@ aes_gcm = ["aes-gcm"]
server_encrypt = ["aes-gcm", "rsa", "spki"]
ip_proxy = ["tokio"]
port_mapping = ["tokio"]
lz4_compress = ["lz4_flex"]
zstd_compress = ["zstd"]
+10 -1
View File
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV6, UdpSocket};
use std::ops::Deref;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;
use std::time::{Duration, Instant};
use std::{io, thread};
@@ -48,6 +48,7 @@ impl ChannelContext {
tcp_map: RwLock::new(HashMap::with_capacity(64)),
route_table: RouteTable::new(use_channel_type, first_latency, channel_num),
is_tcp,
state: AtomicBool::new(true),
packet_loss_rate,
packet_delay,
main_index: AtomicUsize::new(0),
@@ -85,6 +86,8 @@ pub struct ContextInner {
pub route_table: RouteTable,
// 是否使用tcp连接服务器
is_tcp: bool,
//状态
state: AtomicBool,
//控制丢包率,取值v=[0,100_0000] 丢包率r=v/100_0000
packet_loss_rate: u32,
//控制延迟
@@ -97,6 +100,12 @@ impl ContextInner {
pub fn use_channel_type(&self) -> UseChannelType {
self.route_table.use_channel_type
}
pub fn is_stop(&self) -> bool {
!self.state.load(Ordering::Acquire)
}
pub fn stop(&self) {
self.state.store(false, Ordering::Release);
}
/// 通过sub_udp_socket是否为空来判断是否为锥形网络
pub fn is_cone(&self) -> bool {
self.sub_udp_socket.read().is_empty()
+1 -7
View File
@@ -2,11 +2,5 @@ use crate::channel::context::ChannelContext;
use crate::channel::RouteKey;
pub trait RecvChannelHandler: Clone + Send + 'static {
fn handle(
&mut self,
buf: &mut [u8],
extend: &mut [u8],
route_key: RouteKey,
context: &ChannelContext,
);
fn handle(&mut self, buf: &mut [u8], route_key: RouteKey, context: &ChannelContext);
}
+1 -1
View File
@@ -18,7 +18,7 @@ pub mod sender;
pub mod tcp_channel;
pub mod udp_channel;
pub const BUFFER_SIZE: usize = 1024 * 16;
const BUFFER_SIZE: usize = 1024 * 16;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum UseChannelType {
Relay,
+4 -10
View File
@@ -87,7 +87,6 @@ where
let mut read_map: HashMap<Token, (RouteKey, TcpStream, Box<[u8; BUFFER_SIZE]>, usize)> =
HashMap::with_capacity(32);
let mut extend = [0; BUFFER_SIZE];
loop {
poll.poll(&mut events, None)?;
for event in events.iter() {
@@ -133,13 +132,9 @@ where
}
token => {
if event.is_readable() {
if let Err(e) = readable_handle(
&token,
&mut read_map,
&mut recv_handler,
&context,
&mut extend,
) {
if let Err(e) =
readable_handle(&token, &mut read_map, &mut recv_handler, &context)
{
closed_handle_r(&token, &mut read_map);
log::warn!("{:?}", e);
if let Err(e) = write_waker.notify(token, false) {
@@ -344,7 +339,6 @@ fn readable_handle<H>(
map: &mut HashMap<Token, (RouteKey, TcpStream, Box<[u8; BUFFER_SIZE]>, usize)>,
recv_handler: &mut H,
context: &ChannelContext,
extend: &mut [u8],
) -> io::Result<()>
where
H: RecvChannelHandler,
@@ -366,7 +360,7 @@ where
}
*begin += len;
if end > 4 && *begin == end {
recv_handler.handle(&mut buf[4..end], extend, *route_key, context);
recv_handler.handle(&mut buf[4..end], *route_key, context);
*begin = 0;
}
}
-4
View File
@@ -70,7 +70,6 @@ where
{
let mut events = Events::with_capacity(1024);
let mut buf = [0; BUFFER_SIZE];
let mut extend = [0; BUFFER_SIZE];
let mut read_map: HashMap<Token, UdpSocket> = HashMap::with_capacity(32);
loop {
poll.poll(&mut events, None)?;
@@ -116,7 +115,6 @@ where
Ok((len, addr)) => {
recv_handler.handle(
&mut buf[..len],
&mut extend,
RouteKey::new(false, token.0, addr),
&context,
);
@@ -254,7 +252,6 @@ where
}
let mut events = Events::with_capacity(udps.len());
let mut extend = [0; BUFFER_SIZE];
loop {
poll.poll(&mut events, None)?;
for x in events.iter() {
@@ -273,7 +270,6 @@ where
Ok((len, addr)) => {
recv_handler.handle(
&mut buf[..len],
&mut extend,
RouteKey::new(false, index, addr),
&context,
);
-4
View File
@@ -52,13 +52,9 @@ pub enum CipherModel {
impl Display for CipherModel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let str = match self {
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
CipherModel::AesGcm => "aes_gcm".to_string(),
#[cfg(feature = "aes_cbc")]
CipherModel::AesCbc => "aes_cbc".to_string(),
#[cfg(feature = "aes_ecb")]
CipherModel::AesEcb => "aes_ecb".to_string(),
#[cfg(feature = "sm4_cbc")]
CipherModel::Sm4Cbc => "sm4_cbc".to_string(),
CipherModel::None => "none".to_string(),
};
-33
View File
@@ -1,33 +0,0 @@
use anyhow::anyhow;
use crate::protocol::NetPacket;
#[derive(Clone)]
pub struct Lz4Compressor;
impl Lz4Compressor {
pub fn compress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
in_net_packet: &NetPacket<I>,
out: &mut NetPacket<O>,
) -> anyhow::Result<()> {
out.set_data_len_max();
let len = match lz4_flex::compress_into(in_net_packet.payload(), out.payload_mut()) {
Ok(len) => len,
Err(e) => Err(anyhow!("Lz4 compress {}", e))?,
};
out.set_payload_len(len)?;
Ok(())
}
pub fn decompress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
in_net_packet: &NetPacket<I>,
out: &mut NetPacket<O>,
) -> anyhow::Result<()> {
out.set_data_len_max();
let len = match lz4_flex::decompress_into(in_net_packet.payload(), out.payload_mut()) {
Ok(len) => len,
Err(e) => Err(anyhow!("Lz4 decompress {}", e))?,
};
out.set_payload_len(len)?;
Ok(())
}
}
-218
View File
@@ -1,218 +0,0 @@
use std::str::FromStr;
use anyhow::anyhow;
#[cfg(feature = "lz4_compress")]
use crate::compression::lz4_compress::Lz4Compressor;
#[cfg(feature = "zstd_compress")]
use crate::compression::zstd_compress::ZstdCompressor;
use crate::protocol::extension::CompressionAlgorithm;
#[cfg(feature = "zstd_compress")]
use zstd::zstd_safe::CompressionLevel;
use crate::protocol::NetPacket;
#[cfg(feature = "lz4_compress")]
mod lz4_compress;
#[cfg(feature = "zstd_compress")]
mod zstd_compress;
#[derive(Clone, Copy, Debug)]
pub enum Compressor {
#[cfg(feature = "lz4_compress")]
Lz4,
#[cfg(feature = "zstd_compress")]
Zstd(CompressionLevel),
None,
}
impl FromStr for Compressor {
type Err = String;
#[cfg(not(any(feature = "lz4_compress", feature = "zstd_compress")))]
fn from_str(s: &str) -> Result<Self, Self::Err> {
Err(format!("not match '{}', Compression not supported", s))
}
#[cfg(any(feature = "lz4_compress", feature = "zstd_compress"))]
fn from_str(s: &str) -> Result<Self, Self::Err> {
let str = s.trim().to_lowercase();
match str.as_str() {
#[cfg(feature = "lz4_compress")]
"lz4" => Ok(Compressor::Lz4),
#[cfg(feature = "zstd_compress")]
"zstd" => Ok(Compressor::Zstd(9)),
"none" => Ok(Compressor::None),
_ => {
#[cfg(feature = "zstd_compress")]
{
let string_array: Vec<String> = str.split(',').map(|s| s.to_string()).collect();
if string_array.len() != 2 || string_array[0] != "zstd" {
return Err(format!("not match '{}', exp: zstd,10", s));
}
return match CompressionLevel::from_str(&string_array[1]) {
Ok(level) => Ok(Compressor::Zstd(level)),
Err(_) => Err(format!("not match '{}', exp: zstd,10", s)),
};
}
#[cfg(not(feature = "zstd_compress"))]
#[cfg(feature = "lz4_compress")]
return Err(format!("not match '{}', exp: lz4", s));
}
}
}
}
#[cfg(not(any(feature = "lz4_compress", feature = "zstd_compress")))]
impl Compressor {
pub fn compress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
&self,
_in_net_packet: &NetPacket<I>,
_out: &mut NetPacket<O>,
) -> anyhow::Result<bool> {
Ok(false)
}
pub fn decompress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
_algorithm: CompressionAlgorithm,
_in_net_packet: &NetPacket<I>,
_out: &mut NetPacket<O>,
) -> anyhow::Result<()> {
Err(anyhow!("Unsupported decompress"))
}
}
#[cfg(any(feature = "lz4_compress", feature = "zstd_compress"))]
impl Compressor {
pub fn compress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
&self,
in_net_packet: &NetPacket<I>,
out: &mut NetPacket<O>,
) -> anyhow::Result<bool> {
match self {
#[cfg(feature = "lz4_compress")]
Compressor::Lz4 => {
if in_net_packet.data_len() < 128 {
return Ok(false);
}
Lz4Compressor::compress(in_net_packet, out)?;
let mut compression_extension_tail = out.append_compression_extension_tail()?;
compression_extension_tail.set_algorithm(CompressionAlgorithm::Lz4);
//压缩没效果,则放弃压缩
if out.data_len() >= in_net_packet.data_len() - 16 {
return Ok(false);
}
return Ok(true);
}
#[cfg(feature = "zstd_compress")]
Compressor::Zstd(level) => {
if in_net_packet.data_len() < 128 {
return Ok(false);
}
ZstdCompressor::compress(*level, in_net_packet, out)?;
let mut compression_extension_tail = out.append_compression_extension_tail()?;
compression_extension_tail.set_algorithm(CompressionAlgorithm::Zstd);
//压缩没效果,则放弃压缩
if out.data_len() >= in_net_packet.data_len() - 16 {
return Ok(false);
}
return Ok(true);
}
Compressor::None => {}
}
Ok(false)
}
pub fn decompress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
algorithm: CompressionAlgorithm,
in_net_packet: &NetPacket<I>,
out: &mut NetPacket<O>,
) -> anyhow::Result<()> {
match algorithm {
#[cfg(feature = "lz4_compress")]
CompressionAlgorithm::Lz4 => Lz4Compressor::decompress(in_net_packet, out),
#[cfg(feature = "zstd_compress")]
CompressionAlgorithm::Zstd => ZstdCompressor::decompress(in_net_packet, out),
_ => Err(anyhow!("Unknown decompress {:?}", algorithm)),
}
}
}
#[test]
fn test_lz4() {
use crate::protocol::extension::{CompressionAlgorithm, ExtensionTailPacket};
let lz4 = Compressor::Lz4;
let in_packet = NetPacket::new([
65, 108, 105, 99, 101, 32, 119, 97, 116, 32, 98, 101, 103, 105, 110, 110, 105, 110, 103,
32, 116, 111, 32, 103, 101, 116, 32, 118, 101, 114, 121, 32, 116, 105, 114, 101, 100, 32,
111, 102, 32, 115, 105, 116, 116, 105, 110, 103, 32, 98, 121, 32, 104, 101, 114, 32, 115,
105, 115, 116, 101, 114, 32, 111, 110, 32, 116, 104, 101, 32, 98, 97, 110, 107, 44, 32, 97,
110, 100, 32, 111, 102, 32, 104, 97, 118, 105, 110, 103, 32, 110, 111, 116, 104, 105, 110,
103, 32, 116, 111, 32, 100, 111, 58, 32, 111, 110, 99, 101, 32, 111, 114, 32, 116, 119,
105, 99, 101, 32, 115, 104, 101, 32, 104, 97, 100, 32, 112, 101, 101, 112, 101, 100, 32,
105, 110, 116, 111, 32, 116, 104, 101, 32, 98, 111, 111, 107, 32, 104, 101, 114, 32, 115,
105, 115, 116, 101, 114, 32, 119, 97, 115, 32, 114, 101, 97, 100, 105, 110, 103, 44, 32,
98, 117, 116, 32, 105, 116, 32, 104, 97, 100, 32, 110, 111, 32, 112, 105, 99, 116, 117,
114, 101, 115, 32, 111, 114, 32, 99, 111, 110, 118, 101, 114, 115, 97, 116, 105,
])
.unwrap();
let mut out_packet = NetPacket::new([0; 1000]).unwrap();
let mut src_out_packet = NetPacket::new([0; 1000]).unwrap();
lz4.compress(&in_packet, &mut out_packet).unwrap();
let tail = out_packet.split_tail_packet().unwrap();
match tail {
ExtensionTailPacket::Compression(c) => match c.algorithm() {
CompressionAlgorithm::Lz4 => {
Compressor::decompress(CompressionAlgorithm::Lz4, &out_packet, &mut src_out_packet)
.unwrap();
}
_ => {
unimplemented!()
}
},
ExtensionTailPacket::Unknown => {
unimplemented!()
}
}
assert!(!out_packet.is_extension());
assert_eq!(in_packet.payload(), src_out_packet.payload())
}
#[test]
fn test_zstd() {
use crate::protocol::extension::{CompressionAlgorithm, ExtensionTailPacket};
let zstd = Compressor::Zstd(22);
let in_packet = NetPacket::new([
65, 108, 105, 99, 101, 32, 119, 97, 115, 32, 98, 101, 103, 105, 110, 110, 105, 110, 103,
32, 116, 111, 32, 103, 101, 116, 32, 118, 101, 114, 121, 32, 116, 105, 114, 101, 100, 32,
111, 102, 32, 115, 105, 116, 116, 105, 110, 103, 32, 98, 121, 32, 104, 101, 114, 32, 115,
105, 115, 116, 101, 114, 32, 111, 110, 32, 116, 104, 101, 32, 98, 97, 110, 107, 44, 32, 97,
110, 100, 32, 111, 102, 32, 104, 97, 118, 105, 110, 103, 32, 110, 111, 116, 104, 105, 110,
103, 32, 116, 111, 32, 100, 111, 58, 32, 111, 110, 99, 101, 32, 111, 114, 32, 116, 119,
105, 99, 101, 32, 115, 104, 101, 32, 104, 97, 100, 32, 112, 101, 101, 112, 101, 100, 32,
105, 110, 116, 111, 32, 116, 104, 101, 32, 98, 111, 111, 107, 32, 104, 101, 114, 32, 115,
105, 115, 116, 101, 114, 32, 119, 97, 115, 32, 114, 101, 97, 100, 105, 110, 103, 44, 32,
98, 117, 116, 32, 105, 116, 32, 104, 97, 100, 32, 110, 111, 32, 112, 105, 99, 116, 117,
114, 101, 115, 32, 111, 114, 32, 99, 111, 110, 118, 101, 114, 115, 97, 116, 105,
])
.unwrap();
let mut out_packet = NetPacket::new([0; 1000]).unwrap();
let mut src_out_packet = NetPacket::new([0; 1000]).unwrap();
zstd.compress(&in_packet, &mut out_packet).unwrap();
let tail = out_packet.split_tail_packet().unwrap();
match tail {
ExtensionTailPacket::Compression(c) => match c.algorithm() {
CompressionAlgorithm::Zstd => {
Compressor::decompress(
CompressionAlgorithm::Zstd,
&out_packet,
&mut src_out_packet,
)
.unwrap();
}
_ => {
unimplemented!()
}
},
ExtensionTailPacket::Unknown => {
unimplemented!()
}
}
assert!(!out_packet.is_extension());
assert_eq!(in_packet.payload(), src_out_packet.payload())
}
-38
View File
@@ -1,38 +0,0 @@
use crate::protocol::NetPacket;
use anyhow::anyhow;
use zstd::zstd_safe::CompressionLevel;
#[derive(Clone)]
pub struct ZstdCompressor;
impl ZstdCompressor {
pub fn compress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
compression_level: CompressionLevel,
in_net_packet: &NetPacket<I>,
out: &mut NetPacket<O>,
) -> anyhow::Result<()> {
out.set_data_len_max();
let len = match zstd::zstd_safe::compress(
out.payload_mut(),
in_net_packet.payload(),
compression_level,
) {
Ok(len) => len,
Err(e) => Err(anyhow!("zstd compress {}", e))?,
};
out.set_payload_len(len)?;
Ok(())
}
pub fn decompress<I: AsRef<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
in_net_packet: &NetPacket<I>,
out: &mut NetPacket<O>,
) -> anyhow::Result<()> {
out.set_data_len_max();
let len = match zstd::zstd_safe::decompress(out.payload_mut(), in_net_packet.payload()) {
Ok(len) => len,
Err(e) => Err(anyhow!("zstd decompress {}", e))?,
};
out.set_payload_len(len)?;
Ok(())
}
}
+16 -25
View File
@@ -6,6 +6,7 @@ use std::time::Duration;
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::{Mutex, RwLock};
use rand::Rng;
use rsa::signature::digest::Digest;
#[cfg(not(target_os = "android"))]
use tun::device::IFace;
@@ -38,7 +39,7 @@ pub struct Vnt {
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
nat_test: NatTest,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
context: Arc<Mutex<Option<ChannelContext>>>,
context: ChannelContext,
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
down_count_watcher: WatchU64Adder,
up_count_watcher: WatchSingleU64Adder,
@@ -47,7 +48,7 @@ pub struct Vnt {
impl Vnt {
pub fn new<Call: VntCallback>(config: Config, callback: Call) -> anyhow::Result<Self> {
log::info!("config.toml:{:?}", config);
log::info!("config:{:?}", config);
//服务端非对称加密
#[cfg(feature = "server_encrypt")]
let rsa_cipher: Arc<Mutex<Option<RsaCipher>>> = Arc::new(Mutex::new(None));
@@ -79,7 +80,14 @@ impl Vnt {
config.name.clone(),
config.token.clone(),
config.ip,
config.password_hash(),
config.password.as_ref().map(|v| {
let mut hasher = sha2::Sha256::new();
hasher.update(config.cipher_model.to_string().as_bytes());
hasher.update(v.as_bytes());
hasher.update(config.token.as_bytes());
let key: [u8; 32] = hasher.finalize().into();
key[16..].try_into().unwrap()
}),
config.server_encrypt,
config.device_id.clone(),
config.server_address_str.clone(),
@@ -132,11 +140,8 @@ impl Vnt {
// pc上先创建虚拟网卡
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
let device = {
log::info!("开始创建tun");
let device = tun_tap_device::create_device(&config)?;
log::info!("创建tun成功");
let tun_info = DeviceInfo::new(device.name()?, device.version()?);
log::info!("tun信息{:?}", tun_info);
callback.create_tun(tun_info);
device
};
@@ -162,10 +167,7 @@ impl Vnt {
let down_counter =
U64Adder::with_capacity(config.ports.as_ref().map(|v| v.len()).unwrap_or_default() + 8);
let down_count_watcher = down_counter.watch();
let handshake = Handshake::new(
#[cfg(feature = "server_encrypt")]
rsa_cipher.clone(),
);
let handshake = Handshake::new(rsa_cipher.clone());
let up_counter = SingleU64Adder::new();
let up_count_watcher = up_counter.watch();
let tun_helper = TunDeviceHelper::new(
@@ -180,7 +182,6 @@ impl Vnt {
config.parallel,
up_counter,
device_list.clone(),
config.compressor,
);
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
let device_adapter = DeviceAdapter::new(device.clone());
@@ -277,7 +278,7 @@ impl Vnt {
current_device,
nat_test,
device_list,
context: Arc::new(Mutex::new(Some(context))),
context,
peer_nat_info_map,
down_count_watcher,
up_count_watcher,
@@ -394,24 +395,16 @@ impl Vnt {
device_list
}
pub fn route(&self, ip: &Ipv4Addr) -> Option<Route> {
self.context.lock().as_ref()?.route_table.route_one(ip)
self.context.route_table.route_one(ip)
}
pub fn is_gateway(&self, ip: &Ipv4Addr) -> bool {
self.current_device.load().is_gateway(ip)
}
pub fn route_key(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
self.context
.lock()
.as_ref()?
.route_table
.route_to_id(route_key)
self.context.route_table.route_to_id(route_key)
}
pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec<Route>)> {
if let Some(context) = self.context.lock().as_ref() {
context.route_table.route_table()
} else {
vec![]
}
self.context.route_table.route_table()
}
pub fn up_stream(&self) -> u64 {
self.up_count_watcher.get()
@@ -420,8 +413,6 @@ impl Vnt {
self.down_count_watcher.get()
}
pub fn stop(&self) {
//退出协助回收资源
let _ = self.context.lock().take();
self.stop_manager.stop()
}
pub fn wait(&self) {
-34
View File
@@ -7,7 +7,6 @@ pub use conn::Vnt;
use crate::channel::punch::PunchModel;
use crate::channel::UseChannelType;
use crate::cipher::CipherModel;
use crate::compression::Compressor;
use crate::util::{address_choose, dns_query_all};
mod conn;
@@ -47,7 +46,6 @@ pub struct Config {
// 端口映射
#[cfg(feature = "port_mapping")]
pub port_mapping_list: Vec<(bool, SocketAddr, String)>,
pub compressor: Compressor,
}
impl Config {
@@ -79,7 +77,6 @@ impl Config {
packet_delay: u32,
// 例如 [udp:127.0.0.1:80->10.26.0.10:8080,tcp:127.0.0.1:80->10.26.0.10:8080]
#[cfg(feature = "port_mapping")] port_mapping_list: Vec<String>,
compressor: Compressor,
) -> anyhow::Result<Self> {
for x in stun_server.iter_mut() {
if !x.contains(":") {
@@ -143,37 +140,6 @@ impl Config {
packet_delay,
#[cfg(feature = "port_mapping")]
port_mapping_list,
compressor,
})
}
}
impl Config {
#[cfg(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
))]
pub fn password_hash(&self) -> Option<[u8; 16]> {
self.password.as_ref().map(|v| {
use sha2::Digest;
let mut hasher = sha2::Sha256::new();
hasher.update(self.cipher_model.to_string().as_bytes());
hasher.update(v.as_bytes());
hasher.update(self.token.as_bytes());
let key: [u8; 32] = hasher.finalize().into();
key[16..].try_into().unwrap()
})
}
#[cfg(not(any(
feature = "aes_gcm",
feature = "server_encrypt",
feature = "aes_cbc",
feature = "aes_ecb",
feature = "sm4_cbc"
)))]
pub fn password_hash(&self) -> Option<[u8; 16]> {
None
}
}
-24
View File
@@ -1,24 +0,0 @@
use crate::compression::Compressor;
use crate::protocol::extension::ExtensionTailPacket;
use crate::protocol::NetPacket;
use anyhow::anyhow;
pub fn handle_extension_tail<I: AsRef<[u8]> + AsMut<[u8]>, O: AsRef<[u8]> + AsMut<[u8]>>(
in_net_packet: &mut NetPacket<I>,
out: &mut NetPacket<O>,
) -> anyhow::Result<bool> {
if in_net_packet.is_extension() {
let tail_packet = in_net_packet.split_tail_packet()?;
match tail_packet {
ExtensionTailPacket::Compression(extension) => {
let compression_algorithm = extension.algorithm();
Compressor::decompress(compression_algorithm, &in_net_packet, out)?;
out.head_mut().copy_from_slice(in_net_packet.head());
Ok(true)
}
ExtensionTailPacket::Unknown => Err(anyhow!("Unknown decompress")),
}
} else {
Ok(false)
}
}
+1 -7
View File
@@ -4,7 +4,6 @@ use std::sync::Arc;
use std::time::{Duration, Instant};
use crossbeam_utils::atomic::AtomicCell;
#[cfg(feature = "server_encrypt")]
use parking_lot::Mutex;
use protobuf::Message;
@@ -29,16 +28,12 @@ pub enum HandshakeEnum {
#[derive(Clone)]
pub struct Handshake {
time: Arc<AtomicCell<Instant>>,
#[cfg(feature = "server_encrypt")]
rsa_cipher: Arc<Mutex<Option<RsaCipher>>>,
}
impl Handshake {
pub fn new(
#[cfg(feature = "server_encrypt")] rsa_cipher: Arc<Mutex<Option<RsaCipher>>>,
) -> Self {
pub fn new(rsa_cipher: Arc<Mutex<Option<RsaCipher>>>) -> Self {
Handshake {
time: Arc::new(AtomicCell::new(Instant::now() - Duration::from_secs(60))),
#[cfg(feature = "server_encrypt")]
rsa_cipher,
}
}
@@ -59,7 +54,6 @@ impl Handshake {
let mut request = HandshakeRequest::new();
request.secret = secret;
request.version = crate::VNT_VERSION.to_string();
#[cfg(feature = "server_encrypt")]
if let Some(finger) = self.rsa_cipher.lock().as_ref().map(|v| v.finger().clone()) {
request.key_finger = finger;
}
-1
View File
@@ -2,7 +2,6 @@ use crossbeam_utils::atomic::AtomicCell;
use std::net::{Ipv4Addr, SocketAddr};
pub mod callback;
mod extension;
pub mod handshaker;
pub mod maintain;
pub mod recv_data;
+1 -14
View File
@@ -14,7 +14,6 @@ use crate::channel::punch::NatInfo;
use crate::channel::{Route, RouteKey};
use crate::cipher::Cipher;
use crate::external_route::AllowExternalRoute;
use crate::handle::extension::handle_extension_tail;
use crate::handle::maintain::PunchSender;
use crate::handle::recv_data::PacketHandler;
use crate::handle::CurrentDeviceInfo;
@@ -71,26 +70,14 @@ impl PacketHandler for ClientPacketHandler {
fn handle(
&self,
mut net_packet: NetPacket<&mut [u8]>,
mut extend: NetPacket<&mut [u8]>,
route_key: RouteKey,
context: &ChannelContext,
current_device: &CurrentDeviceInfo,
) -> anyhow::Result<()> {
) -> io::Result<()> {
self.client_cipher.decrypt_ipv4(&mut net_packet)?;
context
.route_table
.update_read_time(&net_packet.source(), &route_key);
//处理扩展
let net_packet = if net_packet.is_extension() {
//这样重用数组,减少一次数据拷贝
if handle_extension_tail(&mut net_packet, &mut extend)? {
extend
} else {
net_packet
}
} else {
net_packet
};
match net_packet.protocol() {
Protocol::Service => {}
Protocol::Error => {}
+8 -17
View File
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use std::net::Ipv4Addr;
use std::sync::Arc;
use std::thread;
use std::{io, thread};
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::{Mutex, RwLock};
@@ -43,13 +43,7 @@ pub struct RecvDataHandler<Call> {
}
impl<Call: VntCallback> RecvChannelHandler for RecvDataHandler<Call> {
fn handle(
&mut self,
buf: &mut [u8],
extend: &mut [u8],
route_key: RouteKey,
context: &ChannelContext,
) {
fn handle(&mut self, buf: &mut [u8], route_key: RouteKey, context: &ChannelContext) {
//判断stun响应包
if !route_key.is_tcp() {
if let Ok(rs) = self
@@ -61,7 +55,7 @@ impl<Call: VntCallback> RecvChannelHandler for RecvDataHandler<Call> {
}
}
}
if let Err(e) = self.handle0(buf, extend, route_key, context) {
if let Err(e) = self.handle0(buf, route_key, context) {
log::error!("[{}]-{:?}", thread::current().name().unwrap_or(""), e);
}
}
@@ -122,14 +116,12 @@ impl<Call: VntCallback> RecvDataHandler<Call> {
fn handle0(
&mut self,
buf: &mut [u8],
extend: &mut [u8],
route_key: RouteKey,
context: &ChannelContext,
) -> anyhow::Result<()> {
) -> io::Result<()> {
// 统计流量
self.counter.add(buf.len() as _);
let net_packet = NetPacket::new(buf)?;
let extend = NetPacket::unchecked(extend);
if net_packet.ttl() == 0 || net_packet.source_ttl() < net_packet.ttl() {
log::warn!("丢弃过时包:{:?}", net_packet.head());
return Ok(());
@@ -147,16 +139,16 @@ impl<Call: VntCallback> RecvDataHandler<Call> {
if net_packet.is_gateway() {
//服务端-客户端包
self.server
.handle(net_packet, extend, route_key, context, &current_device)
.handle(net_packet, route_key, context, &current_device)
} else {
//客户端-客户端包
self.client
.handle(net_packet, extend, route_key, context, &current_device)
.handle(net_packet, route_key, context, &current_device)
}
} else {
//转发包
self.turn
.handle(net_packet, extend, route_key, context, &current_device)
.handle(net_packet, route_key, context, &current_device)
}
}
}
@@ -165,9 +157,8 @@ pub trait PacketHandler {
fn handle(
&self,
net_packet: NetPacket<&mut [u8]>,
extend: NetPacket<&mut [u8]>,
route_key: RouteKey,
context: &ChannelContext,
current_device: &CurrentDeviceInfo,
) -> anyhow::Result<()>;
) -> io::Result<()>;
}
+1 -3
View File
@@ -94,11 +94,10 @@ impl<Call: VntCallback> PacketHandler for ServerPacketHandler<Call> {
fn handle(
&self,
mut net_packet: NetPacket<&mut [u8]>,
_extend: NetPacket<&mut [u8]>,
route_key: RouteKey,
context: &ChannelContext,
current_device: &CurrentDeviceInfo,
) -> anyhow::Result<()> {
) -> io::Result<()> {
context
.route_table
.update_read_time(&net_packet.source(), &route_key);
@@ -194,7 +193,6 @@ impl<Call: VntCallback> PacketHandler for ServerPacketHandler<Call> {
}
return Ok(());
}
#[cfg(feature = "server_encrypt")]
if let Ok(rsa_cipher) = RsaCipher::new(&response.public_key) {
self.rsa_cipher.lock().replace(rsa_cipher);
}
+2 -6
View File
@@ -3,7 +3,6 @@ use crate::channel::RouteKey;
use crate::handle::recv_data::PacketHandler;
use crate::handle::CurrentDeviceInfo;
use crate::protocol::NetPacket;
use anyhow::Context;
/// 处理客户端中转包
#[derive(Clone)]
@@ -19,11 +18,10 @@ impl PacketHandler for TurnPacketHandler {
fn handle(
&self,
mut net_packet: NetPacket<&mut [u8]>,
_extend: NetPacket<&mut [u8]>,
route_key: RouteKey,
context: &ChannelContext,
_current_device: &CurrentDeviceInfo,
) -> anyhow::Result<()> {
) -> std::io::Result<()> {
// ttl减一
let ttl = net_packet.incr_ttl();
if ttl > 0 {
@@ -35,9 +33,7 @@ impl PacketHandler for TurnPacketHandler {
return Ok(());
}
if route.metric <= ttl {
return context
.send_by_key(net_packet.buffer(), route.route_key())
.context("转发失败");
return context.send_by_key(net_packet.buffer(), route.route_key());
}
}
//其他没有路由的不转发
+4 -31
View File
@@ -5,7 +5,6 @@ use std::{io, thread};
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::Mutex;
use crate::channel::BUFFER_SIZE;
use packet::icmp::icmp::IcmpPacket;
use packet::icmp::Kind;
use packet::ip::ipv4::packet::IpV4Packet;
@@ -15,13 +14,11 @@ use tun::Device;
use crate::channel::context::ChannelContext;
use crate::cipher::Cipher;
use crate::compression::Compressor;
use crate::external_route::ExternalRoute;
use crate::handle::tun_tap::channel_group::channel_group;
use crate::handle::{check_dest, CurrentDeviceInfo, PeerDeviceInfo};
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::IpProxyMap;
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::ProxyHandler;
use crate::protocol;
use crate::protocol::body::ENCRYPTION_RESERVED;
@@ -29,7 +26,7 @@ use crate::protocol::ip_turn_packet::BroadcastPacket;
use crate::protocol::{ip_turn_packet, NetPacket, MAX_TTL};
use crate::util::{SingleU64Adder, StopManager};
fn icmp(device_writer: &Device, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> anyhow::Result<()> {
fn icmp(device_writer: &Device, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> io::Result<()> {
if ipv4_packet.protocol() == Protocol::Icmp {
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
if icmp.kind() == Kind::EchoRequest {
@@ -50,7 +47,6 @@ pub(crate) fn handle(
context: &ChannelContext,
data: &mut [u8],
len: usize,
extend: &mut [u8],
device_writer: &Device,
current_device: CurrentDeviceInfo,
ip_route: &ExternalRoute,
@@ -58,8 +54,7 @@ pub(crate) fn handle(
client_cipher: &Cipher,
server_cipher: &Cipher,
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
compressor: &Compressor,
) -> anyhow::Result<()> {
) -> io::Result<()> {
//忽略掉结构不对的情况(ipv6数据、win tap会读到空数据),不然日志打印太多了
let ipv4_packet = match IpV4Packet::new(&mut data[12..len]) {
Ok(packet) => packet,
@@ -74,7 +69,6 @@ pub(crate) fn handle(
context,
data,
len,
extend,
current_device,
ip_route,
#[cfg(feature = "ip_proxy")]
@@ -82,7 +76,6 @@ pub(crate) fn handle(
client_cipher,
server_cipher,
device_list,
compressor,
);
}
@@ -98,7 +91,6 @@ pub fn start(
parallel: usize,
mut up_counter: SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
compressor: Compressor,
) -> io::Result<()> {
if parallel > 1 {
let (sender, receivers) = channel_group::<(Vec<u8>, usize)>(parallel, 16);
@@ -115,7 +107,6 @@ pub fn start(
thread::Builder::new()
.name(format!("tunHandler-{}", index))
.spawn(move || {
let mut extend = [0; BUFFER_SIZE];
while let Ok((mut buf, len)) = receiver.recv() {
#[cfg(not(target_os = "macos"))]
let start = 0;
@@ -125,7 +116,6 @@ pub fn start(
&context,
&mut buf[start..],
len,
&mut extend,
&device,
current_device.load(),
&ip_route,
@@ -134,7 +124,6 @@ pub fn start(
&client_cipher,
&server_cipher,
&device_list,
&compressor,
) {
Ok(_) => {}
Err(e) => {
@@ -172,7 +161,6 @@ pub fn start(
server_cipher,
&mut up_counter,
device_list,
compressor,
) {
log::warn!("stop:{}", e);
}
@@ -272,21 +260,18 @@ fn base_handle(
context: &ChannelContext,
buf: &mut [u8],
data_len: usize, //数据总长度=12+ip包长度
extend: &mut [u8],
current_device: CurrentDeviceInfo,
ip_route: &ExternalRoute,
#[cfg(feature = "ip_proxy")] proxy_map: &Option<IpProxyMap>,
client_cipher: &Cipher,
server_cipher: &Cipher,
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
compressor: &Compressor,
) -> anyhow::Result<()> {
) -> io::Result<()> {
let ipv4_packet = IpV4Packet::new(&buf[12..data_len])?;
let protocol = ipv4_packet.protocol();
let src_ip = ipv4_packet.source_ip();
let mut dest_ip = ipv4_packet.destination_ip();
let mut net_packet = NetPacket::new0(data_len, buf)?;
let mut out = NetPacket::unchecked(extend);
net_packet.set_default_version();
net_packet.set_protocol(protocol::Protocol::IpTurn);
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4.into());
@@ -302,17 +287,6 @@ fn base_handle(
}
return Ok(());
}
let mut net_packet = if compressor.compress(&net_packet, &mut out)? {
out.set_default_version();
out.set_protocol(protocol::Protocol::IpTurn);
out.set_transport_protocol(ip_turn_packet::Protocol::Ipv4.into());
out.first_set_ttl(6);
out.set_source(src_ip);
out.set_destination(dest_ip);
out
} else {
net_packet
};
if dest_ip.is_multicast() {
//当作广播处理
dest_ip = Ipv4Addr::BROADCAST;
@@ -358,6 +332,5 @@ fn base_handle(
&dest_ip,
current_device.connect_server,
current_device.status.online(),
)?;
Ok(())
)
}
+1 -10
View File
@@ -1,11 +1,8 @@
use crate::channel::context::ChannelContext;
use crate::channel::BUFFER_SIZE;
use crate::cipher::Cipher;
use crate::compression::Compressor;
use crate::external_route::ExternalRoute;
use crate::handle::tun_tap::channel_group::GroupSyncSender;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::IpProxyMap;
use crate::util::{SingleU64Adder, StopManager};
use crossbeam_utils::atomic::AtomicCell;
@@ -32,7 +29,6 @@ pub(crate) fn start_simple(
server_cipher: Cipher,
up_counter: &mut SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
compressor: Compressor,
) -> io::Result<()> {
let poll = Poll::new()?;
let waker = Arc::new(Waker::new(poll.registry(), STOP)?);
@@ -52,7 +48,6 @@ pub(crate) fn start_simple(
server_cipher,
up_counter,
device_list,
compressor,
) {
log::error!("{:?}", e);
};
@@ -72,10 +67,8 @@ fn start_simple0(
server_cipher: Cipher,
up_counter: &mut SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
compressor: Compressor,
) -> io::Result<()> {
let mut buf = [0; BUFFER_SIZE];
let mut extend = [0; BUFFER_SIZE];
let mut buf = [0; 1024 * 16];
let fd = device.as_tun_fd();
fd.set_nonblock()?;
SourceFd(&fd.as_raw_fd()).register(poll.registry(), FD, Interest::READABLE)?;
@@ -108,7 +101,6 @@ fn start_simple0(
context,
&mut buf,
len,
&mut extend,
&device,
current_device.load(),
&ip_route,
@@ -117,7 +109,6 @@ fn start_simple0(
&client_cipher,
&server_cipher,
&device_list,
&compressor,
) {
Ok(_) => {}
Err(e) => {
+1 -10
View File
@@ -1,11 +1,8 @@
use crate::channel::context::ChannelContext;
use crate::channel::BUFFER_SIZE;
use crate::cipher::Cipher;
use crate::compression::Compressor;
use crate::external_route::ExternalRoute;
use crate::handle::tun_tap::channel_group::GroupSyncSender;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::IpProxyMap;
use crate::util::{SingleU64Adder, StopManager};
use crossbeam_utils::atomic::AtomicCell;
@@ -26,7 +23,6 @@ pub(crate) fn start_simple(
server_cipher: Cipher,
up_counter: &mut SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
compressor: Compressor,
) -> io::Result<()> {
let worker = {
let device = device.clone();
@@ -47,7 +43,6 @@ pub(crate) fn start_simple(
server_cipher,
up_counter,
device_list,
compressor,
) {
log::error!("{:?}", e);
}
@@ -64,10 +59,8 @@ fn start_simple0(
server_cipher: Cipher,
up_counter: &mut SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
compressor: Compressor,
) -> io::Result<()> {
let mut buf = [0; BUFFER_SIZE];
let mut extend = [0; BUFFER_SIZE];
let mut buf = [0; 1024 * 16];
loop {
let len = device.read(&mut buf[12..])? + 12;
//单线程的
@@ -78,7 +71,6 @@ fn start_simple0(
context,
&mut buf,
len,
&mut extend,
&device,
current_device.load(),
&ip_route,
@@ -87,7 +79,6 @@ fn start_simple0(
&client_cipher,
&server_cipher,
&device_list,
&compressor,
) {
Ok(_) => {}
Err(e) => {
+30 -28
View File
@@ -87,36 +87,38 @@ async fn icmp_proxy(
client_cipher: Cipher,
) -> io::Result<()> {
let mut buf = [0u8; 65535 - 20 - 8];
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
let start = 12;
#[cfg(target_os = "android")]
let start = 12 + 20;
loop {
let (len, addr) = icmp_socket.recv_from(&mut buf[start..]).await?;
if let IpAddr::V4(peer_ip) = addr.ip() {
#[cfg(target_os = "android")]
{
let buf = &mut buf[12..];
// ipv4 头部20字节
buf[0] = 0b0100_0110;
//写入总长度
buf[2..4].copy_from_slice(&((20 + len) as u16).to_be_bytes());
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
let start = 12;
#[cfg(target_os = "android")]
let start = 12 + 20;
loop {
let (len, addr) = icmp_socket.recv_from(&mut buf[start..]).await?;
if let IpAddr::V4(peer_ip) = addr.ip() {
#[cfg(target_os = "android")]
{
let buf = &mut buf[12..];
// ipv4 头部20字节
buf[0] = 0b0100_0110;
//写入总长度
buf[2..4].copy_from_slice(&((20 + len) as u16).to_be_bytes());
let mut ipv4 = IpV4Packet::unchecked(buf);
ipv4.set_flags(2);
ipv4.set_ttl(1);
ipv4.set_protocol(packet::ip::ipv4::protocol::Protocol::Icmp);
ipv4.set_source_ip(peer_ip);
let mut ipv4 = IpV4Packet::unchecked(buf);
ipv4.set_flags(2);
ipv4.set_ttl(1);
ipv4.set_protocol(packet::ip::ipv4::protocol::Protocol::Icmp);
ipv4.set_source_ip(peer_ip);
}
recv_handle(
&mut buf,
start + len,
peer_ip,
&nat_map,
&context,
&current_device,
&client_cipher,
);
}
recv_handle(
&mut buf,
start + len,
peer_ip,
&nat_map,
&context,
&current_device,
&client_cipher,
);
}
}
}
@@ -165,7 +167,7 @@ fn recv_handle(
}
}
h => {
log::debug!("不支持的icmp代理 {:?},{:?}", peer_ip, h)
log::warn!("不支持的icmp代理 {:?},{:?}", peer_ip, h)
}
},
Err(e) => {
+4 -11
View File
@@ -10,13 +10,11 @@ use packet::ip::ipv4::packet::IpV4Packet;
use crate::channel::context::ChannelContext;
use crate::cipher::Cipher;
use crate::handle::CurrentDeviceInfo;
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
use crate::ip_proxy::icmp_proxy::IcmpProxy;
use crate::ip_proxy::tcp_proxy::TcpProxy;
use crate::ip_proxy::udp_proxy::UdpProxy;
use crate::util::StopManager;
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
pub mod icmp_proxy;
pub mod tcp_proxy;
pub mod udp_proxy;
@@ -33,7 +31,6 @@ pub trait ProxyHandler {
#[derive(Clone)]
pub struct IpProxyMap {
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
icmp_proxy: IcmpProxy,
tcp_proxy: TcpProxy,
udp_proxy: UdpProxy,
@@ -68,17 +65,15 @@ pub fn init_proxy(
}
async fn init_proxy0(
_context: ChannelContext,
_current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
_client_cipher: Cipher,
context: ChannelContext,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
client_cipher: Cipher,
) -> anyhow::Result<IpProxyMap> {
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
let icmp_proxy = IcmpProxy::new(_context, _current_device, _client_cipher).await?;
let icmp_proxy = IcmpProxy::new(context, current_device, client_cipher).await?;
let tcp_proxy = TcpProxy::new().await?;
let udp_proxy = UdpProxy::new().await?;
Ok(IpProxyMap {
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
icmp_proxy,
tcp_proxy,
udp_proxy,
@@ -95,7 +90,6 @@ impl ProxyHandler for IpProxyMap {
match ipv4.protocol() {
ipv4::protocol::Protocol::Tcp => self.tcp_proxy.recv_handle(ipv4, source, destination),
ipv4::protocol::Protocol::Udp => self.udp_proxy.recv_handle(ipv4, source, destination),
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
ipv4::protocol::Protocol::Icmp => {
self.icmp_proxy.recv_handle(ipv4, source, destination)
}
@@ -116,7 +110,6 @@ impl ProxyHandler for IpProxyMap {
match ipv4.protocol() {
ipv4::protocol::Protocol::Tcp => self.tcp_proxy.send_handle(ipv4),
ipv4::protocol::Protocol::Udp => self.udp_proxy.send_handle(ipv4),
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
ipv4::protocol::Protocol::Icmp => self.icmp_proxy.send_handle(ipv4),
_ => Ok(()),
}
-1
View File
@@ -16,4 +16,3 @@ pub mod tun_tap_device;
pub mod util;
pub use handle::callback::*;
pub mod compression;
+5 -9
View File
@@ -71,15 +71,11 @@ pub fn stun_test_nat0(stun_servers: Vec<String>) -> io::Result<(NatType, Vec<Ipv
}
}
}
if hash_set.is_empty() {
Ok((nat_type, vec![], 0))
} else {
Ok((
nat_type,
hash_set.into_iter().collect(),
max_port - min_port,
))
}
Ok((
nat_type,
hash_set.into_iter().collect(),
max_port - min_port,
))
}
fn test_nat(udp: &UdpSocket, stun_server: &String) -> io::Result<HashSet<SocketAddr>> {
-141
View File
@@ -1,141 +0,0 @@
/* 扩展协议
0 15 31
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 扩展数据(n) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 扩展数据(n) | type(8) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
注:扩展数据的长度由type决定
*/
use anyhow::anyhow;
use std::io;
use crate::protocol::NetPacket;
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum ExtensionTailType {
Compression,
Unknown(u8),
}
impl From<u8> for ExtensionTailType {
fn from(value: u8) -> Self {
if value == 0 {
ExtensionTailType::Compression
} else {
ExtensionTailType::Unknown(value)
}
}
}
pub enum ExtensionTailPacket<B> {
Compression(CompressionExtensionTail<B>),
Unknown,
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
/// 分离尾部数据
pub fn split_tail_packet(&mut self) -> anyhow::Result<ExtensionTailPacket<&[u8]>> {
if self.is_extension() {
let payload = self.payload();
if let Some(v) = payload.last() {
return match ExtensionTailType::from(*v) {
ExtensionTailType::Compression => {
let data_len = self.data_len - 4;
self.set_data_len(data_len)?;
self.set_extension_flag(false);
Ok(ExtensionTailPacket::Compression(
CompressionExtensionTail::new(
&self.raw_buffer()[data_len..data_len + 4],
),
))
}
ExtensionTailType::Unknown(e) => Err(anyhow!("unknown extension {}", e)),
};
}
}
Err(anyhow!("not extension"))
}
/// 追加压缩扩展
pub fn append_compression_extension_tail(
&mut self,
) -> io::Result<CompressionExtensionTail<&mut [u8]>> {
let len = self.data_len;
//增加数据长度
self.set_data_len(self.data_len + 4)?;
self.set_extension_flag(true);
let mut tail = CompressionExtensionTail::new(&mut self.buffer_mut()[len..]);
tail.init();
return Ok(tail);
}
}
/* 扩展协议
0 15 31
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| algorithm(8) | | type(8) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
注:扩展数据的长度由type决定
*/
/// 压缩扩展
pub struct CompressionExtensionTail<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> CompressionExtensionTail<B> {
pub fn new(buffer: B) -> CompressionExtensionTail<B> {
assert_eq!(buffer.as_ref().len(), 4);
CompressionExtensionTail { buffer }
}
}
impl<B: AsRef<[u8]>> CompressionExtensionTail<B> {
pub fn algorithm(&self) -> CompressionAlgorithm {
self.buffer.as_ref()[0].into()
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> CompressionExtensionTail<B> {
pub fn init(&mut self) {
self.buffer.as_mut().fill(0);
}
pub fn set_algorithm(&mut self, algorithm: CompressionAlgorithm) {
self.buffer.as_mut()[0] = algorithm.into()
}
}
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum CompressionAlgorithm {
#[cfg(feature = "lz4_compress")]
Lz4,
#[cfg(feature = "zstd_compress")]
Zstd,
Unknown(u8),
}
impl From<u8> for CompressionAlgorithm {
fn from(value: u8) -> Self {
match value {
#[cfg(feature = "lz4_compress")]
1 => CompressionAlgorithm::Lz4,
#[cfg(feature = "zstd_compress")]
2 => CompressionAlgorithm::Zstd,
v => CompressionAlgorithm::Unknown(v),
}
}
}
impl From<CompressionAlgorithm> for u8 {
fn from(value: CompressionAlgorithm) -> Self {
match value {
#[cfg(feature = "lz4_compress")]
CompressionAlgorithm::Lz4 => 1,
#[cfg(feature = "zstd_compress")]
CompressionAlgorithm::Zstd => 2,
CompressionAlgorithm::Unknown(val) => val,
}
}
}
-23
View File
@@ -21,7 +21,6 @@ pub const HEAD_LEN: usize = 12;
pub mod body;
pub mod control_packet;
pub mod error_packet;
pub mod extension;
pub mod ip_turn_packet;
pub mod other_turn_packet;
pub mod service_packet;
@@ -102,10 +101,6 @@ pub struct NetPacket<B> {
}
impl<B: AsRef<[u8]>> NetPacket<B> {
pub fn unchecked(buffer: B) -> Self {
let data_len = buffer.as_ref().len();
Self { data_len, buffer }
}
pub fn new(buffer: B) -> io::Result<NetPacket<B>> {
let data_len = buffer.as_ref().len();
Self::new0(data_len, buffer)
@@ -163,10 +158,6 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
pub fn is_gateway(&self) -> bool {
self.buffer.as_ref()[0] & 0x40 == 0x40
}
/// 扩展协议
pub fn is_extension(&self) -> bool {
self.buffer.as_ref()[0] & 0x20 == 0x20
}
pub fn version(&self) -> Version {
Version::from(self.buffer.as_ref()[0] & 0x0F)
}
@@ -199,9 +190,6 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
pub fn head_mut(&mut self) -> &mut [u8] {
&mut self.buffer.as_mut()[..12]
}
pub fn buffer_mut(&mut self) -> &mut [u8] {
&mut self.buffer.as_mut()[..self.data_len]
}
@@ -220,13 +208,6 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF
};
}
pub fn set_extension_flag(&mut self, is_extension: bool) {
if is_extension {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x20
} else {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xDF
};
}
pub fn set_default_version(&mut self) {
let v: u8 = Version::V2.into();
self.buffer.as_mut()[0] = (self.buffer.as_ref()[0] & 0xF0) | (0x0F & v);
@@ -283,10 +264,6 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
self.data_len = data_len;
Ok(())
}
pub fn set_payload_len(&mut self, payload_len: usize) -> io::Result<()> {
let data_len = HEAD_LEN + payload_len;
self.set_data_len(data_len)
}
pub fn set_data_len_max(&mut self) {
self.data_len = self.buffer.as_ref().len();
}
@@ -8,10 +8,8 @@ use tun::Device;
use crate::channel::context::ChannelContext;
use crate::cipher::Cipher;
use crate::compression::Compressor;
use crate::external_route::ExternalRoute;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::IpProxyMap;
use crate::util::{SingleU64Adder, StopManager};
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
@@ -79,7 +77,6 @@ struct TunDeviceHelperInner {
parallel: usize,
up_counter: SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
compressor: Compressor,
}
impl TunDeviceHelper {
@@ -94,7 +91,6 @@ impl TunDeviceHelper {
parallel: usize,
up_counter: SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
compressor: Compressor,
) -> Self {
Self {
inner: Arc::new(AtomicCell::new(Some(TunDeviceHelperInner {
@@ -102,14 +98,12 @@ impl TunDeviceHelper {
context,
current_device,
ip_route,
#[cfg(feature = "ip_proxy")]
ip_proxy_map,
client_cipher,
server_cipher,
parallel,
up_counter,
device_list,
compressor,
}))),
}
}
@@ -128,7 +122,6 @@ impl TunDeviceHelper {
inner.parallel,
inner.up_counter,
inner.device_list,
inner.compressor,
)?;
Ok(())
} else {
+12 -12
View File
@@ -41,10 +41,9 @@ pub fn address_choose(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
/// 后续实现选择延迟最低的可用地址,需要服务端配合
/// 现在是选择第一个地址,优先ipv6
fn address_choose0(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
let v4: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv4()).copied().collect();
let v6: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv6()).copied().collect();
let v4: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv4()).map(|v| *v).collect();
let v6: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv6()).map(|v| *v).collect();
let check_addr = |addrs: &Vec<SocketAddr>| -> anyhow::Result<SocketAddr> {
let mut err = Vec::new();
if !addrs.is_empty() {
let udp = if addrs[0].is_ipv6() {
UdpSocket::bind("[::]:0")?
@@ -52,14 +51,12 @@ fn address_choose0(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
UdpSocket::bind("0.0.0.0:0")?
};
for addr in addrs {
if let Err(e) = udp.connect(addr) {
err.push((*addr, e));
} else {
if udp.connect(addr).is_ok() {
return Ok(*addr);
}
}
}
Err(anyhow::anyhow!("Unable to connect to address {:?}", err))
Err(anyhow::anyhow!("Unable to connect to address {:?}", addrs))
};
if v6.is_empty() {
return check_addr(&v4);
@@ -81,7 +78,9 @@ pub fn dns_query_all(
mut name_servers: Vec<String>,
) -> anyhow::Result<Vec<SocketAddr>> {
match SocketAddr::from_str(domain) {
Ok(addr) => Ok(vec![addr]),
Ok(addr) => {
return Ok(vec![addr]);
}
Err(_) => {
let txt_domain = domain
.to_lowercase()
@@ -95,6 +94,7 @@ pub fn dns_query_all(
return Ok(domain
.to_socket_addrs()
.with_context(|| format!("DNS query failed {:?}", domain))?
.into_iter()
.collect());
}
}
@@ -119,7 +119,7 @@ pub fn dns_query_all(
continue;
}
let end_index = domain
.rfind(':')
.rfind(":")
.with_context(|| format!("{:?} not port", domain))?;
let host = &domain[..end_index];
let port = u16::from_str(&domain[end_index + 1..])
@@ -219,7 +219,7 @@ fn query<'a>(
domain
));
}
if pkt.answers.is_empty() {
if pkt.answers.len() == 0 {
return Err(anyhow::anyhow!(
"No records received DNS {:?} domain {:?}",
name_server,
@@ -240,8 +240,8 @@ pub fn txt_dns(domain: &str, name_server: String) -> anyhow::Result<Vec<SocketAd
if let RData::TXT(txt) = record.data {
for x in txt.iter() {
let txt = std::str::from_utf8(x).context("record type txt is not string")?;
let addr =
SocketAddr::from_str(txt).context("record type txt is not SocketAddr")?;
let addr = SocketAddr::from_str(&txt.to_string())
.context("record type txt is not SocketAddr")?;
rs.push(addr);
}
}