summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mullvad-cli/src/cmds/custom_dns.rs132
-rw-r--r--mullvad-daemon/src/lib.rs31
-rw-r--r--mullvad-daemon/src/management_interface.rs52
-rw-r--r--mullvad-daemon/src/settings.rs12
-rw-r--r--mullvad-management-interface/proto/management_interface.proto9
-rw-r--r--mullvad-types/src/settings/mod.rs20
-rw-r--r--talpid-types/src/net/mod.rs3
-rw-r--r--windows/winfw/src/winfw/winfw.cpp2
8 files changed, 182 insertions, 79 deletions
diff --git a/mullvad-cli/src/cmds/custom_dns.rs b/mullvad-cli/src/cmds/custom_dns.rs
index daba881f36..c573abeca3 100644
--- a/mullvad-cli/src/cmds/custom_dns.rs
+++ b/mullvad-cli/src/cmds/custom_dns.rs
@@ -1,4 +1,5 @@
use crate::{new_rpc_client, Command, Result};
+use clap::value_t_or_exit;
use mullvad_management_interface::types;
pub struct CustomDns;
@@ -14,38 +15,88 @@ impl Command for CustomDns {
.about("Configure custom DNS servers to use when connected")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(
- clap::SubCommand::with_name("set")
- .about("Change custom DNS setting")
- .arg(
- clap::Arg::with_name("servers")
- .multiple(true)
- .help("One or more IP addresses pointing to DNS resolvers.")
- .required(true),
+ clap::SubCommand::with_name("servers")
+ .about("Set custom DNS servers to use")
+ .setting(clap::AppSettings::SubcommandRequiredElseHelp)
+ .subcommand(
+ clap::SubCommand::with_name("set")
+ .about("Set custom DNS servers to use")
+ .arg(
+ clap::Arg::with_name("servers")
+ .multiple(true)
+ .help("One or more IP addresses pointing to DNS resolvers.")
+ .required(true),
+ ),
+ )
+ .subcommand(
+ clap::SubCommand::with_name("clear").about("Remove all custom DNS servers"),
),
)
- .subcommand(clap::SubCommand::with_name("reset").about("Remove all custom DNS servers"))
.subcommand(
- clap::SubCommand::with_name("get").about("Display the current custom DNS setting"),
+ clap::SubCommand::with_name("get").about("Display the current custom DNS settings"),
+ )
+ .subcommand(
+ clap::SubCommand::with_name("set")
+ .about("Enable or disable custom DNS")
+ .arg(
+ clap::Arg::with_name("enabled")
+ .required(true)
+ .possible_values(&["on", "off"]),
+ ),
)
}
async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
- if let Some(set_matches) = matches.subcommand_matches("set") {
- self.set(set_matches.values_of_lossy("servers")).await
- } else if let Some(_matches) = matches.subcommand_matches("reset") {
- self.reset().await
- } else if let Some(_matches) = matches.subcommand_matches("get") {
- self.get().await
- } else {
- unreachable!("No custom-dns command given");
+ match matches.subcommand() {
+ ("servers", Some(matches)) => match matches.subcommand() {
+ ("set", Some(matches)) => {
+ self.set_servers(matches.values_of_lossy("servers")).await
+ }
+ ("clear", _) => self.clear_servers().await,
+ _ => unreachable!("No custom-dns server command given"),
+ },
+ ("set", Some(matches)) => {
+ let enabled = value_t_or_exit!(matches.value_of("enabled"), String);
+ self.set_state(enabled == "on").await
+ }
+ ("get", _) => self.get().await,
+ _ => unreachable!("No custom-dns command given"),
}
}
}
impl CustomDns {
- async fn set(&self, servers: Option<Vec<String>>) -> Result<()> {
+ async fn set_state(&self, enabled: bool) -> Result<()> {
let mut rpc = new_rpc_client().await?;
- rpc.set_custom_dns(types::CustomDns {
+ let options = rpc
+ .get_settings(())
+ .await?
+ .into_inner()
+ .tunnel_options
+ .unwrap()
+ .dns_options
+ .unwrap();
+ rpc.set_dns_options(types::DnsOptions {
+ custom: enabled,
+ addresses: options.addresses,
+ })
+ .await?;
+ println!("Updated custom DNS settings");
+ Ok(())
+ }
+
+ async fn set_servers(&self, servers: Option<Vec<String>>) -> Result<()> {
+ let mut rpc = new_rpc_client().await?;
+ let options = rpc
+ .get_settings(())
+ .await?
+ .into_inner()
+ .tunnel_options
+ .unwrap()
+ .dns_options
+ .unwrap();
+ rpc.set_dns_options(types::DnsOptions {
+ custom: options.custom,
addresses: servers.unwrap_or_default(),
})
.await?;
@@ -53,34 +104,53 @@ impl CustomDns {
Ok(())
}
- async fn reset(&self) -> Result<()> {
+ async fn clear_servers(&self) -> Result<()> {
let mut rpc = new_rpc_client().await?;
- rpc.set_custom_dns(types::CustomDns { addresses: vec![] })
- .await?;
+ let options = rpc
+ .get_settings(())
+ .await?
+ .into_inner()
+ .tunnel_options
+ .unwrap()
+ .dns_options
+ .unwrap();
+ rpc.set_dns_options(types::DnsOptions {
+ custom: options.custom,
+ addresses: vec![],
+ })
+ .await?;
println!("Cleared list of custom DNS servers");
Ok(())
}
async fn get(&self) -> Result<()> {
let mut rpc = new_rpc_client().await?;
- let custom_dns = rpc
+ let options = rpc
.get_settings(())
.await?
.into_inner()
.tunnel_options
.unwrap()
- .generic
- .unwrap()
- .custom_dns;
- match custom_dns {
- None => println!("No DNS servers are configured"),
- Some(types::CustomDns { addresses }) => {
- println!("Custom DNS servers:");
- for server in &addresses {
+ .dns_options
+ .unwrap();
+
+ let state = if options.custom {
+ "enabled"
+ } else {
+ "disabled"
+ };
+ println!("Custom DNS: {}", state);
+
+ match options.addresses.len() {
+ 0 => println!("No DNS servers are configured"),
+ _ => {
+ println!("Servers:");
+ for server in &options.addresses {
println!("\t{}", server);
}
}
}
+
Ok(())
}
}
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index 7f5b85f7e0..320e839a0a 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -26,6 +26,8 @@ use futures::{
};
use log::{debug, error, info, warn};
use mullvad_rpc::AccountsProxy;
+#[cfg(windows)]
+use mullvad_types::settings::DnsOptions;
use mullvad_types::{
account::{AccountData, AccountToken, VoucherSubmission},
endpoint::MullvadEndpoint,
@@ -196,7 +198,7 @@ pub enum DaemonCommand {
SetEnableIpv6(oneshot::Sender<()>, bool),
/// Set custom DNS servers to use instead of passing requests to the gateway
#[cfg(windows)]
- SetCustomDns(oneshot::Sender<()>, Option<Vec<IpAddr>>),
+ SetDnsOptions(oneshot::Sender<()>, DnsOptions),
/// Set MTU for wireguard tunnels
SetWireguardMtu(oneshot::Sender<()>, Option<u16>),
/// Set automatic key rotation interval for wireguard tunnels
@@ -581,7 +583,7 @@ where
settings.allow_lan,
settings.block_when_disconnected,
#[cfg(windows)]
- settings.tunnel_options.generic.custom_dns.clone(),
+ Self::get_custom_resolvers(&settings.tunnel_options.dns_options),
tunnel_parameters_generator,
log_dir,
resource_dir,
@@ -634,6 +636,15 @@ where
Ok(daemon)
}
+ #[cfg(windows)]
+ fn get_custom_resolvers(dns_options: &DnsOptions) -> Option<Vec<IpAddr>> {
+ if dns_options.custom {
+ Some(dns_options.addresses.clone())
+ } else {
+ None
+ }
+ }
+
/// Consume the `Daemon` and run the main event loop. Blocks until an error happens or a
/// shutdown event is received.
pub async fn run(mut self) -> Result<(), Error> {
@@ -1046,7 +1057,7 @@ where
SetBridgeState(tx, bridge_state) => self.on_set_bridge_state(tx, bridge_state),
SetEnableIpv6(tx, enable_ipv6) => self.on_set_enable_ipv6(tx, enable_ipv6),
#[cfg(windows)]
- SetCustomDns(tx, dns_servers) => self.on_set_custom_dns(tx, dns_servers),
+ SetDnsOptions(tx, dns_servers) => self.on_set_dns_options(tx, dns_servers),
SetWireguardMtu(tx, mtu) => self.on_set_wireguard_mtu(tx, mtu),
SetWireguardRotationInterval(tx, interval) => {
self.on_set_wireguard_rotation_interval(tx, interval).await
@@ -1686,15 +1697,17 @@ where
}
#[cfg(windows)]
- fn on_set_custom_dns(&mut self, tx: oneshot::Sender<()>, servers: Option<Vec<IpAddr>>) {
- let save_result = self.settings.set_custom_dns(servers.clone());
+ fn on_set_dns_options(&mut self, tx: oneshot::Sender<()>, dns_options: DnsOptions) {
+ let save_result = self.settings.set_dns_options(dns_options.clone());
match save_result {
Ok(settings_changed) => {
- Self::oneshot_send(tx, (), "set_custom_dns response");
+ Self::oneshot_send(tx, (), "set_dns_options response");
if settings_changed {
- self.event_listener
- .notify_settings(self.settings.to_settings());
- self.send_tunnel_command(TunnelCommand::CustomDns(servers));
+ let settings = self.settings.to_settings();
+ let resolvers =
+ Self::get_custom_resolvers(&settings.tunnel_options.dns_options);
+ self.event_listener.notify_settings(settings);
+ self.send_tunnel_command(TunnelCommand::CustomDns(resolvers));
}
}
Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index a5cfebedc3..ca324308cb 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -6,6 +6,8 @@ use mullvad_management_interface::{
};
use mullvad_paths;
use mullvad_rpc::{rest::Error as RestError, StatusCode};
+#[cfg(windows)]
+use mullvad_types::settings::DnsOptions;
use mullvad_types::{
account::AccountToken,
location::GeoIpLocation,
@@ -409,12 +411,16 @@ impl ManagementService for ManagementServiceImpl {
}
#[cfg(windows)]
- async fn set_custom_dns(&self, request: Request<types::CustomDns>) -> ServiceResult<()> {
- let servers = request.into_inner();
- log::debug!("set_custom_dns({:?})", servers.addresses);
+ async fn set_dns_options(&self, request: Request<types::DnsOptions>) -> ServiceResult<()> {
+ let options = request.into_inner();
+ log::debug!(
+ "set_dns_options({}, {:?})",
+ options.custom,
+ options.addresses
+ );
let mut servers_ip = vec![];
- for server in servers.addresses.into_iter() {
+ for server in options.addresses.into_iter() {
if let Ok(addr) = server.parse() {
servers_ip.push(addr);
} else {
@@ -423,20 +429,20 @@ impl ManagementService for ManagementServiceImpl {
}
}
- let servers_ip = if !servers_ip.is_empty() {
- Some(servers_ip)
- } else {
- None
- };
-
let (tx, rx) = oneshot::channel();
- self.send_command_to_daemon(DaemonCommand::SetCustomDns(tx, servers_ip))?;
+ self.send_command_to_daemon(DaemonCommand::SetDnsOptions(
+ tx,
+ DnsOptions {
+ custom: options.custom,
+ addresses: servers_ip,
+ },
+ ))?;
rx.await
.map(Response::new)
.map_err(|_| Status::internal("internal error"))
}
#[cfg(not(windows))]
- async fn set_custom_dns(&self, _: Request<types::CustomDns>) -> ServiceResult<()> {
+ async fn set_dns_options(&self, _: Request<types::DnsOptions>) -> ServiceResult<()> {
Ok(Response::new(()))
}
@@ -1172,17 +1178,19 @@ fn convert_tunnel_options(options: &TunnelOptions) -> types::TunnelOptions {
}),
generic: Some(types::tunnel_options::GenericOptions {
enable_ipv6: options.generic.enable_ipv6,
- #[cfg(windows)]
- custom_dns: options
- .generic
- .custom_dns
- .as_ref()
- .map(|addresses| types::CustomDns {
- addresses: addresses.iter().map(|addr| addr.to_string()).collect(),
- }),
- #[cfg(not(windows))]
- custom_dns: None,
}),
+ #[cfg(windows)]
+ dns_options: Some(types::DnsOptions {
+ custom: options.dns_options.custom,
+ addresses: options
+ .dns_options
+ .addresses
+ .iter()
+ .map(|addr| addr.to_string())
+ .collect(),
+ }),
+ #[cfg(not(windows))]
+ dns_options: None,
}
}
diff --git a/mullvad-daemon/src/settings.rs b/mullvad-daemon/src/settings.rs
index 1f6f6a447c..bcc07f84ae 100644
--- a/mullvad-daemon/src/settings.rs
+++ b/mullvad-daemon/src/settings.rs
@@ -1,10 +1,10 @@
use log::{debug, error, info};
+#[cfg(windows)]
+use mullvad_types::settings::DnsOptions;
use mullvad_types::{
relay_constraints::{BridgeSettings, BridgeState, RelaySettingsUpdate},
settings::Settings,
};
-#[cfg(windows)]
-use std::net::IpAddr;
use std::{
fs::{self, File},
io,
@@ -213,11 +213,9 @@ impl SettingsPersister {
}
#[cfg(windows)]
- pub fn set_custom_dns(&mut self, servers: Option<Vec<IpAddr>>) -> Result<bool, Error> {
- let should_save = Self::update_field(
- &mut self.settings.tunnel_options.generic.custom_dns,
- servers,
- );
+ pub fn set_dns_options(&mut self, options: DnsOptions) -> Result<bool, Error> {
+ let should_save =
+ Self::update_field(&mut self.settings.tunnel_options.dns_options, options);
self.update(should_save)
}
diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto
index b66bc7439f..6d40e50d78 100644
--- a/mullvad-management-interface/proto/management_interface.proto
+++ b/mullvad-management-interface/proto/management_interface.proto
@@ -39,7 +39,7 @@ service ManagementService {
rpc SetOpenvpnMssfix(google.protobuf.UInt32Value) returns (google.protobuf.Empty) {}
rpc SetWireguardMtu(google.protobuf.UInt32Value) returns (google.protobuf.Empty) {}
rpc SetEnableIpv6(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
- rpc SetCustomDns(CustomDns) returns (google.protobuf.Empty) {}
+ rpc SetDnsOptions(DnsOptions) returns (google.protobuf.Empty) {}
// Account management
rpc CreateNewAccount(google.protobuf.Empty) returns (google.protobuf.StringValue) {}
@@ -360,16 +360,17 @@ message TunnelOptions {
}
message GenericOptions {
bool enable_ipv6 = 1;
- CustomDns custom_dns = 2;
}
OpenvpnOptions openvpn = 1;
WireguardOptions wireguard = 2;
GenericOptions generic = 3;
+ DnsOptions dns_options = 4;
}
-message CustomDns {
- repeated string addresses = 1;
+message DnsOptions {
+ bool custom = 1;
+ repeated string addresses = 2;
}
message PublicKey {
diff --git a/mullvad-types/src/settings/mod.rs b/mullvad-types/src/settings/mod.rs
index 2b8ce221b8..0c8810b1db 100644
--- a/mullvad-types/src/settings/mod.rs
+++ b/mullvad-types/src/settings/mod.rs
@@ -7,6 +7,8 @@ use jnix::IntoJava;
use log::{debug, info};
use serde::{Deserialize, Serialize};
use serde_json;
+#[cfg(windows)]
+use std::net::IpAddr;
use talpid_types::net::{openvpn, wireguard, GenericTunnelOptions};
mod migrations;
@@ -164,6 +166,20 @@ pub struct TunnelOptions {
/// Contains generic tunnel options that may apply to more than a single tunnel type.
#[cfg_attr(target_os = "android", jnix(skip))]
pub generic: GenericTunnelOptions,
+ /// Custom DNS options.
+ #[cfg(windows)]
+ pub dns_options: DnsOptions,
+}
+
+/// Custom DNS config
+#[cfg(windows)]
+#[serde(default)]
+#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
+pub struct DnsOptions {
+ /// Whether to use the addresses in `custom_dns`.
+ pub custom: bool,
+ /// Custom DNS servers to use.
+ pub addresses: Vec<IpAddr>,
}
impl Default for TunnelOptions {
@@ -177,9 +193,9 @@ impl Default for TunnelOptions {
generic: GenericTunnelOptions {
// Enable IPv6 be default on Android
enable_ipv6: cfg!(target_os = "android"),
- #[cfg(windows)]
- custom_dns: None,
},
+ #[cfg(windows)]
+ dns_options: DnsOptions::default(),
}
}
}
diff --git a/talpid-types/src/net/mod.rs b/talpid-types/src/net/mod.rs
index 36528e9744..15bf33a5bb 100644
--- a/talpid-types/src/net/mod.rs
+++ b/talpid-types/src/net/mod.rs
@@ -203,9 +203,6 @@ pub struct GenericTunnelOptions {
/// Enable configuration of IPv6 on the tunnel interface, allowing IPv6 communication to be
/// forwarded through the tunnel.
pub enable_ipv6: bool,
- /// Custom DNS servers to use.
- #[cfg(windows)]
- pub custom_dns: Option<Vec<IpAddr>>,
}
/// Returns a vector of IP networks representing all of the internet, 0.0.0.0/0.
diff --git a/windows/winfw/src/winfw/winfw.cpp b/windows/winfw/src/winfw/winfw.cpp
index 080713b742..0ea46c2ce2 100644
--- a/windows/winfw/src/winfw/winfw.cpp
+++ b/windows/winfw/src/winfw/winfw.cpp
@@ -346,7 +346,7 @@ WinFw_ApplyPolicyConnected(
THROW_ERROR("Invalid argument: v4Gateway");
}
- if (nullptr == dnsServers || 0 == numDnsServers)
+ if (nullptr == dnsServers)
{
THROW_ERROR("Invalid argument: dnsServers");
}