Получение интерфейсов и их DNS-серверов, которые имеют STATI C (не выделен dhcp) - PullRequest
3 голосов
/ 14 января 2020

Я пытаюсь получить DNS-серверы сетевых интерфейсов через WMI, которые установлены c (размещены пользователем). У меня есть этот скрипт, который работает, за исключением части курса stati c:

Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DNSServerSearchOrder -ne $null} | Select DnsServerSearchOrder,Index,InterfaceIndex

Это приводит к выводу примерно так:

DnsServerSearchOrder   Index InterfaceIndex
--------------------   ----- --------------
{192.168.122.1}            1              6
{1.1.1.1}                  2             10

Интерфейс с 192.168.122.1 имеет настройку DNS для DHCP, так что это значение не подходит для меня. Как отфильтровать интерфейсы, где dns не является c? Есть идеи?

netsh interface ip show config:

Configuration for interface "Ethernet"
    DHCP enabled:                         Yes
    IP Address:                           192.168.122.130
    Subnet Prefix:                        192.168.122.0/24 (mask 255.255.255.0)
    Default Gateway:                      192.168.122.1
    Gateway Metric:                       0
    InterfaceMetric:                      35
    DNS servers configured through DHCP:  192.168.122.1
    Register with which suffix:           Primary only
    WINS servers configured through DHCP: None

Configuration for interface "Ethernet 2"
    DHCP enabled:                         Yes
    IP Address:                           10.0.0.17
    Subnet Prefix:                        10.0.0.0/24 (mask 255.255.255.0)
    Default Gateway:                      10.0.0.1
    Gateway Metric:                       0
    InterfaceMetric:                      35
    Statically Configured DNS Servers:    1.1.1.1
    Register with which suffix:           Primary only
    WINS servers configured through DHCP: None

Обратите внимание на разницу между Statically Configured DNS Servers и DNS servers configured through DHCP. Я подумал, что мог бы проанализировать этот вывод, но я не уверен, смогу ли я положиться на этот текст, если windows язык / локаль изменен, и я предпочел бы использовать интерфейс WMI, если это возможно.

Ответы [ 2 ]

3 голосов
/ 14 января 2020

Я думал, что это может быть доступно в System.Net.NetworkInformation пространстве имен , но, очевидно, нет. Я просмотрел несколько низкоуровневых Windows сетевых API , думая конечно он должен существовать где-то там, но такой удачи не было. После запуска dumpbin на netsh.exe, чтобы увидеть, какие виды библиотек / функций он потребляет, у меня появилась идея посмотреть еще одно место: реестр.

Как это происходит , если вы загляните в реестр под ключом HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\, вы увидите ключ для каждого сетевого интерфейса с именем в формате GUID. В ключе интерфейса вы найдете два значения: DhcpNameServer и NameServer. В моей клиентской системе, где DNS-сервер установлен по DHCP, DhcpNameServer содержит IP-адрес этого DNS-сервера, а NameServer содержит пустой [String]. Если я вручную задаю DNS-сервер, сохраняя автоматически назначенный адрес для самого интерфейса, NameServer затем содержит этот заданный вручную адрес DNS-сервера, тогда как DhcpNameServer все еще содержит тот же DNS-сервер, указанный DHCP.

На основании этих наблюдений может показаться, что ...

  • Значение DhcpNameServer всегда содержит DNS-сервер (ы), заданный DHCP.
  • Значение NameServer всегда содержит DNS-сервер (ы), указанные вручную.
  • Когда вы запрашиваете у системы его серверы имен (например, через свойство Win32_NetworkAdapterConfiguration.DNSServerSearchOrder), результат будет содержать значение NameServer, если оно предоставлено, в противном случае значение DhcpNameServer, если предусмотрено. Другими словами, система сообщает вам, какие DNS-серверы в настоящее время используются, но не то, как были указаны их адреса.
  • Чтобы определить, имеет ли интерфейс назначенные вручную DNS-серверы, проверьте, NameServer имеет непустое значение.

Таким образом, имея интерфейс с идентификатором $interfaceID, вы можете построить путь к его ключу реестра следующим образом ...

$interfaceKeyPath = "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\$interfaceID"

... и затем получить динамически назначенные и назначенные вручную значения сервера имен, как это ...

Get-ItemProperty -Path $interfaceKeyPath -Name 'DhcpNameServer', 'NameServer'

