mirror of
https://github.com/yuezk/GlobalProtect-openconnect.git
synced 2025-04-02 18:31:50 -04:00
feat: add internal host detection support (#384)
This commit is contained in:
parent
6357a4087d
commit
26dbd8d312
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -889,6 +889,18 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
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]]
|
[[package]]
|
||||||
name = "document-features"
|
name = "document-features"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
@ -1424,6 +1436,7 @@ dependencies = [
|
|||||||
"base64 0.21.5",
|
"base64 0.21.5",
|
||||||
"chacha20poly1305",
|
"chacha20poly1305",
|
||||||
"clap",
|
"clap",
|
||||||
|
"dns-lookup",
|
||||||
"log",
|
"log",
|
||||||
"md5",
|
"md5",
|
||||||
"open",
|
"open",
|
||||||
|
@ -17,6 +17,7 @@ base64 = "0.21"
|
|||||||
clap = { version = "4.4.2", features = ["derive"] }
|
clap = { version = "4.4.2", features = ["derive"] }
|
||||||
ctrlc = "3.4"
|
ctrlc = "3.4"
|
||||||
directories = "5.0"
|
directories = "5.0"
|
||||||
|
dns-lookup = "2.0.4"
|
||||||
env_logger = "0.10"
|
env_logger = "0.10"
|
||||||
is_executable = "1.0"
|
is_executable = "1.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
@ -7,6 +7,7 @@ license = "MIT"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
base64.workspace = true
|
base64.workspace = true
|
||||||
|
dns-lookup.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
reqwest.workspace = true
|
reqwest.workspace = true
|
||||||
openssl.workspace = true
|
openssl.workspace = true
|
||||||
|
@ -2,9 +2,17 @@ use roxmltree::Document;
|
|||||||
|
|
||||||
use super::{Gateway, PriorityRule};
|
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 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
|
let gateways = list_gateway
|
||||||
.children()
|
.children()
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
|
use dns_lookup::lookup_addr;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use reqwest::{Client, StatusCode};
|
use reqwest::{Client, StatusCode};
|
||||||
use roxmltree::Document;
|
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 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");
|
info!("No gateways found in portal config");
|
||||||
vec![]
|
vec![]
|
||||||
});
|
});
|
||||||
|
@ -46,7 +46,26 @@
|
|||||||
<use-sso>yes</use-sso>
|
<use-sso>yes</use-sso>
|
||||||
<ip-address></ip-address>
|
<ip-address></ip-address>
|
||||||
<host></host>
|
<host></host>
|
||||||
|
<internal-host-detection>
|
||||||
|
<ip-address></ip-address>
|
||||||
|
<host></host>
|
||||||
|
<ipv6-address/>
|
||||||
|
<ipv6-host/>
|
||||||
|
</internal-host-detection>
|
||||||
<gateways>
|
<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>
|
<cutoff-time>5</cutoff-time>
|
||||||
<external>
|
<external>
|
||||||
<list>
|
<list>
|
||||||
@ -63,6 +82,19 @@
|
|||||||
</external>
|
</external>
|
||||||
</gateways>
|
</gateways>
|
||||||
<gateways-v6>
|
<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>
|
<cutoff-time>5</cutoff-time>
|
||||||
<external>
|
<external>
|
||||||
<list>
|
<list>
|
||||||
|
Loading…
Reference in New Issue
Block a user