Tag Archives: nslookup

Parsing nslookup: Only Return the Resolved IP

It was late last Friday evening when a vendor and I worked though some maintenance. As a part of the work (which actually lasted well into the weekend), we needed to remove two DNS A records and replace them with CNAME records. I figured that before the change, I would return the current resolution results, so I would be able to ensure the DNS change took place, after the night’s weekend’s work.

You’re probably familiar with the standard output of nslookup.

PS> nslookup subdomain.mydomain.com
Server:  mydomain.com
Address:  10.10.10.1

Name:    subdomain.mydomain.com
Address:  10.20.30.40

These results indicate the name, subdomain.mydomain.com, resolves to an IP address of 10.20.30.40 when using the mydomain.com nameserver, at 10.10.10.1. I wanted to clean up this output, and since I had time to kill while fighting off sleep, I figured — why not? I started by piping the results of nslookup to the Select-String cmdlet looking for the string, ‘Address.’ As you can see in the example below, it returns both the IP of the server where the resolution took place, and the results. After that, there doesn’t seem to be a way to distinguish one line from the other. I needed another way to only return the results.

PS> nslookup subdomain.mydomain.com | Select-String Address

Address: 10.10.10.1
Address: 10.20.30.40

I decided to pipe the command above to the Get-Member cmdlet to see what kind of object the Select-String cmdlet returned. The property that jumped out at me right away was LineNumber — was it really going to be that easy?

   TypeName: Microsoft.PowerShell.Commands.MatchInfo

Name         MemberType Definition
----         ---------- ----------
Equals       Method     bool Equals(System.Object obj)
GetHashCode  Method     int GetHashCode()
GetType      Method     type GetType()
RelativePath Method     string RelativePath(string directory)
ToString     Method     string ToString(), string ToString(string directory)
Context      Property   Microsoft.PowerShell.Commands.MatchInfoContext Context {get;set;}
Filename     Property   string Filename {get;}
IgnoreCase   Property   bool IgnoreCase {get;set;}
Line         Property   string Line {get;set;}
LineNumber   Property   int LineNumber {get;set;}
Matches      Property   System.Text.RegularExpressions.Match[] Matches {get;set;}
Path         Property   string Path {get;set;}
Pattern      Property   string Pattern {get;set;}

Here’s the thing, the output of nslookup is always the same: this on a this line, and that on that line. This is likely why the LineNumber property looked so promising, so quickly. Now that we know we have this property, let’s try and use it. While my first line number guess worked (read, dumb luck), let’s do it wrong first. Consider again our most recent output below.

PS> nslookup subdomain.mydomain.com | Select-String Address

Address: 10.10.10.1
Address: 10.20.30.40

You might think you would want line 3 of our output, but that’s not correct. Even though Select-String has trimmed down the output, the line numbers are all still intact. Look at the very first example at the top of this post. Line 3 is blank — it’s line 5 that we want! Take a look.

PS> nslookup subdomain.mydomain.com | Select-String Address | Where-Object LineNumber -eq 5

Address: 10.20.30.40

If you want to store this as as a string, use the .ToString() method.

PS> (nslookup subdomain.mydomain.com | Select-String Address | Where-Object LineNumber -eq 5).ToString()
Address: 10.20.30.40

And, if you want to remove the word “address,” the colon, and the space, in order to only return the IP address, then you can parse the string by using the .Split() method. The example below splits the string at the space and return the last element — what’s on the right side of the space.

PS> (nslookup subdomain.mydomain.com | Select-String Address | Where-Object LineNumber -eq 5).ToString().Split(' ')[-1]
10.20.30.40

I hope this was helpful for someone. Until next time.

Finding Non-Resolveable IP Addresses

When preparing to bring new servers online, I often need a quick way to know what IP addresses, in a range of IP addresses, do not resolve to a name. This is the first step to determine unused IP addresses. The first time I did this was back before I was running Windows PowerShell 4.0 on Windows 8.1 which includes the Resolve-DnsName cmdlet. It meant I needed to use the command line tool nslookup; we’ll discuss both options in this post.

The first two examples below, use nslookup to try and resolve two different IPs: one that does resolve and one that doesn’t. It should be noted that resolving an IP address to a name is called Reverse DNS (rDNS). In the first example we have an IP address that resolves. That means it likely wouldn’t be an IP address I would want to use for a new server.

PS C:\> nslookup 10.10.10.2
Server:  dns.mydomain.com
Address:  10.10.10.1

Name:    dc01.mydomain.com
Address:  10.10.10.2

The next example shows an IP address that doesn’t resolve, and therefore, would likely be a useable IP address for one of my servers. Remember, we want to collect our failed name resolutions.

