Resolving Reverse DNS Lookups in PowerShell (and some issues to be aware of)

1. August 2012 20:59 by Forrest C. Shields II in PowerShell  //  Tags:   //   Comments (6)

Reverse DNS Lookups

God, I love PowerShell! What do you do when you want to find out the host name associated with an an IP address, such as 123.45.67.89?  Well you can do this:

[System.Net.Dns]::GetHostByAddress("123.45.67.89")

But GetHostByAddress is Obsolete

According to the MSDN documentation for the .NET Framework 4, the GetHostByAddress() method is "obsolete". This isn't a problem for PowerShell v1 and v2 users because each of those use .NET 2.0.  However, if you want your scripts to be forwardly compatible with Powershell v3 (which uses .NET 4.0), then you will have to find another method.  Thankfully, there is a recommended replacement method called GetHostEntry() that has been in place since .NET 2.0 so it will work now and in the future.

[System.Net.Dns]::GetHostEntry("123.45.67.89")

Problems Galore with GetHostEntry()

Problem #1

I swear that I thought I must be going crazy, or that there is a bug in one of the System.Net.Dns methods!  The results from GetHostEntry() are not the same as from GetHostByAddress().

Try this using the old method:

PS C:\Users\fshields> [System.Net.Dns]::GetHostByAddress("107.63.47.191")

HostName                                Aliases               AddressList
--------                                -------               -----------
107-63-47-191.pools.spcsdns.net         {}                    {107.63.47.191}

Now try the new method:

PS C:\Users\fshields> [System.Net.Dns]::GetHostEntry("107.63.47.191")
Exception calling "GetHostEntry" with "1" argument(s): "No such host is known"
At line:1 char:31
+ [System.Net.Dns]::GetHostEntry <<<< ("107.63.47.191")
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

No, you didn't make a typing mistake. The same IP address resolved in one case and not in another.

GetHostEntry() is overloaded for both a String input and a IPAddress input. So I thought that I'd specifically cast my address as an IPAddress just to ensure that this wasn't the problem:

PS C:\Users\fshields> [System.Net.Dns]::GetHostEntry([System.Net.IPAddress]"107.63.47.191")
Exception calling "GetHostEntry" with "1" argument(s): "No such host is known"
At line:1 char:31
+ [System.Net.Dns]::GetHostEntry <<<< ([System.Net.IPAddress]"107.63.47.191")
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

The strange part is that this only happens with certain IP addresses such as 107.63.47.191 or 187.210.78.116. Most other IP addresses resolve fine.

Upon further investigation of the MSDN documentation, I discover that the GetHostEntry() method first does a reverse lookup on the IP address to find a host name (from the DNS PTR record), then it does a forward lookup on that host name (from the host name's DNS A record) to populate the AddressList property. However, if the forward lookup fails (due to lack of a DNS A record) then the method bombs out with an Exception and doesn't return an object!

I can't go into all the reasons why this is complete bogus, but suffice it to say that there are legitimate reasons why a DNS PTR record would not have a corresponding A record. In fact, this is rather common on the Internet.

Problem #2

If the IP address you are using is a non-routable one (one of the private IP addresses: 10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16) then thow out everything I just said above. For some reason, it returns the IP address as the HostName:

PS C:\Users\fshields> [System.Net.Dns]::GetHostEntry("192.168.1.1")

HostName                                Aliases               AddressList
--------                                -------               -----------
192.168.1.1                             {}                    {192.168.1.1}

Problem #3

If you pass it an empty String, it will return the NETBIOS name of the local computer!

PS C:\Users\fshields> [System.Net.Dns]::GetHostEntry("")

HostName                                Aliases               AddressList
--------                                -------               -----------
MyPC                                    {}                    {192.168.1.100}

While this may seem to be a convenient way to get the host name, it really sucks if you are processing a list of IP addresses and some of them are blank.

Conclusion

What to do? Really, you have no choice but to use the soon-to-be "obsolete" GetHostByAddress(). Sorry.

Comments (6) -

Wael
Wael
1/2/2013 11:08:39 PM #

I have the same exact problem, I can't figure a way to solve it.

Al Feersum
Al Feersum
3/17/2013 1:11:38 AM #

I wanted a method to resolve IPs to hostnames with PowerShell.  First stop, Google.  About the 5th entry down, I came across your blog.

You're right, the GetHostEntry is great when it works, but it's pretty poor when it doesn't.

GetHostByAddress doesn't seem to want to play nice either.

OK, so it's lazy, but it works.

Function ResolveAddress {

    Param($IP)
    
    try {
        $Resolved = [system.net.dns]::GetHostEntry([system.net.ipaddress]$IP).HostName
    }
    catch {
        $Resolved = ((&nslookup $IP)|where {$_ -match "^Name:"}).split(':')[1].trim()
    }
    return $Resolved
}

ResolveAddress 157.55.36.39

Al Feersum
Al Feersum
3/17/2013 1:23:43 AM #

Better...

Function ResolveAddress {

    Param($IP)
    
    try {$Resolved = [system.net.dns]::GetHostEntry([system.net.ipaddress]$IP).HostName}
    catch {
        try {$Resolved = (&nslookup $IP 2>$null)
            $Resolved = ($Resolved|where {$_ -match "^Name:"}).split(':')[1].trim()}
        catch { $Resolved = "Unable to resolve" }
    }
    return $Resolved
}

ResolveAddress 254.222.194.224

Al Feersum
Al Feersum
3/17/2013 9:19:42 AM #

Better again...


Function ResolveAddress {
    Param([string]$IP)
    
    [bool]$IPv6 = ($IP -match "^[a-z0-9][a-z0-9][a-z0-9][a-z0-9]::")
    try {$Resolved = ([system.net.dns]::GetHostEntry([system.net.ipaddress]$IP)).HostName}
    catch {
        try {
            if (-not($IPv6)) {
                $Resolved = (&nslookup -timeout=1 $IP 2>$null)
                $Resolved = ($Resolved|where {$_ -match "^Name:"}).split(':')[1].trim()
            } else {
                $Resolved = "Unresolvable v6 local address"
            }
        }
        catch { $Resolved = "Unable to resolve" }
    }
    return $Resolved
}

Forrest C. Shields II
Forrest C. Shields II
3/18/2013 8:30:06 PM #

Al,

Thanks for commenting on my article and especially for contributing new code. It will definitely help the others that come here looking for answers.

Al Feersum
Al Feersum
4/12/2013 8:35:40 AM #

Hmm.  More.  Though I suspect that this isn't going to be for everyone....

www.thethinkingman.org/.../...ell-Host-Lookup.aspx

Add comment

  Country flag

biuquotecode
  • Comment
  • Preview
Loading

About the author

Forrest C. Shields II is a Technology Consultant at iServices.com, LLC in Colorado Springs, CO USA. Forrest has worked as a consultant for over 22 years where he specializes in using technology to find solutions to business problems in the small-to-medium sized business sector. His expertise covers the entire spectrum of Microsoft products, including: SharePoint, Exchange, SQL Server, IIS, Hyper-V, and the entire Microsoft Office Suite.

Month List