diff --git a/README.md b/README.md index 7907b15..10565e9 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,7 @@ Options: -b, --bypass IPs used in routing setup which should bypass the tunnel, in the form of IP or IP/CIDR. Multiple IPs can be specified, e.g. --bypass 3.4.5.0/24 --bypass 5.6.7.8 --tcp-timeout TCP timeout in seconds [default: 600] + --tcp-mss MSS advertised in the SYN-ACK to the kernel side [default: none] --udp-timeout UDP timeout in seconds [default: 10] -v, --verbosity Verbosity level [default: info] [possible values: off, error, warn, info, debug, trace] --daemonize Daemonize for unix family or run as Windows service diff --git a/src/args.rs b/src/args.rs index fa6a8a2..1976cbe 100644 --- a/src/args.rs +++ b/src/args.rs @@ -116,6 +116,14 @@ pub struct Args { #[arg(long, value_name = "seconds", default_value = "600")] pub tcp_timeout: u64, + /// MSS advertised in the SYN-ACK to the kernel side. By default the userspace + /// stack sends no MSS option, so the peer OS falls back to its own default + /// (e.g. 512 on macOS), fragmenting large first segments such as a TLS + /// ClientHello. Set this to the tunnel's (MTU - 40) to let the peer send big + /// segments. `None` keeps the previous behaviour (no option advertised). + #[arg(long, value_name = "bytes")] + pub tcp_mss: Option, + /// UDP timeout in seconds #[arg(long, value_name = "seconds", default_value = "10")] pub udp_timeout: u64, @@ -191,6 +199,7 @@ impl Default for Args { bypass: vec![], mtu: tun::DEFAULT_MTU, tcp_timeout: 600, + tcp_mss: None, udp_timeout: 10, verbosity: ArgVerbosity::Info, virtual_dns_pool: IpCidr::from_str("198.18.0.0/15").unwrap(), diff --git a/src/lib.rs b/src/lib.rs index 2830517..52addbb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -243,6 +243,9 @@ where ipstack_config.mtu(mtu)?; let mut tcp_cfg = ipstack::TcpConfig::default(); tcp_cfg.timeout = std::time::Duration::from_secs(args.tcp_timeout); + if let Some(mss) = args.tcp_mss { + tcp_cfg.options = Some(vec![ipstack::TcpOptions::MaximumSegmentSize(mss)]); + } ipstack_config.with_tcp_config(tcp_cfg); ipstack_config.udp_timeout(std::time::Duration::from_secs(args.udp_timeout));