Monthly Archive

DNS

Parsing ipconfig /displaydns with regular expressions

In yesterdays post I used a series of split operations to parse the strings produced by ipconfig /displaydns

 

Regular expressions should give a more power full way to perform this task. Not being a big fan of regular expressions I tend not to use them but for the sake of experimentation I thought I’d try and figure out a set of regex to use.

 

This is as far as I’ve got

 

$props = [ordered]@{
  RecordName = ""
  RecordType = ""
  Section    = ""
  TimeToLive = 0
  DataLength = 0
  Data       = ""
}

$recs = @()

$cache = ipconfig /displaydns
for($i=0; $i -le ($cache.Count -1); $i++) {
if ($cache[$i] -like '*Record Name*'){
    $rec = New-Object -TypeName psobject -Property $props
    $rec.RecordName = $cache[$i] -replace "(\s*\w*){2}(\s\.){5}(\s\:\s)", ""
    $rec.Section = $cache[$i+4] -replace "\s*\w*(\s\.){7}(\s\:\s)", ""
    $rec.TimeToLive = $cache[$i+2] -replace "(\s*\w*){3}\s(\s\.){4}(\s\:\s)", ""
    $rec.DataLength = $cache[$i+3] -replace "(\s*\w*){2}(\s\.){5}(\s\:\s)", ""
   
    $irec = ($cache[$i+5] -split ": ")
    $rec.RecordType = ($irec[0].TrimStart() -split ' ')[0]
    $rec.Data = $irec[1]

    $recs += $rec
}
else {
    continue
}
}

$recs | Format-Table –AutoSize

 

I still need to work out how to process the data and record type using regular expressions

Parsing ipconfig /displaydns

 

A recent question on the forum asked how you could get the contents on Windows 7 machines and earlier.

On later machines – Windows 8 and above -  its easy because you can use Get-DnsClientCache from the DnsClient module. This module is based on CIM classes that aren’t present on Windows 7 and earlier systems.

 

You can use ipconfig /displaydns to display the data but it looks like this

Record Name . . . . . : ns-nw.noaa.gov
Record Type . . . . . : 1
Time To Live  . . . . : 81966
Data Length . . . . . : 4
Section . . . . . . . : Additional
A (Host) Record . . . : 161.55.32.2

 

so you need to parse the strings into a format that you can work with. 

 

This is one solution

 

$props = [ordered]@{
  RecordName = ""
  RecordType = ""
  Section    = ""
  TimeToLive = 0
  DataLength = 0
  Data       = ""
}

$recs = @()

$cache = ipconfig /displaydns
for($i=0; $i -le ($cache.Count -1); $i++) {
if ($cache[$i] -like '*Record Name*'){
    $rec = New-Object -TypeName psobject -Property $props
    $rec.RecordName = ($cache[$i] -split -split ": ")[1]
    $rec.Section = ($cache[$i+4] -split -split ": ")[1]
    $rec.TimeToLive = ($cache[$i+2] -split -split ": ")[1]
    $rec.DataLength = ($cache[$i+3] -split -split ": ")[1]
   
    $irec = ($cache[$i+5] -split ": ")
    $rec.RecordType = ($irec[0].TrimStart() -split ' ')[0]
    $rec.Data = $irec[1]

    $recs += $rec
}
else {
    continue
}
}

$recs | Format-Table –AutoSize

Create an ordered hash table of output properties and an empty array to hold the results.

 

Get the output of  ipconfig /displaydns into $cache which will be an array of strings

Loop through $cache

 

if the record is like *Record Name*' then process that record and the next five records to give the results.  The actual data record is split twice to give the record type and the data – otherwise you’ll have to translate the numeric values in the Record Type line.

 

The results are put into an object which is added to the output array.

 

Continue looping through $cache until you meet the next line with a Record Name or end of file.

 

Finally display the results.

 

This works but is messy – I’m going to investigate alternatives

