tun2proxy/src/desktop_api.rs

156 lines
4.6 KiB
Rust
Raw Normal View History

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};
2024-02-25 16:59:18 +08:00
use tun2::{AbstractDevice, DEFAULT_MTU as MTU};
2024-02-13 10:46:13 +08:00
static TUN_QUIT: std::sync::Mutex<Option<tokio_util::sync::CancellationToken>> = std::sync::Mutex::new(None);
/// # Safety
///
/// Run the tun2proxy component with some arguments.
2024-02-29 07:08:44 +03:30
/// Parameters:
/// - proxy_url: the proxy url, e.g. "socks5://127.0.0.1:1080"
/// - tun: the tun device name, e.g. "utun5"
/// - bypass: the bypass ip, e.g. "123.45.67.89"
/// - dns_strategy: the dns strategy, see ArgDns enum
/// - root_privilege: whether to run with root privilege
/// - verbosity: the verbosity level, see ArgVerbosity enum
2024-02-13 10:46:13 +08:00
#[no_mangle]
2024-02-29 07:08:44 +03:30
pub unsafe extern "C" fn tun2proxy_with_name_run(
2024-02-13 10:46:13 +08:00
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,
},
};
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);
2024-02-25 16:59:18 +08:00
} else if let Some(ref tun) = args.tun {
config.tun_name(tun);
2024-02-13 10:46:13 +08:00
}
#[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_mut, unused_assignments, unused_variables)]
let mut setup = true;
let device = tun2::create_as_async(&config)?;
2024-02-25 16:59:18 +08:00
if let Ok(tun_name) = device.as_ref().tun_name() {
tproxy_args = tproxy_args.tun_name(&tun_name);
}
let mut restore: Option<tproxy_config::TproxyRestore> = None;
2024-02-13 10:46:13 +08:00
#[cfg(target_os = "linux")]
{
setup = args.setup;
}
2024-02-25 16:59:18 +08:00
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
2024-02-13 10:46:13 +08:00
if setup {
restore = Some(tproxy_config::tproxy_setup(&tproxy_args)?);
2024-02-13 10:46:13 +08:00
}
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"))]
2024-02-25 22:20:54 +08:00
if setup {
tproxy_config::tproxy_remove(restore)?;
2024-02-13 10:46:13 +08:00
}
Ok::<(), std::io::Error>(())
}
/// # Safety
///
/// Shutdown the tun2proxy component.
#[no_mangle]
2024-02-29 07:08:44 +03:30
pub unsafe extern "C" fn tun2proxy_with_name_stop() -> c_int {
2024-03-06 18:01:02 +08:00
if let Ok(mut lock) = TUN_QUIT.lock() {
if let Some(shutdown_token) = lock.take() {
2024-02-13 10:46:13 +08:00
shutdown_token.cancel();
return 0;
}
}
-1
}