Как программно фильтровать IP-адреса из виртуальной машины?

Вопрос или проблема

У меня есть этот фрагмент кода для получения IP-адреса Ethernet:

public static IPAddress GetEthernetIpAddress()
{
    foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
    {
        if (ni.OperationalStatus == OperationalStatus.Up)
        {
            if (ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
            {
                foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
                {
                    if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                    {
                        return ip.Address;
                    }
                }
            }
        }
    }

    return default;
}

Однако, если установлена виртуальная машина, она может вернуть IP-адрес этой VM. Как исключить IP-адреса виртуальных машин?

Одно решение, которое я нашел в интернете, предлагает проверять, есть ли адрес шлюза, потому что, по-видимому, у сетевого интерфейса VM его не будет, но поиск в Google для подтверждения этого дал мне другой ответ:

if (ni.GetIPProperties().GatewayAddresses.FirstOrDefault() == null)

ChatGPT o1-preview предложил проверить имя сетевого интерфейса на наличие “vEthernet”, но я не доверяю этому методу (не беспокойтесь об этом параметре StringComparison):

if (!ni.Name.Contains("vEthernet", StringComparison.OrdinalIgnoreCase))

Я не нашел ничего полезного в официальной документации для NetworkInterface или UnicastIPAddressInformation. Есть идеи?

Ответ или решение

Программа для фильтрации IP-адресов из виртуальных машин (VM)

Основная задача, стоящая перед вами, заключается в том, чтобы программно фильтровать IP-адреса, получая лишь IP-адреса Ethernet интерфейсов, избегая виртуальных машин. Рассмотрим несколько методов, которые помогут вам разработать улучшенный код для этой цели.

1. Проверка по типу сетевого интерфейса

Сетевые интерфейсы, которые созданы для виртуальных машин, обычно имеют определённые имена, такие как "vEthernet" или "Hyper-V Virtual Ethernet Adapter". Следовательно, вы можете дополнить ваш текущий метод проверкой имени сетевого интерфейса. Например:

if (!ni.Name.Contains("vEthernet", StringComparison.OrdinalIgnoreCase) && 
    !ni.Name.Contains("Virtual", StringComparison.OrdinalIgnoreCase) && 
    !ni.Name.Contains("Hyper-V", StringComparison.OrdinalIgnoreCase))
{
    // Код для обработки IP-адреса
}

2. Использование шлюзов

Проверка на наличие шлюза также может быть полезной, поскольку у некоторых виртуальных сетевых интерфейсов действительно может не быть настроенного шлюза. Вы можете сделать так:

if (ni.GetIPProperties().GatewayAddresses.Count > 0)
{
    // У интерфейса есть шлюз, продолжаем обработку IP-адреса
}

3. Проверка операционных состояний

Поскольку виртуальные сети могут быть неактивными или находиться в состоянии, отличном от "Up", вы можете добавить дополнительный фильтр:

if (ni.OperationalStatus == OperationalStatus.Up &&
    ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
{
    // Код для обработки IP-адреса
}

4. Полный переработанный код

С учётом всех вышеуказанных проверок, ваш метод может выглядеть следующим образом:

public static IPAddress GetEthernetIpAddress()
{
    foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
    {
        // Проверка на операционное состояние и тип интерфейса
        if (ni.OperationalStatus == OperationalStatus.Up && 
            ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
        {
            // Фильтрация по имени
            if (!ni.Name.Contains("vEthernet", StringComparison.OrdinalIgnoreCase) && 
                !ni.Name.Contains("Virtual", StringComparison.OrdinalIgnoreCase) && 
                !ni.Name.Contains("Hyper-V", StringComparison.OrdinalIgnoreCase))
            {
                // Проверка на наличие шлюзов
                if (ni.GetIPProperties().GatewayAddresses.Count > 0)
                {
                    foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
                    {
                        if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            return ip.Address; // Возврат первого подходящего IP-адреса
                        }
                    }
                }
            }
        }
    }

    return default; // Возврат значения по умолчанию, если IP не найден
}

Заключение

Используя описанный выше подход, вы сможете эффективно фильтровать IP-адреса, исключая адреса виртуальных машин. Этот улучшенный метод основывается на проверке имени интерфейса, состоянии операционной системы и наличия шлюзов, что в совокупности обеспечивает надёжный способ получения актуальных Ethernet IP-адресов.

Если у вас есть дополнительные вопросы или нужна помощь с другим аспектом, не стесняйтесь обращаться.

Оцените материал
Добавить комментарий

Капча загружается...