DNS client settings

Following yesterdays post there are a couple of other cmdlets worth looking at if you want to dig into the DNS settings on your client machines.

Get-DnsClient wil show you the DNS relsted settings for all of your network interfaces by default.  To investigate a single interface

 

£> Get-DnsClient -InterfaceAlias vEthernet* | fl

InterfaceAlias                     : vEthernet (External01)
InterfaceIndex                     : 20
ConnectionSpecificSuffix           :
ConnectionSpecificSuffixSearchList : {}
RegisterThisConnectionsAddress     : True
UseSuffixWhenRegistering           : False

InterfaceAlias                     : vEthernet (Internal01)
InterfaceIndex                     : 16
ConnectionSpecificSuffix           :
ConnectionSpecificSuffixSearchList : {}
RegisterThisConnectionsAddress     : True
UseSuffixWhenRegistering           : False

 

You can also see the DNS servers a particular interface will use:

£> Get-DnsClientServerAddress -InterfaceAlias vEthernet*

InterfaceAlias               Interface Address ServerAddresses
                             Index     Family
--------------               --------- ------- ---------------
vEthernet (External01)              20 IPv4    {192.168.0.1}
vEthernet (External01)              20 IPv6    {}
vEthernet (Internal01)              16 IPv4    {}
vEthernet (Internal01)              16 IPv6    {fec0:0:0:ffff::1, fec0:0:0:ffff::2, fec0:0:0:ffff::3}

Have you been talking to strangers?

Want to know the machines to which your machine has been connecting?

 

Try looking in the client DNS cache:

 

Get-DnsClientCache

 

will show a wealth of useful data.  All in the form:

£> Get-DnsClientCache | where Entry -like '*www.intelliweather.net*' | fl *

TTL                   : 39
Caption               :
Description           :
ElementName           :
InstanceID            :
Data                  : cache1.intelliweather.net
DataLength            : 8
Entry                 : www.intelliweather.net
Name                  : www.intelliweather.net
Section               : 1
Status                : 0
TimeToLive            : 39
Type                  : 5
PSComputerName        :
CimClass              : ROOT/StandardCimv2:MSFT_DNSClientCache
CimInstanceProperties : {Caption, Description, ElementName, InstanceID...}
CimSystemProperties   : Microsoft.Management.Infrastructure.CimSystemProperties

TTL                   : 39
Caption               :
Description           :
ElementName           :
InstanceID            :
Data                  : 38.114.169.29
DataLength            : 4
Entry                 : www.intelliweather.net
Name                  : cache1.intelliweather.net
Section               : 1
Status                : 0
TimeToLive            : 39
Type                  : 1
PSComputerName        :
CimClass              : ROOT/StandardCimv2:MSFT_DNSClientCache
CimInstanceProperties : {Caption, Description, ElementName, InstanceID...}
CimSystemProperties   : Microsoft.Management.Infrastructure.CimSystemProperties

 

 

What is interesting is the Time To Live settings on some of the records:

£> Get-DnsClientCache | sort TTL -Descending | group TTL -NoElement

Count Name
----- ----
    7 74538
    1 70203
    1 64639
    1 53300
    1 53299
    1 16441
    2 9308
    1 2579
    1 2573
    3 2475
    6 2469
    2 2327
    2 1986
    1 1890
    1 1089
    1 999
    2 899
    2 891
    2 878
    3 728
    1 724
    6 711
    1 631
    1 458
    1 412
    1 363
    1 133
   15 0

 

Some of those records will be around for a long time!

DNS zone types

I was looking at the DNS zones for a project I’m working on. I needed to discover the conditional forwarder zone and hence the IP address of the DNS server to which the forwarding was occurring.

The zone I wanted had a ZoneType of 4 which puzzled me.

I remembered showing code to create a conditional forwarder in PowerShell in Practice (www.manning.com/siddaway)

