diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2019-03-26 14:02:12 +0100 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2019-03-26 14:02:12 +0100 |
| commit | 893b279542915e5e2332686141382146b8aa7efe (patch) | |
| tree | c987fa46f4e0e61667d963aaee8f2dc16e4e3302 | |
| parent | 0d95132e5ab6eb072ede73e901d783eaef12cad1 (diff) | |
| parent | 492e60e9c4907e3574ef6137a68215d5303012d7 (diff) | |
| download | mullvadvpn-893b279542915e5e2332686141382146b8aa7efe.tar.xz mullvadvpn-893b279542915e5e2332686141382146b8aa7efe.zip | |
Merge branch 'fetch-both-ipv-exit-addrs'
| -rw-r--r-- | CHANGELOG.md | 3 | ||||
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | gui/src/main/daemon-rpc.ts | 3 | ||||
| -rw-r--r-- | gui/src/renderer/components/Connect.tsx | 3 | ||||
| -rw-r--r-- | gui/src/renderer/redux/connection/reducers.ts | 6 | ||||
| -rw-r--r-- | gui/src/shared/daemon-rpc-types.ts | 3 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/status.rs | 19 | ||||
| -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 |
12 files changed, 99 insertions, 27 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 9627586f20..e7967b0e16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ Line wrap the file at 100 chars. Th ## [Unreleased] +### Added +- When IPv6 is enabled, get both exit IP versions from am.i.mullvad.net and show in UI. + ### Removed - Remove the Mullvad OpenVPN intermediate transition CA. Used when transitioning from the old to the new root CA. Now the app only bundles and trust the new Mullvad root CA valid until 2028. 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/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts index f3e4d5a144..94cbeeb984 100644 --- a/gui/src/main/daemon-rpc.ts +++ b/gui/src/main/daemon-rpc.ts @@ -31,7 +31,8 @@ import { const locationSchema = maybe( partialObject({ - ip: maybe(string), + ipv4: maybe(string), + ipv6: maybe(string), country: string, city: maybe(string), latitude: number, diff --git a/gui/src/renderer/components/Connect.tsx b/gui/src/renderer/components/Connect.tsx index 6d10400a30..dea950b3f1 100644 --- a/gui/src/renderer/components/Connect.tsx +++ b/gui/src/renderer/components/Connect.tsx @@ -151,7 +151,8 @@ export default class Connect extends Component<IProps, IState> { const status = this.props.connection.status; const relayOutAddress: IRelayOutAddress = { - ipv4: this.props.connection.ip, + ipv4: this.props.connection.ipv4, + ipv6: this.props.connection.ipv6, }; const relayInAddress: IRelayInAddress | undefined = (status.state === 'connecting' || status.state === 'connected') && status.details diff --git a/gui/src/renderer/redux/connection/reducers.ts b/gui/src/renderer/redux/connection/reducers.ts index a0918f53ee..5175b6c5ec 100644 --- a/gui/src/renderer/redux/connection/reducers.ts +++ b/gui/src/renderer/redux/connection/reducers.ts @@ -4,7 +4,8 @@ import { ReduxAction } from '../store'; export interface IConnectionReduxState { status: TunnelStateTransition; isBlocked: boolean; - ip?: Ip; + ipv4?: Ip; + ipv6?: Ip; hostname?: string; latitude?: number; longitude?: number; @@ -15,7 +16,8 @@ export interface IConnectionReduxState { const initialState: IConnectionReduxState = { status: { state: 'disconnected' }, isBlocked: false, - ip: undefined, + ipv4: undefined, + ipv6: undefined, hostname: undefined, latitude: undefined, longitude: undefined, diff --git a/gui/src/shared/daemon-rpc-types.ts b/gui/src/shared/daemon-rpc-types.ts index 4582a66549..7908c4f67e 100644 --- a/gui/src/shared/daemon-rpc-types.ts +++ b/gui/src/shared/daemon-rpc-types.ts @@ -4,7 +4,8 @@ export interface IAccountData { export type AccountToken = string; export type Ip = string; export interface ILocation { - ip?: string; + ipv4?: string; + ipv6?: string; country: string; city?: string; latitude: number; diff --git a/mullvad-cli/src/cmds/status.rs b/mullvad-cli/src/cmds/status.rs index b1fb696b7f..f39d9cef68 100644 --- a/mullvad-cli/src/cmds/status.rs +++ b/mullvad-cli/src/cmds/status.rs @@ -78,15 +78,22 @@ fn print_location(rpc: &mut DaemonRpcClient) -> Result<()> { return Ok(()); } }; - let city_and_country = if let Some(city) = location.city { - format!("{}, {}", city, location.country) - } else { - format!("{}", location.country) - }; if let Some(hostname) = location.hostname { println!("Relay: {}", hostname); } - println!("Location: {}", city_and_country); + if let Some(ipv4) = location.ipv4 { + println!("IPv4: {}", ipv4); + } + if let Some(ipv6) = location.ipv6 { + println!("IPv6: {}", ipv6); + } + + print!("Location: "); + if let Some(city) = location.city { + print!("{}, ", city); + } + println!("{}", location.country); + println!( "Position: {:.5}°N, {:.5}°W", location.latitude, location.longitude 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, + } + } +} |
