summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mullvad-cli/src/cmds/bridge.rs354
-rw-r--r--mullvad-cli/src/cmds/mod.rs4
-rw-r--r--mullvad-cli/src/cmds/relay.rs82
-rw-r--r--mullvad-cli/src/cmds/tunnel.rs240
-rw-r--r--mullvad-cli/src/location.rs69
-rw-r--r--mullvad-cli/src/main.rs1
-rw-r--r--mullvad-daemon/src/lib.rs79
-rw-r--r--mullvad-daemon/src/management_interface.rs46
-rw-r--r--mullvad-daemon/src/relays.rs6
-rw-r--r--mullvad-ipc-client/src/lib.rs15
-rw-r--r--mullvad-types/src/custom_tunnel.rs2
-rw-r--r--mullvad-types/src/relay_constraints.rs23
-rw-r--r--mullvad-types/src/settings.rs13
-rw-r--r--talpid-core/src/process/openvpn.rs4
-rw-r--r--talpid-core/src/tunnel/openvpn.rs6
-rw-r--r--talpid-core/src/tunnel_state_machine/connected_state.rs2
-rw-r--r--talpid-core/src/tunnel_state_machine/connecting_state.rs2
-rw-r--r--talpid-types/src/net/openvpn.rs3
18 files changed, 568 insertions, 383 deletions
diff --git a/mullvad-cli/src/cmds/bridge.rs b/mullvad-cli/src/cmds/bridge.rs
new file mode 100644
index 0000000000..3c686154eb
--- /dev/null
+++ b/mullvad-cli/src/cmds/bridge.rs
@@ -0,0 +1,354 @@
+use crate::{location, new_rpc_client, Command, Result};
+use clap::value_t;
+
+use mullvad_types::relay_constraints::{BridgeConstraints, BridgeSettings, BridgeState};
+use talpid_types::net::openvpn::{self, SHADOWSOCKS_CIPHERS};
+
+use std::net::{IpAddr, SocketAddr};
+
+pub struct Bridge;
+
+impl Command for Bridge {
+ fn name(&self) -> &'static str {
+ "bridge"
+ }
+
+ fn clap_subcommand(&self) -> clap::App<'static, 'static> {
+ clap::SubCommand::with_name(self.name())
+ .about("Manage use of bridges")
+ .setting(clap::AppSettings::SubcommandRequiredElseHelp)
+ .subcommand(create_bridge_set_subcommand())
+ .subcommand(
+ clap::SubCommand::with_name("get").about("Get current bridge settings and state"),
+ )
+ .subcommand(clap::SubCommand::with_name("list").about("List brigde relays"))
+ }
+
+ fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ match matches.subcommand() {
+ ("set", Some(set_matches)) => Self::handle_set(set_matches),
+ ("get", _) => Self::handle_get(),
+ ("list", _) => Self::list_bridge_relays(),
+ _ => unreachable!("unhandled command"),
+ }
+ }
+}
+
+fn create_bridge_set_subcommand() -> clap::App<'static, 'static> {
+ clap::SubCommand::with_name("set")
+ .about("Set bridge state and settings")
+ .setting(clap::AppSettings::SubcommandRequiredElseHelp)
+ .subcommand(create_set_state_subcommand())
+ .subcommand(create_set_custom_settings_subcommand())
+ .subcommand(location::get_subcommand().about(
+ "Set country or city to select bridge relays from. Use the 'list' \
+ command to show available alternatives.",
+ ))
+}
+
+
+fn create_set_custom_settings_subcommand() -> clap::App<'static, 'static> {
+ clap::SubCommand::with_name("custom")
+ .about("Configure a SOCKS5 proxy")
+ .setting(clap::AppSettings::SubcommandRequiredElseHelp)
+ .subcommand(
+ clap::SubCommand::with_name("local")
+ .about("Registers a local SOCKS5 proxy")
+ .arg(
+ clap::Arg::with_name("local-port")
+ .help("Specifies the port the local proxy server is listening on")
+ .required(true)
+ .index(1),
+ )
+ .arg(
+ clap::Arg::with_name("remote-ip")
+ .help("Specifies the IP of the proxy server peer")
+ .required(true)
+ .index(2),
+ )
+ .arg(
+ clap::Arg::with_name("remote-port")
+ .help("Specifies the port of the proxy server peer")
+ .required(true)
+ .index(3),
+ ),
+ )
+ .subcommand(
+ clap::SubCommand::with_name("remote")
+ .about("Registers a remote SOCKS5 proxy")
+ .arg(
+ clap::Arg::with_name("remote-ip")
+ .help("Specifies the IP of the remote proxy server")
+ .required(true)
+ .index(1),
+ )
+ .arg(
+ clap::Arg::with_name("remote-port")
+ .help("Specifies the port the remote proxy server is listening on")
+ .required(true)
+ .index(2),
+ )
+ .arg(
+ clap::Arg::with_name("username")
+ .help("Specifies the username for remote authentication")
+ .required(true)
+ .index(3),
+ )
+ .arg(
+ clap::Arg::with_name("password")
+ .help("Specifies the password for remote authentication")
+ .required(true)
+ .index(4),
+ ),
+ )
+ .subcommand(
+ clap::SubCommand::with_name("shadowsocks")
+ .about("Configure bundled Shadowsocks proxy")
+ .arg(
+ clap::Arg::with_name("remote-ip")
+ .help("Specifies the IP of the remote Shadowsocks server")
+ .required(true)
+ .index(1),
+ )
+ .arg(
+ clap::Arg::with_name("remote-port")
+ .help("Specifies the port of the remote Shadowsocks server")
+ .default_value("443")
+ .index(2),
+ )
+ .arg(
+ clap::Arg::with_name("password")
+ .help("Specifies the password on the remote Shadowsocks server")
+ .default_value("23#dfsbbb")
+ .index(3),
+ )
+ .arg(
+ clap::Arg::with_name("cipher")
+ .help("Specifies the cipher to use")
+ .default_value("chacha20")
+ .possible_values(SHADOWSOCKS_CIPHERS)
+ .index(4),
+ ),
+ )
+}
+
+fn create_set_state_subcommand() -> clap::App<'static, 'static> {
+ clap::SubCommand::with_name("state")
+ .about("Set bridge state")
+ .arg(
+ clap::Arg::with_name("state")
+ .help("Specifies whether a bridge should be used")
+ .index(1)
+ .possible_values(&["auto", "on", "off"]),
+ )
+}
+
+impl Bridge {
+ fn handle_set(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ match matches.subcommand() {
+ ("location", Some(location_matches)) => {
+ Self::handle_set_bridge_location(location_matches)
+ }
+ ("custom", Some(custom_matches)) => {
+ Self::handle_bridge_set_custom_settings(custom_matches)
+ }
+ ("state", Some(set_matches)) => Self::handle_set_bridge_state(set_matches),
+ _ => unreachable!("unhandled command"),
+ }
+ }
+
+ fn handle_get() -> Result<()> {
+ let mut rpc = new_rpc_client()?;
+ let settings = rpc.get_settings()?;
+ println!("Bridge state - {}", settings.get_bridge_state());
+ match settings.get_bridge_settings() {
+ BridgeSettings::Custom(proxy) => {
+ match proxy {
+ openvpn::ProxySettings::Local(local_proxy) => {
+ Self::print_local_proxy(&local_proxy)
+ }
+ openvpn::ProxySettings::Remote(remote_proxy) => {
+ Self::print_remote_proxy(&remote_proxy)
+ }
+ openvpn::ProxySettings::Shadowsocks(shadowsocks_proxy) => {
+ Self::print_shadowsocks_proxy(&shadowsocks_proxy)
+ }
+ };
+ }
+ BridgeSettings::Normal(constraints) => {
+ println!("Bridge constraints: {}", constraints);
+ }
+ };
+ Ok(())
+ }
+
+ fn handle_set_bridge_location(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ let location = location::get_constraint(matches);
+ let mut rpc = new_rpc_client()?;
+ rpc.set_bridge_settings(BridgeSettings::Normal(BridgeConstraints { location }))?;
+ Ok(())
+ }
+
+ fn handle_set_bridge_state(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ let state = match matches.value_of("state").unwrap() {
+ "auto" => BridgeState::Auto,
+ "on" => BridgeState::On,
+ "off" => BridgeState::Off,
+ _ => unreachable!(),
+ };
+ let mut rpc = new_rpc_client()?;
+ rpc.set_bridge_state(state)?;
+ Ok(())
+ }
+
+ fn handle_bridge_set_custom_settings(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ if let Some(args) = matches.subcommand_matches("local") {
+ let local_port =
+ value_t!(args.value_of("local-port"), u16).unwrap_or_else(|e| e.exit());
+ let remote_ip =
+ value_t!(args.value_of("remote-ip"), IpAddr).unwrap_or_else(|e| e.exit());
+ let remote_port =
+ value_t!(args.value_of("remote-port"), u16).unwrap_or_else(|e| e.exit());
+
+ let proxy = openvpn::LocalProxySettings {
+ port: local_port,
+ peer: SocketAddr::new(remote_ip, remote_port),
+ };
+
+ let packed_proxy = openvpn::ProxySettings::Local(proxy);
+
+ if let Err(error) = openvpn::validate_proxy_settings(&packed_proxy) {
+ panic!(error);
+ }
+
+ let mut rpc = new_rpc_client()?;
+ rpc.set_bridge_settings(BridgeSettings::Custom(packed_proxy))?;
+ } else if let Some(args) = matches.subcommand_matches("remote") {
+ let remote_ip =
+ value_t!(args.value_of("remote-ip"), IpAddr).unwrap_or_else(|e| e.exit());
+ let remote_port =
+ value_t!(args.value_of("remote-port"), u16).unwrap_or_else(|e| e.exit());
+ let username = args.value_of("username");
+ let password = args.value_of("password");
+
+ let auth = match (username, password) {
+ (Some(username), Some(password)) => Some(openvpn::ProxyAuth {
+ username: username.to_string(),
+ password: password.to_string(),
+ }),
+ _ => None,
+ };
+
+ let proxy = openvpn::RemoteProxySettings {
+ address: SocketAddr::new(remote_ip, remote_port),
+ auth,
+ };
+
+ let packed_proxy = openvpn::ProxySettings::Remote(proxy);
+
+ if let Err(error) = openvpn::validate_proxy_settings(&packed_proxy) {
+ panic!(error);
+ }
+
+ let mut rpc = new_rpc_client()?;
+ rpc.set_bridge_settings(BridgeSettings::Custom(packed_proxy))?;
+ } else if let Some(args) = matches.subcommand_matches("shadowsocks") {
+ let remote_ip =
+ value_t!(args.value_of("remote-ip"), IpAddr).unwrap_or_else(|e| e.exit());
+ let remote_port =
+ value_t!(args.value_of("remote-port"), u16).unwrap_or_else(|e| e.exit());
+ let password = args.value_of("password").unwrap().to_string();
+ let cipher = args.value_of("cipher").unwrap().to_string();
+
+ let proxy = openvpn::ShadowsocksProxySettings {
+ peer: SocketAddr::new(remote_ip, remote_port),
+ password,
+ cipher,
+ };
+
+ let packed_proxy = openvpn::ProxySettings::Shadowsocks(proxy);
+
+ if let Err(error) = openvpn::validate_proxy_settings(&packed_proxy) {
+ panic!(error);
+ }
+
+ let mut rpc = new_rpc_client()?;
+ rpc.set_bridge_settings(BridgeSettings::Custom(packed_proxy))?;
+ } else {
+ unreachable!("unhandled proxy type");
+ }
+
+ println!("proxy details have been updated");
+ Ok(())
+ }
+
+ fn print_local_proxy(proxy: &openvpn::LocalProxySettings) {
+ println!("proxy: local");
+ println!(" local port: {}", proxy.port);
+ println!(" peer IP: {}", proxy.peer.ip());
+ println!(" peer port: {}", proxy.peer.port());
+ }
+
+ fn print_remote_proxy(proxy: &openvpn::RemoteProxySettings) {
+ println!("proxy: remote");
+ println!(" server IP: {}", proxy.address.ip());
+ println!(" server port: {}", proxy.address.port());
+
+ if let Some(ref auth) = proxy.auth {
+ println!(" auth username: {}", auth.username);
+ println!(" auth password: {}", auth.password);
+ } else {
+ println!(" auth: none");
+ }
+ }
+
+ fn print_shadowsocks_proxy(proxy: &openvpn::ShadowsocksProxySettings) {
+ println!("proxy: Shadowsocks");
+ println!(" peer IP: {}", proxy.peer.ip());
+ println!(" peer port: {}", proxy.peer.port());
+ println!(" password: {}", proxy.password);
+ println!(" cipher: {}", proxy.cipher);
+ }
+
+ fn list_bridge_relays() -> Result<()> {
+ let mut rpc = new_rpc_client()?;
+ let mut locations = rpc.get_relay_locations()?;
+
+ locations.countries = locations
+ .countries
+ .into_iter()
+ .filter_map(|mut country| {
+ country.cities = country
+ .cities
+ .into_iter()
+ .filter_map(|mut city| {
+ city.relays.retain(|relay| !relay.bridges.is_empty());
+ if !city.relays.is_empty() {
+ Some(city)
+ } else {
+ None
+ }
+ })
+ .collect();
+ if !country.cities.is_empty() {
+ Some(country)
+ } else {
+ None
+ }
+ })
+ .collect();
+
+ for mut country in locations.countries {
+ country.cities.sort_by(|c1, c2| c1.name.cmp(&c2.name));
+ println!("{} ({})", country.name, country.code);
+ for city in &country.cities {
+ println!(
+ "\t{} ({}) @ {:.5}°N, {:.5}°W",
+ city.name, city.code, city.latitude, city.longitude
+ );
+ }
+ println!();
+ }
+ Ok(())
+ }
+}
diff --git a/mullvad-cli/src/cmds/mod.rs b/mullvad-cli/src/cmds/mod.rs
index 43e1968065..83bfd47883 100644
--- a/mullvad-cli/src/cmds/mod.rs
+++ b/mullvad-cli/src/cmds/mod.rs
@@ -7,6 +7,9 @@ pub use self::account::Account;
mod auto_connect;
pub use self::auto_connect::AutoConnect;
+mod bridge;
+pub use self::bridge::Bridge;
+
mod status;
pub use self::status::Status;
@@ -37,6 +40,7 @@ pub fn get_commands() -> HashMap<&'static str, Box<dyn Command>> {
Box::new(Account),
Box::new(AutoConnect),
Box::new(BlockWhenDisconnected),
+ Box::new(Bridge),
Box::new(Connect),
Box::new(Disconnect),
Box::new(Lan),
diff --git a/mullvad-cli/src/cmds/relay.rs b/mullvad-cli/src/cmds/relay.rs
index 5cc8f2815b..965107057d 100644
--- a/mullvad-cli/src/cmds/relay.rs
+++ b/mullvad-cli/src/cmds/relay.rs
@@ -1,4 +1,4 @@
-use crate::{new_rpc_client, Command, Error, Result};
+use crate::{location, new_rpc_client, Command, Error, Result};
use clap::{value_t, values_t};
use std::{
io::{self, BufRead},
@@ -8,8 +8,8 @@ use std::{
use mullvad_types::{
relay_constraints::{
- Constraint, LocationConstraint, OpenVpnConstraints, RelayConstraintsUpdate,
- RelaySettingsUpdate, TunnelConstraints, WireguardConstraints,
+ Constraint, OpenVpnConstraints, RelayConstraintsUpdate, RelaySettingsUpdate,
+ TunnelConstraints, WireguardConstraints,
},
ConnectionConfig, CustomTunnelEndpoint,
};
@@ -109,31 +109,9 @@ impl Command for Relay {
)
)
.subcommand(
- clap::SubCommand::with_name("location")
- .about(
- "Set country or city to select relays from. Use the 'list' \
- command to show available alternatives.",
- )
- .arg(
- clap::Arg::with_name("country")
- .help(
- "The two letter country code, or 'any' for no preference.",
- )
- .required(true)
- .index(1)
- .validator(country_code_validator),
- )
- .arg(
- clap::Arg::with_name("city")
- .help("The three letter city code")
- .index(2)
- .validator(city_code_validator),
- )
- .arg(
- clap::Arg::with_name("hostname")
- .help("The relay hostname")
- .index(3),
- ),
+ location::get_subcommand()
+ .about("Set country or city to select relays from. Use the 'list' \
+ command to show available alternatives.")
)
.subcommand(
clap::SubCommand::with_name("tunnel")
@@ -289,37 +267,7 @@ impl Relay {
}
fn set_location(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
- let country = matches.value_of("country").unwrap();
- let city = matches.value_of("city");
- let hostname = matches.value_of("hostname");
-
- let location_constraint = match (country, city, hostname) {
- ("any", None, None) => Constraint::Any,
- ("any", ..) => clap::Error::with_description(
- "City can't be given when selecting 'any' country",
- clap::ErrorKind::InvalidValue,
- )
- .exit(),
- (country, None, None) => {
- Constraint::Only(LocationConstraint::Country(country.to_owned()))
- }
- (country, Some(city), None) => Constraint::Only(LocationConstraint::City(
- country.to_owned(),
- city.to_owned(),
- )),
- (country, Some(city), Some(hostname)) => {
- Constraint::Only(LocationConstraint::Hostname(
- country.to_owned(),
- city.to_owned(),
- hostname.to_owned(),
- ))
- }
- (..) => clap::Error::with_description(
- "Invalid country, city and hostname combination given",
- clap::ErrorKind::InvalidValue,
- )
- .exit(),
- };
+ let location_constraint = location::get_constraint(matches);
self.update_constraints(RelaySettingsUpdate::Normal(RelayConstraintsUpdate {
location: Some(location_constraint),
@@ -409,19 +357,3 @@ fn parse_protocol_constraint(raw_protocol: &str) -> Constraint<TransportProtocol
_ => unreachable!(),
}
}
-
-fn country_code_validator(code: String) -> ::std::result::Result<(), String> {
- if code.len() == 2 || code == "any" {
- Ok(())
- } else {
- Err(String::from("Country codes must be two letters, or 'any'."))
- }
-}
-
-fn city_code_validator(code: String) -> ::std::result::Result<(), String> {
- if code.len() == 3 {
- Ok(())
- } else {
- Err(String::from("City codes must be three letters"))
- }
-}
diff --git a/mullvad-cli/src/cmds/tunnel.rs b/mullvad-cli/src/cmds/tunnel.rs
index c02a88d03a..136290d5bb 100644
--- a/mullvad-cli/src/cmds/tunnel.rs
+++ b/mullvad-cli/src/cmds/tunnel.rs
@@ -2,9 +2,6 @@ use crate::{new_rpc_client, Command, Result};
use clap::value_t;
use mullvad_types::settings::TunnelOptions;
-use talpid_types::net::openvpn::{self, SHADOWSOCKS_CIPHERS};
-
-use std::net::{IpAddr, SocketAddr};
pub struct Tunnel;
@@ -67,7 +64,6 @@ fn create_openvpn_subcommand() -> clap::App<'static, 'static> {
.about("Manage options for OpenVPN tunnels")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(create_openvpn_mssfix_subcommand())
- .subcommand(create_openvpn_proxy_subcommand())
}
fn create_openvpn_mssfix_subcommand() -> clap::App<'static, 'static> {
@@ -81,97 +77,6 @@ fn create_openvpn_mssfix_subcommand() -> clap::App<'static, 'static> {
)
}
-fn create_openvpn_proxy_subcommand() -> clap::App<'static, 'static> {
- clap::SubCommand::with_name("proxy")
- .about("Configure a SOCKS5 proxy")
- .setting(clap::AppSettings::SubcommandRequiredElseHelp)
- .subcommand(clap::SubCommand::with_name("get"))
- .subcommand(clap::SubCommand::with_name("unset"))
- .subcommand(
- clap::SubCommand::with_name("set")
- .setting(clap::AppSettings::SubcommandRequiredElseHelp)
- .subcommand(
- clap::SubCommand::with_name("local")
- .about("Registers a local SOCKS5 proxy")
- .arg(
- clap::Arg::with_name("local-port")
- .help("Specifies the port the local proxy server is listening on")
- .required(true)
- .index(1),
- )
- .arg(
- clap::Arg::with_name("remote-ip")
- .help("Specifies the IP of the proxy server peer")
- .required(true)
- .index(2),
- )
- .arg(
- clap::Arg::with_name("remote-port")
- .help("Specifies the port of the proxy server peer")
- .required(true)
- .index(3),
- ),
- )
- .subcommand(
- clap::SubCommand::with_name("remote")
- .about("Registers a remote SOCKS5 proxy")
- .arg(
- clap::Arg::with_name("remote-ip")
- .help("Specifies the IP of the remote proxy server")
- .required(true)
- .index(1),
- )
- .arg(
- clap::Arg::with_name("remote-port")
- .help("Specifies the port the remote proxy server is listening on")
- .required(true)
- .index(2),
- )
- .arg(
- clap::Arg::with_name("username")
- .help("Specifies the username for remote authentication")
- .required(true)
- .index(3),
- )
- .arg(
- clap::Arg::with_name("password")
- .help("Specifies the password for remote authentication")
- .required(true)
- .index(4),
- ),
- )
- .subcommand(
- clap::SubCommand::with_name("shadowsocks")
- .about("Configure bundled Shadowsocks proxy")
- .arg(
- clap::Arg::with_name("remote-ip")
- .help("Specifies the IP of the remote Shadowsocks server")
- .required(true)
- .index(1),
- )
- .arg(
- clap::Arg::with_name("remote-port")
- .help("Specifies the port of the remote Shadowsocks server")
- .default_value("443")
- .index(2),
- )
- .arg(
- clap::Arg::with_name("password")
- .help("Specifies the password on the remote Shadowsocks server")
- .default_value("23#dfsbbb")
- .index(3),
- )
- .arg(
- clap::Arg::with_name("cipher")
- .help("Specifies the cipher to use")
- .default_value("chacha20")
- .possible_values(SHADOWSOCKS_CIPHERS)
- .index(4),
- ),
- ),
- )
-}
-
fn create_ipv6_subcommand() -> clap::App<'static, 'static> {
clap::SubCommand::with_name("ipv6")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
@@ -190,7 +95,6 @@ impl Tunnel {
fn handle_openvpn_cmd(matches: &clap::ArgMatches<'_>) -> Result<()> {
match matches.subcommand() {
("mssfix", Some(mssfix_matches)) => Self::handle_openvpn_mssfix_cmd(mssfix_matches),
- ("proxy", Some(proxy_matches)) => Self::handle_openvpn_proxy_cmd(proxy_matches),
_ => unreachable!("unhandled command"),
}
}
@@ -204,15 +108,6 @@ impl Tunnel {
}
}
- fn handle_openvpn_proxy_cmd(matches: &clap::ArgMatches<'_>) -> Result<()> {
- match matches.subcommand() {
- ("get", Some(_)) => Self::process_openvpn_proxy_get(),
- ("unset", Some(_)) => Self::process_openvpn_proxy_unset(),
- ("set", Some(set_matches)) => Self::process_openvpn_proxy_set(set_matches),
- _ => unreachable!("unhandled command"),
- }
- }
-
fn handle_wireguard_cmd(matches: &clap::ArgMatches<'_>) -> Result<()> {
match matches.subcommand() {
("mtu", Some(matches)) => match matches.subcommand() {
@@ -323,141 +218,6 @@ impl Tunnel {
Ok(())
}
- fn process_openvpn_proxy_get() -> Result<()> {
- let tunnel_options = Self::get_tunnel_options()?;
- if let Some(proxy) = tunnel_options.openvpn.proxy {
- if let openvpn::ProxySettings::Local(local_proxy) = proxy {
- Self::print_local_proxy(&local_proxy)
- } else if let openvpn::ProxySettings::Remote(remote_proxy) = proxy {
- Self::print_remote_proxy(&remote_proxy)
- } else if let openvpn::ProxySettings::Shadowsocks(shadowsocks_proxy) = proxy {
- Self::print_shadowsocks_proxy(&shadowsocks_proxy)
- } else {
- unreachable!("unhandled proxy type");
- }
- } else {
- println!("proxy: unset");
- }
- Ok(())
- }
-
- fn print_local_proxy(proxy: &openvpn::LocalProxySettings) {
- println!("proxy: local");
- println!(" local port: {}", proxy.port);
- println!(" peer IP: {}", proxy.peer.ip());
- println!(" peer port: {}", proxy.peer.port());
- }
-
- fn print_remote_proxy(proxy: &openvpn::RemoteProxySettings) {
- println!("proxy: remote");
- println!(" server IP: {}", proxy.address.ip());
- println!(" server port: {}", proxy.address.port());
-
- if let Some(ref auth) = proxy.auth {
- println!(" auth username: {}", auth.username);
- println!(" auth password: {}", auth.password);
- } else {
- println!(" auth: none");
- }
- }
-
- fn print_shadowsocks_proxy(proxy: &openvpn::ShadowsocksProxySettings) {
- println!("proxy: Shadowsocks");
- println!(" peer IP: {}", proxy.peer.ip());
- println!(" peer port: {}", proxy.peer.port());
- println!(" password: {}", proxy.password);
- println!(" cipher: {}", proxy.cipher);
- }
-
- fn process_openvpn_proxy_unset() -> Result<()> {
- let mut rpc = new_rpc_client()?;
- rpc.set_openvpn_proxy(None)?;
- println!("proxy details have been unset");
- Ok(())
- }
-
- fn process_openvpn_proxy_set(matches: &clap::ArgMatches<'_>) -> Result<()> {
- if let Some(args) = matches.subcommand_matches("local") {
- let local_port =
- value_t!(args.value_of("local-port"), u16).unwrap_or_else(|e| e.exit());
- let remote_ip =
- value_t!(args.value_of("remote-ip"), IpAddr).unwrap_or_else(|e| e.exit());
- let remote_port =
- value_t!(args.value_of("remote-port"), u16).unwrap_or_else(|e| e.exit());
-
- let proxy = openvpn::LocalProxySettings {
- port: local_port,
- peer: SocketAddr::new(remote_ip, remote_port),
- };
-
- let packed_proxy = openvpn::ProxySettings::Local(proxy);
-
- if let Err(error) = openvpn::validate_proxy_settings(&packed_proxy) {
- panic!(error);
- }
-
- let mut rpc = new_rpc_client()?;
- rpc.set_openvpn_proxy(Some(packed_proxy))?;
- } else if let Some(args) = matches.subcommand_matches("remote") {
- let remote_ip =
- value_t!(args.value_of("remote-ip"), IpAddr).unwrap_or_else(|e| e.exit());
- let remote_port =
- value_t!(args.value_of("remote-port"), u16).unwrap_or_else(|e| e.exit());
- let username = args.value_of("username");
- let password = args.value_of("password");
-
- let auth = match (username, password) {
- (Some(username), Some(password)) => Some(openvpn::ProxyAuth {
- username: username.to_string(),
- password: password.to_string(),
- }),
- _ => None,
- };
-
- let proxy = openvpn::RemoteProxySettings {
- address: SocketAddr::new(remote_ip, remote_port),
- auth,
- };
-
- let packed_proxy = openvpn::ProxySettings::Remote(proxy);
-
- if let Err(error) = openvpn::validate_proxy_settings(&packed_proxy) {
- panic!(error);
- }
-
- let mut rpc = new_rpc_client()?;
- rpc.set_openvpn_proxy(Some(packed_proxy))?;
- } else if let Some(args) = matches.subcommand_matches("shadowsocks") {
- let remote_ip =
- value_t!(args.value_of("remote-ip"), IpAddr).unwrap_or_else(|e| e.exit());
- let remote_port =
- value_t!(args.value_of("remote-port"), u16).unwrap_or_else(|e| e.exit());
- let password = args.value_of("password").unwrap().to_string();
- let cipher = args.value_of("cipher").unwrap().to_string();
-
- let proxy = openvpn::ShadowsocksProxySettings {
- peer: SocketAddr::new(remote_ip, remote_port),
- password,
- cipher,
- };
-
- let packed_proxy = openvpn::ProxySettings::Shadowsocks(proxy);
-
- if let Err(error) = openvpn::validate_proxy_settings(&packed_proxy) {
- panic!(error);
- }
-
- let mut rpc = new_rpc_client()?;
- rpc.set_openvpn_proxy(Some(packed_proxy))?;
- } else {
- unreachable!("unhandled proxy type");
- }
-
- println!("proxy details have been updated");
- println!("note: The OpenVPN tunnel constraints have been updated to use TCP");
- Ok(())
- }
-
fn process_ipv6_get() -> Result<()> {
let tunnel_options = Self::get_tunnel_options()?;
println!(
diff --git a/mullvad-cli/src/location.rs b/mullvad-cli/src/location.rs
new file mode 100644
index 0000000000..10b27b61d8
--- /dev/null
+++ b/mullvad-cli/src/location.rs
@@ -0,0 +1,69 @@
+use mullvad_types::relay_constraints::{Constraint, LocationConstraint};
+
+pub fn get_subcommand() -> clap::App<'static, 'static> {
+ clap::SubCommand::with_name("location")
+ .arg(
+ clap::Arg::with_name("country")
+ .help("The two letter country code, or 'any' for no preference.")
+ .required(true)
+ .index(1)
+ .validator(country_code_validator),
+ )
+ .arg(
+ clap::Arg::with_name("city")
+ .help("The three letter city code")
+ .index(2)
+ .validator(city_code_validator),
+ )
+ .arg(
+ clap::Arg::with_name("hostname")
+ .help("The hostname")
+ .index(3),
+ )
+}
+
+pub fn get_constraint(matches: &clap::ArgMatches<'_>) -> Constraint<LocationConstraint> {
+ let country = matches.value_of("country").unwrap();
+ let city = matches.value_of("city");
+ let hostname = matches.value_of("hostname");
+
+ match (country, city, hostname) {
+ ("any", None, None) => Constraint::Any,
+ ("any", ..) => clap::Error::with_description(
+ "City can't be given when selecting 'any' country",
+ clap::ErrorKind::InvalidValue,
+ )
+ .exit(),
+ (country, None, None) => Constraint::Only(LocationConstraint::Country(country.to_owned())),
+ (country, Some(city), None) => Constraint::Only(LocationConstraint::City(
+ country.to_owned(),
+ city.to_owned(),
+ )),
+ (country, Some(city), Some(hostname)) => Constraint::Only(LocationConstraint::Hostname(
+ country.to_owned(),
+ city.to_owned(),
+ hostname.to_owned(),
+ )),
+ (..) => clap::Error::with_description(
+ "Invalid country, city and hostname combination given",
+ clap::ErrorKind::InvalidValue,
+ )
+ .exit(),
+ }
+}
+
+fn country_code_validator(code: String) -> ::std::result::Result<(), String> {
+ if code.len() == 2 || code == "any" {
+ Ok(())
+ } else {
+ Err(String::from("Country codes must be two letters, or 'any'."))
+ }
+}
+
+fn city_code_validator(code: String) -> ::std::result::Result<(), String> {
+ if code.len() == 3 {
+ Ok(())
+ } else {
+ Err(String::from("City codes must be three letters"))
+ }
+}
diff --git a/mullvad-cli/src/main.rs b/mullvad-cli/src/main.rs
index 3dc1879fb8..4abe16224c 100644
--- a/mullvad-cli/src/main.rs
+++ b/mullvad-cli/src/main.rs
@@ -14,6 +14,7 @@ use std::io;
use talpid_types::ErrorExt;
mod cmds;
+mod location;
pub const PRODUCT_VERSION: &str = include_str!(concat!(env!("OUT_DIR"), "/product-version.txt"));
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index 50b8dae23f..1d5851d94f 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -446,7 +446,8 @@ where
RelaySettings::CustomTunnelEndpoint(custom_relay) => {
self.last_generated_relay = None;
custom_relay
- .to_tunnel_parameters(self.settings.get_tunnel_options().clone())
+ // TODO(emilsp): generate proxy settings for custom tunnels
+ .to_tunnel_parameters(self.settings.get_tunnel_options().clone(), None)
.map_err(|e| {
e.display_chain_with_msg("Custom tunnel endpoint could not be resolved")
})
@@ -491,7 +492,7 @@ where
account_token: String,
retry_attempt: u32,
) -> Result<TunnelParameters> {
- let mut tunnel_options = self.settings.get_tunnel_options().clone();
+ let tunnel_options = self.settings.get_tunnel_options().clone();
let location = relay.location.as_ref().expect("Relay has no location set");
match endpoint {
MullvadEndpoint::OpenVpn(endpoint) => {
@@ -529,7 +530,6 @@ where
}
}
};
- tunnel_options.openvpn.proxy = proxy_settings;
Ok(openvpn::TunnelParameters {
config: openvpn::ConnectionConfig::new(
@@ -539,6 +539,7 @@ where
),
options: tunnel_options.openvpn,
generic_options: tunnel_options.generic,
+ proxy: proxy_settings,
}
.into())
}
@@ -620,7 +621,10 @@ where
}
SetAutoConnect(tx, auto_connect) => self.on_set_auto_connect(tx, auto_connect),
SetOpenVpnMssfix(tx, mssfix_arg) => self.on_set_openvpn_mssfix(tx, mssfix_arg),
- SetOpenVpnProxy(tx, proxy) => self.on_set_openvpn_proxy(tx, proxy),
+ SetBridgeSettings(tx, bridge_settings) => {
+ self.on_set_bridge_settings(tx, bridge_settings)
+ }
+ SetBridgeState(tx, bridge_state) => self.on_set_bridge_state(tx, bridge_state),
SetEnableIpv6(tx, enable_ipv6) => self.on_set_enable_ipv6(tx, enable_ipv6),
SetWireguardMtu(tx, mtu) => self.on_set_wireguard_mtu(tx, mtu),
GetSettings(tx) => self.on_get_settings(tx),
@@ -876,35 +880,62 @@ where
}
}
- fn on_set_openvpn_proxy(
+ fn on_set_bridge_settings(
&mut self,
tx: oneshot::Sender<::std::result::Result<(), settings::Error>>,
- proxy: Option<openvpn::ProxySettings>,
+ new_settings: BridgeSettings,
) {
- let constraints_result = match proxy {
- Some(_) => self.apply_proxy_constraints(),
- _ => Ok(false),
- };
- let proxy_result = self.settings.set_openvpn_proxy(proxy);
+ match self.settings.set_bridge_settings(new_settings) {
+ Ok(settings_changes) => {
+ if settings_changes {
+ self.event_listener.notify_settings(self.settings.clone());
+ self.reconnect_tunnel();
+ };
+ Self::oneshot_send(tx, Ok(()), "set_bridge_settings");
+ }
+
+ Err(e) => {
+ log::error!(
+ "{}",
+ e.display_chain_with_msg("Failed to set new bridge settings")
+ );
+ Self::oneshot_send(tx, Err(e), "set_bridge_settings");
+ }
+ }
+ }
+
+ fn on_set_bridge_state(
+ &mut self,
+ tx: oneshot::Sender<::std::result::Result<(), settings::Error>>,
+ bridge_state: BridgeState,
+ ) {
+ let result = match self.settings.set_bridge_state(bridge_state.clone()) {
+ Ok(settings_changed) => {
+ if settings_changed {
+ if bridge_state == BridgeState::On {
+ if let Err(e) = self.apply_proxy_constraints() {
+ log::error!(
+ "{}",
+ e.display_chain_with_msg("Failed to apply proxy constraints")
+ );
+ }
+ }
- match (proxy_result, constraints_result) {
- (Ok(proxy_changed), Ok(constraints_changed)) => {
- Self::oneshot_send(tx, Ok(()), "set_openvpn_proxy response");
- if proxy_changed || constraints_changed {
self.event_listener.notify_settings(self.settings.clone());
- info!("Initiating tunnel restart because the OpenVPN proxy setting changed");
+ log::info!("Initiating tunnel restart because bridge state changed");
self.reconnect_tunnel();
}
+ Ok(())
}
- (Ok(_), Err(error)) | (Err(error), Ok(_)) => {
- error!("{}", error.display_chain());
- Self::oneshot_send(tx, Err(error), "set_openvpn_proxy response");
- }
- (Err(error), Err(_)) => {
- error!("{}", error.display_chain());
- Self::oneshot_send(tx, Err(error), "set_openvpn_proxy response");
+ Err(error) => {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to set new bridge state")
+ );
+ Err(error)
}
- }
+ };
+ Self::oneshot_send(tx, result, "on_set_bridge_state response");
}
// Set the OpenVPN tunnel to use TCP.
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index 9d212abef8..7c195d74e2 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -15,7 +15,7 @@ use mullvad_rpc;
use mullvad_types::{
account::{AccountData, AccountToken},
location::GeoIpLocation,
- relay_constraints::RelaySettingsUpdate,
+ relay_constraints::{BridgeSettings, BridgeState, RelaySettingsUpdate},
relay_list::RelayList,
settings::{self, Settings},
states::TargetState,
@@ -27,11 +27,7 @@ use std::{
};
use talpid_core::mpsc::IntoSender;
use talpid_ipc;
-use talpid_types::{
- net::{openvpn, wireguard},
- tunnel::TunnelStateTransition,
- ErrorExt,
-};
+use talpid_types::{net::wireguard, tunnel::TunnelStateTransition, ErrorExt};
use uuid;
/// FIXME(linus): This is here just because the futures crate has deprecated it and jsonrpc_core
@@ -115,8 +111,12 @@ build_rpc_trait! {
fn set_openvpn_mssfix(&self, Self::Metadata, Option<u16>) -> BoxFuture<(), Error>;
/// Sets proxy details for OpenVPN
- #[rpc(meta, name = "set_openvpn_proxy")]
- fn set_openvpn_proxy(&self, Self::Metadata, Option<openvpn::ProxySettings>) -> BoxFuture<(), Error>;
+ #[rpc(meta, name = "set_bridge_settings")]
+ fn set_bridge_settings(&self, Self::Metadata, BridgeSettings) -> BoxFuture<(), Error>;
+
+ /// Sets bridge state
+ #[rpc(meta, name = "set_bridge_state")]
+ fn set_bridge_state(&self, Self::Metadata, BridgeState) -> BoxFuture<(), Error>;
/// Set if IPv6 is enabled in the tunnel
#[rpc(meta, name = "set_enable_ipv6")]
@@ -202,10 +202,9 @@ pub enum ManagementCommand {
/// Set the mssfix argument for OpenVPN
SetOpenVpnMssfix(OneshotSender<()>, Option<u16>),
/// Set proxy details for OpenVPN
- SetOpenVpnProxy(
- OneshotSender<Result<(), settings::Error>>,
- Option<openvpn::ProxySettings>,
- ),
+ SetBridgeSettings(OneshotSender<Result<(), settings::Error>>, BridgeSettings),
+ /// Set proxy state
+ SetBridgeState(OneshotSender<Result<(), settings::Error>>, BridgeState),
/// Set if IPv6 should be enabled in the tunnel
SetEnableIpv6(OneshotSender<()>, bool),
/// Set MTU for wireguard tunnels
@@ -546,15 +545,15 @@ impl<T: From<ManagementCommand> + 'static + Send> ManagementInterfaceApi
Box::new(future)
}
- fn set_openvpn_proxy(
+ fn set_bridge_settings(
&self,
_: Self::Metadata,
- proxy: Option<openvpn::ProxySettings>,
+ bridge_settings: BridgeSettings,
) -> BoxFuture<(), Error> {
- log::debug!("set_openvpn_proxy({:?})", proxy);
+ log::debug!("set_bridge_settings({:?})", bridge_settings);
let (tx, rx) = sync::oneshot::channel();
let future = self
- .send_command_to_daemon(ManagementCommand::SetOpenVpnProxy(tx, proxy))
+ .send_command_to_daemon(ManagementCommand::SetBridgeSettings(tx, bridge_settings))
.and_then(|_| rx.map_err(|_| Error::internal_error()))
.and_then(|settings_result| {
settings_result.map_err(|error| match error {
@@ -568,6 +567,21 @@ impl<T: From<ManagementCommand> + 'static + Send> ManagementInterfaceApi
Box::new(future)
}
+ fn set_bridge_state(
+ &self,
+ _: Self::Metadata,
+ bridge_state: BridgeState,
+ ) -> BoxFuture<(), Error> {
+ log::debug!("set_bridge_state({:?})", bridge_state);
+ let (tx, rx) = sync::oneshot::channel();
+ let future = self
+ .send_command_to_daemon(ManagementCommand::SetBridgeState(tx, bridge_state))
+ .and_then(|_| rx.map_err(|_| Error::internal_error()))
+ .and_then(|settings_result| settings_result.map_err(|_| Error::internal_error()));
+
+ Box::new(future)
+ }
+
fn set_enable_ipv6(&self, _: Self::Metadata, enable_ipv6: bool) -> BoxFuture<(), Error> {
log::debug!("set_enable_ipv6({})", enable_ipv6);
let (tx, rx) = sync::oneshot::channel();
diff --git a/mullvad-daemon/src/relays.rs b/mullvad-daemon/src/relays.rs
index 955d577994..b2a0b14387 100644
--- a/mullvad-daemon/src/relays.rs
+++ b/mullvad-daemon/src/relays.rs
@@ -284,6 +284,12 @@ impl RelaySelector {
if !self.should_use_bridge(retry_attempt) {
return None;
}
+
+ // For now, only TCP tunnels are supported.
+ if let &Constraint::Only(TransportProtocol::Udp) = &bridge_constraints.transport_protocol {
+ return None;
+ }
+
self.get_proxy_settings(bridge_constraints, location)
}
diff --git a/mullvad-ipc-client/src/lib.rs b/mullvad-ipc-client/src/lib.rs
index 1c7433a6f9..29f8985287 100644
--- a/mullvad-ipc-client/src/lib.rs
+++ b/mullvad-ipc-client/src/lib.rs
@@ -6,7 +6,7 @@ use jsonrpc_client_ipc::IpcTransport;
use mullvad_types::{
account::{AccountData, AccountToken},
location::GeoIpLocation,
- relay_constraints::{RelaySettings, RelaySettingsUpdate},
+ relay_constraints::{BridgeSettings, BridgeState, RelaySettings, RelaySettingsUpdate},
relay_list::RelayList,
settings::{Settings, TunnelOptions},
version::AppVersionInfo,
@@ -14,10 +14,7 @@ use mullvad_types::{
};
use serde::{Deserialize, Serialize};
use std::{io, path::Path, thread};
-use talpid_types::{
- net::{openvpn, wireguard},
- tunnel::TunnelStateTransition,
-};
+use talpid_types::{net::wireguard, tunnel::TunnelStateTransition};
static NO_ARGS: [u8; 0] = [];
@@ -194,8 +191,12 @@ impl DaemonRpcClient {
self.call("set_openvpn_mssfix", &[mssfix])
}
- pub fn set_openvpn_proxy(&mut self, proxy: Option<openvpn::ProxySettings>) -> Result<()> {
- self.call("set_openvpn_proxy", &[proxy])
+ pub fn set_bridge_settings(&mut self, settings: BridgeSettings) -> Result<()> {
+ self.call("set_bridge_settings", &[settings])
+ }
+
+ pub fn set_bridge_state(&mut self, state: BridgeState) -> Result<()> {
+ self.call("set_bridge_state", &[state])
}
pub fn shutdown(&mut self) -> Result<()> {
diff --git a/mullvad-types/src/custom_tunnel.rs b/mullvad-types/src/custom_tunnel.rs
index ac46b609a3..9559711314 100644
--- a/mullvad-types/src/custom_tunnel.rs
+++ b/mullvad-types/src/custom_tunnel.rs
@@ -31,6 +31,7 @@ impl CustomTunnelEndpoint {
pub fn to_tunnel_parameters(
&self,
tunnel_options: TunnelOptions,
+ proxy: Option<openvpn::ProxySettings>,
) -> Result<TunnelParameters, Error> {
let ip = resolve_to_ip(&self.host)?;
let mut config = self.config.clone();
@@ -41,6 +42,7 @@ impl CustomTunnelEndpoint {
config,
options: tunnel_options.openvpn.clone(),
generic_options: tunnel_options.generic.clone(),
+ proxy,
}
.into(),
ConnectionConfig::Wireguard(connection) => wireguard::TunnelParameters {
diff --git a/mullvad-types/src/relay_constraints.rs b/mullvad-types/src/relay_constraints.rs
index 47170adfef..cd901c6bbc 100644
--- a/mullvad-types/src/relay_constraints.rs
+++ b/mullvad-types/src/relay_constraints.rs
@@ -248,6 +248,15 @@ pub struct BridgeConstraints {
pub location: Constraint<LocationConstraint>,
}
+impl fmt::Display for BridgeConstraints {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
+ match self.location {
+ Constraint::Any => write!(f, "any location"),
+ Constraint::Only(ref location_constraint) => location_constraint.fmt(f),
+ }
+ }
+}
+
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum BridgeState {
@@ -256,6 +265,20 @@ pub enum BridgeState {
Off,
}
+impl fmt::Display for BridgeState {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "{}",
+ match self {
+ BridgeState::Auto => "auto",
+ BridgeState::On => "on",
+ BridgeState::Off => "off",
+ }
+ )
+ }
+}
+
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
pub struct InternalBridgeConstraints {
pub location: Constraint<LocationConstraint>,
diff --git a/mullvad-types/src/settings.rs b/mullvad-types/src/settings.rs
index 32047d31be..10e5b03298 100644
--- a/mullvad-types/src/settings.rs
+++ b/mullvad-types/src/settings.rs
@@ -207,19 +207,6 @@ impl Settings {
}
}
- pub fn set_openvpn_proxy(&mut self, proxy: Option<openvpn::ProxySettings>) -> Result<bool> {
- if let Some(ref settings) = proxy {
- openvpn::validate_proxy_settings(settings).map_err(Error::InvalidProxyData)?;
- }
-
- if self.tunnel_options.openvpn.proxy != proxy {
- self.tunnel_options.openvpn.proxy = proxy;
- self.save().map(|_| true)
- } else {
- Ok(false)
- }
- }
-
pub fn set_enable_ipv6(&mut self, enable_ipv6: bool) -> Result<bool> {
if self.tunnel_options.generic.enable_ipv6 != enable_ipv6 {
self.tunnel_options.generic.enable_ipv6 = enable_ipv6;
diff --git a/talpid-core/src/process/openvpn.rs b/talpid-core/src/process/openvpn.rs
index 50c0c61206..c3e7bfcf16 100644
--- a/talpid-core/src/process/openvpn.rs
+++ b/talpid-core/src/process/openvpn.rs
@@ -62,6 +62,7 @@ pub struct OpenVpnCommand {
plugin: Option<(PathBuf, Vec<String>)>,
log: Option<PathBuf>,
tunnel_options: net::openvpn::TunnelOptions,
+ proxy_settings: Option<net::openvpn::ProxySettings>,
tunnel_alias: Option<OsString>,
enable_ipv6: bool,
proxy_port: Option<u16>,
@@ -83,6 +84,7 @@ impl OpenVpnCommand {
plugin: None,
log: None,
tunnel_options: net::openvpn::TunnelOptions::default(),
+ proxy_settings: None,
tunnel_alias: None,
enable_ipv6: true,
proxy_port: None,
@@ -283,7 +285,7 @@ impl OpenVpnCommand {
fn proxy_arguments(&self) -> Vec<String> {
let mut args = vec![];
- match self.tunnel_options.proxy {
+ match self.proxy_settings {
Some(net::openvpn::ProxySettings::Local(ref local_proxy)) => {
args.push("--socks-proxy".to_owned());
args.push("127.0.0.1".to_owned());
diff --git a/talpid-core/src/tunnel/openvpn.rs b/talpid-core/src/tunnel/openvpn.rs
index 8186ab9683..f6174c5e7c 100644
--- a/talpid-core/src/tunnel/openvpn.rs
+++ b/talpid-core/src/tunnel/openvpn.rs
@@ -147,8 +147,8 @@ impl OpenVpnMonitor<OpenVpnCommand> {
Self::create_credentials_file(&params.config.username, &params.config.password)
.map_err(Error::CredentialsWriteError)?;
- let proxy_auth_file = Self::create_proxy_auth_file(&params.options.proxy)
- .map_err(Error::CredentialsWriteError)?;
+ let proxy_auth_file =
+ Self::create_proxy_auth_file(&params.proxy).map_err(Error::CredentialsWriteError)?;
let user_pass_file_path = user_pass_file.to_path_buf();
@@ -184,7 +184,7 @@ impl OpenVpnMonitor<OpenVpnCommand> {
log_dir,
};
- let proxy_monitor = Self::start_proxy(&params.options.proxy, &proxy_resources)?;
+ let proxy_monitor = Self::start_proxy(&params.proxy, &proxy_resources)?;
let cmd = Self::create_openvpn_cmd(
params,
diff --git a/talpid-core/src/tunnel_state_machine/connected_state.rs b/talpid-core/src/tunnel_state_machine/connected_state.rs
index 324d2cbbc8..bc1ca6d4af 100644
--- a/talpid-core/src/tunnel_state_machine/connected_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connected_state.rs
@@ -61,7 +61,7 @@ impl ConnectedState {
fn get_endpoint_from_params(&self) -> Endpoint {
match self.tunnel_parameters {
- TunnelParameters::OpenVpn(ref config) => match config.options.proxy {
+ TunnelParameters::OpenVpn(ref config) => match config.proxy {
Some(ref proxy_settings) => proxy_settings.get_endpoint(),
None => self.tunnel_parameters.get_tunnel_endpoint().endpoint,
},
diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs
index ddb591bad0..1f6afc16ad 100644
--- a/talpid-core/src/tunnel_state_machine/connecting_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs
@@ -286,7 +286,7 @@ fn get_openvpn_proxy_settings(
tunnel_parameters: &TunnelParameters,
) -> &Option<openvpn::ProxySettings> {
match tunnel_parameters {
- TunnelParameters::OpenVpn(ref config) => &config.options.proxy,
+ TunnelParameters::OpenVpn(ref config) => &config.proxy,
_ => &None,
}
}
diff --git a/talpid-types/src/net/openvpn.rs b/talpid-types/src/net/openvpn.rs
index 4eaa2cb218..a763b01b12 100644
--- a/talpid-types/src/net/openvpn.rs
+++ b/talpid-types/src/net/openvpn.rs
@@ -7,6 +7,7 @@ pub struct TunnelParameters {
pub config: ConnectionConfig,
pub options: TunnelOptions,
pub generic_options: GenericTunnelOptions,
+ pub proxy: Option<ProxySettings>,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
@@ -40,8 +41,6 @@ pub struct TunnelOptions {
/// Optional argument for openvpn to try and limit TCP packet size,
/// as discussed [here](https://openvpn.net/archive/openvpn-users/2003-11/msg00154.html)
pub mssfix: Option<u16>,
- /// Proxy settings, for when the relay connection should be via a proxy.
- pub proxy: Option<ProxySettings>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]