$ip = “192.168.40.1”
$zone = [WMIClass]”\\dc02\root\MicrosoftDNS:MicrosoftDNS_Zone”
$zone.Create(“conditional.com”, 3, $true, $null, $ip)

When creating a conditional forwarder you use 3 for the zone type but when reading the zone you get a 4 as the zone type. Other zone types have similar differences

Primary zone (forward or reverse lookup) = create as type 0 and read as type 1

Stub zone = create as type 2 and read as type 3

This is another of the oddities that make WMI so much fun to work with. Easy when you know what’s happening but confusing when you don’t – just like so much with WMI. Does the W stand for Weird?  Smile

The Windows Server 2012 DNS cmdlets make this sooooo  much easier.

Creating DNS PTR records

When I was writing the DNS chapter of PowerShell in Practice I couldn’t get the CreateInstanceFromPropertyData  method on the MicrosoftDNS_PTRType  class to work. Revisiting DNS for AD management in a Month of lunches this time round I have access to the CIM cmdlets so can put the parameter names in.  This gives usage like this.  I’ve shown Invoke-WmiMethod and Invoke-CimMethod so you can see the parameter names:

Invoke-WmiMethod -Namespace root\MicrosoftDNS -Class MicrosoftDNS_PTRType `
-Name CreateInstanceFromPropertyData `
-ArgumentList "175.168.192.in-addr.arpa", 'server02', '55.175.168.192.in-addr.arpa',
"ADMLServer02.admldns.test" 

Invoke-CimMethod -Namespace root\MicrosoftDNS -ClassName MicrosoftDNS_PTRType `
-MethodName CreateInstanceFromPropertyData `
-Arguments @{Containername = "175.168.192.in-addr.arpa";
DnsServerName = 'server02'; OwnerName = '55.175.168.192.in-addr.arpa';
PTRDomainName ="ADMLServer02.admldns.test"}

 

If you have access to Windows 2012 then you are better off using the cmdlet

