diff options
| author | David Lönnhager <david.l@mullvad.net> | 2021-03-02 15:49:23 +0100 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2021-04-13 13:06:30 +0200 |
| commit | 14a349fcdb266057bd7265879758f212f7a4224c (patch) | |
| tree | 413faca6954dbf2f6816d83119c5722b7a8005ac | |
| parent | db2accf33367d37d71c907333af6885032329e68 (diff) | |
| download | mullvadvpn-14a349fcdb266057bd7265879758f212f7a4224c.tar.xz mullvadvpn-14a349fcdb266057bd7265879758f212f7a4224c.zip | |
Add TCP WireGuard custom tunnel option
| -rw-r--r-- | Cargo.lock | 150 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/relay.rs | 72 | ||||
| -rw-r--r-- | mullvad-daemon/src/management_interface.rs | 31 | ||||
| -rw-r--r-- | mullvad-daemon/src/relays.rs | 1 | ||||
| -rw-r--r-- | mullvad-management-interface/proto/management_interface.proto | 1 | ||||
| -rw-r--r-- | talpid-core/Cargo.toml | 4 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/mod.rs | 2 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/mod.rs | 98 | ||||
| -rw-r--r-- | talpid-types/src/net/wireguard.rs | 10 |
9 files changed, 221 insertions, 148 deletions
diff --git a/Cargo.lock b/Cargo.lock index ab08657340..1524765cb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,8 +445,11 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" dependencies = [ + "atty", + "humantime 1.3.0", "log 0.4.14", "regex", + "termcolor", ] [[package]] @@ -456,7 +459,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26ecb66b4bdca6c1409b40fb255eefc2bd4f6d135dab3c3124f80ffa2a9661e" dependencies = [ "atty", - "humantime", + "humantime 2.1.0", "log 0.4.14", "regex", "termcolor", @@ -777,7 +780,7 @@ dependencies = [ "http", "indexmap", "slab", - "tokio 0.2.25", + "tokio", "tokio-util 0.3.1", "tracing", "tracing-futures", @@ -858,6 +861,15 @@ checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" [[package]] name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" @@ -880,7 +892,7 @@ dependencies = [ "itoa", "pin-project 1.0.5", "socket2", - "tokio 0.2.25", + "tokio", "tower-service", "tracing", "want", @@ -899,7 +911,7 @@ dependencies = [ "log 0.4.14", "rustls", "rustls-native-certs", - "tokio 0.2.25", + "tokio", "tokio-rustls", "webpki", ] @@ -1159,19 +1171,6 @@ dependencies = [ ] [[package]] -name = "mio" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5dede4e2065b3842b8b0af444119f3aa331cc7cc2dd20388bfb0f5d5a38823a" -dependencies = [ - "libc", - "log 0.4.14", - "miow 0.3.6", - "ntapi", - "winapi 0.3.9", -] - -[[package]] name = "mio-extras" version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1179,7 +1178,7 @@ checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" dependencies = [ "lazycell", "log 0.4.14", - "mio 0.6.23", + "mio", "slab", ] @@ -1190,7 +1189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656" dependencies = [ "log 0.4.14", - "mio 0.6.23", + "mio", "miow 0.3.6", "winapi 0.3.9", ] @@ -1203,7 +1202,7 @@ checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" dependencies = [ "iovec", "libc", - "mio 0.6.23", + "mio", ] [[package]] @@ -1266,7 +1265,7 @@ dependencies = [ "natord", "serde", "talpid-types", - "tokio 0.2.25", + "tokio", "winapi 0.3.9", "winres", ] @@ -1304,7 +1303,7 @@ dependencies = [ "talpid-core", "talpid-platform-metadata", "talpid-types", - "tokio 0.2.25", + "tokio", "triggered", "uuid", "winapi 0.3.9", @@ -1341,7 +1340,7 @@ dependencies = [ "rand 0.7.3", "talpid-core", "talpid-types", - "tokio 0.2.25", + "tokio", ] [[package]] @@ -1356,7 +1355,7 @@ dependencies = [ "parity-tokio-ipc", "prost", "prost-types", - "tokio 0.2.25", + "tokio", "tonic", "tonic-build", "tower", @@ -1387,7 +1386,7 @@ dependencies = [ "regex", "talpid-platform-metadata", "talpid-types", - "tokio 0.2.25", + "tokio", "uuid", "winapi 0.3.9", "winres", @@ -1415,7 +1414,7 @@ dependencies = [ "socket2", "talpid-types", "tempfile", - "tokio 0.2.25", + "tokio", "tokio-rustls", "urlencoding", "webpki", @@ -1436,7 +1435,7 @@ dependencies = [ "mullvad-types", "talpid-core", "talpid-types", - "tokio 0.2.25", + "tokio", "widestring", "winapi 0.3.9", "winres", @@ -1530,7 +1529,7 @@ dependencies = [ "log 0.4.14", "netlink-packet-core", "netlink-sys 0.5.0", - "tokio 0.2.25", + "tokio", "tokio-util 0.2.0", ] @@ -1553,8 +1552,8 @@ dependencies = [ "futures", "libc", "log 0.4.14", - "mio 0.6.23", - "tokio 0.2.25", + "mio", + "tokio", ] [[package]] @@ -1605,6 +1604,18 @@ dependencies = [ ] [[package]] +name = "nix" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +dependencies = [ + "bitflags 1.2.1", + "cc", + "cfg-if 1.0.0", + "libc", +] + +[[package]] name = "notify" version = "4.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1616,22 +1627,13 @@ dependencies = [ "fsevent-sys", "inotify", "libc", - "mio 0.6.23", + "mio", "mio-extras", "walkdir", "winapi 0.3.9", ] [[package]] -name = "ntapi" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] name = "num-integer" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1711,7 +1713,7 @@ dependencies = [ "mio-named-pipes", "miow 0.3.6", "rand 0.7.3", - "tokio 0.2.25", + "tokio", "winapi 0.3.9", ] @@ -2651,7 +2653,7 @@ dependencies = [ "talpid-platform-metadata", "talpid-types", "tempfile", - "tokio 0.2.25", + "tokio", "tonic", "tonic-build", "triggered", @@ -2688,7 +2690,7 @@ dependencies = [ "parity-tokio-ipc", "prost", "talpid-types", - "tokio 0.2.25", + "tokio", "tonic", "tonic-build", "tower", @@ -2812,34 +2814,18 @@ dependencies = [ "lazy_static", "libc", "memchr", - "mio 0.6.23", + "mio", "mio-named-pipes", "mio-uds", "num_cpus", "pin-project-lite 0.1.11", "signal-hook-registry", "slab", - "tokio-macros 0.2.6", + "tokio-macros", "winapi 0.3.9", ] [[package]] -name = "tokio" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8190d04c665ea9e6b6a0dc45523ade572c088d2e6566244c1122671dbf4ae3a" -dependencies = [ - "autocfg", - "bytes 1.0.1", - "libc", - "memchr", - "mio 0.7.9", - "num_cpus", - "pin-project-lite 0.2.4", - "tokio-macros 1.1.0", -] - -[[package]] name = "tokio-macros" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2851,17 +2837,6 @@ dependencies = [ ] [[package]] -name = "tokio-macros" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] name = "tokio-rustls" version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2869,7 +2844,7 @@ checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a" dependencies = [ "futures-core", "rustls", - "tokio 0.2.25", + "tokio", "webpki", ] @@ -2884,7 +2859,7 @@ dependencies = [ "futures-sink", "log 0.4.14", "pin-project-lite 0.1.11", - "tokio 0.2.25", + "tokio", ] [[package]] @@ -2898,7 +2873,7 @@ dependencies = [ "futures-sink", "log 0.4.14", "pin-project-lite 0.1.11", - "tokio 0.2.25", + "tokio", ] [[package]] @@ -2929,7 +2904,7 @@ dependencies = [ "pin-project 0.4.27", "prost", "prost-derive", - "tokio 0.2.25", + "tokio", "tokio-util 0.3.1", "tower", "tower-balance", @@ -2982,7 +2957,7 @@ dependencies = [ "pin-project 0.4.27", "rand 0.7.3", "slab", - "tokio 0.2.25", + "tokio", "tower-discover", "tower-layer", "tower-load", @@ -3000,7 +2975,7 @@ checksum = "c4887dc2a65d464c8b9b66e0e4d51c2fd6cf5b3373afc72805b0a60bce00446a" dependencies = [ "futures-core", "pin-project 0.4.27", - "tokio 0.2.25", + "tokio", "tower-layer", "tower-service", "tracing", @@ -3031,7 +3006,7 @@ checksum = "92c3040c5dbed68abffaa0d4517ac1a454cd741044f33ab0eefab6b8d1361404" dependencies = [ "futures-core", "pin-project 0.4.27", - "tokio 0.2.25", + "tokio", "tower-layer", "tower-load", "tower-service", @@ -3046,7 +3021,7 @@ dependencies = [ "futures-core", "log 0.4.14", "pin-project 0.4.27", - "tokio 0.2.25", + "tokio", "tower-discover", "tower-service", ] @@ -3069,7 +3044,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce50370d644a0364bf4877ffd4f76404156a248d104e2cc234cd391ea5cdc965" dependencies = [ - "tokio 0.2.25", + "tokio", "tower-service", ] @@ -3083,7 +3058,7 @@ dependencies = [ "futures-util", "indexmap", "log 0.4.14", - "tokio 0.2.25", + "tokio", "tower-service", ] @@ -3095,7 +3070,7 @@ checksum = "e6727956aaa2f8957d4d9232b308fe8e4e65d99db30f42b225646e86c9b6a952" dependencies = [ "futures-core", "pin-project 0.4.27", - "tokio 0.2.25", + "tokio", "tower-layer", "tower-service", ] @@ -3113,7 +3088,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "127b8924b357be938823eaaec0608c482d40add25609481027b96198b2e4b31e" dependencies = [ "pin-project 0.4.27", - "tokio 0.2.25", + "tokio", "tower-layer", "tower-service", ] @@ -3216,14 +3191,15 @@ checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "udp-over-tcp" version = "0.1.0" -source = "git+https://github.com/mullvad/udp-over-tcp?rev=942483b#942483b69651c9f59384606dee9cb1776a0b76fc" +source = "git+https://github.com/mullvad/udp-over-tcp?rev=3d1abafe112ee8c2db47ca401f8e286756454e7a#3d1abafe112ee8c2db47ca401f8e286756454e7a" dependencies = [ - "env_logger 0.8.2", + "env_logger 0.7.1", "err-context", "futures", "log 0.4.14", + "nix 0.20.0", "structopt", - "tokio 1.2.0", + "tokio", ] [[package]] diff --git a/mullvad-cli/src/cmds/relay.rs b/mullvad-cli/src/cmds/relay.rs index 6343b9e5d5..5544e58062 100644 --- a/mullvad-cli/src/cmds/relay.rs +++ b/mullvad-cli/src/cmds/relay.rs @@ -44,42 +44,47 @@ impl Command for Relay { .arg( clap::Arg::with_name("host") .help("Hostname or IP") - .required(true) - .index(1), + .required(true), ) .arg( clap::Arg::with_name("port") .help("Remote network port") - .required(true) - .index(2), + .required(true), + ) + .arg( + clap::Arg::with_name("protocol") + .help("Transport protocol") + .default_value("udp") + .possible_values(&["udp", "tcp"]) + .required(true), ) .arg( clap::Arg::with_name("peer-key") .help("Base64 encoded peer public key") - .index(3) - .required(false), + .required(true) + .takes_value(true), + ) + .arg( + clap::Arg::with_name("addr") + .help("Local address of wireguard tunnel") + .long("addr") + .required(true) + .takes_value(true) + .multiple(true), ) .arg( clap::Arg::with_name("v4-gateway") .help("IPv4 gateway address") .long("v4-gateway") - .index(4) - .required(false), - ).arg( + .required(true) + .takes_value(true), + ) + .arg( clap::Arg::with_name("v6-gateway") .help("IPv6 gateway address") .long("v6-gateway") - .takes_value(true) - .required(false), + .takes_value(true), ) - .arg( - clap::Arg::with_name("addr") - .help("Local address of wireguard tunnel") - .long("addr") - .takes_value(true) - .multiple(true) - .required(false), - ), ) .subcommand(clap::SubCommand::with_name("openvpn") .arg( @@ -96,7 +101,7 @@ impl Command for Relay { ) .arg( clap::Arg::with_name("protocol") - .help("Transport protocol. For Wireguard this is ignored.") + .help("Transport protocol") .index(3) .default_value("udp") .possible_values(&["udp", "tcp"]), @@ -152,14 +157,12 @@ impl Command for Relay { .arg( clap::Arg::with_name("transport protocol") .long("protocol") - .required(false) .default_value("any") .possible_values(&["any", "udp", "tcp"]), ) .arg( clap::Arg::with_name("ip version") .long("ipv") - .required(false) .default_value("any") .possible_values(&["any", "4", "6"]), ), @@ -248,15 +251,7 @@ impl Relay { let password = value_t!(matches.value_of("password"), String).unwrap_or_else(|e| e.exit()); let protocol = value_t!(matches.value_of("protocol"), String).unwrap_or_else(|e| e.exit()); - let protocol = match protocol.as_str() { - "udp" => TransportProtocol::Udp, - "tcp" => TransportProtocol::Tcp, - _ => clap::Error::with_description( - "unknown transport protocol", - clap::ErrorKind::ValueValidation, - ) - .exit(), - }; + let protocol = Self::validate_transport_protocol(&protocol); CustomRelaySettings { host, @@ -288,6 +283,8 @@ impl Relay { _ => e.exit(), }, }; + let protocol = value_t!(matches.value_of("protocol"), String).unwrap_or_else(|e| e.exit()); + let protocol = Self::validate_transport_protocol(&protocol); let mut private_key_str = String::new(); println!("Reading private key from standard input"); let _ = io::stdin().lock().read_line(&mut private_key_str); @@ -316,6 +313,7 @@ impl Relay { .collect(), endpoint: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), port) .to_string(), + protocol: protocol as i32, }), ipv4_gateway: ipv4_gateway.to_string(), ipv6_gateway: ipv6_gateway @@ -346,6 +344,18 @@ impl Relay { key } + fn validate_transport_protocol(protocol: &str) -> TransportProtocol { + match protocol { + "udp" => TransportProtocol::Udp, + "tcp" => TransportProtocol::Tcp, + _ => clap::Error::with_description( + "unknown transport protocol", + clap::ErrorKind::ValueValidation, + ) + .exit(), + } + } + async fn set_hostname(&self, matches: &clap::ArgMatches<'_>) -> Result<()> { let hostname = matches.value_of("hostname").unwrap(); let countries = Self::get_filtered_relays().await?; diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs index dff318cece..f32c3986fa 100644 --- a/mullvad-daemon/src/management_interface.rs +++ b/mullvad-daemon/src/management_interface.rs @@ -808,15 +808,7 @@ fn convert_relay_settings_update( ConnectionConfig::OpenVpn(openvpn::ConnectionConfig { endpoint: net::Endpoint { address, - protocol: match types::TransportProtocol::from_i32(config.protocol) { - Some(types::TransportProtocol::Udp) => TransportProtocol::Udp, - Some(types::TransportProtocol::Tcp) => TransportProtocol::Tcp, - None => { - return Err(Status::invalid_argument( - "invalid transport protocol", - )) - } - }, + protocol: convert_proto_transport_protocol(config.protocol)?, }, username: config.username.clone(), password: config.password.clone(), @@ -893,6 +885,7 @@ fn convert_relay_settings_update( public_key: wireguard::PublicKey::from(public_key), allowed_ips, endpoint, + protocol: convert_proto_transport_protocol(peer.protocol)?, }, ipv4_gateway, ipv6_gateway, @@ -934,13 +927,7 @@ fn convert_relay_settings_update( let transport_protocol = if let Some(ref constraints) = settings.openvpn_constraints { match &constraints.protocol { Some(constraint) => { - match types::TransportProtocol::from_i32(constraint.protocol) { - Some(types::TransportProtocol::Udp) => Some(TransportProtocol::Udp), - Some(types::TransportProtocol::Tcp) => Some(TransportProtocol::Tcp), - None => { - return Err(Status::invalid_argument("unknown transport protocol")) - } - } + Some(convert_proto_transport_protocol(constraint.protocol)?) } None => None, } @@ -1103,6 +1090,10 @@ fn convert_connection_config(config: &ConnectionConfig) -> types::ConnectionConf .map(|address| address.to_string()) .collect(), endpoint: config.peer.endpoint.to_string(), + protocol: i32::from(match config.peer.protocol { + TransportProtocol::Udp => types::TransportProtocol::Udp, + TransportProtocol::Tcp => types::TransportProtocol::Tcp, + }), }), ipv4_gateway: config.ipv4_gateway.to_string(), ipv6_gateway: config @@ -1546,6 +1537,14 @@ fn convert_proto_location(location: types::RelayLocation) -> Constraint<Location } } +fn convert_proto_transport_protocol(protocol: i32) -> Result<TransportProtocol, Status> { + match types::TransportProtocol::from_i32(protocol) { + Some(types::TransportProtocol::Udp) => Ok(TransportProtocol::Udp), + Some(types::TransportProtocol::Tcp) => Ok(TransportProtocol::Tcp), + None => Err(Status::invalid_argument("invalid transport protocol")), + } +} + pub struct ManagementInterfaceServer { subscriptions: Arc<RwLock<Vec<EventsListenerSender>>>, socket_path: String, diff --git a/mullvad-daemon/src/relays.rs b/mullvad-daemon/src/relays.rs index 54d2074ad9..c029baaa54 100644 --- a/mullvad-daemon/src/relays.rs +++ b/mullvad-daemon/src/relays.rs @@ -697,6 +697,7 @@ impl RelaySelector { public_key: data.public_key, endpoint: SocketAddr::new(host, port), allowed_ips: all_of_the_internet(), + protocol: TransportProtocol::Udp, }; Some(MullvadEndpoint::Wireguard { peer: peer_config, diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto index 9404baaaf3..ba36deeea4 100644 --- a/mullvad-management-interface/proto/management_interface.proto +++ b/mullvad-management-interface/proto/management_interface.proto @@ -340,6 +340,7 @@ message ConnectionConfig { bytes public_key = 1; repeated string allowed_ips = 2; string endpoint = 3; + TransportProtocol protocol = 4; } TunnelConfig tunnel = 1; diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml index b322b05df4..5413634702 100644 --- a/talpid-core/Cargo.toml +++ b/talpid-core/Cargo.toml @@ -26,9 +26,9 @@ talpid-types = { path = "../talpid-types" } uuid = { version = "0.8", features = ["v4"] } zeroize = "1" chrono = "0.4" -tokio = { version = "0.2", features = [ "process", "rt-threaded", "stream" ] } +tokio = { version = "0.2", features = [ "process", "rt-threaded", "stream" ] } rand = "0.7" -udp-over-tcp = { git = "https://github.com/mullvad/udp-over-tcp", rev = "942483b" } +udp-over-tcp = { git = "https://github.com/mullvad/udp-over-tcp", rev = "3d1abafe112ee8c2db47ca401f8e286756454e7a" } [target.'cfg(not(target_os="android"))'.dependencies] diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs index 769297b7c8..87fc3d4306 100644 --- a/talpid-core/src/tunnel/mod.rs +++ b/talpid-core/src/tunnel/mod.rs @@ -215,7 +215,7 @@ impl TunnelMonitor { let config = wireguard::config::Config::from_parameters(¶ms)?; let monitor = wireguard::WireguardMonitor::start( runtime, - &config, + config, log.as_ref().map(|p| p.as_path()), on_event, tun_provider, diff --git a/talpid-core/src/tunnel/wireguard/mod.rs b/talpid-core/src/tunnel/wireguard/mod.rs index a1ed3c692d..81089e59e6 100644 --- a/talpid-core/src/tunnel/wireguard/mod.rs +++ b/talpid-core/src/tunnel/wireguard/mod.rs @@ -3,16 +3,19 @@ use self::config::Config; use super::tun_provider; use super::{tun_provider::TunProvider, TunnelEvent, TunnelMetadata}; use crate::routing::{self, RequiredRoute}; +use futures::future::abortable; #[cfg(target_os = "linux")] use lazy_static::lazy_static; #[cfg(target_os = "linux")] use std::env; use std::{ collections::HashSet, + net::SocketAddr, path::Path, sync::{mpsc, Arc, Mutex}, }; -use talpid_types::ErrorExt; +use talpid_types::{net::TransportProtocol, ErrorExt}; +use udp_over_tcp::{TcpOptions, Udp2Tcp}; /// WireGuard config data-types pub mod config; @@ -29,6 +32,7 @@ type Result<T> = std::result::Result<T, Error>; /// Errors that can happen in the Wireguard tunnel monitor. #[derive(err_derive::Error, Debug)] +#[error(no_from)] pub enum Error { /// Failed to set up routing. #[error(display = "Failed to setup routing")] @@ -42,6 +46,14 @@ pub enum Error { #[error(display = "Tunnel failed")] TunnelError(#[error(source)] TunnelError), + /// Failed to set up Udp2Tcp + #[error(display = "Failed to start UDP-over-TCP proxy")] + Udp2TcpError(#[error(source)] udp_over_tcp::udp2tcp::ConnectError), + + /// Failed to obtain the local UDP socket address + #[error(display = "Failed obtain local address for the UDP socket in Udp2Tcp")] + GetLocalUdpAddress(#[error(source)] std::io::Error), + /// Failed to setup connectivity monitor #[error(display = "Connectivity monitor failed")] ConnectivityMonitorError(#[error(source)] connectivity_check::Error), @@ -57,6 +69,7 @@ pub struct WireguardMonitor { close_msg_sender: mpsc::Sender<CloseMsg>, close_msg_receiver: mpsc::Receiver<CloseMsg>, pinger_stop_sender: mpsc::Sender<()>, + _tcp_proxies: Vec<TcpProxy>, } #[cfg(target_os = "linux")] @@ -71,17 +84,77 @@ lazy_static! { .unwrap_or(false); } +struct TcpProxy { + local_addr: SocketAddr, + abort_handle: futures::future::AbortHandle, +} + +impl TcpProxy { + pub fn new(runtime: &tokio::runtime::Handle, endpoint: SocketAddr) -> Result<Self> { + let listen_addr = if endpoint.is_ipv4() { + SocketAddr::new("127.0.0.1".parse().unwrap(), 0) + } else { + SocketAddr::new("::1".parse().unwrap(), 0) + }; + + let udp2tcp = runtime + .block_on(Udp2Tcp::new( + listen_addr, + endpoint, + Some(&TcpOptions { + #[cfg(target_os = "linux")] + fwmark: Some(crate::linux::TUNNEL_FW_MARK), + ..TcpOptions::default() + }), + )) + .map_err(Error::Udp2TcpError)?; + + let local_addr = udp2tcp + .local_udp_addr() + .map_err(Error::GetLocalUdpAddress)?; + + let (udp2tcp_future, abort_handle) = abortable(udp2tcp.run()); + runtime.spawn(udp2tcp_future); + + Ok(Self { + local_addr, + abort_handle, + }) + } + + pub fn local_udp_addr(&self) -> SocketAddr { + self.local_addr + } +} + +impl Drop for TcpProxy { + fn drop(&mut self) { + self.abort_handle.abort(); + } +} + impl WireguardMonitor { /// Starts a WireGuard tunnel with the given config pub fn start<F: Fn(TunnelEvent) + Send + Sync + Clone + 'static>( runtime: tokio::runtime::Handle, - config: &Config, + mut config: Config, log_path: Option<&Path>, on_event: F, tun_provider: &mut TunProvider, route_manager: &mut routing::RouteManager, ) -> Result<WireguardMonitor> { - // FIXME: Set up udp2tcp and use it for peer config here + let mut tcp_proxies = vec![]; + + for peer in &mut config.peers { + if peer.protocol == TransportProtocol::Tcp { + let udp2tcp = TcpProxy::new(&runtime, peer.endpoint.clone())?; + + // Replace remote peer with proxy + peer.endpoint = udp2tcp.local_udp_addr(); + + tcp_proxies.push(udp2tcp); + } + } let tunnel = Self::open_tunnel(&config, log_path, tun_provider, route_manager)?; let iface_name = tunnel.get_interface_name().to_string(); @@ -108,6 +181,7 @@ impl WireguardMonitor { close_msg_sender, close_msg_receiver, pinger_stop_sender: pinger_tx, + _tcp_proxies: tcp_proxies, }; let metadata = Self::tunnel_metadata(&iface_name, &config); @@ -118,7 +192,8 @@ impl WireguardMonitor { iface_name.to_string(), Arc::downgrade(&monitor.tunnel), pinger_rx, - )?; + ) + .map_err(Error::ConnectivityMonitorError)?; std::thread::spawn(move || { match connectivity_monitor.establish_connectivity() { @@ -191,12 +266,15 @@ impl WireguardMonitor { #[cfg(target_os = "linux")] log::debug!("Using userspace WireGuard implementation"); - Ok(Box::new(WgGoTunnel::start_tunnel( - &config, - log_path, - tun_provider, - Self::get_tunnel_routes(config), - )?)) + Ok(Box::new( + WgGoTunnel::start_tunnel( + &config, + log_path, + tun_provider, + Self::get_tunnel_routes(config), + ) + .map_err(Error::TunnelError)?, + )) } /// Returns a close handle for the tunnel diff --git a/talpid-types/src/net/wireguard.rs b/talpid-types/src/net/wireguard.rs index 731d93c79e..60a0a29a6d 100644 --- a/talpid-types/src/net/wireguard.rs +++ b/talpid-types/src/net/wireguard.rs @@ -34,7 +34,7 @@ impl ConnectionConfig { pub fn get_endpoint(&self) -> Endpoint { Endpoint { address: self.peer.endpoint, - protocol: TransportProtocol::Udp, + protocol: self.peer.protocol, } } } @@ -47,6 +47,14 @@ pub struct PeerConfig { pub allowed_ips: Vec<IpNetwork>, /// IP address of the WireGuard server. pub endpoint: SocketAddr, + /// Transport protocol. WireGuard only supports UDP directly. + /// If this is set to TCP, then traffic is proxied using [`udp_to_tcp::Udp2Tcp`]. + #[serde(default = "default_peer_transport")] + pub protocol: TransportProtocol, +} + +fn default_peer_transport() -> TransportProtocol { + TransportProtocol::Udp } #[derive(Clone, Eq, PartialEq, Deserialize, Serialize, Debug)] |
