summaryrefslogtreecommitdiffhomepage
path: root/mullvad-cli/src
diff options
context:
space:
mode:
authorEmīls <emils@mullvad.net>2021-09-07 16:33:53 +0100
committerOdd Stranne <odd@mullvad.net>2022-03-24 10:36:16 +0100
commit35d511e205c32312ca8a7a0a9271445bb29df35b (patch)
tree9ab798da1c37597ce542231507b522c807dddd16 /mullvad-cli/src
parente7b6106bb86513d99d164a5184ad68f56e44dd32 (diff)
downloadmullvadvpn-35d511e205c32312ca8a7a0a9271445bb29df35b.tar.xz
mullvadvpn-35d511e205c32312ca8a7a0a9271445bb29df35b.zip
Add CLI commands for configuring obfuscation
Diffstat (limited to 'mullvad-cli/src')
-rw-r--r--mullvad-cli/src/cmds/mod.rs4
-rw-r--r--mullvad-cli/src/cmds/obfuscation.rs134
-rw-r--r--mullvad-cli/src/format.rs21
3 files changed, 158 insertions, 1 deletions
diff --git a/mullvad-cli/src/cmds/mod.rs b/mullvad-cli/src/cmds/mod.rs
index 2ceb3bfdcf..4c374d64ee 100644
--- a/mullvad-cli/src/cmds/mod.rs
+++ b/mullvad-cli/src/cmds/mod.rs
@@ -28,6 +28,9 @@ pub use self::dns::Dns;
mod lan;
pub use self::lan::Lan;
+mod obfuscation;
+pub use self::obfuscation::Obfuscation;
+
mod reconnect;
pub use self::reconnect::Reconnect;
@@ -64,6 +67,7 @@ pub fn get_commands() -> HashMap<&'static str, Box<dyn Command>> {
Box::new(Dns),
Box::new(Reconnect),
Box::new(Lan),
+ Box::new(Obfuscation),
Box::new(Relay),
Box::new(Reset),
#[cfg(any(target_os = "linux", windows))]
diff --git a/mullvad-cli/src/cmds/obfuscation.rs b/mullvad-cli/src/cmds/obfuscation.rs
new file mode 100644
index 0000000000..99887db555
--- /dev/null
+++ b/mullvad-cli/src/cmds/obfuscation.rs
@@ -0,0 +1,134 @@
+use crate::{new_rpc_client, Command, Result};
+
+use mullvad_management_interface::{types as grpc_types, ManagementServiceClient};
+
+use mullvad_types::relay_constraints::{ObfuscationSettings, SelectedObfuscation};
+
+use std::convert::TryFrom;
+
+pub struct Obfuscation;
+
+#[mullvad_management_interface::async_trait]
+impl Command for Obfuscation {
+ fn name(&self) -> &'static str {
+ "obfuscation"
+ }
+
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
+ .about("Manage use of obfuscators")
+ .setting(clap::AppSettings::SubcommandRequiredElseHelp)
+ .subcommand(create_obfuscation_set_subcommand())
+ .subcommand(create_obfuscation_get_subcommand())
+ }
+
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
+ match matches.subcommand() {
+ Some(("set", set_matches)) => Self::handle_set(set_matches).await,
+ Some(("get", get_matches)) => Self::handle_get(get_matches).await,
+ _ => unreachable!("unhandled command"),
+ }
+ }
+}
+
+impl Obfuscation {
+ async fn handle_set(matches: &clap::ArgMatches) -> Result<()> {
+ match matches.subcommand() {
+ Some(("mode", mode_matches)) => {
+ let obfuscator_type = mode_matches.value_of("mode").unwrap();
+ let mut rpc = new_rpc_client().await?;
+ let mut settings = Self::get_obfuscation_settings(&mut rpc).await?;
+ settings.selected_obfuscation = match obfuscator_type {
+ "auto" => SelectedObfuscation::Auto,
+ "off" => SelectedObfuscation::Off,
+ "udp2tcp" => SelectedObfuscation::Udp2Tcp,
+ _ => unreachable!("Unhandled obfuscator mode"),
+ };
+ Self::set_obfuscation_settings(&mut rpc, &settings).await?;
+ }
+ Some(("udp2tcp-settings", settings_matches)) => {
+ let port: String = settings_matches.value_of_t_or_exit("port");
+ let mut rpc = new_rpc_client().await?;
+ let mut settings = Self::get_obfuscation_settings(&mut rpc).await?;
+ settings.udp2tcp.port = if port == "any" {
+ mullvad_types::relay_constraints::Constraint::Any
+ } else {
+ mullvad_types::relay_constraints::Constraint::Only(
+ port.parse::<u16>().expect("Invalid port number"),
+ )
+ };
+ Self::set_obfuscation_settings(&mut rpc, &settings).await?;
+ }
+ _ => unreachable!("unhandled command"),
+ }
+ Ok(())
+ }
+
+ async fn handle_get(matches: &clap::ArgMatches) -> Result<()> {
+ let mut rpc = new_rpc_client().await?;
+ let settings = Self::get_obfuscation_settings(&mut rpc).await?;
+ match matches.subcommand() {
+ Some(("udp2tcp-settings", _)) => println!("Udp2Tcp: {}", settings.udp2tcp),
+ _ => println!("Current settings: {}", settings),
+ }
+ Ok(())
+ }
+
+ async fn get_obfuscation_settings(
+ rpc: &mut ManagementServiceClient,
+ ) -> Result<ObfuscationSettings> {
+ let settings = rpc.get_settings(()).await?.into_inner();
+
+ let obfuscation_settings = ObfuscationSettings::try_from(
+ settings
+ .obfuscation_settings
+ .expect("No obfuscation settings"),
+ )
+ .expect("failed to parse obfuscation settings");
+ Ok(obfuscation_settings)
+ }
+
+ async fn set_obfuscation_settings(
+ rpc: &mut ManagementServiceClient,
+ settings: &ObfuscationSettings,
+ ) -> Result<()> {
+ let grpc_settings: grpc_types::ObfuscationSettings = settings.into();
+ let _ = rpc.set_obfuscation_settings(grpc_settings).await?;
+ Ok(())
+ }
+}
+
+fn create_obfuscation_set_subcommand() -> clap::App<'static> {
+ clap::App::new("set")
+ .about("Set obfuscation settings")
+ .setting(clap::AppSettings::SubcommandRequiredElseHelp)
+ .subcommand(
+ clap::App::new("mode").about("Set obfuscation mode").arg(
+ clap::Arg::new("mode")
+ .help("Specifies what kind of obfuscation should be used, if any")
+ .required(true)
+ .index(1)
+ .possible_values(&["auto", "off", "udp2tcp"]),
+ ),
+ )
+ .subcommand(
+ clap::App::new("udp2tcp-settings")
+ .about("Specifies the config for the udp2tcp obfuscator")
+ .setting(clap::AppSettings::ArgRequiredElseHelp)
+ .arg(
+ clap::Arg::new("port")
+ .help("TCP port of remote endpoint. Either 'any' or a specific port")
+ .long("port")
+ .takes_value(true),
+ ),
+ )
+}
+
+fn create_obfuscation_get_subcommand() -> clap::App<'static> {
+ clap::App::new("get")
+ .about("Get obfuscation settings")
+ .subcommand(
+ clap::App::new("udp2tcp-settings")
+ .about("Specifies the config for the udp2tcp obfuscator"),
+ )
+}
diff --git a/mullvad-cli/src/format.rs b/mullvad-cli/src/format.rs
index eb91ffcca8..76ffcf7fb1 100644
--- a/mullvad-cli/src/format.rs
+++ b/mullvad-cli/src/format.rs
@@ -5,7 +5,8 @@ use mullvad_management_interface::types::{
},
tunnel_state,
tunnel_state::State::*,
- ErrorState, ProxyType, TransportProtocol, TunnelEndpoint, TunnelState, TunnelType,
+ ErrorState, ObfuscationType, ProxyType, TransportProtocol, TunnelEndpoint, TunnelState,
+ TunnelType,
};
use mullvad_types::auth_failed::AuthFailed;
use std::fmt::Write;
@@ -83,6 +84,24 @@ fn format_endpoint(endpoint: &TunnelEndpoint) -> String {
)
.unwrap();
}
+ if let Some(ref obfuscation) = endpoint.obfuscation {
+ write!(
+ &mut out,
+ " via {} {}:{} over {}",
+ match ObfuscationType::from_i32(obfuscation.obfuscation_type)
+ .expect("invalid obfuscation type")
+ {
+ ObfuscationType::Udp2tcp => "Udp2Tcp",
+ },
+ obfuscation.address,
+ obfuscation.port,
+ format_protocol(
+ TransportProtocol::from_i32(obfuscation.protocol)
+ .expect("invalid transport protocol")
+ )
+ )
+ .unwrap();
+ }
}
}