Add-DnsServerResourceRecordPtr –Name ‘54’ `
–ZoneName “175.168.192.in-addr.arpa” `
–PtrDomainName  ‘ADMLServer01.admldns.test’  `
–ComputerName server02

 

Which ever method you use – you can easily create PTR records

DnsClient module: #2 DnsClient & Cache

The DnsClient module has a number of Get- cmdlets

Get-DnsClient | Format-List InterfaceAlias, ConnectionSpecificSuffix, Register*, UseSuffix*

An example of the output is

InterfaceAlias                 : Ethernet
ConnectionSpecificSuffix       :
RegisterThisConnectionsAddress : True
UseSuffixWhenRegistering       : False

Of more interest when trouble shooting is Get-DnsClientCache

PS> Get-DnsClientCache | select -f 1 | fl

Entry      : 14.54.10.10.in-addr.arpa
RecordName : 14.54.10.10.in-addr.arpa.
RecordType : PTR
Status     : Success
Section    : Answer
TimeToLive : 86400
DataLength : 4
Data       : Win7test

You get a number of ways to interrogate the cache

PS> Get-Command Get-DnsClientCache  -Syntax

Get-DnsClientCache [[-Entry] <string[]>] [-Name <string[]>] [-Type <Type[]>] [-Status <Status[]>]
[-Section<Section[]>] [-TimeToLive <uint32[]>] [-DataLength <uint16[]>] [-Data <string[]>]
[-CimSession <CimSession[]>][-ThrottleLimit <int>] [-AsJob] [<CommonParameters>]

Its another CIM based cmdlet so you can use CimSessions to access remote machines. Very useful if you think the machine isn’t resolving DNS names properly

DnsClient module: #1 Get-DnsClientServerAddress

Started to investigate the DnsClient module.  First cmdlet to catch my eye was Get-DnsClientServerAddress.

Always good to know a way to find the DNS server.

PS> Get-DnsClientServerAddress

InterfaceAlias               Interface Address ServerAddresses
                             Index     Family
--------------               --------- ------- ---------------
Bluetooth Network Connection        19 IPv4    {}
Bluetooth Network Connection        19 IPv6    {fec0:0:0:ffff::1, fec0:0:0:ffff::2, fec0:0:0:ffff::3}
WiFi                                12 IPv4    {192.168.1.1}
WiFi                                12 IPv6    {}
isatap.tiscali.co.uk                14 IPv4    {192.168.1.1}
isatap.tiscali.co.uk                14 IPv6    {}
Ethernet                            13 IPv4    {}
Ethernet                            13 IPv6    {fec0:0:0:ffff::1, fec0:0:0:ffff::2, fec0:0:0:ffff::3}
Loopback Pseudo-Interface 1          1 IPv4    {}
Loopback Pseudo-Interface 1          1 IPv6    {fec0:0:0:ffff::1, fec0:0:0:ffff::2, fec0:0:0:ffff::3}
Teredo Tunneling Pseudo-I...        15 IPv4    {}
Teredo Tunneling Pseudo-I...        15 IPv6    {}

Now thats OK but I’d like a bit more information – especially the adapter and IP version.  We can get that data using Get-NetAdapter from the NetAdapter module.

Get-DnsClientServerAddress |             
where {$_.ServerAddresses -and $_.InterfaceAlias -notlike "Loop*" }|            
foreach {            
 $nic = $_            
 Get-NetAdapter -IncludeHidden -InterfaceIndex $($nic.InterfaceIndex) |            
 Add-Member -MemberType NoteProperty -Name ServerAddresses -Value $($nic.ServerAddresses) -PassThru |            
 Add-Member -MemberType NoteProperty -Name AddressFamily -Value $(if ($nic.AddressFamily -eq 2){"IPv4"}else{"IPv6"} ) -PassThru|            
 select Name, InterfaceDescription, ifIndex, Status, MacAddress, LinkSpeed, AddressFamily, ServerAddresses             
 }

 

I restricted the output to those interfaces that had DNS server addresses. Used the interface to get the adapter – notice the use of –IncludeHidden – and then used Add-Member to add the addresses and Address family to the data.

These may be CDXML cmdlets but they work the same as any other cmdlet

Finding the primary name of a DNS alias record

A forum question asked how to find the primary name from an alias or CNAME record.

Get-WmiObject -Namespace 'root\MicrosoftDNS' -Class MicrosoftDNS_CNAMEType `
-Filter "ContainerName = 'Manticore.org'" -ComputerName server02  |             
select @{N='Alias'; E={$_.Ownername}}, Primaryname            

 

use the MicrosoftDNS_CNAMEType class. Filter on the domain ie containername.  ComputerName holds the DNS server name.

Change OwnerName to Alias in a select calculated field

Get Global Catalog from DNS

One option for finding global catalog servers is often overlooked – DNS.  In an AD environment DNS stores the SRV records that advertise the services domain controllers can deliver

$dnsserver = "dc02"            
Get-WmiObject -Namespace 'root\MicrosoftDNS' -Class  MicrosoftDNS_SRVType `
-ComputerName $dnsserver -Filter "ContainerName = 'Manticore.org'" |             
Where {$_.OwnerName -like "_gc*"} |            
select TextRepresentation

We are interested in the ‘root\MicrosoftDNS’ name space and the MicrosoftDNS_SRVType records. We want the manticore.org zone and all records where the Ownername is like “_gc*”

The results look like this

_gc._tcp.Site1._sites.Manticore.org IN SRV 0 100 3268 dc02.manticore.org.

_gc._tcp.Site1._sites.Manticore.org IN SRV 0 100 3268 server02.manticore.org.  
_gc._tcp.Manticore.org IN SRV 0 100 3268 dc02.manticore.org.  
_gc._tcp.Manticore.org IN SRV 0 100 3268 server02.manticore.org.