PS C:\> nslookup 10.10.10.4
Server:  dns.mydomain.com
Address:  10.10.10.1

*** dns.mydomain.com can't find 10.10.10.4: Non-existent domain

Let’s assume our range of possibly useable IPs is 10.10.10.2 – 10.10.10.254. This assumes we’re using .1 for the gateway and .255 for broadcast. We’ll use a sub range of this full range (10.10.10.2 through 10.10.10.5) for most of our testing and examples. We’re going to use the range operator (..) to help automate checking the IP addresses.

PS C:\> 2..5 | ForEach-Object {nslookup 10.10.10.$_}
Server:  dns.mydomain.com
Address:  10.10.10.1

Name:    dc01.mydomain.com
Address:  10.10.10.2

Server:  dns.mydomain.com
Address:  10.10.10.1

Name:    dc02.mydomain.com
Address:  10.10.10.3

Server:  dns.mydomain.com
Address:  10.10.10.1

*** dns.mydomain.com can't find 10.10.10.4: Non-existent domain
Server:  dns.mydomain.com
Address:  10.10.10.1

*** dns.mydomain.com can't find 10.10.10.5: Non-existent domain

Our results, above, indicate that .2 and .3 are resolving and therefore are likely not useable for us. It also indicates we may be able to use .4 and .5, since those are not resolving. There’s still too much information returned by nslookup, so let’s clean that up by only returning failed resolutions.

In the example below, we’ll pipe our nslookup results to the Select-String cmdlet and search for the three asterisks (***) that begin each line where there is a failed name resolution. By default, the Select-String cmdlet does a regex match, so we’ll need to use the more literal approach and include the -SimpleMatch parameter of Select-String.

PS C:\> 2..5 | ForEach-Object {nslookup 10.10.10.$_ | Select-String -Pattern *** -SimpleMatch}
*** dns.mydomain.com can't find 10.10.10.4: Non-existent domain
*** dns.mydomain.com can't find 10.10.10.5: Non-existent domain

PowerShell 3.0 on Windows 8 and Server 2012 brought us the Resolve-DnsName cmdlet as part of the DnsClient module. This is essentially the replacement for nslookup on newer versions of PowerShell, on newer versions of the underlying operating system. By default, this cmdlet will return much more information on a successful resolution and an error on a failed resolution. Although I’ve truncated the successful results, there is an example of both a success and failure, below.

PS C:\> Resolve-DnsName -Name 10.10.10.2

Name                       Type   TTL   Section    NameHost
----                       ----   ---   -------    --------
2.10.10.10.in-addr.arpa    PTR    214   Answer     dc01.mydomain.com
...

PS C:\> Resolve-DnsName -Name 10.10.10.4
Resolve-DnsName : 10.10.10.4 : The filename, directory name, or volume label syntax is incorrect
At line:1 char:1
+ Resolve-DnsName -Name 10.10.10.4
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (10.10.10.4:String) [Resolve-DnsName], Win32Exception
    + FullyQualifiedErrorId : ERROR_INVALID_NAME,Microsoft.DnsClient.Commands.ResolveDnsName

Now, what we need to do is find the failed name resolutions for our IP test range without displaying errors. This will require a little more work, but gives us more control over what’s actually displayed, instead of relying on the default output of nslookup.

In this example, we’ll run Resolve-DnsName for each IP address in our test range: 10.10.10.2 through 10.10.10.5. If it is unable to resolve, we’ll suppress the error using the -ErrorAction parameter, and then display our own message to inform us which IPs in our range didn’t resolve.

PS C:\> 2..5 | ForEach-Object {
>> If (-not(Resolve-DnsName -Name 10.10.10.$_ -ErrorAction SilentlyContinue)) {
>> Write-Output -Verbose "10.10.10.$_ -- Not Resolving"}
>> }
>>
10.10.10.4 -- Not Resolving
10.10.10.5 -- Not Resolving

If you made it all the way down here, then thanks for reading this post; I hope you found something useful. I would like to mention how to use .NET to resolve names to IPs, and IPs to names. Here’s a couple examples of both using a Microsoft name and IP.

PS C:\> [System.Net.Dns]::GetHostAddresses('microsoft.com')

Address            : 783919750
AddressFamily      : InterNetwork
ScopeId            :
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv4MappedToIPv6 : False
IPAddressToString  : 134.170.185.46

Address            : 3720129158
AddressFamily      : InterNetwork
ScopeId            :
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv4MappedToIPv6 : False
IPAddressToString  : 134.170.188.221

PS C:\> [System.Net.Dns]::GetHostByAddress('134.170.185.46')

HostName                                Aliases                                 AddressList
--------                                -------                                 -----------
grv.microsoft.com                       {}                                      {134.170.185.46}