diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2019-03-25 11:19:27 +0100 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2019-03-26 12:36:31 +0100 |
| commit | 4b2841c9dfc75a513f99cd9695fc27977699cc91 (patch) | |
| tree | 1cbda717667c2d569ebfea2bfb14f39e210131c2 | |
| parent | 0d95132e5ab6eb072ede73e901d783eaef12cad1 (diff) | |
| download | mullvadvpn-4b2841c9dfc75a513f99cd9695fc27977699cc91.tar.xz mullvadvpn-4b2841c9dfc75a513f99cd9695fc27977699cc91.zip | |
Send two GeoIP lookups, one over each IPv
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/status.rs | 14 | ||||
| -rw-r--r-- | mullvad-daemon/src/geoip.rs | 35 | ||||
| -rw-r--r-- | mullvad-daemon/src/lib.rs | 6 | ||||
| -rw-r--r-- | mullvad-rpc/Cargo.toml | 1 | ||||
| -rw-r--r-- | mullvad-rpc/src/lib.rs | 9 | ||||
| -rw-r--r-- | mullvad-types/src/location.rs | 37 |
7 files changed, 83 insertions, 20 deletions
diff --git a/Cargo.lock b/Cargo.lock index b2b0bae84d..9478ab7cea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1196,7 +1196,6 @@ dependencies = [ "hyper-openssl 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-client-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-client-http 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mullvad-types 0.1.0", "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/mullvad-cli/src/cmds/status.rs b/mullvad-cli/src/cmds/status.rs index b1fb696b7f..29ce0d2c6d 100644 --- a/mullvad-cli/src/cmds/status.rs +++ b/mullvad-cli/src/cmds/status.rs @@ -78,14 +78,20 @@ fn print_location(rpc: &mut DaemonRpcClient) -> Result<()> { return Ok(()); } }; + if let Some(hostname) = location.hostname { + println!("Relay: {}", hostname); + } + if let Some(ipv4) = location.ipv4 { + println!("IPv4: {}", ipv4); + } + if let Some(ipv6) = location.ipv6 { + println!("IPv6: {}", ipv6); + } let city_and_country = if let Some(city) = location.city { format!("{}, {}", city, location.country) } else { - format!("{}", location.country) + location.country.clone() }; - if let Some(hostname) = location.hostname { - println!("Relay: {}", hostname); - } println!("Location: {}", city_and_country); println!( "Position: {:.5}°N, {:.5}°W", diff --git a/mullvad-daemon/src/geoip.rs b/mullvad-daemon/src/geoip.rs index 2faed344a6..ffd805739b 100644 --- a/mullvad-daemon/src/geoip.rs +++ b/mullvad-daemon/src/geoip.rs @@ -1,10 +1,11 @@ use futures::{self, Future}; use mullvad_rpc; -use mullvad_types::location::GeoIpLocation; +use mullvad_types::location::{AmIMullvad, GeoIpLocation}; use serde_json; -const URI: &str = "https://am.i.mullvad.net/json"; +const URI_V4: &str = "https://ipv4.am.i.mullvad.net/json"; +const URI_V6: &str = "https://ipv6.am.i.mullvad.net/json"; error_chain! { errors { @@ -22,8 +23,36 @@ error_chain! { pub fn send_location_request( request_sender: mullvad_rpc::rest::RequestSender, ) -> impl Future<Item = GeoIpLocation, Error = Error> { + let v4_future = + send_location_request_internal(URI_V4, request_sender.clone()).map(GeoIpLocation::from); + let v6_future = send_location_request_internal(URI_V6, request_sender).map(GeoIpLocation::from); + + v4_future.then(|v4_result| { + v6_future.then(|v6_result| match (v4_result, v6_result) { + (Ok(mut v4), Ok(v6)) => { + v4.ipv6 = v6.ipv6; + v4.mullvad_exit_ip = v4.mullvad_exit_ip && v6.mullvad_exit_ip; + Ok(v4) + } + (Ok(v4), Err(e)) => { + log::debug!("Unable to fetch IPv6 GeoIP location: {}", e); + Ok(v4) + } + (Err(e), Ok(v6)) => { + log::debug!("Unable to fetch IPv4 GeoIP location: {}", e); + Ok(v6) + } + (Err(e_v4), Err(_)) => Err(e_v4), + }) + }) +} + +fn send_location_request_internal( + uri: &'static str, + request_sender: mullvad_rpc::rest::RequestSender, +) -> impl Future<Item = AmIMullvad, Error = Error> { let (response_tx, response_rx) = futures::sync::oneshot::channel(); - let request = mullvad_rpc::rest::create_get_request(URI.parse().unwrap()); + let request = mullvad_rpc::rest::create_get_request(uri.parse().unwrap()); futures::Sink::send(request_sender, (request, response_tx)) .map_err(|e| Error::with_chain(e, ErrorKind::NoResponse)) diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index bc7e32dcbc..7a4e4b9943 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -512,7 +512,8 @@ impl Daemon { Some(location_from_relay) => Box::new( self.get_geo_location() .map(|fetched_location| GeoIpLocation { - ip: fetched_location.ip, + ipv4: fetched_location.ipv4, + ipv6: fetched_location.ipv6, ..location_from_relay }) .map(Some), @@ -545,7 +546,8 @@ impl Daemon { let hostname = relay.hostname.clone(); Some(GeoIpLocation { - ip: None, + ipv4: None, + ipv6: None, country: location.country, city: Some(location.city), latitude: location.latitude, diff --git a/mullvad-rpc/Cargo.toml b/mullvad-rpc/Cargo.toml index 2f21283c58..a2449842a7 100644 --- a/mullvad-rpc/Cargo.toml +++ b/mullvad-rpc/Cargo.toml @@ -12,7 +12,6 @@ error-chain = "0.12" futures = "0.1.15" jsonrpc-client-core = "0.5" jsonrpc-client-http = "0.5" -lazy_static = "1.0" serde_json = "1.0" tokio-core = "0.1" hyper = "0.11" diff --git a/mullvad-rpc/src/lib.rs b/mullvad-rpc/src/lib.rs index 58fa07440f..6d32d0dea0 100644 --- a/mullvad-rpc/src/lib.rs +++ b/mullvad-rpc/src/lib.rs @@ -13,7 +13,6 @@ extern crate error_chain; use chrono::{offset::Utc, DateTime}; use jsonrpc_client_core::{expand_params, jsonrpc_client}; use jsonrpc_client_http::{header::Host, HttpTransport, HttpTransportBuilder}; -use lazy_static::lazy_static; use mullvad_types::{account::AccountToken, relay_list::RelayList, version}; use std::{ collections::HashMap, @@ -43,9 +42,7 @@ const DNS_THREADS: usize = 2; const API_HOST: &str = "api.mullvad.net"; const RPC_TIMEOUT: Duration = Duration::from_secs(10); pub const API_IP_CACHE_FILENAME: &str = "api-ip-address.txt"; -lazy_static! { - static ref API_IP: IpAddr = IpAddr::V4(Ipv4Addr::new(193, 138, 218, 73)); -} +const API_IP: IpAddr = IpAddr::V4(Ipv4Addr::new(193, 138, 218, 73)); /// A type that helps with the creation of RPC connections. @@ -58,7 +55,7 @@ impl MullvadRpcFactory { /// Create a new `MullvadRpcFactory`. pub fn new<P: Into<PathBuf>>(ca_path: P) -> Self { MullvadRpcFactory { - cached_dns_resolver: CachedDnsResolver::new(API_HOST.to_owned(), None, *API_IP), + cached_dns_resolver: CachedDnsResolver::new(API_HOST.to_owned(), None, API_IP), ca_path: ca_path.into(), } } @@ -67,7 +64,7 @@ impl MullvadRpcFactory { pub fn with_cache_dir<P: Into<PathBuf>>(cache_dir: &Path, ca_path: P) -> Self { let cache_file = cache_dir.join(API_IP_CACHE_FILENAME); let cached_dns_resolver = - CachedDnsResolver::new(API_HOST.to_owned(), Some(cache_file), *API_IP); + CachedDnsResolver::new(API_HOST.to_owned(), Some(cache_file), API_IP); MullvadRpcFactory { cached_dns_resolver, diff --git a/mullvad-types/src/location.rs b/mullvad-types/src/location.rs index 7f326ead42..1c59c0d416 100644 --- a/mullvad-types/src/location.rs +++ b/mullvad-types/src/location.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use std::net::IpAddr; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; pub type CountryCode = String; pub type CityCode = String; @@ -15,14 +15,45 @@ pub struct Location { pub longitude: f64, } +/// The response from the am.i.mullvad.net location service. +#[derive(Debug, Deserialize)] +pub struct AmIMullvad { + pub ip: IpAddr, + pub country: String, + pub city: Option<String>, + pub latitude: f64, + pub longitude: f64, + pub mullvad_exit_ip: bool, +} + +/// GeoIP information exposed from the daemon to frontends. #[derive(Debug, Serialize, Deserialize)] pub struct GeoIpLocation { - pub ip: Option<IpAddr>, + pub ipv4: Option<Ipv4Addr>, + pub ipv6: Option<Ipv6Addr>, pub country: String, pub city: Option<String>, pub latitude: f64, pub longitude: f64, pub mullvad_exit_ip: bool, - #[serde(default)] pub hostname: Option<String>, } + +impl From<AmIMullvad> for GeoIpLocation { + fn from(location: AmIMullvad) -> GeoIpLocation { + let (ipv4, ipv6) = match location.ip { + IpAddr::V4(v4) => (Some(v4), None), + IpAddr::V6(v6) => (None, Some(v6)), + }; + GeoIpLocation { + ipv4, + ipv6, + country: location.country, + city: location.city, + latitude: location.latitude, + longitude: location.longitude, + mullvad_exit_ip: location.mullvad_exit_ip, + hostname: None, + } + } +} |
