Add AllowedIps setting to CLI

This commit is contained in:
Sebastian Holmin 2025-05-27 11:59:48 +02:00
parent e2d1514cf2
commit e91d35854c
No known key found for this signature in database
GPG Key ID: 9C88494B3F2F9089
16 changed files with 309 additions and 39 deletions

1
Cargo.lock generated
View File

@ -2926,6 +2926,7 @@ dependencies = [
"fern",
"futures",
"hickory-resolver",
"ipnetwork",
"libc",
"log",
"log-panics",

View File

@ -6,9 +6,9 @@ use mullvad_types::{
constraints::{Constraint, Match},
location::CountryCode,
relay_constraints::{
GeographicLocationConstraint, LocationConstraint, LocationConstraintFormatter,
OpenVpnConstraints, Ownership, Provider, Providers, RelayConstraints, RelayOverride,
RelaySettings, TransportPort, WireguardConstraints,
allowed_ip::AllowedIps, GeographicLocationConstraint, LocationConstraint,
LocationConstraintFormatter, OpenVpnConstraints, Ownership, Provider, Providers,
RelayConstraints, RelayOverride, RelaySettings, TransportPort, WireguardConstraints,
},
relay_list::{RelayEndpointData, RelayListCountry},
ConnectionConfig, CustomTunnelEndpoint,
@ -18,9 +18,7 @@ use std::{
io::BufRead,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
};
use talpid_types::net::{
all_of_the_internet, openvpn, wireguard, Endpoint, IpVersion, TransportProtocol, TunnelType,
};
use talpid_types::net::{openvpn, wireguard, Endpoint, IpVersion, TransportProtocol, TunnelType};
use super::{relay_constraints::LocationArgs, BooleanOption};
use crate::{cmds::receive_confirmation, print_option};
@ -538,7 +536,7 @@ impl Relay {
},
peer: wireguard::PeerConfig {
public_key: peer_pubkey,
allowed_ips: all_of_the_internet(),
allowed_ips: AllowedIps::allow_all().resolve(Some(ipv4_gateway), ipv6_gateway),
endpoint: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), port),
psk: None,
constant_packet_size: false,

View File

@ -3,6 +3,7 @@ use clap::Subcommand;
use mullvad_management_interface::MullvadProxyClient;
use mullvad_types::{
constraints::Constraint,
relay_constraints::{AllowedIps, RelaySettings, WireguardConstraints},
wireguard::{QuantumResistantState, RotationInterval, DEFAULT_ROTATION_INTERVAL},
};
@ -44,6 +45,15 @@ pub enum TunnelOptions {
/// Configure whether to enable DAITA direct only
#[arg(long)]
daita_direct_only: Option<BooleanOption>,
/// Specify custom allowed IPs for WireGuard tunnels. Use comma-separated values of IPs and IP ranges in CIDR notation.
/// A empty string resets to the default value, where all traffic is allowed, i.e. (0.0.0.0/0,::/0).
/// For CIDR ranges, host bits must be zero (e.g., "10.0.0.0/24" is valid, "10.0.0.1/24" is not).
///
/// Example: "10.0.0.0/24,192.168.1.1,fd00::/8"
///
/// WARNING: Setting this value incorrectly may cause internet access to be blocked or the app to not work properly.
#[arg(long)]
allowed_ips: Option<String>,
/// The key rotation interval. Number of hours, or 'any'
#[arg(long)]
rotation_interval: Option<Constraint<RotationInterval>>,
@ -117,6 +127,22 @@ impl Tunnel {
},
);
// Get the WireGuard allowed IPs
let wireguard_constraints = match rpc.get_settings().await?.relay_settings {
RelaySettings::Normal(settings) => settings.wireguard_constraints,
RelaySettings::CustomTunnelEndpoint(_) => WireguardConstraints::default(),
};
print_option!(
"Allowed IPs",
match wireguard_constraints.allowed_ips {
mullvad_types::constraints::Constraint::Any => "all traffic (default)".to_string(),
mullvad_types::constraints::Constraint::Only(ips) => {
ips.to_string()
}
},
);
println!("Generic options");
print_option!(
@ -139,6 +165,7 @@ impl Tunnel {
quantum_resistant,
daita,
daita_direct_only,
allowed_ips,
rotation_interval,
rotate_key,
} => {
@ -147,6 +174,7 @@ impl Tunnel {
quantum_resistant,
daita,
daita_direct_only,
allowed_ips,
rotation_interval,
rotate_key,
)
@ -179,6 +207,7 @@ impl Tunnel {
quantum_resistant: Option<QuantumResistantState>,
daita: Option<BooleanOption>,
daita_direct_only: Option<BooleanOption>,
allowed_ips: Option<String>,
rotation_interval: Option<Constraint<RotationInterval>>,
rotate_key: Option<RotateKey>,
) -> Result<()> {
@ -194,6 +223,13 @@ impl Tunnel {
println!("Quantum resistant setting has been updated");
}
if let Some(allowed_ips_str) = allowed_ips {
let ips = AllowedIps::parse(allowed_ips_str.split(','))?;
rpc.set_wireguard_allowed_ips(ips).await?;
println!("WireGuard allowed IPs have been updated")
}
if let Some(enable_daita) = daita {
rpc.set_enable_daita(*enable_daita).await?;
println!("DAITA setting has been updated");

View File

@ -31,6 +31,7 @@ serde_json = { workspace = true }
tokio = { workspace = true, features = ["fs", "io-util", "rt-multi-thread", "sync", "time"] }
tokio-stream = { version = "0.1", features = ["sync"]}
socket2 = { workspace = true }
ipnetwork = { workspace = true }
mullvad-relay-selector = { path = "../mullvad-relay-selector" }
mullvad-types = { path = "../mullvad-types" }

View File

@ -53,12 +53,14 @@ use mullvad_types::{
access_method::{AccessMethod, AccessMethodSetting},
account::{AccountData, AccountNumber, VoucherSubmission},
auth_failed::AuthFailed,
constraints::Constraint,
custom_list::CustomList,
device::{Device, DeviceEvent, DeviceEventCause, DeviceId, DeviceState, RemoveDeviceEvent},
features::{compute_feature_indicators, FeatureIndicator, FeatureIndicators},
location::{GeoIpLocation, LocationEventData},
relay_constraints::{
BridgeSettings, BridgeState, BridgeType, ObfuscationSettings, RelayOverride, RelaySettings,
allowed_ip::AllowedIps, BridgeSettings, BridgeState, BridgeType, ObfuscationSettings,
RelayOverride, RelaySettings,
},
relay_list::RelayList,
settings::{DnsOptions, Settings},
@ -289,6 +291,8 @@ pub enum DaemonCommand {
/// Toggle macOS network check leak
/// Set MTU for wireguard tunnels
SetWireguardMtu(ResponseTx<(), settings::Error>, Option<u16>),
/// Set allowed IPs for wireguard tunnels
SetWireguardAllowedIps(ResponseTx<(), settings::Error>, Constraint<AllowedIps>),
/// Set automatic key rotation interval for wireguard tunnels
SetWireguardRotationInterval(ResponseTx<(), settings::Error>, Option<RotationInterval>),
/// Get the daemon settings
@ -1419,6 +1423,9 @@ impl Daemon {
}
ClearAllRelayOverrides(tx) => self.on_clear_all_relay_overrides(tx).await,
SetWireguardMtu(tx, mtu) => self.on_set_wireguard_mtu(tx, mtu).await,
SetWireguardAllowedIps(tx, allowed_ips) => {
self.on_set_wireguard_allowed_ips(tx, allowed_ips).await
}
SetWireguardRotationInterval(tx, interval) => {
self.on_set_wireguard_rotation_interval(tx, interval).await
}
@ -2785,6 +2792,38 @@ impl Daemon {
}
}
async fn on_set_wireguard_allowed_ips(
&mut self,
tx: ResponseTx<(), settings::Error>,
allowed_ips: Constraint<AllowedIps>,
) {
match self
.settings
.update(move |settings| {
if let RelaySettings::Normal(ref mut relay_settings) = settings.relay_settings {
relay_settings.wireguard_constraints.allowed_ips = allowed_ips;
}
})
.await
{
Ok(settings_changed) => {
Self::oneshot_send(tx, Ok(()), "set_wireguard_allowed_ips response");
if settings_changed {
if let Some(TunnelType::Wireguard) = self.get_connected_tunnel_type() {
log::info!(
"Initiating tunnel restart because the WireGuard allowed IPs setting changed"
);
self.reconnect_tunnel();
}
}
}
Err(e) => {
log::error!("{}", e.display_chain_with_msg("Unable to save settings"));
Self::oneshot_send(tx, Err(e), "set_wireguard_allowed_ips response");
}
}
}
fn on_rotate_wireguard_key(&self, tx: ResponseTx<(), Error>) {
let manager = self.account_manager.clone();
tokio::spawn(async move {

View File

@ -11,7 +11,8 @@ use mullvad_management_interface::{
use mullvad_types::{
account::AccountNumber,
relay_constraints::{
BridgeSettings, BridgeState, ObfuscationSettings, RelayOverride, RelaySettings,
allowed_ip::AllowedIps, BridgeSettings, BridgeState, ObfuscationSettings, RelayOverride,
RelaySettings,
},
relay_list::RelayList,
settings::{DnsOptions, Settings},
@ -639,6 +640,26 @@ impl ManagementService for ManagementServiceImpl {
}
}
async fn set_wireguard_allowed_ips(
&self,
request: Request<types::AllowedIpsList>,
) -> ServiceResult<()> {
let allowed_ips_str = request.into_inner().values;
log::debug!("set_wireguard_allowed_ips({:?})", allowed_ips_str);
let (tx, rx) = oneshot::channel();
let allowed_ips = AllowedIps::parse(&allowed_ips_str)
.map_err(|e| {
log::error!("{e}");
Status::invalid_argument(format!("Invalid allowed IPs: {}", e))
})?
.to_constraint();
self.send_command_to_daemon(DaemonCommand::SetWireguardAllowedIps(tx, allowed_ips))?;
self.wait_for_result(rx).await??;
Ok(Response::new(()))
}
// Custom lists
//

View File

@ -39,6 +39,9 @@ pub enum Error {
#[error("Failed to apply settings update")]
UpdateFailed(Box<dyn std::error::Error + Send + Sync>),
#[error("Failed to parse IP network from string: {0}")]
ParseIp(String),
}
/// Converts an [Error] to a management interface status
@ -57,9 +60,10 @@ impl From<Error> for mullvad_management_interface::Status {
let custom_list_err = *err.downcast::<CustomListError>().unwrap();
handle_custom_list_error(custom_list_err)
}
Error::SerializeError(..) | Error::ParseError(..) | Error::UpdateFailed(..) => {
Status::new(Code::Internal, error.to_string())
}
Error::SerializeError(..)
| Error::ParseError(..)
| Error::UpdateFailed(..)
| Error::ParseIp(..) => Status::new(Code::Internal, error.to_string()),
}
}
}

View File

@ -48,6 +48,7 @@ service ManagementService {
rpc SetAutoConnect(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
rpc SetOpenvpnMssfix(google.protobuf.UInt32Value) returns (google.protobuf.Empty) {}
rpc SetWireguardMtu(google.protobuf.UInt32Value) returns (google.protobuf.Empty) {}
rpc SetWireguardAllowedIps(AllowedIpsList) returns (google.protobuf.Empty) {}
rpc SetEnableIpv6(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
rpc SetQuantumResistantTunnel(QuantumResistantState) returns (google.protobuf.Empty) {}
rpc SetEnableDaita(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
@ -562,8 +563,9 @@ enum IpVersion {
message WireguardConstraints {
optional uint32 port = 1;
optional IpVersion ip_version = 2;
bool use_multihop = 3;
LocationConstraint entry_location = 4;
repeated string allowed_ips = 3;
bool use_multihop = 4;
LocationConstraint entry_location = 5;
}
message CustomRelaySettings {
@ -831,3 +833,5 @@ message PlayPurchase {
}
message PlayPurchasePaymentToken { string token = 1; }
message AllowedIpsList { repeated string values = 1; }

View File

@ -22,7 +22,7 @@ use mullvad_types::{
device::{Device, DeviceId, DeviceState},
features::FeatureIndicators,
relay_constraints::{
BridgeSettings, BridgeState, ObfuscationSettings, RelayOverride, RelaySettings,
AllowedIps, BridgeSettings, BridgeState, ObfuscationSettings, RelayOverride, RelaySettings,
},
settings::DnsOptions,
wireguard::{PublicKey, QuantumResistantState, RotationInterval},
@ -779,6 +779,16 @@ impl MullvadProxyClient {
self.0.enable_relay(relay).await.map_err(Error::Rpc)?;
Ok(())
}
pub async fn set_wireguard_allowed_ips(&mut self, allowed_ips: AllowedIps) -> Result<()> {
self.0
.set_wireguard_allowed_ips(types::AllowedIpsList {
values: allowed_ips.0.iter().map(ToString::to_string).collect(),
})
.await
.map_err(Error::Rpc)?;
Ok(())
}
}
#[cfg(not(target_os = "android"))]

View File

@ -1,6 +1,11 @@
use crate::types::{conversions::net::try_tunnel_type_from_i32, proto, FromProtobufTypeError};
use mullvad_types::{
constraints::Constraint, custom_list::Id, relay_constraints::GeographicLocationConstraint,
constraints::Constraint,
custom_list::Id,
relay_constraints::{
allowed_ip::{self, AllowedIps},
GeographicLocationConstraint,
},
};
use std::str::FromStr;
use talpid_types::net::proxy::CustomProxy;
@ -24,10 +29,17 @@ impl TryFrom<&proto::WireguardConstraints>
)),
None => None,
};
let allowed_ips = AllowedIps::parse(&constraints.allowed_ips)
.map_err(|e| {
log::error!("Failed to parse allowed IPs: {}", e);
FromProtobufTypeError::InvalidArgument("invalid allowed IPs")
})?
.to_constraint();
Ok(mullvad_constraints::WireguardConstraints {
port: Constraint::from(constraints.port.map(|port| port as u16)),
ip_version: Constraint::from(ip_version),
allowed_ips,
use_multihop: constraints.use_multihop,
entry_location: constraints
.entry_location
@ -252,6 +264,14 @@ impl From<mullvad_types::relay_constraints::RelaySettings> for proto::RelaySetti
.ip_version
.option()
.map(|ipv| i32::from(proto::IpVersion::from(ipv))),
allowed_ips: allowed_ip::resolve_from_constraint(
&constraints.wireguard_constraints.allowed_ips,
None,
None,
)
.into_iter()
.map(|ip| ip.to_string())
.collect(),
use_multihop: constraints.wireguard_constraints.multihop(),
entry_location: constraints
.wireguard_constraints

View File

@ -13,14 +13,13 @@ use ipnetwork::IpNetwork;
use mullvad_types::{
constraints::Constraint,
endpoint::MullvadWireguardEndpoint,
relay_constraints::TransportPort,
relay_constraints::{allowed_ip::resolve_from_constraint, TransportPort},
relay_list::{
BridgeEndpointData, OpenVpnEndpoint, OpenVpnEndpointData, Relay, RelayEndpointData,
WireguardEndpointData,
},
};
use talpid_types::net::{
all_of_the_internet,
proxy::Shadowsocks,
wireguard::{PeerConfig, PublicKey},
Endpoint, IpVersion, TransportProtocol,
@ -79,7 +78,13 @@ fn wireguard_singlehop_endpoint(
let peer_config = PeerConfig {
public_key: get_public_key(exit)?.clone(),
endpoint,
allowed_ips: all_of_the_internet(),
// The peer should be able to route incoming VPN traffic to the given user given IP
// ranges, if any, else the rest of the internet.
allowed_ips: resolve_from_constraint(
&query.allowed_ips,
Some(data.ipv4_gateway),
Some(data.ipv6_gateway),
),
// This will be filled in later, not the relay selector's problem
psk: None,
// This will be filled in later
@ -118,9 +123,13 @@ fn wireguard_multihop_endpoint(
let exit = PeerConfig {
public_key: get_public_key(exit)?.clone(),
endpoint: exit_endpoint,
// The exit peer should be able to route incoming VPN traffic to the rest of
// the internet.
allowed_ips: all_of_the_internet(),
// The exit peer should be able to route incoming VPN traffic to the given user given IP
// ranges, if any, else the rest of the internet.
allowed_ips: resolve_from_constraint(
&query.allowed_ips,
Some(data.ipv4_gateway),
Some(data.ipv6_gateway),
),
// This will be filled in later, not the relay selector's problem
psk: None,
// This will be filled in later

View File

@ -330,6 +330,7 @@ impl<'a> TryFrom<NormalSelectorConfig<'a>> for RelayQuery {
let WireguardConstraints {
port,
ip_version,
allowed_ips,
use_multihop,
entry_location,
} = wireguard_constraints;
@ -341,6 +342,7 @@ impl<'a> TryFrom<NormalSelectorConfig<'a>> for RelayQuery {
WireguardRelayQuery {
port,
ip_version,
allowed_ips,
use_multihop: Constraint::Only(use_multihop),
entry_location,
obfuscation: ObfuscationQuery::from(obfuscation_settings),

View File

@ -32,9 +32,9 @@ use crate::Error;
use mullvad_types::{
constraints::Constraint,
relay_constraints::{
BridgeConstraints, BridgeSettings, BridgeState, BridgeType, LocationConstraint,
ObfuscationSettings, OpenVpnConstraints, Ownership, Providers, RelayConstraints,
RelaySettings, SelectedObfuscation, ShadowsocksSettings, TransportPort,
allowed_ip::AllowedIps, BridgeConstraints, BridgeSettings, BridgeState, BridgeType,
LocationConstraint, ObfuscationSettings, OpenVpnConstraints, Ownership, Providers,
RelayConstraints, RelaySettings, SelectedObfuscation, ShadowsocksSettings, TransportPort,
Udp2TcpObfuscationSettings, WireguardConstraints,
},
wireguard::QuantumResistantState,
@ -268,6 +268,7 @@ impl From<RelayQuery> for RelaySettings {
pub struct WireguardRelayQuery {
pub port: Constraint<u16>,
pub ip_version: Constraint<IpVersion>,
pub allowed_ips: Constraint<AllowedIps>,
pub use_multihop: Constraint<bool>,
pub entry_location: Constraint<LocationConstraint>,
pub obfuscation: ObfuscationQuery,
@ -360,6 +361,7 @@ impl WireguardRelayQuery {
WireguardRelayQuery {
port: Constraint::Any,
ip_version: Constraint::Any,
allowed_ips: Constraint::Any,
use_multihop: Constraint::Any,
entry_location: Constraint::Any,
obfuscation: ObfuscationQuery::Auto,
@ -374,6 +376,7 @@ impl WireguardRelayQuery {
WireguardConstraints {
port: self.port,
ip_version: self.ip_version,
allowed_ips: self.allowed_ips,
entry_location: self.entry_location,
use_multihop: self.use_multihop.unwrap_or(false),
}
@ -392,6 +395,7 @@ impl From<WireguardRelayQuery> for WireguardConstraints {
WireguardConstraints {
port: value.port,
ip_version: value.ip_version,
allowed_ips: value.allowed_ips,
entry_location: value.entry_location,
use_multihop: value.use_multihop.unwrap_or(false),
}

View File

@ -130,15 +130,16 @@ macro_rules! impl_intersection_partialeq {
};
}
// Note that deriving `Intersection` for using `impl_intersection_partialeq`
// may not do what you expect for data structures that represent/wrap sets, such as
// `Vec<T>` or `HashSet<T>`. `Constraint::Only` will only match if the
// `Vec<T>` or `HashSet<T>` is exactly the same, not if they contain overlapping elements.
impl_intersection_partialeq!(u16);
impl_intersection_partialeq!(bool);
// NOTE: this implementation does not do what you may expect of an intersection
impl_intersection_partialeq!(relay_constraints::Providers);
// NOTE: should take actual intersection
impl_intersection_partialeq!(relay_constraints::LocationConstraint);
impl_intersection_partialeq!(relay_constraints::Ownership);
// NOTE: it contains an inner constraint
impl_intersection_partialeq!(talpid_types::net::TransportProtocol);
impl_intersection_partialeq!(talpid_types::net::TunnelType);
impl_intersection_partialeq!(talpid_types::net::IpVersion);
impl_intersection_partialeq!(relay_constraints::AllowedIps);

View File

@ -407,10 +407,140 @@ impl fmt::Display for OpenVpnConstraints {
pub struct WireguardConstraints {
pub port: Constraint<u16>,
pub ip_version: Constraint<IpVersion>,
pub allowed_ips: Constraint<AllowedIps>,
pub use_multihop: bool,
pub entry_location: Constraint<LocationConstraint>,
}
pub use allowed_ip::AllowedIps;
pub mod allowed_ip {
use std::net::{Ipv4Addr, Ipv6Addr};
use crate::constraints::Constraint;
use ipnetwork::IpNetwork;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct AllowedIps(pub Vec<IpNetwork>);
impl Default for AllowedIps {
fn default() -> Self {
AllowedIps::allow_all()
}
}
impl std::fmt::Display for AllowedIps {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(
&self
.0
.iter()
.map(|net| net.to_string())
.collect::<Vec<_>>()
.join(", "),
)
}
}
#[derive(Debug, thiserror::Error)]
pub enum AllowedIpParseError {
#[error("Failed to parse IP network: {0}")]
Parse(#[from] ipnetwork::IpNetworkError),
#[error("IP network {0} has non-zero host bits (should be {1})")]
NonZeroHostBits(IpNetwork, std::net::IpAddr),
}
/// Represents a collection of allowed IP networks.
///
/// Provides utility methods to construct `AllowedIps` from various sources,
/// including allowing all IPs, parsing from string representations, and
/// converting into a constraint.
impl AllowedIps {
/// Creates an `AllowedIps` instance that allows all IP addresses.
///
/// # Returns
///
/// An `AllowedIps` containing all possible IP networks.
pub fn allow_all() -> Self {
AllowedIps(vec![
"0.0.0.0/0".parse().expect("Failed to parse ipv4 network"),
"::0/0".parse().expect("Failed to parse ipv6 network"),
])
}
/// Constructs an `AllowedIps` from an iterator of string representations of IP networks.
///
/// Each string should be a valid CIDR notation (e.g., "192.168.1.0/24").
/// Ignores empty strings. Returns an error if any string is not a valid network or if it contains non-zero host bits.
///
/// # Errors
///
/// Returns `AllowedIpParseError::Parse` if parsing fails, or
/// `AllowedIpParseError::NonZeroHostBits` if the network contains non-zero host bits.
pub fn parse<I, S>(allowed_ips: I) -> Result<AllowedIps, AllowedIpParseError>
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
let mut networks = vec![];
for s in allowed_ips {
let s = s.as_ref().trim();
if !s.is_empty() {
let net: IpNetwork = s.parse().map_err(AllowedIpParseError::Parse)?;
if net.network() != net.ip() {
return Err(AllowedIpParseError::NonZeroHostBits(net, net.network()));
}
networks.push(net);
}
}
Ok(AllowedIps(networks))
}
/// Converts the `AllowedIps` into a `Constraint<AllowedIps>`.
/// If the list of ip ranges is empty, it returns `Constraint::Any`, otherwise it returns `Constraint::Only(self)`.
pub fn to_constraint(self) -> Constraint<AllowedIps> {
if self.0.is_empty() {
Constraint::Any
} else {
Constraint::Only(self)
}
}
/// Resolves the allowed IPs to a `Vec<IpNetwork>`, adding the host IPv4 and IPv6 addresses if provided.
pub fn resolve(
self,
host_ipv4: Option<Ipv4Addr>,
host_ipv6: Option<Ipv6Addr>,
) -> Vec<IpNetwork> {
let mut networks = self.0;
if let Some(host_ipv6) = host_ipv6 {
networks.push(IpNetwork::V6(host_ipv6.into()));
}
if let Some(host_ipv4) = host_ipv4 {
networks.push(IpNetwork::V4(host_ipv4.into()));
}
log::trace!("Resolved allowed IPs: {networks:?}");
networks
}
}
/// Resolves the allowed IPs from a `Constraint<AllowedIps>`, adding the host IPv4 and IPv6 addresses if provided.
/// If the constraint is `Constraint::Any` or `Constraint::Only` with an empty list, it allows all IPs.
/// Returns a vector of `IpNetwork` containing the resolved allowed IPs.
pub fn resolve_from_constraint(
allowed_ips: &Constraint<AllowedIps>,
host_ipv4: Option<Ipv4Addr>,
host_ipv6: Option<Ipv6Addr>,
) -> Vec<IpNetwork> {
match allowed_ips {
Constraint::Any => AllowedIps::allow_all(),
Constraint::Only(ips) if ips.0.is_empty() => AllowedIps::allow_all(),
Constraint::Only(ips) => ips.clone(),
}
.resolve(host_ipv4, host_ipv6)
}
}
impl WireguardConstraints {
/// Enable or disable multihop.
pub fn use_multihop(&mut self, multihop: bool) {

View File

@ -544,16 +544,6 @@ pub struct GenericTunnelOptions {
pub enable_ipv6: bool,
}
/// Returns a vector of IP networks representing all of the internet, 0.0.0.0/0.
/// This may be used in [`crate::net::wireguard::PeerConfig`] to route all traffic
/// to the tunnel interface.
pub fn all_of_the_internet() -> Vec<ipnetwork::IpNetwork> {
vec![
"0.0.0.0/0".parse().expect("Failed to parse ipv6 network"),
"::0/0".parse().expect("Failed to parse ipv6 network"),
]
}
/// Details about the hosts's connectivity.
///
/// Information about the host's connectivity, such as the preesence of