diff --git a/README.md b/README.md index 6b540b5..ee91dad 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,13 @@ 将不同网络下的多个设备虚拟到一个局域网下 -### 示例: +### 快速使用: 1. 指定一个token,在多台设备上运行该程序,例如: ```shell # linux上 root@DESKTOP-0BCHNIO:/opt# ./switch-desktop start --token 123456 - # 在另一台linux上使用nohup后台运行,不在命令行指定配置时,将在home/.switch/config文件中读取配置 + # 在另一台linux上使用nohup后台运行,不在命令行指定配置时,将在home/.switch_desktop/config文件中读取配置 [root@izj6cemne76ykdzkataftfz switch]# nohup ./switch-desktop start & # windows上 D:\switch\bin_v1>switch-desktop.exe start --token 123456 @@ -49,6 +49,7 @@ 1. 和远程桌面(如mstsc)搭配,超低延迟的体验 2. 安装samba服务,共享磁盘 3. 搭配公网服务器nginx反向代理,在公网访问本地文件 +4. 点对网(结合启动参数'--in-ip'和'--out-ip') ### 使用须知 @@ -79,6 +80,7 @@ - 点对点穿透 - 服务端中继转发 - 客户端中继转发 +- IP代理 ### Todo - 支持安卓 diff --git a/switch-desktop/Cargo.toml b/switch-desktop/Cargo.toml index c444347..1f91447 100644 --- a/switch-desktop/Cargo.toml +++ b/switch-desktop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "switch-desktop" -version = "1.0.2" +version = "1.0.4" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,7 +13,7 @@ console = "0.15.2" dirs = "4.0.0" log = "0.4.17" log4rs = "1.2.0" -#tokio = { version = "1.24.1", features = ["full"] } +tokio = { version = "1.28.1", features = ["full"] } chrono = "0.4.23" serde = "1.0" diff --git a/switch-desktop/src/config/log_config.rs b/switch-desktop/src/config/log_config.rs index 5194e05..2386d59 100644 --- a/switch-desktop/src/config/log_config.rs +++ b/switch-desktop/src/config/log_config.rs @@ -1,19 +1,17 @@ use std::io; -use crate::config::SWITCH_HOME_PATH; +use std::path::PathBuf; +use crate::config::get_home; + #[cfg(target_os = "windows")] pub fn log_service_init() -> io::Result<()> { - log_init_("switch-service.log") + log_init_(crate::config::get_win_server_home().join("switch-service.log")) } + pub fn log_init() -> io::Result<()> { - log_init_("switch-desktop.log") + log_init_(get_home().join("switch-desktop.log")) } -pub fn log_init_(file_name:&str) -> io::Result<()> { - let home = SWITCH_HOME_PATH.lock().clone(); - let home = if let Some(home) = home { - home - } else { - return Err(io::Error::new(io::ErrorKind::Other, "not found")); - }; + +fn log_init_(file_name: PathBuf) -> io::Result<()> { let stderr = log4rs::append::console::ConsoleAppender::builder() .target(log4rs::append::console::Target::Stderr) .build(); @@ -22,7 +20,7 @@ pub fn log_init_(file_name:&str) -> io::Result<()> { .encoder(Box::new(log4rs::encode::pattern::PatternEncoder::new( "{d(%+)(utc)} [{f}:{L}] {h({l})} {M}:{m}{n}\n", ))) - .build(home.join(file_name))?; + .build(file_name)?; match log4rs::Config::builder() .appender(log4rs::config::Appender::builder().build("logfile", Box::new(logfile))) .appender( diff --git a/switch-desktop/src/config/mod.rs b/switch-desktop/src/config/mod.rs index 244aa76..4bed80f 100644 --- a/switch-desktop/src/config/mod.rs +++ b/switch-desktop/src/config/mod.rs @@ -1,7 +1,7 @@ use std::fs::{File, OpenOptions}; use std::io; use std::io::{Read, Write}; -use std::net::{SocketAddr, ToSocketAddrs}; +use std::net::{Ipv4Addr, SocketAddr, ToSocketAddrs}; use std::path::PathBuf; use lazy_static::lazy_static; @@ -11,6 +11,14 @@ use serde::{Deserialize, Serialize}; use crate::StartArgs; pub mod log_config; +lazy_static! { + pub static ref SWITCH_HOME_PATH: Mutex> = Mutex::new(None); +} + +#[cfg(windows)] +pub fn get_win_server_home() -> PathBuf { + "./".into() +} pub struct StartConfig { pub tap: bool, @@ -19,27 +27,73 @@ pub struct StartConfig { pub server: SocketAddr, pub nat_test_server: Vec, pub device_id: String, + pub in_ips: Vec<(u32, u32, Ipv4Addr)>, + pub out_ips: Vec<(u32, u32, Ipv4Addr)>, + #[cfg(any(unix))] + pub off_command_server: bool, +} + +fn ips_parse(ips: &Vec) -> Result, String> { + let mut in_ips_c = vec![]; + for x in ips { + let mut split = x.split(","); + let net = if let Some(net) = split.next() { + net + } else { + return Err("参数错误".to_string()); + }; + let ip = if let Some(ip) = split.next() { + ip + } else { + return Err("参数错误".to_string()); + }; + let ip = if let Ok(ip) = ip.parse::() { + ip + } else { + return Err("参数错误".to_string()); + }; + let mut split = net.split("/"); + let dest = if let Some(dest) = split.next() { + dest + } else { + return Err("参数错误".to_string()); + }; + let mask = if let Some(mask) = split.next() { + mask + } else { + return Err("参数错误".to_string()); + }; + let dest = if let Ok(dest) = dest.parse::() { + dest + } else { + return Err("参数错误".to_string()); + }; + let mask = if let Ok(m) = mask.parse::() { + let mut mask = 0 as u32; + for i in 0..m { + mask = mask | (1 << (31 - i)); + } + mask + } else { + return Err("参数错误".to_string()); + }; + in_ips_c.push((u32::from_be_bytes(dest.octets()), mask, ip)); + } + Ok(in_ips_c) } pub fn default_config(start_args: StartArgs) -> Result { println!("========参数配置========"); - let args_config = read_config(); - let tap = start_args.tap.unwrap_or_else(|| { - if let Some(c) = &args_config { - c.tap - } else { - false - } - }); + let tap = start_args.tap; if tap { println!("use tap"); } else { println!("use tun"); } - if args_config.is_none() && start_args.token.is_none() { + if start_args.token.is_none() { return Err("找不到token(Token not found)".to_string()); } - let token = start_args.token.unwrap_or_else(|| args_config.as_ref().unwrap().token.clone()).trim().to_string(); + let token = start_args.token.unwrap(); if token.is_empty() { return Err("token不能为空(Token cannot be empty)".to_string()); } @@ -48,11 +102,6 @@ pub fn default_config(start_args: StartArgs) -> Result { } println!("token:{:?}", token); let name = start_args.name.unwrap_or_else(|| { - if let Some(c) = &args_config { - if !c.name.is_empty() { - return c.name.clone(); - } - } os_info::get().to_string() }); let name = name.trim(); @@ -63,11 +112,6 @@ pub fn default_config(start_args: StartArgs) -> Result { }; println!("name:{:?}", name); let device_id = start_args.device_id.unwrap_or_else(|| { - if let Some(c) = &args_config { - if !c.device_id.is_empty() { - return c.device_id.clone(); - } - } if let Ok(Some(mac_address)) = mac_address::get_mac_address() { mac_address.to_string() } else { @@ -78,12 +122,27 @@ pub fn default_config(start_args: StartArgs) -> Result { return Err("设备id不能为空并且长度不能大于64字符(The device id cannot be empty and the length cannot be greater than 64 characters)".to_string()); } println!("device_id:{:?}", device_id); + let in_ips = start_args.in_ip.unwrap_or_else(|| { + vec![] + }); + let out_ips = start_args.out_ip.unwrap_or_else(|| { + vec![] + }); + println!("in_ips:{:?}", in_ips); + let in_ips_c = if let Ok(in_ips_c) = ips_parse(&in_ips) { + in_ips_c + } else { + return Err("in_ips 参数错误 示例:--in_ip 192.168.10.0/24,10.26.0.3".to_string()); + }; + println!("out_ips:{:?}", out_ips); + let out_ips_c = if let Ok(out_ips_c) = ips_parse(&out_ips) { + out_ips_c + } else { + return Err("out_ips 参数错误 示例:--out_ip 192.168.10.0/24,192.168.0.5".to_string()); + }; + + let server = match start_args.server.unwrap_or_else(|| { - if let Some(c) = &args_config { - if !c.server.is_empty() { - return c.server.clone(); - } - } "nat1.wherewego.top:29871".to_string() }).to_socket_addrs() { Ok(mut server) => { @@ -99,11 +158,6 @@ pub fn default_config(start_args: StartArgs) -> Result { }; println!("中继服务器:{:?}", server); let nat_test_server = start_args.nat_test_server.unwrap_or_else(|| { - if let Some(c) = &args_config { - if !c.nat_test_server.is_empty() { - return c.nat_test_server.join(","); - } - } "nat1.wherewego.top:35061,nat1.wherewego.top:35062,nat2.wherewego.top:35061,nat2.wherewego.top:35062".to_string() }).split(",").flat_map(|a| a.to_socket_addrs()).flatten() .collect::>(); @@ -118,19 +172,128 @@ pub fn default_config(start_args: StartArgs) -> Result { server, nat_test_server, device_id, + in_ips: in_ips_c, + out_ips: out_ips_c, + #[cfg(any(unix))] + off_command_server: start_args.off_command_server, }; println!("========参数配置========"); Ok(base_config) } -lazy_static! { - static ref CONFIG: Mutex> = Mutex::new(None); - pub static ref SWITCH_HOME_PATH: Mutex> = Mutex::new(None); +pub fn read_config_file(config_path: PathBuf) -> Result { + println!("========读取配置文件========"); + let args_config = if let Ok(config) = read_config(config_path) { + config + } else { + return Err("读取配置文件失败".to_string()); + }; + + let tap = args_config.tap; + if tap { + println!("use tap"); + } else { + println!("use tun"); + } + let token = args_config.token; + if token.is_empty() { + return Err("token不能为空(Token cannot be empty)".to_string()); + } + if token.len() > 64 { + return Err("token不能超过64字符(Token cannot exceed 64 characters)".to_string()); + } + println!("token:{:?}", token); + let name = args_config.name; + let name = name.trim(); + let name = if name.len() > 64 { + name[..64].to_string() + } else { + name.to_string() + }; + println!("name:{:?}", name); + let device_id = if !args_config.device_id.is_empty() { + args_config.device_id + } else { + if let Ok(Some(mac_address)) = mac_address::get_mac_address() { + mac_address.to_string() + } else { + "".to_string() + } + }; + 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()); + } + println!("device_id:{:?}", device_id); + let in_ips = args_config.in_ips; + let out_ips = args_config.out_ips; + println!("in_ips:{:?}", in_ips); + let in_ips_c = if let Ok(in_ips_c) = ips_parse(&in_ips) { + in_ips_c + } else { + return Err("in_ips 参数错误 示例:--in_ip 192.168.10.0/24,10.26.0.3".to_string()); + }; + println!("out_ips:{:?}", out_ips); + let out_ips_c = if let Ok(out_ips_c) = ips_parse(&out_ips) { + out_ips_c + } else { + return Err("out_ips 参数错误 示例:--out_ip 192.168.10.0/24,192.168.0.5".to_string()); + }; + let server = match { + if !args_config.server.is_empty() { + args_config.server + } else { + "nat1.wherewego.top:29871".to_string() + } + }.to_socket_addrs() + { + Ok(mut server) => { + if let Some(addr) = server.next() { + addr + } else { + return Err("中继服务器地址错误( Relay server address error)".to_string()); + } + } + Err(e) => { + return Err(format!("中继服务器地址错误( Relay server address error) :{:?}", e)); + } + }; + println!("中继服务器:{:?}", server); + let nat_test_server = if args_config.nat_test_server.is_empty() { + vec!["nat1.wherewego.top:35061".to_string(), "nat1.wherewego.top:35062".to_string(), "nat2.wherewego.top:35061".to_string(), "nat2.wherewego.top:35062".to_string()] + } else { + args_config.nat_test_server + }.iter().flat_map(|a| a.to_socket_addrs()).flatten() + .collect::>(); + if nat_test_server.is_empty() { + return Err("NAT检测服务地址错误(NAT detection service address error)".to_string()); + } + println!("NAT探测服务器:{:?}", nat_test_server); + let base_config = StartConfig { + tap, + name, + token, + server, + nat_test_server, + device_id, + in_ips: in_ips_c, + out_ips: out_ips_c, + #[cfg(any(unix))] + off_command_server: args_config.off_command_server, + }; + println!("========参数配置========"); + Ok(base_config) +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct RuntimeData { + #[serde(default = "default_pid")] + pub pid: u32, + pub command_port: Option, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct ArgsConfig { - #[serde(default = "default_tap")] + #[serde(default = "default_false")] pub tap: bool, #[serde(default = "default_version")] pub version: String, @@ -138,18 +301,22 @@ pub struct ArgsConfig { pub token: String, #[serde(default = "default_str")] pub name: String, - pub command_port: Option, #[serde(default = "default_str")] pub server: String, #[serde(default = "default_vec")] pub nat_test_server: Vec, #[serde(default = "default_str")] pub device_id: String, - #[serde(default = "default_pid")] - pub pid: u32, + #[serde(default = "default_vec")] + pub in_ips: Vec, + #[serde(default = "default_vec")] + pub out_ips: Vec, + #[cfg(any(unix))] + #[serde(default = "default_false")] + pub off_command_server: bool, } -fn default_tap() -> bool { +fn default_false() -> bool { false } @@ -169,38 +336,35 @@ fn default_pid() -> u32 { 0 } -impl ArgsConfig { - pub fn new(tap: bool, token: String, name: String, server: SocketAddr, - nat_test_server: &Vec, device_id: String, ) -> Self { - Self { - tap, - version: "1.0".to_string(), - token, - name, - command_port: None, - server: server.to_string(), - nat_test_server: nat_test_server.iter().map(|v| v.to_string()).collect::>(), - device_id, - pid: 0, - } - } -} +// impl ArgsConfig { +// pub fn new(tap: bool, token: String, name: String, server: SocketAddr, +// nat_test_server: &Vec, device_id: String, +// in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32, Ipv4Addr)>, ) -> Self { +// +// Self { +// tap, +// version: "1.0".to_string(), +// token, +// name, +// command_port: None, +// server: server.to_string(), +// nat_test_server: nat_test_server.iter().map(|v| v.to_string()).collect::>(), +// device_id, +// pid: 0, +// } +// } +// } pub fn lock_file() -> io::Result { - let path = SWITCH_HOME_PATH.lock().clone().unwrap().join(".lock"); + let path = get_home().join(".lock"); let file = File::create(path)?; file.sync_all()?; Ok(file) } -pub fn save_config(config: ArgsConfig) -> io::Result<()> { - let config_path = SWITCH_HOME_PATH.lock().clone().unwrap().join("config"); - save_config_(config, config_path) -} -fn save_config_(config: ArgsConfig, config_path: PathBuf) -> io::Result<()> { - let mut config_lock = CONFIG.lock(); - config_lock.replace(config.clone()); +fn save_runtime_data(config: RuntimeData) -> io::Result<()> { + let config_path = get_runtime_data_path(); let str = serde_yaml::to_string(&config).unwrap(); let mut file = File::create(config_path)?; file.write_all(str.as_bytes())?; @@ -208,41 +372,25 @@ fn save_config_(config: ArgsConfig, config_path: PathBuf) -> io::Result<()> { } pub fn update_pid(pid: u32) -> io::Result<()> { - let home_lock = SWITCH_HOME_PATH.lock(); - if let Some(home) = home_lock.clone() { - drop(home_lock); - let config_path = home.join("config"); - if let Some(mut config) = read_config() { - config.pid = pid; - return save_config_(config, config_path); - } - } - Err(io::Error::new(io::ErrorKind::Other, "not found")) + let mut config = read_runtime_data()?; + config.pid = pid; + return save_runtime_data(config); } #[cfg(any(unix))] pub fn read_pid() -> io::Result { - let home = SWITCH_HOME_PATH.lock().clone().unwrap(); - let config = read_config_(home)?; + let config = read_runtime_data()?; Ok(config.pid) } pub fn update_command_port(port: u16) -> io::Result<()> { - let home_lock = SWITCH_HOME_PATH.lock(); - if let Some(home) = home_lock.clone() { - drop(home_lock); - let config_path = home.join("config"); - if let Some(mut config) = read_config() { - config.command_port = Some(port); - return save_config_(config, config_path); - } - } - Err(io::Error::new(io::ErrorKind::Other, "not found")) + let mut config = read_runtime_data()?; + config.command_port = Some(port); + return save_runtime_data(config); } pub fn read_command_port() -> io::Result { - let home = SWITCH_HOME_PATH.lock().clone().unwrap(); - let config = read_config_(home)?; + let config = read_runtime_data()?; if let Some(p) = config.command_port { Ok(p) } else { @@ -250,37 +398,22 @@ pub fn read_command_port() -> io::Result { } } -pub fn read_config() -> Option { - let mut lock = CONFIG.lock(); - let c = lock.clone(); - if c.is_some() { - return c; - } - if let Some(home) = SWITCH_HOME_PATH.lock().clone() { - match read_config_(home.to_path_buf()) { - Ok(config) => { - lock.replace(config.clone()); - Some(config) - } - Err(e) => { - log::error!("{:?},path:{:?}", e,home); - None - } - } - } else { - None - } -} -pub fn set_home(home: PathBuf) { +pub fn get_home() -> PathBuf { + let home = dirs::home_dir().unwrap().join(".switch_desktop"); if !home.exists() { std::fs::create_dir(&home).unwrap(); } - SWITCH_HOME_PATH.lock().replace(home); + home } -fn read_config_(home: PathBuf) -> io::Result { - let config_path = home.join("config"); +pub fn get_runtime_data_path() -> PathBuf { + let home = get_home(); + home.join("config") +} + +fn read_runtime_data() -> io::Result { + let config_path = get_runtime_data_path(); let mut file = if config_path.exists() { File::open(config_path)? } else { @@ -288,6 +421,19 @@ fn read_config_(home: PathBuf) -> io::Result { }; let mut str = String::new(); file.read_to_string(&mut str)?; + match serde_yaml::from_str::(&str) { + Ok(config) => Ok(config), + Err(e) => { + log::warn!("{:?}", e); + Err(io::Error::new(io::ErrorKind::Other, "config error")) + } + } +} + +fn read_config(config_path: PathBuf) -> io::Result { + let mut file = File::open(config_path)?; + let mut str = String::new(); + file.read_to_string(&mut str)?; match serde_yaml::from_str::(&str) { Ok(config) => Ok(config), Err(e) => { @@ -295,4 +441,4 @@ fn read_config_(home: PathBuf) -> io::Result { Err(io::Error::new(io::ErrorKind::Other, "config error")) } } -} +} \ No newline at end of file diff --git a/switch-desktop/src/main.rs b/switch-desktop/src/main.rs index 3c625cf..0ce4577 100644 --- a/switch-desktop/src/main.rs +++ b/switch-desktop/src/main.rs @@ -97,7 +97,18 @@ pub struct StartArgs { log: bool, /// 使用tap网卡 #[arg(long)] - tap: Option, + tap: bool, + /// 配置点对网时使用,--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 + #[arg(long)] + in_ip:Option>, + /// 配置点对网时使用,--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 + #[arg(long)] + out_ip:Option>, + /// 读取配置文件 --config config_file_path + /// Read configuration file + config:Option, } #[cfg(target_os = "windows")] @@ -124,28 +135,27 @@ pub struct ConfigArgs { #[cfg(windows)] -fn main() { +#[tokio::main] +async fn main() { let args: Vec<_> = std::env::args().collect(); if args.len() == 3 && args[1] == windows::SERVICE_FLAG { //以服务的方式启动 - config::set_home(std::path::PathBuf::from(&args[2])); windows::service::start(); return; } else { - let home = dirs::home_dir().unwrap().join(".switch_desktop"); - config::set_home(home); let args = BaseArgs::parse(); if let Commands::Start(start_args) = &args.command { if start_args.log { let _ = log_init(); } } - windows::main0(args); + windows::main0(args).await; } } #[cfg(any(target_os = "linux", target_os = "macos"))] -fn main() { +#[tokio::main] +async fn main() { if sudo::RunningAs::Root != sudo::check() { println!( "{}", @@ -154,14 +164,12 @@ fn main() { sudo::escalate_if_needed().unwrap(); } let args = BaseArgs::parse(); - let home = dirs::home_dir().unwrap().join(".switch_desktop"); - config::set_home(home); if let Commands::Start(start_args) = &args.command { if start_args.log { let _ = log_init(); } } - unix::main0(args); + unix::main0(args).await; } pub fn console_listen(switch: &Switch) { diff --git a/switch-desktop/src/unix/mod.rs b/switch-desktop/src/unix/mod.rs index 7697548..347b080 100644 --- a/switch-desktop/src/unix/mod.rs +++ b/switch-desktop/src/unix/mod.rs @@ -9,87 +9,91 @@ use crate::{BaseArgs, Commands, config}; use crate::command::{command, CommandEnum}; -pub fn main0(base_args: BaseArgs) { +pub async fn main0(base_args: BaseArgs) { match base_args.command { Commands::Start(args) => { - let off_command_server = args.off_command_server; - match config::default_config(args) { - Ok(start_config) => { - let config = Config::new( - start_config.tap, - start_config.token.clone(), - start_config.device_id.clone(), - start_config.name.clone(), - start_config.server, - start_config.nat_test_server.clone(), - ); - let args_config = config::ArgsConfig::new( - start_config.tap, - start_config.token.clone(), - start_config.name.clone(), - start_config.server, - &start_config.nat_test_server, - start_config.device_id.clone(), - ); - let lock = match config::lock_file() { - Ok(lock) => { - lock - } - Err(e) => { - log::error!("{:?}",e); - println!("文件锁定失败:{:?}", e); - return; - } - }; - if lock.try_lock_exclusive().is_err() { - println!("{}", style("文件被重复打开").red()); + let start_config = if let Some(config_path) = &args.config { + match config::read_config_file(config_path.into()) { + Ok(start_config) => { + start_config + } + Err(e) => { + println!("{}", style(&e).red()); + log::error!("{:?}", e); return; } - if let Err(e) = config::save_config(args_config) { - log::error!("{:?}",e); - lock.unlock().unwrap(); + } + } else { + match config::default_config(args) { + Ok(start_config) => { + start_config + } + Err(e) => { + println!("{}", style(&e).red()); + log::error!("{:?}", e); return; } - let switch = match Switch::start(config) { - Ok(switch) => { - switch - } - Err(e) => { - log::error!("{:?}", e); - println!("启动switch失败:{:?}", e); - lock.unlock().unwrap(); - return; - } - }; - let switch = Arc::new(switch); - let command_server = crate::command::server::CommandServer::new(); - if off_command_server { - crate::console_listen(&switch); - log::info!("前台任务结束"); - } else { - if let Err(e) = config::update_pid(std::process::id()) { - log::error!("{:?}", e); - } - let switch1 = switch.clone(); - let handle = std::thread::Builder::new().name("cmd-server".into()).spawn(move || { - if let Err(e) = command_server.start(switch1) { - log::error!("{:?}", e); - } - }).unwrap(); - crate::console_listen(&switch); - if let Err(e) = handle.join() { - log::error!("后台任务异常{:?}",e); - } else { - log::info!("后台任务结束"); - } - } - lock.unlock().unwrap(); + } + }; + let off_command_server = start_config.off_command_server; + let config = Config::new( + start_config.tap, + start_config.token.clone(), + start_config.device_id.clone(), + start_config.name.clone(), + start_config.server, + start_config.nat_test_server.clone(), + start_config.in_ips.clone(), + start_config.out_ips.clone(), + ); + let lock = match config::lock_file() { + Ok(lock) => { + lock } Err(e) => { - println!("{}", style(&e).red()); + log::error!("{:?}",e); + println!("文件锁定失败:{:?}", e); + return; + } + }; + if lock.try_lock_exclusive().is_err() { + println!("{}", style("文件被重复打开").red()); + return; + } + let switch = match Switch::start(config).await { + Ok(switch) => { + switch + } + Err(e) => { + log::error!("{:?}", e); + println!("启动switch失败:{:?}", e); + lock.unlock().unwrap(); + return; + } + }; + let switch = Arc::new(switch); + let command_server = crate::command::server::CommandServer::new(); + if off_command_server { + crate::console_listen(&switch); + log::info!("前台任务结束"); + } else { + if let Err(e) = config::update_pid(std::process::id()) { log::error!("{:?}", e); } + let switch1 = switch.clone(); + let handle = std::thread::Builder::new().name("cmd-server".into()).spawn(move || { + if let Err(e) = command_server.start(switch1) { + log::error!("{:?}", e); + } + }).unwrap(); + crate::console_listen(&switch); + if let Err(e) = handle.join() { + log::error!("后台任务异常{:?}",e); + } else { + log::info!("后台任务结束"); + } } + lock.unlock().unwrap(); } Commands::Stop => { command(CommandEnum::Stop); diff --git a/switch-desktop/src/windows/mod.rs b/switch-desktop/src/windows/mod.rs index c6d6c7e..3b14768 100644 --- a/switch-desktop/src/windows/mod.rs +++ b/switch-desktop/src/windows/mod.rs @@ -52,7 +52,7 @@ fn not_started() -> bool { return true; } -pub fn main0(base_args: BaseArgs) { +pub async fn main0(base_args: BaseArgs) { match base_args.command { Commands::Start(args) => { if admin_check() { @@ -62,92 +62,97 @@ pub fn main0(base_args: BaseArgs) { // 允许应用通过防火墙 let _udp = UdpSocket::bind("0.0.0.0:0").unwrap(); } - let out_log = args.log; - match config::default_config(args) { - Ok(start_config) => { - if let Err(e) = config::save_config(config::ArgsConfig::new(start_config.tap, - start_config.token.clone(), - start_config.name.clone(), - start_config.server, - &start_config.nat_test_server, - start_config.device_id.clone(), - )) { + let start_config = if let Some(config_path) = &args.config { + match config::read_config_file(config_path.into()) { + Ok(start_config) => { + start_config + } + Err(e) => { println!("{}", style(&e).red()); - log::error!("{:?}",e); + log::error!("{:?}", e); return; } - match service_state() { - Ok(state) => { - if state == ServiceState::Stopped { - match start(out_log) { - Ok(_) => { - //需要检查启动状态 - thread::sleep(Duration::from_secs(2)); - println!("{}", style("启动成功(Start successfully)").green()) - } - Err(e) => { - log::error!("{:?}", e); - } - } - } else { - println!("服务未停止(Service not stopped)"); + } + } else { + match config::default_config(args) { + Ok(start_config) => { + start_config + } + Err(e) => { + println!("{}", style(&e).red()); + log::error!("{:?}", e); + return; + } + } + }; + match service_state() { + Ok(state) => { + if state == ServiceState::Stopped { + match start() { + Ok(_) => { + //需要检查启动状态 + thread::sleep(Duration::from_secs(2)); + println!("{}", style("启动成功(Start successfully)").green()) + } + Err(e) => { + log::error!("{:?}", e); } } - Err(e) => { - match e { - Error::Winapi(ref e) => { - if let Some(code) = e.raw_os_error() { - if code == 1060 { - //指定的服务未安装。 - println!( - "{}", - style("服务未安装,在当前进程启动(The service is not installed and started in the current process)").red() - ); - let config = Config::new( - start_config.tap, - start_config.token, - start_config.device_id, - start_config.name, - start_config.server, - start_config.nat_test_server, - ); - let lock = match config::lock_file() { - Ok(lock) => { - lock - } - Err(e) => { - log::error!("文件锁定失败:{:?}",e); - println!("文件锁定失败:{:?}", e); - return; - } - }; - if lock.try_lock_exclusive().is_err() { - println!("{}", style("文件被重复打开").red()); - return; - } - match Switch::start(config) { - Ok(switch) => { - crate::console_listen(&switch); - } - Err(e) => { - log::error!("{:?}", e); - println!("启动switch失败:{:?}", e); - } - } - lock.unlock().unwrap(); - return; - } - } - } - _ => {} - } - println!("{:?}", e); - } + } else { + println!("服务未停止(Service not stopped)"); } } Err(e) => { - println!("{}", style(&e).red()); - log::error!("{:?}", e); + match e { + Error::Winapi(ref e) => { + if let Some(code) = e.raw_os_error() { + if code == 1060 { + //指定的服务未安装。 + println!( + "{}", + style("服务未安装,在当前进程启动(The service is not installed and started in the current process)").red() + ); + let config = Config::new( + start_config.tap, + start_config.token, + start_config.device_id, + start_config.name, + start_config.server, + start_config.nat_test_server, + start_config.in_ips, + start_config.out_ips, + ); + let lock = match config::lock_file() { + Ok(lock) => { + lock + } + Err(e) => { + log::error!("文件锁定失败:{:?}",e); + println!("文件锁定失败:{:?}", e); + return; + } + }; + if lock.try_lock_exclusive().is_err() { + println!("{}", style("文件被重复打开").red()); + return; + } + match Switch::start(config).await { + Ok(switch) => { + crate::console_listen(&switch); + } + Err(e) => { + log::error!("{:?}", e); + println!("启动switch失败:{:?}", e); + } + } + lock.unlock().unwrap(); + return; + } + } + } + _ => {} + } + println!("{:?}", e); } }; pause(); @@ -259,7 +264,7 @@ fn install(path: PathBuf, auto: bool) -> Result<(), Error> { let mut launch_arguments = Vec::new(); launch_arguments.push(OsString::from(SERVICE_FLAG)); launch_arguments.push(OsString::from( - dirs::home_dir().unwrap().join(".switch").to_str().unwrap(), + config::get_home().to_str().unwrap(), )); let start_type = if auto { ServiceStartType::AutoStart @@ -298,7 +303,7 @@ fn change(auto: bool) -> Result<(), Error> { let mut launch_arguments = Vec::new(); launch_arguments.push(OsString::from(SERVICE_FLAG)); launch_arguments.push(OsString::from( - dirs::home_dir().unwrap().join(".switch").to_str().unwrap(), + config::get_home().to_str().unwrap(), )); let service_info = ServiceInfo { name: OsString::from(SERVICE_NAME), @@ -333,15 +338,12 @@ fn uninstall() -> Result<(), Error> { Ok(()) } -fn start(out_log: bool) -> Result<(), Error> { +fn start() -> Result<(), Error> { let manager_access = ServiceManagerAccess::CONNECT; let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?; let service = service_manager.open_service(SERVICE_NAME, ServiceAccess::START)?; - if out_log { - service.start(&["log"]) - } else { - service.start(&[""]) - } + let args: Vec<_> = std::env::args().collect(); + service.start(&args[1..]) } fn service_state() -> Result { diff --git a/switch-desktop/src/windows/service.rs b/switch-desktop/src/windows/service.rs index 8e1c861..6a4517d 100644 --- a/switch-desktop/src/windows/service.rs +++ b/switch-desktop/src/windows/service.rs @@ -5,6 +5,7 @@ use std::ffi::OsString; use std::sync::Arc; use std::thread; use std::time::Duration; +use clap::Parser; use windows_service::{define_windows_service, service_control_handler, service_dispatcher}; use windows_service::service::{ @@ -14,27 +15,36 @@ use windows_service::service_control_handler::ServiceControlHandlerResult; use switch::core::{Config, Switch}; -use crate::{config, StartArgs}; +use crate::{BaseArgs, Commands, config, StartArgs}; use crate::windows::SERVICE_NAME; define_windows_service!(ffi_service_main, switch_service_main); pub fn switch_service_main(arguments: Vec) { - if !arguments.is_empty() { - if let Some(str) = arguments[0].to_str() { - if str == "log" { + let base_args = BaseArgs::parse_from(arguments); + match base_args.command { + Commands::Start(args) => { + if args.log { let _ = config::log_config::log_service_init(); } + tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .unwrap() + .block_on(async { + match service_main(args).await { + Ok(_) => {} + Err(e) => { + log::error!("启动服务失败:{:?}",e); + } + } + }) } + _ => {} } - thread::spawn(|| match service_main() { - Ok(_) => {} - Err(e) => { - log::error!("{:?}", e); - } - }); } -fn service_main() -> windows_service::Result<()> { +async fn service_main(args: StartArgs) -> windows_service::Result<()> { + log::error!("service_main:{:?}",args); let parker = crossbeam::sync::Parker::new(); let un_parker = parker.unparker().clone(); let event_handler = move |control_event| -> ServiceControlHandlerResult { @@ -68,7 +78,7 @@ fn service_main() -> windows_service::Result<()> { wait_hint: Duration::default(), process_id: None, })?; - match start_switch() { + match start_switch(args).await { Ok(switch) => { parker.park(); if let Err(e) = switch.stop() { @@ -90,36 +100,52 @@ fn service_main() -> windows_service::Result<()> { }) } -fn start_switch() -> switch::Result> { - match config::default_config(StartArgs::default()) { - Ok(start_config) => { - let config = Config::new( - start_config.tap, - start_config.token, - start_config.device_id, - start_config.name, - start_config.server, - start_config.nat_test_server, - ); - let switch = Switch::start(config)?; - log::info!("switch-service服务启动"); - let switch = Arc::new(switch); - let command_server = crate::command::server::CommandServer::new(); - let switch1 = switch.clone(); - thread::spawn(move || { - if let Err(e) = config::update_pid(std::process::id()) { - log::error!("{:?}", e); - } - if let Err(e) = command_server.start(switch1) { - log::error!("{:?}", e); - } - }); - Ok(switch) +async fn start_switch(args: StartArgs) -> switch::Result> { + let start_config = if let Some(config_path) = &args.config { + match config::read_config_file(config_path.into()) { + Ok(start_config) => { + start_config + } + Err(e) => { + log::error!("{:?}", e); + return Err(switch::error::Error::Stop(e)); + } } - Err(e) => { - return Err(switch::error::Error::Stop(e)); + } else { + match config::default_config(args) { + Ok(start_config) => { + start_config + } + Err(e) => { + log::error!("{:?}", e); + return Err(switch::error::Error::Stop(e)); + } } - } + }; + let config = Config::new( + start_config.tap, + start_config.token, + start_config.device_id, + start_config.name, + start_config.server, + start_config.nat_test_server, + start_config.in_ips, + start_config.out_ips, + ); + let switch = Switch::start(config).await?; + log::info!("switch-service服务启动"); + let switch = Arc::new(switch); + let command_server = crate::command::server::CommandServer::new(); + let switch1 = switch.clone(); + thread::spawn(move || { + if let Err(e) = config::update_pid(std::process::id()) { + log::error!("{:?}", e); + } + if let Err(e) = command_server.start(switch1) { + log::error!("{:?}", e); + } + }); + Ok(switch) } pub fn start() { diff --git a/switch/Cargo.toml b/switch/Cargo.toml index 5748f80..4ea4092 100644 --- a/switch/Cargo.toml +++ b/switch/Cargo.toml @@ -28,13 +28,12 @@ chrono = "0.4.23" protobuf = "3.2.0" #local-ip-address = "0.4.9" socket2 ={ version = "0.5.2", features = ["all"] } - -#mio = {version = "0.8.6",features = ["os-poll", "net"]} -#tokio = { version = "1.24.1", features = ["full"] } +tokio = { version = "1.28.1", features = ["full"] } [target.'cfg(any(unix))'.dependencies] tun = { path = "./rust-tun" } [target.'cfg(target_os = "windows")'.dependencies] + win-tun-tap = {path = "./win-tun-tap"} libloading = "0.7.4" diff --git a/switch/packet/src/icmp/icmp.rs b/switch/packet/src/icmp/icmp.rs index b175403..c079302 100644 --- a/switch/packet/src/icmp/icmp.rs +++ b/switch/packet/src/icmp/icmp.rs @@ -21,7 +21,7 @@ use crate::icmp::{Code, Kind}; use crate::ip::ipv4::packet::IpV4Packet; pub struct IcmpPacket { - buffer: B, + pub buffer: B, } impl> IcmpPacket { diff --git a/switch/packet/src/ip/ipv4/protocol.rs b/switch/packet/src/ip/ipv4/protocol.rs index 0dc8e4f..e4d7baa 100644 --- a/switch/packet/src/ip/ipv4/protocol.rs +++ b/switch/packet/src/ip/ipv4/protocol.rs @@ -1,4 +1,4 @@ -#[derive(Eq, PartialEq, Copy, Clone, Debug)] +#[derive(Eq, PartialEq,Ord, PartialOrd, Copy, Clone, Debug)] pub enum Protocol { /// Hopopt, diff --git a/switch/packet/src/tcp/tcp.rs b/switch/packet/src/tcp/tcp.rs index 646f2d9..d0ca2dc 100644 --- a/switch/packet/src/tcp/tcp.rs +++ b/switch/packet/src/tcp/tcp.rs @@ -1,7 +1,5 @@ use std::fmt; -use std::net::IpAddr; - -use byteorder::{BigEndian, ReadBytesExt}; +use std::net::Ipv4Addr; use crate::error::*; use crate::tcp::Flags; @@ -48,20 +46,20 @@ use crate::tcp::Flags; Options+Padding:32位整数倍,最多40个字节 */ pub struct TcpPacket { - source_ip: IpAddr, - destination_ip: IpAddr, + source_ip: Ipv4Addr, + destination_ip: Ipv4Addr, buffer: B, } impl> TcpPacket { - pub fn unchecked(source_ip: IpAddr, destination_ip: IpAddr, buffer: B) -> TcpPacket { + pub fn unchecked(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> TcpPacket { TcpPacket { source_ip, destination_ip, buffer, } } - pub fn new(source_ip: IpAddr, destination_ip: IpAddr, buffer: B) -> Result> { + pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> Result> { let packet = TcpPacket::unchecked(source_ip, destination_ip, buffer); if packet.buffer.as_ref().len() < 20 { @@ -80,6 +78,12 @@ impl + AsMut<[u8]>> TcpPacket { fn set_checksum(&mut self, value: u16) { self.buffer.as_mut()[16..18].copy_from_slice(&value.to_be_bytes()) } + pub fn set_source_port(&mut self, value: u16) { + self.buffer.as_mut()[0..2].copy_from_slice(&value.to_be_bytes()) + } + pub fn set_destination_port(&mut self, value: u16) { + self.buffer.as_mut()[2..4].copy_from_slice(&value.to_be_bytes()) + } /// 更新校验和 pub fn update_checksum(&mut self) { //先将校验和置0 @@ -87,31 +91,24 @@ impl + AsMut<[u8]>> TcpPacket { self.set_checksum(self.cal_checksum()) } } + impl> TcpPacket { /// 源端口 pub fn source_port(&self) -> u16 { - (&self.buffer.as_ref()[0..]) - .read_u16::() - .unwrap() + u16::from_be_bytes(self.buffer.as_ref()[0..2].try_into().unwrap()) } /// 目标端口 pub fn destination_port(&self) -> u16 { - (&self.buffer.as_ref()[2..]) - .read_u16::() - .unwrap() + u16::from_be_bytes(self.buffer.as_ref()[2..4].try_into().unwrap()) } /// 序列号 pub fn sequence(&self) -> u32 { - (&self.buffer.as_ref()[4..]) - .read_u32::() - .unwrap() + u32::from_be_bytes(self.buffer.as_ref()[4..8].try_into().unwrap()) } /// 确认号 pub fn acknowledgment(&self) -> u32 { - (&self.buffer.as_ref()[8..]) - .read_u32::() - .unwrap() + u32::from_be_bytes(self.buffer.as_ref()[8..12].try_into().unwrap()) } /// 数据偏移 4字节为单位 pub fn data_offset(&self) -> u8 { @@ -121,14 +118,10 @@ impl> TcpPacket { Flags(self.buffer.as_ref()[13]) } pub fn window(&self) -> u16 { - (&self.buffer.as_ref()[14..]) - .read_u16::() - .unwrap() + u16::from_be_bytes(self.buffer.as_ref()[14..16].try_into().unwrap()) } pub fn checksum(&self) -> u16 { - (&self.buffer.as_ref()[16..]) - .read_u16::() - .unwrap() + u16::from_be_bytes(self.buffer.as_ref()[16..18].try_into().unwrap()) } /// 验证校验和,ipv4中为0表示不使用校验和,ipv6校验和不能为0 /// TCP/IP协议栈不会自己计算校验和,而是简单地将一个空的校验和字段(零或随机填充)交给网卡硬件。 @@ -137,26 +130,16 @@ impl> TcpPacket { self.checksum() == 0 || self.cal_checksum() == 0 } fn cal_checksum(&self) -> u16 { - match self.source_ip { - IpAddr::V4(src) => { - if let IpAddr::V4(dest) = self.destination_ip { - return crate::ipv4_cal_checksum( - self.buffer.as_ref(), - &src, - &dest, - 6, - self.buffer.as_ref().len() as u16, - ); - } - } - IpAddr::V6(_src) => {} - } - unimplemented!() + crate::ipv4_cal_checksum( + self.buffer.as_ref(), + &self.source_ip, + &self.destination_ip, + 6, + self.buffer.as_ref().len() as u16, + ) } pub fn urgent_pointer(&self) -> u16 { - (&self.buffer.as_ref()[18..]) - .read_u16::() - .unwrap() + u16::from_be_bytes(self.buffer.as_ref()[18..20].try_into().unwrap()) } pub fn options(&self) -> &[u8] { &self.buffer.as_ref()[20..(self.data_offset() as usize * 4)] diff --git a/switch/packet/src/udp/udp.rs b/switch/packet/src/udp/udp.rs index af6b1c5..b52e4b9 100644 --- a/switch/packet/src/udp/udp.rs +++ b/switch/packet/src/udp/udp.rs @@ -1,9 +1,5 @@ use std::fmt; -use std::io::Cursor; -use std::net::IpAddr; - -use byteorder::WriteBytesExt; -use byteorder::{BigEndian, ReadBytesExt}; +use std::net::Ipv4Addr; use crate::error::*; @@ -53,20 +49,20 @@ RFC 768 https://www.ietf.org/rfc/rfc768.txt */ pub struct UdpPacket { - source_ip: IpAddr, - destination_ip: IpAddr, + source_ip: Ipv4Addr, + destination_ip: Ipv4Addr, buffer: B, } impl> UdpPacket { - pub fn unchecked(source_ip: IpAddr, destination_ip: IpAddr, buffer: B) -> UdpPacket { + pub fn unchecked(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> UdpPacket { UdpPacket { source_ip, destination_ip, buffer, } } - pub fn new(source_ip: IpAddr, destination_ip: IpAddr, buffer: B) -> Result> { + pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> Result> { if buffer.as_ref().len() < 8 { Err(Error::SmallBuffer)? } @@ -78,30 +74,22 @@ impl> UdpPacket { impl> UdpPacket { /// 源端口 pub fn source_port(&self) -> u16 { - (&self.buffer.as_ref()[0..]) - .read_u16::() - .unwrap() + u16::from_be_bytes(self.buffer.as_ref()[0..2].try_into().unwrap()) } /// 目标端口 pub fn destination_port(&self) -> u16 { - (&self.buffer.as_ref()[2..]) - .read_u16::() - .unwrap() + u16::from_be_bytes(self.buffer.as_ref()[2..4].try_into().unwrap()) } /// 总字节数 pub fn length(&self) -> u16 { - (&self.buffer.as_ref()[4..]) - .read_u16::() - .unwrap() + u16::from_be_bytes(self.buffer.as_ref()[4..6].try_into().unwrap()) } /// Checksum of the packet. pub fn checksum(&self) -> u16 { - (&self.buffer.as_ref()[6..]) - .read_u16::() - .unwrap() + u16::from_be_bytes(self.buffer.as_ref()[6..8].try_into().unwrap()) } /// 验证校验和,ipv4中为0表示不使用校验和,ipv6校验和不能为0 pub fn is_valid(&self) -> bool { @@ -111,21 +99,13 @@ impl> UdpPacket { &self.buffer.as_ref()[8..] } fn cal_checksum(&self) -> u16 { - match self.source_ip { - IpAddr::V4(src) => { - if let IpAddr::V4(dest) = self.destination_ip { - return crate::ipv4_cal_checksum( - self.buffer.as_ref(), - &src, - &dest, - 17, - self.length(), - ); - } - } - IpAddr::V6(_src) => {} - } - unimplemented!() + crate::ipv4_cal_checksum( + self.buffer.as_ref(), + &self.source_ip, + &self.destination_ip, + 17, + self.length(), + ) } } @@ -137,29 +117,21 @@ impl + AsMut<[u8]>> UdpPacket { impl + AsMut<[u8]>> UdpPacket { /// 设置源端口 - pub fn set_source_port(&mut self, value: u16) -> &mut Self { - Cursor::new(&mut self.header_mut()[0..]) - .write_u16::(value) - .unwrap(); - self + pub fn set_source_port(&mut self, value: u16) { + self.buffer.as_mut()[0..2].copy_from_slice(&value.to_be_bytes()) } /// 设置目的端口 - pub fn set_destination_port(&mut self, value: u16) -> &mut Self { - Cursor::new(&mut self.header_mut()[2..]) - .write_u16::(value) - .unwrap(); - self + pub fn set_destination_port(&mut self, value: u16) { + self.buffer.as_mut()[2..4].copy_from_slice(&value.to_be_bytes()) } - fn set_checknum(&mut self, value: u16) { - Cursor::new(&mut self.header_mut()[6..]) - .write_u16::(value) - .unwrap(); + fn set_checksum(&mut self, value: u16) { + self.buffer.as_mut()[6..8].copy_from_slice(&value.to_be_bytes()) } - pub fn update_checknum(&mut self) { + pub fn update_checksum(&mut self) { //先写0 - self.set_checknum(0); - self.set_checknum(self.cal_checksum()); + self.set_checksum(0); + self.set_checksum(self.cal_checksum()); } } diff --git a/switch/src/core/mod.rs b/switch/src/core/mod.rs index c5e3eda..22c2220 100644 --- a/switch/src/core/mod.rs +++ b/switch/src/core/mod.rs @@ -1,15 +1,19 @@ use std::io; use std::net::{Ipv4Addr, SocketAddr}; use std::sync::Arc; + use crossbeam::atomic::AtomicCell; use crossbeam_skiplist::SkipMap; use parking_lot::Mutex; + use p2p_channel::boot::Boot; use p2p_channel::channel::{Channel, Route, RouteKey}; use p2p_channel::punch::NatInfo; -use crate::handle::{ConnectStatus, CurrentDeviceInfo, heartbeat_handler, PeerDeviceInfo, punch_handler, recv_handler, registration_handler, tap_handler, tun_handler}; -use crate::nat::NatTest; + use crate::{tap_device, tun_device}; +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::nat::NatTest; use crate::tap_device::TapWriter; use crate::tun_device::TunWriter; @@ -29,8 +33,9 @@ pub struct Switch { } impl Switch { - pub fn start(config: Config) -> crate::Result { + pub async fn start(config: Config) -> crate::Result { log::info!("config:{:?}",config); + let (mut channel, punch, idle) = Boot::new::(80, 15000, 0)?; 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())); @@ -45,18 +50,24 @@ impl Switch { let local_port = channel.local_addr()?.port(); // 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 (current_device, tun_writer, tap_writer) = if config.tap { + let in_ips = config.in_ips.iter().map(|(dest, mask, _)| { (Ipv4Addr::from(*dest), Ipv4Addr::from(*mask)) }).collect::>(); + + let out_ips = config.out_ips.iter().map(|(_, _, ip)| *ip).collect::>(); + let out_external_route = ExternalRoute::new(config.out_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 ip_proxy_map = crate::ip_proxy::init_proxy(channel.sender()?,out_ips,current_device.clone()).await?; + let ( current_device_ext,tun_writer, tap_writer) = if config.tap { #[cfg(windows)] { //删除switch的tun网卡避免ip冲突,因为非正常退出会保留网卡 tun_device::delete_tun(); } let (tap_writer, tap_reader, mac) = tap_device::create_tap(virtual_ip, virtual_netmask, virtual_gateway)?; - let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, - config.server_address, mac))); + let current_device_ext = Arc::new(AtomicCell::new(CurrentDeviceInfoExt::new( mac))); //tap数据处理 - tap_handler::start(channel.sender()?, tap_reader.clone(), tap_writer.clone(), current_device.clone()); - (current_device, None, Some(tap_writer)) + tap_handler::start(channel.sender()?, tap_reader.clone(), tap_writer.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone()); + (current_device_ext, None, Some(tap_writer)) } else { #[cfg(windows)] { @@ -64,15 +75,16 @@ impl Switch { tap_device::delete_tap(); } // tun通道 - let (tun_writer, tun_reader) = tun_device::create_tun(virtual_ip, virtual_netmask, virtual_gateway)?; - let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, config.server_address, [0, 0, 0, 0, 0, 0]))); + let (tun_writer, tun_reader) = tun_device::create_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]))); //tun数据接收处理 - tun_handler::start(channel.sender()?, tun_reader.clone(), tun_writer.clone(), current_device.clone()); - (current_device, Some(tun_writer), None) + tun_handler::start(channel.sender()?, tun_reader.clone(), tun_writer.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone()); + (current_device_ext,Some(tun_writer), None) }; //外部数据接收处理 - let channel_recv_handler = recv_handler::RecvHandler::new(channel.try_clone()?, current_device.clone(), device_list.clone(), register.clone(), - nat_test.clone(), tun_writer.clone(), tap_writer.clone(), connect_status.clone(), peer_nat_info_map.clone()); + let channel_recv_handler = recv_handler::RecvHandler::new(channel.try_clone()?, current_device.clone(), current_device_ext,device_list.clone(), register.clone(), + nat_test.clone(), tun_writer.clone(), tap_writer.clone(), + connect_status.clone(), peer_nat_info_map.clone(), ip_proxy_map, out_external_route); recv_handler::start(channel_recv_handler); // 定时心跳 heartbeat_handler::start_heartbeat(channel.sender()?, device_list.clone(), current_device.clone()); @@ -148,6 +160,8 @@ pub struct Config { pub name: String, pub server_address: SocketAddr, pub nat_test_server: Vec, + pub in_ips: Vec<(u32, u32, Ipv4Addr)>, + pub out_ips: Vec<(u32, u32, Ipv4Addr)>, } impl Config { @@ -155,7 +169,8 @@ impl Config { device_id: String, name: String, server_address: SocketAddr, - nat_test_server: Vec, ) -> Self { + nat_test_server: Vec, + in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32, Ipv4Addr)>, ) -> Self { Self { tap, token, @@ -163,6 +178,8 @@ impl Config { name, server_address, nat_test_server, + in_ips, + out_ips, } } } \ No newline at end of file diff --git a/switch/src/external_route/mod.rs b/switch/src/external_route/mod.rs new file mode 100644 index 0000000..a7cd6af --- /dev/null +++ b/switch/src/external_route/mod.rs @@ -0,0 +1,24 @@ +use std::net::Ipv4Addr; + +// 目标ip,子网掩码,网关 + +pub struct ExternalRoute { + route_table: Vec<(u32, u32, Ipv4Addr)>, +} + +impl ExternalRoute { + pub fn new(route_table: Vec<(u32, u32, Ipv4Addr)>) -> Self { + Self { + route_table + } + } + pub fn route(&self, ip: &Ipv4Addr) -> Option { + let ip = u32::from_be_bytes(ip.octets()); + for (dest, mask, gateway) in &self.route_table { + if *mask & ip == *mask & *dest { + return Some(*gateway); + } + } + None + } +} \ No newline at end of file diff --git a/switch/src/handle/mod.rs b/switch/src/handle/mod.rs index 480dca6..d6e9121 100644 --- a/switch/src/handle/mod.rs +++ b/switch/src/handle/mod.rs @@ -60,6 +60,19 @@ pub enum ConnectStatus { 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)] pub struct CurrentDeviceInfo { virtual_ip: Ipv4Addr, @@ -71,7 +84,7 @@ pub struct CurrentDeviceInfo { pub broadcast_address: Ipv4Addr, //链接的服务器地址 pub connect_server: SocketAddr, - pub mac:[u8;6] + } impl CurrentDeviceInfo { @@ -80,7 +93,6 @@ impl CurrentDeviceInfo { virtual_gateway: Ipv4Addr, virtual_netmask: Ipv4Addr, connect_server: SocketAddr, - mac:[u8;6], ) -> Self { let broadcast_address = (!u32::from_be_bytes(virtual_netmask.octets())) | u32::from_be_bytes(virtual_gateway.octets()); @@ -95,7 +107,6 @@ impl CurrentDeviceInfo { virtual_network, broadcast_address, connect_server, - mac } } #[inline] diff --git a/switch/src/handle/recv_handler.rs b/switch/src/handle/recv_handler.rs index 03a1a23..d3aa721 100644 --- a/switch/src/handle/recv_handler.rs +++ b/switch/src/handle/recv_handler.rs @@ -1,5 +1,5 @@ -use std::{io, thread}; -use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use std::thread; +use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4}; use std::sync::Arc; use chrono::Local; @@ -12,12 +12,15 @@ use p2p_channel::channel::{Channel, Route, RouteKey}; use p2p_channel::punch::NatInfo; use packet::ethernet; use packet::icmp::{icmp, Kind}; +use packet::icmp::icmp::HeaderOther; use packet::ip::ipv4; use packet::ip::ipv4::packet::IpV4Packet; use crate::error::Error; -use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo}; +use crate::external_route::ExternalRoute; +use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, CurrentDeviceInfoExt, PeerDeviceInfo}; use crate::handle::registration_handler::Register; +use crate::ip_proxy::IpProxyMap; use crate::nat; use crate::nat::NatTest; use crate::proto::message::{DeviceList, PunchInfo, PunchNatType, RegistrationResponse}; @@ -56,6 +59,7 @@ pub fn start(mut handler: RecvHandler) { pub struct RecvHandler { channel: Channel, current_device: Arc>, + current_device_ext: Arc>, device_list: Arc)>>, register: Arc, nat_test: NatTest, @@ -63,11 +67,14 @@ pub struct RecvHandler { tap_writer: Option, connect_status: Arc>, peer_nat_info_map: Arc>, + ip_proxy_map: IpProxyMap, + out_external_route: ExternalRoute, } impl RecvHandler { pub fn new(channel: Channel, current_device: Arc>, + current_device_ext: Arc>, device_list: Arc)>>, register: Arc, nat_test: NatTest, @@ -75,10 +82,13 @@ impl RecvHandler { tap_writer: Option, connect_status: Arc>, peer_nat_info_map: Arc>, + ip_proxy_map: IpProxyMap, + out_external_route: ExternalRoute, ) -> Self { Self { channel, current_device, + current_device_ext, device_list, register, nat_test, @@ -86,21 +96,23 @@ impl RecvHandler { tap_writer, connect_status, peer_nat_info_map, + ip_proxy_map, + out_external_route, } } - pub fn try_clone(&self) -> io::Result { - 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(), - }) - } + // pub fn try_clone(&self) -> io::Result { + // 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 { @@ -144,36 +156,82 @@ impl RecvHandler { match net_packet.protocol() { Protocol::Ipv4Turn => { let mut ipv4 = IpV4Packet::new(net_packet.payload_mut())?; + if ipv4.destination_ip() == destination && ipv4.protocol() == ipv4::protocol::Protocol::Icmp { + let mut icmp_packet = icmp::IcmpPacket::new(ipv4.payload_mut())?; + if icmp_packet.kind() == Kind::EchoRequest { + //开启ping + icmp_packet.set_kind(Kind::EchoReply); + icmp_packet.update_checksum(); + ipv4.set_source_ip(destination); + ipv4.set_destination_ip(source); + ipv4.update_checksum(); + net_packet.set_source(destination); + net_packet.set_destination(source); + self.channel.send_to_route(net_packet.buffer(), route_key)?; + return Ok(()); + } + } if ipv4.destination_ip() != destination { - //todo 外部数据转发 - } else { - if ipv4.protocol() == ipv4::protocol::Protocol::Icmp { - let mut icmp_packet = icmp::IcmpPacket::new(ipv4.payload_mut())?; - if icmp_packet.kind() == Kind::EchoRequest { - //开启ping - icmp_packet.set_kind(Kind::EchoReply); - icmp_packet.update_checksum(); - ipv4.set_source_ip(destination); - ipv4.set_destination_ip(source); - ipv4.update_checksum(); - net_packet.set_source(destination); - net_packet.set_destination(source); - self.channel.send_to_route(net_packet.buffer(), route_key)?; - return Ok(()); + 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(); + println!("{:?}",ipv4); + 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(()); + } } } - 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(¤t_device.mac); - ethernet_packet.set_protocol(ethernet::protocol::Protocol::Ipv4); - ethernet_packet.payload_mut().copy_from_slice(ipv4.buffer); - tap_writer.write(ðernet_packet.buffer)?; - } + } + 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(ðernet_packet.buffer)?; } } } @@ -225,7 +283,7 @@ impl RecvHandler { } } let new_current_device = CurrentDeviceInfo::new(virtual_ip, virtual_gateway, - virtual_netmask, current_device.connect_server, current_device.mac); + virtual_netmask, current_device.connect_server); if let Err(e) = self.current_device.compare_exchange(current_device, new_current_device) { log::warn!("替换失败:{:?}",e); } diff --git a/switch/src/handle/tap_handler.rs b/switch/src/handle/tap_handler.rs index 333c9c3..af7bcd5 100644 --- a/switch/src/handle/tap_handler.rs +++ b/switch/src/handle/tap_handler.rs @@ -1,4 +1,4 @@ -use std::net::Ipv4Addr; +use std::net::{Ipv4Addr, SocketAddrV4}; use std::sync::Arc; use std::{io, thread}; use crossbeam::atomic::AtomicCell; @@ -10,16 +10,20 @@ 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, tap_reader: TapReader, tap_writer: TapWriter, - current_device: Arc>, ) { + current_device: Arc>, + 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) { + if let Err(e) = start_(sender, tap_reader, tap_writer, current_device,ip_route,ip_proxy_map) { log::warn!("{:?}",e); } }).unwrap(); @@ -28,7 +32,9 @@ pub fn start(sender: Sender, fn start_(sender: Sender, tap_reader: TapReader, tap_writer: TapWriter, - current_device: Arc>, ) -> io::Result<()> { + current_device: Arc>, + 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); @@ -41,17 +47,17 @@ fn start_(sender: Sender, continue; } let mut ethernet_packet = EthernetPacket::unchecked(&mut buf[..len]); - if let Err(e) = handle(&mut net_packet, ¤t_device, &tap_writer, &mut ethernet_packet, &sender) { + if let Err(e) = handle(&mut net_packet, ¤t_device, &tap_writer, &mut ethernet_packet, &sender,&ip_route,&ip_proxy_map) { log::error!("tap handle{:?}",e); } } } -fn handle(net_packet: &mut NetPacket>, current_device: &AtomicCell, tap_writer: &TapWriter, ethernet_packet: &mut EthernetPacket<&mut [u8]>, sender: &Sender) -> io::Result<()> { +fn handle(net_packet: &mut NetPacket>, current_device: &AtomicCell, tap_writer: &TapWriter, ethernet_packet: &mut EthernetPacket<&mut [u8]>, sender: &Sender, 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 = ethernet::packet::EthernetPacket::unchecked(ethernet_packet.buffer.to_vec()); + 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(); @@ -75,10 +81,55 @@ fn handle(net_packet: &mut NetPacket>, current_device: &AtomicCell { + 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()); @@ -103,8 +154,8 @@ fn handle(net_packet: &mut NetPacket>, current_device: &AtomicCell { - log::warn!("不支持的二层协议:{:?}",p) + _ => { + // log::warn!("不支持的二层协议:{:?}",p) } } Ok(()) diff --git a/switch/src/handle/tun_handler.rs b/switch/src/handle/tun_handler.rs index 69afd83..4a7c6fe 100644 --- a/switch/src/handle/tun_handler.rs +++ b/switch/src/handle/tun_handler.rs @@ -1,17 +1,19 @@ use std::{io, thread}; -use std::net::Ipv4Addr; +use std::net::{Ipv4Addr, SocketAddrV4}; use std::sync::Arc; use crossbeam::atomic::AtomicCell; use p2p_channel::channel::sender::Sender; -use packet::icmp::icmp::IcmpPacket; -use packet::icmp::Kind; +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}; @@ -33,9 +35,9 @@ fn icmp(tun_writer: &TunWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Resul /// 接收tun数据,并且转发到udp上 #[inline] -fn handle(sender: &Sender, data: &mut [u8], tun_writer: &TunWriter, current_device: CurrentDeviceInfo, net_packet: &mut NetPacket>) -> Result<()> { +fn handle(sender: &Sender, 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 ipv4_packet = match IpV4Packet::new(data) { + let mut ipv4_packet = match IpV4Packet::new(data) { Ok(ipv4_packet) => ipv4_packet, Err(packet::error::Error::Unimplemented) => { return Ok(()); @@ -43,18 +45,65 @@ fn handle(sender: &Sender, data: &mut [u8], tun_writer: &TunWriter, cu Err(e) => Err(e)?, }; let src_ip = ipv4_packet.source_ip(); - let dest_ip = ipv4_packet.destination_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() || (!check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) && !dest_ip.is_broadcast()) { + 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); @@ -68,9 +117,11 @@ fn handle(sender: &Sender, data: &mut [u8], tun_writer: &TunWriter, cu pub fn start(sender: Sender, tun_reader: TunReader, tun_writer: TunWriter, - current_device: Arc>) { + current_device: Arc>, + 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) { + if let Err(e) = start_(sender, tun_reader, tun_writer, current_device, ip_route, ip_proxy_map) { log::warn!("{:?}",e); } }).unwrap(); @@ -80,15 +131,17 @@ pub fn start(sender: Sender, fn start_(sender: Sender, tun_reader: TunReader, tun_writer: TunWriter, - current_device: Arc>) -> io::Result<()> { - let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + 1500])?; + current_device: Arc>, + 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) { + 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) @@ -101,8 +154,10 @@ fn start_(sender: Sender, fn start_(sender: Sender, tun_reader: TunReader, tun_writer: TunWriter, - current_device: Arc>, ) -> io::Result<()> { - let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + 1500])?; + current_device: Arc>, + 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()); @@ -110,7 +165,7 @@ fn start_(sender: Sender, 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) { + 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) diff --git a/switch/src/ip_proxy/icmp_proxy.rs b/switch/src/ip_proxy/icmp_proxy.rs new file mode 100644 index 0000000..d74087d --- /dev/null +++ b/switch/src/ip_proxy/icmp_proxy.rs @@ -0,0 +1,131 @@ +use std::io; +use std::mem::MaybeUninit; +use std::net::{IpAddr, Ipv4Addr, SocketAddrV4}; +use std::sync::Arc; +use crossbeam::atomic::AtomicCell; + +use crossbeam_skiplist::SkipMap; +use socket2::{Domain, SockAddr, Socket, Type}; +use p2p_channel::channel::sender::Sender; + +use packet::icmp::icmp; +use packet::icmp::icmp::HeaderOther; +use packet::ip::ipv4; +use crate::handle::CurrentDeviceInfo; +use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version}; + +pub struct IcmpProxy { + icmp_socket: Arc, + // 对端-> 真实来源 + icmp_proxy_map: Arc>, + sender: Sender, + current_device: Arc>, +} + +impl IcmpProxy { + pub fn new(addr: SocketAddrV4, icmp_proxy_map: Arc>, sender: Sender, current_device: Arc>) -> io::Result { + let icmp_socket = Arc::new(Socket::new(Domain::IPV4, Type::RAW, Some(socket2::Protocol::ICMPV4))?); + icmp_socket.bind(&SockAddr::from(addr))?; + // // 设置 SIO_RCVALL 参数 + // #[cfg(windows)] + // { + // use std::os::windows::io::AsRawSocket; + // let raw_fd = icmp_socket.as_raw_socket(); + // let mut rcvall: winapi::shared::minwindef::DWORD = 1; + // let mut bytes_returned: winapi::shared::minwindef::DWORD = 0; + // let result = unsafe { + // winapi::um::winsock2::WSAIoctl( + // raw_fd as _, + // winapi::shared::mstcpip::SIO_RCVALL, + // &mut rcvall as *mut winapi::shared::minwindef::DWORD as *mut std::ffi::c_void, + // std::mem::size_of::() as winapi::shared::minwindef::DWORD, + // std::ptr::null_mut(), + // 0, + // &mut bytes_returned as winapi::shared::minwindef::LPDWORD, + // std::ptr::null_mut(), + // None, + // ) + // }; + // if result != 0 { + // return Err(io::Error::from_raw_os_error(unsafe { winapi::um::winsock2::WSAGetLastError() })); + // } + // } + Ok(IcmpProxy { + icmp_socket, + icmp_proxy_map, + sender, + current_device, + }) + } + pub fn icmp_socket(&self) ->Arc{ + self.icmp_socket.clone() + } + pub fn start(self) { + let mut buf = [0 as u8; 1500]; + let data: &mut [MaybeUninit] = + unsafe { std::mem::transmute(&mut buf[..]) }; + let mut net_packet = NetPacket::new([0u8; 4 + 8 + 1500]).unwrap(); + net_packet.set_version(Version::V1); + net_packet.set_protocol(Protocol::Ipv4Turn); + net_packet.set_transport_protocol(ipv4::protocol::Protocol::Ipv4.into()); + net_packet.set_ttl(MAX_TTL); + loop { + match self.recv(data) { + Ok((len, peer_ip)) => { + match peer_ip { + IpAddr::V4(peer_ip) => { + match ipv4::packet::IpV4Packet::new(&mut buf[..len]) { + Ok(mut ipv4_packet) => { + match icmp::IcmpPacket::new(ipv4_packet.payload()) { + Ok(icmp_packet) => { + match icmp_packet.header_other() { + HeaderOther::Identifier(id, seq) => { + if let Some(entry) = self.icmp_proxy_map.get(&(peer_ip, id, seq)) { + //将数据发送到真实的来源 + let dest_ip = *entry.value(); + ipv4_packet.set_destination_ip(dest_ip); + ipv4_packet.update_checksum(); + let virtual_ip = self.current_device.load().virtual_ip(); + net_packet.set_source(virtual_ip); + net_packet.set_destination(dest_ip); + let data_len = ipv4_packet.buffer.len(); + net_packet.set_payload(ipv4_packet.buffer); + let _ = self.sender.send_to_id(&net_packet.buffer()[..(12 + data_len)], &dest_ip); + } + } + _ => { + continue; + } + } + } + Err(_) => {} + }; + } + Err(_) => {} + } + } + IpAddr::V6(_) => {} + } + } + Err(e) => { + log::warn!("icmp代理异常:{:?}",e); + } + } + } + } + fn recv(&self, buf: &mut [MaybeUninit]) -> io::Result<(usize, IpAddr)> { + let (size, addr) = self.icmp_socket.recv_from(buf)?; + let addr = match addr.as_socket() { + None => { + IpAddr::V4(Ipv4Addr::UNSPECIFIED) + } + Some(add) => { + add.ip() + } + }; + Ok((size, addr)) + } + // fn send_to(&self, buf: &[u8], addr: SocketAddrV4) -> io::Result { + // self.icmp_socket.send_to(buf, &SockAddr::from(addr)) + // } +} \ No newline at end of file diff --git a/switch/src/ip_proxy/mod.rs b/switch/src/ip_proxy/mod.rs new file mode 100644 index 0000000..c75c7f8 --- /dev/null +++ b/switch/src/ip_proxy/mod.rs @@ -0,0 +1,90 @@ +use std::{io, thread}; +use std::collections::HashMap; +use std::net::{Ipv4Addr, SocketAddrV4}; +use std::sync::Arc; +use crossbeam::atomic::AtomicCell; +use crossbeam_skiplist::SkipMap; +use socket2::{SockAddr, Socket}; +use tokio::net::{TcpListener, UdpSocket}; +use p2p_channel::channel::sender::Sender; +use crate::handle::CurrentDeviceInfo; +use crate::ip_proxy::icmp_proxy::IcmpProxy; +use crate::ip_proxy::tcp_proxy::TcpProxy; +use crate::ip_proxy::udp_proxy::UdpProxy; + +pub mod icmp_proxy; +pub mod tcp_proxy; +pub mod udp_proxy; + +#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)] +pub enum Protocol { + Icmp, + Tcp, + Udp, +} + +#[derive(Clone)] +pub struct IpProxyMap { + pub(crate) tcp_proxy_port: u16, + pub(crate) udp_proxy_port: u16, + //真实源地址 -> (绑定地址,目的地址) + pub(crate) tcp_proxy_map: Arc>, + pub(crate) udp_proxy_map: Arc>, + // icmp用Identifier来区分,没有Identifier的一律不转发 + pub(crate) icmp_proxy_map: Arc>, + icmp_sockets: HashMap>, +} + +impl IpProxyMap { + pub fn send_icmp(&self, buf: &[u8], src: &Ipv4Addr, dest: &Ipv4Addr) -> io::Result { + if let Some(socket) = self.icmp_sockets.get(src) { + socket.send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0))) + } else { + Err(io::Error::new(io::ErrorKind::Other, format!("not found src:{},dest:{}", src, dest))) + } + } +} + +pub async fn init_proxy(sender: Sender, bind_ips: Vec, current_device: Arc>) -> io::Result { + let mut icmp_sockets = HashMap::new(); + let tcp_proxy_map: Arc> = Arc::new(SkipMap::new()); + let udp_proxy_map: Arc> = Arc::new(SkipMap::new()); + let icmp_proxy_map: Arc> = Arc::new(SkipMap::new()); + let tcp_listener = TcpListener::bind("0.0.0.0:0").await?; + let udp_socket = UdpSocket::bind("0.0.0.0:0").await?; + let tcp_proxy_port = tcp_listener.local_addr()?.port(); + let udp_proxy_port = udp_socket.local_addr()?.port(); + + { + let tcp_proxy_map = tcp_proxy_map.clone(); + tokio::spawn(async { + let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map); + tcp_proxy.start().await + }); + } + { + let udp_proxy_map = udp_proxy_map.clone(); + tokio::spawn(async { + let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map); + udp_proxy.start().await + }); + } + for ip in bind_ips { + let addr = SocketAddrV4::new(ip, 0); + let icmp_proxy_map = icmp_proxy_map.clone(); + let icmp_proxy = IcmpProxy::new(addr, icmp_proxy_map, sender.try_clone()?, current_device.clone())?; + icmp_sockets.insert(ip, icmp_proxy.icmp_socket()); + thread::spawn(move || { + icmp_proxy.start(); + }); + } + + Ok(IpProxyMap { + tcp_proxy_port, + udp_proxy_port, + tcp_proxy_map, + udp_proxy_map, + icmp_proxy_map, + icmp_sockets, + }) +} \ No newline at end of file diff --git a/switch/src/ip_proxy/tcp_proxy.rs b/switch/src/ip_proxy/tcp_proxy.rs new file mode 100644 index 0000000..6798003 --- /dev/null +++ b/switch/src/ip_proxy/tcp_proxy.rs @@ -0,0 +1,70 @@ +use std::io; +use std::net::{SocketAddr, SocketAddrV4}; +use std::sync::Arc; +use crossbeam_skiplist::SkipMap; +use tokio::net::{TcpListener, TcpStream}; + +pub struct TcpProxy { + tcp_listener: TcpListener, + // todo 怎么过期 + map: Arc>, +} + +impl TcpProxy { + pub fn new(tcp_listener: TcpListener, map: Arc>) -> Self { + Self { + tcp_listener, + map, + } + } + pub async fn start(self) { + let tcp_listener = self.tcp_listener; + let map = self.map; + loop { + match tcp_listener.accept().await { + Ok((tcp_stream, sender_addr)) => { + match sender_addr { + SocketAddr::V4(sender_addr) => { + if let Some(entry) = map.get(&sender_addr) { + let (src_addr, dest_addr) = *entry.value(); + let peer_tcp_stream = match TcpStream::connect(dest_addr).await { + Ok(peer_tcp_stream) => {peer_tcp_stream} + Err(e) => { + log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr); + continue; + } + }; + tokio::spawn(async move { + match proxy(tcp_stream, peer_tcp_stream).await { + Ok(_) => {} + Err(e) => { + log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr); + } + } + }); + } + } + SocketAddr::V6(_) => {} + } + + } + Err(e) => { + log::warn!("tcp代理监听:{:?}",e); + } + } + + } + } +} + +async fn proxy(mut client: TcpStream, mut server: TcpStream) -> io::Result<()> { + let (mut client_reader, mut client_writer) = client.split(); + let (mut server_reader, mut server_writer) = server.split(); + + let client_to_server = tokio::io::copy(&mut client_reader, &mut server_writer); + let server_to_client = tokio::io::copy(&mut server_reader, &mut client_writer); + + tokio::try_join!(client_to_server, server_to_client)?; + + Ok(()) +} \ No newline at end of file diff --git a/switch/src/ip_proxy/udp_proxy.rs b/switch/src/ip_proxy/udp_proxy.rs new file mode 100644 index 0000000..9e0be3d --- /dev/null +++ b/switch/src/ip_proxy/udp_proxy.rs @@ -0,0 +1,96 @@ +use std::io; +use std::net::{SocketAddr, SocketAddrV4}; +use std::sync::Arc; +use std::time::Duration; +use crossbeam_skiplist::SkipMap; +use tokio::net::UdpSocket; + +/// 一个udp代理,作用是利用系统协议栈,将udp数据报解析出来再转发到目的地址 +pub struct UdpProxy { + udp_socket: Arc, + // todo 过期处理 + map: Arc>, +} + +impl UdpProxy { + pub fn new(udp_socket: UdpSocket, map: Arc>) -> Self { + let udp_socket = Arc::new(udp_socket); + Self { + udp_socket, + map, + } + } + pub async fn start(self) { + let map = self.map; + let udp_socket = self.udp_socket; + let mut buf = [0u8; 65536]; + let inner_map: Arc>> = Arc::new(SkipMap::new()); + + loop { + match udp_socket.recv_from(&mut buf).await { + Ok((len, sender_addr)) => { + match sender_addr { + SocketAddr::V4(sender_addr) => { + match start0(&buf[..len], sender_addr, &inner_map, &map, &udp_socket).await { + Ok(_) => {} + Err(e) => { + log::warn!("udp代理异常:{:?},来源:{}",e,sender_addr); + } + } + } + SocketAddr::V6(_) => {} + } + } + Err(e) => { + log::warn!("udp代理异常:{:?}",e); + } + }; + } + } +} + +async fn start0(buf: &[u8], sender_addr: SocketAddrV4, inner_map: &Arc>>, map: &Arc>, udp_socket: &Arc) -> io::Result<()> { + if let Some(entry) = inner_map.get(&sender_addr) { + entry.value().send(buf).await?; + } else if let Some(entry) = map.get(&sender_addr) { + let (src_addr, dest_addr) = *entry.value(); + let peer_udp_socket = UdpSocket::bind("0.0.0.0:0").await?; + peer_udp_socket.connect(dest_addr).await?; + peer_udp_socket.send(buf).await?; + let peer_udp_socket = Arc::new(peer_udp_socket); + let inner_map = inner_map.clone(); + inner_map.insert(sender_addr, peer_udp_socket.clone()); + let udp_socket = udp_socket.clone(); + tokio::spawn(async move { + let mut buf = [0u8; 65536]; + loop { + match tokio::time::timeout(Duration::from_secs(300), peer_udp_socket.recv(&mut buf)).await { + Ok(rs) => { + match rs { + Ok(len) => { + match udp_socket.send_to(&buf[..len], sender_addr).await { + Ok(_) => {} + Err(e) => { + log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr); + break; + } + } + } + Err(e) => { + log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr); + break; + } + } + } + Err(_) => { + //超时关闭 + log::warn!("udp代理超时关闭,来源:{},目标:{}",src_addr,dest_addr); + break; + } + } + } + inner_map.remove(&sender_addr); + }); + } + Ok(()) +} \ No newline at end of file diff --git a/switch/src/lib.rs b/switch/src/lib.rs index a870d4d..547a74a 100644 --- a/switch/src/lib.rs +++ b/switch/src/lib.rs @@ -11,4 +11,6 @@ pub mod proto; pub mod protocol; pub mod tun_device; pub mod tap_device; +pub mod ip_proxy; +pub mod external_route; pub mod core; diff --git a/switch/src/tun_device/linux.rs b/switch/src/tun_device/linux.rs index 0e5c277..ccc671d 100644 --- a/switch/src/tun_device/linux.rs +++ b/switch/src/tun_device/linux.rs @@ -1,13 +1,16 @@ +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(); @@ -19,20 +22,36 @@ pub fn create_tun( .mtu(1420) // .queues(2) 用多个队列有兼容性问题 .up(); - // - // config.platform(|config| { - // config.packet_information(true); - // }); 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(); - println!("name:{:?}", dev.name()); + 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(()) +} diff --git a/switch/src/tun_device/mac.rs b/switch/src/tun_device/mac.rs index f95dde7..cc53d8e 100644 --- a/switch/src/tun_device/mac.rs +++ b/switch/src/tun_device/mac.rs @@ -11,6 +11,7 @@ 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(); @@ -23,13 +24,17 @@ pub fn create_tun( .up(); let dev = tun::create(&config).unwrap(); - config_ip(dev.name(), address, netmask, gateway)?; - + 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:{:?}", dev.name()); + println!("name:{:?}", name); println!("========TUN网卡配置========"); Ok(( TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))), @@ -37,12 +42,24 @@ pub fn create_tun( )) } +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 route_add_str: String = format!( - "sudo route -n add -net {:?} -netmask {:?} {:?}", - address, netmask, gateway - ); let up_eth_out = Command::new("sh") .arg("-c") .arg(up_eth_str) @@ -51,13 +68,5 @@ pub(crate) fn config_ip(name: &str, address: Ipv4Addr, netmask: Ipv4Addr, gatewa if !up_eth_out.status.success() { return Err(io::Error::new(io::ErrorKind::Other, format!("设置网络地址失败: {:?}", up_eth_out))); } - let if_config_out = Command::new("sh") - .arg("-c") - .arg(route_add_str) - .output() - .expect("sh exec error!"); - if !if_config_out.status.success() { - return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: {:?}", if_config_out))); - } Ok(()) } diff --git a/switch/src/tun_device/windows.rs b/switch/src/tun_device/windows.rs index 5cbdefb..d82f670 100644 --- a/switch/src/tun_device/windows.rs +++ b/switch/src/tun_device/windows.rs @@ -67,6 +67,7 @@ pub fn create_tun( address: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr, + in_ips:Vec<(Ipv4Addr,Ipv4Addr)> ) -> io::Result<(TunWriter, TunReader)> { unsafe { println!("========TUN网卡配置========"); @@ -103,6 +104,9 @@ pub fn create_tun( 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网卡配置========");