调整条件编译
This commit is contained in:
Generated
+1
@@ -1625,6 +1625,7 @@ dependencies = [
|
|||||||
name = "vnt-cli"
|
name = "vnt-cli"
|
||||||
version = "1.2.9"
|
version = "1.2.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
"common",
|
"common",
|
||||||
"console",
|
"console",
|
||||||
|
|||||||
@@ -85,24 +85,33 @@ features说明
|
|||||||
| server_encrypt | 支持服务端加密 | 是 |
|
| server_encrypt | 支持服务端加密 | 是 |
|
||||||
| ip_proxy | 内置ip代理 | 是 |
|
| ip_proxy | 内置ip代理 | 是 |
|
||||||
| port_mapping | 端口映射 | 是 |
|
| port_mapping | 端口映射 | 是 |
|
||||||
|
| log | 日志 | 是 |
|
||||||
|
| command | list、route等命令 | 是 |
|
||||||
|
| file_config | yaml配置文件 | 是 |
|
||||||
|
|
||||||
### ip转发/代理
|
### ip转发/代理
|
||||||
|
|
||||||
如果编译时去除了内置的ip代理(或使用--no-proxy关闭了代理),则可以使用网卡NAT转发来实现点对网,
|
如果编译时去除了内置的ip代理(或使用--no-proxy关闭了代理),则可以使用网卡NAT转发来实现点对网,
|
||||||
一般来说使用网卡NAT转发会比内置的ip代理性能更好
|
一般来说使用网卡NAT转发会比内置的ip代理性能更好
|
||||||
<details> <summary>NAT配置可参考如下示例,点击展开</summary>
|
<details> <summary>NAT配置可参考如下示例,点击展开</summary>
|
||||||
|
|
||||||
### 在出口一端做如下配置
|
### 在出口一端做如下配置
|
||||||
|
|
||||||
注意原有的-i(入口)和-o(出口)的参数不能少
|
注意原有的-i(入口)和-o(出口)的参数不能少
|
||||||
|
|
||||||
### windows
|
### windows
|
||||||
|
|
||||||
参考 https://learn.microsoft.com/zh-cn/virtualization/hyper-v-on-windows/user-guide/setup-nat-network
|
参考 https://learn.microsoft.com/zh-cn/virtualization/hyper-v-on-windows/user-guide/setup-nat-network
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
#设置nat,名字可以自己取,网段是vnt的网段
|
#设置nat,名字可以自己取,网段是vnt的网段
|
||||||
New-NetNat -Name vntnat -InternalIPInterfaceAddressPrefix 10.26.0.0/24
|
New-NetNat -Name vntnat -InternalIPInterfaceAddressPrefix 10.26.0.0/24
|
||||||
#查看设置
|
#查看设置
|
||||||
Get-NetNat
|
Get-NetNat
|
||||||
```
|
```
|
||||||
|
|
||||||
### linux
|
### linux
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# 开启ip转发
|
# 开启ip转发
|
||||||
sudo sysctl -w net.ipv4.ip_forward=1
|
sudo sysctl -w net.ipv4.ip_forward=1
|
||||||
@@ -145,6 +154,7 @@ sudo iptables-restore iptables.rules
|
|||||||
```
|
```
|
||||||
|
|
||||||
### macos
|
### macos
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# 开启ip转发
|
# 开启ip转发
|
||||||
sudo sysctl -w net.ipv4.ip_forward=1
|
sudo sysctl -w net.ipv4.ip_forward=1
|
||||||
@@ -154,6 +164,7 @@ nat on en0 from 10.26.0.0/24 to any -> (en0)
|
|||||||
# 加载规则
|
# 加载规则
|
||||||
sudo pfctl -f /etc/pf.conf -e
|
sudo pfctl -f /etc/pf.conf -e
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 支持平台
|
### 支持平台
|
||||||
@@ -256,10 +267,15 @@ vnt默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突
|
|||||||
2. 如果p2p后效果很差,可以选择禁用p2p(vnt-cli增加--use-channel relay 参数)
|
2. 如果p2p后效果很差,可以选择禁用p2p(vnt-cli增加--use-channel relay 参数)
|
||||||
|
|
||||||
#### 问题4:重启后虚拟IP发生变化,或指定了IP不能启动
|
#### 问题4:重启后虚拟IP发生变化,或指定了IP不能启动
|
||||||
|
|
||||||
##### 可能原因:
|
##### 可能原因:
|
||||||
|
|
||||||
设备重启后程序自动获取的id值改变,导致注册时重新分配了新的IP,或是IP冲突
|
设备重启后程序自动获取的id值改变,导致注册时重新分配了新的IP,或是IP冲突
|
||||||
|
|
||||||
##### 解决方法:
|
##### 解决方法:
|
||||||
|
|
||||||
1. 命令行启动增加-d参数(使用配置文件启动则在配置文件中增加device_id参数),要保证每个设备的值都不一样,取值可以任意64位以内字符串
|
1. 命令行启动增加-d参数(使用配置文件启动则在配置文件中增加device_id参数),要保证每个设备的值都不一样,取值可以任意64位以内字符串
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 交流群
|
### 交流群
|
||||||
|
|||||||
+6
-2
@@ -14,7 +14,8 @@ os_info = "3.7.0"
|
|||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_yaml = "0.9.32"
|
serde_yaml = "0.9.32"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
log4rs = "1.2.0"
|
log4rs = { version = "1.2.0", optional = true }
|
||||||
|
anyhow = "1.0.82"
|
||||||
[dependencies.uuid]
|
[dependencies.uuid]
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
features = [
|
features = [
|
||||||
@@ -28,7 +29,7 @@ sudo = "0.6.0"
|
|||||||
winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] }
|
winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "ip_proxy", "port_mapping"]
|
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "ip_proxy", "port_mapping", "log", "command", "file_config"]
|
||||||
openssl = ["vnt/openssl"]
|
openssl = ["vnt/openssl"]
|
||||||
openssl-vendored = ["vnt/openssl-vendored"]
|
openssl-vendored = ["vnt/openssl-vendored"]
|
||||||
ring-cipher = ["vnt/ring-cipher"]
|
ring-cipher = ["vnt/ring-cipher"]
|
||||||
@@ -39,6 +40,9 @@ aes_gcm = ["vnt/aes_gcm"]
|
|||||||
server_encrypt = ["vnt/server_encrypt"]
|
server_encrypt = ["vnt/server_encrypt"]
|
||||||
ip_proxy = ["vnt/ip_proxy"]
|
ip_proxy = ["vnt/ip_proxy"]
|
||||||
port_mapping = ["vnt/port_mapping"]
|
port_mapping = ["vnt/port_mapping"]
|
||||||
|
log = ["log4rs"]
|
||||||
|
command = []
|
||||||
|
file_config = []
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
embed-manifest = "1.4.0"
|
embed-manifest = "1.4.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
|||||||
+7
-166
@@ -1,171 +1,12 @@
|
|||||||
use std::io;
|
#[cfg(feature = "file_config")]
|
||||||
use std::net::Ipv4Addr;
|
mod file_config;
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
#[cfg(feature = "file_config")]
|
||||||
|
pub use file_config::read_config;
|
||||||
|
|
||||||
use vnt::channel::punch::PunchModel;
|
#[cfg(not(feature = "file_config"))]
|
||||||
use vnt::channel::UseChannelType;
|
pub fn read_config(_file_path: &str) -> anyhow::Result<(vnt::core::Config, bool)> {
|
||||||
use vnt::cipher::CipherModel;
|
unimplemented!()
|
||||||
use vnt::core::Config;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
#[serde(default)]
|
|
||||||
pub struct FileConfig {
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub tap: bool,
|
|
||||||
pub token: String,
|
|
||||||
pub device_id: String,
|
|
||||||
pub name: String,
|
|
||||||
pub server_address: String,
|
|
||||||
pub stun_server: Vec<String>,
|
|
||||||
pub dns: Vec<String>,
|
|
||||||
pub in_ips: Vec<String>,
|
|
||||||
pub out_ips: Vec<String>,
|
|
||||||
pub password: Option<String>,
|
|
||||||
pub mtu: Option<u32>,
|
|
||||||
pub tcp: bool,
|
|
||||||
pub ip: Option<String>,
|
|
||||||
pub use_channel: String,
|
|
||||||
#[cfg(feature = "ip_proxy")]
|
|
||||||
pub no_proxy: bool,
|
|
||||||
pub server_encrypt: bool,
|
|
||||||
pub parallel: usize,
|
|
||||||
pub cipher_model: String,
|
|
||||||
pub finger: bool,
|
|
||||||
pub punch_model: String,
|
|
||||||
pub ports: Option<Vec<u16>>,
|
|
||||||
pub cmd: bool,
|
|
||||||
pub first_latency: bool,
|
|
||||||
pub device_name: Option<String>,
|
|
||||||
pub packet_loss: Option<f64>,
|
|
||||||
pub packet_delay: u32,
|
|
||||||
#[cfg(feature = "port_mapping")]
|
|
||||||
pub mapping: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for FileConfig {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
tap: false,
|
|
||||||
token: "".to_string(),
|
|
||||||
device_id: get_device_id(),
|
|
||||||
name: os_info::get().to_string(),
|
|
||||||
server_address: "nat1.wherewego.top:29872".to_string(),
|
|
||||||
stun_server: vec![
|
|
||||||
"stun1.l.google.com:19302".to_string(),
|
|
||||||
"stun2.l.google.com:19302".to_string(),
|
|
||||||
"stun.miwifi.com:3478".to_string(),
|
|
||||||
],
|
|
||||||
dns: vec![],
|
|
||||||
in_ips: vec![],
|
|
||||||
out_ips: vec![],
|
|
||||||
password: None,
|
|
||||||
mtu: None,
|
|
||||||
tcp: false,
|
|
||||||
ip: None,
|
|
||||||
use_channel: "all".to_string(),
|
|
||||||
#[cfg(feature = "ip_proxy")]
|
|
||||||
no_proxy: false,
|
|
||||||
server_encrypt: false,
|
|
||||||
parallel: 1,
|
|
||||||
cipher_model: "aes_gcm".to_string(),
|
|
||||||
finger: false,
|
|
||||||
punch_model: "all".to_string(),
|
|
||||||
ports: None,
|
|
||||||
cmd: false,
|
|
||||||
first_latency: false,
|
|
||||||
device_name: None,
|
|
||||||
packet_loss: None,
|
|
||||||
packet_delay: 0,
|
|
||||||
#[cfg(feature = "port_mapping")]
|
|
||||||
mapping: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_config(file_path: &str) -> io::Result<(Config, bool)> {
|
|
||||||
let conf = std::fs::read_to_string(file_path)?;
|
|
||||||
let file_conf = match serde_yaml::from_str::<FileConfig>(&conf) {
|
|
||||||
Ok(val) => val,
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("{:?}", e);
|
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, format!("{}", e)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if file_conf.token.is_empty() {
|
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "token is_empty"));
|
|
||||||
}
|
|
||||||
|
|
||||||
let in_ips = match common::args_parse::ips_parse(&file_conf.in_ips) {
|
|
||||||
Ok(in_ips) => in_ips,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("in_ips {:?} error:{}", &file_conf.in_ips, e),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let out_ips = match common::args_parse::out_ips_parse(&file_conf.out_ips) {
|
|
||||||
Ok(out_ips) => out_ips,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("out_ips {:?} error:{}", &file_conf.out_ips, e),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let virtual_ip = match file_conf.ip.clone().map(|v| Ipv4Addr::from_str(&v)) {
|
|
||||||
None => None,
|
|
||||||
Some(r) => Some(r.map_err(|e| {
|
|
||||||
io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("ip {:?} error:{}", &file_conf.ip, e),
|
|
||||||
)
|
|
||||||
})?),
|
|
||||||
};
|
|
||||||
|
|
||||||
let cipher_model = CipherModel::from_str(&file_conf.cipher_model)
|
|
||||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
|
||||||
|
|
||||||
let punch_model = PunchModel::from_str(&file_conf.punch_model)
|
|
||||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
|
||||||
let use_channel_type = UseChannelType::from_str(&file_conf.use_channel)
|
|
||||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
|
||||||
let config = Config::new(
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
file_conf.tap,
|
|
||||||
file_conf.token,
|
|
||||||
file_conf.device_id,
|
|
||||||
file_conf.name,
|
|
||||||
file_conf.server_address,
|
|
||||||
file_conf.dns,
|
|
||||||
file_conf.stun_server,
|
|
||||||
in_ips,
|
|
||||||
out_ips,
|
|
||||||
file_conf.password,
|
|
||||||
file_conf.mtu,
|
|
||||||
file_conf.tcp,
|
|
||||||
virtual_ip,
|
|
||||||
#[cfg(feature = "ip_proxy")]
|
|
||||||
file_conf.no_proxy,
|
|
||||||
file_conf.server_encrypt,
|
|
||||||
file_conf.parallel,
|
|
||||||
cipher_model,
|
|
||||||
file_conf.finger,
|
|
||||||
punch_model,
|
|
||||||
file_conf.ports,
|
|
||||||
file_conf.first_latency,
|
|
||||||
file_conf.device_name,
|
|
||||||
use_channel_type,
|
|
||||||
file_conf.packet_loss,
|
|
||||||
file_conf.packet_delay,
|
|
||||||
#[cfg(feature = "port_mapping")]
|
|
||||||
file_conf.mapping,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
Ok((config, file_conf.cmd))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_device_id() -> String {
|
pub fn get_device_id() -> String {
|
||||||
|
|||||||
+61
-46
@@ -1,7 +1,7 @@
|
|||||||
|
use std::io;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::{io, thread};
|
|
||||||
|
|
||||||
use console::style;
|
use console::style;
|
||||||
use getopts::Options;
|
use getopts::Options;
|
||||||
@@ -12,8 +12,10 @@ use vnt::channel::UseChannelType;
|
|||||||
use vnt::cipher::CipherModel;
|
use vnt::cipher::CipherModel;
|
||||||
use vnt::core::{Config, Vnt};
|
use vnt::core::{Config, Vnt};
|
||||||
|
|
||||||
|
#[cfg(feature = "command")]
|
||||||
mod command;
|
mod command;
|
||||||
mod config;
|
mod config;
|
||||||
|
#[cfg(feature = "command")]
|
||||||
mod console_out;
|
mod console_out;
|
||||||
mod generated_serial_number;
|
mod generated_serial_number;
|
||||||
mod root_check;
|
mod root_check;
|
||||||
@@ -41,6 +43,7 @@ pub fn app_home() -> io::Result<PathBuf> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
#[cfg(feature = "log")]
|
||||||
let _ = log4rs::init_file("log4rs.yaml", Default::default());
|
let _ = log4rs::init_file("log4rs.yaml", Default::default());
|
||||||
let args: Vec<String> = std::env::args().collect();
|
let args: Vec<String> = std::env::args().collect();
|
||||||
let program = args[0].clone();
|
let program = args[0].clone();
|
||||||
@@ -100,6 +103,7 @@ fn main() {
|
|||||||
sudo::escalate_if_needed().unwrap();
|
sudo::escalate_if_needed().unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "command")]
|
||||||
if matches.opt_present("list") {
|
if matches.opt_present("list") {
|
||||||
command::command(command::CommandEnum::List);
|
command::command(command::CommandEnum::List);
|
||||||
return;
|
return;
|
||||||
@@ -342,7 +346,7 @@ fn main() {
|
|||||||
|
|
||||||
mod callback;
|
mod callback;
|
||||||
|
|
||||||
fn main0(config: Config, show_cmd: bool) {
|
fn main0(config: Config, _show_cmd: bool) {
|
||||||
#[cfg(feature = "port_mapping")]
|
#[cfg(feature = "port_mapping")]
|
||||||
for (is_tcp, addr, dest) in config.port_mapping_list.iter() {
|
for (is_tcp, addr, dest) in config.port_mapping_list.iter() {
|
||||||
if *is_tcp {
|
if *is_tcp {
|
||||||
@@ -352,36 +356,40 @@ fn main0(config: Config, show_cmd: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let vnt_util = Vnt::new(config, callback::VntHandler {}).unwrap();
|
let vnt_util = Vnt::new(config, callback::VntHandler {}).unwrap();
|
||||||
let vnt_c = vnt_util.clone();
|
#[cfg(feature = "command")]
|
||||||
thread::Builder::new()
|
{
|
||||||
.name("CommandServer".into())
|
let vnt_c = vnt_util.clone();
|
||||||
.spawn(move || {
|
std::thread::Builder::new()
|
||||||
if let Err(e) = command::server::CommandServer::new().start(vnt_c) {
|
.name("CommandServer".into())
|
||||||
log::warn!("cmd:{:?}", e);
|
.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();
|
.expect("CommandServer");
|
||||||
loop {
|
if _show_cmd {
|
||||||
cmd.clear();
|
let mut cmd = String::new();
|
||||||
println!("======== input:list,info,route,all,stop ========");
|
loop {
|
||||||
match io::stdin().read_line(&mut cmd) {
|
cmd.clear();
|
||||||
Ok(len) => {
|
println!("======== input:list,info,route,all,stop ========");
|
||||||
if !command(&cmd[..len], &vnt_util) {
|
match io::stdin().read_line(&mut cmd) {
|
||||||
|
Ok(len) => {
|
||||||
|
if !command(&cmd[..len], &vnt_util) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("input err:{}", e);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
|
||||||
println!("input err:{}", e);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vnt_util.wait()
|
vnt_util.wait()
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "command")]
|
||||||
fn command(cmd: &str, vnt: &Vnt) -> bool {
|
fn command(cmd: &str, vnt: &Vnt) -> bool {
|
||||||
if cmd.is_empty() {
|
if cmd.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
@@ -427,10 +435,11 @@ fn print_usage(program: &str, _opts: Options) {
|
|||||||
println!(" -s <server> 注册和中继服务器地址,以'TXT:'开头表示解析TXT记录");
|
println!(" -s <server> 注册和中继服务器地址,以'TXT:'开头表示解析TXT记录");
|
||||||
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可使用多个地址,如-e stun1.l.google.com -e stun2.l.google.com");
|
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可使用多个地址,如-e stun1.l.google.com -e stun2.l.google.com");
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
println!(" -a 使用tap模式,默认使用tun模式");
|
println!(
|
||||||
|
" -a 使用tap模式,默认使用tun模式,使用tap时需要配合'--nic'参数指定tap网卡"
|
||||||
|
);
|
||||||
println!(" -i <in-ip> 配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据");
|
println!(" -i <in-ip> 配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据");
|
||||||
println!(" 并转发到10.26.0.3,可指定多个网段");
|
println!(" 并转发到10.26.0.3,可指定多个网段");
|
||||||
#[cfg(feature = "ip_proxy")]
|
|
||||||
println!(" -o <out-ip> 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段");
|
println!(" -o <out-ip> 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段");
|
||||||
#[cfg(not(any(
|
#[cfg(not(any(
|
||||||
feature = "aes_gcm",
|
feature = "aes_gcm",
|
||||||
@@ -462,6 +471,7 @@ fn print_usage(program: &str, _opts: Options) {
|
|||||||
#[cfg(feature = "server_encrypt")]
|
#[cfg(feature = "server_encrypt")]
|
||||||
println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确");
|
println!(" -W 加密当前客户端和服务端通信的数据,请留意服务端指纹是否正确");
|
||||||
println!(" -u <mtu> 自定义mtu(不加密默认为1450,加密默认为1410)");
|
println!(" -u <mtu> 自定义mtu(不加密默认为1450,加密默认为1410)");
|
||||||
|
#[cfg(feature = "file_config")]
|
||||||
println!(" -f <conf_file> 读取配置文件中的配置");
|
println!(" -f <conf_file> 读取配置文件中的配置");
|
||||||
|
|
||||||
println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp");
|
println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp");
|
||||||
@@ -478,6 +488,7 @@ fn print_usage(program: &str, _opts: Options) {
|
|||||||
}
|
}
|
||||||
println!(" --punch <punch> 取值ipv4/ipv6/all,ipv4表示仅使用ipv4打洞");
|
println!(" --punch <punch> 取值ipv4/ipv6/all,ipv4表示仅使用ipv4打洞");
|
||||||
println!(" --ports <port,port> 取值0~65535,指定本地监听的一组端口,默认监听两个随机端口,使用过多端口会增加网络负担");
|
println!(" --ports <port,port> 取值0~65535,指定本地监听的一组端口,默认监听两个随机端口,使用过多端口会增加网络负担");
|
||||||
|
#[cfg(feature = "command")]
|
||||||
println!(" --cmd 开启交互式命令,使用此参数开启控制台输入");
|
println!(" --cmd 开启交互式命令,使用此参数开启控制台输入");
|
||||||
#[cfg(feature = "ip_proxy")]
|
#[cfg(feature = "ip_proxy")]
|
||||||
println!(" --no-proxy 关闭内置代理,如需点对网则需要配置网卡NAT转发");
|
println!(" --no-proxy 关闭内置代理,如需点对网则需要配置网卡NAT转发");
|
||||||
@@ -493,26 +504,29 @@ fn print_usage(program: &str, _opts: Options) {
|
|||||||
println!(" --mapping <mapping> 端口映射,例如 --mapping udp:0.0.0.0:80->10.26.0.10:80 --mapping tcp:0.0.0.0:80->10.26.0.10:80");
|
println!(" --mapping <mapping> 端口映射,例如 --mapping udp:0.0.0.0:80->10.26.0.10:80 --mapping tcp:0.0.0.0:80->10.26.0.10:80");
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
println!(
|
#[cfg(feature = "command")]
|
||||||
" --list {}",
|
{
|
||||||
yellow("后台运行时,查看其他设备列表".to_string())
|
println!(
|
||||||
);
|
" --list {}",
|
||||||
println!(
|
yellow("后台运行时,查看其他设备列表".to_string())
|
||||||
" --all {}",
|
);
|
||||||
yellow("后台运行时,查看其他设备完整信息".to_string())
|
println!(
|
||||||
);
|
" --all {}",
|
||||||
println!(
|
yellow("后台运行时,查看其他设备完整信息".to_string())
|
||||||
" --info {}",
|
);
|
||||||
yellow("后台运行时,查看当前设备信息".to_string())
|
println!(
|
||||||
);
|
" --info {}",
|
||||||
println!(
|
yellow("后台运行时,查看当前设备信息".to_string())
|
||||||
" --route {}",
|
);
|
||||||
yellow("后台运行时,查看数据转发路径".to_string())
|
println!(
|
||||||
);
|
" --route {}",
|
||||||
println!(
|
yellow("后台运行时,查看数据转发路径".to_string())
|
||||||
" --stop {}",
|
);
|
||||||
yellow("停止后台运行".to_string())
|
println!(
|
||||||
);
|
" --stop {}",
|
||||||
|
yellow("停止后台运行".to_string())
|
||||||
|
);
|
||||||
|
}
|
||||||
println!(" -h, --help 帮助");
|
println!(" -h, --help 帮助");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,6 +534,7 @@ fn green(str: String) -> impl std::fmt::Display {
|
|||||||
style(str).green()
|
style(str).green()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "command")]
|
||||||
fn yellow(str: String) -> impl std::fmt::Display {
|
fn yellow(str: String) -> impl std::fmt::Display {
|
||||||
style(str).yellow()
|
style(str).yellow()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use std::time::Duration;
|
|||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use sha2::Digest;
|
|
||||||
#[cfg(not(target_os = "android"))]
|
#[cfg(not(target_os = "android"))]
|
||||||
use tun::device::IFace;
|
use tun::device::IFace;
|
||||||
|
|
||||||
@@ -80,14 +79,7 @@ impl Vnt {
|
|||||||
config.name.clone(),
|
config.name.clone(),
|
||||||
config.token.clone(),
|
config.token.clone(),
|
||||||
config.ip,
|
config.ip,
|
||||||
config.password.as_ref().map(|v| {
|
config.password_hash(),
|
||||||
let mut hasher = sha2::Sha256::new();
|
|
||||||
hasher.update(config.cipher_model.to_string().as_bytes());
|
|
||||||
hasher.update(v.as_bytes());
|
|
||||||
hasher.update(config.token.as_bytes());
|
|
||||||
let key: [u8; 32] = hasher.finalize().into();
|
|
||||||
key[16..].try_into().unwrap()
|
|
||||||
}),
|
|
||||||
config.server_encrypt,
|
config.server_encrypt,
|
||||||
config.device_id.clone(),
|
config.device_id.clone(),
|
||||||
config.server_address_str.clone(),
|
config.server_address_str.clone(),
|
||||||
|
|||||||
@@ -143,3 +143,33 @@ impl Config {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -87,38 +87,36 @@ async fn icmp_proxy(
|
|||||||
client_cipher: Cipher,
|
client_cipher: Cipher,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
let mut buf = [0u8; 65535 - 20 - 8];
|
let mut buf = [0u8; 65535 - 20 - 8];
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
|
let start = 12;
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
let start = 12 + 20;
|
||||||
loop {
|
loop {
|
||||||
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
let (len, addr) = icmp_socket.recv_from(&mut buf[start..]).await?;
|
||||||
let start = 12;
|
if let IpAddr::V4(peer_ip) = addr.ip() {
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
let start = 12 + 20;
|
{
|
||||||
loop {
|
let buf = &mut buf[12..];
|
||||||
let (len, addr) = icmp_socket.recv_from(&mut buf[start..]).await?;
|
// ipv4 头部20字节
|
||||||
if let IpAddr::V4(peer_ip) = addr.ip() {
|
buf[0] = 0b0100_0110;
|
||||||
#[cfg(target_os = "android")]
|
//写入总长度
|
||||||
{
|
buf[2..4].copy_from_slice(&((20 + len) as u16).to_be_bytes());
|
||||||
let buf = &mut buf[12..];
|
|
||||||
// ipv4 头部20字节
|
|
||||||
buf[0] = 0b0100_0110;
|
|
||||||
//写入总长度
|
|
||||||
buf[2..4].copy_from_slice(&((20 + len) as u16).to_be_bytes());
|
|
||||||
|
|
||||||
let mut ipv4 = IpV4Packet::unchecked(buf);
|
let mut ipv4 = IpV4Packet::unchecked(buf);
|
||||||
ipv4.set_flags(2);
|
ipv4.set_flags(2);
|
||||||
ipv4.set_ttl(1);
|
ipv4.set_ttl(1);
|
||||||
ipv4.set_protocol(packet::ip::ipv4::protocol::Protocol::Icmp);
|
ipv4.set_protocol(packet::ip::ipv4::protocol::Protocol::Icmp);
|
||||||
ipv4.set_source_ip(peer_ip);
|
ipv4.set_source_ip(peer_ip);
|
||||||
}
|
|
||||||
recv_handle(
|
|
||||||
&mut buf,
|
|
||||||
start + len,
|
|
||||||
peer_ip,
|
|
||||||
&nat_map,
|
|
||||||
&context,
|
|
||||||
¤t_device,
|
|
||||||
&client_cipher,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
recv_handle(
|
||||||
|
&mut buf,
|
||||||
|
start + len,
|
||||||
|
peer_ip,
|
||||||
|
&nat_map,
|
||||||
|
&context,
|
||||||
|
¤t_device,
|
||||||
|
&client_cipher,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ pub fn address_choose(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
|
|||||||
/// 后续实现选择延迟最低的可用地址,需要服务端配合
|
/// 后续实现选择延迟最低的可用地址,需要服务端配合
|
||||||
/// 现在是选择第一个地址,优先ipv6
|
/// 现在是选择第一个地址,优先ipv6
|
||||||
fn address_choose0(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
|
fn address_choose0(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
|
||||||
let v4: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv4()).map(|v| *v).collect();
|
let v4: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv4()).copied().collect();
|
||||||
let v6: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv6()).map(|v| *v).collect();
|
let v6: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv6()).copied().collect();
|
||||||
let check_addr = |addrs: &Vec<SocketAddr>| -> anyhow::Result<SocketAddr> {
|
let check_addr = |addrs: &Vec<SocketAddr>| -> anyhow::Result<SocketAddr> {
|
||||||
if !addrs.is_empty() {
|
if !addrs.is_empty() {
|
||||||
let udp = if addrs[0].is_ipv6() {
|
let udp = if addrs[0].is_ipv6() {
|
||||||
@@ -78,9 +78,7 @@ pub fn dns_query_all(
|
|||||||
mut name_servers: Vec<String>,
|
mut name_servers: Vec<String>,
|
||||||
) -> anyhow::Result<Vec<SocketAddr>> {
|
) -> anyhow::Result<Vec<SocketAddr>> {
|
||||||
match SocketAddr::from_str(domain) {
|
match SocketAddr::from_str(domain) {
|
||||||
Ok(addr) => {
|
Ok(addr) => Ok(vec![addr]),
|
||||||
return Ok(vec![addr]);
|
|
||||||
}
|
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let txt_domain = domain
|
let txt_domain = domain
|
||||||
.to_lowercase()
|
.to_lowercase()
|
||||||
@@ -94,7 +92,6 @@ pub fn dns_query_all(
|
|||||||
return Ok(domain
|
return Ok(domain
|
||||||
.to_socket_addrs()
|
.to_socket_addrs()
|
||||||
.with_context(|| format!("DNS query failed {:?}", domain))?
|
.with_context(|| format!("DNS query failed {:?}", domain))?
|
||||||
.into_iter()
|
|
||||||
.collect());
|
.collect());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,7 +116,7 @@ pub fn dns_query_all(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let end_index = domain
|
let end_index = domain
|
||||||
.rfind(":")
|
.rfind(':')
|
||||||
.with_context(|| format!("{:?} not port", domain))?;
|
.with_context(|| format!("{:?} not port", domain))?;
|
||||||
let host = &domain[..end_index];
|
let host = &domain[..end_index];
|
||||||
let port = u16::from_str(&domain[end_index + 1..])
|
let port = u16::from_str(&domain[end_index + 1..])
|
||||||
@@ -219,7 +216,7 @@ fn query<'a>(
|
|||||||
domain
|
domain
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if pkt.answers.len() == 0 {
|
if pkt.answers.is_empty() {
|
||||||
return Err(anyhow::anyhow!(
|
return Err(anyhow::anyhow!(
|
||||||
"No records received DNS {:?} domain {:?}",
|
"No records received DNS {:?} domain {:?}",
|
||||||
name_server,
|
name_server,
|
||||||
@@ -240,8 +237,8 @@ pub fn txt_dns(domain: &str, name_server: String) -> anyhow::Result<Vec<SocketAd
|
|||||||
if let RData::TXT(txt) = record.data {
|
if let RData::TXT(txt) = record.data {
|
||||||
for x in txt.iter() {
|
for x in txt.iter() {
|
||||||
let txt = std::str::from_utf8(x).context("record type txt is not string")?;
|
let txt = std::str::from_utf8(x).context("record type txt is not string")?;
|
||||||
let addr = SocketAddr::from_str(&txt.to_string())
|
let addr =
|
||||||
.context("record type txt is not SocketAddr")?;
|
SocketAddr::from_str(txt).context("record type txt is not SocketAddr")?;
|
||||||
rs.push(addr);
|
rs.push(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user