Это просто оставляет вопрос о том, откуда вы получаете значение для $interfaceID, и существует множество источников, хотя хитрость будет исключать нежелательные интерфейсы (например, в моей системе Windows 10 у меня есть адаптер обратной связи с захватом пакетов и адаптер гипервизора, который я бы хотел исключить из такого запроса). Наиболее совместимым способом (начиная с. NET 2.0) будет свойство Id класса NetworkInterface ...

[System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() `
    | Select-Object -ExpandProperty 'Id'

... хотя единственными полезными свойствами для фильтрации являются Name и NetworkInterfaceType.

On Windows Vista и выше Win32_NetworkAdapter класс предоставляет свойство GUID ...

Get-WmiObject -Class 'Win32_NetworkAdapter' -Property 'GUID' -Filter 'PhysicalAdapter = true'

... хотя даже при фильтрации на PhysicalAdapter он по-прежнему возвращает loopback и гипервизор адаптеры, и я не вижу каких-либо определенных свойств или отношений классов, которые можно использовать для выбора только аппаратных адаптеров.

Win32_NetworkAdapterConfiguration класс во многом такой же ...

Get-WmiObject -Class 'Win32_NetworkAdapterConfiguration' -Property 'SettingID'

... без свойств для фильтрации не аппаратных или даже нефизических адаптеров.

Вкл (я думаю) Windows 8 и выше есть Get-NetConnectionProfile cmdlet ...

Get-NetConnectionProfile | Select-Object -ExpandProperty 'InstanceID'

, который задокументирован для получения "профиля соединения, связанного с одним или несколькими физическими сетевыми адаптерами", и в моей системе он возвращает только мой p физический адаптер.

Существует также командлет Get-NetAdapter ...

Get-NetAdapter -Physical `
    | Where-Object -Property 'EndPointInterface' -NE -Value $true `
    | Select-Object -ExpandProperty 'InterfaceGuid'

Я обнаружил, что передача параметра -Physical исключает адаптер гипервизора, но не адаптер обратной связи, поэтому для устранения этого необходимо было отфильтровать, где EndPointInterface равно $true. Свойства HardwareInterface и Virtual также могут представлять интерес.

Другой вариант - вызвать Get-NetAdapterHardwareInfo командлет , который, похоже, знает, как отличить guish настоящие аппаратные адаптеры, и пусть они определяют, какие адаптеры извлекаются с помощью Get-NetAdapter ...

Get-NetAdapterHardwareInfo `
    | Get-NetAdapter `
    | Select-Object -ExpandProperty 'InterfaceGuid'

Приведенные выше командлеты Get-Net* возвращают экземпляры CIM, поэтому, например, вместо Get-NetAdapter -Physical вы может использовать что-то вроде ...

Get-WmiObject -Namespace 'Root\StandardCimv2' -Class 'MSFT_NetAdapter' `
    -Property 'InterfaceGuid' -Filter 'HardwareInterface = true AND EndPointInterface = false'

для получения экземпляров MSFT_NetAdapter точно так же. Я не совсем уверен, что руководство по использованию одного против другого. Казалось бы, нужно отдавать предпочтение командлетам, и все же, в отличие от WMI / CIM, они предлагают ограниченные параметры / нет параметров для эффективной фильтрации выходных данных или указания желаемых свойств, так что вы должны сделать это в конвейере. Я думаю, что примечательно, что я не смог найти никакой текущей документации для этих MSFT_* классов; все они говорят, что больше не обновляются, за исключением класса MSFT_NetConnectionProfile, для которого я вообще не смог найти страницу документации. Это говорит мне о том, что Microsoft не хочет, чтобы вы полагались на какую-то определенную структуру этих классов, и все же, если командлеты просто передают эти экземпляры классов ... Я не уверен, как вы можете полноценно и надежно взаимодействовать с ними, если ничего не происходит. задокументировано.

Кроме того, имейте в виду, что вы захотите отдать предпочтение Get-CimInstance и его значение над Get-WmiObject, где это возможно. Я не думаю, что я когда-либо встречал случай, когда это было более сложным, чем изменение Get-WmiObject на Get-CimInstance, хотя есть больше различий (не обязательно плохих), чем имя.

1 голос
/ 14 января 2020

После достаточного избиения я нашел решение, но я не на 100% уверен, что это правильный путь. На всех DHCP-серверах DNS значения DNS содержат один IP-адрес, и этот IP-адрес равен значению Default Gateway. Когда эти значения совпадают, мы имеем дело с DHCP-сервером DHCP и не статически настроены.

...