Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff4580b9bf | ||
|
|
6daa75d2f2 | ||
|
|
59f07f2d75 | ||
|
|
44035685c8 |
@@ -86,3 +86,11 @@
|
|||||||
- 支持安卓
|
- 支持安卓
|
||||||
- 数据加密
|
- 数据加密
|
||||||
|
|
||||||
|
### 常见问题
|
||||||
|
#### 问题1: 设置网络地址失败
|
||||||
|
##### 可能原因:
|
||||||
|
switch默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突
|
||||||
|
##### 解决方法:
|
||||||
|
1. 方法一:找到冲突的IP,将其改成别的
|
||||||
|
2. 方法二:自建服务器,指定其他不会冲突的网段
|
||||||
|
3. 方法三:增加参数--device-id,设置不同的id会让switch-server分配不同的IP,从而绕开有冲突的IP
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "switch-desktop"
|
name = "switch-desktop"
|
||||||
version = "1.0.4"
|
version = "1.0.5"
|
||||||
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
|
||||||
@@ -28,9 +28,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"
|
||||||
|
|
||||||
|
|||||||
@@ -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,7 @@ 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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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 +91,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");
|
||||||
@@ -181,6 +186,7 @@ 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,
|
||||||
};
|
};
|
||||||
println!("========参数配置========");
|
println!("========参数配置========");
|
||||||
Ok(base_config)
|
Ok(base_config)
|
||||||
@@ -193,7 +199,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");
|
||||||
@@ -284,6 +293,7 @@ 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,
|
||||||
};
|
};
|
||||||
println!("========参数配置========");
|
println!("========参数配置========");
|
||||||
Ok(base_config)
|
Ok(base_config)
|
||||||
@@ -319,6 +329,43 @@ 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,
|
||||||
|
}
|
||||||
|
#[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.5".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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[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 {
|
||||||
|
|||||||
@@ -194,9 +194,12 @@ pub fn console_listen(switch: &Switch) {
|
|||||||
);
|
);
|
||||||
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());
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -252,7 +248,10 @@ fn pause() {
|
|||||||
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();
|
||||||
@@ -305,18 +304,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
|
||||||
|
|||||||
@@ -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,13 @@ 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 +90,76 @@ 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) => {
|
log::error!("auto_config_path()? {:?}",auto_config_path()?);
|
||||||
log::error!("{:?}", e);
|
let config = config::ArgsConfig::new(start_config);
|
||||||
return Err(switch::error::Error::Stop(e));
|
match serde_yaml::to_string(&config) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -132,20 +173,28 @@ async fn start_switch(args: StartArgs) -> switch::Result<Arc<Switch>> {
|
|||||||
start_config.in_ips,
|
start_config.in_ips,
|
||||||
start_config.out_ips,
|
start_config.out_ips,
|
||||||
);
|
);
|
||||||
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() {
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ fn start_heartbeat_(
|
|||||||
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.first_set_ttl(2);
|
||||||
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_to_id(net_packet.buffer(), &peer.virtual_ip)
|
||||||
@@ -103,6 +103,7 @@ fn start_heartbeat_(
|
|||||||
l
|
l
|
||||||
});
|
});
|
||||||
let mut num = 0;
|
let mut num = 0;
|
||||||
|
//只寻找两跳以内能到的目标
|
||||||
net_packet.first_set_ttl(2);
|
net_packet.first_set_ttl(2);
|
||||||
for (peer_ip, route) in route_list.iter() {
|
for (peer_ip, route) in route_list.iter() {
|
||||||
if peer_ip != &peer.virtual_ip && route.metric == 1 {
|
if peer_ip != &peer.virtual_ip && route.metric == 1 {
|
||||||
|
|||||||
@@ -25,37 +25,64 @@ 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)))?;
|
let len = loop {
|
||||||
if server_address != route.addr {
|
match channel.send_to_addr(buf, server_address) {
|
||||||
return Err(Error::Warn(format!("数据来源错误:{:?}", route.addr)));
|
Ok(_) => {
|
||||||
}
|
match channel.recv_from(&mut recv_buf, Some(Duration::from_millis(300))) {
|
||||||
let net_packet = NetPacket::new(&recv_buf[..len])?;
|
Ok((len, route)) => {
|
||||||
return match net_packet.protocol() {
|
if server_address == route.addr {
|
||||||
Protocol::Service => {
|
let net_packet = NetPacket::new(&recv_buf[..len])?;
|
||||||
match service_packet::Protocol::from(net_packet.transport_protocol()) {
|
match net_packet.protocol() {
|
||||||
service_packet::Protocol::RegistrationResponse => {
|
Protocol::Service => {
|
||||||
let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?;
|
match service_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||||
Ok(response)
|
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(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))),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,9 +139,9 @@ impl Register {
|
|||||||
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,7 +153,7 @@ 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_to_addr(buf, self.server_address)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ pub fn create_tap(
|
|||||||
println!("version:{:x?}", tap_device.get_version()?);
|
println!("version:{:x?}", tap_device.get_version()?);
|
||||||
println!("mac:{:x?}", mac);
|
println!("mac:{:x?}", mac);
|
||||||
tap_device.set_ip(address, netmask)?;
|
tap_device.set_ip(address, netmask)?;
|
||||||
|
tap_device.set_metric(1)?;
|
||||||
tap_device.set_mtu(1420)?;
|
tap_device.set_mtu(1420)?;
|
||||||
tap_device.set_status(true)?;
|
tap_device.set_status(true)?;
|
||||||
tap_device.add_route(address, netmask, gateway)?;
|
tap_device.add_route(address, netmask, gateway)?;
|
||||||
|
|||||||
@@ -73,9 +73,8 @@ pub fn create_tun(
|
|||||||
unsafe {
|
unsafe {
|
||||||
println!("========TUN网卡配置========");
|
println!("========TUN网卡配置========");
|
||||||
match Library::new("wintun.dll") {
|
match Library::new("wintun.dll") {
|
||||||
Ok(lib) => match TunDevice::open(lib, TUN_INTERFACE_NAME) {
|
Ok(lib) => match TunDevice::delete_for_name(lib, TUN_INTERFACE_NAME) {
|
||||||
Ok(tun_device) => {
|
Ok(_) => {
|
||||||
let _ = tun_device.delete();
|
|
||||||
thread::sleep(Duration::from_millis(5));
|
thread::sleep(Duration::from_millis(5));
|
||||||
}
|
}
|
||||||
Err(_) => {}
|
Err(_) => {}
|
||||||
@@ -113,8 +112,8 @@ pub fn create_tun(
|
|||||||
};
|
};
|
||||||
println!("name:{:?}", tun_device.get_name()?);
|
println!("name:{:?}", tun_device.get_name()?);
|
||||||
println!("version:{:?}", tun_device.version()?);
|
println!("version:{:?}", tun_device.version()?);
|
||||||
log::error!("创建tun成功 {:?}",tun_device.get_name()?);
|
|
||||||
tun_device.set_ip(address, netmask)?;
|
tun_device.set_ip(address, netmask)?;
|
||||||
|
tun_device.set_metric(1)?;
|
||||||
tun_device.set_mtu(1420)?;
|
tun_device.set_mtu(1420)?;
|
||||||
for (address, netmask) in in_ips {
|
for (address, netmask) in in_ips {
|
||||||
tun_device.add_route(address, netmask, gateway)?;
|
tun_device.add_route(address, netmask, gateway)?;
|
||||||
@@ -132,9 +131,8 @@ pub fn create_tun(
|
|||||||
pub fn delete_tun() {
|
pub fn delete_tun() {
|
||||||
unsafe {
|
unsafe {
|
||||||
match Library::new("wintun.dll") {
|
match Library::new("wintun.dll") {
|
||||||
Ok(lib) => match TunDevice::open(lib, TUN_INTERFACE_NAME) {
|
Ok(lib) => match TunDevice::delete_for_name(lib, TUN_INTERFACE_NAME) {
|
||||||
Ok(tun_device) => {
|
Ok(_) => {
|
||||||
let _ = tun_device.delete();
|
|
||||||
}
|
}
|
||||||
Err(_) => {}
|
Err(_) => {}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -45,4 +45,6 @@ pub trait IFace {
|
|||||||
where IP: Into<net::Ipv4Addr>;
|
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<()>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
@@ -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> {
|
||||||
@@ -150,6 +154,11 @@ impl IFace for TapDevice {
|
|||||||
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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};
|
||||||
|
|
||||||
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,
|
||||||
|
|
||||||
@@ -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,13 @@ 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 +163,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)
|
||||||
})
|
})
|
||||||
@@ -185,6 +193,11 @@ impl IFace for TunDevice {
|
|||||||
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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user