Skip to content

Commit

Permalink
Merge branch 'implement-wgturnonmultihop-for-android-droid-1365'
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkusPettersson98 committed Nov 22, 2024
2 parents b2d3287 + 3516c3c commit b1737f5
Show file tree
Hide file tree
Showing 22 changed files with 1,381 additions and 639 deletions.
6 changes: 0 additions & 6 deletions mullvad-relay-selector/src/relay_selector/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,12 +722,6 @@ impl RelaySelector {
custom_lists: &CustomListsSettings,
parsed_relays: &ParsedRelays,
) -> Result<WireguardConfig, Error> {
// TODO: Remove when Android gets support for multihop.
if cfg!(target_os = "android") {
let relay = Self::get_wireguard_singlehop_config(query, custom_lists, parsed_relays)
.ok_or(Error::NoRelay)?;
return Ok(WireguardConfig::from(relay));
}
let inner = if query.singlehop() {
match Self::get_wireguard_singlehop_config(query, custom_lists, parsed_relays) {
Some(exit) => WireguardConfig::from(exit),
Expand Down
11 changes: 11 additions & 0 deletions talpid-types/src/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,15 +435,26 @@ impl AllowedClients {
}
}

/// What [`Endpoint`]s to allow the client to send traffic to and receive from.
///
/// In some cases we want to restrict what IP addresses the client may communicate with even
/// inside of the tunnel, for example while negotiating a PQ-safe PSK with an ephemeral peer.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum AllowedTunnelTraffic {
/// Block all traffic inside the tunnel.
None,
/// Allow all traffic inside the tunnel. This is the normal mode of operation.
All,
/// Only allow communication with this specific endpoint. This will usually be a relay during a
/// short amount of time.
One(Endpoint),
/// Only allow communication with these two specific endpoints. The intended use case for this
/// is while negotiating for example a PSK with both the entry & exit relays in a multihop setup.
Two(Endpoint, Endpoint),
}

impl AllowedTunnelTraffic {
/// Do we currently allow traffic to all endpoints?
pub fn all(&self) -> bool {
matches!(self, AllowedTunnelTraffic::All)
}
Expand Down
91 changes: 59 additions & 32 deletions talpid-wireguard/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{
ffi::CString,
net::{Ipv4Addr, Ipv6Addr},
};
use talpid_types::net::wireguard::{PeerConfig, PrivateKey};
use talpid_types::net::{obfuscation::ObfuscatorConfig, wireguard, GenericTunnelOptions};

/// Name to use for the tunnel device
Expand Down Expand Up @@ -121,38 +122,12 @@ impl Config {
/// Returns a CString with the appropriate config for WireGuard-go
// TODO: Consider outputting both overriding and additive configs
pub fn to_userspace_format(&self) -> CString {
// the order of insertion matters, public key entry denotes a new peer entry
let mut wg_conf = WgConfigBuffer::new();
wg_conf
.add::<&[u8]>("private_key", self.tunnel.private_key.to_bytes().as_ref())
.add("listen_port", "0");

#[cfg(target_os = "linux")]
if let Some(fwmark) = &self.fwmark {
wg_conf.add("fwmark", fwmark.to_string().as_str());
}

wg_conf.add("replace_peers", "true");

for peer in self.peers() {
wg_conf
.add::<&[u8]>("public_key", peer.public_key.as_bytes().as_ref())
.add("endpoint", peer.endpoint.to_string().as_str())
.add("replace_allowed_ips", "true");
if let Some(ref psk) = peer.psk {
wg_conf.add::<&[u8]>("preshared_key", psk.as_bytes().as_ref());
}
for addr in &peer.allowed_ips {
wg_conf.add("allowed_ip", addr.to_string().as_str());
}
#[cfg(daita)]
if peer.constant_packet_size {
wg_conf.add("constant_packet_size", "true");
}
}

let bytes = wg_conf.into_config();
CString::new(bytes).expect("null bytes inside config")
userspace_format(
&self.tunnel.private_key,
self.peers(),
#[cfg(target_os = "linux")]
self.fwmark,
)
}

/// Return whether the config connects to an exit peer from another remote peer.
Expand Down Expand Up @@ -185,6 +160,13 @@ impl Config {
.into_iter()
.chain(std::iter::once(&mut self.entry_peer))
}

/// Return routes for all allowed IPs.
pub fn get_tunnel_destinations(&self) -> impl Iterator<Item = ipnetwork::IpNetwork> + '_ {
self.peers()
.flat_map(|peer| peer.allowed_ips.iter())
.cloned()
}
}

enum ConfValue<'a> {
Expand Down Expand Up @@ -235,3 +217,48 @@ impl WgConfigBuffer {
self.buf
}
}

/// Returns a CString with the appropriate config for WireGuard-go
#[allow(single_use_lifetimes)]
pub fn userspace_format<'a>(
private_key: &PrivateKey,
peers: impl Iterator<Item = &'a PeerConfig>,
#[cfg(target_os = "linux")] fwmark: Option<u32>,
) -> CString {
// the order of insertion matters, public key entry denotes a new peer entry
let mut wg_conf = WgConfigBuffer::new();
wg_conf
.add::<&[u8]>("private_key", private_key.to_bytes().as_ref())
.add("listen_port", "0");

#[cfg(target_os = "linux")]
if let Some(fwmark) = fwmark {
wg_conf.add("fwmark", fwmark.to_string().as_str());
}

wg_conf.add("replace_peers", "true");

for peer in peers {
write_peer_to_config(&mut wg_conf, peer)
}

let bytes = wg_conf.into_config();
CString::new(bytes).expect("null bytes inside config")
}

fn write_peer_to_config(wg_conf: &mut WgConfigBuffer, peer: &PeerConfig) {
wg_conf
.add::<&[u8]>("public_key", peer.public_key.as_bytes().as_ref())
.add("endpoint", peer.endpoint.to_string().as_str())
.add("replace_allowed_ips", "true");
if let Some(ref psk) = peer.psk {
wg_conf.add::<&[u8]>("preshared_key", psk.as_bytes().as_ref());
}
for addr in &peer.allowed_ips {
wg_conf.add("allowed_ip", addr.to_string().as_str());
}
#[cfg(daita)]
if peer.constant_packet_size {
wg_conf.add("constant_packet_size", "true");
}
}
Loading

0 comments on commit b1737f5

Please sign in to comment.