use std::net::IpAddr;
pub fn is_private_ip(ip: IpAddr) -> bool {
match ip {
IpAddr::V4(ipv4) => {
ipv4.is_private()
|| ipv4.is_loopback()
|| ipv4.is_link_local()
|| ipv4.is_broadcast()
|| ipv4.is_multicast()
|| ipv4.is_unspecified()
|| (ipv4.octets()[0] == 169 && ipv4.octets()[1] == 254) }
IpAddr::V6(ipv6) => {
ipv6.is_loopback()
|| ipv6.is_multicast()
|| ipv6.is_unspecified()
|| ipv6.segments()[0] & 0xfe00 == 0xfc00 || ipv6.segments()[0] & 0xffc0 == 0xfe80 }
}
}
pub fn is_aws_metadata(host: &str) -> bool {
host == "169.254.169.254" || host == "fd00:ec2::254"
}
#[cfg(test)]
mod tests {
use super::*;
use std::net::Ipv4Addr;
#[test]
fn private_ipv4_blocked() {
assert!(is_private_ip(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1))));
assert!(is_private_ip(IpAddr::V4(Ipv4Addr::new(172, 16, 0, 1))));
assert!(is_private_ip(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1))));
assert!(is_private_ip(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))));
assert!(is_private_ip(IpAddr::V4(Ipv4Addr::new(169, 254, 1, 1))));
}
#[test]
fn public_ipv4_allowed() {
assert!(!is_private_ip(IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8))));
assert!(!is_private_ip(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1))));
}
#[test]
fn aws_metadata_blocked() {
assert!(is_aws_metadata("169.254.169.254"));
assert!(is_aws_metadata("fd00:ec2::254"));
assert!(!is_aws_metadata("8.8.8.8"));
}
}