tun2proxy/src/bin/main.rs

87 lines
3.1 KiB
Rust
Raw Normal View History

2024-02-24 20:40:39 +08:00
use tun2proxy::{Args, BoxError};
2024-02-01 19:15:32 +08:00
#[tokio::main]
2024-02-13 10:46:13 +08:00
async fn main() -> Result<(), BoxError> {
2024-02-01 19:15:32 +08:00
dotenvy::dotenv().ok();
let args = Args::parse_args();
2024-03-03 19:49:10 +08:00
// let default = format!("{}={:?},trust_dns_proto=warn", module_path!(), args.verbosity);
let default = format!("{:?},trust_dns_proto=warn", args.verbosity);
2024-02-01 19:15:32 +08:00
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or(default)).init();
2024-02-13 10:46:13 +08:00
let shutdown_token = tokio_util::sync::CancellationToken::new();
2024-02-24 19:24:51 +08:00
let join_handle = tokio::spawn({
let shutdown_token = shutdown_token.clone();
async move {
2024-04-07 21:12:20 +02:00
#[cfg(target_os = "linux")]
if args.unshare && args.socket_transfer_fd.is_none() {
if let Err(err) = namespace_proxy_main(args, shutdown_token).await {
log::error!("namespace proxy error: {}", err);
}
2024-04-07 21:12:20 +02:00
return;
}
if let Err(err) = tun2proxy::desktop_run_async(args, shutdown_token).await {
2024-04-03 22:39:05 +02:00
log::error!("main loop error: {}", err);
2024-02-24 19:24:51 +08:00
}
}
});
2024-02-01 19:15:32 +08:00
ctrlc2::set_async_handler(async move {
log::info!("Ctrl-C received, exiting...");
shutdown_token.cancel();
2024-02-01 19:15:32 +08:00
})
.await;
if let Err(err) = join_handle.await {
2024-02-24 23:38:52 +01:00
log::error!("main_entry error {}", err);
2024-02-01 19:15:32 +08:00
}
Ok(())
}
#[cfg(target_os = "linux")]
async fn namespace_proxy_main(
_args: Args,
_shutdown_token: tokio_util::sync::CancellationToken,
) -> Result<std::process::ExitStatus, tun2proxy::Error> {
use std::os::fd::AsRawFd;
let (socket, remote_fd) = tun2proxy::socket_transfer::create_transfer_socket_pair().await?;
let child = tokio::process::Command::new("unshare")
.args("--user --map-current-user --net --mount --keep-caps --kill-child --fork".split(' '))
.arg(std::env::current_exe()?)
.arg("--socket-transfer-fd")
.arg(remote_fd.as_raw_fd().to_string())
.args(std::env::args().skip(1))
.kill_on_drop(true)
.spawn();
let mut child = match child {
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
log::error!("`unshare(1)` executable wasn't located in PATH.");
log::error!("Consider installing linux utils package: `apt install util-linux`");
log::error!("Or similar for your distribution.");
return Err(err.into());
}
child => child?,
};
log::info!("The tun proxy is running in unprivileged mode. See `namespaces(7)`.");
log::info!("");
log::info!("If you need to run a process that relies on root-like capabilities (e.g. `openvpn`)");
log::info!("Use `tun2proxy --unshare --setup [...] -- openvpn --config [...]`");
log::info!("");
log::info!("To run a new process in the created namespace (e.g. a flatpak app)");
log::info!(
"Use `nsenter --preserve-credentials --user --net --mount --target {} /bin/sh`",
child.id().unwrap_or(0)
);
log::info!("");
tokio::spawn(async move { tun2proxy::socket_transfer::process_socket_requests(&socket).await });
Ok(child.wait().await?)
}