powershell 获取静态(未分配dhcp)的接口及其DNS服务器

wh6knrhe  于 2023-05-07  发布在  Shell
关注(0)|答案(3)|浏览(138)

我正试图通过静态的WMI(由用户放置)的网络接口的DNS服务器。我有这个脚本,当然除了静态部分:

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不是静态的接口?有什么想法吗
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 ServersDNS servers configured through DHCP之间的术语差异。我想我可能会解析这个输出,但我不确定如果windows语言/区域设置改变了,我是否可以依赖这个文本,如果可能的话,我宁愿使用WMI接口。

y4ekin9u

y4ekin9u1#

我认为这可能在System.Net.NetworkInformation namespace中可用,但显然不是。我查看了一些较低级别的Windows networking APIs,心想 * 肯定 * 它一定存在于其中的某个地方,但没有这样的运气。在netsh.exe上运行dumpbin以查看它使用了哪些类型的库/函数之后,我确实想到了另一个可以查看的地方:登记处。
如果您在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\项下查看注册表,您将看到每个网络接口的一个项,其名称为GUID格式。在接口的键中,您会发现两个感兴趣的值:DhcpNameServerNameServer。在我的客户端系统中,DNS服务器由DHCP设置,DhcpNameServer包含该DNS服务器的IP地址,NameServer包含空的[String]。如果我手动设置DNS服务器,同时保留接口本身的自动分配地址,则NameServer包含手动设置的DNS服务器地址,而DhcpNameServer仍然包含DHCP指定的相同DNS服务器。
基于这些观察,似乎…

  • DhcpNameServer值始终包含DHCP指定的DNS服务器。
  • NameServer值始终包含手动指定的DNS服务器。
  • 当您查询系统的名称服务器(例如经由Win32_NetworkAdapterConfiguration.DNSServerSearchOrder属性),如果提供,则结果将包含NameServer的值,否则如果提供,则结果将包含DhcpNameServer的值。换句话说,系统会告诉你哪些DNS服务器 * 当前 * 正在使用,但不会告诉你它们的地址是如何指定的。
  • 要确定接口是否具有手动分配的DNS服务器,请检查NameServer是否具有非空值。

因此,给定一个ID为$interfaceID的接口,您可以像这样构建其注册表项的路径...

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

...然后像这样检索动态分配和手动分配的nameserver值...

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

这就剩下从哪里获取$interfaceID的值的问题了,有很多来源,尽管技巧是排除不需要的接口(例如,在我的Windows 10系统上,我有一个数据包捕获环回适配器和一个管理程序适配器,我希望从这样的查询中排除)。最兼容的方式(可以追溯到.NET 2.0)是NetworkInterface classId property

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

...尽管要过滤的唯一有用属性是NameNetworkInterfaceType
在Windows Vista及更高版本上,Win32_NetworkAdapter class提供GUID属性...

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

...虽然即使在PhysicalAdapter上进行过滤时,它仍然返回loopback和hypervisor适配器,并且我没有看到任何可用于仅选择硬件适配器的明确属性或类关系。
Win32_NetworkAdapterConfiguration class是一样的。

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

...没有属性来过滤掉非硬件甚至非物理适配器。
在(我认为)Windows 8及以上版本中有Get-NetConnectionProfile cmdlet...

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

它被记录为获取“与一个或多个物理网络适配器相关联的连接配置文件”,并且在我的系统上,它确实只返回我的物理适配器。
另外还有Get-NetAdapter cmdlet

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

我发现传递-Physical参数排除了hypervisor适配器,但没有排除loopback适配器,因此有必要过滤掉EndPointInterface$true的地方。HardwareInterfaceVirtual属性也可能会引起兴趣。
另一个选择是调用Get-NetAdapterHardwareInfo cmdlet,它似乎知道如何区分真正的硬件适配器,并让它确定Get-NetAdapter检索哪些适配器…

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

上面的Get-Net* cmdlet返回CIM示例,因此,例如,您可以使用类似...的内容来代替Get-NetAdapter -Physical

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

同样检索MSFT_NetAdapter示例。我真的不知道使用一个与另一个的指导是什么。看起来人们应该更喜欢cmdlet,但是,与WMI/CIM不同,它们提供有限的/没有参数来有效地过滤输出或指定所需的属性,因此您必须在管道中执行此操作。不过,我认为值得注意的是,我找不到这些MSFT_*类的任何 * 当前 * 文档;他们都说他们不再更新了,除了MSFT_NetConnectionProfile类,我根本找不到任何文档页面。对我来说,微软不希望你依赖于这些类的任何明确的结构,但是如果cmdlet只是沿着这些类示例......我不确定如果没有任何文档,你如何能够有意义地和可靠地与它们交互。
另外,请记住,在可能的情况下,您将want to preferGet-CimInstanceits ilk超过Get-WmiObject。我认为我还没有遇到过比将Get-WmiObject更改为Get-CimInstance更复杂的示例,尽管有比名称更多的差异(不一定是坏的)。

luaexgnf

luaexgnf2#

经过足够的抨击,我找到了一个解决方案,但我不是100%肯定是正确的道路。在所有DHCP DNS服务器上,DNS值都包含一个IP地址,并且该IP地址等于Default Gateway值。当这些值匹配时,我们正在处理一个DHCP DNS服务器,而不是静态配置的。

h43kikqp

h43kikqp3#

既然netsh知道这一切,为什么不走这条路呢?喜欢

get-netadapter | % { $adapter=$_ | Add-Member -PassThru -Name staticDNS -Type NoteProperty -Value "" | Add-Member -PassThru -Name dhcpDNS -Type NoteProperty -Value ""; $dnsInfo=netsh interface ipv4 show dns name="$($_.Name)"; $dnsInfo -split '`n' | % { if ($_ -like '*stat*10*' ) { $dummy=$_ -split ' '; $adapter.staticDNS+=@($dummy[$dummy.count-1]) }; if ($_ -like '*dhcp*' ) { $dummy=$_ -split ' '; $adapter.dhcpDNS+=@($dummy[$dummy.count-1]) } }; $adapter }

相关问题