summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2021-03-02 15:49:23 +0100
committerDavid Lönnhager <david.l@mullvad.net>2021-04-13 13:06:30 +0200
commit14a349fcdb266057bd7265879758f212f7a4224c (patch)
tree413faca6954dbf2f6816d83119c5722b7a8005ac
parentdb2accf33367d37d71c907333af6885032329e68 (diff)
downloadmullvadvpn-14a349fcdb266057bd7265879758f212f7a4224c.tar.xz
mullvadvpn-14a349fcdb266057bd7265879758f212f7a4224c.zip
Add TCP WireGuard custom tunnel option
-rw-r--r--Cargo.lock150
-rw-r--r--mullvad-cli/src/cmds/relay.rs72
-rw-r--r--mullvad-daemon/src/management_interface.rs31
-rw-r--r--mullvad-daemon/src/relays.rs1
-rw-r--r--mullvad-management-interface/proto/management_interface.proto1
-rw-r--r--talpid-core/Cargo.toml4
-rw-r--r--talpid-core/src/tunnel/mod.rs2
-rw-r--r--talpid-core/src/tunnel/wireguard/mod.rs98
-rw-r--r--talpid-types/src/net/wireguard.rs10
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(&params)?;
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)]