2023-03-22 11:17:28 +01:00
|
|
|
use clap::Parser;
|
2023-07-23 02:03:15 +08:00
|
|
|
use std::{net::IpAddr, process::ExitCode};
|
|
|
|
use tun2proxy::{error::Error, main_entry, NetworkInterface, Options, Proxy};
|
2023-03-20 14:13:06 +08:00
|
|
|
|
2023-04-10 20:59:54 +02:00
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
use tun2proxy::setup::{get_default_cidrs, Setup};
|
|
|
|
|
2023-03-20 14:13:06 +08:00
|
|
|
/// Tunnel interface to proxy
|
|
|
|
#[derive(Parser)]
|
|
|
|
#[command(author, version, about = "Tunnel interface to proxy.", long_about = None)]
|
|
|
|
struct Args {
|
|
|
|
/// Name of the tun interface
|
2023-03-22 11:17:28 +01:00
|
|
|
#[arg(short, long, value_name = "name", default_value = "tun0")]
|
2023-03-20 14:13:06 +08:00
|
|
|
tun: String,
|
|
|
|
|
2023-04-13 21:54:02 +02:00
|
|
|
/// File descriptor of the tun interface
|
|
|
|
#[arg(long, value_name = "fd")]
|
|
|
|
tun_fd: Option<i32>,
|
|
|
|
|
|
|
|
/// MTU of the tun interface (only with tunnel file descriptor)
|
|
|
|
#[arg(long, value_name = "mtu", default_value = "1500")]
|
|
|
|
tun_mtu: usize,
|
|
|
|
|
2023-03-23 21:59:18 +01:00
|
|
|
/// Proxy URL in the form proto://[username[:password]@]host:port
|
2023-03-23 18:01:25 +01:00
|
|
|
#[arg(short, long, value_parser = Proxy::from_url, value_name = "URL")]
|
2023-03-22 13:18:07 +01:00
|
|
|
proxy: Proxy,
|
2023-03-23 13:03:01 +01:00
|
|
|
|
2023-03-23 21:59:18 +01:00
|
|
|
/// DNS handling
|
2023-08-08 23:45:16 +08:00
|
|
|
#[arg(short, long, value_name = "method", value_enum, default_value = "virtual")]
|
2023-03-23 21:59:18 +01:00
|
|
|
dns: ArgDns,
|
2023-03-25 21:12:41 +01:00
|
|
|
|
2023-03-26 00:46:59 +01:00
|
|
|
/// Routing and system setup
|
2023-03-25 21:12:41 +01:00
|
|
|
#[arg(short, long, value_name = "method", value_enum)]
|
2023-03-26 00:46:59 +01:00
|
|
|
setup: Option<ArgSetup>,
|
2023-03-26 11:02:13 +02:00
|
|
|
|
2023-07-23 02:03:15 +08:00
|
|
|
/// Public proxy IP used in routing setup which should bypassing the tunnel
|
2023-03-26 11:07:06 +02:00
|
|
|
#[arg(long, value_name = "IP")]
|
2023-07-23 02:03:15 +08:00
|
|
|
bypass_ip: Option<IpAddr>,
|
2023-08-08 11:37:24 +08:00
|
|
|
|
|
|
|
/// Verbosity level
|
|
|
|
#[arg(short, long, value_name = "level", value_enum, default_value = "info")]
|
|
|
|
verbosity: ArgVerbosity,
|
2023-08-21 19:58:13 +08:00
|
|
|
|
2023-08-22 23:43:27 +08:00
|
|
|
/// Enable DNS over TCP
|
2023-08-21 19:58:13 +08:00
|
|
|
#[arg(long)]
|
|
|
|
dns_over_tcp: bool,
|
2023-03-23 21:59:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)]
|
|
|
|
enum ArgDns {
|
|
|
|
Virtual,
|
|
|
|
None,
|
2023-03-22 11:17:28 +01:00
|
|
|
}
|
|
|
|
|
2023-03-25 21:12:41 +01:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)]
|
|
|
|
enum ArgSetup {
|
|
|
|
Auto,
|
|
|
|
}
|
|
|
|
|
2023-08-08 11:37:24 +08:00
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)]
|
|
|
|
enum ArgVerbosity {
|
|
|
|
Off,
|
|
|
|
Error,
|
|
|
|
Warn,
|
|
|
|
Info,
|
|
|
|
Debug,
|
|
|
|
Trace,
|
|
|
|
}
|
|
|
|
|
2023-03-25 21:41:40 +01:00
|
|
|
fn main() -> ExitCode {
|
2023-03-23 13:28:05 +01:00
|
|
|
dotenvy::dotenv().ok();
|
2023-03-22 11:17:28 +01:00
|
|
|
let args = Args::parse();
|
|
|
|
|
2023-08-08 11:37:24 +08:00
|
|
|
let default = format!("{}={:?}", module_path!(), args.verbosity);
|
|
|
|
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or(default)).init();
|
|
|
|
|
2023-03-22 11:17:28 +01:00
|
|
|
let addr = args.proxy.addr;
|
2023-03-22 12:18:41 +01:00
|
|
|
let proxy_type = args.proxy.proxy_type;
|
|
|
|
log::info!("Proxy {proxy_type} server: {addr}");
|
|
|
|
|
2023-03-23 13:03:01 +01:00
|
|
|
let mut options = Options::new();
|
2023-03-23 21:59:18 +01:00
|
|
|
if args.dns == ArgDns::Virtual {
|
2023-03-23 13:03:01 +01:00
|
|
|
options = options.with_virtual_dns();
|
|
|
|
}
|
|
|
|
|
2023-08-21 19:58:13 +08:00
|
|
|
if args.dns_over_tcp {
|
|
|
|
options = options.with_dns_over_tcp();
|
|
|
|
}
|
|
|
|
|
2023-04-13 21:54:02 +02:00
|
|
|
let interface = match args.tun_fd {
|
|
|
|
None => NetworkInterface::Named(args.tun.clone()),
|
|
|
|
Some(fd) => {
|
|
|
|
options = options.with_mtu(args.tun_mtu);
|
|
|
|
NetworkInterface::Fd(fd)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-07-23 02:03:15 +08:00
|
|
|
let block = || -> Result<(), Error> {
|
2023-04-10 20:59:54 +02:00
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
{
|
|
|
|
let mut setup: Setup;
|
|
|
|
if args.setup == Some(ArgSetup::Auto) {
|
2023-07-23 02:03:15 +08:00
|
|
|
let bypass_tun_ip = match args.bypass_ip {
|
2023-04-10 20:59:54 +02:00
|
|
|
Some(addr) => addr,
|
|
|
|
None => args.proxy.addr.ip(),
|
|
|
|
};
|
2023-08-08 23:45:16 +08:00
|
|
|
setup = Setup::new(&args.tun, &bypass_tun_ip, get_default_cidrs(), args.bypass_ip.is_some());
|
2023-04-10 20:59:54 +02:00
|
|
|
|
|
|
|
setup.configure()?;
|
|
|
|
|
|
|
|
setup.drop_privileges()?;
|
|
|
|
}
|
2023-03-25 21:12:41 +01:00
|
|
|
}
|
|
|
|
|
2023-04-10 23:24:53 +02:00
|
|
|
main_entry(&interface, &args.proxy, options)?;
|
2023-04-01 02:19:20 +02:00
|
|
|
|
|
|
|
Ok(())
|
2023-07-23 02:03:15 +08:00
|
|
|
};
|
|
|
|
if let Err(e) = block() {
|
2023-03-24 09:27:31 +08:00
|
|
|
log::error!("{e}");
|
2023-04-03 00:39:13 +02:00
|
|
|
return ExitCode::FAILURE;
|
2023-07-23 02:03:15 +08:00
|
|
|
}
|
2023-04-01 02:19:20 +02:00
|
|
|
|
2023-03-25 21:41:40 +01:00
|
|
|
ExitCode::SUCCESS
|
2021-09-02 11:30:23 +02:00
|
|
|
}
|