summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2023-09-20 13:41:43 +0200
committerDavid Lönnhager <david.l@mullvad.net>2023-10-09 14:40:06 +0200
commit7fcaad31643ca324c5dd4a17ddf0f445ac679384 (patch)
tree9a913059321b437857863efed43b4d47ed9c0eb4
parentfc477f4e4df6db2973ff88fc4b6819d38d64d8cc (diff)
downloadmullvadvpn-7fcaad31643ca324c5dd4a17ddf0f445ac679384.tar.xz
mullvadvpn-7fcaad31643ca324c5dd4a17ddf0f445ac679384.zip
Add `mullvad proxy test`
For quickly assessing whether an api access method can reach the API or not.
-rw-r--r--mullvad-cli/src/cmds/proxy.rs34
-rw-r--r--mullvad-daemon/src/lib.rs10
-rw-r--r--mullvad-daemon/src/management_interface.rs11
-rw-r--r--mullvad-management-interface/proto/management_interface.proto2
-rw-r--r--mullvad-management-interface/src/client.rs5
5 files changed, 62 insertions, 0 deletions
diff --git a/mullvad-cli/src/cmds/proxy.rs b/mullvad-cli/src/cmds/proxy.rs
index c876a25d2e..fa05081f89 100644
--- a/mullvad-cli/src/cmds/proxy.rs
+++ b/mullvad-cli/src/cmds/proxy.rs
@@ -24,6 +24,8 @@ pub enum Proxy {
Enable(SelectItem),
/// Disable an API proxy
Disable(SelectItem),
+ /// Test an API proxy
+ Test(SelectItem),
/// Force the use of a specific API proxy.
Use(SelectItem),
}
@@ -59,6 +61,10 @@ impl Proxy {
let enabled = false;
Self::toggle(index, enabled).await?;
}
+ Proxy::Test(cmd) => {
+ let index = Self::zero_to_one_based_index(cmd.index)?;
+ Self::test(index).await?;
+ }
Proxy::Use(cmd) => {
let index = Self::zero_to_one_based_index(cmd.index)?;
Self::set(index).await?;
@@ -199,6 +205,34 @@ impl Proxy {
Ok(())
}
+ /// Test an access method to see if it successfully reaches the Mullvad API.
+ async fn test(index: usize) -> Result<()> {
+ let mut rpc = MullvadProxyClient::new().await?;
+ // TODO: Refactor this into some helper function. This code has been copy-pastead a lot already ..
+ // Step 1.
+ let access_method = rpc
+ .get_api_access_methods()
+ .await?
+ .get(index)
+ .ok_or(anyhow!(format!(
+ "Access method {} does not exist",
+ index + 1
+ )))?
+ .clone();
+
+ // Step 2.
+ rpc.set_access_method(access_method).await?;
+ // Step 3.
+ let api_call = rpc.test_api().await;
+ // Step 4.
+ match api_call {
+ Ok(_) => println!("API call succeeded!"),
+ Err(_) => println!("API call failed :-("),
+ }
+
+ Ok(())
+ }
+
/// Force the use of a specific access method when trying to reach the
/// Mullvad API. If this method fails, the daemon will resume the automatic
/// roll-over behavior (which is the default).
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index 3c822fdf4e..ed7bafd007 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -275,6 +275,8 @@ pub enum DaemonCommand {
ToggleApiAccessMethod(ResponseTx<(), Error>, ApiAccessMethodToggle),
/// Set the API access method to use
SetApiAccessMethod(ResponseTx<(), Error>, AccessMethod),
+ /// Get the addresses of all known API endpoints
+ GetApiAddresses(ResponseTx<Vec<std::net::SocketAddr>, Error>),
/// Get information about the currently running and latest app versions
GetVersionInfo(oneshot::Sender<Option<AppVersionInfo>>),
/// Return whether the daemon is performing post-upgrade tasks
@@ -1067,6 +1069,7 @@ where
}
ToggleApiAccessMethod(tx, method) => self.on_toggle_api_access_method(tx, method).await,
SetApiAccessMethod(tx, method) => self.on_set_api_access_method(tx, method).await,
+ GetApiAddresses(tx) => self.on_get_api_addresses(tx).await,
IsPerformingPostUpgrade(tx) => self.on_is_performing_post_upgrade(tx),
GetCurrentVersion(tx) => self.on_get_current_version(tx),
#[cfg(not(target_os = "android"))]
@@ -2298,6 +2301,13 @@ where
Self::oneshot_send(tx, result, "set_api_access_method response");
}
+ async fn on_get_api_addresses(&mut self, tx: ResponseTx<Vec<std::net::SocketAddr>, Error>) {
+ let api_proxy = mullvad_api::ApiProxy::new(self.api_handle.clone());
+ let result = api_proxy.get_api_addrs().await.map_err(Error::RestError);
+
+ Self::oneshot_send(tx, result, "on_get_api_adressess response");
+ }
+
fn on_get_settings(&self, tx: oneshot::Sender<Settings>) {
Self::oneshot_send(tx, self.settings.to_settings(), "get_settings response");
}
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index 2b6481207a..88ea87056c 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -654,6 +654,17 @@ impl ManagementService for ManagementServiceImpl {
.map_err(map_daemon_error)
}
+ async fn get_api_addressess(&self, _: Request<()>) -> ServiceResult<()> {
+ log::debug!("test_api");
+ let (tx, rx) = oneshot::channel();
+ self.send_command_to_daemon(DaemonCommand::GetApiAddresses(tx))?;
+ self.wait_for_result(rx)
+ .await?
+ .map(drop)
+ .map(Response::new)
+ .map_err(map_daemon_error)
+ }
+
// Split tunneling
//
diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto
index a062e0b642..018906cdaf 100644
--- a/mullvad-management-interface/proto/management_interface.proto
+++ b/mullvad-management-interface/proto/management_interface.proto
@@ -91,6 +91,8 @@ service ManagementService {
// Can I return something useful here instead of Empty?
}
+ rpc GetApiAddressess(google.protobuf.Empty) returns (google.protobuf.Empty) {}
+
// Split tunneling (Linux)
rpc GetSplitTunnelProcesses(google.protobuf.Empty) returns (stream google.protobuf.Int32Value) {}
rpc AddSplitTunnelProcess(google.protobuf.Int32Value) returns (google.protobuf.Empty) {}
diff --git a/mullvad-management-interface/src/client.rs b/mullvad-management-interface/src/client.rs
index 900775b10a..049f8a2fe3 100644
--- a/mullvad-management-interface/src/client.rs
+++ b/mullvad-management-interface/src/client.rs
@@ -181,6 +181,11 @@ impl MullvadProxyClient {
.collect()
}
+ pub async fn test_api(&mut self) -> Result<()> {
+ self.0.get_api_addressess(()).await.map_err(Error::Rpc)?;
+ Ok(())
+ }
+
pub async fn update_relay_locations(&mut self) -> Result<()> {
self.0
.update_relay_locations(())