using System.Net; using System.Net.Sockets; namespace MoShiro.Protocol; /// 哪些地址算「公网上能拨进来的地址」:Agent 上报本机地址和面板自动识别共用同一套判断。 public static class PublicAddress { public static bool IsPublicIpv4(IPAddress address) { if (address.AddressFamily != AddressFamily.InterNetwork) { return false; } byte[] b = address.GetAddressBytes(); return !(b[0] is 0 or 10 or 127 or >= 224 || (b[0] == 100 && b[1] is >= 64 and <= 127) || (b[0] == 169 && b[1] == 254) || (b[0] == 172 && b[1] is >= 16 and <= 31) || (b[0] == 192 && b[1] == 168) || (b[0] == 192 && b[1] == 0 && b[2] is 0 or 2) || (b[0] == 198 && b[1] is 18 or 19) || (b[0] == 198 && b[1] == 51 && b[2] == 100) || (b[0] == 203 && b[1] == 0 && b[2] == 113)); } public static bool IsGlobalIpv6(IPAddress address) { if (address.AddressFamily != AddressFamily.InterNetworkV6 || address.IsIPv4MappedToIPv6) { return false; } byte[] b = address.GetAddressBytes(); if ((b[0] & 0xE0) != 0x20) { return false; } // 2001:db8::/32 文档、2002::/16 6to4、2001::/32 Teredo return !((b[0] == 0x20 && b[1] == 0x01 && b[2] == 0x0d && b[3] == 0xb8) || (b[0] == 0x20 && b[1] == 0x02) || (b[0] == 0x20 && b[1] == 0x01 && b[2] == 0 && b[3] == 0)); } }