Как определить, является ли IP-адрес приватным?
Пока у меня есть этот код:
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adapter in adapters)
{
IPInterfaceProperties properties = adapter.GetIPProperties();
foreach (IPAddressInformation uniCast in properties.UnicastAddresses)
{
// Ignore loop-back addresses & IPv6
if (!IPAddress.IsLoopback(uniCast.Address) &&
uniCast.Address.AddressFamily!= AddressFamily.InterNetworkV6)
Addresses.Add(uniCast.Address);
}
}
Как я могу отфильтровать частные IP-адреса? Точно так же я фильтрую IP-адреса loopback.
Ответы
Ответ 1
Более подробный ответ здесь:
private bool _IsPrivate(string ipAddress)
{
int[] ipParts = ipAddress.Split(new String[] { "." }, StringSplitOptions.RemoveEmptyEntries)
.Select(s => int.Parse(s)).ToArray();
// in private ip range
if (ipParts[0] == 10 ||
(ipParts[0] == 192 && ipParts[1] == 168) ||
(ipParts[0] == 172 && (ipParts[1] >= 16 && ipParts[1] <= 31))) {
return true;
}
// IP Address is probably public.
// This doesn't catch some VPN ranges like OpenVPN and Hamachi.
return false;
}
Ответ 2
Диапазоны частных адресов определены в RFC1918. Это:
- 10.0.0.0 - 10.255.255.255 (префикс 10/8)
- 172.16.0.0 - 172.31.255.255 (префикс 172.16/12)
- 192.168.0.0 - 192.168.255.255 (префикс 192.168/16)
Вы также можете отфильтровать локальные локальные ссылки (169.254/16), как определено в RFC3927.
Ответ 3
10.0.0.0 - 10.255.255.255 (10/8 prefix)
172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
Используйте диапазоны, определенные в RFC (как было предложено Anders); чем использовать регулярное выражение для обнаружения/удаления частного IP-адреса из списка.
Вот пример RegEx для обнаружения частных IP-адресов. (Не проверено мной)
(^127\.0\.0\.1)|
(^10\.)|
(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|
(^192\.168\.)
Ответ 4
Лучше всего это будет метод расширения класса IP-адресов
/// <summary>
/// An extension method to determine if an IP address is internal, as specified in RFC1918
/// </summary>
/// <param name="toTest">The IP address that will be tested</param>
/// <returns>Returns true if the IP is internal, false if it is external</returns>
public static bool IsInternal(this IPAddress toTest)
{
byte[] bytes = toTest.GetAddressBytes();
switch( bytes[ 0 ] )
{
case 10:
return true;
case 172:
return bytes[ 1 ] < 32 && bytes[ 1 ] >= 16;
case 192:
return bytes[ 1 ] == 168;
default:
return false;
}
}
Затем можно вызвать метод в экземпляре класса IP-адреса
bool isIpInternal = ipAddressInformation.Address.IsInternal();
Ответ 5
Добавлены случаи IPv6 и localhost.
/* An IP should be considered as internal when:
::1 - IPv6 loopback
10.0.0.0 - 10.255.255.255 (10/8 prefix)
127.0.0.0 - 127.255.255.255 (127/8 prefix)
172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
*/
public bool IsInternal(string testIp)
{
if(testIp == "::1") return true;
byte[] ip = IPAddress.Parse(testIp).GetAddressBytes();
switch (ip[0])
{
case 10:
case 127:
return true;
case 172:
return ip[1] >= 16 && ip[1] < 32;
case 192:
return ip[1] == 168;
default:
return false;
}
}