2024-02-13 10:46:13 +08:00
|
|
|
#![cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
args::{ArgDns, ArgProxy},
|
|
|
|
ArgVerbosity, Args,
|
|
|
|
};
|
|
|
|
use std::os::raw::{c_char, c_int};
|
|
|
|
use tproxy_config::{TproxyArgs, TUN_GATEWAY, TUN_IPV4, TUN_NETMASK};
|
|
|
|
use tun2::DEFAULT_MTU as MTU;
|
|
|
|
|
|
|
|
static TUN_QUIT: std::sync::Mutex<Option<tokio_util::sync::CancellationToken>> = std::sync::Mutex::new(None);
|
|
|
|
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// Run the tun2proxy component with some arguments.
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn tun2proxy_run_with_name(
|
|
|
|
proxy_url: *const c_char,
|
|
|
|
tun: *const c_char,
|
|
|
|
bypass: *const c_char,
|
|
|
|
dns_strategy: ArgDns,
|
|
|
|
_root_privilege: bool,
|
|
|
|
verbosity: ArgVerbosity,
|
|
|
|
) -> c_int {
|
|
|
|
let shutdown_token = tokio_util::sync::CancellationToken::new();
|
|
|
|
{
|
|
|
|
if let Ok(mut lock) = TUN_QUIT.lock() {
|
|
|
|
if lock.is_some() {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*lock = Some(shutdown_token.clone());
|
|
|
|
} else {
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log::set_max_level(verbosity.into());
|
|
|
|
log::set_boxed_logger(Box::<crate::dump_logger::DumpLogger>::default()).unwrap();
|
|
|
|
|
|
|
|
let proxy_url = std::ffi::CStr::from_ptr(proxy_url).to_str().unwrap();
|
|
|
|
let proxy = ArgProxy::from_url(proxy_url).unwrap();
|
|
|
|
let tun = std::ffi::CStr::from_ptr(tun).to_str().unwrap().to_string();
|
|
|
|
|
|
|
|
let mut args = Args::default();
|
|
|
|
args.proxy(proxy).tun(tun).dns(dns_strategy).verbosity(verbosity);
|
|
|
|
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
args.setup(_root_privilege);
|
|
|
|
|
|
|
|
if let Ok(bypass) = std::ffi::CStr::from_ptr(bypass).to_str() {
|
|
|
|
args.bypass(bypass.parse().unwrap());
|
|
|
|
}
|
|
|
|
|
2024-02-24 20:40:39 +08:00
|
|
|
let main_loop = async move {
|
|
|
|
if let Err(err) = desktop_run_async(args, shutdown_token).await {
|
|
|
|
log::error!("main loop error: {}", err);
|
|
|
|
return Err(err);
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
};
|
|
|
|
|
2024-02-13 10:46:13 +08:00
|
|
|
let exit_code = match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
|
|
|
|
Err(_e) => -3,
|
2024-02-24 20:40:39 +08:00
|
|
|
Ok(rt) => match rt.block_on(main_loop) {
|
2024-02-13 10:46:13 +08:00
|
|
|
Ok(_) => 0,
|
|
|
|
Err(_e) => -4,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
// release shutdown token before exit.
|
|
|
|
if let Ok(mut lock) = TUN_QUIT.lock() {
|
|
|
|
let _ = lock.take();
|
|
|
|
}
|
|
|
|
|
|
|
|
exit_code
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Run the tun2proxy component with some arguments.
|
|
|
|
pub async fn desktop_run_async(args: Args, shutdown_token: tokio_util::sync::CancellationToken) -> std::io::Result<()> {
|
|
|
|
let bypass_ips = args.bypass.clone();
|
|
|
|
|
|
|
|
let mut config = tun2::Configuration::default();
|
|
|
|
config.address(TUN_IPV4).netmask(TUN_NETMASK).mtu(MTU).up();
|
|
|
|
config.destination(TUN_GATEWAY);
|
|
|
|
if let Some(tun_fd) = args.tun_fd {
|
|
|
|
config.raw_fd(tun_fd);
|
|
|
|
} else {
|
|
|
|
config.name(&args.tun);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
config.platform_config(|config| {
|
|
|
|
#[allow(deprecated)]
|
|
|
|
config.packet_information(true);
|
|
|
|
config.ensure_root_privileges(args.setup);
|
|
|
|
});
|
|
|
|
|
|
|
|
#[cfg(target_os = "windows")]
|
|
|
|
config.platform_config(|config| {
|
|
|
|
config.device_guid(Some(12324323423423434234_u128));
|
|
|
|
});
|
|
|
|
|
|
|
|
#[allow(unused_variables)]
|
|
|
|
let mut tproxy_args = TproxyArgs::new()
|
|
|
|
.tun_dns(args.dns_addr)
|
|
|
|
.proxy_addr(args.proxy.addr)
|
|
|
|
.bypass_ips(&bypass_ips);
|
|
|
|
#[allow(unused_assignments)]
|
|
|
|
if args.tun_fd.is_none() {
|
|
|
|
tproxy_args = tproxy_args.tun_name(&args.tun);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(unused_mut, unused_assignments, unused_variables)]
|
|
|
|
let mut setup = true;
|
|
|
|
|
2024-02-25 00:45:42 +01:00
|
|
|
let device = tun2::create_as_async(&config)?;
|
|
|
|
|
2024-02-13 10:46:13 +08:00
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
{
|
|
|
|
setup = args.setup;
|
|
|
|
if setup {
|
2024-02-25 00:45:42 +01:00
|
|
|
log::trace!("Entering route setup");
|
2024-02-13 10:46:13 +08:00
|
|
|
tproxy_config::tproxy_setup(&tproxy_args)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
|
|
|
if setup {
|
|
|
|
tproxy_config::tproxy_setup(&tproxy_args)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
log::info!("Proxy {} server: {}", args.proxy.proxy_type, args.proxy.addr);
|
|
|
|
|
|
|
|
let join_handle = tokio::spawn(crate::run(device, MTU, args, shutdown_token));
|
|
|
|
join_handle.await.map_err(std::io::Error::from)??;
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
|
|
|
|
if setup {
|
|
|
|
tproxy_config::tproxy_remove(&tproxy_args)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok::<(), std::io::Error>(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// Shutdown the tun2proxy component.
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn tun2proxy_stop() -> c_int {
|
|
|
|
if let Ok(lock) = TUN_QUIT.lock() {
|
|
|
|
if let Some(shutdown_token) = lock.as_ref() {
|
|
|
|
shutdown_token.cancel();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
-1
|
|
|
|
}
|