diff --git a/Cargo.lock b/Cargo.lock index 5af2cd1..55d89f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -889,6 +889,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "dns-lookup" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5766087c2235fec47fafa4cfecc81e494ee679d0fd4a59887ea0919bfb0e4fc" +dependencies = [ + "cfg-if", + "libc", + "socket2", + "windows-sys 0.48.0", +] + [[package]] name = "document-features" version = "0.2.8" @@ -1424,6 +1436,7 @@ dependencies = [ "base64 0.21.5", "chacha20poly1305", "clap", + "dns-lookup", "log", "md5", "open", diff --git a/Cargo.toml b/Cargo.toml index 04852b7..052875e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ base64 = "0.21" clap = { version = "4.4.2", features = ["derive"] } ctrlc = "3.4" directories = "5.0" +dns-lookup = "2.0.4" env_logger = "0.10" is_executable = "1.0" log = "0.4" diff --git a/crates/gpapi/Cargo.toml b/crates/gpapi/Cargo.toml index 35e7187..8b2994d 100644 --- a/crates/gpapi/Cargo.toml +++ b/crates/gpapi/Cargo.toml @@ -7,6 +7,7 @@ license = "MIT" [dependencies] anyhow.workspace = true base64.workspace = true +dns-lookup.workspace = true log.workspace = true reqwest.workspace = true openssl.workspace = true diff --git a/crates/gpapi/src/gateway/parse_gateways.rs b/crates/gpapi/src/gateway/parse_gateways.rs index 70cc6ea..2ce2675 100644 --- a/crates/gpapi/src/gateway/parse_gateways.rs +++ b/crates/gpapi/src/gateway/parse_gateways.rs @@ -2,9 +2,17 @@ use roxmltree::Document; use super::{Gateway, PriorityRule}; -pub(crate) fn parse_gateways(doc: &Document) -> Option> { +pub(crate) fn parse_gateways(doc: &Document, external: bool) -> Option> { let node_gateways = doc.descendants().find(|n| n.has_tag_name("gateways"))?; - let list_gateway = node_gateways.descendants().find(|n| n.has_tag_name("list"))?; + + // if external flag is set, look for external gateways, otherwise look for internal gateways + let kind_gateways = if external { + node_gateways.descendants().find(|n| n.has_tag_name("external"))? + } else { + node_gateways.descendants().find(|n| n.has_tag_name("internal"))? + }; + + let list_gateway = kind_gateways.descendants().find(|n| n.has_tag_name("list"))?; let gateways = list_gateway .children() diff --git a/crates/gpapi/src/portal/config.rs b/crates/gpapi/src/portal/config.rs index bd89f86..94d6b08 100644 --- a/crates/gpapi/src/portal/config.rs +++ b/crates/gpapi/src/portal/config.rs @@ -1,4 +1,5 @@ use anyhow::bail; +use dns_lookup::lookup_addr; use log::{info, warn}; use reqwest::{Client, StatusCode}; use roxmltree::Document; @@ -125,7 +126,38 @@ pub async fn retrieve_config(portal: &str, cred: &Credential, gp_params: &GpPara let doc = Document::parse(&res_xml).map_err(|e| PortalError::ConfigError(e.to_string()))?; - let mut gateways = parse_gateways(&doc).unwrap_or_else(|| { + let mut external_gateway = true; + + // Perform DNS lookup, set flag to internal or external, and pass it to parse_gateways + if let Some(_) = xml::get_child_text(&doc, "internal-host-detection") { + let ip_info = [ + (xml::get_child_text(&doc, "ip-address"), xml::get_child_text(&doc, "host")), + (xml::get_child_text(&doc, "ipv6-address"), xml::get_child_text(&doc, "ipv6-host")), + ]; + + info!("internal-host-detection returned, performing DNS lookup"); + + for (ip_address, host) in ip_info.iter() { + if let (Some(ip_address), Some(host)) = (ip_address.as_deref(), host.as_deref()) { + if !ip_address.is_empty() && !host.is_empty() { + match ip_address.parse::() { + Ok(ip) => match lookup_addr(&ip) { + Ok(host_lookup) if host_lookup == *host => { + external_gateway = false; + break; + } + Ok(_) => (), + Err(err) => warn!("DNS lookup failed for {}: {}", ip_address, err), + }, + Err(err) => warn!("Invalid IP address {}: {}", ip_address, err), + } + } + } + } + } + + + let mut gateways = parse_gateways(&doc, external_gateway).unwrap_or_else(|| { info!("No gateways found in portal config"); vec![] }); diff --git a/crates/gpapi/tests/files/portal_config.xml b/crates/gpapi/tests/files/portal_config.xml index 0aab3ca..2804af1 100644 --- a/crates/gpapi/tests/files/portal_config.xml +++ b/crates/gpapi/tests/files/portal_config.xml @@ -46,7 +46,26 @@ yes + + + + + + + + + + + + 1 + + + 1 + vpn_gateway + + + 5 @@ -63,6 +82,19 @@ + + + + xxx.xxx.xxx.xxx + + + 1 + + + 1 + + + 5