feat: add internal host detection support (#384)

This commit is contained in:
Ruben Rodriguez 2024-07-02 15:30:34 +02:00 committed by GitHub
parent 6357a4087d
commit 26dbd8d312
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 90 additions and 3 deletions

13
Cargo.lock generated
View File

@ -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",

View File

@ -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"

View File

@ -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

View File

@ -2,9 +2,17 @@ use roxmltree::Document;
use super::{Gateway, PriorityRule};
pub(crate) fn parse_gateways(doc: &Document) -> Option<Vec<Gateway>> {
pub(crate) fn parse_gateways(doc: &Document, external: bool) -> Option<Vec<Gateway>> {
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()

View File

@ -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::<std::net::IpAddr>() {
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![]
});

View File

@ -46,7 +46,26 @@
<use-sso>yes</use-sso>
<ip-address></ip-address>
<host></host>
<internal-host-detection>
<ip-address></ip-address>
<host></host>
<ipv6-address/>
<ipv6-host/>
</internal-host-detection>
<gateways>
<internal>
<list>
<entry name="xxx.xxx.xxx.xxx">
<priority-rule>
<entry name="Any">
<priority>1</priority>
</entry>
</priority-rule>
<priority>1</priority>
<description>vpn_gateway</description>
</entry>
</list>
</internal>
<cutoff-time>5</cutoff-time>
<external>
<list>
@ -63,6 +82,19 @@
</external>
</gateways>
<gateways-v6>
<internal>
<list>
<entry name="vpn_gateway">
<ipv4>xxx.xxx.xxx.xxx</ipv4>
<priority-rule>
<entry name="Any">
<priority>1</priority>
</entry>
</priority-rule>
<priority>1</priority>
</entry>
</list>
</internal>
<cutoff-time>5</cutoff-time>
<external>
<list>