use log::warn;
use tokio_util::sync::CancellationToken;
pub async fn get_public_ipv4(force_local_network: bool) -> anyhow::Result<String> {
match force_local_network {
true => Ok("127.0.0.1".to_string()),
false => {
let client = reqwest::ClientBuilder::new().danger_accept_invalid_certs(true).build()?; let response = client.get("https://api4.ipify.org").send().await?.text().await?;
Ok(response)
}
}
}
pub fn spawn_ctrl_c_handler(cancellation_token: CancellationToken) {
tokio::spawn(async move {
if tokio::signal::ctrl_c().await.is_ok() {
warn!("Ctrl+C received, cancelling...");
cancellation_token.cancel();
}
});
}
pub fn is_ssrf_protected_ip(ip: std::net::IpAddr) -> bool {
match ip {
std::net::IpAddr::V4(v4) => {
let o = v4.octets();
v4.is_loopback() || v4.is_private() || v4.is_link_local() || v4.is_multicast() || v4.is_unspecified() || v4.is_broadcast() || (o[0] == 100 && (o[1] & 0xC0) == 64) }
std::net::IpAddr::V6(v6) => {
let s = v6.segments();
v6.is_loopback() || v6.is_multicast() || v6.is_unspecified() || (s[0] & 0xFFC0) == 0xFE80 || (s[0] & 0xFE00) == 0xFC00 || matches!(v6.to_ipv4_mapped(), Some(v4) if is_ssrf_protected_ip(std::net::IpAddr::V4(v4)))
}
}
}