mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-09 04:30:20 +08:00
feat(http): expose narrow benchmarking fake-ip predicate
This commit is contained in:
@@ -89,6 +89,24 @@ pub fn is_private_or_reserved_ip(ip: IpAddr) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return whether an address belongs to RFC 2544's IPv4 benchmarking range.
|
||||
///
|
||||
/// Local DNS interception tools (for example, Surge in Fake-IP mode) commonly
|
||||
/// synthesize answers from `198.18.0.0/15`. The range is intentionally still
|
||||
/// classified as reserved by [`is_private_or_reserved_ip`]; callers may use
|
||||
/// this predicate only when they have independently established that the
|
||||
/// hostname is a trusted, fixed destination. Keeping the predicates separate
|
||||
/// prevents a compatibility exception from weakening the generic SSRF guard.
|
||||
pub fn is_ipv4_benchmarking_fake_ip(ip: IpAddr) -> bool {
|
||||
match ip {
|
||||
IpAddr::V4(ip) => {
|
||||
let octets = ip.octets();
|
||||
octets[0] == 198 && (18..=19).contains(&octets[1])
|
||||
}
|
||||
IpAddr::V6(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return true only when a URL names loopback without relying on DNS.
|
||||
///
|
||||
/// This is intentionally stricter than accepting names that currently resolve
|
||||
@@ -110,8 +128,8 @@ pub fn is_https_or_loopback_http_url(url: &Url) -> bool {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
connection_declared_header_names, is_https_or_loopback_http_url, is_private_or_reserved_ip,
|
||||
url_has_literal_loopback_host,
|
||||
connection_declared_header_names, is_https_or_loopback_http_url,
|
||||
is_ipv4_benchmarking_fake_ip, is_private_or_reserved_ip, url_has_literal_loopback_host,
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -151,6 +169,19 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn benchmarking_fake_ip_predicate_is_narrow_and_does_not_change_private_policy() {
|
||||
for address in ["198.18.0.1", "198.19.255.254"] {
|
||||
let ip = address.parse().expect("benchmarking address");
|
||||
assert!(is_ipv4_benchmarking_fake_ip(ip));
|
||||
assert!(is_private_or_reserved_ip(ip));
|
||||
}
|
||||
for address in ["198.17.255.254", "198.20.0.1", "2001:db8::1"] {
|
||||
let ip = address.parse().expect("non-benchmarking address");
|
||||
assert!(!is_ipv4_benchmarking_fake_ip(ip));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sensitive_http_transport_allows_https_or_literal_loopback_only() {
|
||||
for allowed in [
|
||||
|
||||
@@ -9,8 +9,8 @@ pub use client::{apply_http_client_config, build_http_client, build_http_client_
|
||||
pub use config::{HttpClientConfig, HttpRetryConfig};
|
||||
pub use dns::{lookup_host_with_limits, DEFAULT_DNS_LOOKUP_TIMEOUT, MAX_DNS_RESOLVED_ADDRESSES};
|
||||
pub use header_security::{
|
||||
connection_declared_header_names, is_https_or_loopback_http_url, is_private_or_reserved_ip,
|
||||
url_has_literal_loopback_host,
|
||||
connection_declared_header_names, is_https_or_loopback_http_url, is_ipv4_benchmarking_fake_ip,
|
||||
is_private_or_reserved_ip, url_has_literal_loopback_host,
|
||||
};
|
||||
pub use response_body::{read_response_bytes_with_limit, ResponseBodyReadError};
|
||||
pub use retry::jittered_delay_for_retry;
|
||||
|
||||
Reference in New Issue
Block a user