Browse Source

cli: add --mtu flag for tun2proxy-bin

The bin always passes `tun::DEFAULT_MTU` (1500) to `general_run_async`,
which the userspace TCP stack then uses to derive the MSS of segments
written into the TUN. When the TUN traffic is forwarded onwards over a
link with a smaller MTU (a WireGuard underlay at 1420 is the common
case), the kernel either fragments or, with the DF bit set, silently
drops segments larger than the next-hop MTU, and the resulting
black-hole is hard to diagnose because the proxy-side TCP looks
healthy end to end. Setting the iface MTU alone is not enough because
the userspace stack derives MSS from the value passed at startup, not
from the live iface MTU.

`tun2proxy::general_api::general_run_for_api` already takes a `tun_mtu`
parameter from the C/JNI APIs, so this just plumbs the same value
through the CLI path. Default stays at 1500, so behaviour for existing
users is unchanged.

Signed-off-by: DL6ER <[email protected]>
pull/252/head
DL6ER 4 weeks ago
parent
commit
e0a0d14420
No known key found for this signature in database GPG Key ID: 135ACBD90B28DD
  1. 9
      src/args.rs
  2. 3
      src/bin/main.rs

9
src/args.rs

@ -104,6 +104,14 @@ pub struct Args {
#[arg(short, long, value_name = "IP/CIDR")]
pub bypass: Vec<IpCidr>,
/// MTU of the TUN device. Userspace TCP stack uses (MTU - 40) as the
/// effective MSS for synthesized segments going to the kernel side, so
/// lower this when the kernel forwards the traffic onwards through a
/// link with a smaller MTU (e.g. a WireGuard tunnel at 1420) to avoid
/// having the bigger segments silently dropped.
#[arg(long, value_name = "bytes", default_value_t = tun::DEFAULT_MTU)]
pub mtu: u16,
/// TCP timeout in seconds
#[arg(long, value_name = "seconds", default_value = "600")]
pub tcp_timeout: u64,
@ -181,6 +189,7 @@ impl Default for Args {
dns: ArgDns::default(),
dns_addr: "8.8.8.8".parse().unwrap(),
bypass: vec![],
mtu: tun::DEFAULT_MTU,
tcp_timeout: 600,
udp_timeout: 10,
verbosity: ArgVerbosity::Info,

3
src/bin/main.rs

@ -77,7 +77,8 @@ async fn main_async(args: Args) -> Result<(), BoxError> {
}
unsafe { tun2proxy::tun2proxy_set_traffic_status_callback(1, Some(traffic_cb), std::ptr::null_mut()) };
let ret = tun2proxy::general_run_async(args, tun::DEFAULT_MTU, cfg!(target_os = "macos"), shutdown_token).await;
let mtu = args.mtu;
let ret = tun2proxy::general_run_async(args, mtu, cfg!(target_os = "macos"), shutdown_token).await;
if let Err(err) = &ret {
log::error!("main loop error: {err}");
}

Loading…
Cancel
Save