Compare commits

...
18 Commits
Author SHA1 Message Date
lubeilin be3bf82e35 支持客户端加密 2023-06-26 22:38:15 +08:00
lubeilin e8af503130 支持p2p组播/广播 2023-06-23 15:38:13 +08:00
lubeilin 466174ef88 增加国际化输出 2023-06-23 15:33:08 +08:00
lubeilin ba2c792e2a 使用tokio改写处理逻辑 2023-06-23 15:32:49 +08:00
lubeilin 17f3fcf9b0 优化tun\tap处理 2023-06-23 15:31:44 +08:00
lubeilin 11d1ff4b42 igmp解析 2023-06-23 15:30:07 +08:00
lubeilin b640bc50ef 合并tun、tap配置,减少重复代码 2023-06-23 15:29:03 +08:00
lubeilin 4bbd5282ee 优化tun设置 2023-06-23 15:28:11 +08:00
lubeilin d7fd504f8f 添加igmp、调整返回值 2023-06-23 15:25:00 +08:00
lubeilin cf4375b405 使用tokio改写网络通道 2023-06-23 15:17:46 +08:00
lbl8603 45da060c1a Update README.md 2023-06-03 20:48:29 +08:00
lbl8603 4dc84914dd Update README.md 2023-06-03 20:47:55 +08:00
lbl8603 c1ee7ac11c Update README.md 2023-06-03 09:38:46 +08:00
lubeilin 409b57c171 update 2023-06-03 09:37:51 +08:00
lubeilin ff4580b9bf 优化重连逻辑和路径探测 2023-06-02 18:28:33 +08:00
lubeilin 6daa75d2f2 优化网卡配置,增加metric设置 2023-06-02 18:28:02 +08:00
lubeilin 59f07f2d75 修复windows服务不能自启动的问题 2023-06-02 18:26:38 +08:00
lbl8603 44035685c8 Update README.md 2023-06-01 12:42:01 +08:00
80 changed files with 4556 additions and 1745 deletions
-3
View File
@@ -1,3 +0,0 @@
[submodule "switch/p2p_channel"]
path = switch/p2p_channel
url = https://github.com/lbl8603/p2p_channel
+15 -5
View File
@@ -10,8 +10,8 @@
```shell ```shell
# linux上 # linux上
root@DESKTOP-0BCHNIO:/opt# ./switch-desktop start --token 123456 root@DESKTOP-0BCHNIO:/opt# ./switch-desktop start --token 123456
# 在另一台linux上使用nohup后台运行,不在命令行指定配置时,将在home/.switch_desktop/config文件中读取配置 # 在另一台linux上使用nohup后台运行
[root@izj6cemne76ykdzkataftfz switch]# nohup ./switch-desktop start & [root@izj6cemne76ykdzkataftfz switch]# nohup ./switch-desktop start --token 123456 &
# windows上 # windows上
D:\switch\bin_v1>switch-desktop.exe start --token 123456 D:\switch\bin_v1>switch-desktop.exe start --token 123456
``` ```
@@ -69,8 +69,8 @@
- Mac - Mac
- Linux - Linux
- Windows - Windows
- 使用tun网卡 依赖wintun.dll(https://www.wintun.net/) - 使用tun网卡 依赖wintun.dll(https://www.wintun.net/ )(将dll放到同目录下,建议使用版本0.14.1)
- 使用tap网卡 依赖tap-windows(https://build.openvpn.net/downloads/releases/) - 使用tap网卡 依赖tap-windows(https://build.openvpn.net/downloads/releases/ )(建议使用版本9.24.7)
### 特性 ### 特性
- IP层数据转发 - IP层数据转发
@@ -81,8 +81,18 @@
- 服务端中继转发 - 服务端中继转发
- 客户端中继转发 - 客户端中继转发
- IP代理 - IP代理
- p2p组播/广播
- 客户端数据加密
### Todo ### Todo
- 支持安卓 - 支持安卓
- 数据加密 - 服务端数据加密
### 常见问题
#### 问题1: 设置网络地址失败
##### 可能原因:
switch默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突
##### 解决方法:
1. 方法一:找到冲突的IP,将其改成别的
2. 方法二:自建服务器,指定其他不会冲突的网段
3. 方法三:增加参数--device-id,设置不同的id会让switch-server分配不同的IP,从而绕开有冲突的IP
+4 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "switch-desktop" name = "switch-desktop"
version = "1.0.4" version = "1.0.6"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -16,6 +16,7 @@ log4rs = "1.2.0"
tokio = { version = "1.28.1", features = ["full"] } tokio = { version = "1.28.1", features = ["full"] }
chrono = "0.4.23" chrono = "0.4.23"
rust-i18n = "1.2.2"
serde = "1.0" serde = "1.0"
serde_yaml = "0.9" serde_yaml = "0.9"
serde_json = "1.0.94" serde_json = "1.0.94"
@@ -28,9 +29,10 @@ fs2 = "0.4.3"
os_info = "3.5.1" os_info = "3.5.1"
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies] [target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
sudo = "0.6.0" sudo = "0.6.0"
libc = "0.2"
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] } winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] }
#runas = "0.2.1" #runas = "0.2.1"
windows-service = "0.5.0" windows-service = "0.6.0"
+50
View File
@@ -0,0 +1,50 @@
switch_about: "A virtual network tool that will obtain an ip after startup. Devices under the same token will form a virtual local area network, and can use ip to communicate directly with each other."
switch_usage: "switch-desktop.exe <COMMAND>"
switch_start_about: "Start switch"
switch_token_help: "Using the same token, you can build a local area network. It is recommended to use a more complex token to avoid connecting to other people's local area network"
switch_name_help: "Give the device a name, the system version information will be used by default"
switch_device_id_help: "The unique identifier of the device, the ip is assigned according to the id, and the MAC address is used by default"
switch_server_help: "Registry and relay server address, public server is used by default"
switch_nat_test_server_help: "NAT detection server addresses, separated by commas"
switch_log_help: "Record the log, the output is in the '${home}/.switch_desktop' directory, it is not recommended to open it for long-term use"
switch_tap_help: "Use tap mode, tun mode will be used by default"
switch_in_ip_help: "Use when configuring point-to-network (IP proxy), --in-ip 192.168.10.0/24,10.26.0.3, which means it is allowed to receive data from the network segment 192.168.10.0/24 and forward it to 10.26.0.3"
switch_out_ip_help: "Use when configuring point-to-network, --out-ip 192.168.10.0/24,192.168.1.10, which means that the data with the target of 192.168.10.0/24 is allowed to be forwarded from the network card 192.168.1.10"
switch_password_help: "Client Data Encryption"
switch_config_help: "Read configuration file"
switch_stop_about: "Stop background service"
switch_route_about: "View route"
switch_list_about: "View device list"
switch_list_all_help: "View full information"
switch_status_about: "View current device information"
switch_install_about: "Install windows service"
switch_path_help: "Service installation path, it is recommended to use an empty directory"
switch_auto_help: "Service starts automatically at boot"
switch_uninstall_about: "Uninstall windows service"
switch_config_about: "Change Windows Service Configuration"
switch_use_admin_print: "Please run with administrator privileges"
switch_use_root_print: "Please run with root privileges"
switch_service_not_start_print: "service not started"
switch_start_successfully_print: "Start successfully"
switch_start_failed_print: "Startup failed"
switch_service_not_stopped_print: "service not stopped"
switch_stopped_print: "stopped"
switch_server_already_installed_print: "service is installed"
switch_repeated_start_print: "cannot be restarted repeatedly"
switch_token_not_found_print: "missing token"
switch_token_cannot_be_empty_print: "token cannot be empty"
switch_token_cannot_exceed_64_print: "token cannot exceed 64 characters"
switch_device_id_is_empty_print: "The device id cannot be empty and the length cannot be greater than 64 characters"
switch_in_ips_example_print: "in_ips Parameter error Example:--in_ip 192.168.10.0/24,10.26.0.3"
switch_out_ips_example_print: "out_ips Parameter error Example:--out_ip 192.168.10.0/24,192.168.0.5"
switch_relay_server_address_error: "Wrong relay server address"
switch_nat_test_server_address_error: "NAT detection service address error"
switch_press_any_key_to_exit: "Press any key to exit"
switch_virtual_ip: "virtual ip"
switch_virtual_gateway: "virtual gateway"
switch_please_enter_the_command: "Please enter the command (Usage: list,route,status,exit,help):"
+50
View File
@@ -0,0 +1,50 @@
switch_about: "一个虚拟网络工具,启动后会获取一个ip,相同token下的设备会组件虚拟局域网,之间可以用ip直接通信"
switch_usage: "switch-desktop.exe <命令>"
switch_start_about: "启动switch"
switch_token_help: "使用相同的token,就能组建一个局域网络,建议使用一个复杂一点的token,避免连到其他人的局域网中"
switch_name_help: "给设备一个名字,默认会使用系统版本信息"
switch_device_id_help: "设备唯一标识符,凭id分配ip,默认使用MAC地址"
switch_server_help: "注册和中继服务器地址,默认使用公共服务器"
switch_nat_test_server_help: "NAT探测服务器地址,使用逗号分隔"
switch_log_help: "记录日志,输出在 '${home}/.switch_desktop' 目录下,长时间使用时不建议开启"
switch_tap_help: "使用tap模式,默认会使用tun模式"
switch_in_ip_help: "配置点对网(IP代理)时使用,--in-ip 192.168.10.0/24,10.26.0.3,表示允许接收网段192.168.10.0/24的数据并转发到10.26.0.3"
switch_out_ip_help: "配置点对网时使用,--out-ip 192.168.10.0/24,192.168.1.10,表示允许目标为192.168.10.0/24的数据从网卡192.168.1.10转发出去"
switch_password_help: "使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密。使用相同密码的客户端才能通信"
switch_config_help: "读取配置文件"
switch_stop_about: "停止后台服务"
switch_route_about: "查看路由"
switch_list_about: "查看设备列表"
switch_list_all_help: "查看完整信息"
switch_status_about: "查看当前设备信息"
switch_install_about: "安装Windows服务"
switch_path_help: "服务安装路径,建议使用一个空目录"
switch_auto_help: "服务开机自启动"
switch_uninstall_about: "卸载Windows服务"
switch_config_about: "改变Windows服务配置"
switch_use_admin_print: "请使用管理员权限运行"
switch_use_root_print: "请使用root权限运行"
switch_service_not_start_print: "服务未启动"
switch_start_successfully_print: "启动成功"
switch_start_failed_print: "启动失败"
switch_service_not_stopped_print: "服务未停止"
switch_stopped_print: "已停止"
switch_server_already_installed_print: "服务已经安装"
switch_repeated_start_print: "不能重复启动"
switch_token_not_found_print: "缺少token"
switch_token_cannot_be_empty_print: "token不能为空"
switch_token_cannot_exceed_64_print: "token不能超过64个字符"
switch_device_id_is_empty_print: "设备id不能为空并且长度不能大于64字符"
switch_in_ips_example_print: "in_ips 参数错误 示例:--in_ip 192.168.10.0/24,10.26.0.3"
switch_out_ips_example_print: "out_ips 参数错误 示例:--out_ip 192.168.10.0/24,192.168.0.5"
switch_relay_server_address_error: "中继服务器地址错误"
switch_nat_test_server_address_error: "NAT检测服务地址错误"
switch_press_any_key_to_exit: "按任意键退出"
switch_virtual_ip: "当前虚拟ip(virtual ip)"
switch_virtual_gateway: "虚拟网关(virtual gateway)"
switch_please_enter_the_command: "输入命令 (例如: list,route,status,exit,help):"
+1 -1
View File
@@ -182,7 +182,7 @@ fn command(cmd: &str, switch: &Switch) -> io::Result<String> {
"stopping".to_string() "stopping".to_string()
} }
_ => { _ => {
format!("command '{}' not fount. \n Try to enter: 'help'\n", cmd) format!("command '{}' not found. \n Try to enter: 'help'\n", cmd)
} }
}; };
Ok(out_str) Ok(out_str)
+133
View File
@@ -0,0 +1,133 @@
use clap::{Arg, ArgAction, Command};
use clap::builder::BoolishValueParser;
use crate::i18n::*;
fn common() -> Command {
Command::new("switch-desktop")
.about(switch_about())
// .version(switch_version())
.subcommand_required(true)
.arg_required_else_help(true)
// .author(switch_author())
.override_usage(switch_usage())
.subcommand(
Command::new("start")
.about(switch_start_about())
.arg(
Arg::new("token")
.long("token")
.help(switch_token_help())
.action(ArgAction::Set)
)
.arg(
Arg::new("name")
.long("name")
.help(switch_name_help())
.action(ArgAction::Set)
)
.arg(
Arg::new("device_id")
.long("device-id")
.help(switch_device_id_help())
.action(ArgAction::Set)
).arg(
Arg::new("server")
.long("server")
.help(switch_server_help())
.action(ArgAction::Set)
).arg(
Arg::new("nat_test_server")
.long("nat-test-server")
.help(switch_nat_test_server_help())
.action(ArgAction::Set)
).arg(
Arg::new("log")
.long("log")
.help(switch_log_help())
.action(ArgAction::SetTrue)
.value_parser(BoolishValueParser::new()),
).arg(
Arg::new("tap")
.long("tap")
.help(switch_tap_help())
.action(ArgAction::SetTrue),
).arg(
Arg::new("in_ip")
.long("in-ip")
.help(switch_in_ip_help())
.action(ArgAction::Append)
.num_args(1..),
).arg(
Arg::new("out_ip")
.long("out-ip")
.help(switch_out_ip_help())
.action(ArgAction::Append)
).arg(
Arg::new("password")
.long("password")
.help(switch_password_help())
.action(ArgAction::Set)
).arg(
Arg::new("config")
.long("config")
.help(switch_config_help())
.action(ArgAction::Set)
)
,
).subcommand(
Command::new("stop")
.about(switch_stop_about()))
.subcommand(
Command::new("route")
.about(switch_route_about()))
.subcommand(Command::new("list")
.about(switch_list_about()).arg(
Arg::new("all")
.long("all")
.short('a')
.help(switch_list_all_help())
.action(ArgAction::SetTrue)
.value_parser(BoolishValueParser::new()), ))
.subcommand(Command::new("status")
.about(switch_status_about()))
}
pub fn check() -> bool {
#[cfg(windows)]
let cmd = common().subcommand(Command::new("install")
.about(switch_install_about())
.arg(
Arg::new("path")
.long("path")
.help(switch_path_help())
.action(ArgAction::Set)
.num_args(1..))
.arg(
Arg::new("auto")
.long("auto")
.help(switch_auto_help())
.action(ArgAction::SetTrue)
.value_parser(BoolishValueParser::new()), ))
.subcommand(Command::new("uninstall")
.about(switch_uninstall_about()))
.subcommand(Command::new("config")
.about(switch_config_about())
.arg(
Arg::new("auto")
.long("auto")
.help(switch_auto_help())
.action(ArgAction::SetTrue)
.value_parser(BoolishValueParser::new()), ));
#[cfg(any(unix))]
let cmd = common();
match cmd.try_get_matches() {
Ok(_) => {
true
}
Err(e) => {
println!("{}", e);
false
}
}
}
+75 -21
View File
@@ -8,7 +8,7 @@ use lazy_static::lazy_static;
use parking_lot::Mutex; use parking_lot::Mutex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::StartArgs; use crate::{i18n, StartArgs};
pub mod log_config; pub mod log_config;
lazy_static! { lazy_static! {
@@ -25,6 +25,7 @@ pub fn set_win_server_home(home: PathBuf) {
let _ = SWITCH_HOME_PATH.lock().insert(home); let _ = SWITCH_HOME_PATH.lock().insert(home);
} }
#[derive(Clone, Debug)]
pub struct StartConfig { pub struct StartConfig {
pub tap: bool, pub tap: bool,
pub name: String, pub name: String,
@@ -36,6 +37,8 @@ pub struct StartConfig {
pub out_ips: Vec<(u32, u32, Ipv4Addr)>, pub out_ips: Vec<(u32, u32, Ipv4Addr)>,
#[cfg(any(unix))] #[cfg(any(unix))]
pub off_command_server: bool, pub off_command_server: bool,
pub log: bool,
pub password: Option<String>,
} }
fn ips_parse(ips: &Vec<String>) -> Result<Vec<(u32, u32, Ipv4Addr)>, String> { fn ips_parse(ips: &Vec<String>) -> Result<Vec<(u32, u32, Ipv4Addr)>, String> {
@@ -89,6 +92,9 @@ fn ips_parse(ips: &Vec<String>) -> Result<Vec<(u32, u32, Ipv4Addr)>, String> {
pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> { pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
println!("========参数配置========"); println!("========参数配置========");
if start_args.log {
println!("print log");
}
let tap = start_args.tap; let tap = start_args.tap;
if tap { if tap {
println!("use tap"); println!("use tap");
@@ -96,14 +102,14 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
println!("use tun"); println!("use tun");
} }
if start_args.token.is_none() { if start_args.token.is_none() {
return Err("找不到token(Token not found)".to_string()); return Err(i18n::switch_token_not_found_print());
} }
let token = start_args.token.unwrap(); let token = start_args.token.unwrap();
if token.is_empty() { if token.is_empty() {
return Err("token不能为空(Token cannot be empty)".to_string()); return Err(i18n::switch_token_cannot_be_empty_print());
} }
if token.len() > 64 { if token.len() > 64 {
return Err("token不能超过64字符(Token cannot exceed 64 characters)".to_string()); return Err(i18n::switch_token_cannot_exceed_64_print());
} }
println!("token:{:?}", token); println!("token:{:?}", token);
let name = start_args.name.unwrap_or_else(|| { let name = start_args.name.unwrap_or_else(|| {
@@ -124,7 +130,7 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
} }
}); });
if device_id.is_empty() || device_id.len() > 64 { if device_id.is_empty() || device_id.len() > 64 {
return Err("设备id不能为空并且长度不能大于64字符(The device id cannot be empty and the length cannot be greater than 64 characters)".to_string()); return Err(i18n::switch_device_id_is_empty_print());
} }
println!("device_id:{:?}", device_id); println!("device_id:{:?}", device_id);
let in_ips = start_args.in_ip.unwrap_or_else(|| { let in_ips = start_args.in_ip.unwrap_or_else(|| {
@@ -137,13 +143,13 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
let in_ips_c = if let Ok(in_ips_c) = ips_parse(&in_ips) { let in_ips_c = if let Ok(in_ips_c) = ips_parse(&in_ips) {
in_ips_c in_ips_c
} else { } else {
return Err("in_ips 参数错误 示例:--in_ip 192.168.10.0/24,10.26.0.3".to_string()); return Err(i18n::switch_in_ips_example_print());
}; };
println!("out_ips:{:?}", out_ips); println!("out_ips:{:?}", out_ips);
let out_ips_c = if let Ok(out_ips_c) = ips_parse(&out_ips) { let out_ips_c = if let Ok(out_ips_c) = ips_parse(&out_ips) {
out_ips_c out_ips_c
} else { } else {
return Err("out_ips 参数错误 示例:--out_ip 192.168.10.0/24,192.168.0.5".to_string()); return Err(i18n::switch_out_ips_example_print());
}; };
@@ -154,11 +160,11 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
if let Some(addr) = server.next() { if let Some(addr) = server.next() {
addr addr
} else { } else {
return Err("中继服务器地址错误( Relay server address error)".to_string()); return Err(i18n::switch_relay_server_address_error());
} }
} }
Err(e) => { Err(e) => {
return Err(format!("中继服务器地址错误( Relay server address error) :{:?}", e)); return Err(format!("{} :{:?}", i18n::switch_relay_server_address_error(), e));
} }
}; };
println!("中继服务器:{:?}", server); println!("中继服务器:{:?}", server);
@@ -167,7 +173,7 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
}).split(",").flat_map(|a| a.to_socket_addrs()).flatten() }).split(",").flat_map(|a| a.to_socket_addrs()).flatten()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if nat_test_server.is_empty() { if nat_test_server.is_empty() {
return Err("NAT检测服务地址错误(NAT detection service address error)".to_string()); return Err(i18n::switch_nat_test_server_address_error());
} }
println!("NAT探测服务器:{:?}", nat_test_server); println!("NAT探测服务器:{:?}", nat_test_server);
let base_config = StartConfig { let base_config = StartConfig {
@@ -181,6 +187,8 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
out_ips: out_ips_c, out_ips: out_ips_c,
#[cfg(any(unix))] #[cfg(any(unix))]
off_command_server: start_args.off_command_server, off_command_server: start_args.off_command_server,
log: start_args.log,
password: start_args.password,
}; };
println!("========参数配置========"); println!("========参数配置========");
Ok(base_config) Ok(base_config)
@@ -193,7 +201,10 @@ pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, String> {
} else { } else {
return Err("读取配置文件失败".to_string()); return Err("读取配置文件失败".to_string());
}; };
let log = args_config.log;
if log {
println!("print log");
}
let tap = args_config.tap; let tap = args_config.tap;
if tap { if tap {
println!("use tap"); println!("use tap");
@@ -202,10 +213,10 @@ pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, String> {
} }
let token = args_config.token; let token = args_config.token;
if token.is_empty() { if token.is_empty() {
return Err("token不能为空(Token cannot be empty)".to_string()); return Err(i18n::switch_token_cannot_be_empty_print());
} }
if token.len() > 64 { if token.len() > 64 {
return Err("token不能超过64字符(Token cannot exceed 64 characters)".to_string()); return Err(i18n::switch_token_cannot_exceed_64_print());
} }
println!("token:{:?}", token); println!("token:{:?}", token);
let name = args_config.name; let name = args_config.name;
@@ -226,7 +237,7 @@ pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, String> {
} }
}; };
if device_id.is_empty() || device_id.len() > 64 { if device_id.is_empty() || device_id.len() > 64 {
return Err("设备id不能为空并且长度不能大于64字符(The device id cannot be empty and the length cannot be greater than 64 characters)".to_string()); return Err(i18n::switch_device_id_is_empty_print());
} }
println!("device_id:{:?}", device_id); println!("device_id:{:?}", device_id);
let in_ips = args_config.in_ips; let in_ips = args_config.in_ips;
@@ -235,13 +246,13 @@ pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, String> {
let in_ips_c = if let Ok(in_ips_c) = ips_parse(&in_ips) { let in_ips_c = if let Ok(in_ips_c) = ips_parse(&in_ips) {
in_ips_c in_ips_c
} else { } else {
return Err("in_ips 参数错误 示例:--in_ip 192.168.10.0/24,10.26.0.3".to_string()); return Err(i18n::switch_in_ips_example_print());
}; };
println!("out_ips:{:?}", out_ips); println!("out_ips:{:?}", out_ips);
let out_ips_c = if let Ok(out_ips_c) = ips_parse(&out_ips) { let out_ips_c = if let Ok(out_ips_c) = ips_parse(&out_ips) {
out_ips_c out_ips_c
} else { } else {
return Err("out_ips 参数错误 示例:--out_ip 192.168.10.0/24,192.168.0.5".to_string()); return Err(i18n::switch_out_ips_example_print());
}; };
let server = match { let server = match {
if !args_config.server.is_empty() { if !args_config.server.is_empty() {
@@ -255,11 +266,11 @@ pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, String> {
if let Some(addr) = server.next() { if let Some(addr) = server.next() {
addr addr
} else { } else {
return Err("中继服务器地址错误( Relay server address error)".to_string()); return Err(i18n::switch_relay_server_address_error());
} }
} }
Err(e) => { Err(e) => {
return Err(format!("中继服务器地址错误( Relay server address error) :{:?}", e)); return Err(format!("{}:{:?}", i18n::switch_relay_server_address_error(), e));
} }
}; };
println!("中继服务器:{:?}", server); println!("中继服务器:{:?}", server);
@@ -270,7 +281,7 @@ pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, String> {
}.iter().flat_map(|a| a.to_socket_addrs()).flatten() }.iter().flat_map(|a| a.to_socket_addrs()).flatten()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if nat_test_server.is_empty() { if nat_test_server.is_empty() {
return Err("NAT检测服务地址错误(NAT detection service address error)".to_string()); return Err(i18n::switch_nat_test_server_address_error());
} }
println!("NAT探测服务器:{:?}", nat_test_server); println!("NAT探测服务器:{:?}", nat_test_server);
let base_config = StartConfig { let base_config = StartConfig {
@@ -284,6 +295,8 @@ pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, String> {
out_ips: out_ips_c, out_ips: out_ips_c,
#[cfg(any(unix))] #[cfg(any(unix))]
off_command_server: args_config.off_command_server, off_command_server: args_config.off_command_server,
log,
password:args_config.password
}; };
println!("========参数配置========"); println!("========参数配置========");
Ok(base_config) Ok(base_config)
@@ -319,6 +332,47 @@ pub struct ArgsConfig {
#[cfg(any(unix))] #[cfg(any(unix))]
#[serde(default = "default_false")] #[serde(default = "default_false")]
pub off_command_server: bool, pub off_command_server: bool,
#[serde(default = "default_false")]
pub log: bool,
pub password: Option<String>,
}
#[cfg(windows)]
impl ArgsConfig {
pub fn new(start_config: StartConfig) -> ArgsConfig {
let in_ips = start_config.in_ips.iter().map(|(ip, mask, dest)| {
format!("{}/{},{}", Ipv4Addr::from(*ip), subnet_mask_to_integer(*mask), dest)
}).collect::<Vec<String>>();
let out_ips = start_config.out_ips.iter().map(|(ip, mask, dest)| {
format!("{}/{},{}", Ipv4Addr::from(*ip), subnet_mask_to_integer(*mask), dest)
}).collect::<Vec<String>>();
ArgsConfig {
tap: start_config.tap,
version: "1.0.6".to_string(),
token: start_config.token.to_string(),
name: start_config.name.to_string(),
server: start_config.server.to_string(),
nat_test_server: start_config.nat_test_server.iter().map(|v| v.to_string()).collect(),
device_id: start_config.device_id,
in_ips,
out_ips,
log: start_config.log,
#[cfg(any(unix))]
off_command_server: start_config.off_command_server,
password: start_config.password,
}
}
}
#[cfg(windows)]
fn subnet_mask_to_integer(subnet_mask: u32) -> u8 {
let mut mask_bits = subnet_mask;
let mut num_bits = 0;
while mask_bits != 0 {
num_bits += 1;
mask_bits <<= 1;
}
num_bits as u8
} }
fn default_false() -> bool { fn default_false() -> bool {
@@ -326,7 +380,7 @@ fn default_false() -> bool {
} }
fn default_version() -> String { fn default_version() -> String {
"1.0".to_string() "1.0.6".to_string()
} }
fn default_str() -> String { fn default_str() -> String {
@@ -399,7 +453,7 @@ pub fn read_command_port() -> io::Result<u16> {
if let Some(p) = config.command_port { if let Some(p) = config.command_port {
Ok(p) Ok(p)
} else { } else {
Err(io::Error::new(io::ErrorKind::Other, "not fount config")) Err(io::Error::new(io::ErrorKind::Other, "not found config"))
} }
} }
+214
View File
@@ -0,0 +1,214 @@
#[cfg(target_os = "windows")]
fn get_default_language() -> Option<String> {
use std::process::Command;
use std::str;
let output = Command::new("powershell")
.arg("-Command")
.arg("[System.Globalization.CultureInfo]::CurrentCulture.Name")
.output()
.ok()?;
let language_code = str::from_utf8(&output.stdout)
.ok()?
.trim()
.to_string();
Some(language_code)
}
pub fn init() {
#[cfg(target_os = "windows")]
{
if let Some(l) = get_default_language() {
rust_i18n::set_locale(&l);
}
}
}
pub fn switch_about() -> String {
rust_i18n::t!("switch_about")
}
pub fn switch_usage() -> String {
rust_i18n::t!("switch_usage")
}
pub fn switch_start_about() -> String {
rust_i18n::t!("switch_start_about")
}
pub fn switch_token_help() -> String {
rust_i18n::t!("switch_token_help")
}
pub fn switch_name_help() -> String {
rust_i18n::t!("switch_name_help")
}
pub fn switch_device_id_help() -> String {
rust_i18n::t!("switch_device_id_help")
}
pub fn switch_server_help() -> String {
rust_i18n::t!("switch_server_help")
}
pub fn switch_nat_test_server_help() -> String {
rust_i18n::t!("switch_nat_test_server_help")
}
pub fn switch_log_help() -> String {
rust_i18n::t!("switch_log_help")
}
pub fn switch_tap_help() -> String {
rust_i18n::t!("switch_tap_help")
}
pub fn switch_in_ip_help() -> String {
rust_i18n::t!("switch_in_ip_help")
}
pub fn switch_out_ip_help() -> String {
rust_i18n::t!("switch_out_ip_help")
}
pub fn switch_password_help() -> String {
rust_i18n::t!("switch_password_help")
}
pub fn switch_config_help() -> String {
rust_i18n::t!("switch_config_help")
}
pub fn switch_stop_about() -> String {
rust_i18n::t!("switch_stop_about")
}
pub fn switch_route_about() -> String {
rust_i18n::t!("switch_route_about")
}
pub fn switch_list_about() -> String {
rust_i18n::t!("switch_list_about")
}
pub fn switch_list_all_help() -> String {
rust_i18n::t!("switch_list_all_help")
}
pub fn switch_status_about() -> String {
rust_i18n::t!("switch_status_about")
}
#[cfg(windows)]
pub fn switch_install_about() -> String {
rust_i18n::t!("switch_install_about")
}
#[cfg(windows)]
pub fn switch_path_help() -> String {
rust_i18n::t!("switch_path_help")
}
#[cfg(windows)]
pub fn switch_auto_help() -> String {
rust_i18n::t!("switch_auto_help")
}
#[cfg(windows)]
pub fn switch_uninstall_about() -> String {
rust_i18n::t!("switch_uninstall_about")
}
#[cfg(windows)]
pub fn switch_config_about() -> String {
rust_i18n::t!("switch_config_about")
}
#[cfg(windows)]
pub fn switch_use_root_print() -> String {
rust_i18n::t!("switch_use_admin_print")
}
#[cfg(unix)]
pub fn switch_use_root_print() -> String {
rust_i18n::t!("switch_use_root_print")
}
#[cfg(windows)]
pub fn switch_service_not_start_print() -> String {
rust_i18n::t!("switch_service_not_start_print")
}
pub fn switch_start_successfully_print() -> String {
rust_i18n::t!("switch_start_successfully_print")
}
#[cfg(windows)]
pub fn switch_start_failed_print() -> String {
rust_i18n::t!("switch_start_failed_print")
}
#[cfg(windows)]
pub fn switch_service_not_stopped_print() -> String {
rust_i18n::t!("switch_service_not_stopped_print")
}
#[cfg(windows)]
pub fn switch_server_already_installed_print() -> String {
rust_i18n::t!("switch_server_already_installed_print")
}
pub fn switch_repeated_start_print() -> String {
rust_i18n::t!("switch_repeated_start_print")
}
pub fn switch_stopped_print() -> String {
rust_i18n::t!("switch_stopped_print")
}
pub fn switch_token_not_found_print() -> String {
rust_i18n::t!("switch_token_not_found_print")
}
pub fn switch_token_cannot_be_empty_print() -> String {
rust_i18n::t!("switch_token_cannot_be_empty_print")
}
pub fn switch_token_cannot_exceed_64_print() -> String {
rust_i18n::t!("switch_token_cannot_exceed_64_print")
}
pub fn switch_device_id_is_empty_print() -> String {
rust_i18n::t!("switch_device_id_is_empty_print")
}
pub fn switch_in_ips_example_print() -> String {
rust_i18n::t!("switch_in_ips_example_print")
}
pub fn switch_out_ips_example_print() -> String {
rust_i18n::t!("switch_out_ips_example_print")
}
pub fn switch_relay_server_address_error() -> String {
rust_i18n::t!("switch_relay_server_address_error")
}
pub fn switch_nat_test_server_address_error() -> String {
rust_i18n::t!("switch_nat_test_server_address_error")
}
pub fn switch_press_any_key_to_exit() -> String {
rust_i18n::t!("switch_press_any_key_to_exit")
}
pub fn switch_virtual_ip() -> String {
rust_i18n::t!("switch_virtual_ip")
}
pub fn switch_virtual_gateway() -> String {
rust_i18n::t!("switch_virtual_gateway")
}
pub fn switch_please_enter_the_command() -> String {
rust_i18n::t!("switch_please_enter_the_command")
}
+29 -21
View File
@@ -11,10 +11,11 @@ mod command;
mod config; mod config;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
mod windows; mod windows;
#[cfg(any(unix))] #[cfg(any(unix))]
mod unix; mod unix;
mod console_out; mod console_out;
mod command_args;
mod i18n;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command( #[command(
@@ -60,7 +61,7 @@ enum Commands {
Status, Status,
} }
#[derive(Parser, Debug,Default)] #[derive(Parser, Debug, Default)]
pub struct StartArgs { pub struct StartArgs {
/// 不超过64个字符 /// 不超过64个字符
/// 相同token的设备之间才能通信。 /// 相同token的设备之间才能通信。
@@ -101,15 +102,18 @@ pub struct StartArgs {
/// 配置点对网时使用,--in-ip 192.168.10.0/24,10.26.0.3,表示允许接收网段192.168.10.0/24的数据并转发到10.26.0.3 /// 配置点对网时使用,--in-ip 192.168.10.0/24,10.26.0.3,表示允许接收网段192.168.10.0/24的数据并转发到10.26.0.3
/// Use when configuring peer-to-peer networks /// Use when configuring peer-to-peer networks
#[arg(long)] #[arg(long)]
in_ip:Option<Vec<String>>, in_ip: Option<Vec<String>>,
/// 配置点对网时使用,--out-ip 192.168.10.0/24,192.168.1.10,表示允许目标为192.168.10.0/24的数据从网卡192.168.1.10转发出去 /// 配置点对网时使用,--out-ip 192.168.10.0/24,192.168.1.10,表示允许目标为192.168.10.0/24的数据从网卡192.168.1.10转发出去
/// Use when configuring peer-to-peer networks /// Use when configuring peer-to-peer networks
#[arg(long)] #[arg(long)]
out_ip:Option<Vec<String>>, out_ip: Option<Vec<String>>,
/// 客户端数据加密
#[arg(long)]
password:Option<String>,
/// 读取配置文件 --config config_file_path /// 读取配置文件 --config config_file_path
/// Read configuration file /// Read configuration file
#[arg(long)] #[arg(long)]
config:Option<String>, config: Option<String>,
} }
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
@@ -134,10 +138,14 @@ pub struct ConfigArgs {
auto: bool, auto: bool,
} }
#[macro_use]
extern crate rust_i18n;
i18n!("locales", fallback = "en");
#[cfg(windows)] #[cfg(windows)]
#[tokio::main] fn main() {
async fn main() { i18n::init();
let args: Vec<_> = std::env::args().collect(); let args: Vec<_> = std::env::args().collect();
if args.len() == 3 && args[1] == windows::SERVICE_FLAG { if args.len() == 3 && args[1] == windows::SERVICE_FLAG {
//以服务的方式启动 //以服务的方式启动
@@ -145,13 +153,16 @@ async fn main() {
windows::service::start(); windows::service::start();
return; return;
} else { } else {
if !command_args::check() {
return;
}
let args = BaseArgs::parse(); let args = BaseArgs::parse();
if let Commands::Start(start_args) = &args.command { if let Commands::Start(start_args) = &args.command {
if start_args.log { if start_args.log {
let _ = log_init(); let _ = log_init();
} }
} }
windows::main0(args).await; windows::main0(args);
} }
} }
@@ -177,26 +188,23 @@ async fn main() {
pub fn console_listen(switch: &Switch) { pub fn console_listen(switch: &Switch) {
use console::Term; use console::Term;
let term = Term::stdout(); let term = Term::stdout();
println!("{}", style("启动成功 started").green()); println!("{}", style(i18n::switch_start_successfully_print()).green());
let current_device = switch.current_device(); let current_device = switch.current_device();
println!( println!("{}: {:?}", i18n::switch_virtual_ip(), style(current_device.virtual_ip()).green());
"当前虚拟ip(virtual ip): {:?}", println!("{}: {:?}", i18n::switch_virtual_gateway(), style(current_device.virtual_gateway()).green());
style(current_device.virtual_ip()).green()
);
println!(
"虚拟网关(virtual gateway): {:?}",
style(current_device.virtual_gateway()).green()
);
loop { loop {
println!( println!(
"{}", "{}",
style("Please enter the command (Usage: list,status,exit,help):").color256(102) style(i18n::switch_please_enter_the_command()).color256(102)
); );
match term.read_line() { match term.read_line() {
Ok(cmd) => { Ok(cmd) => {
#[cfg(unix)]
if cmd.is_empty() { if cmd.is_empty() {
log::warn!("非正常返回"); use libc::{STDIN_FILENO, isatty};
return; if !unsafe { isatty(STDIN_FILENO) != 0 } {
return;
}
} }
if command(cmd.trim(), &switch).is_err() { if command(cmd.trim(), &switch).is_err() {
println!("{}", style("stopping").red()); println!("{}", style("stopping").red());
@@ -249,7 +257,7 @@ fn command(cmd: &str, switch: &Switch) -> Result<(), ()> {
return Err(()); return Err(());
} }
_ => { _ => {
println!("command '{}' not fount. ", style(cmd).red()); println!("command '{}' not found. ", style(cmd).red());
println!("Try to enter: '{}'", style("help").green()); println!("Try to enter: '{}'", style("help").green());
} }
} }
+1
View File
@@ -45,6 +45,7 @@ pub async fn main0(base_args: BaseArgs) {
start_config.nat_test_server.clone(), start_config.nat_test_server.clone(),
start_config.in_ips.clone(), start_config.in_ips.clone(),
start_config.out_ips.clone(), start_config.out_ips.clone(),
start_config.password.clone(),
); );
let lock = match config::lock_file() { let lock = match config::lock_file() {
Ok(lock) => { Ok(lock) => {
+56 -34
View File
@@ -14,7 +14,7 @@ use windows_service::service_manager::{ServiceManager, ServiceManagerAccess};
use switch::core::{Config, Switch}; use switch::core::{Config, Switch};
use crate::{BaseArgs, Commands, config}; use crate::{BaseArgs, Commands, config, i18n};
use crate::command::{command, CommandEnum}; use crate::command::{command, CommandEnum};
pub mod service; pub mod service;
@@ -28,7 +28,7 @@ fn admin_check() -> bool {
if !windows_admin_check::is_app_elevated() { if !windows_admin_check::is_app_elevated() {
println!( println!(
"{}", "{}",
style("请使用管理员权限运行(Please run with administrator privileges)").red() style(i18n::switch_use_root_print()).red()
); );
true true
} else { } else {
@@ -42,7 +42,7 @@ fn not_started() -> bool {
if state == ServiceState::Running { if state == ServiceState::Running {
return false; return false;
} else { } else {
println!("服务未启动") println!("{}", i18n::switch_service_not_start_print())
} }
} }
Err(e) => { Err(e) => {
@@ -52,7 +52,7 @@ fn not_started() -> bool {
return true; return true;
} }
pub async fn main0(base_args: BaseArgs) { pub fn main0(base_args: BaseArgs) {
match base_args.command { match base_args.command {
Commands::Start(args) => { Commands::Start(args) => {
if admin_check() { if admin_check() {
@@ -92,15 +92,15 @@ pub async fn main0(base_args: BaseArgs) {
Ok(_) => { Ok(_) => {
//需要检查启动状态 //需要检查启动状态
thread::sleep(Duration::from_secs(2)); thread::sleep(Duration::from_secs(2));
println!("{}", style("启动成功(Start successfully)").green()); println!("{}", style(i18n::switch_start_successfully_print()).green());
} }
Err(e) => { Err(e) => {
log::error!("{:?}", e); log::error!("{:?}", e);
println!("{}:{}", style("启动失败").red(),e); println!("{}:{}", style(i18n::switch_start_failed_print()).red(), e);
} }
} }
} else { } else {
println!("服务未停止(Service not stopped)"); println!("{}", i18n::switch_service_not_stopped_print());
} }
} }
Err(e) => { Err(e) => {
@@ -109,10 +109,6 @@ pub async fn main0(base_args: BaseArgs) {
if let Some(code) = e.raw_os_error() { if let Some(code) = e.raw_os_error() {
if code == 1060 { if code == 1060 {
//指定的服务未安装。 //指定的服务未安装。
println!(
"{}",
style("服务未安装,在当前进程启动(The service is not installed and started in the current process)").red()
);
let config = Config::new( let config = Config::new(
start_config.tap, start_config.tap,
start_config.token, start_config.token,
@@ -122,6 +118,7 @@ pub async fn main0(base_args: BaseArgs) {
start_config.nat_test_server, start_config.nat_test_server,
start_config.in_ips, start_config.in_ips,
start_config.out_ips, start_config.out_ips,
start_config.password,
); );
let lock = match config::lock_file() { let lock = match config::lock_file() {
Ok(lock) => { Ok(lock) => {
@@ -134,18 +131,20 @@ pub async fn main0(base_args: BaseArgs) {
} }
}; };
if lock.try_lock_exclusive().is_err() { if lock.try_lock_exclusive().is_err() {
println!("{}", style("文件被重复打开").red()); println!("{}", style(i18n::switch_repeated_start_print()).red());
return; return;
} }
match Switch::start(config).await { tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap().block_on(async move {
Ok(switch) => { match Switch::start(config).await {
crate::console_listen(&switch); Ok(switch) => {
crate::console_listen(&switch);
}
Err(e) => {
log::error!("{:?}", e);
println!("启动switch失败:{:?}", e);
}
} }
Err(e) => { });
log::error!("{:?}", e);
println!("启动switch失败:{:?}", e);
}
}
lock.unlock().unwrap(); lock.unlock().unwrap();
return; return;
} }
@@ -167,11 +166,11 @@ pub async fn main0(base_args: BaseArgs) {
} }
match stop() { match stop() {
Ok(_) => { Ok(_) => {
println!("{}", style("停止成功(Stopped successfully)").green()) println!("{}", style(i18n::switch_stopped_print()).green())
} }
Err(e) => { Err(e) => {
log::error!("{:?}", e); log::error!("{:?}", e);
println!("停止失败:{}",e); println!("停止失败:{}", e);
} }
} }
pause(); pause();
@@ -180,6 +179,10 @@ pub async fn main0(base_args: BaseArgs) {
if admin_check() { if admin_check() {
return; return;
} }
if service_state().is_ok() {
println!("{}", i18n::switch_server_already_installed_print());
return;
}
let path: PathBuf = args.path.into(); let path: PathBuf = args.path.into();
if !path.exists() { if !path.exists() {
std::fs::create_dir_all(&path).unwrap(); std::fs::create_dir_all(&path).unwrap();
@@ -189,7 +192,7 @@ pub async fn main0(base_args: BaseArgs) {
} else { } else {
if let Err(e) = install(path, args.auto) { if let Err(e) = install(path, args.auto) {
log::error!("{:?}", e); log::error!("{:?}", e);
println!("安装失败:{}",e); println!("安装失败:{}", e);
} else { } else {
println!("{}", style("安装成功(Installation succeeded)").green()) println!("{}", style("安装成功(Installation succeeded)").green())
} }
@@ -200,18 +203,24 @@ pub async fn main0(base_args: BaseArgs) {
if admin_check() { if admin_check() {
return; return;
} }
if service_state().is_err() {
println!("服务未安装");
}
if let Err(e) = uninstall() { if let Err(e) = uninstall() {
log::error!("{:?}", e); log::error!("{:?}", e);
println!("卸载失败:{}",e); println!("卸载失败:{}", e);
} else { } else {
println!("{}", style("卸载成功(Uninstall succeeded)").green()) println!("{}", style("卸载成功(Uninstall succeeded)").green())
} }
pause(); pause();
} }
Commands::Config(args) => { Commands::Config(args) => {
if service_state().is_err() {
println!("服务未安装");
}
if let Err(e) = change(args.auto) { if let Err(e) = change(args.auto) {
log::error!("{:?}", e); log::error!("{:?}", e);
println!("配置失败:{}",e); println!("配置失败:{}", e);
} else { } else {
println!("{}", style("配置成功(Config succeeded)").green()) println!("{}", style("配置成功(Config succeeded)").green())
} }
@@ -245,14 +254,17 @@ pub async fn main0(base_args: BaseArgs) {
fn pause() { fn pause() {
println!( println!(
"{}", "{}",
style("按任意键退出(Press any key to exit)...").green() style(i18n::switch_press_any_key_to_exit()).green()
); );
use console::Term; use console::Term;
let term = Term::stdout(); let term = Term::stdout();
let _ = term.read_char().unwrap(); let _ = term.read_char().unwrap();
} }
fn install(path: PathBuf, auto: bool) -> Result<(), Error> { fn install(mut path: PathBuf, auto: bool) -> Result<(), Error> {
if !path.is_absolute() {
path = path.canonicalize().unwrap();
}
let manager_access = ServiceManagerAccess::CONNECT | ServiceManagerAccess::CREATE_SERVICE; let manager_access = ServiceManagerAccess::CONNECT | ServiceManagerAccess::CREATE_SERVICE;
let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?; let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?;
let current_exe_path = std::env::current_exe().unwrap(); let current_exe_path = std::env::current_exe().unwrap();
@@ -260,7 +272,7 @@ fn install(path: PathBuf, auto: bool) -> Result<(), Error> {
std::fs::copy(current_exe_path, service_path.as_path()).unwrap(); std::fs::copy(current_exe_path, service_path.as_path()).unwrap();
if let Err(e) = std::fs::copy("wintun.dll", path.join("wintun.dll").as_path()) { if let Err(e) = std::fs::copy("wintun.dll", path.join("wintun.dll").as_path()) {
if e.kind() == io::ErrorKind::NotFound { if e.kind() == io::ErrorKind::NotFound {
println!("Not fount 'wintun.dll'. Please put 'wintun.dll' in the current directory"); println!("'wintun.dll' not found. Please put 'wintun.dll' in the current directory");
std::process::exit(0); std::process::exit(0);
} else { } else {
panic!("{:?}", e) panic!("{:?}", e)
@@ -305,18 +317,28 @@ fn change(auto: bool) -> Result<(), Error> {
} else { } else {
ServiceStartType::OnDemand ServiceStartType::OnDemand
}; };
let mut launch_arguments = Vec::new(); let executable_path = config.executable_path.to_string_lossy().to_string();
launch_arguments.push(OsString::from(SERVICE_FLAG)); let executable_path = if executable_path.starts_with('"') && executable_path.ends_with('"') {
launch_arguments.push(OsString::from( &executable_path[1..executable_path.len() - 1]
config::get_home().to_str().unwrap(), } else {
)); &executable_path
};
let mut split = executable_path.split(SERVICE_FLAG);
let executable_path = split.next().unwrap().trim();
let executable_path = if executable_path.starts_with('"') && executable_path.ends_with('"') {
PathBuf::from(&executable_path[1..executable_path.len() - 1])
} else {
PathBuf::from(executable_path)
};
let home_path = split.next().unwrap().trim();
let launch_arguments = vec![OsString::from(SERVICE_FLAG), OsString::from(home_path)];
let service_info = ServiceInfo { let service_info = ServiceInfo {
name: OsString::from(SERVICE_NAME), name: OsString::from(SERVICE_NAME),
display_name: config.display_name, display_name: config.display_name,
service_type: SERVICE_TYPE, service_type: SERVICE_TYPE,
start_type, start_type,
error_control: config.error_control, error_control: config.error_control,
executable_path: config.executable_path, executable_path,
launch_arguments, launch_arguments,
dependencies: config.dependencies, dependencies: config.dependencies,
account_name: None, // run as System account_name: None, // run as System
+106 -59
View File
@@ -3,7 +3,9 @@
use std::ffi::OsString; use std::ffi::OsString;
use std::sync::Arc; use std::sync::Arc;
use std::thread; use std::io;
use std::io::Write;
use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
use clap::Parser; use clap::Parser;
@@ -15,36 +17,26 @@ use windows_service::service_control_handler::ServiceControlHandlerResult;
use switch::core::{Config, Switch}; use switch::core::{Config, Switch};
use crate::{BaseArgs, Commands, config, StartArgs}; use crate::{BaseArgs, Commands, config};
use crate::windows::SERVICE_NAME; use crate::windows::SERVICE_NAME;
define_windows_service!(ffi_service_main, switch_service_main); define_windows_service!(ffi_service_main, switch_service_main);
pub fn switch_service_main(arguments: Vec<OsString>) { pub fn switch_service_main(arguments: Vec<OsString>) {
let base_args = BaseArgs::parse_from(arguments); tokio::runtime::Builder::new_multi_thread()
match base_args.command { .enable_all()
Commands::Start(args) => { .build()
if args.log { .unwrap()
let _ = config::log_config::log_service_init(); .block_on(async {
match service_main(arguments).await {
Ok(_) => {}
Err(e) => {
log::error!("启动服务失败:{:?}",e);
}
} }
tokio::runtime::Builder::new_multi_thread() })
.enable_all()
.build()
.unwrap()
.block_on(async {
match service_main(args).await {
Ok(_) => {}
Err(e) => {
log::error!("启动服务失败:{:?}",e);
}
}
})
}
_ => {}
}
} }
async fn service_main(args: StartArgs) -> windows_service::Result<()> { async fn service_main(arguments: Vec<OsString>) -> windows_service::Result<()> {
log::info!("service_main{:?}",args);
let parker = crossbeam::sync::Parker::new(); let parker = crossbeam::sync::Parker::new();
let un_parker = parker.unparker().clone(); let un_parker = parker.unparker().clone();
let event_handler = move |control_event| -> ServiceControlHandlerResult { let event_handler = move |control_event| -> ServiceControlHandlerResult {
@@ -78,15 +70,12 @@ async fn service_main(args: StartArgs) -> windows_service::Result<()> {
wait_hint: Duration::default(), wait_hint: Duration::default(),
process_id: None, process_id: None,
})?; })?;
match start_switch(args).await { match start_switch(arguments).await {
Ok(switch) => { Ok(_) => {
parker.park(); parker.park();
if let Err(e) = switch.stop() {
log::warn!("switch stop:{:?}",e)
}
} }
Err(e) => { Err(e) => {
log::error!("{:?}",e); log::error!("服务启动失败 {:?}",e);
} }
} }
status_handle.set_service_status(ServiceStatus { status_handle.set_service_status(ServiceStatus {
@@ -100,25 +89,75 @@ async fn service_main(args: StartArgs) -> windows_service::Result<()> {
}) })
} }
async fn start_switch(args: StartArgs) -> switch::Result<Arc<Switch>> { fn auto_config_path() -> io::Result<PathBuf> {
let start_config = if let Some(config_path) = &args.config { Ok(config::get_win_server_home().join("auto_config.yaml"))
match config::read_config_file(config_path.into()) { }
Ok(start_config) => {
start_config fn save_auto_config(start_config: config::StartConfig) -> io::Result<()> {
} let mut file = std::fs::File::create(auto_config_path()?)?;
Err(e) => { let config = config::ArgsConfig::new(start_config);
log::error!("{:?}", e); match serde_yaml::to_string(&config) {
return Err(switch::error::Error::Stop(e)); Ok(yaml) => {
file.write_all(yaml.as_bytes())
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)))
}
}
}
async fn start_switch(arguments: Vec<OsString>) -> switch::Result<()> {
let start_config = match BaseArgs::try_parse_from(arguments) {
Ok(args) => {
match args.command {
Commands::Start(args) => {
if args.log {
let _ = config::log_config::log_service_init();
}
if let Some(config_path) = &args.config {
match config::read_config_file(config_path.into()) {
Ok(start_config) => {
if let Err(e) = save_auto_config(start_config.clone()) {
log::warn!("配置文件保存失败:{:?}",e);
}
start_config
}
Err(e) => {
log::error!("{:?}", e);
return Err(switch::error::Error::Stop(e));
}
}
} else {
match config::default_config(args) {
Ok(start_config) => {
if let Err(e) = save_auto_config(start_config.clone()) {
log::warn!("配置文件保存失败:{:?}",e);
}
start_config
}
Err(e) => {
log::error!("{:?}", e);
return Err(switch::error::Error::Stop(e));
}
}
}
}
_ => {
return Err(switch::error::Error::Stop("配置文件错误".to_string()));
}
} }
} }
} else { Err(_) => {
match config::default_config(args) { match config::read_config_file(auto_config_path()?) {
Ok(start_config) => { Ok(start_config) => {
start_config if start_config.log {
} let _ = config::log_config::log_service_init();
Err(e) => { }
log::error!("{:?}", e); start_config
return Err(switch::error::Error::Stop(e)); }
Err(e) => {
return Err(switch::error::Error::Stop(e));
}
} }
} }
}; };
@@ -131,21 +170,29 @@ async fn start_switch(args: StartArgs) -> switch::Result<Arc<Switch>> {
start_config.nat_test_server, start_config.nat_test_server,
start_config.in_ips, start_config.in_ips,
start_config.out_ips, start_config.out_ips,
start_config.password,
); );
let switch = Switch::start(config).await?;
log::info!("switch-service服务启动"); log::info!("switch-service服务启动");
let switch = Arc::new(switch);
let command_server = crate::command::server::CommandServer::new();
let switch1 = switch.clone(); tokio::spawn(async move {
thread::spawn(move || { match Switch::start(config).await {
if let Err(e) = config::update_pid(std::process::id()) { Ok(switch) => {
log::error!("{:?}", e); let switch = Arc::new(switch);
} let command_server = crate::command::server::CommandServer::new();
if let Err(e) = command_server.start(switch1) { if let Err(e) = config::update_pid(std::process::id()) {
log::error!("{:?}", e); log::error!("{:?}", e);
} }
if let Err(e) = command_server.start(switch) {
log::error!("{:?}", e);
}
}
Err(e) => {
log::error!("{:?}", e);
}
};
}); });
Ok(switch) Ok(())
} }
pub fn start() { pub fn start() {
+3 -3
View File
@@ -1,13 +1,12 @@
[package] [package]
name = "switch" name = "switch"
version = "1.0.2" version = "1.0.6"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
packet = { path = "./packet" } packet = { path = "./packet" }
p2p_channel = { path = "./p2p_channel" }
bytes = "1.3.0" bytes = "1.3.0"
log = "0.4.17" log = "0.4.17"
libc = "0.2.137" libc = "0.2.137"
@@ -20,11 +19,12 @@ parking_lot = "0.12.1"
rsa = "0.7.2" rsa = "0.7.2"
rand = "0.8.5" rand = "0.8.5"
sha2 = { version = "0.10.6", features = ["oid"] } sha2 = { version = "0.10.6", features = ["oid"] }
aes-gcm = "0.10.2"
thiserror = "1.0.37" thiserror = "1.0.37"
chrono = "0.4.23" chrono = "0.4.23"
#lazy_static = "1.4.0" #lazy_static = "1.4.0"
#moka = "0.9.6" moka = "0.9.6"
protobuf = "3.2.0" protobuf = "3.2.0"
#local-ip-address = "0.4.9" #local-ip-address = "0.4.9"
socket2 ={ version = "0.5.2", features = ["all"] } socket2 ={ version = "0.5.2", features = ["all"] }
-1
View File
@@ -7,4 +7,3 @@ edition = "2021"
[dependencies] [dependencies]
byteorder = "1.4.3" byteorder = "1.4.3"
thiserror = "1.0.37"
+3 -4
View File
@@ -1,4 +1,4 @@
use std::fmt; use std::{fmt, io};
/// 地址解析协议,由IP地址找到MAC地址 /// 地址解析协议,由IP地址找到MAC地址
/// https://www.ietf.org/rfc/rfc6747.txt /// https://www.ietf.org/rfc/rfc6747.txt
@@ -9,7 +9,6 @@ use std::fmt;
| 源MAC地址 | 源ip地址 | | 源MAC地址 | 源ip地址 |
| 目的MAC地址 | 目的ip地址 | | 目的MAC地址 | 目的ip地址 |
*/ */
use crate::error::*;
pub struct ArpPacket<B> { pub struct ArpPacket<B> {
buffer: B, buffer: B,
@@ -19,9 +18,9 @@ impl<B: AsRef<[u8]>> ArpPacket<B> {
pub fn unchecked(buffer: B) -> Self { pub fn unchecked(buffer: B) -> Self {
Self { buffer } Self { buffer }
} }
pub fn new(buffer: B) -> Result<Self> { pub fn new(buffer: B) -> io::Result<Self> {
if buffer.as_ref().len() != 28 { if buffer.as_ref().len() != 28 {
Err(Error::InvalidPacket)? Err(io::Error::from(io::ErrorKind::InvalidData))?;
} }
let packet = Self::unchecked(buffer); let packet = Self::unchecked(buffer);
Ok(packet) Ok(packet)
-25
View File
@@ -1,25 +0,0 @@
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("the buffer is too small")]
SmallBuffer,
#[error("the packet is invalid")]
InvalidPacket,
#[error("Unimplemented")]
Unimplemented,
// #[error("the vaue is invalid for the field")]
// InvalidValue,
//
// #[error("the value has already been defined")]
// AlreadyDefined,
//
// #[error(transparent)]
// Io(#[from] io::Error),
//
// #[error(transparent)]
// Nul(#[from] ffi::NulError),
}
pub type Result<T> = ::std::result::Result<T, Error>;
+3 -4
View File
@@ -1,5 +1,4 @@
use std::fmt; use std::{fmt, io};
use crate::error::*;
use crate::ethernet::protocol::Protocol; use crate::ethernet::protocol::Protocol;
/// 以太网帧协议 /// 以太网帧协议
@@ -18,11 +17,11 @@ impl<B: AsRef<[u8]>> EthernetPacket<B> {
EthernetPacket { buffer } EthernetPacket { buffer }
} }
pub fn new(buffer: B) -> Result<EthernetPacket<B>> { pub fn new(buffer: B) -> io::Result<EthernetPacket<B>> {
let packet = EthernetPacket::unchecked(buffer); let packet = EthernetPacket::unchecked(buffer);
//头部固定14位 //头部固定14位
if packet.buffer.as_ref().len() < 14 { if packet.buffer.as_ref().len() < 14 {
Err(Error::SmallBuffer)? Err(io::Error::from(io::ErrorKind::InvalidData))?;
} }
Ok(packet) Ok(packet)
+15 -22
View File
@@ -1,9 +1,9 @@
use std::fmt; use std::{fmt, io};
use byteorder::{BigEndian, ReadBytesExt}; use byteorder::{BigEndian, ReadBytesExt};
use crate::cal_checksum; use crate::cal_checksum;
use crate::error::*; use crate::icmp::{Code, Kind};
use crate::ip::ipv4::packet::IpV4Packet;
/// icmp 协议 /// icmp 协议
/* https://www.rfc-editor.org/rfc/rfc792 /* https://www.rfc-editor.org/rfc/rfc792
0 1 2 3 0 1 2 3
@@ -17,8 +17,6 @@ use crate::error::*;
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/ */
use crate::icmp::{Code, Kind};
use crate::ip::ipv4::packet::IpV4Packet;
pub struct IcmpPacket<B> { pub struct IcmpPacket<B> {
pub buffer: B, pub buffer: B,
@@ -28,9 +26,9 @@ impl<B: AsRef<[u8]>> IcmpPacket<B> {
pub fn unchecked(buffer: B) -> Self { pub fn unchecked(buffer: B) -> Self {
Self { buffer } Self { buffer }
} }
pub fn new(buffer: B) -> Result<Self> { pub fn new(buffer: B) -> io::Result<Self> {
if buffer.as_ref().len() < 8 { if buffer.as_ref().len() < 8 {
Err(Error::SmallBuffer)? Err(io::Error::from(io::ErrorKind::InvalidData))?;
} }
let packet = Self::unchecked(buffer); let packet = Self::unchecked(buffer);
Ok(packet) Ok(packet)
@@ -56,9 +54,7 @@ impl<B: AsRef<[u8]>> IcmpPacket<B> {
Code::from(self.kind(), self.buffer.as_ref()[1]) Code::from(self.kind(), self.buffer.as_ref()[1])
} }
pub fn checksum(&self) -> u16 { pub fn checksum(&self) -> u16 {
(&self.buffer.as_ref()[2..]) u16::from_be_bytes(self.buffer.as_ref()[2..4].try_into().unwrap())
.read_u16::<BigEndian>()
.unwrap()
} }
pub fn is_valid(&self) -> bool { pub fn is_valid(&self) -> bool {
self.checksum() == 0 || cal_checksum(self.buffer.as_ref()) == 0 self.checksum() == 0 || cal_checksum(self.buffer.as_ref()) == 0
@@ -71,12 +67,8 @@ impl<B: AsRef<[u8]>> IcmpPacket<B> {
| Kind::TimestampReply | Kind::TimestampReply
| Kind::InformationRequest | Kind::InformationRequest
| Kind::InformationReply => { | Kind::InformationReply => {
let ide = (&self.buffer.as_ref()[4..]) let ide =u16::from_be_bytes(self.buffer.as_ref()[4..6].try_into().unwrap());
.read_u16::<BigEndian>() let seq = u16::from_be_bytes(self.buffer.as_ref()[6..8].try_into().unwrap());
.unwrap();
let seq = (&self.buffer.as_ref()[6..])
.read_u16::<BigEndian>()
.unwrap();
HeaderOther::Identifier(ide, seq) HeaderOther::Identifier(ide, seq)
} }
Kind::DestinationUnreachable | Kind::TimeExceeded | Kind::SourceQuench => { Kind::DestinationUnreachable | Kind::TimeExceeded | Kind::SourceQuench => {
@@ -110,6 +102,7 @@ impl<B: AsRef<[u8]>> IcmpPacket<B> {
}, },
Kind::TimestampRequest | Kind::TimestampReply => { Kind::TimestampRequest | Kind::TimestampReply => {
let mut buffer = Cursor::new(self.payload()); let mut buffer = Cursor::new(self.payload());
Description::Timestamp( Description::Timestamp(
buffer.read_u32::<BigEndian>().unwrap(), buffer.read_u32::<BigEndian>().unwrap(),
buffer.read_u32::<BigEndian>().unwrap(), buffer.read_u32::<BigEndian>().unwrap(),
@@ -128,11 +121,11 @@ impl<B: AsRef<[u8]>> fmt::Debug for IcmpPacket<B> {
} else { } else {
"icmp::Packet!" "icmp::Packet!"
}) })
.field("kind", &self.kind()) .field("kind", &self.kind())
.field("code", &self.code()) .field("code", &self.code())
.field("checksum", &self.checksum()) .field("checksum", &self.checksum())
.field("payload", &self.payload()) .field("payload", &self.payload())
.finish() .finish()
} }
} }
+117
View File
@@ -0,0 +1,117 @@
use std::{fmt, io};
use std::net::Ipv4Addr;
use crate::cal_checksum;
/// igmp v1
/* https://datatracker.ietf.org/doc/html/rfc1112
0 1 2 3
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| Type | Unused | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Group Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/// v1版本的报文
pub struct IgmpV1Packet<B> {
pub buffer: B,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum IgmpV1Type {
/// 0x11 所有组224.0.0.1或者特定组
Query,
/// 0x12
ReportV1,
Unknown(u8),
}
impl From<u8> for IgmpV1Type {
fn from(value: u8) -> IgmpV1Type {
use self::IgmpV1Type::*;
match value {
0x11 => Query,
0x12 => ReportV1,
v => Unknown(v),
}
}
}
impl Into<u8> for IgmpV1Type {
fn into(self) -> u8 {
match self {
IgmpV1Type::Query => 0x11,
IgmpV1Type::ReportV1 => 0x12,
IgmpV1Type::Unknown(v) => v
}
}
}
impl<B: AsRef<[u8]>> IgmpV1Packet<B> {
pub fn unchecked(buffer: B) -> Self {
Self { buffer }
}
pub fn new(buffer: B) -> io::Result<Self> {
if buffer.as_ref().len() != 8 {
Err(io::Error::from(io::ErrorKind::InvalidData))
} else {
let packet = Self::unchecked(buffer);
Ok(packet)
}
}
}
impl<B: AsRef<[u8]>> IgmpV1Packet<B> {
pub fn version(&self) -> u8 {
self.buffer.as_ref()[0] >> 4
}
pub fn igmp_type(&self) -> IgmpV1Type {
IgmpV1Type::from(self.buffer.as_ref()[0] & 0x0F)
}
pub fn unused(&self) -> u8 {
self.buffer.as_ref()[1]
}
pub fn checksum(&self) -> u16 {
u16::from_be_bytes(self.buffer.as_ref()[2..4].try_into().unwrap())
}
pub fn is_valid(&self) -> bool {
self.checksum() == 0 || cal_checksum(self.buffer.as_ref()) == 0
}
pub fn group_address(&self) -> Ipv4Addr {
let tmp: [u8; 4] = self.buffer.as_ref()[4..8].try_into().unwrap();
Ipv4Addr::from(tmp)
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> IgmpV1Packet<B> {
pub fn set_version(&mut self, version: u8) {
self.buffer.as_mut()[0] = (version << 4) | 0x0F & self.buffer.as_mut()[0]
}
pub fn set_type(&mut self, igmp_type: IgmpV1Type) {
let t: u8 = igmp_type.into();
self.buffer.as_mut()[0] = self.buffer.as_mut()[0] & 0xF0 | t
}
pub fn set_checksum(&mut self, checksum: u16) {
self.buffer.as_mut()[2..4].copy_from_slice(&checksum.to_be_bytes());
}
pub fn update_checksum(&mut self) {
self.set_checksum(0);
self.set_checksum(cal_checksum(self.buffer.as_ref()));
}
pub fn set_group_address(&mut self, group_address: Ipv4Addr) {
self.buffer.as_mut()[4..8].copy_from_slice(&group_address.octets());
}
}
impl<B: AsRef<[u8]>> fmt::Debug for IgmpV1Packet<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("igmp::V1")
.field("version", &self.version())
.field("type", &self.igmp_type())
.field("checksum", &self.checksum())
.field("is_valid", &self.is_valid())
.field("group_address", &self.group_address())
.finish()
}
}
+118
View File
@@ -0,0 +1,118 @@
use std::{fmt, io};
use std::net::Ipv4Addr;
use crate::cal_checksum;
/// igmp v2
/* https://www.rfc-editor.org/rfc/rfc2236.html
0 1 2 3
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Max Resp Time | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Group Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/// v2版本的报文
pub struct IgmpV2Packet<B> {
pub buffer: B,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum IgmpV2Type {
/// 0x11 所有组224.0.0.1或者特定组
Query,
/// 0x16
ReportV2,
LeaveV2,
Unknown(u8),
}
impl From<u8> for IgmpV2Type {
fn from(value: u8) -> IgmpV2Type {
use self::IgmpV2Type::*;
match value {
0x11 => Query,
0x16 => ReportV2,
0x17 => LeaveV2,
v => Unknown(v),
}
}
}
impl Into<u8> for IgmpV2Type {
fn into(self) -> u8 {
match self {
IgmpV2Type::Query => 0x11,
IgmpV2Type::ReportV2 => 0x16,
IgmpV2Type::LeaveV2 => 0x17,
IgmpV2Type::Unknown(v) => v
}
}
}
impl<B: AsRef<[u8]>> IgmpV2Packet<B> {
pub fn unchecked(buffer: B) -> Self {
Self { buffer }
}
pub fn new(buffer: B) -> io::Result<Self> {
if buffer.as_ref().len() != 8 {
Err(io::Error::from(io::ErrorKind::InvalidData))
} else {
let packet = Self::unchecked(buffer);
Ok(packet)
}
}
}
impl<B: AsRef<[u8]>> IgmpV2Packet<B> {
pub fn igmp_type(&self) -> IgmpV2Type {
IgmpV2Type::from(self.buffer.as_ref()[0])
}
pub fn max_resp_time(&self) -> u8 {
self.buffer.as_ref()[1]
}
pub fn checksum(&self) -> u16 {
u16::from_be_bytes(self.buffer.as_ref()[2..4].try_into().unwrap())
}
pub fn is_valid(&self) -> bool {
self.checksum() == 0 || cal_checksum(self.buffer.as_ref()) == 0
}
pub fn group_address(&self) -> Ipv4Addr {
let tmp: [u8; 4] = self.buffer.as_ref()[4..8].try_into().unwrap();
Ipv4Addr::from(tmp)
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> IgmpV2Packet<B> {
pub fn set_type(&mut self, igmp_type: IgmpV2Type) {
self.buffer.as_mut()[0] = igmp_type.into()
}
pub fn set_max_resp_time(&mut self, resp: u8) {
self.buffer.as_mut()[1] = resp
}
pub fn set_checksum(&mut self, checksum: u16) {
self.buffer.as_mut()[2..4].copy_from_slice(&checksum.to_be_bytes());
}
pub fn update_checksum(&mut self) {
self.set_checksum(0);
self.set_checksum(cal_checksum(self.buffer.as_ref()));
}
pub fn set_group_address(&mut self, group_address: Ipv4Addr) {
self.buffer.as_mut()[4..8].copy_from_slice(&group_address.octets());
}
}
impl<B: AsRef<[u8]>> fmt::Debug for IgmpV2Packet<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("igmp::V2")
.field("type", &self.igmp_type())
.field("max_resp_time", &self.max_resp_time())
.field("checksum", &self.checksum())
.field("is_valid", &self.is_valid())
.field("group_address", &self.group_address())
.finish()
}
}
+491
View File
@@ -0,0 +1,491 @@
use std::{fmt, io};
use std::net::Ipv4Addr;
use crate::cal_checksum;
/// igmp v3
/* https://www.rfc-editor.org/rfc/rfc3376
Query:
0 1 2 3
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type = 0x11 | Max Resp Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Group Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Resv |S| QRV | QQIC | Number of Sources (N) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address [1] |
+- -+
| Source Address [2] |
+- . -+
. . .
. . .
+- -+
| Source Address [N] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-----------------------------------------------------------------------------
Report:
0 1 2 3
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type = 0x22 | Reserved | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved | Number of Group Records (M) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
. .
. Group Record [1] .
. .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
. .
. Group Record [2] .
. .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| . |
. . .
| . |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
. .
. Group Record [M] .
. .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Group Record:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Record Type | Aux Data Len | Number of Sources (N) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Multicast Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address [1] |
+- -+
| Source Address [2] |
+- -+
. . .
. . .
. . .
+- -+
| Source Address [N] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
. .
. Auxiliary Data .
. .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Record Type:
1 MODE_IS_INCLUDE 表示主机希望加入指定组播组并指定了一个或多个源地址
2 MODE_IS_EXCLUDE 表示主机希望加入指定组播组但排除了一个或多个源地址
3 CHANGE_TO_INCLUDE_MODE 表示主机正在将组播组的过滤模式从排除切换为包括,指定了一个或多个源地址
4 CHANGE_TO_EXCLUDE_MODE 表示主机正在将组播组的过滤模式从包括切换为排除,指定了一个或多个源地址
5 ALLOW_NEW_SOURCES 表示主机希望在已有的源地址列表中添加新的源地址,指定了一个或多个源地址
6 BLOCK_OLD_SOURCES 表示主机希望在已有的源地址列表中删除旧的源地址,指定了一个或多个源地址
*/
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum IgmpV3Type {
/// 0x11 所有组224.0.0.1或者特定组
Query,
/// 0x22
ReportV3,
Unknown(u8),
}
impl From<u8> for IgmpV3Type {
fn from(value: u8) -> IgmpV3Type {
use self::IgmpV3Type::*;
match value {
0x11 => Query,
0x22 => ReportV3,
v => Unknown(v),
}
}
}
impl Into<u8> for IgmpV3Type {
fn into(self) -> u8 {
match self {
IgmpV3Type::Query => 0x11,
IgmpV3Type::ReportV3 => 0x22,
IgmpV3Type::Unknown(v) => v
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum IgmpV3RecordType {
//1 MODE_IS_INCLUDE 表示主机希望加入指定组播组并指定了一个或多个源地址
ModeIsInclude,
//2 MODE_IS_EXCLUDE 表示主机希望加入指定组播组但排除了一个或多个源地址
ModeIsExclude,
//3 CHANGE_TO_INCLUDE_MODE 表示主机正在将组播组的过滤模式从排除切换为包括,指定了一个或多个源地址
ChangeToIncludeMode,
//4 CHANGE_TO_EXCLUDE_MODE 表示主机正在将组播组的过滤模式从包括切换为排除,指定了一个或多个源地址
ChangeToExcludeMode,
//5 ALLOW_NEW_SOURCES 表示主机希望在已有的源地址列表中添加新的源地址,指定了一个或多个源地址
AllowNewSources,
//6 BLOCK_OLD_SOURCES 表示主机希望在已有的源地址列表中删除旧的源地址,指定了一个或多个源地址
BlockOldSources,
Unknown(u8),
}
impl From<u8> for IgmpV3RecordType {
fn from(value: u8) -> IgmpV3RecordType {
use self::IgmpV3RecordType::*;
match value {
1 => ModeIsInclude,
2 => ModeIsExclude,
3 => ChangeToIncludeMode,
4 => ChangeToExcludeMode,
5 => AllowNewSources,
6 => BlockOldSources,
v => Unknown(v),
}
}
}
impl Into<u8> for IgmpV3RecordType {
fn into(self) -> u8 {
use self::IgmpV3RecordType::*;
match self {
ModeIsInclude => 1,
ModeIsExclude => 2,
ChangeToIncludeMode => 3,
ChangeToExcludeMode => 4,
AllowNewSources => 5,
BlockOldSources => 6,
Unknown(v) => v,
}
}
}
/// v3版本的query报文
pub struct IgmpV3QueryPacket<B> {
pub buffer: B,
}
impl<B: AsRef<[u8]>> IgmpV3QueryPacket<B> {
pub fn unchecked(buffer: B) -> Self {
Self { buffer }
}
pub fn new(buffer: B) -> io::Result<Self> {
if buffer.as_ref().len() < 12 {
Err(io::Error::from(io::ErrorKind::InvalidData))
} else {
let packet = Self::unchecked(buffer);
Ok(packet)
}
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> IgmpV3QueryPacket<B> {
pub fn set_igmp_type(&mut self) {
self.buffer.as_mut()[0] = IgmpV3Type::Query.into();
}
pub fn set_max_resp_code(&mut self, code: u8) {
self.buffer.as_mut()[1] = code;
}
pub fn set_group_address(&mut self, addr: Ipv4Addr) {
self.buffer.as_mut()[4..8].copy_from_slice(&addr.octets())
}
pub fn set_checksum(&mut self, checksum: u16) {
self.buffer.as_mut()[2..4].copy_from_slice(&checksum.to_be_bytes())
}
pub fn set_qrv(&mut self, qrv: u8) {
self.buffer.as_mut()[8] = (self.buffer.as_ref()[8]&(!0x07)) | (qrv & 0x07)
}
pub fn set_qqic(&mut self, qqic: u8) {
self.buffer.as_mut()[9] = qqic
}
pub fn update_checksum(&mut self) {
self.set_checksum(0);
let checksum = cal_checksum(self.buffer.as_ref());
self.set_checksum(checksum);
}
}
impl<B: AsRef<[u8]>> IgmpV3QueryPacket<B> {
pub fn igmp_type(&self) -> IgmpV3Type {
IgmpV3Type::from(self.buffer.as_ref()[0])
}
pub fn max_resp_code(&self) -> u8 {
self.buffer.as_ref()[1]
}
pub fn checksum(&self) -> u16 {
u16::from_be_bytes(self.buffer.as_ref()[2..4].try_into().unwrap())
}
pub fn is_valid(&self) -> bool {
self.checksum() == 0 || cal_checksum(self.buffer.as_ref()) == 0
}
pub fn group_address(&self) -> Ipv4Addr {
let tmp: [u8; 4] = self.buffer.as_ref()[4..8].try_into().unwrap();
Ipv4Addr::from(tmp)
}
/// 保留字段,设置为0
pub fn resv(&self) -> u8 {
self.buffer.as_ref()[8] >> 4
}
/// 标志位
/// 该比特位为1时,所有收到此查询报文的其他路由器不启动定时器刷新过程,但是此查询报文并不抑制查询者选举过程和路由器的主机侧处理过程;默认未置位。
pub fn s(&self) -> u8 {
(self.buffer.as_ref()[8] & 0x0F) >> 3
}
/// 查询者向网络通告的健壮系数
/// 此参数可使查询者使用自己的健壮系统同步其他组播路由器的健壮系数;
/// 其他路由器接收到查询报文时,如果发现该字段非0,则将自己的健壮系数调整为该字段的值;如果发现该字段为0,则不做处理。默认健壮系数值为2。
pub fn qrv(&self) -> u8 {
self.buffer.as_ref()[8] & 0x07
}
/// IGMP查询者的查询间隔
/// 非查询者收到查询报文时,如果发现该字段非0,则将自己的查询间隔参数调整为该字段的值:如果发现该字段为0,则不做处理。默认值为60。
pub fn qqic(&self) -> u8 {
self.buffer.as_ref()[9]
}
/// 报文中包含的组播源的数量
/// 对于普遍组查询报文和特定组查询报文,该字段为0;对于特定源组查询报文,该字段非0
pub fn source_number(&self) -> u16 {
u16::from_be_bytes(self.buffer.as_ref()[10..12].try_into().unwrap())
}
pub fn source_addresses(&self) -> Option<Vec<Ipv4Addr>> {
let num = self.source_number();
if num == 0 {
None
} else {
let num = num as usize;
let mut list = Vec::with_capacity(num);
let buf = self.buffer.as_ref();
let len = buf.len();
for index in 0..num {
let start = (12 + index * 4) as usize;
let end = start + 4;
if end > len {
return None;
}
let tmp: [u8; 4] = buf[start..end].try_into().unwrap();
list.push(Ipv4Addr::from(tmp));
}
Some(list)
}
}
pub fn source_address(&self, index: u16) -> Option<Ipv4Addr> {
if self.source_number() >= index {
None
} else {
let start = (12 + index * 4) as usize;
let end = start + 4;
let buf = self.buffer.as_ref();
let len = buf.len();
if end > len {
return None;
}
let tmp: [u8; 4] = buf[start..end].try_into().unwrap();
Some(Ipv4Addr::from(tmp))
}
}
}
/// v3版本的query报文
pub struct IgmpV3ReportPacket<B> {
pub buffer: B,
}
impl<B: AsRef<[u8]>> IgmpV3ReportPacket<B> {
pub fn unchecked(buffer: B) -> Self {
Self { buffer }
}
pub fn new(buffer: B) -> io::Result<Self> {
if buffer.as_ref().len() < 8 {
Err(io::Error::from(io::ErrorKind::InvalidData))
} else {
let packet = Self::unchecked(buffer);
Ok(packet)
}
}
}
impl<B: AsRef<[u8]>> IgmpV3ReportPacket<B> {
pub fn igmp_type(&self) -> IgmpV3Type {
IgmpV3Type::from(self.buffer.as_ref()[0])
}
pub fn reserved1(&self) -> u8 {
self.buffer.as_ref()[1]
}
pub fn checksum(&self) -> u16 {
u16::from_be_bytes(self.buffer.as_ref()[2..4].try_into().unwrap())
}
pub fn is_valid(&self) -> bool {
self.checksum() == 0 || cal_checksum(self.buffer.as_ref()) == 0
}
pub fn reserved2(&self) -> u16 {
u16::from_be_bytes(self.buffer.as_ref()[4..6].try_into().unwrap())
}
pub fn record_number(&self) -> u16 {
u16::from_be_bytes(self.buffer.as_ref()[6..8].try_into().unwrap())
}
pub fn group_records(&self) -> Option<Vec<IgmpV3RecordPacket<&[u8]>>> {
let num = self.record_number();
if num == 0 {
None
} else {
let num = num as usize;
let mut list = Vec::with_capacity(num);
let mut start = 8 as usize;
let buf = self.buffer.as_ref();
let len = buf.len();
for _ in 0..num {
if start >= len {
return None;
}
if let Ok(record) = IgmpV3RecordPacket::new(&buf[start..]) {
let end = start + 8 + record.aux_data_len() as usize * 4 + record.source_number() as usize * 4;
if end > len {
return None;
}
list.push(IgmpV3RecordPacket::new(&buf[start..end]).unwrap());
start = end;
} else {
return None;
}
}
Some(list)
}
}
}
/// group record
pub struct IgmpV3RecordPacket<B> {
pub buffer: B,
}
impl<B: AsRef<[u8]>> IgmpV3RecordPacket<B> {
pub fn unchecked(buffer: B) -> Self {
Self { buffer }
}
pub fn new(buffer: B) -> io::Result<Self> {
if buffer.as_ref().len() < 8 {
Err(io::Error::from(io::ErrorKind::InvalidData))
} else {
let packet = Self::unchecked(buffer);
Ok(packet)
}
}
}
impl<B: AsRef<[u8]>> IgmpV3RecordPacket<B> {
pub fn record_type(&self) -> IgmpV3RecordType {
IgmpV3RecordType::from(self.buffer.as_ref()[0])
}
/// 辅助数据长度 以4字节为单位
pub fn aux_data_len(&self) -> u8 {
self.buffer.as_ref()[1]
}
/// 源地址数
pub fn source_number(&self) -> u16 {
u16::from_be_bytes(self.buffer.as_ref()[2..4].try_into().unwrap())
}
///多播地址
pub fn multicast_address(&self) -> Ipv4Addr {
let tmp: [u8; 4] = self.buffer.as_ref()[4..8].try_into().unwrap();
Ipv4Addr::from(tmp)
}
pub fn source_addresses(&self) -> Option<Vec<Ipv4Addr>> {
let num = self.source_number();
if num == 0 {
None
} else {
let num = num as usize;
let mut list = Vec::with_capacity(num);
let buf = self.buffer.as_ref();
let len = buf.len();
for index in 0..num {
let start = (8 + index * 4) as usize;
let end = start + 4;
if end > len {
return None;
}
let tmp: [u8; 4] = buf[start..end].try_into().unwrap();
list.push(Ipv4Addr::from(tmp));
}
Some(list)
}
}
pub fn source_address(&self, index: u16) -> Option<Ipv4Addr> {
if self.source_number() >= index {
None
} else {
let start = (8 + index * 4) as usize;
let end = start + 4;
if end > self.buffer.as_ref().len() {
return None;
}
let tmp: [u8; 4] = self.buffer.as_ref()[start..end].try_into().unwrap();
Some(Ipv4Addr::from(tmp))
}
}
/// 在文档中没有定义辅助数据的作用,通常应该是空的
pub fn auxiliary_data(&self) -> &[u8] {
let start = 8 + self.source_number() as usize * 4;
let end = start + self.aux_data_len() as usize * 4;
if end > self.buffer.as_ref().len() {
return &[];
}
&self.buffer.as_ref()[start..end]
}
}
impl<B: AsRef<[u8]>> fmt::Debug for IgmpV3QueryPacket<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("igmp::V3Query")
.field("type", &self.igmp_type())
.field("max_resp_code", &self.max_resp_code())
.field("checksum", &self.checksum())
.field("is_valid", &self.is_valid())
.field("group_address", &self.group_address())
.field("s", &self.s())
.field("qrv", &self.qrv())
.field("qqic", &self.qqic())
.field("number of sources", &self.source_number())
.field("source_addresses", &self.source_addresses())
.finish()
}
}
impl<B: AsRef<[u8]>> fmt::Debug for IgmpV3ReportPacket<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("igmp::V3Report")
.field("type", &self.igmp_type())
.field("reserved1", &self.reserved1())
.field("checksum", &self.checksum())
.field("is_valid", &self.is_valid())
.field("reserved2", &self.reserved2())
.field("record_number", &self.record_number())
.field("group_records", &self.group_records())
.finish()
}
}
impl<B: AsRef<[u8]>> fmt::Debug for IgmpV3RecordPacket<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("igmp::V3Record")
.field("record_type", &self.record_type())
.field("aux_data_len", &self.aux_data_len())
.field("source_number", &self.source_number())
.field("multicast_address", &self.multicast_address())
.field("source_addresses", &self.source_addresses())
.field("auxiliary_data", &self.auxiliary_data())
.finish()
}
}
+46
View File
@@ -0,0 +1,46 @@
pub mod igmp_v1;
pub mod igmp_v2;
pub mod igmp_v3;
#[derive(Debug,Copy, Clone,Eq, PartialEq)]
pub enum IgmpType {
/// 0x11 所有组224.0.0.1或者特定组
Query,
/// 0x12
ReportV1,
/// 0x16
ReportV2,
/// 0x22
ReportV3,
/// 0x17 目标组固定是 224.0.0.2
LeaveV2,
Unknown(u8),
}
impl From<u8> for IgmpType {
fn from(value: u8) -> IgmpType {
use self::IgmpType::*;
match value {
0x11 => Query,
0x12 => ReportV1,
0x16 => ReportV2,
0x22 => ReportV3,
0x17 => LeaveV2,
v => Unknown(v),
}
}
}
impl Into<u8> for IgmpType {
fn into(self) -> u8 {
match self {
IgmpType::Query => 0x11,
IgmpType::ReportV1 => 0x12,
IgmpType::ReportV2 => 0x16,
IgmpType::ReportV3 => 0x22,
IgmpType::LeaveV2 => 0x17,
IgmpType::Unknown(v) => v
}
}
}
+13 -20
View File
@@ -1,9 +1,8 @@
use std::fmt; use std::{fmt, io};
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use crate::cal_checksum; use crate::cal_checksum;
use crate::error::*;
use crate::ip::ipv4::protocol::Protocol; use crate::ip::ipv4::protocol::Protocol;
/// ip协议 /// ip协议
@@ -38,16 +37,16 @@ impl<B: AsRef<[u8]>> IpV4Packet<B> {
pub fn unchecked(buffer: B) -> Self { pub fn unchecked(buffer: B) -> Self {
Self { buffer } Self { buffer }
} }
pub fn new(buffer: B) -> Result<Self> { pub fn new(buffer: B) -> io::Result<Self> {
if buffer.as_ref()[0] >> 4 != 4 {
Err(Error::Unimplemented)?
}
if buffer.as_ref().len() < 20 { if buffer.as_ref().len() < 20 {
Err(Error::SmallBuffer)? Err(io::Error::new(io::ErrorKind::InvalidData, "len < 20"))?;
}
if buffer.as_ref()[0] >> 4 != 4 {
Err(io::Error::new(io::ErrorKind::InvalidData, "not ipv4"))?;
} }
let packet = Self::unchecked(buffer); let packet = Self::unchecked(buffer);
if packet.buffer.as_ref().len() < packet.header_len() as usize * 4 { if packet.buffer.as_ref().len() < packet.header_len() as usize * 4 {
Err(Error::SmallBuffer)? Err(io::Error::new(io::ErrorKind::InvalidData, "head_len err"))?;
} }
Ok(packet) Ok(packet)
} }
@@ -59,17 +58,6 @@ impl<B: AsRef<[u8]>> IpV4Packet<B> {
} }
pub fn payload(&self) -> &[u8] { pub fn payload(&self) -> &[u8] {
&self.buffer.as_ref()[(self.header_len() as usize * 4)..] &self.buffer.as_ref()[(self.header_len() as usize * 4)..]
// match self.protocol() {
// Protocol::Udp => {
// let udp = UdpPacket::new(IpAddr::V4(self.source_ip()),
// IpAddr::V4(self.destination_ip()),
// &self.buffer.as_ref()[(self.header_len() as usize * 4)..])?;
// Ok(crate::IpUpperLayer::UDP(udp))
// }
// _ => {
// Ok(crate::IpUpperLayer::Unknown(self.buffer.as_ref()));
// }
// }
} }
} }
@@ -82,13 +70,18 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> IpV4Packet<B> {
let len = self.header_len() as usize * 4; let len = self.header_len() as usize * 4;
&mut self.buffer.as_mut()[len..] &mut self.buffer.as_mut()[len..]
} }
pub fn set_protocol(&mut self, value: Protocol) {
self.header_mut()[9] = value.into();
}
pub fn set_source_ip(&mut self, value: Ipv4Addr) { pub fn set_source_ip(&mut self, value: Ipv4Addr) {
self.header_mut()[12..16].copy_from_slice(&value.octets()); self.header_mut()[12..16].copy_from_slice(&value.octets());
} }
pub fn set_destination_ip(&mut self, value: Ipv4Addr) { pub fn set_destination_ip(&mut self, value: Ipv4Addr) {
self.header_mut()[16..20].copy_from_slice(&value.octets()); self.header_mut()[16..20].copy_from_slice(&value.octets());
} }
pub fn set_flags(&mut self, flags: u8) {
self.buffer.as_mut()[6] = (self.buffer.as_ref()[6] & 0b11100000) | (flags << 5)
}
fn set_checksum(&mut self, value: u16) { fn set_checksum(&mut self, value: u16) {
self.header_mut()[10..12].copy_from_slice(&value.to_be_bytes()) self.header_mut()[10..12].copy_from_slice(&value.to_be_bytes())
} }
+3 -4
View File
@@ -1,7 +1,6 @@
use std::io;
use ipv4::packet::IpV4Packet; use ipv4::packet::IpV4Packet;
use crate::error::*;
pub mod ipv4; pub mod ipv4;
pub enum IpPacket<B> { pub enum IpPacket<B> {
@@ -9,10 +8,10 @@ pub enum IpPacket<B> {
} }
impl<B: AsRef<[u8]>> IpPacket<B> { impl<B: AsRef<[u8]>> IpPacket<B> {
pub fn new(buffer: B) -> Result<Self> { pub fn new(buffer: B) -> io::Result<Self> {
match buffer.as_ref()[0] >> 4 { match buffer.as_ref()[0] >> 4 {
4 => Ok(IpPacket::V4(IpV4Packet::new(buffer)?)), 4 => Ok(IpPacket::V4(IpV4Packet::new(buffer)?)),
_ => Err(Error::InvalidPacket), _ => Err(io::Error::from(io::ErrorKind::InvalidData)),
} }
} }
} }
+1 -1
View File
@@ -3,8 +3,8 @@ use std::net::Ipv4Addr;
use byteorder::BigEndian; use byteorder::BigEndian;
use byteorder::ReadBytesExt; use byteorder::ReadBytesExt;
pub mod error;
pub mod icmp; pub mod icmp;
pub mod igmp;
pub mod ip; pub mod ip;
pub mod tcp; pub mod tcp;
pub mod udp; pub mod udp;
+4 -5
View File
@@ -1,7 +1,6 @@
use std::fmt; use std::{fmt, io};
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use crate::error::*;
use crate::tcp::Flags; use crate::tcp::Flags;
/// tcp /// tcp
@@ -59,15 +58,15 @@ impl<B: AsRef<[u8]>> TcpPacket<B> {
buffer, buffer,
} }
} }
pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> Result<TcpPacket<B>> { pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> io::Result<TcpPacket<B>> {
let packet = TcpPacket::unchecked(source_ip, destination_ip, buffer); let packet = TcpPacket::unchecked(source_ip, destination_ip, buffer);
if packet.buffer.as_ref().len() < 20 { if packet.buffer.as_ref().len() < 20 {
Err(Error::SmallBuffer)? Err(io::Error::from(io::ErrorKind::InvalidData))?;
} }
if packet.buffer.as_ref().len() < packet.data_offset() as usize * 4 { if packet.buffer.as_ref().len() < packet.data_offset() as usize * 4 {
Err(Error::SmallBuffer)? Err(io::Error::from(io::ErrorKind::InvalidData))?;
} }
Ok(packet) Ok(packet)
+3 -5
View File
@@ -1,8 +1,6 @@
use std::fmt; use std::{fmt, io};
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use crate::error::*;
/// udp协议 /// udp协议
/// ///
/* /*
@@ -62,9 +60,9 @@ impl<B: AsRef<[u8]>> UdpPacket<B> {
buffer, buffer,
} }
} }
pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> Result<UdpPacket<B>> { pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> io::Result<UdpPacket<B>> {
if buffer.as_ref().len() < 8 { if buffer.as_ref().len() < 8 {
Err(Error::SmallBuffer)? Err(io::Error::from(io::ErrorKind::InvalidData))?;
} }
let packet = Self::unchecked(source_ip, destination_ip, buffer); let packet = Self::unchecked(source_ip, destination_ip, buffer);
Ok(packet) Ok(packet)
+1
View File
@@ -4,6 +4,7 @@ message RegistrationRequest{
string device_id = 2; string device_id = 2;
string name = 3; string name = 3;
bool is_fast = 4; bool is_fast = 4;
string version = 5;
} }
message RegistrationResponse{ message RegistrationResponse{
+398
View File
@@ -0,0 +1,398 @@
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
use std::sync::Arc;
use std::sync::atomic::{AtomicI64, AtomicUsize, Ordering};
use crossbeam_skiplist::SkipMap;
use dashmap::DashMap;
use tokio::net::UdpSocket;
use tokio::sync::Notify;
use tokio::sync::watch::{channel, Receiver, Sender};
use crate::channel::{Route, RouteKey, Status};
use crate::channel::punch::NatType;
use crate::handle::recv_handler::ChannelDataHandler;
#[derive(Clone)]
pub struct Context {
pub(crate) count: Arc<AtomicUsize>,
pub(crate) main_channel: Arc<UdpSocket>,
pub(crate) route_table: Arc<DashMap<Ipv4Addr, Vec<Route>>>,
pub(crate) route_table_time: Arc<SkipMap<(RouteKey, Ipv4Addr), AtomicI64>>,
pub(crate) status_receiver: Receiver<Status>,
pub(crate) status_sender: Arc<Sender<Status>>,
pub(crate) udp_map: Arc<SkipMap<usize, Arc<UdpSocket>>>,
pub(crate) channel_num: usize,
pub(crate) notify: Arc<Notify>,
}
impl Context {
pub fn new(main_channel: Arc<UdpSocket>, _channel_num: usize) -> Self {
//当前版本只支持一个通道
let channel_num = 1;
let (status_sender, status_receiver) = channel(Status::Cone);
let status_sender = Arc::new(status_sender);
Self {
count: Arc::new(AtomicUsize::new(0)),
main_channel,
route_table: Arc::new(DashMap::with_capacity(16)),
route_table_time: Arc::new(SkipMap::new()),
status_receiver,
status_sender,
udp_map: Arc::new(SkipMap::new()),
channel_num,
notify: Arc::new(Notify::new()),
}
}
}
impl Context {
pub fn is_close(&self) -> bool {
*self.status_receiver.borrow() == Status::Close
}
pub fn is_cone(&self) -> bool {
*self.status_receiver.borrow() == Status::Cone
}
pub fn close(&self) {
let _ = self.status_sender.send(Status::Close);
}
pub fn switch(&self, nat_type: NatType) {
match nat_type {
NatType::Symmetric => {
self.switch_to_symmetric();
}
NatType::Cone => {
self.switch_to_cone();
}
}
}
pub fn switch_to_cone(&self) {
let _ = self.status_sender.send(Status::Cone);
}
pub fn switch_to_symmetric(&self) {
let _ = self.status_sender.send(Status::Symmetric);
}
pub fn main_local_port(&self) -> io::Result<u16> {
self.main_channel.local_addr().map(|k| k.port())
}
pub async fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
self.main_channel.send_to(buf, addr).await
}
pub(crate) async fn send_all(&self, buf: &[u8], addr: SocketAddr) -> io::Result<()> {
for udp in self.udp_map.iter() {
udp.value().send_to(buf, addr).await?;
}
Ok(())
}
pub fn try_send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
self.main_channel.try_send_to(buf, addr)
}
pub async fn send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> {
if let Some(v) = self.route_table.get(id) {
let route = match v.len() {
0 => {
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
}
1 => &v[0],
len => &v[self.count.fetch_add(1, Ordering::Relaxed) % len]
};
if let Some(udp) = self.udp_map.get(&route.index) {
return udp.value().send_to(buf, route.addr).await;
}
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub fn try_send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result<usize> {
if let Some(v) = self.route_table.get(id) {
if v.is_empty() {
return Err(io::Error::new(io::ErrorKind::NotFound, "route not found"));
}
let route = &v[self.count.fetch_add(1, Ordering::Relaxed) % v.len()];
if let Some(udp) = self.udp_map.get(&route.index) {
return udp.value().try_send_to(buf, route.addr);
}
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub async fn send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
if let Some(udp) = self.udp_map.get(&route_key.index) {
return udp.value().send_to(buf, route_key.addr).await;
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub fn try_send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result<usize> {
if let Some(udp) = self.udp_map.get(&route_key.index) {
return udp.value().try_send_to(buf, route_key.addr);
}
Err(io::Error::new(io::ErrorKind::NotFound, "route not found"))
}
pub fn add_route_if_absent(&self, id: Ipv4Addr, route: Route) {
self.add_route_(id, route, true)
}
pub fn add_route(&self, id: Ipv4Addr, route: Route) {
self.add_route_(id, route, false)
}
fn add_route_(&self, id: Ipv4Addr, route: Route, only_if_absent: bool) {
let key = route.route_key();
let mut ref_mut = self.route_table.entry(id.clone()).or_insert(Vec::with_capacity(4));
let mut exist = false;
for x in ref_mut.iter_mut() {
if x.metric < route.metric {
//不能比当前的路径更长
return;
}
if x.route_key() == key {
if only_if_absent {
return;
}
x.metric = route.metric;
x.rt = route.rt;
exist = true;
break;
}
}
if !exist {
if route.metric == 1 {
//添加了直连的则排除非直连的
ref_mut.retain(|k| k.metric == 1);
}
ref_mut.push(route);
let max_len = self.channel_num;
if ref_mut.len() > max_len {
ref_mut.sort_by_key(|k| k.sort_key());
ref_mut.truncate(max_len);
}
}
self.route_table_time.insert((key, id), AtomicI64::new(chrono::Local::now().timestamp_millis()));
self.notify.notify_one();
}
pub fn route(&self, id: &Ipv4Addr) -> Option<Vec<Route>> {
if let Some(v) = self.route_table.get(id) {
Some(v.value().clone())
} else {
None
}
}
pub fn route_one(&self, id: &Ipv4Addr) -> Option<Route> {
if let Some(v) = self.route_table.get(id) {
v.value().iter().max_by_key(|k| k.sort_key()).map(|k| *k)
} else {
None
}
}
pub fn route_to_id(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
for x in self.route_table_time.iter() {
if &x.key().0 == route_key {
return Some(x.key().1);
}
}
None
}
pub fn need_punch(&self, id: &Ipv4Addr) -> bool {
if let Some(v) = self.route_table.get(id) {
if v.iter().filter(|k| k.is_p2p()).count() >= self.channel_num {
return false;
}
}
true
}
pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec<Route>)> {
self.route_table.iter().map(|k| (k.key().clone(), k.value().clone())).collect()
}
pub fn route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
let mut v = Vec::with_capacity(8);
for x in self.route_table.iter() {
if let Some(route) = x.value().iter().max_by_key(|k| k.sort_key()) {
v.push((*x.key(), *route));
}
}
v
}
pub fn direct_route_table_one(&self) -> Vec<(Ipv4Addr, Route)> {
let mut v = Vec::with_capacity(8);
for x in self.route_table.iter() {
if let Some(route) = x.value().iter().max_by_key(|k| k.sort_key()) {
if route.metric == 1 {
v.push((*x.key(), *route));
}
}
}
v
}
pub fn remove_route_all(&self, id: &Ipv4Addr) {
if let Some((_, v)) = self.route_table.remove(id) {
for x in v {
self.route_table_time.remove(&(x.route_key(), id.clone()));
}
}
}
pub fn remove_route(&self, id: &Ipv4Addr, route_key: RouteKey) {
if let Some(mut v) = self.route_table.get_mut(id) {
v.retain(|x| x.route_key() != route_key);
self.route_table_time.remove(&(route_key, id.clone()));
}
}
pub fn update_read_time(&self, id: &Ipv4Addr, route_key: &RouteKey) {
if let Some(time) = self.route_table_time.get(&(*route_key, *id)) {
time.value().store(chrono::Local::now().timestamp_millis(), Ordering::Relaxed);
}
}
}
pub struct Channel {
context: Context,
handler: ChannelDataHandler,
}
impl Channel {
pub fn new(context: Context,
handler: ChannelDataHandler, ) -> Self {
Self {
context,
handler,
}
}
}
impl Channel {
async fn handle(handler: &mut ChannelDataHandler,
udp: &Arc<UdpSocket>,
context: &Context,
id: usize,
result: io::Result<(usize, SocketAddr)>,
buf: &mut [u8], start: usize) {
match result {
Ok((len, addr)) => {
handler.handle(buf, start, start + len, RouteKey::new(id, addr), &udp, context).await;
}
Err(e) => {
log::error!("{:?}",e)
}
}
}
pub async fn start(self,
head_reserve: usize,//头部预留字节
symmetric_channel_num: usize,//对称网络,则再加一组监听,提升打洞成功率
) {
let mut context = self.context;
let main_channel = context.main_channel.clone();
let handler = self.handler.clone();
tokio::spawn(Self::start_(context.clone(), handler, main_channel, head_reserve, true));
let mut cur_status = Status::Cone;
loop {
match context.status_receiver.changed().await {
Ok(_) => {
match *context.status_receiver.borrow() {
Status::Cone => {
cur_status = Status::Cone;
}
Status::Symmetric => {
if cur_status == Status::Symmetric {
continue;
}
cur_status = Status::Symmetric;
for _ in 0..symmetric_channel_num {
match UdpSocket::bind("0.0.0.0:0").await {
Ok(udp) => {
let udp = Arc::new(udp);
let context = context.clone();
let handler = self.handler.clone();
tokio::spawn(Self::start_(context, handler, udp, head_reserve, false));
}
Err(e) => {
log::error!("{}",e);
}
}
}
}
Status::Close => {
break;
}
}
}
Err(_) => {
break;
}
}
}
}
async fn start_(context: Context,
mut handler: ChannelDataHandler,
udp: Arc<UdpSocket>,
head_reserve: usize,
is_core: bool) {
let mut status_receiver = context.status_receiver.clone();
#[cfg(target_os = "windows")]
use std::os::windows::io::AsRawSocket;
#[cfg(target_os = "windows")]
let id = udp.as_raw_socket() as usize;
#[cfg(any(unix))]
use std::os::fd::AsRawFd;
#[cfg(any(unix))]
let id = udp.as_raw_fd() as usize;
context.udp_map.insert(id, udp.clone());
let mut buf = [0; 65536];
loop {
tokio::select! {
rs=udp.recv_from(&mut buf[head_reserve..])=>{
Self::handle(&mut handler,&udp,&context,id,rs,&mut buf,head_reserve).await;
}
changed=status_receiver.changed()=>{
match changed {
Ok(_) => {
match *status_receiver.borrow() {
Status::Cone => {
if !is_core{
break;
}
}
Status::Close=>{
break;
}
Status::Symmetric => {}
}
}
Err(_) => {
break;
}
}
}
}
}
context.udp_map.remove(&id);
}
}
// pub async fn start<H: ChannelDataHandler + Clone>(mut handler: H,
// mut status_receiver: Receiver<Status>,
// head_reserve: usize,
// core_channel_num: usize,
// symmetric_channel_num: usize) -> io::Result<()> {
// for _ in 0..core_channel_num {
// let d = channel(1);
// }
// let udp = UdpSocket::bind("0.0.0.0:0").await?;
// let d = status_receiver.changed().await;
// match d {
// Ok(_) => {
// match *status_receiver.borrow() {
// Status::Cone => {}
// Status::Symmetric => {}
// Status::Close => {}
// }
// }
// Err(_) => {}
// }
// let mut buf = [0; 65546];
// let result = udp.recv_from(&mut buf[head_reserve..]).await;
// match result {
// Ok((len, addr)) => {}
// Err(e) => {}
// }
// Ok(())
// }
//
// pub struct Channel<H: ChannelDataHandler + Clone> {
// handler: H,
//
// }
+62
View File
@@ -0,0 +1,62 @@
use std::io;
use std::io::{Error, ErrorKind};
use std::net::Ipv4Addr;
use std::sync::atomic::Ordering;
use std::time::Duration;
use crate::channel::channel::Context;
use crate::channel::RouteKey;
pub struct Idle {
read_idle: i64,
context: Context,
}
impl Idle {
pub fn new(read_idle: i64,
context: Context, ) -> Self {
Self {
read_idle,
context,
}
}
}
impl Idle {
/// 获取空闲路由
pub async fn next_idle(&self) -> io::Result<(Ipv4Addr, RouteKey)> {
loop {
let now = chrono::Local::now().timestamp_millis();
let last_read_idle = now - self.read_idle;
let mut min = i64::MAX;
for entry in self.context.route_table_time.iter() {
let mut is_read_idle = false;
if self.read_idle > 0 {
let last_read = entry.value().load(Ordering::Relaxed);
if last_read < last_read_idle {
is_read_idle = true;
} else {
if min > last_read {
min = last_read;
}
}
}
if is_read_idle {
return Ok((entry.key().1.clone(), entry.key().0.clone()));
}
}
if self.context.route_table_time.is_empty() {
self.context.notify.notified().await;
} else {
let sleep_time = chrono::Local::now().timestamp_millis() - min;
if sleep_time > 0 {
tokio::time::sleep(Duration::from_millis(sleep_time as u64)).await;
// let _ = tokio::time::timeout(Duration::from_millis(sleep_time as u64), self.context.notify.notified()).await;
}
}
if self.context.is_close() {
return Err(Error::new(ErrorKind::Other, "closed"));
}
}
}
}
+78
View File
@@ -0,0 +1,78 @@
use std::net::SocketAddr;
pub mod channel;
pub mod punch;
pub mod idle;
pub mod sender;
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Status {
Cone,
Symmetric,
Close,
}
#[derive(Copy, Clone, Debug)]
pub struct Route {
index: usize,
pub addr: SocketAddr,
pub metric: u8,
pub rt: i64,
}
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
pub struct RouteSortKey {
pub metric: u8,
pub rt: i64,
}
impl Route {
pub fn new(index: usize,
addr: SocketAddr, metric: u8, rt: i64, ) -> Self {
Self {
index,
addr,
metric,
rt,
}
}
pub fn from(route_key: RouteKey, metric: u8, rt: i64) -> Self {
Self {
index: route_key.index,
addr: route_key.addr,
metric,
rt,
}
}
pub fn route_key(&self) -> RouteKey {
RouteKey {
index: self.index,
addr: self.addr,
}
}
pub fn sort_key(&self) -> RouteSortKey {
RouteSortKey {
metric: self.metric,
rt: self.rt,
}
}
pub fn is_p2p(&self) -> bool {
self.metric == 1
}
}
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
pub struct RouteKey {
index: usize,
pub addr: SocketAddr,
}
impl RouteKey {
pub(crate) fn new(index: usize,
addr: SocketAddr, ) -> Self {
Self {
index,
addr,
}
}
}
+152
View File
@@ -0,0 +1,152 @@
use std::collections::HashMap;
use std::io;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::time::Duration;
use rand::prelude::SliceRandom;
use crate::channel::channel::Context;
#[derive(Clone, Debug)]
pub struct NatInfo {
pub public_ips: Vec<Ipv4Addr>,
pub public_port: u16,
pub public_port_range: u16,
pub local_ip: Ipv4Addr,
pub local_port: u16,
pub nat_type: NatType,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum NatType {
Symmetric,
Cone,
}
impl NatInfo {
pub fn new(public_ips: Vec<Ipv4Addr>,
public_port: u16,
public_port_range: u16,
local_ip: Ipv4Addr,
local_port: u16,
nat_type: NatType, ) -> Self {
Self {
public_ips,
public_port,
public_port_range,
local_ip,
local_port,
nat_type,
}
}
}
#[derive(Clone)]
pub struct Punch {
context: Context,
port_vec: Vec<u16>,
port_index: HashMap<Ipv4Addr, usize>,
}
impl Punch {
pub fn new(context: Context) -> Self {
let mut port_vec: Vec<u16> = (1..65535).collect();
port_vec.push(65535);
let mut rng = rand::thread_rng();
port_vec.shuffle(&mut rng);
Punch {
context,
port_vec,
port_index: HashMap::new(),
}
}
}
impl Punch {
pub async fn punch(&mut self, buf: &[u8], id: Ipv4Addr, nat_info: NatInfo) -> io::Result<()> {
if !self.context.need_punch(&id) {
return Ok(());
}
if !nat_info.local_ip.is_unspecified() || nat_info.local_port != 0 {
let _ = self.context.send_main(buf, SocketAddr::V4(SocketAddrV4::new(nat_info.local_ip, nat_info.local_port))).await;
}
match nat_info.nat_type {
NatType::Symmetric => {
// 假设对方绑定n个端口,通过NAT对外映射出n个 公网ip:公网端口,自己随机尝试k次的情况下
// 猜中的概率 p = 1-((65535-n)/65535)*((65535-n-1)/(65535-1))*...*((65535-n-k+1)/(65535-k+1))
// n取76,k取600,猜中的概率就超过50%了
// 前提 自己是锥形网络,否则猜中了也通信不了
//预测范围内最多发送max_k1个包
let max_k1 = 60;
//全局最多发送max_k2个包
let max_k2 = 800;
if nat_info.public_port_range < max_k1 * 3 {
//端口变化不大时,在预测的范围内随机发送
let min_port = if nat_info.public_port > nat_info.public_port_range {
nat_info.public_port - nat_info.public_port_range
} else {
1
};
let (max_port, overflow) = nat_info.public_port.overflowing_add(nat_info.public_port_range);
let max_port = if overflow {
65535
} else {
max_port
};
let k = if max_port - min_port + 1 > max_k1 {
max_k1 as usize
} else {
(max_port - min_port + 1) as usize
};
let mut nums: Vec<u16> = (min_port..max_port).collect();
nums.push(max_port);
{
let mut rng = rand::thread_rng();
nums.shuffle(&mut rng);
}
self.punch_symmetric(&nums[..k], buf, &nat_info.public_ips, max_k1 as usize).await?;
}
let start = *self.port_index.entry(id.clone()).or_insert(0);
let mut end = start + max_k2;
let mut index = end;
if end >= self.port_vec.len() {
end = self.port_vec.len();
index = 0
}
self.punch_symmetric(&self.port_vec[start..end], buf, &nat_info.public_ips, max_k2).await?;
self.port_index.insert(id, index);
}
NatType::Cone => {
let is_cone = self.context.is_cone();
for ip in nat_info.public_ips {
let addr = SocketAddr::V4(SocketAddrV4::new(ip, nat_info.public_port));
if is_cone {
self.context.send_main(buf, addr).await?;
} else {
//只有一方是对称,则对称方要使用全部端口发送数据,符合上述计算的概率
self.context.send_all(buf, addr).await?;
}
tokio::time::sleep(Duration::from_millis(2)).await;
}
}
}
Ok(())
}
async fn punch_symmetric(&self, ports: &[u16], buf: &[u8], ips: &Vec<Ipv4Addr>, max: usize) -> io::Result<()> {
let mut count = 0;
for port in ports {
for pub_ip in ips {
count += 1;
if count == max {
return Ok(());
}
let addr = SocketAddr::V4(SocketAddrV4::new(*pub_ip, *port));
self.context.send_main(buf, addr).await?;
tokio::time::sleep(Duration::from_millis(2)).await;
}
}
Ok(())
}
}
+23
View File
@@ -0,0 +1,23 @@
use std::ops::Deref;
use crate::channel::channel::Context;
#[derive(Clone)]
pub struct ChannelSender {
context: Context,
}
impl ChannelSender {
pub fn new(context: Context) -> Self {
Self {
context,
}
}
}
impl Deref for ChannelSender {
type Target = Context;
fn deref(&self) -> &Self::Target {
&self.context
}
}
+88 -51
View File
@@ -1,28 +1,35 @@
use std::io; use std::{io, thread};
use std::net::{Ipv4Addr, SocketAddr}; use std::net::{Ipv4Addr, SocketAddr};
use std::sync::Arc; use std::sync::Arc;
use aes_gcm::{Aes256Gcm, Key, KeyInit};
use crossbeam::atomic::AtomicCell; use crossbeam::atomic::AtomicCell;
use crossbeam_skiplist::SkipMap; use crossbeam_skiplist::SkipMap;
use parking_lot::Mutex; use parking_lot::Mutex;
use tokio::net::UdpSocket;
use tokio::sync::mpsc::channel;
use p2p_channel::boot::Boot;
use p2p_channel::channel::{Channel, Route, RouteKey};
use p2p_channel::punch::NatInfo;
use crate::{tap_device, tun_device}; use crate::channel::channel::{Channel, Context};
use crate::channel::idle::Idle;
use crate::channel::punch::{NatInfo, Punch};
use crate::channel::{Route, RouteKey};
use crate::channel::sender::ChannelSender;
use crate::external_route::ExternalRoute; use crate::external_route::ExternalRoute;
use crate::handle::{ConnectStatus, CurrentDeviceInfo, CurrentDeviceInfoExt, heartbeat_handler, PeerDeviceInfo, punch_handler, recv_handler, registration_handler, tap_handler, tun_handler}; use crate::handle::{ConnectStatus, CurrentDeviceInfo, heartbeat_handler, PeerDeviceInfo, punch_handler, registration_handler};
use crate::handle::recv_handler::ChannelDataHandler;
use crate::handle::tun_tap::{tap_handler, tun_handler};
use crate::igmp_server::IgmpServer;
use crate::nat::NatTest; use crate::nat::NatTest;
use crate::tap_device::TapWriter; use crate::tun_tap_device;
use crate::tun_device::TunWriter; use crate::tun_tap_device::DeviceWriter;
pub struct Switch { pub struct Switch {
name: String, name: String,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
tun_writer: Option<TunWriter>, context: Context,
tap_writer: Option<TapWriter>, device_writer: DeviceWriter,
nat_channel: Channel<Ipv4Addr>,
/// 0. 机器纪元,每一次上线或者下线都会增1,用于感知网络中机器变化 /// 0. 机器纪元,每一次上线或者下线都会增1,用于感知网络中机器变化
/// 服务端和客户端的不一致,则服务端会推送新的设备列表 /// 服务端和客户端的不一致,则服务端会推送新的设备列表
/// 1. 网络中的虚拟ip列表 /// 1. 网络中的虚拟ip列表
@@ -35,10 +42,22 @@ pub struct Switch {
impl Switch { impl Switch {
pub async fn start(config: Config) -> crate::Result<Switch> { pub async fn start(config: Config) -> crate::Result<Switch> {
log::info!("config:{:?}",config); log::info!("config:{:?}",config);
let cipher = if let Some(key) = &config.key {
let key: &Key<Aes256Gcm> = key.into();
Some(Aes256Gcm::new(&key))
} else {
None
};
let main_channel = Arc::new(UdpSocket::bind("0.0.0.0:0").await?);
let response = registration_handler::registration(&main_channel, config.server_address, config.token.clone(), config.device_id.clone(), config.name.clone()).await?;
let (cone_sender, cone_receiver) = channel(3);
let (symmetric_sender, symmetric_receiver) = channel(2);
let context = Context::new(main_channel, 1);
let punch = Punch::new(context.clone());
let idle = Idle::new(16000, context.clone());
let channel_sender = ChannelSender::new(context.clone());
let (mut channel, punch, idle) = Boot::new::<Ipv4Addr>(80, 15000, 0)?; let register = Arc::new(registration_handler::Register::new(channel_sender.clone(), config.server_address, config.token.clone(), config.device_id.clone(), config.name.clone()));
let response = registration_handler::registration(&mut channel, config.server_address, config.token.clone(), config.device_id.clone(), config.name.clone())?;
let register = Arc::new(registration_handler::Register::new(channel.sender()?, config.server_address, config.token.clone(), config.device_id.clone(), config.name.clone()));
let device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>> = Arc::new(Mutex::new((0, Vec::new()))); let device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>> = Arc::new(Mutex::new((0, Vec::new())));
let peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>> = Arc::new(SkipMap::new()); let peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>> = Arc::new(SkipMap::new());
let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected)); let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected));
@@ -47,60 +66,71 @@ impl Switch {
let virtual_netmask = Ipv4Addr::from(response.virtual_netmask); let virtual_netmask = Ipv4Addr::from(response.virtual_netmask);
let local_ip = crate::nat::local_ip()?; let local_ip = crate::nat::local_ip()?;
let local_port = channel.local_addr()?.port(); let local_port = context.main_local_port()?;
// NAT检测 // NAT检测
let nat_test = NatTest::new(config.nat_test_server.clone(), Ipv4Addr::from(response.public_ip), response.public_port as u16, local_ip, local_port); let nat_test = NatTest::new(config.nat_test_server.clone(), Ipv4Addr::from(response.public_ip), response.public_port as u16, local_ip, local_port);
let in_ips = config.in_ips.iter().map(|(dest, mask, _)| { (Ipv4Addr::from(*dest), Ipv4Addr::from(*mask)) }).collect::<Vec<(Ipv4Addr, Ipv4Addr)>>(); let in_ips = config.in_ips.iter().map(|(dest, mask, _)| { (Ipv4Addr::from(*dest & *mask), Ipv4Addr::from(*mask)) }).collect::<Vec<(Ipv4Addr, Ipv4Addr)>>();
let out_ips = config.out_ips.iter().map(|(_, _, ip)| *ip).collect::<Vec<Ipv4Addr>>(); let out_ips = config.out_ips.iter().map(|(_, _, ip)| *ip).collect::<Vec<Ipv4Addr>>();
let out_external_route = ExternalRoute::new(config.out_ips); let out_external_route = ExternalRoute::new(config.out_ips);
let in_external_route = ExternalRoute::new(config.in_ips); let in_external_route = ExternalRoute::new(config.in_ips);
let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, config.server_address))); let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, config.server_address)));
let ip_proxy_map = crate::ip_proxy::init_proxy(channel.sender()?,out_ips,current_device.clone()).await?; let ip_proxy_map = crate::ip_proxy::init_proxy(channel_sender.clone(), out_ips, current_device.clone()).await?;
let ( current_device_ext,tun_writer, tap_writer) = if config.tap { let (device_writer, igmp_server) = if config.tap {
#[cfg(windows)] #[cfg(windows)]
{ {
//删除switch的tun网卡避免ip冲突,因为非正常退出会保留网卡 //删除switch的tun网卡避免ip冲突,因为非正常退出会保留网卡
tun_device::delete_tun(); tun_tap_device::delete_device(tun_tap_device::DeviceType::Tap);
} }
let (tap_writer, tap_reader, mac) = tap_device::create_tap(virtual_ip, virtual_netmask, virtual_gateway)?; let (tap_writer, tap_reader) = tun_tap_device::create_device(tun_tap_device::DeviceType::Tap, virtual_ip, virtual_netmask, virtual_gateway, in_ips)?;
let current_device_ext = Arc::new(AtomicCell::new(CurrentDeviceInfoExt::new( mac))); let igmp_server = IgmpServer::new(tap_writer.clone());
//tap数据处理 //tap数据处理
tap_handler::start(channel.sender()?, tap_reader.clone(), tap_writer.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone()); tap_handler::start(channel_sender.clone(), tap_reader.clone(), tap_writer.clone(),
(current_device_ext, None, Some(tap_writer)) igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone());
(tap_writer, igmp_server)
} else { } else {
#[cfg(windows)] #[cfg(windows)]
{ {
//删除switch的tap网卡避免ip冲突,非正常退出会保留网卡 //删除switch的tap网卡避免ip冲突,非正常退出会保留网卡
tap_device::delete_tap(); tun_tap_device::delete_device(tun_tap_device::DeviceType::Tap);
} }
// tun通道 // tun通道
let (tun_writer, tun_reader) = tun_device::create_tun(virtual_ip, virtual_netmask, virtual_gateway,in_ips)?; let (tun_writer, tun_reader) = tun_tap_device::create_device(tun_tap_device::DeviceType::Tun, virtual_ip, virtual_netmask, virtual_gateway, in_ips)?;
let current_device_ext = Arc::new(AtomicCell::new(CurrentDeviceInfoExt::new( [0, 0, 0, 0, 0, 0]))); let igmp_server = IgmpServer::new(tun_writer.clone());
//tun数据接收处理 //tun数据接收处理
tun_handler::start(channel.sender()?, tun_reader.clone(), tun_writer.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone()); tun_handler::start(channel_sender.clone(), tun_reader.clone(), tun_writer.clone(),
(current_device_ext,Some(tun_writer), None) igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone());
(tun_writer, igmp_server)
}; };
//外部数据接收处理 //外部数据接收处理
let channel_recv_handler = recv_handler::RecvHandler::new(channel.try_clone()?, current_device.clone(), current_device_ext,device_list.clone(), register.clone(), let channel_recv_handler = ChannelDataHandler::new(current_device.clone(), device_list.clone(),
nat_test.clone(), tun_writer.clone(), tap_writer.clone(), register.clone(), nat_test.clone(), igmp_server,
connect_status.clone(), peer_nat_info_map.clone(), ip_proxy_map, out_external_route); device_writer.clone(), connect_status.clone(),
recv_handler::start(channel_recv_handler); peer_nat_info_map.clone(), ip_proxy_map, out_external_route,
cone_sender, symmetric_sender, cipher);
let channel = Channel::new(context.clone(), channel_recv_handler);
thread::spawn(move || {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build().unwrap()
.block_on(channel.start(14, 60));
});
context.switch(nat_test.nat_info().nat_type);
// 定时心跳 // 定时心跳
heartbeat_handler::start_heartbeat(channel.sender()?, device_list.clone(), current_device.clone()); heartbeat_handler::start_heartbeat(channel_sender.clone(), device_list.clone(), current_device.clone()).await;
// 空闲检查 // 空闲检查
heartbeat_handler::start_idle(idle, channel.sender()?); heartbeat_handler::start_idle(idle, channel_sender.clone()).await;
// 打洞处理 // 打洞处理
punch_handler::start_cone(punch.try_clone()?, current_device.clone()); punch_handler::start(cone_receiver, punch.clone(), current_device.clone()).await;
punch_handler::start_symmetric(punch, current_device.clone()); punch_handler::start(symmetric_receiver, punch, current_device.clone()).await;
punch_handler::start_punch(nat_test.clone(), device_list.clone(), channel.sender()?, current_device.clone()); punch_handler::start_punch(nat_test.clone(), device_list.clone(), channel_sender.clone(), current_device.clone()).await;
log::info!("switch启动成功"); log::info!("switch启动成功");
Ok(Switch { Ok(Switch {
name: config.name, name: config.name,
current_device, current_device,
tun_writer, context,
tap_writer, device_writer,
nat_channel: channel,
nat_test, nat_test,
device_list, device_list,
connect_status, connect_status,
@@ -132,22 +162,17 @@ impl Switch {
device_list device_list
} }
pub fn route(&self, ip: &Ipv4Addr) -> Option<Route> { pub fn route(&self, ip: &Ipv4Addr) -> Option<Route> {
self.nat_channel.route(ip) self.context.route_one(ip)
} }
pub fn route_key(&self, route_key: &RouteKey) -> Option<Ipv4Addr> { pub fn route_key(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
self.nat_channel.route_to_id(route_key) self.context.route_to_id(route_key)
} }
pub fn route_table(&self) -> Vec<(Ipv4Addr, Route)> { pub fn route_table(&self) -> Vec<(Ipv4Addr, Route)> {
self.nat_channel.route_table() self.context.route_table_one()
} }
pub fn stop(&self) -> io::Result<()> { pub fn stop(&self) -> io::Result<()> {
if let Some(tap) = &self.tap_writer { self.context.close();
tap.close()?; self.device_writer.close()?;
}
if let Some(tun) = &self.tun_writer {
tun.close()?;
}
self.nat_channel.close()?;
Ok(()) Ok(())
} }
} }
@@ -162,15 +187,26 @@ pub struct Config {
pub nat_test_server: Vec<SocketAddr>, pub nat_test_server: Vec<SocketAddr>,
pub in_ips: Vec<(u32, u32, Ipv4Addr)>, pub in_ips: Vec<(u32, u32, Ipv4Addr)>,
pub out_ips: Vec<(u32, u32, Ipv4Addr)>, pub out_ips: Vec<(u32, u32, Ipv4Addr)>,
pub key: Option<[u8; 32]>,
} }
use sha2::Digest;
impl Config { impl Config {
pub fn new(tap: bool, token: String, pub fn new(tap: bool, token: String,
device_id: String, device_id: String,
name: String, name: String,
server_address: SocketAddr, server_address: SocketAddr,
nat_test_server: Vec<SocketAddr>, nat_test_server: Vec<SocketAddr>,
in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32, Ipv4Addr)>, ) -> Self { in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32, Ipv4Addr)>, password: Option<String>, ) -> Self {
let key = if let Some(password) = password {
let mut hasher = sha2::Sha256::new();
hasher.update(password.as_bytes());
let key: [u8; 32] = hasher.finalize().into();
Some(key)
} else {
None
};
Self { Self {
tap, tap,
token, token,
@@ -180,6 +216,7 @@ impl Config {
nat_test_server, nat_test_server,
in_ips, in_ips,
out_ips, out_ips,
key,
} }
} }
} }
-2
View File
@@ -5,8 +5,6 @@ use thiserror::Error;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum Error { pub enum Error {
#[error("packet error")]
PacketError(#[from] packet::error::Error),
#[error("Io error")] #[error("Io error")]
Io(#[from] io::Error), Io(#[from] io::Error),
#[error("Channel error")] #[error("Channel error")]
+1
View File
@@ -2,6 +2,7 @@ use std::net::Ipv4Addr;
// 目标ip,子网掩码,网关 // 目标ip,子网掩码,网关
#[derive(Clone)]
pub struct ExternalRoute { pub struct ExternalRoute {
route_table: Vec<(u32, u32, Ipv4Addr)>, route_table: Vec<(u32, u32, Ipv4Addr)>,
} }
+65 -66
View File
@@ -1,60 +1,54 @@
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use std::{io, thread}; use std::io;
use chrono::Local; use chrono::Local;
use crossbeam::atomic::AtomicCell; use crossbeam::atomic::AtomicCell;
use parking_lot::Mutex; use parking_lot::Mutex;
use rand::prelude::SliceRandom; use rand::prelude::SliceRandom;
use crate::channel::idle::Idle;
use crate::channel::Route;
use crate::channel::sender::ChannelSender;
use p2p_channel::channel::sender::Sender;
use p2p_channel::channel::Route;
use p2p_channel::idle::Idle;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo}; use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
use crate::protocol::control_packet::PingPacket; use crate::protocol::control_packet::PingPacket;
use crate::protocol::{control_packet, NetPacket, Protocol, Version, MAX_TTL}; use crate::protocol::{control_packet, NetPacket, Protocol, Version};
pub fn start_idle(idle: Idle<Ipv4Addr>, sender: Sender<Ipv4Addr>) { pub async fn start_idle(idle: Idle, sender: ChannelSender) {
thread::Builder::new() tokio::spawn(async move {
.name("idle".into()) match start_idle_(idle, sender).await {
.spawn(move || { Ok(_) => {}
if let Err(e) = start_idle_(idle, sender) { Err(e) => {
log::info!("空闲检测线程停止:{:?}", e); log::warn!("空闲检测任务停止:{:?}", e);
} }
}) }
.unwrap(); });
} }
fn start_idle_(idle: Idle<Ipv4Addr>, sender: Sender<Ipv4Addr>) -> io::Result<()> { async fn start_idle_(idle: Idle, sender: ChannelSender) -> io::Result<()> {
loop { loop {
let (idle_status, peer_ips, route) = idle.next_idle()?; let (peer_ip, route) = idle.next_idle().await?;
log::warn!( log::info!(
"peer_ip:{:?},route:{:?},idle_status:{:?}", "peer_ip:{:?},route:{:?}",
peer_ips, peer_ip,
route, route
idle_status
); );
for peer_ip in peer_ips { sender.remove_route(&peer_ip, route);
sender.remove_route(&peer_ip);
}
} }
} }
pub fn start_heartbeat( pub async fn start_heartbeat(
sender: Sender<Ipv4Addr>, sender: ChannelSender,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
) { ) {
thread::Builder::new() tokio::spawn(async move {
.name("heartbeat".into()) if let Err(e) = start_heartbeat_(sender, device_list, current_device).await {
.spawn(move || { log::warn!("心跳任务停止:{:?}", e);
if let Err(e) = start_heartbeat_(sender, device_list, current_device) { }
log::info!("空闲检测线程停止:{:?}", e); });
}
})
.unwrap();
} }
fn set_now_time(packet: &mut NetPacket<[u8; 16]>) -> io::Result<()> { fn set_now_time(packet: &mut NetPacket<[u8; 16]>) -> io::Result<()> {
@@ -64,8 +58,8 @@ fn set_now_time(packet: &mut NetPacket<[u8; 16]>) -> io::Result<()> {
Ok(()) Ok(())
} }
fn start_heartbeat_( async fn start_heartbeat_(
sender: Sender<Ipv4Addr>, sender: ChannelSender,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
) -> io::Result<()> { ) -> io::Result<()> {
@@ -73,7 +67,8 @@ fn start_heartbeat_(
net_packet.set_version(Version::V1); net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Control); net_packet.set_protocol(Protocol::Control);
net_packet.set_transport_protocol(control_packet::Protocol::Ping.into()); net_packet.set_transport_protocol(control_packet::Protocol::Ping.into());
net_packet.first_set_ttl(MAX_TTL); //只寻找两跳以内能到的目标
net_packet.first_set_ttl(2);
let mut count = 0; let mut count = 0;
loop { loop {
let current_device = current_device.load(); let current_device = current_device.load();
@@ -83,19 +78,28 @@ fn start_heartbeat_(
let epoch = { device_list.lock().0 }; let epoch = { device_list.lock().0 };
ping.set_epoch(epoch); ping.set_epoch(epoch);
} }
set_now_time(&mut net_packet)?;
net_packet.set_destination(current_device.virtual_gateway());
if let Err(e) = sender.send_main(net_packet.buffer(), current_device.connect_server).await
{
log::warn!(
"connect_server:{:?},e:{:?}",
current_device.connect_server,
e
);
}
if count < 7 || count % 7 == 0 { if count < 7 || count % 7 == 0 {
let mut route_list: Option<Vec<(Ipv4Addr, Route)>> = None; let mut route_list: Option<Vec<(Ipv4Addr, Vec<Route>)>> = None;
let peer_list = device_list.lock().1.clone(); let peer_list = {device_list.lock().1.clone()};
for peer in peer_list { for peer in peer_list {
set_now_time(&mut net_packet)?; set_now_time(&mut net_packet)?;
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_destination(peer.virtual_ip); net_packet.set_destination(peer.virtual_ip);
if sender if sender
.send_to_id(net_packet.buffer(), &peer.virtual_ip) .send_by_id(net_packet.buffer(), &peer.virtual_ip).await
.is_err() .is_err()
{ {
//没有路由则发送到网关 //没有路由则发送到网关
let _ = sender.send_to_addr(net_packet.buffer(), current_device.connect_server); let _ = sender.try_send_main(net_packet.buffer(), current_device.connect_server);
//再随机发送到其他地址,看有没有客户端符合转发条件 //再随机发送到其他地址,看有没有客户端符合转发条件
let route_list = route_list.get_or_insert_with(|| { let route_list = route_list.get_or_insert_with(|| {
let mut l = sender.route_table(); let mut l = sender.route_table();
@@ -103,42 +107,37 @@ fn start_heartbeat_(
l l
}); });
let mut num = 0; let mut num = 0;
net_packet.first_set_ttl(2); 'a: for (peer_ip, route_list) in route_list.iter() {
for (peer_ip, route) in route_list.iter() { for route in route_list {
if peer_ip != &peer.virtual_ip && route.metric == 1 { if peer_ip != &peer.virtual_ip && route.metric == 1 {
set_now_time(&mut net_packet)?; set_now_time(&mut net_packet)?;
let _ = sender.send_to_route(net_packet.buffer(), &route.route_key()); let _ = sender.try_send_by_key(net_packet.buffer(), &route.route_key());
num += 1; num += 1;
} break;
if num >= 3 { }
break; if num >= 3 {
break 'a;
}
} }
} }
} }
thread::sleep(Duration::from_millis(1)); tokio::time::sleep(Duration::from_millis(1)).await;
}
set_now_time(&mut net_packet)?;
net_packet.set_destination(current_device.virtual_gateway());
if let Err(e) = sender.send_to_addr(net_packet.buffer(), current_device.connect_server)
{
log::warn!(
"connect_server:{:?},e:{:?}",
current_device.connect_server,
e
);
} }
} else { } else {
for (peer_ip, route) in sender.route_table().iter() { for (peer_ip, route_list) in sender.route_table().iter() {
set_now_time(&mut net_packet)?; set_now_time(&mut net_packet)?;
net_packet.set_destination(*peer_ip); net_packet.set_destination(*peer_ip);
if let Err(e) = sender.send_to_route(net_packet.buffer(), &route.route_key()) { for route in route_list {
log::warn!("peer_ip:{:?},route:{:?},e:{:?}", peer_ip, route, e); if let Err(e) = sender.send_by_key(net_packet.buffer(), &route.route_key()).await {
log::warn!("peer_ip:{:?},route:{:?},e:{:?}", peer_ip, route, e);
}
tokio::time::sleep(Duration::from_millis(2)).await;
} }
thread::sleep(Duration::from_millis(1));
} }
} }
count += 1; count += 1;
thread::sleep(Duration::from_millis(5000)); tokio::time::sleep(Duration::from_millis(5000)).await;
} }
} }
+1 -15
View File
@@ -1,11 +1,10 @@
use std::net::{Ipv4Addr, SocketAddr}; use std::net::{Ipv4Addr, SocketAddr};
pub mod heartbeat_handler; pub mod heartbeat_handler;
pub mod tun_handler;
pub mod tap_handler;
pub mod punch_handler; pub mod punch_handler;
pub mod recv_handler; pub mod recv_handler;
pub mod registration_handler; pub mod registration_handler;
pub mod tun_tap;
/// 是否在一个网段 /// 是否在一个网段
fn check_dest(dest: Ipv4Addr, virtual_netmask: Ipv4Addr, virtual_network: Ipv4Addr) -> bool { fn check_dest(dest: Ipv4Addr, virtual_netmask: Ipv4Addr, virtual_network: Ipv4Addr) -> bool {
@@ -60,19 +59,6 @@ pub enum ConnectStatus {
Connected, Connected,
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct CurrentDeviceInfoExt {
pub mac: [u8; 6],
}
impl CurrentDeviceInfoExt {
pub fn new(mac: [u8; 6]) -> Self {
Self {
mac,
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct CurrentDeviceInfo { pub struct CurrentDeviceInfo {
virtual_ip: Ipv4Addr, virtual_ip: Ipv4Addr,
+46 -86
View File
@@ -1,93 +1,72 @@
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo}; use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
use crate::nat::NatTest; use crate::nat::NatTest;
use crate::proto::message::{PunchInfo, PunchNatType}; use crate::proto::message::{PunchInfo, PunchNatType};
use crate::protocol::{control_packet, turn_packet, NetPacket, Protocol, Version, MAX_TTL}; use crate::protocol::{control_packet, other_turn_packet, NetPacket, Protocol, Version, MAX_TTL};
use crossbeam::atomic::AtomicCell; use crossbeam::atomic::AtomicCell;
use p2p_channel::channel::sender::Sender;
use p2p_channel::punch::{NatInfo, NatType, Punch};
use parking_lot::Mutex; use parking_lot::Mutex;
use protobuf::Message; use protobuf::Message;
use rand::prelude::SliceRandom; use rand::prelude::SliceRandom;
use std::net::{IpAddr, Ipv4Addr}; use std::net::Ipv4Addr;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use std::{io, thread}; use std::io;
use tokio::sync::mpsc::Receiver;
use crate::channel::punch::{NatInfo, Punch};
use crate::channel::sender::ChannelSender;
pub fn start_cone(punch: Punch<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) { pub async fn start(receiver: Receiver<(Ipv4Addr, NatInfo)>, punch: Punch, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
thread::Builder::new() tokio::spawn(async move {
.name("punch-cone".into()) start0(receiver, punch, current_device).await;
.spawn(move || { });
if let Err(e) = start_(true, punch, current_device) {
log::warn!("锥形网络打洞处理线程停止 {:?}", e);
}
})
.unwrap();
} }
pub fn start_symmetric(punch: Punch<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) { pub async fn start0(mut receiver: Receiver<(Ipv4Addr, NatInfo)>, mut punch: Punch, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
thread::Builder::new() while let Some((peer_ip, nat_info)) = receiver.recv().await {
.name("punch-symmetric".into()) if let Err(e) = start_(&mut punch, &current_device, peer_ip, nat_info).await {
.spawn(move || { log::warn!("网络打洞异常 {:?}", e);
if let Err(e) = start_(false, punch, current_device) { }
log::warn!("对称网络打洞处理线程停止 {:?}", e); }
}
})
.unwrap();
} }
fn start_( async fn start_(
is_cone: bool, punch: &mut Punch,
mut punch: Punch<Ipv4Addr>, current_device: &Arc<AtomicCell<CurrentDeviceInfo>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, peer_ip: Ipv4Addr,
nat_info: NatInfo,
) -> io::Result<()> { ) -> io::Result<()> {
let mut packet = NetPacket::new([0u8; 12])?; let mut packet = NetPacket::new([0u8; 12])?;
packet.set_version(Version::V1); packet.set_version(Version::V1);
packet.first_set_ttl(1); packet.first_set_ttl(1);
packet.set_protocol(Protocol::Control); packet.set_protocol(Protocol::Control);
packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into()); packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
loop { packet.set_source(current_device.load().virtual_ip());
let (peer_ip, nat_info) = if is_cone { packet.set_destination(peer_ip);
punch.next_cone(None)? log::info!("发起打洞,目标:{:?},{:?}", peer_ip, nat_info);
} else {
punch.next_symmetric(None)? punch.punch(packet.buffer(), peer_ip, nat_info).await
};
if let Some(route) = punch.sender().route(&peer_ip) {
if route.metric == 1 {
//直连地址不需要打洞
continue;
}
}
packet.set_source(current_device.load().virtual_ip());
packet.set_destination(peer_ip);
log::info!("发起打洞,目标:{:?},{:?}", peer_ip, nat_info);
if let Err(e) = punch.punch(packet.buffer(), peer_ip, nat_info) {
log::warn!("peer_ip:{:?},e:{:?}", peer_ip, e);
}
}
} }
pub fn start_punch( pub async fn start_punch(
nat_test: NatTest, nat_test: NatTest,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
sender: Sender<Ipv4Addr>, sender: ChannelSender,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
) { ) {
thread::Builder::new() tokio::spawn(async move {
.name("punch-send-request".into()) if let Err(e) = start_punch_(nat_test, device_list, sender, current_device).await {
.spawn(move || { log::warn!("打洞处理任务停止 {:?}", e);
if let Err(e) = start_punch_(nat_test, device_list, sender, current_device) { }
log::warn!("对称网络打洞处理线程停止 {:?}", e); });
}
})
.unwrap();
} }
fn start_punch_( async fn start_punch_(
nat_test: NatTest, nat_test: NatTest,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
sender: Sender<Ipv4Addr>, sender: ChannelSender,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
) -> crate::Result<()> { ) -> crate::Result<()> {
let mut num = 0;
let sleep_time = [3, 5, 7, 11, 13, 17, 19, 23, 29];
loop { loop {
if sender.is_close() { if sender.is_close() {
return Ok(()); return Ok(());
@@ -102,28 +81,19 @@ fn start_punch_(
if info.virtual_ip <= current_device.virtual_ip { if info.virtual_ip <= current_device.virtual_ip {
continue; continue;
} }
if let Some(route) = sender.route(&info.virtual_ip) { if !sender.need_punch(&info.virtual_ip) {
if route.metric == 1 { continue;
//直连地址不需要打洞
continue;
}
} }
count += 1; count += 1;
if count > 3 { if count > 2 {
break; break;
} }
let buf = punch_packet(current_device.virtual_ip(), &nat_info, info.virtual_ip)?; let buf = punch_packet(current_device.virtual_ip(), &nat_info, info.virtual_ip)?;
sender.send_to_addr(&buf, current_device.connect_server)?; sender.send_main(&buf, current_device.connect_server).await?;
}
}
match nat_info.nat_type {
NatType::Symmetric => {
thread::sleep(Duration::from_secs(28));
}
NatType::Cone => {
thread::sleep(Duration::from_secs(20));
} }
} }
num += 1;
tokio::time::sleep(Duration::from_secs(sleep_time[num % sleep_time.len()])).await;
} }
} }
@@ -137,28 +107,18 @@ pub fn punch_packet(
punch_reply.public_ip_list = nat_info punch_reply.public_ip_list = nat_info
.public_ips .public_ips
.iter() .iter()
.map(|i| match i { .map(|ip| u32::from_be_bytes(ip.octets()))
IpAddr::V4(ip) => u32::from_be_bytes(ip.octets()),
IpAddr::V6(_) => {
panic!()
}
})
.collect(); .collect();
punch_reply.public_port = nat_info.public_port as u32; punch_reply.public_port = nat_info.public_port as u32;
punch_reply.public_port_range = nat_info.public_port_range as u32; punch_reply.public_port_range = nat_info.public_port_range as u32;
punch_reply.local_ip = match nat_info.local_ip { punch_reply.local_ip = u32::from_be_bytes(nat_info.local_ip.octets());
IpAddr::V4(ip) => u32::from_be_bytes(ip.octets()),
IpAddr::V6(_) => {
panic!()
}
};
punch_reply.local_port = nat_info.local_port as u32; punch_reply.local_port = nat_info.local_port as u32;
punch_reply.nat_type = protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type)); punch_reply.nat_type = protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type));
let bytes = punch_reply.write_to_bytes()?; let bytes = punch_reply.write_to_bytes()?;
let mut net_packet = NetPacket::new(vec![0u8; 12 + bytes.len()])?; let mut net_packet = NetPacket::new(vec![0u8; 12 + bytes.len()])?;
net_packet.set_version(Version::V1); net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::OtherTurn); net_packet.set_protocol(Protocol::OtherTurn);
net_packet.set_transport_protocol(turn_packet::Protocol::Punch.into()); net_packet.set_transport_protocol(other_turn_packet::Protocol::Punch.into());
net_packet.first_set_ttl(MAX_TTL); net_packet.first_set_ttl(MAX_TTL);
net_packet.set_source(virtual_ip); net_packet.set_source(virtual_ip);
net_packet.set_destination(dest); net_packet.set_destination(dest);
+251 -212
View File
@@ -1,134 +1,111 @@
use std::thread; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4};
use std::sync::Arc; use std::sync::Arc;
use aes_gcm::{AeadInPlace, Aes256Gcm, Nonce, Tag};
use aes_gcm::aead::consts::{U12, U16};
use aes_gcm::aead::generic_array::GenericArray;
use chrono::Local; use chrono::Local;
use crossbeam::atomic::AtomicCell; use crossbeam::atomic::AtomicCell;
use crossbeam_skiplist::SkipMap; use crossbeam_skiplist::SkipMap;
use parking_lot::Mutex; use parking_lot::Mutex;
use protobuf::Message; use protobuf::Message;
use tokio::net::UdpSocket;
use tokio::sync::mpsc::Sender;
use p2p_channel::channel::{Channel, Route, RouteKey};
use p2p_channel::punch::NatInfo;
use packet::ethernet;
use packet::icmp::{icmp, Kind}; use packet::icmp::{icmp, Kind};
use packet::icmp::icmp::HeaderOther; use packet::icmp::icmp::HeaderOther;
use packet::ip::ipv4; use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet; use packet::ip::ipv4::packet::IpV4Packet;
use crate::channel::channel::Context;
use crate::channel::punch::{NatInfo, NatType};
use crate::channel::{Route, RouteKey};
use crate::error::Error; use crate::error::Error;
use crate::external_route::ExternalRoute; use crate::external_route::ExternalRoute;
use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, CurrentDeviceInfoExt, PeerDeviceInfo}; use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo};
use crate::handle::registration_handler::Register; use crate::handle::registration_handler::Register;
use crate::igmp_server::IgmpServer;
use crate::ip_proxy::IpProxyMap; use crate::ip_proxy::IpProxyMap;
use crate::nat; use crate::nat;
use crate::nat::NatTest; use crate::nat::NatTest;
use crate::proto::message::{DeviceList, PunchInfo, PunchNatType, RegistrationResponse}; use crate::proto::message::{DeviceList, PunchInfo, PunchNatType, RegistrationResponse};
use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, service_packet, turn_packet, Version}; use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, service_packet, other_turn_packet, Version, ip_turn_packet};
use crate::protocol::control_packet::ControlPacket; use crate::protocol::control_packet::ControlPacket;
use crate::protocol::error_packet::InErrorPacket; use crate::protocol::error_packet::InErrorPacket;
use crate::tap_device::TapWriter; use crate::tun_tap_device::DeviceWriter;
use crate::tun_device::TunWriter;
pub fn start(mut handler: RecvHandler) { #[derive(Clone)]
thread::Builder::new().name("udp-recv-handler".into()).spawn(move || { pub struct ChannelDataHandler {
let mut buf = [0; 4096];
loop {
match handler.channel.recv_from(&mut buf, None) {
Ok((len, route)) => {
if let Err(e) = handler.handle(&mut buf[..len], &route) {
log::warn!("数据处理失败:{:?},e:{:?}",route,e);
if let Error::Stop(_) = e {
let _ = handler.channel.close();
break;
}
}
}
Err(e) => {
log::warn!("{:?}",e);
// 检查关闭状态
if handler.channel.is_close() {
break;
}
}
}
}
}).unwrap();
}
pub struct RecvHandler {
channel: Channel<Ipv4Addr>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
current_device_ext: Arc<AtomicCell<CurrentDeviceInfoExt>>,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
register: Arc<Register>, register: Arc<Register>,
nat_test: NatTest, nat_test: NatTest,
tun_writer: Option<TunWriter>, igmp_server: IgmpServer,
tap_writer: Option<TapWriter>, device_writer: DeviceWriter,
connect_status: Arc<AtomicCell<ConnectStatus>>, connect_status: Arc<AtomicCell<ConnectStatus>>,
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>, peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
ip_proxy_map: IpProxyMap, ip_proxy_map: IpProxyMap,
out_external_route: ExternalRoute, out_external_route: ExternalRoute,
cone_sender: Sender<(Ipv4Addr, NatInfo)>,
symmetric_sender: Sender<(Ipv4Addr, NatInfo)>,
cipher: Option<Aes256Gcm>,
} }
impl RecvHandler { impl ChannelDataHandler {
pub fn new(channel: Channel<Ipv4Addr>, pub fn new(current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
current_device_ext: Arc<AtomicCell<CurrentDeviceInfoExt>>,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
register: Arc<Register>, register: Arc<Register>,
nat_test: NatTest, nat_test: NatTest,
tun_writer: Option<TunWriter>, igmp_server: IgmpServer,
tap_writer: Option<TapWriter>, device_writer: DeviceWriter,
connect_status: Arc<AtomicCell<ConnectStatus>>, connect_status: Arc<AtomicCell<ConnectStatus>>,
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>, peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
ip_proxy_map: IpProxyMap, ip_proxy_map: IpProxyMap,
out_external_route: ExternalRoute, out_external_route: ExternalRoute,
) -> Self { cone_sender: Sender<(Ipv4Addr, NatInfo)>,
symmetric_sender: Sender<(Ipv4Addr, NatInfo)>,
cipher: Option<Aes256Gcm>, ) -> Self {
Self { Self {
channel,
current_device, current_device,
current_device_ext,
device_list, device_list,
register, register,
nat_test, nat_test,
tun_writer, igmp_server,
tap_writer, device_writer,
connect_status, connect_status,
peer_nat_info_map, peer_nat_info_map,
ip_proxy_map, ip_proxy_map,
out_external_route, out_external_route,
cone_sender,
symmetric_sender,
cipher,
} }
} }
// pub fn try_clone(&self) -> io::Result<Self> {
// Ok(Self {
// channel: self.channel.try_clone()?,
// current_device: self.current_device.clone(),
// device_list: self.device_list.clone(),
// register: self.register.clone(),
// nat_test: self.nat_test.clone(),
// tun_writer: self.tun_writer.clone(),
// tap_writer: self.tap_writer.clone(),
// connect_status: self.connect_status.clone(),
// peer_nat_info_map: self.peer_nat_info_map.clone(),
// })
// }
} }
impl RecvHandler {
fn handle(&self, buf: &mut [u8], route_key: &RouteKey) -> crate::Result<()> { impl ChannelDataHandler {
let mut net_packet = NetPacket::new(buf)?; pub async fn handle(&mut self, buf: &mut [u8], start: usize, end: usize, route_key: RouteKey, _udp: &Arc<UdpSocket>,
context: &Context, ) {
assert_eq!(start, 14);
match self.handle0(&mut buf[..end], &route_key, context).await {
Ok(_) => {}
Err(e) => {
log::error!("{:?}",e);
}
}
}
async fn handle0(&self, buf: &mut [u8], route_key: &RouteKey, context: &Context) -> crate::Result<()> {
let mut net_packet = NetPacket::new(&mut buf[14..])?;
if net_packet.ttl() == 0 { if net_packet.ttl() == 0 {
return Ok(()); return Ok(());
} }
let source = net_packet.source(); let source = net_packet.source();
let current_device = self.current_device.load(); let current_device = self.current_device.load();
if source == current_device.virtual_ip() {
return Ok(());
}
let destination = net_packet.destination(); let destination = net_packet.destination();
if !destination.is_broadcast() && destination != current_device.broadcast_address if current_device.virtual_ip() != destination
&& current_device.virtual_ip() != destination && self.connect_status.load() == ConnectStatus::Connected { && !destination.is_broadcast() && !destination.is_multicast() && destination != current_device.broadcast_address
&& self.connect_status.load() == ConnectStatus::Connected {
if !check_dest(source, current_device.virtual_netmask, current_device.virtual_network) { if !check_dest(source, current_device.virtual_netmask, current_device.virtual_network) {
log::warn!("转发数据,源地址错误:{:?},当前网络:{:?},route_key:{:?}",source,current_device.virtual_network,route_key); log::warn!("转发数据,源地址错误:{:?},当前网络:{:?},route_key:{:?}",source,current_device.virtual_network,route_key);
return Ok(()); return Ok(());
@@ -141,111 +118,185 @@ impl RecvHandler {
let ttl = net_packet.ttl(); let ttl = net_packet.ttl();
if ttl > 0 { if ttl > 0 {
// 转发 // 转发
if let Some(route) = self.channel.route(&destination) { if let Some(route) = context.route_one(&destination) {
if route.metric <= net_packet.ttl() { if route.metric <= net_packet.ttl() {
self.channel.send_to_route(net_packet.buffer(), &route.route_key())?; context.send_by_key(net_packet.buffer(), &route.route_key()).await?;
} }
} else if (ttl > 1 || destination == current_device.virtual_gateway()) } else if (ttl > 1 || destination == current_device.virtual_gateway())
&& source != current_device.virtual_gateway() { && source != current_device.virtual_gateway() {
//网关默认要转发一次,生存时间不够的发到网关也会被丢弃 //网关默认要转发一次,生存时间不够的发到网关也会被丢弃
self.channel.send_to_addr(net_packet.buffer(), current_device.connect_server)?; context.send_main(net_packet.buffer(), current_device.connect_server).await?;
} }
} }
return Ok(()); return Ok(());
} }
match net_packet.protocol() { match net_packet.protocol() {
Protocol::Ipv4Turn => { Protocol::IpTurn => {
let mut ipv4 = IpV4Packet::new(net_packet.payload_mut())?; match ip_turn_packet::Protocol::from(net_packet.transport_protocol()) {
if ipv4.destination_ip() == destination && ipv4.protocol() == ipv4::protocol::Protocol::Icmp { ip_turn_packet::Protocol::Icmp => {
let mut icmp_packet = icmp::IcmpPacket::new(ipv4.payload_mut())?; let ipv4 = IpV4Packet::new(net_packet.payload())?;
if icmp_packet.kind() == Kind::EchoRequest { if ipv4.protocol() == ipv4::protocol::Protocol::Icmp {
//开启ping self.device_writer.write_ipv4(&mut buf[12..])?;
icmp_packet.set_kind(Kind::EchoReply); return Ok(());
icmp_packet.update_checksum(); }
ipv4.set_source_ip(destination); }
ipv4.set_destination_ip(source); ip_turn_packet::Protocol::Igmp => {
ipv4.update_checksum(); let ipv4 = IpV4Packet::new(net_packet.payload())?;
net_packet.set_source(destination); if ipv4.protocol() == ipv4::protocol::Protocol::Igmp {
net_packet.set_destination(source); self.igmp_server.handle(ipv4.payload(), source)?;
self.channel.send_to_route(net_packet.buffer(), route_key)?; }
return Ok(()); return Ok(());
} }
} ip_turn_packet::Protocol::Ipv4 => {
if ipv4.destination_ip() != destination { let data = if let Some(cipher) = &self.cipher {
if let Some(gate_way) = self.out_external_route.route(&ipv4.destination_ip()) { if !net_packet.is_encrypt() {
match ipv4.protocol() { //未加密的数据之间丢弃
ipv4::protocol::Protocol::Tcp => { return Ok(());
let dest_ip = ipv4.destination_ip();
//转发到代理目标地址
let mut tcp_packet = packet::tcp::tcp::TcpPacket::new(source, destination, ipv4.payload_mut())?;
let source_port = tcp_packet.source_port();
let dest_port = tcp_packet.destination_port();
tcp_packet.set_destination_port(self.ip_proxy_map.tcp_proxy_port);
tcp_packet.update_checksum();
ipv4.set_destination_ip(destination);
ipv4.update_checksum();
self.ip_proxy_map.tcp_proxy_map.insert(SocketAddrV4::new(source, source_port),
(SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port)));
} }
ipv4::protocol::Protocol::Udp => { if net_packet.payload().len() < 16 {
let dest_ip = ipv4.destination_ip(); log::error!("数据异常,长度小于16");
//转发到代理目标地址 return Ok(());
let mut udp_packet = packet::udp::udp::UdpPacket::new(source, destination, ipv4.payload_mut())?; }
let source_port = udp_packet.source_port(); //需要解密
let dest_port = udp_packet.destination_port(); let mut nonce = [0; 12];
udp_packet.set_destination_port(self.ip_proxy_map.udp_proxy_port); nonce[0..4].copy_from_slice(&source.octets());
udp_packet.update_checksum(); nonce[4..8].copy_from_slice(&destination.octets());
ipv4.set_destination_ip(destination); nonce[8] = Protocol::IpTurn.into();
ipv4.update_checksum(); nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
println!("{:?}",ipv4); let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce);
self.ip_proxy_map.udp_proxy_map.insert(SocketAddrV4::new(source, source_port), let data_len = net_packet.payload().len() - 16;
(SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port))); let tag: GenericArray<u8, U16> = Tag::clone_from_slice(&net_packet.payload()[data_len..]);
match cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..data_len], &tag) {
Ok(_) => {}
Err(e) => {
log::error!("数据解密异常:{}",e);
return Ok(());
}
}
&mut net_packet.payload_mut()[..data_len]
} else {
net_packet.payload_mut()
};
let mut ipv4 = IpV4Packet::new(data)?;
match ipv4.protocol() {
ipv4::protocol::Protocol::Igmp => {
self.igmp_server.handle(ipv4.payload(), source)?;
return Ok(());
} }
ipv4::protocol::Protocol::Icmp => { ipv4::protocol::Protocol::Icmp => {
let dest_ip = ipv4.destination_ip(); if ipv4.destination_ip() == destination {
//转发到代理目标地址 let mut icmp_packet = icmp::IcmpPacket::new(ipv4.payload_mut())?;
let icmp_packet = icmp::IcmpPacket::new(ipv4.payload())?; if icmp_packet.kind() == Kind::EchoRequest {
match icmp_packet.header_other() { //开启ping
HeaderOther::Identifier(id, seq) => { icmp_packet.set_kind(Kind::EchoReply);
self.ip_proxy_map.icmp_proxy_map.insert((dest_ip, id, seq), source); icmp_packet.update_checksum();
self.ip_proxy_map.send_icmp(ipv4.payload(), &gate_way, &dest_ip)?; ipv4.set_source_ip(destination);
ipv4.set_destination_ip(source);
ipv4.update_checksum();
net_packet.set_source(destination);
net_packet.set_destination(source);
if let Some(cipher) = &self.cipher {
//需要加密
let mut nonce = [0; 12];
nonce[0..4].copy_from_slice(&destination.octets());
nonce[4..8].copy_from_slice(&source.octets());
nonce[8] = Protocol::IpTurn.into();
nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce);
let data_len = net_packet.payload().len() - 16;
match cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..data_len]) {
Ok(tag) => {
if tag.len() != 16 {
log::error!("加密tag长度错误:{}",tag.len());
return Ok(());
}
net_packet.set_encrypt_flag(true);
net_packet.payload_mut()[data_len..data_len + 16].copy_from_slice(tag.as_slice());
}
Err(e) => {
log::error!("加密失败:{}",e);
return Ok(());
}
}
}
context.send_by_key(net_packet.buffer(), route_key).await?;
return Ok(());
}
}
}
_ => {}
}
if ipv4.destination_ip() != destination {
if let Some(gate_way) = self.out_external_route.route(&ipv4.destination_ip()) {
match ipv4.protocol() {
ipv4::protocol::Protocol::Tcp => {
let dest_ip = ipv4.destination_ip();
//转发到代理目标地址
let mut tcp_packet = packet::tcp::tcp::TcpPacket::new(source, destination, ipv4.payload_mut())?;
let source_port = tcp_packet.source_port();
let dest_port = tcp_packet.destination_port();
tcp_packet.set_destination_port(self.ip_proxy_map.tcp_proxy_port);
tcp_packet.update_checksum();
ipv4.set_destination_ip(destination);
ipv4.update_checksum();
self.ip_proxy_map.tcp_proxy_map.insert(SocketAddrV4::new(source, source_port),
(SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port)));
}
ipv4::protocol::Protocol::Udp => {
let dest_ip = ipv4.destination_ip();
//转发到代理目标地址
let mut udp_packet = packet::udp::udp::UdpPacket::new(source, destination, ipv4.payload_mut())?;
let source_port = udp_packet.source_port();
let dest_port = udp_packet.destination_port();
udp_packet.set_destination_port(self.ip_proxy_map.udp_proxy_port);
udp_packet.update_checksum();
ipv4.set_destination_ip(destination);
ipv4.update_checksum();
self.ip_proxy_map.udp_proxy_map.insert(SocketAddrV4::new(source, source_port),
(SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port)));
}
ipv4::protocol::Protocol::Icmp => {
let dest_ip = ipv4.destination_ip();
//转发到代理目标地址
let icmp_packet = icmp::IcmpPacket::new(ipv4.payload())?;
match icmp_packet.header_other() {
HeaderOther::Identifier(id, seq) => {
self.ip_proxy_map.icmp_proxy_map.insert((dest_ip, id, seq), source);
self.ip_proxy_map.send_icmp(ipv4.payload(), &gate_way, &dest_ip)?;
}
_ => {
return Ok(());
}
}
} }
_ => { _ => {
return Ok(()); return Ok(());
} }
} }
} }
_ => {
return Ok(());
}
} }
//传输协议12字节
self.device_writer.write_ipv4(&mut buf[12..])?;
return Ok(());
} }
} ip_turn_packet::Protocol::Ipv4Broadcast => {
if let Some(tun_writer) = &self.tun_writer { //客户端不帮忙转发广播包,所以不会出现这种类型的数据
tun_writer.write(net_packet.payload())?;
} else {
if let Some(tap_writer) = &self.tap_writer {
let mut ethernet_packet = ethernet::packet::EthernetPacket::unchecked(vec![0; 14 + ipv4.buffer.len()]);
let source = source.octets();
ethernet_packet.set_source(&[source[0], source[1], source[2], source[3], 123, 234]);
ethernet_packet.set_destination(&self.current_device_ext.load().mac);
ethernet_packet.set_protocol(ethernet::protocol::Protocol::Ipv4);
ethernet_packet.payload_mut().copy_from_slice(ipv4.buffer);
tap_writer.write(&ethernet_packet.buffer)?;
} }
ip_turn_packet::Protocol::Unknown(_) => {}
} }
} }
Protocol::Service => { Protocol::Service => {
self.service(current_device, source, net_packet, route_key)?; self.service(context, current_device, source, net_packet, route_key).await?;
} }
Protocol::Error => { Protocol::Error => {
self.error(current_device, source, net_packet, route_key)?; self.error(context, current_device, source, net_packet, route_key).await?;
} }
Protocol::Control => { Protocol::Control => {
self.control(current_device, source, net_packet, route_key)?; self.control(context, current_device, source, net_packet, route_key).await?;
} }
Protocol::OtherTurn => { Protocol::OtherTurn => {
self.other_turn(current_device, source, net_packet, route_key)?; self.other_turn(context, current_device, source, net_packet, route_key).await?;
} }
Protocol::UnKnow(e) => { Protocol::UnKnow(e) => {
log::info!("不支持的协议:{}",e); log::info!("不支持的协议:{}",e);
@@ -253,18 +304,20 @@ impl RecvHandler {
} }
Ok(()) Ok(())
} }
fn service(&self, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> { async fn service(&self, context: &Context, current_device: CurrentDeviceInfo, _source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
if route_key.addr != current_device.connect_server || source != current_device.virtual_gateway() { //todo 校验来源
if route_key.addr != current_device.connect_server {
return Ok(()); return Ok(());
} }
match service_packet::Protocol::from(net_packet.transport_protocol()) { match service_packet::Protocol::from(net_packet.transport_protocol()) {
service_packet::Protocol::RegistrationRequest => {} service_packet::Protocol::RegistrationRequest => {}
service_packet::Protocol::RegistrationResponse => { service_packet::Protocol::RegistrationResponse => {
let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?; let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?;
let local_port = self.channel.local_addr()?.port(); let local_port = context.main_local_port()?;
let local_ip = nat::local_ip()?; let local_ip = nat::local_ip()?;
let nat_info = self.nat_test.re_test(Ipv4Addr::from(response.public_ip), response.public_port as u16, local_ip, local_port); let nat_info = self.nat_test.re_test(Ipv4Addr::from(response.public_ip),
self.channel.set_nat_type(nat_info.nat_type)?; response.public_port as u16, local_ip, local_port);
context.switch(nat_info.nat_type);
let new_ip = Ipv4Addr::from(response.virtual_ip); let new_ip = Ipv4Addr::from(response.virtual_ip);
let current_ip = current_device.virtual_ip(); let current_ip = current_device.virtual_ip();
if current_ip != new_ip { if current_ip != new_ip {
@@ -275,13 +328,7 @@ impl RecvHandler {
let virtual_ip = Ipv4Addr::from(response.virtual_ip); let virtual_ip = Ipv4Addr::from(response.virtual_ip);
let virtual_gateway = Ipv4Addr::from(response.virtual_gateway); let virtual_gateway = Ipv4Addr::from(response.virtual_gateway);
let virtual_netmask = Ipv4Addr::from(response.virtual_netmask); let virtual_netmask = Ipv4Addr::from(response.virtual_netmask);
if let Some(tun_writer) = &self.tun_writer { self.device_writer.change_ip(virtual_ip, virtual_netmask, virtual_gateway, old_netmask, old_gateway)?;
tun_writer.change_ip(virtual_ip, virtual_netmask, virtual_gateway, old_netmask, old_gateway)?;
} else {
if let Some(tap_writer) = &self.tap_writer {
tap_writer.change_ip(virtual_ip, virtual_netmask, virtual_gateway, old_netmask, old_gateway)?;
}
}
let new_current_device = CurrentDeviceInfo::new(virtual_ip, virtual_gateway, let new_current_device = CurrentDeviceInfo::new(virtual_ip, virtual_gateway,
virtual_netmask, current_device.connect_server); virtual_netmask, current_device.connect_server);
if let Err(e) = self.current_device.compare_exchange(current_device, new_current_device) { if let Err(e) = self.current_device.compare_exchange(current_device, new_current_device) {
@@ -310,14 +357,14 @@ impl RecvHandler {
dev.1 = ip_list; dev.1 = ip_list;
} }
} }
service_packet::Protocol::UnKnow(u) => { service_packet::Protocol::Unknown(u) => {
log::warn!("未知服务协议:{}",u); log::warn!("未知服务协议:{}",u);
} }
} }
Ok(()) Ok(())
} }
fn error(&self, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> { async fn error(&self, _context: &Context, current_device: CurrentDeviceInfo, _source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
if route_key.addr != current_device.connect_server || source != current_device.virtual_gateway() { if route_key.addr != current_device.connect_server {
return Ok(()); return Ok(());
} }
match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload())? { match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
@@ -325,8 +372,14 @@ impl RecvHandler {
return Err(Error::Stop("Token error".to_string())); return Err(Error::Stop("Token error".to_string()));
} }
InErrorPacket::Disconnect => { InErrorPacket::Disconnect => {
{
//掉线epoch要归零
let mut dev = self.device_list.lock();
dev.0 = 0;
}
self.connect_status.store(ConnectStatus::Connecting); self.connect_status.store(ConnectStatus::Connecting);
self.register.fast_register()?; self.register.fast_register().await?;
} }
InErrorPacket::AddressExhausted => { InErrorPacket::AddressExhausted => {
//地址用尽 //地址用尽
@@ -338,42 +391,28 @@ impl RecvHandler {
} }
Ok(()) Ok(())
} }
fn control(&self, current_device: CurrentDeviceInfo, source: Ipv4Addr, mut net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> { async fn control(&self, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, mut net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? { match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
ControlPacket::PingPacket(_) => { ControlPacket::PingPacket(_) => {
let metric = net_packet.source_ttl() - net_packet.ttl() + 1; context.update_read_time(&source, route_key);
net_packet.set_transport_protocol(control_packet::Protocol::Pong.into()); net_packet.set_transport_protocol(control_packet::Protocol::Pong.into());
net_packet.set_source(current_device.virtual_ip()); net_packet.set_source(current_device.virtual_ip());
net_packet.set_destination(source); net_packet.set_destination(source);
net_packet.first_set_ttl(MAX_TTL); net_packet.first_set_ttl(MAX_TTL);
self.channel.send_to_route(net_packet.buffer(), route_key)?; context.send_by_key(net_packet.buffer(), route_key).await?;
if metric == 1 { let route = Route::from(*route_key, metric, 99);
if let Some(current_route) = self.channel.route(&source) { context.add_route_if_absent(source, route);
if current_route.metric > 1 {
let route = Route::from(*route_key, 1, -1);
self.channel.add_route(source, route);
}
}
}
} }
ControlPacket::PongPacket(pong_packet) => { ControlPacket::PongPacket(pong_packet) => {
context.update_read_time(&source, route_key);
let current_time = Local::now().timestamp_millis() as u16; let current_time = Local::now().timestamp_millis() as u16;
if current_time < pong_packet.time() { if current_time < pong_packet.time() {
return Ok(()); return Ok(());
} }
let rt = (current_time - pong_packet.time()) as i64; let rt = (current_time - pong_packet.time()) as i64;
let metric = net_packet.source_ttl() - net_packet.ttl() + 1; let route = Route::from(*route_key, metric, rt);
if let Some(current_route) = self.channel.route(&source) { context.add_route(source, route);
if &current_route.route_key() == route_key {
self.channel.update_route(&source, metric, rt);
} else if current_route.metric >= metric && current_route.rt > rt {
let route = Route::from(*route_key, metric, rt);
self.channel.add_route(source, route);
}
} else {
let route = Route::from(*route_key, metric, rt);
self.channel.add_route(source, route);
}
if route_key.addr == current_device.connect_server && source == current_device.virtual_gateway() { if route_key.addr == current_device.connect_server && source == current_device.virtual_gateway() {
let epoch = self.device_list.lock().0; let epoch = self.device_list.lock().0;
if pong_packet.epoch() != epoch { if pong_packet.epoch() != epoch {
@@ -384,7 +423,7 @@ impl RecvHandler {
poll_device.first_set_ttl(MAX_TTL); poll_device.first_set_ttl(MAX_TTL);
poll_device.set_protocol(Protocol::Service); poll_device.set_protocol(Protocol::Service);
poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into()); poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into());
self.channel.send_to_route(poll_device.buffer(), route_key)?; context.send_by_key(poll_device.buffer(), route_key).await?;
} }
} }
} }
@@ -395,28 +434,28 @@ impl RecvHandler {
net_packet.set_source(current_device.virtual_ip()); net_packet.set_source(current_device.virtual_ip());
net_packet.set_destination(source); net_packet.set_destination(source);
net_packet.first_set_ttl(1); net_packet.first_set_ttl(1);
self.channel.send_to_route(net_packet.buffer(), route_key)?; context.send_by_key(net_packet.buffer(), route_key).await?;
let route = Route::from(*route_key, 1, -1); let route = Route::from(*route_key, metric, 99);
self.channel.add_route(source, route); context.add_route_if_absent(source, route);
} }
ControlPacket::PunchResponse => { ControlPacket::PunchResponse => {
// log::info!("PunchResponse route_key:{:?}",route_key); // log::info!("PunchResponse route_key:{:?}",route_key);
let route = Route::from(*route_key, 1, -1); let route = Route::from(*route_key, metric, 99);
self.channel.add_route(net_packet.source(), route); context.add_route_if_absent(source, route);
} }
} }
Ok(()) Ok(())
} }
fn other_turn(&self, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> { async fn other_turn(&self, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
match turn_packet::Protocol::from(net_packet.transport_protocol()) { match other_turn_packet::Protocol::from(net_packet.transport_protocol()) {
turn_packet::Protocol::Punch => { other_turn_packet::Protocol::Punch => {
let punch_info = PunchInfo::parse_from_bytes(net_packet.payload())?; let punch_info = PunchInfo::parse_from_bytes(net_packet.payload())?;
let public_ips = punch_info.public_ip_list. let public_ips = punch_info.public_ip_list.
iter().map(|v| { IpAddr::from(v.to_be_bytes()) }).collect(); iter().map(|v| { Ipv4Addr::from(v.to_be_bytes()) }).collect();
let peer_nat_info = NatInfo::new(public_ips, let peer_nat_info = NatInfo::new(public_ips,
punch_info.public_port as u16, punch_info.public_port as u16,
punch_info.public_port_range as u16, punch_info.public_port_range as u16,
IpAddr::from(punch_info.local_ip.to_be_bytes()), Ipv4Addr::from(punch_info.local_ip.to_be_bytes()),
punch_info.local_port as u16, punch_info.local_port as u16,
punch_info.nat_type.enum_value_or_default().into()); punch_info.nat_type.enum_value_or_default().into());
self.peer_nat_info_map.insert(source, peer_nat_info.clone()); self.peer_nat_info_map.insert(source, peer_nat_info.clone());
@@ -424,20 +463,12 @@ impl RecvHandler {
let mut punch_reply = PunchInfo::new(); let mut punch_reply = PunchInfo::new();
punch_reply.reply = true; punch_reply.reply = true;
let nat_info = self.nat_test.nat_info(); let nat_info = self.nat_test.nat_info();
punch_reply.public_ip_list = nat_info.public_ips.iter().map(|i| { punch_reply.public_ip_list = nat_info.public_ips.iter().map(|ip| u32::from_be_bytes(ip.octets())).collect();
match i {
IpAddr::V4(ip) => u32::from_be_bytes(ip.octets()),
IpAddr::V6(_) => 0
}
}).collect();
punch_reply.public_port = nat_info.public_port as u32; punch_reply.public_port = nat_info.public_port as u32;
punch_reply.public_port_range = nat_info.public_port_range as u32; punch_reply.public_port_range = nat_info.public_port_range as u32;
punch_reply.nat_type = punch_reply.nat_type =
protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type)); protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type));
punch_reply.local_ip = match nat_info.local_ip { punch_reply.local_ip = u32::from_be_bytes(nat_info.local_ip.octets());
IpAddr::V4(ip) => u32::from_be_bytes(ip.octets()),
IpAddr::V6(_) => 0
};
punch_reply.local_port = nat_info.local_port as u32; punch_reply.local_port = nat_info.local_port as u32;
let bytes = punch_reply.write_to_bytes()?; let bytes = punch_reply.write_to_bytes()?;
let mut net_packet = let mut net_packet =
@@ -445,7 +476,7 @@ impl RecvHandler {
net_packet.set_version(Version::V1); net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::OtherTurn); net_packet.set_protocol(Protocol::OtherTurn);
net_packet.set_transport_protocol( net_packet.set_transport_protocol(
turn_packet::Protocol::Punch.into(), other_turn_packet::Protocol::Punch.into(),
); );
net_packet.first_set_ttl(MAX_TTL); net_packet.first_set_ttl(MAX_TTL);
net_packet.set_source(current_device.virtual_ip()); net_packet.set_source(current_device.virtual_ip());
@@ -459,21 +490,29 @@ impl RecvHandler {
packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into()); packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
packet.set_source(current_device.virtual_ip()); packet.set_source(current_device.virtual_ip());
packet.set_destination(source); packet.set_destination(source);
let _ = self.channel.send_to_addr(packet.buffer(), SocketAddr::new(peer_nat_info.local_ip, peer_nat_info.local_port)); let _ = context.send_main(packet.buffer(), SocketAddr::V4(SocketAddrV4::new(peer_nat_info.local_ip, peer_nat_info.local_port))).await;
} }
if let Err(e) = self.channel.punch(source, peer_nat_info) { if self.punch(source, peer_nat_info).await {
log::warn!("发送到打洞通道失败 {:?}",e); context.send_by_key(net_packet.buffer(), route_key).await?;
return Ok(());
} }
self.channel.send_to_route(net_packet.buffer(), route_key)?;
} else { } else {
let _ = self.channel.punch(source, peer_nat_info); self.punch(source, peer_nat_info).await;
} }
} }
turn_packet::Protocol::UnKnow(e) => { other_turn_packet::Protocol::Unknown(e) => {
log::warn!("不支持的转发协议 {:?},source:{:?}",e,source); log::warn!("不支持的转发协议 {:?},source:{:?}",e,source);
} }
} }
Ok(()) Ok(())
} }
async fn punch(&self, peer_ip: Ipv4Addr, peer_nat_info: NatInfo) -> bool {
match peer_nat_info.nat_type {
NatType::Symmetric => {
self.symmetric_sender.try_send((peer_ip, peer_nat_info)).is_ok()
}
NatType::Cone => {
self.cone_sender.try_send((peer_ip, peer_nat_info)).is_ok()
}
}
}
} }
+77 -41
View File
@@ -1,12 +1,12 @@
use std::io; use std::io;
use std::net::{Ipv4Addr, SocketAddr}; use std::net::SocketAddr;
use std::sync::atomic::{AtomicI64, Ordering}; use std::sync::atomic::{AtomicI64, Ordering};
use std::time::Duration; use std::time::Duration;
use chrono::Local; use chrono::Local;
use p2p_channel::channel::sender::Sender;
use p2p_channel::channel::Channel;
use protobuf::Message; use protobuf::Message;
use tokio::net::UdpSocket;
use crate::channel::sender::ChannelSender;
use crate::error::*; use crate::error::*;
use crate::proto::message::{RegistrationRequest, RegistrationResponse}; use crate::proto::message::{RegistrationRequest, RegistrationResponse};
@@ -14,8 +14,8 @@ use crate::protocol::error_packet::InErrorPacket;
use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL}; use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL};
///向中继服务器注册,token标识一个虚拟网关,device_id防止多次注册时得到的ip不一致 ///向中继服务器注册,token标识一个虚拟网关,device_id防止多次注册时得到的ip不一致
pub fn registration( pub async fn registration(
channel: &mut Channel<Ipv4Addr>, main_channel: &UdpSocket,
server_address: SocketAddr, server_address: SocketAddr,
token: String, token: String,
device_id: String, device_id: String,
@@ -25,37 +25,72 @@ pub fn registration(
registration_request_packet(token.clone(), device_id.clone(), name.clone(), false)?; registration_request_packet(token.clone(), device_id.clone(), name.clone(), false)?;
let buf = request_packet.buffer(); let buf = request_packet.buffer();
let mut recv_buf = [0u8; 10240]; let mut recv_buf = [0u8; 10240];
channel.send_to_addr(buf, server_address)?; let mut count = 0;
let (len, route) = channel.recv_from(&mut recv_buf, Some(Duration::from_millis(300)))?; loop {
if server_address != route.addr { match main_channel.send_to(buf, server_address).await {
return Err(Error::Warn(format!("数据来源错误:{:?}", route.addr))); Ok(_) => {
} match tokio::time::timeout(Duration::from_millis(300), main_channel.recv_from(&mut recv_buf)).await {
let net_packet = NetPacket::new(&recv_buf[..len])?; Ok(rs) => {
return match net_packet.protocol() { match rs {
Protocol::Service => { Ok((len, addr)) => {
match service_packet::Protocol::from(net_packet.transport_protocol()) { if server_address == addr {
service_packet::Protocol::RegistrationResponse => { let net_packet = NetPacket::new(&recv_buf[..len])?;
let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?; match net_packet.protocol() {
Ok(response) Protocol::Service => {
match service_packet::Protocol::from(net_packet.transport_protocol()) {
service_packet::Protocol::RegistrationResponse => {
let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?;
return Ok(response);
}
_ => println!("响应数据错误"),
}
}
Protocol::Error => {
match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload()) {
Ok(e) => match e {
InErrorPacket::TokenError => return Err(Error::Stop("token错误".to_string())),
InErrorPacket::Disconnect => {
println!("断开连接");
}
InErrorPacket::AddressExhausted => {
println!("地址用尽");
log::warn!("地址用尽");
}
InErrorPacket::OtherError(e) => match e.message() {
Ok(str) => {
println!("其他异常:{:?}", str);
log::warn!("其他异常{:?}",str);
}
Err(e) => println!("其他异常:{:?}", e),
},
},
Err(e) => println!("数据解析异常:{:?}", e),
}
}
_ => println!("响应数据错误"),
};
}
}
Err(e) => {
println!("接收服务器数据失败:{:?}", e);
log::warn!("接收服务器数据失败:{:?}",e);
}
}
}
Err(_) => {
println!("接收超时");
log::warn!("接收超时");
}
} }
_ => Err(Error::Warn(format!("数据错误:{:?}", net_packet))), }
Err(e) => {
println!("发送数据到服务器失败:{:?}", e);
log::warn!("发送数据到服务器失败:{:?}",e);
} }
} }
Protocol::Error => { count += 1;
match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload()) { println!("重试中(retrying)...");
Ok(e) => match e { std::thread::sleep(Duration::from_secs(count % 10 + 1));
InErrorPacket::TokenError => Err(Error::Stop("token错误".to_string())),
InErrorPacket::Disconnect => Err(Error::Warn("断开连接".to_string())),
InErrorPacket::AddressExhausted => Err(Error::Stop("地址用尽".to_string())),
InErrorPacket::OtherError(e) => match e.message() {
Ok(str) => Err(Error::Warn(str)),
Err(e) => Err(Error::Warn(format!("{:?}", e))),
},
},
Err(e) => Err(Error::Warn(format!("{:?}", e))),
}
}
_ => Err(Error::Warn(format!("数据错误:{:?}", net_packet))),
}; };
} }
@@ -70,6 +105,7 @@ fn registration_request_packet(
request.device_id = device_id; request.device_id = device_id;
request.name = name; request.name = name;
request.is_fast = is_fast; request.is_fast = is_fast;
request.version = "1.0.6".to_string();
let bytes = request.write_to_bytes()?; let bytes = request.write_to_bytes()?;
let buf = vec![0u8; 12 + bytes.len()]; let buf = vec![0u8; 12 + bytes.len()];
let mut net_packet = NetPacket::new(buf)?; let mut net_packet = NetPacket::new(buf)?;
@@ -82,7 +118,7 @@ fn registration_request_packet(
} }
pub struct Register { pub struct Register {
sender: Sender<Ipv4Addr>, sender: ChannelSender,
server_address: SocketAddr, server_address: SocketAddr,
token: String, token: String,
device_id: String, device_id: String,
@@ -92,7 +128,7 @@ pub struct Register {
impl Register { impl Register {
pub fn new( pub fn new(
sender: Sender<Ipv4Addr>, sender: ChannelSender,
server_address: SocketAddr, server_address: SocketAddr,
token: String, token: String,
device_id: String, device_id: String,
@@ -107,14 +143,14 @@ impl Register {
time: AtomicI64::new(0), time: AtomicI64::new(0),
} }
} }
pub fn fast_register(&self) -> io::Result<()> { pub async fn fast_register(&self) -> io::Result<()> {
let last = self.time.load(Ordering::Relaxed); let last = self.time.load(Ordering::Relaxed);
let new = Local::now().timestamp_millis(); let new = Local::now().timestamp_millis();
if new - last < 1000 if new - last < 1000
|| self || self
.time .time
.compare_exchange(last, new, Ordering::Relaxed, Ordering::Relaxed) .compare_exchange(last, new, Ordering::Relaxed, Ordering::Relaxed)
.is_err() .is_err()
{ {
//短时间不重复注册 //短时间不重复注册
return Ok(()); return Ok(());
@@ -126,9 +162,9 @@ impl Register {
self.name.clone(), self.name.clone(),
false, false,
) )
.unwrap(); .unwrap();
let buf = request_packet.buffer(); let buf = request_packet.buffer();
self.sender.send_to_addr(buf, self.server_address)?; self.sender.send_main(buf, self.server_address).await?;
Ok(()) Ok(())
} }
} }
-163
View File
@@ -1,163 +0,0 @@
use std::net::{Ipv4Addr, SocketAddrV4};
use std::sync::Arc;
use std::{io, thread};
use crossbeam::atomic::AtomicCell;
use p2p_channel::channel::sender::Sender;
use packet::arp::arp::ArpPacket;
use packet::ethernet;
use packet::ethernet::packet::EthernetPacket;
use packet::icmp::icmp::IcmpPacket;
use packet::icmp::Kind;
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use crate::external_route::ExternalRoute;
use crate::handle::{check_dest, CurrentDeviceInfo};
use crate::ip_proxy::IpProxyMap;
use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version};
use crate::tap_device::{TapReader, TapWriter};
pub fn start(sender: Sender<Ipv4Addr>,
tap_reader: TapReader,
tap_writer: TapWriter,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: ExternalRoute,
ip_proxy_map: IpProxyMap) {
thread::Builder::new().name("tap-handler".into()).spawn(move || {
if let Err(e) = start_(sender, tap_reader, tap_writer, current_device,ip_route,ip_proxy_map) {
log::warn!("{:?}",e);
}
}).unwrap();
}
fn start_(sender: Sender<Ipv4Addr>,
tap_reader: TapReader,
tap_writer: TapWriter,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: ExternalRoute,
ip_proxy_map: IpProxyMap) -> io::Result<()> {
let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + 1500]).unwrap();
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Ipv4Turn);
net_packet.set_transport_protocol(ipv4::protocol::Protocol::Ipv4.into());
net_packet.set_ttl(MAX_TTL);
let mut buf = [0; 2048];
loop {
let len = tap_reader.read(&mut buf)?;
if len == 0 {
continue;
}
let mut ethernet_packet = EthernetPacket::unchecked(&mut buf[..len]);
if let Err(e) = handle(&mut net_packet, &current_device, &tap_writer, &mut ethernet_packet, &sender,&ip_route,&ip_proxy_map) {
log::error!("tap handle{:?}",e);
}
}
}
fn handle(net_packet: &mut NetPacket<Vec<u8>>, current_device: &AtomicCell<CurrentDeviceInfo>, tap_writer: &TapWriter, ethernet_packet: &mut EthernetPacket<&mut [u8]>, sender: &Sender<Ipv4Addr>, ip_route: &ExternalRoute, proxy_map: &IpProxyMap) -> crate::Result<()> {
let current_device = current_device.load();
match ethernet_packet.protocol() {
ethernet::protocol::Protocol::Arp => {
let mut out_ethernet_packet = EthernetPacket::unchecked(ethernet_packet.buffer.to_vec());
let arp_packet = ArpPacket::unchecked(ethernet_packet.payload());
let mut out_arp_packet = ArpPacket::unchecked(out_ethernet_packet.payload_mut());
let sender_h = arp_packet.sender_hardware_addr();
let sender_p = arp_packet.sender_protocol_addr();
let target_p = arp_packet.target_protocol_addr();
if target_p == &[0, 0, 0, 0] || sender_p == &[0, 0, 0, 0] || target_p == sender_p {
return Ok(());
}
//回复一个虚假的MAC地址
out_arp_packet.set_sender_hardware_addr(&[target_p[0], target_p[1], target_p[2], target_p[3], 123, 234]);
out_arp_packet.set_sender_protocol_addr(target_p);
out_arp_packet.set_target_hardware_addr(sender_h);
out_arp_packet.set_target_protocol_addr(sender_p);
out_arp_packet.set_op_code(2);
out_ethernet_packet.set_source(&[target_p[0], target_p[1], target_p[2], target_p[3], 123, 234]);
out_ethernet_packet.set_destination(sender_h);
tap_writer.write(&out_ethernet_packet.buffer)?;
}
ethernet::protocol::Protocol::Ipv4 => {
// println!("in ethernet_packet {:?}", ethernet_packet);
let mut ipv4_packet = IpV4Packet::unchecked(ethernet_packet.payload_mut());
let src_ip = ipv4_packet.source_ip();
let mut dest_ip = ipv4_packet.destination_ip();
if src_ip != current_device.virtual_ip() {
return Ok(());
}
if !check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) && !dest_ip.is_broadcast() {
if let Some(r_dest_ip) = ip_route.route(&dest_ip) {
//路由的目标不能是自己
if r_dest_ip == src_ip {
return Ok(());
}
dest_ip = r_dest_ip;
} else {
return Ok(());
}
}else{
match ipv4_packet.protocol() {
ipv4::protocol::Protocol::Tcp => {
let dest_addr = {
let tcp_packet = packet::tcp::tcp::TcpPacket::new(src_ip, dest_ip, ipv4_packet.payload())?;
SocketAddrV4::new(dest_ip, tcp_packet.destination_port())
};
if let Some(entry) = proxy_map.tcp_proxy_map.get(&dest_addr) {
let source_addr = entry.value().1;
let source_ip = *source_addr.ip();
let mut tcp_packet = packet::tcp::tcp::TcpPacket::new(source_ip, dest_ip, ipv4_packet.payload_mut())?;
tcp_packet.set_source_port(source_addr.port());
tcp_packet.update_checksum();
ipv4_packet.set_source_ip(source_ip);
ipv4_packet.update_checksum();
}
}
ipv4::protocol::Protocol::Udp => {
let dest_addr = {
let udp_packet = packet::udp::udp::UdpPacket::new(src_ip, dest_ip, ipv4_packet.payload())?;
SocketAddrV4::new(dest_ip, udp_packet.destination_port())
};
if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) {
let source_addr = entry.value().1;
let source_ip = *source_addr.ip();
let mut udp_packet = packet::udp::udp::UdpPacket::new(src_ip, dest_ip, ipv4_packet.payload_mut())?;
udp_packet.set_source_port(source_addr.port());
udp_packet.update_checksum();
ipv4_packet.set_source_ip(source_ip);
ipv4_packet.update_checksum();
}
}
_ => {}
}
}
if src_ip == dest_ip {
if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp {
let mut icmp = IcmpPacket::unchecked(ipv4_packet.payload_mut());
if icmp.kind() == Kind::EchoRequest {
icmp.set_kind(Kind::EchoReply);
icmp.update_checksum();
let src = ipv4_packet.source_ip();
ipv4_packet.set_source_ip(ipv4_packet.destination_ip());
ipv4_packet.set_destination_ip(src);
ipv4_packet.update_checksum();
tap_writer.write(ethernet_packet.buffer)?;
return Ok(());
}
}
}
net_packet.set_source(src_ip);
net_packet.set_destination(dest_ip);
let data_len = ipv4_packet.buffer.len();
net_packet.set_payload(ipv4_packet.buffer);
//优先发到直连到地址
if sender.send_to_id(&net_packet.buffer()[..(12 + data_len)], &dest_ip).is_err() {
sender.send_to_addr(&net_packet.buffer()[..(12 + data_len)], current_device.connect_server)?;
}
}
_ => {
// log::warn!("不支持的二层协议:{:?}",p)
}
}
Ok(())
}
-175
View File
@@ -1,175 +0,0 @@
use std::{io, thread};
use std::net::{Ipv4Addr, SocketAddrV4};
use std::sync::Arc;
use crossbeam::atomic::AtomicCell;
use p2p_channel::channel::sender::Sender;
use packet::icmp:: Kind;
use packet::icmp::icmp:: IcmpPacket;
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use crate::error::*;
use crate::external_route::ExternalRoute;
use crate::handle::{check_dest, CurrentDeviceInfo};
use crate::ip_proxy::IpProxyMap;
use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version};
use crate::tun_device::{TunReader, TunWriter};
fn icmp(tun_writer: &TunWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Result<()> {
if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp {
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
if icmp.kind() == Kind::EchoRequest {
icmp.set_kind(Kind::EchoReply);
icmp.update_checksum();
let src = ipv4_packet.source_ip();
ipv4_packet.set_source_ip(ipv4_packet.destination_ip());
ipv4_packet.set_destination_ip(src);
ipv4_packet.update_checksum();
tun_writer.write(ipv4_packet.buffer)?;
}
}
Ok(())
}
/// 接收tun数据,并且转发到udp上
#[inline]
fn handle(sender: &Sender<Ipv4Addr>, data: &mut [u8], tun_writer: &TunWriter, current_device: CurrentDeviceInfo, net_packet: &mut NetPacket<[u8; 1512]>, ip_route: &ExternalRoute, proxy_map: &IpProxyMap) -> Result<()> {
let data_len = data.len();
let mut ipv4_packet = match IpV4Packet::new(data) {
Ok(ipv4_packet) => ipv4_packet,
Err(packet::error::Error::Unimplemented) => {
return Ok(());
}
Err(e) => Err(e)?,
};
let src_ip = ipv4_packet.source_ip();
let mut dest_ip = ipv4_packet.destination_ip();
// if dest_ip == cur_info.broadcast_address {
// // 启动服务后会收到对137端口的广播
// // 137端口是在局域网中提供计算机的名字或IP地址查询服务
// return Ok(());
// }
if src_ip != current_device.virtual_ip() {
return Ok(());
}
if src_ip == dest_ip {
return icmp(&tun_writer, ipv4_packet);
}
if !check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) && !dest_ip.is_broadcast() {
// println!("非目标 {:?}",ipv4_packet);
if let Some(r_dest_ip) = ip_route.route(&dest_ip) {
//路由的目标不能是自己
if r_dest_ip == src_ip {
return Ok(());
}
dest_ip = r_dest_ip;
} else {
return Ok(());
}
} else {
match ipv4_packet.protocol() {
ipv4::protocol::Protocol::Tcp => {
let dest_addr = {
let tcp_packet = packet::tcp::tcp::TcpPacket::new(src_ip, dest_ip, ipv4_packet.payload())?;
SocketAddrV4::new(dest_ip, tcp_packet.destination_port())
};
if let Some(entry) = proxy_map.tcp_proxy_map.get(&dest_addr) {
let source_addr = entry.value().1;
let source_ip = *source_addr.ip();
let mut tcp_packet = packet::tcp::tcp::TcpPacket::new(source_ip, dest_ip, ipv4_packet.payload_mut())?;
tcp_packet.set_source_port(source_addr.port());
tcp_packet.update_checksum();
ipv4_packet.set_source_ip(source_ip);
ipv4_packet.update_checksum();
}
}
ipv4::protocol::Protocol::Udp => {
let dest_addr = {
let udp_packet = packet::udp::udp::UdpPacket::new(src_ip, dest_ip, ipv4_packet.payload())?;
SocketAddrV4::new(dest_ip, udp_packet.destination_port())
};
if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) {
let source_addr = entry.value().1;
let source_ip = *source_addr.ip();
let mut udp_packet = packet::udp::udp::UdpPacket::new(source_ip, dest_ip, ipv4_packet.payload_mut())?;
udp_packet.set_source_port(source_addr.port());
udp_packet.update_checksum();
ipv4_packet.set_source_ip(source_ip);
ipv4_packet.update_checksum();
}
}
_ => {}
}
}
net_packet.set_source(src_ip);
net_packet.set_destination(dest_ip);
net_packet.set_payload(ipv4_packet.buffer);
//优先发到直连到地址
if sender.send_to_id(&net_packet.buffer()[..(12 + data_len)], &dest_ip).is_err() {
sender.send_to_addr(&net_packet.buffer()[..(12 + data_len)], current_device.connect_server)?;
}
return Ok(());
}
pub fn start(sender: Sender<Ipv4Addr>,
tun_reader: TunReader,
tun_writer: TunWriter,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: ExternalRoute,
ip_proxy_map: IpProxyMap) {
thread::Builder::new().name("tun-handler".into()).spawn(move || {
if let Err(e) = start_(sender, tun_reader, tun_writer, current_device, ip_route, ip_proxy_map) {
log::warn!("{:?}",e);
}
}).unwrap();
}
#[cfg(target_os = "windows")]
fn start_(sender: Sender<Ipv4Addr>,
tun_reader: TunReader,
tun_writer: TunWriter,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: ExternalRoute,
ip_proxy_map: IpProxyMap) -> io::Result<()> {
let mut net_packet = NetPacket::new([0u8; 4 + 8 + 1500])?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Ipv4Turn);
net_packet.set_transport_protocol(ipv4::protocol::Protocol::Ipv4.into());
net_packet.set_ttl(MAX_TTL);
loop {
let mut data = tun_reader.next()?;
match handle(&sender, data.bytes_mut(), &tun_writer, current_device.load(), &mut net_packet, &ip_route, &ip_proxy_map) {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
}
}
#[cfg(any(target_os = "linux", target_os = "macos"))]
fn start_(sender: Sender<Ipv4Addr>,
tun_reader: TunReader,
tun_writer: TunWriter,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: ExternalRoute,
ip_proxy_map: IpProxyMap) -> io::Result<()> {
let mut net_packet = NetPacket::new([0u8; 4 + 8 + 1500])?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Ipv4Turn);
net_packet.set_transport_protocol(ipv4::protocol::Protocol::Ipv4.into());
net_packet.set_ttl(MAX_TTL);
let mut buf = [0; 4096];
loop {
let len = tun_reader.read(&mut buf)?;
match handle(&sender, &mut buf[..len], &tun_writer, current_device.load(), &mut net_packet, &ip_route, &ip_proxy_map) {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
}
}
+215
View File
@@ -0,0 +1,215 @@
use std::io;
use std::net::{Ipv4Addr, SocketAddrV4};
use aes_gcm::{AeadInPlace, Aes256Gcm, Nonce};
use aes_gcm::aead::consts::U12;
use aes_gcm::aead::generic_array::GenericArray;
use packet::ip::ipv4::packet::IpV4Packet;
use packet::ip::ipv4::protocol::Protocol;
use packet::tcp::tcp::TcpPacket;
use packet::udp::udp::UdpPacket;
use crate::channel::sender::ChannelSender;
use crate::external_route::ExternalRoute;
use crate::handle::{check_dest, CurrentDeviceInfo};
use crate::ip_proxy::IpProxyMap;
use crate::protocol::{ip_turn_packet, NetPacket, Version};
use crate::error::*;
use crate::igmp_server::IgmpServer;
use crate::protocol;
use crate::protocol::ip_turn_packet::BroadcastPacketEnd;
pub mod tun_handler;
pub mod tap_handler;
async fn broadcast(sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]>, data_len: usize, current_device: &CurrentDeviceInfo) -> Result<()> {
let mut peer_ips = Vec::with_capacity(8);
let vec = sender.direct_route_table_one();
for (peer_ip, route) in vec {
if sender.send_by_key(&net_packet.buffer()[..data_len], &route.route_key()).await.is_ok() {
peer_ips.push(peer_ip);
}
}
if peer_ips.is_empty() {
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
} else {
let end_len = 1 + peer_ips.len() * 4;
//剩余的发送到服务端,需要告知哪些已发送过
//放在末尾可以减少复制次数
let mut broadcast = BroadcastPacketEnd::unchecked(&mut net_packet.buffer_mut()[data_len..data_len + end_len]);
broadcast.set_address(&peer_ips)?;
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4Broadcast.into());
sender.send_main(&net_packet.buffer()[..(data_len + end_len)], current_device.connect_server).await?;
}
Ok(())
}
async fn multicast(igmp_server: &IgmpServer, multicast_addr: Ipv4Addr, sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]>, data_len: usize, current_device: &CurrentDeviceInfo) -> Result<()> {
let mut peer_ips = Vec::with_capacity(8);
let vec = sender.direct_route_table_one();
if let Some(members) = igmp_server.load(&multicast_addr) {
for (peer_ip, route) in vec {
let is_send = {members.read().is_send(&peer_ip)};
if is_send {
if sender.send_by_key(&net_packet.buffer()[..data_len], &route.route_key()).await.is_ok() {
peer_ips.push(peer_ip);
if peer_ips.len() == u8::MAX as usize {
break;
}
}
}
}
}
if peer_ips.is_empty() {
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
} else {
let end_len = 1 + peer_ips.len() * 4;
//剩余的发送到服务端,需要告知哪些已发送过
//放在末尾可以减少复制次数
let mut broadcast = BroadcastPacketEnd::unchecked(&mut net_packet.buffer_mut()[data_len..data_len + end_len]);
broadcast.set_address(&peer_ips)?;
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4Broadcast.into());
sender.send_main(&net_packet.buffer()[..(data_len + end_len)], current_device.connect_server).await?;
}
Ok(())
}
/// 实现一个原地发送,必须保证是如下结构
/// |12字节开头|ip报文|至少1024字节+12字节结尾|
///
#[inline]
pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8],
mut data_len: usize,//数据总长度=ip长度+12
igmp_server: &IgmpServer,
current_device: CurrentDeviceInfo,
ip_route: &ExternalRoute, proxy_map: &IpProxyMap, cipher: &Option<Aes256Gcm>) -> Result<()> {
let ipv4_packet = IpV4Packet::new(&buf[12..data_len])?;
let protocol = ipv4_packet.protocol();
let ip_head_len = ipv4_packet.header_len() as usize * 4;
let src_ip = ipv4_packet.source_ip();
let mut dest_ip = ipv4_packet.destination_ip();
let mut net_packet = NetPacket::new(buf)?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(protocol::Protocol::IpTurn);
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4.into());
net_packet.first_set_ttl(3);
net_packet.set_source(src_ip);
net_packet.set_destination(dest_ip);
if dest_ip == current_device.virtual_gateway {
if protocol == Protocol::Icmp {
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Icmp.into());
//发送到服务端的不加密
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
}
return Ok(());
}
if dest_ip.is_multicast() {
if protocol == Protocol::Igmp {
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Igmp.into());
//发送到服务端
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
return Ok(());
}
}
if dest_ip.is_broadcast() || current_device.broadcast_address == dest_ip {
// 广播 发送到直连目标
if Protocol::Udp == protocol {
if let Some(cipher) = cipher {
//需要加密
encrypt(cipher, &mut data_len, &mut net_packet)?;
}
broadcast(sender, &mut net_packet, data_len, &current_device).await?;
}
return Ok(());
} else if dest_ip.is_multicast() {
if protocol == Protocol::Udp {
if let Some(cipher) = cipher {
//需要加密
encrypt(cipher, &mut data_len, &mut net_packet)?;
}
multicast(igmp_server, dest_ip, sender, &mut net_packet, data_len, &current_device).await?;
}
return Ok(());
} else {
if !check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) {
if let Some(r_dest_ip) = ip_route.route(&dest_ip) {
//路由的目标不能是自己
if r_dest_ip == src_ip {
return Ok(());
}
//需要修改目的地址
dest_ip = r_dest_ip;
net_packet.set_destination(r_dest_ip);
} else {
return Ok(());
}
} else {
match protocol {
Protocol::Tcp => {
let dest_addr = {
let tcp_packet = TcpPacket::new(src_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?;
SocketAddrV4::new(dest_ip, tcp_packet.destination_port())
};
if let Some(entry) = proxy_map.tcp_proxy_map.get(&dest_addr) {
let source_addr = entry.value().1;
let source_ip = *source_addr.ip();
let mut tcp_packet = TcpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?;
tcp_packet.set_source_port(source_addr.port());
tcp_packet.update_checksum();
let mut ipv4_packet = IpV4Packet::new(&mut net_packet.buffer_mut()[12..data_len])?;
ipv4_packet.set_source_ip(source_ip);
ipv4_packet.update_checksum();
}
}
Protocol::Udp => {
let dest_addr = {
let udp_packet = UdpPacket::new(src_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?;
SocketAddrV4::new(dest_ip, udp_packet.destination_port())
};
if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) {
let source_addr = entry.value().1;
let source_ip = *source_addr.ip();
let mut udp_packet = UdpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?;
udp_packet.set_source_port(source_addr.port());
udp_packet.update_checksum();
let mut ipv4_packet = IpV4Packet::new(&mut net_packet.buffer_mut()[12..data_len])?;
ipv4_packet.set_source_ip(source_ip);
ipv4_packet.update_checksum();
}
}
_ => {}
}
}
}
if let Some(cipher) = cipher {
//需要加密
encrypt(cipher, &mut data_len, &mut net_packet)?;
}
//优先发到直连到地址
if sender.send_by_id(&net_packet.buffer()[..data_len], &dest_ip).await.is_err() {
sender.send_main(&net_packet.buffer()[..data_len], current_device.connect_server).await?;
}
return Ok(());
}
fn encrypt(cipher: &Aes256Gcm, data_len: &mut usize, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result<()> {
let mut nonce = [0; 12];
nonce[0..4].copy_from_slice(&net_packet.source().octets());
nonce[4..8].copy_from_slice(&net_packet.destination().octets());
nonce[8] = protocol::Protocol::IpTurn.into();
nonce[9] = ip_turn_packet::Protocol::Ipv4.into();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce);
return match cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..*data_len - 12]) {
Ok(tag) => {
if tag.len() != 16 {
return Err(io::Error::new(io::ErrorKind::Other, format!("加密tag长度错误:{}", tag.len())));
}
net_packet.set_encrypt_flag(true);
net_packet.payload_mut()[*data_len - 12..*data_len - 12 + 16].copy_from_slice(tag.as_slice());
*data_len += 16;
Ok(())
}
Err(e) => {
Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e)))
}
};
}
+119
View File
@@ -0,0 +1,119 @@
use std::sync::Arc;
use std::{io, thread};
use aes_gcm::Aes256Gcm;
use crossbeam::atomic::AtomicCell;
use packet::arp::arp::ArpPacket;
use packet::ethernet;
use packet::ethernet::packet::EthernetPacket;
use packet::icmp::icmp::IcmpPacket;
use packet::icmp::Kind;
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use crate::channel::sender::ChannelSender;
use crate::external_route::ExternalRoute;
use crate::handle::CurrentDeviceInfo;
use crate::igmp_server::IgmpServer;
use crate::ip_proxy::IpProxyMap;
use crate::tun_tap_device::{DeviceReader, DeviceWriter};
pub fn start(sender: ChannelSender,
device_reader: DeviceReader,
device_writer: DeviceWriter,
igmp_server: IgmpServer,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: ExternalRoute,
ip_proxy_map: IpProxyMap,
cipher: Option<Aes256Gcm>) {
thread::Builder::new().name("tap-handler".into()).spawn(move || {
tokio::runtime::Builder::new_current_thread()
.enable_all().build().unwrap()
.block_on(async move {
if let Err(e) = start_(sender, device_reader,
device_writer, igmp_server,
current_device, ip_route, ip_proxy_map, cipher).await {
log::warn!("tap:{:?}",e);
}
});
}).unwrap();
}
async fn start_(sender: ChannelSender,
device_reader: DeviceReader,
device_writer: DeviceWriter,
igmp_server: IgmpServer,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: ExternalRoute,
ip_proxy_map: IpProxyMap,
cipher: Option<Aes256Gcm>) -> io::Result<()> {
let mut buf = [0; 2048];
loop {
//ip拆包了会直接丢弃?
let len = device_reader.read(&mut buf)?;
if let Err(e) = handle(&mut buf, len, &igmp_server, &current_device, &device_writer, &sender, &ip_route, &ip_proxy_map, &cipher).await {
log::error!("tap handle{:?}",e);
}
}
}
async fn handle(buf: &mut [u8], len: usize, igmp_server: &IgmpServer, current_device: &AtomicCell<CurrentDeviceInfo>,
device_writer: &DeviceWriter, sender: &ChannelSender, ip_route: &ExternalRoute, proxy_map: &IpProxyMap, cipher: &Option<Aes256Gcm>) -> crate::Result<()> {
let mut ethernet_packet = EthernetPacket::new(&mut buf[..len])?;
let current_device = current_device.load();
match ethernet_packet.protocol() {
ethernet::protocol::Protocol::Arp => {
let mut out_ethernet_packet = EthernetPacket::unchecked(ethernet_packet.buffer.to_vec());
let arp_packet = ArpPacket::unchecked(ethernet_packet.payload());
let mut out_arp_packet = ArpPacket::unchecked(out_ethernet_packet.payload_mut());
let sender_h = arp_packet.sender_hardware_addr();
let sender_p = arp_packet.sender_protocol_addr();
let target_p = arp_packet.target_protocol_addr();
if target_p == &[0, 0, 0, 0] || sender_p == &[0, 0, 0, 0] || target_p == sender_p {
return Ok(());
}
//回复一个虚假的MAC地址
out_arp_packet.set_sender_hardware_addr(&[target_p[0], target_p[1], target_p[2], target_p[3], !sender_h[5], 234]);
out_arp_packet.set_sender_protocol_addr(target_p);
out_arp_packet.set_target_hardware_addr(sender_h);
out_arp_packet.set_target_protocol_addr(sender_p);
out_arp_packet.set_op_code(2);
out_ethernet_packet.set_source(&[target_p[0], target_p[1], target_p[2], target_p[3], !sender_h[5], 234]);
out_ethernet_packet.set_destination(sender_h);
device_writer.write_ethernet_tap(&out_ethernet_packet.buffer)?;
}
ethernet::protocol::Protocol::Ipv4 => {
let mut ipv4_packet = IpV4Packet::unchecked(ethernet_packet.payload_mut());
let src_ip = ipv4_packet.source_ip();
if src_ip != current_device.virtual_ip() {
return Ok(());
}
let dest_ip = ipv4_packet.destination_ip();
let protocol = ipv4_packet.protocol();
if src_ip == dest_ip {
if protocol == ipv4::protocol::Protocol::Icmp {
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
if icmp.kind() == Kind::EchoRequest {
icmp.set_kind(Kind::EchoReply);
icmp.update_checksum();
ipv4_packet.set_source_ip(dest_ip);
ipv4_packet.set_destination_ip(src_ip);
ipv4_packet.update_checksum();
let source = ethernet_packet.source().to_vec();
let dest = ethernet_packet.destination().to_vec();
ethernet_packet.set_source(&dest);
ethernet_packet.set_destination(&source);
device_writer.write_ethernet_tap(&ethernet_packet.buffer)?;
}
}
return Ok(());
}
// 以太网帧头部14字节,预留12字节
return crate::handle::tun_tap::base_handle(sender, &mut buf[2..], len - 2, igmp_server, current_device,
ip_route, proxy_map, cipher).await;
}
_ => {
// log::warn!("不支持的二层协议:{:?}",p)
}
}
Ok(())
}
+93
View File
@@ -0,0 +1,93 @@
use std::{io, thread};
use std::sync::Arc;
use aes_gcm::Aes256Gcm;
use crossbeam::atomic::AtomicCell;
use packet::icmp::Kind;
use packet::icmp::icmp::IcmpPacket;
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use crate::channel::sender::ChannelSender;
use crate::error::*;
use crate::external_route::ExternalRoute;
use crate::handle::CurrentDeviceInfo;
use crate::igmp_server::IgmpServer;
use crate::ip_proxy::IpProxyMap;
use crate::tun_tap_device::{DeviceReader, DeviceWriter};
fn icmp(device_writer: &DeviceWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Result<()> {
if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp {
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
if icmp.kind() == Kind::EchoRequest {
icmp.set_kind(Kind::EchoReply);
icmp.update_checksum();
let src = ipv4_packet.source_ip();
ipv4_packet.set_source_ip(ipv4_packet.destination_ip());
ipv4_packet.set_destination_ip(src);
ipv4_packet.update_checksum();
device_writer.write_ipv4_tun(ipv4_packet.buffer)?;
}
}
Ok(())
}
/// 接收tun数据,并且转发到udp上
#[inline]
async fn handle(sender: &ChannelSender, data: &mut [u8], len: usize, device_writer: &DeviceWriter, igmp_server: &IgmpServer, current_device: CurrentDeviceInfo,
ip_route: &ExternalRoute, proxy_map: &IpProxyMap,cipher: &Option<Aes256Gcm>) -> Result<()> {
let ipv4_packet = if let Ok(ipv4_packet) = IpV4Packet::new(&mut data[12..len]) {
ipv4_packet
} else {
return Ok(());
};
let src_ip = ipv4_packet.source_ip();
let dest_ip = ipv4_packet.destination_ip();
if src_ip != current_device.virtual_ip() {
return Ok(());
}
if src_ip == dest_ip {
return icmp(&device_writer, ipv4_packet);
}
return crate::handle::tun_tap::base_handle(sender, data, len, igmp_server, current_device, ip_route, proxy_map,cipher).await;
}
pub fn start(sender: ChannelSender,
device_reader: DeviceReader,
device_writer: DeviceWriter,
igmp_server: IgmpServer,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: ExternalRoute,
ip_proxy_map: IpProxyMap,
cipher: Option<Aes256Gcm>) {
thread::Builder::new().name("tun-handler".into()).spawn(move || {
tokio::runtime::Builder::new_current_thread()
.enable_all().build().unwrap()
.block_on(async move {
if let Err(e) = start_(sender, device_reader, device_writer, igmp_server, current_device, ip_route, ip_proxy_map,cipher).await {
log::warn!("tun:{:?}",e);
}
})
}).unwrap();
}
async fn start_(sender: ChannelSender,
device_reader: DeviceReader,
device_writer: DeviceWriter,
igmp_server: IgmpServer,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: ExternalRoute,
ip_proxy_map: IpProxyMap,
cipher: Option<Aes256Gcm>) -> io::Result<()> {
let mut buf = [0; 4096];
loop {
let len = device_reader.read(&mut buf[12..])? + 12;
match handle(&sender, &mut buf, len, &device_writer, &igmp_server, current_device.load(), &ip_route, &ip_proxy_map,&cipher).await {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
}
}
+248
View File
@@ -0,0 +1,248 @@
use std::collections::{HashMap, HashSet};
use std::net::Ipv4Addr;
use std::sync::Arc;
use std::time::Duration;
use moka::sync::Cache;
use parking_lot::RwLock;
use packet::igmp::igmp_v2::IgmpV2Packet;
use packet::igmp::igmp_v3::{IgmpV3QueryPacket, IgmpV3RecordType, IgmpV3ReportPacket};
use packet::igmp::IgmpType;
use packet::ip::ipv4::protocol::Protocol;
use crate::tun_tap_device::DeviceWriter;
//1. 定时发送query,启动时20秒一次,连发3次,之后8分钟一次
//2. 接收网关的igmp report 维护组播源信息
#[derive(Clone, Debug)]
pub struct Multicast {
//成员虚拟ip
members: HashSet<Ipv4Addr>,
//是否是过滤模式
//成员过滤或包含的源ip
map: HashMap<Ipv4Addr, (bool, HashSet<Ipv4Addr>)>,
}
impl Multicast {
pub fn new() -> Self {
Self {
members: Default::default(),
map: Default::default(),
}
}
pub fn is_send(&self, ip: &Ipv4Addr) -> bool {
if self.members.contains(ip) {
if let Some((is_include, set)) = self.map.get(ip) {
if *is_include {
set.contains(ip)
} else {
!set.contains(ip)
}
} else {
true
}
} else {
false
}
}
}
#[derive(Clone)]
pub struct IgmpServer {
multicast: Cache<Ipv4Addr, Arc<RwLock<Multicast>>>,
members: Cache<(Ipv4Addr, Ipv4Addr), ()>,
}
impl IgmpServer {
pub fn new(device_writer: DeviceWriter) -> Self {
let multicast: Cache<Ipv4Addr, Arc<RwLock<Multicast>>> = Cache::builder()
.time_to_idle(Duration::from_secs(30 * 60)).build();
let m = multicast.clone();
let members: Cache<(Ipv4Addr, Ipv4Addr), ()> = Cache::builder()
.time_to_idle(Duration::from_secs(20 * 60)).eviction_listener(move |k: Arc<(Ipv4Addr, Ipv4Addr)>, _, cause| {
if cause == moka::notification::RemovalCause::Replaced {
return;
}
log::info!("MULTICAST_MEMBER eviction {:?}", k);
if let Some(v) = m.get(&k.0) {
let mut lock = v.write();
lock.members.remove(&k.1);
lock.map.remove(&k.1);
}
}).build();
std::thread::spawn(move || {
//定时发送query,启动时20秒一次,连发3次,之后125秒一次
let mut count = 0;
//预留以太网帧头和ip头
let mut buf = [0; 14 + 24 + 12];
let dest = Ipv4Addr::new(224, 0, 0, 1);
let src = Ipv4Addr::new(10, 26, 0, 1);
{
let buf = &mut buf[14..];
let len = buf.len();
// ipv4 头部20字节
buf[0] = 0b0100_0110;
//写入总长度
buf[2..4].copy_from_slice(&(len as u16).to_be_bytes());
//ttl
buf[8] = 1;
buf[20] = 0x94;
buf[21] = 0x04;
let mut ipv4 = packet::ip::ipv4::packet::IpV4Packet::unchecked(buf);
ipv4.set_flags(2);
ipv4.set_protocol(Protocol::Igmp);
ipv4.set_source_ip(src);
ipv4.set_destination_ip(dest);
ipv4.update_checksum();
}
{
let mut igmp_query = IgmpV3QueryPacket::unchecked(&mut buf[14 + 24..]);
igmp_query.set_igmp_type();
igmp_query.set_max_resp_code(100);
igmp_query.set_group_address(Ipv4Addr::UNSPECIFIED);
igmp_query.set_qrv(2);
igmp_query.set_qqic(125);
igmp_query.update_checksum();
}
loop {
let _ = device_writer.write_ipv4(&mut buf);
if count < 3 {
count += 1;
std::thread::sleep(Duration::from_secs(20))
} else {
std::thread::sleep(Duration::from_secs(125))
}
}
});
Self {
multicast,
members,
}
}
pub fn load(&self, multicast_addr: &Ipv4Addr) -> Option<Arc<RwLock<Multicast>>> {
self.multicast.get(multicast_addr)
}
pub fn handle(&self, buf: &[u8], source: Ipv4Addr) -> crate::Result<()> {
match IgmpType::from(buf[0]) {
IgmpType::Query => {}
IgmpType::ReportV1 | IgmpType::ReportV2 => {
//加入组播,v1和v2差不多
let report = IgmpV2Packet::new(buf)?;
let multicast_addr = report.group_address();
if !multicast_addr.is_multicast() {
return Ok(());
}
let multi = self.multicast.get_with(multicast_addr, || {
Arc::new(RwLock::new(Multicast::new()))
});
let mut guard = multi.write();
guard.members.insert(source);
drop(guard);
self.members.insert((multicast_addr, source), ());
}
IgmpType::LeaveV2 => {
//退出组播
let leave = IgmpV2Packet::new(buf)?;
let multicast_addr = leave.group_address();
if !multicast_addr.is_multicast() {
return Ok(());
}
self.members.invalidate(&(multicast_addr, source));
}
IgmpType::ReportV3 => {
let report = IgmpV3ReportPacket::new(buf)?;
if let Some(group_records) = report.group_records() {
for group_record in group_records {
let multicast_addr = group_record.multicast_address();
if !multicast_addr.is_multicast() {
return Ok(());
}
let multi = self.multicast.get_with(multicast_addr, || {
Arc::new(RwLock::new(Multicast::new()))
});
let mut guard = multi.write();
match group_record.record_type() {
IgmpV3RecordType::ModeIsInclude | IgmpV3RecordType::ChangeToIncludeMode => {
match group_record.source_addresses() {
None => {
//不接收所有
guard.members.remove(&source);
guard.map.remove(&source);
}
Some(src) => {
guard.members.insert(source);
guard.map.insert(source, (true, HashSet::from_iter(src)));
drop(guard);
self.members.insert((multicast_addr, source), ());
}
}
}
IgmpV3RecordType::ModeIsExclude | IgmpV3RecordType::ChangeToExcludeMode => {
match group_record.source_addresses() {
None => {
//接收所有
guard.members.insert(source);
guard.map.remove(&source);
}
Some(src) => {
guard.members.insert(source);
guard.map.insert(source, (false, HashSet::from_iter(src)));
}
}
drop(guard);
self.members.insert((multicast_addr, source), ());
}
IgmpV3RecordType::AllowNewSources => {
//在已有源的基础上,接收目标源,如果是排除模式,则删除;是包含模式则添加
match group_record.source_addresses() {
None => {}
Some(src) => {
match guard.map.get_mut(&source) {
None => {}
Some((is_include, set)) => {
for ip in src {
if *is_include {
set.insert(ip);
} else {
set.remove(&ip);
}
}
}
}
}
}
drop(guard);
self.members.insert((multicast_addr, source), ());
}
IgmpV3RecordType::BlockOldSources => {
//在已有源的基础上,不接收目标源
match group_record.source_addresses() {
None => {}
Some(src) => {
match guard.map.get_mut(&source) {
None => {}
Some((is_include, set)) => {
for ip in src {
if *is_include {
set.remove(&ip);
} else {
set.insert(ip);
}
}
}
}
}
}
drop(guard);
self.members.insert((multicast_addr, source), ());
}
IgmpV3RecordType::Unknown(_) => {}
}
}
}
}
IgmpType::Unknown(_) => {}
}
Ok(())
}
}
+6 -6
View File
@@ -6,11 +6,11 @@ use crossbeam::atomic::AtomicCell;
use crossbeam_skiplist::SkipMap; use crossbeam_skiplist::SkipMap;
use socket2::{Domain, SockAddr, Socket, Type}; use socket2::{Domain, SockAddr, Socket, Type};
use p2p_channel::channel::sender::Sender;
use packet::icmp::icmp; use packet::icmp::icmp;
use packet::icmp::icmp::HeaderOther; use packet::icmp::icmp::HeaderOther;
use packet::ip::ipv4; use packet::ip::ipv4;
use crate::channel::sender::ChannelSender;
use crate::handle::CurrentDeviceInfo; use crate::handle::CurrentDeviceInfo;
use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version}; use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version};
@@ -18,12 +18,12 @@ pub struct IcmpProxy {
icmp_socket: Arc<Socket>, icmp_socket: Arc<Socket>,
// 对端-> 真实来源 // 对端-> 真实来源
icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>, icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
sender: Sender<Ipv4Addr>, sender: ChannelSender,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
} }
impl IcmpProxy { impl IcmpProxy {
pub fn new(addr: SocketAddrV4, icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>, sender: Sender<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<IcmpProxy> { pub fn new(addr: SocketAddrV4, icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>, sender: ChannelSender, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<IcmpProxy> {
let icmp_socket = Arc::new(Socket::new(Domain::IPV4, Type::RAW, Some(socket2::Protocol::ICMPV4))?); let icmp_socket = Arc::new(Socket::new(Domain::IPV4, Type::RAW, Some(socket2::Protocol::ICMPV4))?);
icmp_socket.bind(&SockAddr::from(addr))?; icmp_socket.bind(&SockAddr::from(addr))?;
// // 设置 SIO_RCVALL 参数 // // 设置 SIO_RCVALL 参数
@@ -66,8 +66,8 @@ impl IcmpProxy {
unsafe { std::mem::transmute(&mut buf[..]) }; unsafe { std::mem::transmute(&mut buf[..]) };
let mut net_packet = NetPacket::new([0u8; 4 + 8 + 1500]).unwrap(); let mut net_packet = NetPacket::new([0u8; 4 + 8 + 1500]).unwrap();
net_packet.set_version(Version::V1); net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Ipv4Turn); net_packet.set_protocol(Protocol::IpTurn);
net_packet.set_transport_protocol(ipv4::protocol::Protocol::Ipv4.into()); net_packet.set_transport_protocol(ipv4::protocol::Protocol::Icmp.into());
net_packet.set_ttl(MAX_TTL); net_packet.set_ttl(MAX_TTL);
loop { loop {
match self.recv(data) { match self.recv(data) {
@@ -90,7 +90,7 @@ impl IcmpProxy {
net_packet.set_destination(dest_ip); net_packet.set_destination(dest_ip);
let data_len = ipv4_packet.buffer.len(); let data_len = ipv4_packet.buffer.len();
net_packet.set_payload(ipv4_packet.buffer); net_packet.set_payload(ipv4_packet.buffer);
let _ = self.sender.send_to_id(&net_packet.buffer()[..(12 + data_len)], &dest_ip); let _ = self.sender.try_send_by_id(&net_packet.buffer()[..(12 + data_len)], &dest_ip);
} }
} }
_ => { _ => {
+12 -12
View File
@@ -6,7 +6,7 @@ use crossbeam::atomic::AtomicCell;
use crossbeam_skiplist::SkipMap; use crossbeam_skiplist::SkipMap;
use socket2::{SockAddr, Socket}; use socket2::{SockAddr, Socket};
use tokio::net::{TcpListener, UdpSocket}; use tokio::net::{TcpListener, UdpSocket};
use p2p_channel::channel::sender::Sender; use crate::channel::sender::ChannelSender;
use crate::handle::CurrentDeviceInfo; use crate::handle::CurrentDeviceInfo;
use crate::ip_proxy::icmp_proxy::IcmpProxy; use crate::ip_proxy::icmp_proxy::IcmpProxy;
use crate::ip_proxy::tcp_proxy::TcpProxy; use crate::ip_proxy::tcp_proxy::TcpProxy;
@@ -45,34 +45,34 @@ impl IpProxyMap {
} }
} }
pub async fn init_proxy(sender: Sender<Ipv4Addr>, bind_ips: Vec<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<IpProxyMap> { pub async fn init_proxy(sender: ChannelSender, bind_ips: Vec<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<IpProxyMap> {
let mut icmp_sockets = HashMap::new(); let mut icmp_sockets = HashMap::new();
let tcp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>> = Arc::new(SkipMap::new()); let tcp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>> = Arc::new(SkipMap::new());
let udp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>> = Arc::new(SkipMap::new()); let udp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>> = Arc::new(SkipMap::new());
let icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>> = Arc::new(SkipMap::new()); let icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>> = Arc::new(SkipMap::new());
let tcp_listener = TcpListener::bind("0.0.0.0:0").await?; let (tcp_proxy_port, udp_proxy_port) = if !bind_ips.is_empty() {
let udp_socket = UdpSocket::bind("0.0.0.0:0").await?; let tcp_listener = TcpListener::bind("0.0.0.0:0").await?;
let tcp_proxy_port = tcp_listener.local_addr()?.port(); let udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
let udp_proxy_port = udp_socket.local_addr()?.port(); let tcp_proxy_port = tcp_listener.local_addr()?.port();
let udp_proxy_port = udp_socket.local_addr()?.port();
{
let tcp_proxy_map = tcp_proxy_map.clone(); let tcp_proxy_map = tcp_proxy_map.clone();
tokio::spawn(async { tokio::spawn(async {
let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map); let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map);
tcp_proxy.start().await tcp_proxy.start().await
}); });
}
{
let udp_proxy_map = udp_proxy_map.clone(); let udp_proxy_map = udp_proxy_map.clone();
tokio::spawn(async { tokio::spawn(async {
let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map); let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map);
udp_proxy.start().await udp_proxy.start().await
}); });
} (tcp_proxy_port, udp_proxy_port)
} else {
(0, 0)
};
for ip in bind_ips { for ip in bind_ips {
let addr = SocketAddrV4::new(ip, 0); let addr = SocketAddrV4::new(ip, 0);
let icmp_proxy_map = icmp_proxy_map.clone(); let icmp_proxy_map = icmp_proxy_map.clone();
let icmp_proxy = IcmpProxy::new(addr, icmp_proxy_map, sender.try_clone()?, current_device.clone())?; let icmp_proxy = IcmpProxy::new(addr, icmp_proxy_map, sender.clone(), current_device.clone())?;
icmp_sockets.insert(ip, icmp_proxy.icmp_socket()); icmp_sockets.insert(ip, icmp_proxy.icmp_socket());
thread::spawn(move || { thread::spawn(move || {
icmp_proxy.start(); icmp_proxy.start();
+3 -4
View File
@@ -1,7 +1,5 @@
use crate::error::Error; use crate::error::Error;
pub use p2p_channel::channel::{Route, RouteKey};
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
pub mod error; pub mod error;
@@ -9,8 +7,9 @@ pub mod handle;
pub mod nat; pub mod nat;
pub mod proto; pub mod proto;
pub mod protocol; pub mod protocol;
pub mod tun_device;
pub mod tap_device;
pub mod ip_proxy; pub mod ip_proxy;
pub mod external_route; pub mod external_route;
pub mod igmp_server;
pub mod tun_tap_device;
pub mod core; pub mod core;
pub mod channel;
+1 -1
View File
@@ -1,8 +1,8 @@
use p2p_channel::punch::NatType;
use std::collections::HashSet; use std::collections::HashSet;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket}; use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
use std::time::Duration; use std::time::Duration;
use std::{io, thread}; use std::{io, thread};
use crate::channel::punch::NatType;
// #[derive(Debug, Copy, Clone, PartialEq)] // #[derive(Debug, Copy, Clone, PartialEq)]
// pub enum NatType { // pub enum NatType {
+16 -9
View File
@@ -1,5 +1,4 @@
use crate::proto::message::PunchNatType; use crate::proto::message::PunchNatType;
use p2p_channel::punch::{NatInfo, NatType};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::io; use std::io;
use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::net::{IpAddr, Ipv4Addr, SocketAddr};
@@ -8,12 +7,20 @@ use std::sync::Arc;
pub mod check; pub mod check;
use std::net::UdpSocket; use std::net::UdpSocket;
use crate::channel::punch::{NatInfo, NatType};
pub fn local_ip() -> io::Result<IpAddr> { pub fn local_ip() -> io::Result<Ipv4Addr> {
let socket = UdpSocket::bind("0.0.0.0:0")?; let socket = UdpSocket::bind("0.0.0.0:0")?;
socket.connect("8.8.8.8:80")?; socket.connect("8.8.8.8:80")?;
let addr = socket.local_addr()?; let addr = socket.local_addr()?;
Ok(addr.ip()) match addr.ip() {
IpAddr::V4(ip) => {
Ok(ip)
}
IpAddr::V6(_) => {
Ok(Ipv4Addr::UNSPECIFIED)
}
}
} }
#[derive(Clone)] #[derive(Clone)]
@@ -45,7 +52,7 @@ impl NatTest {
nat_test_server: Vec<SocketAddr>, nat_test_server: Vec<SocketAddr>,
public_ip: Ipv4Addr, public_ip: Ipv4Addr,
public_port: u16, public_port: u16,
local_ip: IpAddr, local_ip: Ipv4Addr,
local_port: u16, local_port: u16,
) -> NatTest { ) -> NatTest {
let info = NatTest::re_test_( let info = NatTest::re_test_(
@@ -67,7 +74,7 @@ impl NatTest {
&self, &self,
public_ip: Ipv4Addr, public_ip: Ipv4Addr,
public_port: u16, public_port: u16,
local_ip: IpAddr, local_ip: Ipv4Addr,
local_port: u16, local_port: u16,
) -> NatInfo { ) -> NatInfo {
let info = NatTest::re_test_( let info = NatTest::re_test_(
@@ -84,16 +91,16 @@ impl NatTest {
nat_test_server: &Vec<SocketAddr>, nat_test_server: &Vec<SocketAddr>,
public_ip: Ipv4Addr, public_ip: Ipv4Addr,
public_port: u16, public_port: u16,
local_ip: IpAddr, local_ip: Ipv4Addr,
local_port: u16, local_port: u16,
) -> NatInfo { ) -> NatInfo {
return match check::public_ip_list(nat_test_server) { return match check::public_ip_list(nat_test_server) {
Ok((nat_type, ips, port_range)) => { Ok((nat_type, ips, port_range)) => {
let mut public_ips = Vec::new(); let mut public_ips = Vec::new();
public_ips.push(IpAddr::from(public_ip)); public_ips.push(Ipv4Addr::from(public_ip));
for ip in ips { for ip in ips {
if ip != public_ip { if ip != public_ip {
public_ips.push(IpAddr::from(ip)); public_ips.push(ip);
} }
} }
NatInfo::new( NatInfo::new(
@@ -108,7 +115,7 @@ impl NatTest {
Err(e) => { Err(e) => {
log::warn!("{:?}", e); log::warn!("{:?}", e);
NatInfo::new( NatInfo::new(
vec![IpAddr::from(public_ip)], vec![public_ip],
public_port, public_port,
0, 0,
local_ip, local_ip,
+42 -23
View File
@@ -37,6 +37,8 @@ pub struct RegistrationRequest {
pub name: ::std::string::String, pub name: ::std::string::String,
// @@protoc_insertion_point(field:RegistrationRequest.is_fast) // @@protoc_insertion_point(field:RegistrationRequest.is_fast)
pub is_fast: bool, pub is_fast: bool,
// @@protoc_insertion_point(field:RegistrationRequest.version)
pub version: ::std::string::String,
// special fields // special fields
// @@protoc_insertion_point(special_field:RegistrationRequest.special_fields) // @@protoc_insertion_point(special_field:RegistrationRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields, pub special_fields: ::protobuf::SpecialFields,
@@ -54,7 +56,7 @@ impl RegistrationRequest {
} }
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(4); let mut fields = ::std::vec::Vec::with_capacity(5);
let mut oneofs = ::std::vec::Vec::with_capacity(0); let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"token", "token",
@@ -76,6 +78,11 @@ impl RegistrationRequest {
|m: &RegistrationRequest| { &m.is_fast }, |m: &RegistrationRequest| { &m.is_fast },
|m: &mut RegistrationRequest| { &mut m.is_fast }, |m: &mut RegistrationRequest| { &mut m.is_fast },
)); ));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"version",
|m: &RegistrationRequest| { &m.version },
|m: &mut RegistrationRequest| { &mut m.version },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<RegistrationRequest>( ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<RegistrationRequest>(
"RegistrationRequest", "RegistrationRequest",
fields, fields,
@@ -106,6 +113,9 @@ impl ::protobuf::Message for RegistrationRequest {
32 => { 32 => {
self.is_fast = is.read_bool()?; self.is_fast = is.read_bool()?;
}, },
42 => {
self.version = is.read_string()?;
},
tag => { tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
}, },
@@ -130,6 +140,9 @@ impl ::protobuf::Message for RegistrationRequest {
if self.is_fast != false { if self.is_fast != false {
my_size += 1 + 1; my_size += 1 + 1;
} }
if !self.version.is_empty() {
my_size += ::protobuf::rt::string_size(5, &self.version);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32); self.special_fields.cached_size().set(my_size as u32);
my_size my_size
@@ -148,6 +161,9 @@ impl ::protobuf::Message for RegistrationRequest {
if self.is_fast != false { if self.is_fast != false {
os.write_bool(4, self.is_fast)?; os.write_bool(4, self.is_fast)?;
} }
if !self.version.is_empty() {
os.write_string(5, &self.version)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?; os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(()) ::std::result::Result::Ok(())
} }
@@ -169,6 +185,7 @@ impl ::protobuf::Message for RegistrationRequest {
self.device_id.clear(); self.device_id.clear();
self.name.clear(); self.name.clear();
self.is_fast = false; self.is_fast = false;
self.version.clear();
self.special_fields.clear(); self.special_fields.clear();
} }
@@ -178,6 +195,7 @@ impl ::protobuf::Message for RegistrationRequest {
device_id: ::std::string::String::new(), device_id: ::std::string::String::new(),
name: ::std::string::String::new(), name: ::std::string::String::new(),
is_fast: false, is_fast: false,
version: ::std::string::String::new(),
special_fields: ::protobuf::SpecialFields::new(), special_fields: ::protobuf::SpecialFields::new(),
}; };
&instance &instance
@@ -1017,28 +1035,29 @@ impl PunchNatType {
} }
static file_descriptor_proto_data: &'static [u8] = b"\ static file_descriptor_proto_data: &'static [u8] = b"\
\n\rmessage.proto\"u\n\x13RegistrationRequest\x12\x14\n\x05token\x18\x01\ \n\rmessage.proto\"\x8f\x01\n\x13RegistrationRequest\x12\x14\n\x05token\
\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\tR\x08device\ \x18\x01\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\tR\
Id\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\x07is_fast\ \x08deviceId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\x07\
\x18\x04\x20\x01(\x08R\x06isFast\"\x92\x02\n\x14RegistrationResponse\x12\ is_fast\x18\x04\x20\x01(\x08R\x06isFast\x12\x18\n\x07version\x18\x05\x20\
\x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tvirtualIp\x12'\n\x0fvirtual_ga\ \x01(\tR\x07version\"\x92\x02\n\x14RegistrationResponse\x12\x1d\n\nvirtu\
teway\x18\x02\x20\x01(\x07R\x0evirtualGateway\x12'\n\x0fvirtual_netmask\ al_ip\x18\x01\x20\x01(\x07R\tvirtualIp\x12'\n\x0fvirtual_gateway\x18\x02\
\x18\x03\x20\x01(\x07R\x0evirtualNetmask\x12\x14\n\x05epoch\x18\x04\x20\ \x20\x01(\x07R\x0evirtualGateway\x12'\n\x0fvirtual_netmask\x18\x03\x20\
\x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x05\x20\x03(\x0b2\x0b.D\ \x01(\x07R\x0evirtualNetmask\x12\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05e\
eviceInfoR\x0edeviceInfoList\x12\x1b\n\tpublic_ip\x18\x06\x20\x01(\x07R\ poch\x125\n\x10device_info_list\x18\x05\x20\x03(\x0b2\x0b.DeviceInfoR\
\x08publicIp\x12\x1f\n\x0bpublic_port\x18\x07\x20\x01(\rR\npublicPort\"d\ \x0edeviceInfoList\x12\x1b\n\tpublic_ip\x18\x06\x20\x01(\x07R\x08publicI\
\n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\x12\x1d\n\n\ p\x12\x1f\n\x0bpublic_port\x18\x07\x20\x01(\rR\npublicPort\"d\n\nDeviceI\
virtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\x12#\n\rdevice_status\x18\ nfo\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\x12\x1d\n\nvirtual_ip\
\x03\x20\x01(\rR\x0cdeviceStatus\"Y\n\nDeviceList\x12\x14\n\x05epoch\x18\ \x18\x02\x20\x01(\x07R\tvirtualIp\x12#\n\rdevice_status\x18\x03\x20\x01(\
\x01\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x02\x20\x03(\ \rR\x0cdeviceStatus\"Y\n\nDeviceList\x12\x14\n\x05epoch\x18\x01\x20\x01(\
\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xf8\x01\n\tPunchInfo\x12$\n\ \rR\x05epoch\x125\n\x10device_info_list\x18\x02\x20\x03(\x0b2\x0b.Device\
\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIpList\x12\x1f\n\x0bpu\ InfoR\x0edeviceInfoList\"\xf8\x01\n\tPunchInfo\x12$\n\x0epublic_ip_list\
blic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11public_port_range\ \x18\x02\x20\x03(\x07R\x0cpublicIpList\x12\x1f\n\x0bpublic_port\x18\x03\
\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12(\n\x08nat_type\x18\x05\x20\ \x20\x01(\rR\npublicPort\x12*\n\x11public_port_range\x18\x04\x20\x01(\rR\
\x01(\x0e2\r.PunchNatTypeR\x07natType\x12\x14\n\x05reply\x18\x06\x20\x01\ \x0fpublicPortRange\x12(\n\x08nat_type\x18\x05\x20\x01(\x0e2\r.PunchNatT\
(\x08R\x05reply\x12\x19\n\x08local_ip\x18\x07\x20\x01(\x07R\x07localIp\ ypeR\x07natType\x12\x14\n\x05reply\x18\x06\x20\x01(\x08R\x05reply\x12\
\x12\x1d\n\nlocal_port\x18\x08\x20\x01(\rR\tlocalPort*'\n\x0cPunchNatTyp\ \x19\n\x08local_ip\x18\x07\x20\x01(\x07R\x07localIp\x12\x1d\n\nlocal_por\
e\x12\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\x10\x01b\x06proto3\ t\x18\x08\x20\x01(\rR\tlocalPort*'\n\x0cPunchNatType\x12\r\n\tSymmetric\
\x10\0\x12\x08\n\x04Cone\x10\x01b\x06proto3\
"; ";
/// `FileDescriptorProto` object which was a source for this generated file /// `FileDescriptorProto` object which was a source for this generated file
+5 -6
View File
@@ -17,7 +17,7 @@ pub enum Protocol {
PunchRequest, PunchRequest,
/// 打洞响应 /// 打洞响应
PunchResponse, PunchResponse,
UnKnow(u8), Unknown(u8),
} }
impl From<u8> for Protocol { impl From<u8> for Protocol {
@@ -27,7 +27,7 @@ impl From<u8> for Protocol {
2 => Protocol::Pong, 2 => Protocol::Pong,
3 => Protocol::PunchRequest, 3 => Protocol::PunchRequest,
4 => Protocol::PunchResponse, 4 => Protocol::PunchResponse,
val => Protocol::UnKnow(val), val => Protocol::Unknown(val),
} }
} }
} }
@@ -39,7 +39,7 @@ impl Into<u8> for Protocol {
Protocol::Pong => 2, Protocol::Pong => 2,
Protocol::PunchRequest => 3, Protocol::PunchRequest => 3,
Protocol::PunchResponse => 4, Protocol::PunchResponse => 4,
Protocol::UnKnow(val) => val, Protocol::Unknown(val) => val,
} }
} }
} }
@@ -58,18 +58,17 @@ impl<B: AsRef<[u8]>> ControlPacket<B> {
Protocol::Pong => Ok(ControlPacket::PongPacket(PongPacket::new(buffer)?)), Protocol::Pong => Ok(ControlPacket::PongPacket(PongPacket::new(buffer)?)),
Protocol::PunchRequest => Ok(ControlPacket::PunchRequest), Protocol::PunchRequest => Ok(ControlPacket::PunchRequest),
Protocol::PunchResponse => Ok(ControlPacket::PunchResponse), Protocol::PunchResponse => Ok(ControlPacket::PunchResponse),
Protocol::UnKnow(_) => Err(io::Error::new(io::ErrorKind::InvalidData, "Unsupported")), Protocol::Unknown(_) => Err(io::Error::new(io::ErrorKind::InvalidData, "Unsupported")),
} }
} }
} }
/// 网络探针 /// 网络探针
#[derive(Copy, Clone)]
pub struct PingPacket<B> { pub struct PingPacket<B> {
buffer: B, buffer: B,
} }
type PongPacket<B> = PingPacket<B>; pub type PongPacket<B> = PingPacket<B>;
impl<B: AsRef<[u8]>> PingPacket<B> { impl<B: AsRef<[u8]>> PingPacket<B> {
pub fn new(buffer: B) -> io::Result<PingPacket<B>> { pub fn new(buffer: B) -> io::Result<PingPacket<B>> {
+105
View File
@@ -0,0 +1,105 @@
use std::io;
use std::net::Ipv4Addr;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Protocol {
Icmp,
Igmp,
Ipv4,
Ipv4Broadcast,
Unknown(u8),
}
impl From<u8> for Protocol {
fn from(value: u8) -> Self {
match value {
1 => Protocol::Icmp,
2 => Protocol::Igmp,
4 => Protocol::Ipv4,
201 => Protocol::Ipv4Broadcast,
val => Protocol::Unknown(val),
}
}
}
impl Into<u8> for Protocol {
fn into(self) -> u8 {
match self {
Protocol::Icmp => 1,
Protocol::Igmp => 2,
Protocol::Ipv4 => 4,
Protocol::Ipv4Broadcast => 201,
Protocol::Unknown(val) => val,
}
}
}
pub struct BroadcastPacketEnd<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
pub fn unchecked(buffer: B) -> Self {
Self { buffer }
}
pub fn new(buffer: B) -> io::Result<Self> {
let len = buffer.as_ref().len();
let packet = Self::unchecked(buffer);
if len < 1 || packet.len() != len {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"InvalidData",
))
} else {
Ok(packet)
}
}
}
impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
pub fn len(&self) -> usize {
1 + self.num() as usize * 4
}
pub fn num(&self) -> u8 {
let len = self.buffer.as_ref().len();
self.buffer.as_ref()[len - 1]
}
/// 已经发送给了这些地址
/// 从尾往头拿
pub fn addresses(&self) -> Vec<Ipv4Addr> {
let num = self.num() as usize;
let mut list = Vec::with_capacity(num);
let buf = self.buffer.as_ref();
let mut offset = buf.len() + 4 - 2;
for _ in 0..num {
offset -= 4;
list.push(Ipv4Addr::new(buf[offset - 3], buf[offset - 2], buf[offset - 1], buf[offset]));
}
list
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> BroadcastPacketEnd<B> {
/// 从头往尾放
pub fn set_address(&mut self, addr: &[Ipv4Addr]) -> io::Result<()> {
let buf = self.buffer.as_mut();
if buf.len() < 1 + addr.len() * 4 || addr.len() > u8::MAX as usize {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"InvalidData",
))
} else {
let mut offset = 0;
for ip in addr {
buf[offset..offset + 4].copy_from_slice(&ip.octets());
offset += 4;
}
self.buffer.as_mut()[offset] = addr.len() as u8;
Ok(())
}
}
}
+23 -8
View File
@@ -5,7 +5,7 @@ use std::{fmt, io};
0 15 31 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 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 版本(8) | 协议(8) | 上层协议(8) | 初始ttl(4) | 生存时间(4) | | p|unused| 版本(4) | 协议(8) | 上层协议(8) | 初始ttl(4) | 生存时间(4) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源ip地址(32) | | 源ip地址(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -18,7 +18,8 @@ use std::{fmt, io};
pub mod control_packet; pub mod control_packet;
pub mod error_packet; pub mod error_packet;
pub mod service_packet; pub mod service_packet;
pub mod turn_packet; pub mod ip_turn_packet;
pub mod other_turn_packet;
#[derive(Eq, PartialEq, Copy, Clone, Debug)] #[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Version { pub enum Version {
@@ -52,8 +53,8 @@ pub enum Protocol {
Error, Error,
/// 控制协议 /// 控制协议
Control, Control,
/// 转发ipv4数据 /// 转发ip数据
Ipv4Turn, IpTurn,
/// 转发其他数据 /// 转发其他数据
OtherTurn, OtherTurn,
UnKnow(u8), UnKnow(u8),
@@ -65,7 +66,7 @@ impl From<u8> for Protocol {
1 => Protocol::Service, 1 => Protocol::Service,
2 => Protocol::Error, 2 => Protocol::Error,
3 => Protocol::Control, 3 => Protocol::Control,
4 => Protocol::Ipv4Turn, 4 => Protocol::IpTurn,
5 => Protocol::OtherTurn, 5 => Protocol::OtherTurn,
val => Protocol::UnKnow(val), val => Protocol::UnKnow(val),
} }
@@ -78,7 +79,7 @@ impl Into<u8> for Protocol {
Protocol::Service => 1, Protocol::Service => 1,
Protocol::Error => 2, Protocol::Error => 2,
Protocol::Control => 3, Protocol::Control => 3,
Protocol::Ipv4Turn => 4, Protocol::IpTurn => 4,
Protocol::OtherTurn => 5, Protocol::OtherTurn => 5,
Protocol::UnKnow(val) => val, Protocol::UnKnow(val) => val,
} }
@@ -114,8 +115,11 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
} }
impl<B: AsRef<[u8]>> NetPacket<B> { impl<B: AsRef<[u8]>> NetPacket<B> {
pub fn is_encrypt(&self) -> bool {
self.buffer.as_ref()[0] & 0x80 == 0x80
}
pub fn version(&self) -> Version { pub fn version(&self) -> Version {
Version::from(self.buffer.as_ref()[0]) Version::from(self.buffer.as_ref()[0] & 0x0F)
} }
pub fn protocol(&self) -> Protocol { pub fn protocol(&self) -> Protocol {
Protocol::from(self.buffer.as_ref()[1]) Protocol::from(self.buffer.as_ref()[1])
@@ -143,8 +147,19 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
} }
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> { impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
pub fn buffer_mut(&mut self) -> &mut [u8] {
self.buffer.as_mut()
}
pub fn set_encrypt_flag(&mut self, is_encrypt: bool) {
if is_encrypt {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x80
} else {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0x7F
};
}
pub fn set_version(&mut self, version: Version) { pub fn set_version(&mut self, version: Version) {
self.buffer.as_mut()[0] = version.into(); let v: u8 = version.into();
self.buffer.as_mut()[0] = (self.buffer.as_ref()[0] & 0xF0) | (0x0F & v);
} }
pub fn set_protocol(&mut self, protocol: Protocol) { pub fn set_protocol(&mut self, protocol: Protocol) {
self.buffer.as_mut()[1] = protocol.into(); self.buffer.as_mut()[1] = protocol.into();
@@ -1,14 +1,14 @@
#[derive(Copy, Clone, Eq, PartialEq, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Protocol { pub enum Protocol {
Punch, Punch,
UnKnow(u8), Unknown(u8),
} }
impl From<u8> for Protocol { impl From<u8> for Protocol {
fn from(value: u8) -> Self { fn from(value: u8) -> Self {
match value { match value {
1 => Protocol::Punch, 1 => Protocol::Punch,
val => Protocol::UnKnow(val), val => Protocol::Unknown(val),
} }
} }
} }
@@ -17,7 +17,7 @@ impl Into<u8> for Protocol {
fn into(self) -> u8 { fn into(self) -> u8 {
match self { match self {
Protocol::Punch => 1, Protocol::Punch => 1,
Protocol::UnKnow(val) => val, Protocol::Unknown(val) => val,
} }
} }
} }
+3 -3
View File
@@ -8,7 +8,7 @@ pub enum Protocol {
PollDeviceList, PollDeviceList,
/// 推送设备列表 /// 推送设备列表
PushDeviceList, PushDeviceList,
UnKnow(u8), Unknown(u8),
} }
impl From<u8> for Protocol { impl From<u8> for Protocol {
@@ -18,7 +18,7 @@ impl From<u8> for Protocol {
2 => Self::RegistrationResponse, 2 => Self::RegistrationResponse,
3 => Self::PollDeviceList, 3 => Self::PollDeviceList,
4 => Self::PushDeviceList, 4 => Self::PushDeviceList,
val => Self::UnKnow(val), val => Self::Unknown(val),
} }
} }
} }
@@ -30,7 +30,7 @@ impl Into<u8> for Protocol {
Self::RegistrationResponse => 2, Self::RegistrationResponse => 2,
Self::PollDeviceList => 3, Self::PollDeviceList => 3,
Self::PushDeviceList => 4, Self::PushDeviceList => 4,
Self::UnKnow(val) => val, Self::Unknown(val) => val,
} }
} }
} }
-58
View File
@@ -1,58 +0,0 @@
use crate::tun_device::{TunReader, TunWriter};
pub type TapReader = TunReader;
pub type TapWriter = TunWriter;
use std::net::Ipv4Addr;
use std::sync::Arc;
use tun::Device;
use parking_lot::Mutex;
use std::io;
pub fn create_tap(
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
) -> io::Result<(TunWriter, TunReader, [u8; 6])> {
println!("========TAP网卡配置========");
let mut config = tun::Configuration::default();
config
.destination(gateway)
.address(address)
.netmask(netmask)
.mtu(1420)
.layer(tun::Layer::L2)
// .queues(2) 用多个队列有兼容性问题
.up();
let dev = tun::create(&config).unwrap();
let name = dev.name();
println!("name:{:?}", name);
let packet_information = dev.has_packet_information();
let queue = dev.queue(0).unwrap();
let reader = queue.reader();
let writer = queue.writer();
let get_mac_cmd = format!("cat /sys/class/net/{}/address", name);
let mac_out = std::process::Command::new("sh")
.arg("-c")
.arg(get_mac_cmd)
.output()
.expect("sh exec error!");
if !mac_out.status.success() {
return Err(io::Error::new(io::ErrorKind::Other, format!("获取mac地址错误: {:?}", mac_out)));
}
let mac_str = String::from_utf8(mac_out.stdout).unwrap();
let mut mac = [0; 6];
let mut split = mac_str.split(":");
for i in 0..6 {
mac[i] = u8::from_str_radix(&split.next().unwrap()[..2], 16).unwrap();
}
println!("mac:{:?}", mac);
println!("========TAP网卡配置========");
Ok((
TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))),
TunReader(reader, packet_information),
mac
))
}
-13
View File
@@ -1,13 +0,0 @@
use crate::tun_device::{TunReader, TunWriter};
pub type TapReader = TunReader;
pub type TapWriter = TunWriter;
use std::net::Ipv4Addr;
pub fn create_tap(
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
) -> crate::error::Result<(TapWriter, TapReader, [u8; 6])> {
unimplemented!()
}
-21
View File
@@ -1,21 +0,0 @@
#[cfg(target_os = "windows")]
mod windows;
#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux;
#[cfg(target_os = "macos")]
mod mac;
#[cfg(target_os = "macos")]
pub use mac::{TapWriter, TapReader};
#[cfg(target_os = "macos")]
pub use mac::create_tap;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub use linux::{TapWriter, TapReader};
#[cfg(any(target_os = "linux", target_os = "android"))]
pub use linux::create_tap;
#[cfg(target_os = "windows")]
pub use windows::create_tap;
#[cfg(target_os = "windows")]
pub use windows::delete_tap;
#[cfg(target_os = "windows")]
pub use windows::{TapReader, TapWriter};
-100
View File
@@ -1,100 +0,0 @@
use std::io;
use std::net::Ipv4Addr;
use std::sync::Arc;
use parking_lot::Mutex;
use win_tun_tap::{IFace, TapDevice};
#[derive(Clone)]
pub struct TapWriter(Arc<TapDevice>, Arc<Mutex<()>>);
impl TapWriter {
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
pub fn change_ip(
&self,
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
old_netmask: Ipv4Addr,
old_gateway: Ipv4Addr,
) -> io::Result<()> {
if let Err(e) =
self.0.delete_route(dest(old_gateway, old_gateway), old_netmask, old_gateway)
{
log::warn!("{:?}", e);
}
self.0.set_ip(address, netmask)?;
self.0.add_route(dest(gateway, netmask), netmask, gateway)
}
pub fn close(&self) -> io::Result<()> {
self.0.shutdown()
}
}
fn dest(ip: Ipv4Addr, mask: Ipv4Addr) -> Ipv4Addr {
let ip = ip.octets();
let mask = mask.octets();
Ipv4Addr::from([
ip[0] & mask[0],
ip[1] & mask[1],
ip[2] & mask[2],
ip[3] & mask[3],
])
}
#[derive(Clone)]
pub struct TapReader(Arc<TapDevice>);
impl TapReader {
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
}
pub const TAP_INTERFACE_NAME: &str = "Switch-Tap-V1";
pub fn create_tap(
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
) -> io::Result<(TapWriter, TapReader, [u8; 6])> {
println!("========TAP网卡配置========");
let tap_device = match TapDevice::open(TAP_INTERFACE_NAME) {
Ok(tap_device) => tap_device,
Err(e) => {
log::warn!("{:?}", e);
let tap_device = TapDevice::create()?;
tap_device.set_name(TAP_INTERFACE_NAME)?;
tap_device
}
};
let mac = tap_device.get_mac()?;
println!("name:{:?}", tap_device.get_name()?);
println!("version:{:x?}", tap_device.get_version()?);
println!("mac:{:x?}", mac);
tap_device.set_ip(address, netmask)?;
tap_device.set_mtu(1420)?;
tap_device.set_status(true)?;
tap_device.add_route(address, netmask, gateway)?;
let tap = Arc::new(tap_device);
println!("========TAP网卡配置========");
Ok((
TapWriter(tap.clone(), Arc::default()),
TapReader(tap),
mac
))
}
pub fn delete_tap() {
let tap_device = match TapDevice::open(TAP_INTERFACE_NAME) {
Ok(tap_device) => tap_device,
Err(_) => {
return;
}
};
let _ = tap_device.delete();
}
-57
View File
@@ -1,57 +0,0 @@
use std::io;
use crate::tun_device::{TunReader, TunWriter};
use std::net::Ipv4Addr;
use std::sync::Arc;
use tun::Device;
use parking_lot::Mutex;
use std::process::Command;
pub fn create_tun(
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
) -> crate::error::Result<(TunWriter, TunReader)> {
println!("========TUN网卡配置========");
let mut config = tun::Configuration::default();
config
.destination(gateway)
.address(address)
.netmask(netmask)
.mtu(1420)
// .queues(2) 用多个队列有兼容性问题
.up();
let dev = tun::create(&config).unwrap();
let packet_information = dev.has_packet_information();
let queue = dev.queue(0).unwrap();
let reader = queue.reader();
let writer = queue.writer();
let name = dev.name();
println!("name:{:?}", name);
for (address, netmask) in in_ips {
add_route(name, address, netmask)?;
}
println!("========TUN网卡配置========");
Ok((
TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))),
TunReader(reader, packet_information),
))
}
fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
let route_add_str: String = format!(
"ip route add {:?}/{:?} dev {}",
address, netmask, name
);
let route_add_out = Command::new("sh")
.arg("-c")
.arg(route_add_str)
.output()
.expect("sh exec error!");
if !route_add_out.status.success() {
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: {:?}", route_add_out)));
}
Ok(())
}
-72
View File
@@ -1,72 +0,0 @@
use std::net::Ipv4Addr;
use std::process::Command;
use std::io;
use tun::Device;
use parking_lot::Mutex;
use std::sync::Arc;
use crate::tun_device::{TunReader, TunWriter};
pub fn create_tun(
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
) -> crate::error::Result<(TunWriter, TunReader)> {
println!("========TUN网卡配置========");
let mut config = tun::Configuration::default();
config
.destination(gateway)
.address(address)
.netmask(netmask)
.mtu(1420)
.up();
let dev = tun::create(&config).unwrap();
let name = dev.name();
config_ip(name, address, netmask, gateway)?;
add_route(name, address, netmask)?;
for (address, netmask) in in_ips {
add_route(name, address, netmask)?;
}
let packet_information = dev.has_packet_information();
let queue = dev.queue(0).unwrap();
let reader = queue.reader();
let writer = queue.writer();
println!("name:{:?}", name);
println!("========TUN网卡配置========");
Ok((
TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))),
TunReader(reader, packet_information),
))
}
fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
let route_add_str: String = format!(
"sudo route -n add -net {:?}/{:?} -interface {}",
address, netmask, name
);
let route_add_out = Command::new("sh")
.arg("-c")
.arg(route_add_str)
.output()
.expect("sh exec error!");
if !route_add_out.status.success() {
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: {:?}", route_add_out)));
}
Ok(())
}
pub(crate) fn config_ip(name: &str, address: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
let up_eth_str: String = format!("ifconfig {} {:?} {:?} up ", name, address, gateway);
let up_eth_out = Command::new("sh")
.arg("-c")
.arg(up_eth_str)
.output()
.expect("sh exec error!");
if !up_eth_out.status.success() {
return Err(io::Error::new(io::ErrorKind::Other, format!("设置网络地址失败: {:?}", up_eth_out)));
}
Ok(())
}
-21
View File
@@ -1,21 +0,0 @@
#[cfg(any(target_os = "linux", target_os = "android"))]
pub use linux::create_tun;
#[cfg(target_os = "macos")]
pub use mac::create_tun;
#[cfg(any(unix))]
pub use unix::{TunReader, TunWriter};
#[cfg(target_os = "windows")]
pub use windows::create_tun;
#[cfg(target_os = "windows")]
pub use windows::delete_tun;
#[cfg(target_os = "windows")]
pub use windows::{TunReader, TunWriter};
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod linux;
#[cfg(target_os = "macos")]
pub mod mac;
#[cfg(any(unix))]
pub mod unix;
#[cfg(target_os = "windows")]
pub mod windows;
-72
View File
@@ -1,72 +0,0 @@
use std::io;
use std::sync::Arc;
use bytes::BufMut;
use tun::platform::posix::{Reader, Writer};
use std::net::Ipv4Addr;
use std::os::unix::io::AsRawFd;
#[cfg(any(target_os = "linux", target_os = "android"))]
use tun::platform::linux::Device;
#[cfg(any(target_os = "macos", target_os = "ios"))]
use tun::platform::macos::Device;
use parking_lot::Mutex;
#[derive(Clone)]
pub struct TunReader(pub(crate) Reader, pub(crate) bool);
impl TunReader {
pub fn read(&self, buf: & mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
}
#[derive(Clone)]
pub struct TunWriter(pub(crate) Writer, pub(crate) bool, pub(crate) Arc<Mutex<Device>>);
impl TunWriter {
pub fn write(&self, packet: &[u8]) -> io::Result<()> {
if self.1 {
let mut buf = Vec::<u8>::with_capacity(4 + packet.len());
buf.put_u16(0);
#[cfg(any(target_os = "macos", target_os = "ios"))]
buf.put_u16(libc::PF_INET as u16);
#[cfg(any(target_os = "linux", target_os = "android"))]
buf.put_u16(libc::ETH_P_IP as u16);
buf.extend_from_slice(packet);
self.0.write_all(&buf)
} else {
self.0.write_all(packet)
}
}
pub fn close(&self) -> io::Result<()>{
unsafe {
let raw = self.0.as_raw_fd();
if raw >= 0 {
libc::close(raw);
}
}
Ok(())
}
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> {
let mut config = tun::Configuration::default();
use tun::Device;
config
.destination(gateway)
.address(address)
.netmask(netmask)
.mtu(1420)
// .queues(2)
.up();
let mut dev = self.2.lock();
if let Err(e) = dev.configure(&config) {
return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)));
}
#[cfg(target_os = "macos")]
if let Err(e) = crate::tun_device::mac::config_ip(dev.name(), address, netmask, gateway){
log::error!("{}",e);
}
return Ok(());
}
}
-149
View File
@@ -1,149 +0,0 @@
use std::{io, thread};
use std::net::Ipv4Addr;
use std::sync::Arc;
use std::time::Duration;
use libloading::Library;
use parking_lot::Mutex;
use win_tun_tap::{IFace, TunDevice};
use win_tun_tap::packet::TunPacket;
pub const TUN_INTERFACE_NAME: &str = "Switch-V1";
pub const TUN_POOL_NAME: &str = "Switch-V1";
#[derive(Clone)]
pub struct TunWriter(Arc<TunDevice>, Arc<Mutex<()>>);
impl TunWriter {
pub fn write(&self, buf: &[u8]) -> io::Result<()> {
let mut packet = self.0.allocate_send_packet(buf.len() as u16)?;
packet.bytes_mut().copy_from_slice(buf);
self.0.send_packet(packet);
return Ok(());
}
pub fn change_ip(
&self,
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
old_netmask: Ipv4Addr,
old_gateway: Ipv4Addr,
) -> io::Result<()> {
if let Err(e) =
self.0.delete_route(dest(old_gateway, old_gateway), old_netmask, old_gateway)
{
log::warn!("{:?}", e);
}
self.0.set_ip(address, netmask)?;
self.0.add_route(dest(gateway, netmask), netmask, gateway)
}
pub fn close(&self) -> io::Result<()> {
self.0.shutdown()
}
}
fn dest(ip: Ipv4Addr, mask: Ipv4Addr) -> Ipv4Addr {
let ip = ip.octets();
let mask = mask.octets();
Ipv4Addr::from([
ip[0] & mask[0],
ip[1] & mask[1],
ip[2] & mask[2],
ip[3] & mask[3],
])
}
#[derive(Clone)]
pub struct TunReader(Arc<TunDevice>);
impl TunReader {
pub fn next(&self) -> io::Result<TunPacket> {
self.0.receive_blocking()
}
}
pub fn create_tun(
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
in_ips:Vec<(Ipv4Addr,Ipv4Addr)>
) -> io::Result<(TunWriter, TunReader)> {
unsafe {
println!("========TUN网卡配置========");
match Library::new("wintun.dll") {
Ok(lib) => match TunDevice::open(lib, TUN_INTERFACE_NAME) {
Ok(tun_device) => {
let _ = tun_device.delete();
thread::sleep(Duration::from_millis(5));
}
Err(_) => {}
},
Err(e) => {
log::error!("wintun.dll not found");
return Err(io::Error::new(
io::ErrorKind::Other,
format!("wintun.dll not found {:?}", e),
));
}
}
let tun_device = match TunDevice::create(
Library::new("wintun.dll").unwrap(),
TUN_POOL_NAME,
TUN_INTERFACE_NAME,
) {
Ok(tun_device) => tun_device,
Err(_) => {
thread::sleep(Duration::from_millis(200));
match TunDevice::create(
Library::new("wintun.dll").unwrap(),
TUN_POOL_NAME,
TUN_INTERFACE_NAME,
) {
Ok(tun_device) => tun_device,
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("{:?}", e),
));
}
}
}
};
println!("name:{:?}", tun_device.get_name()?);
println!("version:{:?}", tun_device.version()?);
log::error!("创建tun成功 {:?}",tun_device.get_name()?);
tun_device.set_ip(address, netmask)?;
tun_device.set_mtu(1420)?;
for (address, netmask) in in_ips {
tun_device.add_route(address, netmask, gateway)?;
}
tun_device.add_route(address, netmask, gateway)?;
let device = Arc::new(tun_device);
println!("========TUN网卡配置========");
Ok((
TunWriter(device.clone(), Arc::default()),
TunReader(device),
))
}
}
pub fn delete_tun() {
unsafe {
match Library::new("wintun.dll") {
Ok(lib) => match TunDevice::open(lib, TUN_INTERFACE_NAME) {
Ok(tun_device) => {
let _ = tun_device.delete();
}
Err(_) => {}
},
Err(_) => {}
}
}
}
+121
View File
@@ -0,0 +1,121 @@
use std::io;
use std::net::Ipv4Addr;
use crate::tun_tap_device::{DeviceReader, DeviceType, DeviceWriter};
use tun::Device;
use parking_lot::Mutex;
use std::process::Command;
use std::sync::Arc;
use crate::tun_tap_device::unix::DeviceW;
impl DeviceWriter {
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> {
let mut config = tun::Configuration::default();
config
.destination(gateway)
.address(address)
.netmask(netmask)
.mtu(1420)
// .queues(2)
.up();
let mut dev = self.lock.lock();
if let Err(e) = dev.configure(&config) {
return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)));
}
let name = dev.name();
for (address, netmask) in &self.in_ips {
add_route(name, *address, *netmask)?;
}
// 当前网段路由
// add_route(name, address, netmask)?;
// 广播和组播路由
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
return Ok(());
}
}
pub fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
let route_add_str: String = format!(
"ip route add {:?}/{:?} dev {}",
address, netmask, name
);
let route_add_out = Command::new("sh")
.arg("-c")
.arg(&route_add_str)
.output()
.expect("sh exec error!");
if !route_add_out.status.success() {
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: cmd:{},out:{:?}", route_add_str, route_add_out)));
}
Ok(())
}
pub fn create_device(device_type: DeviceType,
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
) -> io::Result<(DeviceWriter, DeviceReader)> {
println!("========网卡配置========");
let mut config = tun::Configuration::default();
config
.destination(gateway)
.address(address)
.netmask(netmask)
.mtu(1420)
// .queues(2) 用多个队列有兼容性问题
.up();
match device_type {
DeviceType::Tun => {}
DeviceType::Tap => {
config.layer(tun::Layer::L2);
}
}
let dev = tun::create(&config).unwrap();
let packet_information = dev.has_packet_information();
let queue = dev.queue(0).unwrap();
let reader = queue.reader();
let writer = queue.writer();
let name = dev.name();
println!("name:{:?}", name);
for (address, netmask) in &in_ips {
add_route(name, *address, *netmask)?;
}
// 当前网段路由
// add_route(name, address, netmask)?;
// 广播和组播路由
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
let device_w = match device_type {
DeviceType::Tun => {
DeviceW::Tun(writer)
}
DeviceType::Tap => {
let get_mac_cmd = format!("cat /sys/class/net/{}/address", name);
let mac_out = Command::new("sh")
.arg("-c")
.arg(get_mac_cmd)
.output()
.expect("sh exec error!");
if !mac_out.status.success() {
return Err(io::Error::new(io::ErrorKind::Other, format!("获取mac地址错误: {:?}", mac_out)));
}
let mac_str = String::from_utf8(mac_out.stdout).unwrap();
let mut mac = [0; 6];
let mut split = mac_str.split(":");
for i in 0..6 {
mac[i] = u8::from_str_radix(&split.next().unwrap()[..2], 16).unwrap();
}
DeviceW::Tap((writer, mac))
}
};
println!("========TUN网卡配置========");
Ok((
DeviceWriter::new(device_w, Arc::new(Mutex::new(dev)), in_ips, address, packet_information),
DeviceReader::new(reader),
))
}
pub fn delete_device(_device_type: DeviceType) {}
+114
View File
@@ -0,0 +1,114 @@
use std::io;
use std::net::Ipv4Addr;
use crate::tun_tap_device::{DeviceReader, DeviceType, DeviceWriter};
use tun::Device;
use parking_lot::Mutex;
use std::process::Command;
use std::sync::Arc;
use crate::tun_tap_device::unix::DeviceW;
impl DeviceWriter {
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> {
let mut config = tun::Configuration::default();
config
.destination(gateway)
.address(address)
.netmask(netmask)
.mtu(1420)
.up();
let mut dev = self.lock.lock();
if let Err(e) = dev.configure(&config) {
return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)));
}
if let Err(e) = config_ip(dev.name(), address, netmask, gateway) {
log::error!("{}",e);
}
let name = dev.name();
for (address, netmask) in &self.in_ips {
add_route(name, *address, *netmask)?;
}
// 当前网段路由
add_route(name, address, netmask)?;
// 广播和组播路由
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
return Ok(());
}
}
pub fn create_device(device_type: DeviceType,
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
) -> io::Result<(DeviceWriter, DeviceReader)> {
match device_type {
DeviceType::Tun => {}
DeviceType::Tap => {
unimplemented!()
}
}
println!("========TUN网卡配置========");
let mut config = tun::Configuration::default();
config
.destination(gateway)
.address(address)
.netmask(netmask)
.mtu(1420)
.up();
let dev = tun::create(&config).unwrap();
let name = dev.name();
config_ip(name, address, netmask, gateway)?;
for (address, netmask) in &in_ips {
add_route(name, *address, *netmask)?;
}
// 当前网段路由
add_route(name, address, netmask)?;
// 广播和组播路由
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
let packet_information = dev.has_packet_information();
let queue = dev.queue(0).unwrap();
let reader = queue.reader();
let writer = queue.writer();
println!("name:{:?}", name);
println!("========TUN网卡配置========");
Ok((
DeviceWriter::new(DeviceW::Tun(writer), Arc::new(Mutex::new(dev)), in_ips, address, packet_information),
DeviceReader::new(reader),
))
}
fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
let route_add_str: String = format!(
"sudo route -n add -net {:?}/{:?} -interface {}",
address, netmask, name
);
let route_add_out = Command::new("sh")
.arg("-c")
.arg(&route_add_str)
.output()
.expect("sh exec error!");
if !route_add_out.status.success() {
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: cmd:{},out:{:?}", route_add_str, route_add_out)));
}
Ok(())
}
fn config_ip(name: &str, address: Ipv4Addr, _netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
let up_eth_str: String = format!("ifconfig {} {:?} {:?} up ", name, address, gateway);
let up_eth_out = Command::new("sh")
.arg("-c")
.arg(&up_eth_str)
.output()
.expect("sh exec error!");
if !up_eth_out.status.success() {
return Err(io::Error::new(io::ErrorKind::Other, format!("设置网络地址失败: cmd:{},out:{:?}", up_eth_str, up_eth_out)));
}
Ok(())
}
pub fn delete_device(_device_type: DeviceType) {}
+32
View File
@@ -0,0 +1,32 @@
#[cfg(target_os = "windows")]
pub mod windows;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod linux;
#[cfg(target_os = "macos")]
pub mod mac;
#[cfg(any(unix))]
pub mod unix;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub use linux::create_device;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub use linux::delete_device;
#[cfg(any(unix))]
pub use unix::{DeviceWriter, DeviceReader};
#[cfg(target_os = "macos")]
pub use mac::create_device;
#[cfg(target_os = "macos")]
pub use mac::delete_device;
#[cfg(target_os = "windows")]
pub use windows::create_device;
#[cfg(target_os = "windows")]
pub use windows::delete_device;
#[cfg(target_os = "windows")]
pub use windows::{DeviceWriter, DeviceReader};
pub enum DeviceType {
Tun,
Tap,
}
+144
View File
@@ -0,0 +1,144 @@
use std::io;
use std::sync::Arc;
use bytes::BufMut;
use tun::platform::posix::{Reader, Writer};
use std::net::Ipv4Addr;
use std::os::unix::io::AsRawFd;
use crossbeam::atomic::AtomicCell;
#[cfg(any(target_os = "linux", target_os = "android"))]
use tun::platform::linux::Device;
#[cfg(any(target_os = "macos", target_os = "ios"))]
use tun::platform::macos::Device;
use parking_lot::Mutex;
use packet::ethernet;
use packet::ethernet::packet::EthernetPacket;
#[derive(Clone)]
pub enum DeviceW {
Tun(Writer),
Tap((Writer, [u8; 6])),
}
impl DeviceW {
pub fn is_tun(&self) -> bool {
match self {
DeviceW::Tun(_) => {
true
}
DeviceW::Tap(_) => {
false
}
}
}
}
#[derive(Clone)]
pub struct DeviceWriter {
writer: DeviceW,
pub lock: Arc<Mutex<Device>>,
pub in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
ip: Arc<AtomicCell<Ipv4Addr>>,
packet_information: bool,
}
impl DeviceWriter {
pub fn new(writer: DeviceW,lock: Arc<Mutex<Device>>, in_ips: Vec<(Ipv4Addr, Ipv4Addr)>, ip: Ipv4Addr, packet_information: bool) -> Self {
Self {
writer,
lock,
in_ips,
ip: Arc::new(AtomicCell::new(ip)),
packet_information,
}
}
}
impl DeviceWriter {
pub fn write(packet_information: bool, writer: &Writer, packet: &[u8]) -> io::Result<()> {
if packet_information {
let mut buf = Vec::<u8>::with_capacity(4 + packet.len());
buf.put_u16(0);
#[cfg(any(target_os = "macos", target_os = "ios"))]
buf.put_u16(libc::PF_INET as u16);
#[cfg(any(target_os = "linux", target_os = "android"))]
buf.put_u16(libc::ETH_P_IP as u16);
buf.extend_from_slice(packet);
writer.write_all(&buf)
} else {
writer.write_all(packet)
}
}
///tun网卡写入ipv4数据
pub fn write_ipv4_tun(&self, buf: &[u8]) -> io::Result<()> {
match &self.writer {
DeviceW::Tun(writer) => {
Self::write(self.packet_information, writer, buf)
}
DeviceW::Tap(_) => {
Err(io::Error::from(io::ErrorKind::Unsupported))
}
}
}
/// tap网卡写入以太网帧
pub fn write_ethernet_tap(&self, buf: &[u8]) -> io::Result<()> {
match &self.writer {
DeviceW::Tun(_) => {
Err(io::Error::from(io::ErrorKind::Unsupported))
}
DeviceW::Tap((writer, _)) => {
Self::write(self.packet_information, writer, buf)
}
}
}
///写入ipv4数据,头部必须留14字节,给tap写入以太网帧头
pub fn write_ipv4(&self, buf: &mut [u8]) -> io::Result<()> {
match &self.writer {
DeviceW::Tun(writer) => {
Self::write(self.packet_information, writer, &buf[14..])
}
DeviceW::Tap((writer, mac)) => {
let source_mac = [buf[14 + 12], buf[14 + 13], buf[14 + 14], buf[14 + 15], !mac[5], 234];
let mut ethernet_packet = EthernetPacket::unchecked(buf);
ethernet_packet.set_source(&source_mac);
ethernet_packet.set_destination(mac);
ethernet_packet.set_protocol(ethernet::protocol::Protocol::Ipv4);
Self::write(self.packet_information, writer, &ethernet_packet.buffer)
}
}
}
pub fn ip(&self) -> Ipv4Addr {
self.ip.load()
}
pub fn close(&self) -> io::Result<()> {
unsafe {
match &self.writer {
DeviceW::Tun(writer) => {
libc::close(writer.as_raw_fd());
}
DeviceW::Tap((writer, _)) => {
libc::close(writer.as_raw_fd());
}
}
}
Ok(())
}
pub fn is_tun(&self) -> bool {
self.writer.is_tun()
}
}
#[derive(Clone)]
pub struct DeviceReader(Reader);
impl DeviceReader {
pub fn new(device: Reader) -> Self {
DeviceReader(device)
}
}
impl DeviceReader {
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
}
+365
View File
@@ -0,0 +1,365 @@
use std::{io, thread};
use std::net::Ipv4Addr;
use std::sync::Arc;
use std::time::Duration;
use crossbeam::atomic::AtomicCell;
use libloading::Library;
use parking_lot::Mutex;
use packet::ethernet;
use packet::ethernet::packet::EthernetPacket;
use win_tun_tap::{IFace, TapDevice, TunDevice};
use crate::tun_tap_device::DeviceType;
pub const TUN_INTERFACE_NAME: &str = "Switch-Tun-V1";
pub const TUN_POOL_NAME: &str = "Switch-Tun-V1";
pub const TAP_INTERFACE_NAME: &str = "Switch-Tap-V1";
pub enum Device {
Tun(TunDevice),
Tap((TapDevice, [u8; 6])),
}
impl Device {
pub fn is_tun(&self) -> bool {
match self {
Device::Tun(_) => {
true
}
Device::Tap(_) => {
false
}
}
}
}
#[derive(Clone)]
pub struct DeviceWriter {
device: Arc<Device>,
lock: Arc<Mutex<()>>,
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
ip: Arc<AtomicCell<Ipv4Addr>>,
}
impl DeviceWriter {
pub fn new(device: Arc<Device>, in_ips: Vec<(Ipv4Addr, Ipv4Addr)>, ip: Ipv4Addr) -> Self {
Self {
device,
lock: Arc::new(Default::default()),
in_ips,
ip: Arc::new(AtomicCell::new(ip)),
}
}
}
impl DeviceWriter {
///tun网卡写入ipv4数据
pub fn write_ipv4_tun(&self, buf: &[u8]) -> io::Result<()> {
match self.device.as_ref() {
Device::Tun(dev) => {
let mut packet = dev.allocate_send_packet(buf.len() as u16)?;
packet.bytes_mut().copy_from_slice(buf);
dev.send_packet(packet);
Ok(())
}
Device::Tap(_) => {
Err(io::Error::from(io::ErrorKind::Unsupported))
}
}
}
/// tap网卡写入以太网帧
pub fn write_ethernet_tap(&self, buf: &[u8]) -> io::Result<()> {
match self.device.as_ref() {
Device::Tun(_) => {
Err(io::Error::from(io::ErrorKind::Unsupported))
}
Device::Tap((dev, _)) => {
dev.write(buf)?;
Ok(())
}
}
}
///写入ipv4数据,头部必须留14字节,给tap写入以太网帧头
pub fn write_ipv4(&self, buf: &mut [u8]) -> io::Result<()> {
match self.device.as_ref() {
Device::Tun(dev) => {
let mut packet = dev.allocate_send_packet((buf.len() - 14) as u16)?;
packet.bytes_mut().copy_from_slice(&buf[14..]);
dev.send_packet(packet);
}
Device::Tap((dev, mac)) => {
let source_mac = [buf[14 + 12], buf[14 + 13], buf[14 + 14], buf[14 + 15], !mac[5], 234];
let mut ethernet_packet = EthernetPacket::unchecked(buf);
ethernet_packet.set_source(&source_mac);
ethernet_packet.set_destination(mac);
ethernet_packet.set_protocol(ethernet::protocol::Protocol::Ipv4);
dev.write(&ethernet_packet.buffer)?;
}
}
Ok(())
}
pub fn change_ip(
&self,
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
old_netmask: Ipv4Addr,
old_gateway: Ipv4Addr,
) -> io::Result<()> {
let _guard = self.lock.lock();
let dev: &dyn IFace = match self.device.as_ref() {
Device::Tun(dev) => {
dev as &dyn IFace
}
Device::Tap((dev, _)) => {
dev as &dyn IFace
}
};
if let Err(e) =
dev.delete_route(dest(old_gateway, old_gateway), old_netmask, old_gateway)
{
log::warn!("{:?}", e);
}
dev.set_ip(address, netmask)?;
self.ip.store(address);
for (address, netmask) in &self.in_ips {
dev.add_route(*address, *netmask, gateway, 1)?;
}
// 当前网段路由
dev.add_route(address, netmask, gateway, 1)?;
// 广播和组播路由
dev.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
dev.add_route(Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]), gateway, 1)?;
delete_cache();
Ok(())
}
pub fn ip(&self) -> Ipv4Addr {
self.ip.load()
}
pub fn close(&self) -> io::Result<()> {
match self.device.as_ref() {
Device::Tun(dev) => {
dev.shutdown()
}
Device::Tap((dev, _)) => {
dev.shutdown()
}
}
}
pub fn is_tun(&self) -> bool {
self.device.is_tun()
}
}
fn dest(ip: Ipv4Addr, mask: Ipv4Addr) -> Ipv4Addr {
let ip = ip.octets();
let mask = mask.octets();
Ipv4Addr::from([
ip[0] & mask[0],
ip[1] & mask[1],
ip[2] & mask[2],
ip[3] & mask[3],
])
}
#[derive(Clone)]
pub struct DeviceReader {
device: Arc<Device>,
}
impl DeviceReader {
pub fn new(device: Arc<Device>) -> Self {
Self {
device,
}
}
}
impl DeviceReader {
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
match self.device.as_ref() {
Device::Tun(dev) => {
let packet = dev.receive_blocking()?;
let packet = packet.bytes();
let len = packet.len();
if len > buf.len() {
return Err(io::Error::new(io::ErrorKind::InvalidData, "data too long"));
}
buf[..len].copy_from_slice(packet);
Ok(len)
}
Device::Tap((dev, _)) => {
dev.read(buf)
}
}
}
}
fn create_tun(
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
) -> io::Result<(DeviceWriter, DeviceReader)> {
unsafe {
println!("========TUN网卡配置========");
match Library::new("wintun.dll") {
Ok(lib) => match TunDevice::delete_for_name(lib, TUN_INTERFACE_NAME) {
Ok(_) => {
thread::sleep(Duration::from_millis(5));
}
Err(_) => {}
},
Err(e) => {
log::error!("wintun.dll not found");
return Err(io::Error::new(
io::ErrorKind::Other,
format!("wintun.dll not found {:?}", e),
));
}
}
let tun_device = match TunDevice::create(
Library::new("wintun.dll").unwrap(),
TUN_POOL_NAME,
TUN_INTERFACE_NAME,
) {
Ok(tun_device) => tun_device,
Err(_) => {
thread::sleep(Duration::from_millis(200));
match TunDevice::create(
Library::new("wintun.dll").unwrap(),
TUN_POOL_NAME,
TUN_INTERFACE_NAME,
) {
Ok(tun_device) => tun_device,
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("{:?}", e),
));
}
}
}
};
println!("name:{:?}", tun_device.get_name()?);
println!("version:{:?}", tun_device.version()?);
tun_device.set_ip(address, netmask)?;
tun_device.set_metric(1)?;
tun_device.set_mtu(1420)?;
// ip代理路由
for (address, netmask) in &in_ips {
tun_device.add_route(*address, *netmask, gateway, 1)?;
}
// 当前网段路由
tun_device.add_route(address, netmask, gateway, 1)?;
// 广播和组播路由
tun_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
tun_device.add_route(Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]), gateway, 1)?;
delete_cache();
let device = Arc::new(Device::Tun(tun_device));
println!("========TUN网卡配置========");
Ok((
DeviceWriter::new(device.clone(), in_ips, address),
DeviceReader::new(device),
))
}
}
fn delete_cache(){
//清除路由缓存
let delete_cache = "netsh interface ip delete destinationcache";
let out = std::process::Command::new("cmd")
.arg("/C")
.arg(delete_cache)
.output()
.unwrap();
if !out.status.success(){
log::warn!("删除缓存失败:{:?}",out);
}
}
fn delete_tun() {
unsafe {
match Library::new("wintun.dll") {
Ok(lib) => match TunDevice::delete_for_name(lib, TUN_INTERFACE_NAME) {
Ok(_) => {}
Err(_) => {}
},
Err(_) => {}
}
}
}
fn create_tap(
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
) -> io::Result<(DeviceWriter, DeviceReader)> {
println!("========TAP网卡配置========");
let tap_device = match TapDevice::open(TAP_INTERFACE_NAME) {
Ok(tap_device) => tap_device,
Err(e) => {
log::warn!("{:?}", e);
let tap_device = TapDevice::create()?;
tap_device.set_name(TAP_INTERFACE_NAME)?;
tap_device
}
};
let mac = tap_device.get_mac()?;
println!("name:{:?}", tap_device.get_name()?);
println!("version:{:x?}", tap_device.get_version()?);
println!("mac:{:x?}", mac);
tap_device.set_ip(address, netmask)?;
tap_device.set_metric(1)?;
tap_device.set_mtu(1420)?;
tap_device.set_status(true)?;
tap_device.add_route(address, netmask, gateway, 1)?;
for (address, netmask) in &in_ips {
tap_device.add_route(*address, *netmask, gateway, 1)?;
}
// 广播和组播路由
tap_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
tap_device.add_route(Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]), gateway, 1)?;
delete_cache();
let tap = Arc::new(Device::Tap((tap_device, mac)));
println!("========TAP网卡配置========");
Ok((
DeviceWriter::new(tap.clone(), in_ips, address),
DeviceReader::new(tap)
))
}
fn delete_tap() {
let tap_device = match TapDevice::open(TAP_INTERFACE_NAME) {
Ok(tap_device) => tap_device,
Err(_) => {
return;
}
};
let _ = tap_device.delete();
}
pub fn create_device(device_type: DeviceType, address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>, ) -> io::Result<(DeviceWriter, DeviceReader)> {
match device_type {
DeviceType::Tun => {
create_tun(address, netmask, gateway, in_ips)
}
DeviceType::Tap => {
create_tap(address, netmask, gateway, in_ips)
}
}
}
pub fn delete_device(device_type: DeviceType) {
match device_type {
DeviceType::Tun => {
delete_tun()
}
DeviceType::Tap => {
delete_tap()
}
}
}
+1 -1
View File
@@ -13,7 +13,7 @@ libloading = "0.7"
widestring = "0.4" widestring = "0.4"
once_cell = "1.8" once_cell = "1.8"
itertools = "0.10.1" itertools = "0.10.1"
rand = "0.8.5"
[dependencies.winapi] [dependencies.winapi]
version = "0.3" version = "0.3"
features = [ features = [
+11 -12
View File
@@ -5,8 +5,8 @@ mod tun;
mod ffi; mod ffi;
mod netsh; mod netsh;
mod route; mod route;
use std::{io, net}; use std::{io, net};
use std::net::Ipv4Addr;
pub use tap::TapDevice; pub use tap::TapDevice;
pub use tun::*; pub use tun::*;
@@ -23,7 +23,7 @@ fn decode_utf16(string: &[u16]) -> String {
} }
pub trait IFace { pub trait IFace {
fn shutdown(&self)->io::Result<()>; fn shutdown(&self) -> io::Result<()>;
/// 获取接口索引 /// 获取接口索引
fn get_index(&self) -> io::Result<u32>; fn get_index(&self) -> io::Result<u32>;
/// 获取名称 /// 获取名称
@@ -31,18 +31,17 @@ pub trait IFace {
/// 设置名称 /// 设置名称
fn set_name(&self, new_name: &str) -> io::Result<()>; fn set_name(&self, new_name: &str) -> io::Result<()>;
/// 设置ip /// 设置ip
fn set_ip<IP>(&self, address: IP, mask: IP) -> io::Result<()> fn set_ip(&self, address: Ipv4Addr, mask: Ipv4Addr) -> io::Result<()>;
where IP: Into<net::Ipv4Addr>;
/// 设置路由 /// 设置路由
fn add_route<IP>(&self, dest: IP, fn add_route(&self, dest: Ipv4Addr,
netmask: IP, netmask: Ipv4Addr,
gateway: IP, ) -> io::Result<()> gateway: Ipv4Addr, metric: u16) -> io::Result<()>;
where IP: Into<net::Ipv4Addr>;
/// 删除路由 /// 删除路由
fn delete_route<IP>(&self, dest: IP, fn delete_route(&self, dest: Ipv4Addr,
netmask: IP, netmask: Ipv4Addr,
gateway: IP, ) -> io::Result<()> gateway: Ipv4Addr, ) -> io::Result<()>;
where IP: Into<net::Ipv4Addr>;
/// 设置最大传输单元 /// 设置最大传输单元
fn set_mtu(&self, mtu: u16) -> io::Result<()>; fn set_mtu(&self, mtu: u16) -> io::Result<()>;
/// 设置跃点
fn set_metric(&self, metric: u16) -> io::Result<()>;
} }
+12
View File
@@ -45,4 +45,16 @@ pub fn set_interface_mtu(index: u32, mtu: u16) -> io::Result<()> {
return Err(io::Error::new(io::ErrorKind::Other, format!("设置mtu失败: {:?}", out))); return Err(io::Error::new(io::ErrorKind::Other, format!("设置mtu失败: {:?}", out)));
} }
Ok(()) Ok(())
}
pub fn set_interface_metric(index: u32, metric: u16) -> io::Result<()> {
let set_metric = format!("netsh interface ip set interface {} metric={}", index,metric);
let out = std::process::Command::new("cmd")
.arg("/C")
.arg(&set_metric)
.output()?;
if !out.status.success() {
log::error!("cmd={:?},out={:?}",set_metric,out);
return Err(io::Error::new(io::ErrorKind::Other, format!("设置metric失败: {:?}", out)));
}
Ok(())
} }
+4 -4
View File
@@ -4,10 +4,10 @@ use std::net::Ipv4Addr;
/// 添加路由 /// 添加路由
pub fn add_route(index: u32, dest: Ipv4Addr, pub fn add_route(index: u32, dest: Ipv4Addr,
netmask: Ipv4Addr, netmask: Ipv4Addr,
gateway: Ipv4Addr, ) -> io::Result<()> { gateway: Ipv4Addr, metric: u16) -> io::Result<()> {
let set_route = format!( let set_route = format!(
"route add {:?} mask {:?} {:?} if {}", "route add {:?} mask {:?} {:?} metric {} if {}",
dest, netmask, gateway, index dest, netmask, gateway, metric, index
); );
// 执行添加路由命令 // 执行添加路由命令
let out = std::process::Command::new("cmd") let out = std::process::Command::new("cmd")
@@ -23,7 +23,7 @@ pub fn add_route(index: u32, dest: Ipv4Addr,
} }
/// 删除路由 /// 删除路由
pub fn delete_route(index: u32, dest: Ipv4Addr,netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> { pub fn delete_route(index: u32, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
if index == 0 { if index == 0 {
return Err(io::Error::new(io::ErrorKind::Other, format!("网络接口索引错误: {:?}", index))); return Err(io::Error::new(io::ErrorKind::Other, format!("网络接口索引错误: {:?}", index)));
} }
+22 -13
View File
@@ -1,8 +1,7 @@
use std::{io, net, time}; use std::{io, time};
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use winapi::shared::ifdef::NET_LUID; use winapi::shared::ifdef::NET_LUID;
use winapi::shared::minwindef::*;
use winapi::um::winioctl::*; use winapi::um::winioctl::*;
use winapi::um::winnt::HANDLE; use winapi::um::winnt::HANDLE;
@@ -11,12 +10,15 @@ use crate::{decode_utf16, encode_utf16, ffi, IFace, netsh, route};
mod iface; mod iface;
pub struct TapDevice { pub struct TapDevice {
index: u32,
luid: NET_LUID, luid: NET_LUID,
handle: HANDLE, handle: HANDLE,
} }
unsafe impl Send for TapDevice{}
unsafe impl Sync for TapDevice{} unsafe impl Send for TapDevice {}
unsafe impl Sync for TapDevice {}
impl TapDevice { impl TapDevice {
/// Retieve the mac of the interface /// Retieve the mac of the interface
@@ -95,7 +97,8 @@ impl TapDevice {
Ok(handle) => break handle, Ok(handle) => break handle,
}; };
}; };
Ok(Self { luid, handle }) let index = ffi::luid_to_index(&luid).map(|index| index as u32)?;
Ok(Self { index, luid, handle })
} }
pub fn open(name: &str) -> io::Result<Self> { pub fn open(name: &str) -> io::Result<Self> {
@@ -105,7 +108,8 @@ impl TapDevice {
iface::check_interface(&luid)?; iface::check_interface(&luid)?;
let handle = iface::open_interface(&luid)?; let handle = iface::open_interface(&luid)?;
Ok(Self { luid, handle }) let index = ffi::luid_to_index(&luid).map(|index| index as u32)?;
Ok(Self { index, luid, handle })
} }
pub fn delete(self) -> io::Result<()> { pub fn delete(self) -> io::Result<()> {
@@ -119,7 +123,7 @@ impl IFace for TapDevice {
} }
fn get_index(&self) -> io::Result<u32> { fn get_index(&self) -> io::Result<u32> {
ffi::luid_to_index(&self.luid).map(|index| index as u32) Ok(self.index)
} }
fn get_name(&self) -> io::Result<String> { fn get_name(&self) -> io::Result<String> {
@@ -131,25 +135,30 @@ impl IFace for TapDevice {
netsh::set_interface_name(&name, new_name) netsh::set_interface_name(&name, new_name)
} }
fn set_ip<IP>(&self, address: IP, mask: IP) -> io::Result<()> where IP: Into<Ipv4Addr> { fn set_ip(&self, address: Ipv4Addr, mask: Ipv4Addr) -> io::Result<()> {
let index = self.get_index()?; let index = self.get_index()?;
netsh::set_interface_ip(index, &address.into(), &mask.into()) netsh::set_interface_ip(index, &address, &mask)
} }
fn add_route<IP>(&self, dest: IP, netmask: IP, gateway: IP) -> io::Result<()> where IP: Into<Ipv4Addr> { fn add_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr, metric: u16) -> io::Result<()> {
let index = self.get_index()?; let index = self.get_index()?;
route::add_route(index, dest.into(), netmask.into(), gateway.into()) route::add_route(index, dest, netmask, gateway,metric)
} }
fn delete_route<IP>(&self, dest: IP, netmask: IP, gateway: IP) -> io::Result<()> where IP: Into<Ipv4Addr> { fn delete_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
let index = self.get_index()?; let index = self.get_index()?;
route::delete_route(index, dest.into(), netmask.into(), gateway.into()) route::delete_route(index, dest, netmask, gateway)
} }
fn set_mtu(&self, mtu: u16) -> io::Result<()> { fn set_mtu(&self, mtu: u16) -> io::Result<()> {
let index = self.get_index()?; let index = self.get_index()?;
netsh::set_interface_mtu(index, mtu) netsh::set_interface_mtu(index, mtu)
} }
fn set_metric(&self, metric: u16) -> io::Result<()> {
let index = self.get_index()?;
netsh::set_interface_metric(index, metric)
}
} }
+39 -25
View File
@@ -4,6 +4,7 @@ use std::net::Ipv4Addr;
use winapi::um::{handleapi, synchapi, winbase, winnt}; use winapi::um::{handleapi, synchapi, winbase, winnt};
use crate::{decode_utf16, encode_utf16, ffi, IFace, netsh, route}; use crate::{decode_utf16, encode_utf16, ffi, IFace, netsh, route};
use rand::Rng;
mod wintun_raw; mod wintun_raw;
mod log; mod log;
pub mod packet; pub mod packet;
@@ -19,6 +20,8 @@ pub const MAX_POOL: usize = 256;
pub struct TunDevice { pub struct TunDevice {
pub(crate) luid: u64,
pub(crate) index: u32,
/// The session handle given to us by WintunStartSession /// The session handle given to us by WintunStartSession
pub(crate) session: wintun_raw::WINTUN_SESSION_HANDLE, pub(crate) session: wintun_raw::WINTUN_SESSION_HANDLE,
@@ -41,11 +44,7 @@ pub struct TunDevice {
unsafe impl Send for TunDevice {} unsafe impl Send for TunDevice {}
unsafe impl Sync for TunDevice {} unsafe impl Sync for TunDevice {}
winapi::DEFINE_GUID! {
GUID_NETWORK_ADAPTER,
0x4d36e972, 0xe325, 0x11ce,
0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18
}
impl TunDevice { impl TunDevice {
pub unsafe fn create<L>(library: L, pool: &str, name: &str) -> io::Result<Self> pub unsafe fn create<L>(library: L, pool: &str, name: &str) -> io::Result<Self>
where L: Into<libloading::Library>, { where L: Into<libloading::Library>, {
@@ -63,9 +62,13 @@ impl TunDevice {
if name_utf16.len() > MAX_POOL { if name_utf16.len() > MAX_POOL {
return Err(io::Error::new(io::ErrorKind::Other, format!("长度大于{}:{:?}", MAX_POOL, pool))); return Err(io::Error::new(io::ErrorKind::Other, format!("长度大于{}:{:?}", MAX_POOL, pool)));
} }
let mut guid_bytes: [u8; 16] = [0u8; 16];
rand::thread_rng().fill(&mut guid_bytes);
let guid = u128::from_ne_bytes(guid_bytes);
//SAFETY: guid is a unique integer so transmuting either all zeroes or the user's preferred //SAFETY: guid is a unique integer so transmuting either all zeroes or the user's preferred
//guid to the winapi guid type is safe and will allow the windows kernel to see our GUID //guid to the winapi guid type is safe and will allow the windows kernel to see our GUID
let guid_struct: wintun_raw::GUID = unsafe { std::mem::transmute(GUID_NETWORK_ADAPTER) };
let guid_struct: wintun_raw::GUID = unsafe { std::mem::transmute(guid) };
let guid_ptr = &guid_struct as *const wintun_raw::GUID; let guid_ptr = &guid_struct as *const wintun_raw::GUID;
log::set_default_logger_if_unset(&win_tun); log::set_default_logger_if_unset(&win_tun);
@@ -90,8 +93,12 @@ impl TunDevice {
let shutdown_event = synchapi::CreateEventA(std::ptr::null_mut(), let shutdown_event = synchapi::CreateEventA(std::ptr::null_mut(),
0, 0, std::ptr::null_mut()); 0, 0, std::ptr::null_mut());
let read_event = win_tun.WintunGetReadWaitEvent(session) as winnt::HANDLE; let read_event = win_tun.WintunGetReadWaitEvent(session) as winnt::HANDLE;
let mut luid: wintun_raw::NET_LUID = std::mem::zeroed();
win_tun.WintunGetAdapterLUID(adapter, &mut luid as *mut wintun_raw::NET_LUID);
let index = ffi::luid_to_index(&std::mem::transmute(luid)).map(|index| index as u32)?;
Ok(TunDevice { Ok(TunDevice {
luid: std::mem::transmute(luid),
index,
session, session,
win_tun, win_tun,
read_event, read_event,
@@ -99,7 +106,7 @@ impl TunDevice {
adapter, adapter,
}) })
} }
pub unsafe fn open<L>(library: L, name: &str) -> io::Result<Self> pub unsafe fn delete_for_name<L>(library: L, name: &str) -> io::Result<()>
where L: Into<libloading::Library>, { where L: Into<libloading::Library>, {
let win_tun = match wintun_raw::wintun::from_library(library) { let win_tun = match wintun_raw::wintun::from_library(library) {
Ok(win_tun) => win_tun, Ok(win_tun) => win_tun,
@@ -113,7 +120,9 @@ impl TunDevice {
if adapter.is_null() { if adapter.is_null() {
return Err(io::Error::new(io::ErrorKind::Other, "Failed to open adapter")); return Err(io::Error::new(io::ErrorKind::Other, "Failed to open adapter"));
} }
Self::init(win_tun, adapter) win_tun.WintunCloseAdapter(adapter);
win_tun.WintunDeleteDriver();
Ok(())
} }
pub fn delete(self) -> io::Result<()> { pub fn delete(self) -> io::Result<()> {
drop(self); drop(self);
@@ -138,13 +147,14 @@ pub struct Version {
pub minor: u16, pub minor: u16,
} }
impl TunDevice { // impl TunDevice {
fn get_adapter_luid(&self) -> u64 { // fn get_adapter_luid(&self) -> u64 {
let mut luid: wintun_raw::NET_LUID = unsafe { std::mem::zeroed() }; // let mut luid: wintun_raw::NET_LUID = unsafe { std::mem::zeroed() };
unsafe { self.win_tun.WintunGetAdapterLUID(self.adapter, &mut luid as *mut wintun_raw::NET_LUID) }; // unsafe { self.win_tun.WintunGetAdapterLUID(self.adapter, &mut luid as *mut wintun_raw::NET_LUID) };
unsafe { std::mem::transmute(luid) } // unsafe { std::mem::transmute(luid) }
} // }
} // }
impl IFace for TunDevice { impl IFace for TunDevice {
fn shutdown(&self) -> io::Result<()> { fn shutdown(&self) -> io::Result<()> {
@@ -154,12 +164,11 @@ impl IFace for TunDevice {
} }
fn get_index(&self) -> io::Result<u32> { fn get_index(&self) -> io::Result<u32> {
let luid = self.get_adapter_luid(); Ok(self.index)
ffi::luid_to_index(&unsafe { std::mem::transmute(luid) }).map(|index| index as u32)
} }
fn get_name(&self) -> io::Result<String> { fn get_name(&self) -> io::Result<String> {
let luid = self.get_adapter_luid(); let luid = self.luid;
ffi::luid_to_alias(&unsafe { std::mem::transmute(luid) }).map(|name| { ffi::luid_to_alias(&unsafe { std::mem::transmute(luid) }).map(|name| {
decode_utf16(&name) decode_utf16(&name)
}) })
@@ -170,21 +179,26 @@ impl IFace for TunDevice {
netsh::set_interface_name(&name, new_name) netsh::set_interface_name(&name, new_name)
} }
fn set_ip<IP>(&self, address: IP, mask: IP) -> io::Result<()> where IP: Into<Ipv4Addr> { fn set_ip(&self, address: Ipv4Addr, mask: Ipv4Addr) -> io::Result<()>{
netsh::set_interface_ip(self.get_index()?, &address.into(), &mask.into()) netsh::set_interface_ip(self.get_index()?, &address, &mask)
} }
fn add_route<IP>(&self, dest: IP, netmask: IP, gateway: IP) -> io::Result<()> where IP: Into<Ipv4Addr> { fn add_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr, metric: u16) -> io::Result<()> {
route::add_route(self.get_index()?, dest.into(), netmask.into(), gateway.into()) route::add_route(self.get_index()?, dest, netmask, gateway, metric)
} }
fn delete_route<IP>(&self, dest: IP, netmask: IP, gateway: IP) -> io::Result<()> where IP: Into<Ipv4Addr> { fn delete_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
route::delete_route(self.get_index()?, dest.into(), netmask.into(), gateway.into()) route::delete_route(self.get_index()?, dest, netmask, gateway)
} }
fn set_mtu(&self, mtu: u16) -> io::Result<()> { fn set_mtu(&self, mtu: u16) -> io::Result<()> {
netsh::set_interface_mtu(self.get_index()?, mtu) netsh::set_interface_mtu(self.get_index()?, mtu)
} }
fn set_metric(&self, metric: u16) -> io::Result<()> {
let index = self.get_index()?;
netsh::set_interface_metric(index, metric)
}
} }
impl TunDevice { impl TunDevice {