diff options
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | README.md | 6 | ||||
| -rwxr-xr-x | build.sh | 5 | ||||
| -rw-r--r-- | mullvad-rpc/Cargo.toml | 5 | ||||
| -rw-r--r-- | mullvad-rpc/src/address_cache.rs | 4 | ||||
| -rw-r--r-- | mullvad-rpc/src/lib.rs | 62 |
6 files changed, 73 insertions, 10 deletions
diff --git a/Cargo.lock b/Cargo.lock index 1f453bcfc9..fca01b8956 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1357,6 +1357,7 @@ dependencies = [ "hyper", "hyper-rustls", "ipnetwork", + "lazy_static", "log", "mullvad-types", "rand 0.7.3", @@ -455,6 +455,12 @@ echo "org.gradle.jvmargs=-Xmx4608M" >> ~/.gradle/gradle.properties interface UDS socket to users in the specified group. This means that only users in that group can use the CLI and GUI. By default, everyone has access to the socket. +#### Dev builds only + +* `MULLVAD_API_HOST` - Set the hostname to use in API requests. E.g. `api.mullvad.net`. + +* `MULLVAD_API_ADDRESS` - Set the IP address and port to use in API requests. E.g. `10.10.1.2:443`. + #### Setting environment variable - On Windows, one can use `setx` from an elevated shell, like so ```bat @@ -23,7 +23,10 @@ NPM_PACK_ARGS=() BUILD_MODE="release" while [[ "$#" -gt 0 ]]; do case $1 in - --dev-build) BUILD_MODE="dev" ;; + --dev-build) + BUILD_MODE="dev" + CARGO_ARGS+=(--features api-override) + ;; --target) TARGET=("$2") shift diff --git a/mullvad-rpc/Cargo.toml b/mullvad-rpc/Cargo.toml index b3111a4d45..7a6c970ec2 100644 --- a/mullvad-rpc/Cargo.toml +++ b/mullvad-rpc/Cargo.toml @@ -7,6 +7,10 @@ license = "GPL-3.0" edition = "2018" publish = false +[features] +# Allow the API server to use to be configured via MULLVAD_API_HOST and MULLVAD_API_ADDRESS. +api-override = [] + [dependencies] chrono = { version = "0.4", features = ["serde"] } err-derive = "0.3.0" @@ -24,6 +28,7 @@ tokio = { version = "1.8", features = [ "macros", "time", "rt-multi-thread", "ne tokio-rustls = "0.22" urlencoding = "1" webpki = { version = "0.21", features = [] } +lazy_static = "1.1.0" mullvad-types = { path = "../mullvad-types" } talpid-types = { path = "../talpid-types" } diff --git a/mullvad-rpc/src/address_cache.rs b/mullvad-rpc/src/address_cache.rs index 757d6645ed..b681265dc5 100644 --- a/mullvad-rpc/src/address_cache.rs +++ b/mullvad-rpc/src/address_cache.rs @@ -96,12 +96,12 @@ impl AddressCache { fn get_address_inner(inner: &AddressCacheInner) -> SocketAddr { if inner.addresses.is_empty() { - return API_ADDRESS.into(); + return *API_ADDRESS; } *inner .addresses .get(inner.choice % inner.addresses.len()) - .unwrap_or(&API_ADDRESS.into()) + .unwrap_or(&API_ADDRESS) } pub fn has_tried_current_address(&self) -> bool { diff --git a/mullvad-rpc/src/lib.rs b/mullvad-rpc/src/lib.rs index 883128f8aa..38f1499d02 100644 --- a/mullvad-rpc/src/lib.rs +++ b/mullvad-rpc/src/lib.rs @@ -46,10 +46,38 @@ pub const INVALID_ACCOUNT: &str = "INVALID_ACCOUNT"; /// Error code returned by the Mullvad API if the account token is missing or invalid. pub const INVALID_AUTH: &str = "INVALID_AUTH"; -const API_HOST: &str = "api.mullvad.net"; pub const API_IP_CACHE_FILENAME: &str = "api-ip-address.txt"; -const API_IP: IpAddr = IpAddr::V4(Ipv4Addr::new(193, 138, 218, 78)); -const API_ADDRESS: (IpAddr, u16) = (crate::API_IP, 443); +const API_HOST_DEFAULT: &str = "api.mullvad.net"; +const API_IP_DEFAULT: IpAddr = IpAddr::V4(Ipv4Addr::new(193, 138, 218, 78)); +const API_PORT_DEFAULT: u16 = 443; + +// Override the hostname and IP used to reach the API. +#[cfg(feature = "api-override")] +lazy_static::lazy_static! { + static ref API_HOST: String = std::env::var("MULLVAD_API_HOST") + .ok() + .map(|host| { + log::debug!("Overriding API hostname: {}", host); + host + }) + .unwrap_or(API_HOST_DEFAULT.to_string()); + static ref API_ADDRESS: SocketAddr = std::env::var("MULLVAD_API_ADDRESS") + .ok() + .and_then(|addr| { + let addr = addr.parse().ok(); + if let Some(addr) = &addr { + log::debug!("Overriding API address: {}", addr); + } + addr + }) + .unwrap_or(SocketAddr::new(API_IP_DEFAULT, API_PORT_DEFAULT)); + static ref DISABLE_ADDRESS_ROTATION: bool = std::env::var("MULLVAD_API_ADDRESS").ok().is_some(); +} +#[cfg(not(feature = "api-override"))] +lazy_static::lazy_static! { + static ref API_HOST: String = API_HOST_DEFAULT.to_string(); + static ref API_ADDRESS: SocketAddr = SocketAddr::new(API_IP_DEFAULT, API_PORT_DEFAULT); +} /// A type that helps with the creation of RPC connections. @@ -76,16 +104,27 @@ pub enum Error { impl MullvadRpcRuntime { /// Create a new `MullvadRpcRuntime`. pub fn new(handle: tokio::runtime::Handle) -> Result<Self, Error> { + Self::new_inner( + handle, + #[cfg(target_os = "android")] + None, + ) + } + + fn new_inner( + handle: tokio::runtime::Handle, + #[cfg(target_os = "android")] socket_bypass_tx: Option<mpsc::Sender<SocketBypassRequest>>, + ) -> Result<Self, Error> { Ok(MullvadRpcRuntime { handle, address_cache: AddressCache::new( - vec![API_ADDRESS.into()], + vec![API_ADDRESS.clone()], None, Arc::new(Box::new(|_| Ok(()))), )?, api_availability: ApiAvailability::new(availability::State::default()), #[cfg(target_os = "android")] - socket_bypass_tx: None, + socket_bypass_tx, }) } @@ -100,6 +139,15 @@ impl MullvadRpcRuntime { address_change_listener: impl Fn(SocketAddr) -> Result<(), ()> + Send + Sync + 'static, #[cfg(target_os = "android")] socket_bypass_tx: Option<mpsc::Sender<SocketBypassRequest>>, ) -> Result<Self, Error> { + #[cfg(feature = "api-override")] + if *DISABLE_ADDRESS_ROTATION { + return Self::new_inner( + handle, + #[cfg(target_os = "android")] + socket_bypass_tx, + ); + } + let cache_file = cache_dir.join(API_IP_CACHE_FILENAME); let write_file = if write_changes { Some(cache_file.clone().into_boxed_path()) @@ -177,9 +225,9 @@ impl MullvadRpcRuntime { /// Returns a request factory initialized to create requests for the master API pub fn mullvad_rest_handle(&mut self) -> rest::MullvadRestHandle { - let service = self.new_request_service(Some(API_HOST.to_owned())); + let service = self.new_request_service(Some(API_HOST.clone())); let factory = rest::RequestFactory::new( - API_HOST.to_owned(), + API_HOST.clone(), Box::new(self.address_cache.clone()), Some("app".to_owned()), ); |
