diff --git a/src/args.rs b/src/args.rs index b0766f6..e5d1ca5 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,9 +1,10 @@ use crate::{Error, Result}; use socks5_impl::protocol::UserKey; -use std::{ - ffi::OsString, - net::{IpAddr, SocketAddr, ToSocketAddrs}, -}; + +#[cfg(target_os = "linux")] +use std::ffi::OsString; + +use std::net::{IpAddr, SocketAddr, ToSocketAddrs}; #[derive(Debug, Clone, clap::Parser)] #[command(author, version, about = "Tunnel interface to proxy.", long_about = None)] @@ -25,17 +26,21 @@ pub struct Args { /// Create a tun interface in a newly created unprivileged namespace /// while maintaining proxy connectivity via the global network namespace. + #[cfg(target_os = "linux")] #[arg(long)] pub unshare: bool, /// File descriptor for UNIX datagram socket meant to transfer /// network sockets from global namespace to the new one. /// See `unshare(1)`, `namespaces(7)`, `sendmsg(2)`, `unix(7)`. - #[arg(long, value_name = "fd")] + #[cfg(target_os = "linux")] + #[arg(long, value_name = "fd", hide(true))] pub socket_transfer_fd: Option, - /// Specify a command to run with root-like capabilities in the new namespace. + /// Specify a command to run with root-like capabilities in the new namespace + /// when using `--unshare`. /// This could be useful to start additional daemons, e.g. `openvpn` instance. + #[cfg(target_os = "linux")] #[arg(requires = "unshare")] pub admin_command: Vec, @@ -91,8 +96,11 @@ impl Default for Args { proxy: ArgProxy::default(), tun: None, tun_fd: None, + #[cfg(target_os = "linux")] unshare: false, + #[cfg(target_os = "linux")] socket_transfer_fd: None, + #[cfg(target_os = "linux")] admin_command: Vec::new(), ipv6_enabled: false, setup, diff --git a/src/bin/main.rs b/src/bin/main.rs index 1723895..4984050 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -13,14 +13,15 @@ async fn main() -> Result<(), BoxError> { let join_handle = tokio::spawn({ let shutdown_token = shutdown_token.clone(); async move { + #[cfg(target_os = "linux")] if args.unshare && args.socket_transfer_fd.is_none() { - #[cfg(target_os = "linux")] if let Err(err) = namespace_proxy_main(args, shutdown_token).await { log::error!("namespace proxy error: {}", err); } - #[cfg(not(target_os = "linux"))] - log::error!("Your platform doesn't support unprivileged namespaces"); - } else if let Err(err) = tun2proxy::desktop_run_async(args, shutdown_token).await { + return; + } + + if let Err(err) = tun2proxy::desktop_run_async(args, shutdown_token).await { log::error!("main loop error: {}", err); } } diff --git a/src/desktop_api.rs b/src/desktop_api.rs index 72da377..e1fc29e 100644 --- a/src/desktop_api.rs +++ b/src/desktop_api.rs @@ -149,6 +149,7 @@ pub async fn desktop_run_async(args: Args, shutdown_token: tokio_util::sync::Can run_ip_util(format!("-6 route delete 80::/1 dev {}", tproxy_args.tun_name)); } + #[cfg(target_os = "linux")] if setup && args.unshare { // New namespace doesn't have any other routing device by default // So our `tun` device should act as such to make space for other proxies. @@ -164,27 +165,27 @@ pub async fn desktop_run_async(args: Args, shutdown_token: tokio_util::sync::Can run_ip_util(format!("-6 route add ::/0 dev {}", tproxy_args.tun_name)); } } - } - let mut admin_command_args = args.admin_command.iter(); - if let Some(command) = admin_command_args.next() { - let child = tokio::process::Command::new(command) - .args(admin_command_args) - .kill_on_drop(true) - .spawn(); + let mut admin_command_args = args.admin_command.iter(); + if let Some(command) = admin_command_args.next() { + let child = tokio::process::Command::new(command) + .args(admin_command_args) + .kill_on_drop(true) + .spawn(); - match child { - Err(err) => { - log::warn!("Failed to start admin process: {err}"); - } - Ok(mut child) => { - tokio::spawn(async move { - if let Err(err) = child.wait().await { - log::warn!("Admin process terminated: {err}"); - } - }); - } - }; + match child { + Err(err) => { + log::warn!("Failed to start admin process: {err}"); + } + Ok(mut child) => { + tokio::spawn(async move { + if let Err(err) = child.wait().await { + log::warn!("Admin process terminated: {err}"); + } + }); + } + }; + } } let join_handle = tokio::spawn(crate::run(device, MTU, args, shutdown_token));