using System.Net; using System.Net.Sockets; namespace PrivaPub.Infrastructure.Http { public static class IpRangeGuard { static readonly IPNetwork[] BlockedV4 = { IPNetwork.Parse("0.0.0.0/8"), IPNetwork.Parse("10.0.0.0/8"), IPNetwork.Parse("100.64.0.0/10"), IPNetwork.Parse("127.0.0.0/8"), IPNetwork.Parse("169.254.0.0/16"), IPNetwork.Parse("172.16.0.0/12"), IPNetwork.Parse("192.0.0.0/24"), IPNetwork.Parse("192.0.2.0/24"), IPNetwork.Parse("192.88.99.0/24"), IPNetwork.Parse("192.168.0.0/16"), IPNetwork.Parse("198.18.0.0/15"), IPNetwork.Parse("198.51.100.0/24"), IPNetwork.Parse("203.0.113.0/24"), IPNetwork.Parse("224.0.0.0/4"), IPNetwork.Parse("240.0.0.0/4") }; static readonly IPNetwork GlobalUnicastV6 = IPNetwork.Parse("2000::/3"); static readonly IPNetwork[] BlockedV6 = { IPNetwork.Parse("2001::/32"),//Teredo IPNetwork.Parse("2001:2::/48"), IPNetwork.Parse("2001:10::/28"), IPNetwork.Parse("2001:20::/28"), IPNetwork.Parse("2001:db8::/32"), IPNetwork.Parse("2002::/16"),//6to4 IPNetwork.Parse("3fff::/20") }; public static bool IsPublic(IPAddress address) { if (address == default) return false; if (address.IsIPv4MappedToIPv6) address = address.MapToIPv4(); return address.AddressFamily switch { AddressFamily.InterNetwork => !BlockedV4.Any(range => range.Contains(address)), AddressFamily.InterNetworkV6 => GlobalUnicastV6.Contains(address) && !BlockedV6.Any(range => range.Contains(address)), _ => false }; } } }