PowerShell Problem Solver: Where is that IP?

In a previous PowerShell Problem Solver article, I used PowerShell to convert a ctime value to a proper datetime format. I had a list of IP addresses as part of the same troubleshooting process, and this is something you also might come across in a log file.

I wanted to be figure out where the IP address was coming from. For example, I might have an IPv4 address like this:

​
What is the IP address' country of origin? Fortunately, I knew of a website that provides that information. Although I initially accessed this from the website, I wanted to access this information from PowerShell. To simplify this process, PowerShell 3.0 introduced a new cmdlet called New-WebServiceProxy. You can use the cmdlet to create a special type of object that acts as a proxy to the web service. You don't have to figure out any arcane syntax to use the web service. Everything is exposed as an object that's complete with method members. Let me show you.
First, I need to create the proxy object.
​
Most of the time the proxy properties don't really matter.
Proxy properties in Windows PowerShell. (Image Credit: Jeff Hicks)
Proxy properties in Windows PowerShell. (Image Credit: Jeff Hicks)
What's really interesting is what I can do with the proxy object. Pipe the object to Get-Member and discover its methods.
Piping our proxy object to Get-Member in Windows PowerShell. (Image Credit: Jeff Hicks)
Piping our proxy object to Get-Member in Windows PowerShell. (Image Credit: Jeff Hicks)
You might also need to read any documentation from the associated site about these methods. Instead of trying to construct a URL to invoke these methods, I can use PowerShell and the proxy object. Let's look at the GetGeoIP method.
The GetGeoIP method in Windows PowerShell. (Image Credit: Jeff Hicks)
The GetGeoIP method in Windows PowerShell. (Image Credit: Jeff Hicks)
It looks like all I need to do is give it an IP address as a parameter. Let's test.
Providing an IP address as a parameter for GetGeoIP. (Image Credit: Jeff Hicks)
Providing an IP address as a parameter for GetGeoIP. (Image Credit: Jeff Hicks)
Well that was easy. I should also see what happens when this fails because eventually I'm going to want to use this in a function.
Invalid IP address error with GetGeoIP. (Image Credit: Jeff Hicks)
Invalid IP address error with GetGeoIP. (Image Credit: Jeff Hicks)
I'll keep that in mind. In the meantime, I can try using the returned information to analyze some IP addresses that I have pulled from my log file.
​
Errors were still written to the console, but I was able to successfully resolve a number of addresses. I only tested with a subset of addresses to prove this would work.
IP addresses that we've tested in GridView. (Image Credit: Jeff Hicks)
IP addresses that we've tested in GridView. (Image Credit: Jeff Hicks)
That is very useful. I could combine this with other PowerShell commands.
031815 1718 PowerShellP7
The other piece to the puzzle was that I wanted to know what company or organization owned particular IP address. In other words, I needed some way to do a WhoIs type lookup but from PowerShell.

It turns out this can also be done fromthe web. Instead of a web service, I need to invoke a Rest method using the services described here. This will require using another newer cmdlet called Invoke-RestMethod.
I will need to construct a URI using my test IP address.
​
Next, I can run it.
​
Most of the time, you'll end up with an XML document that's easy to traverse in PowerShell.
031815 1718 PowerShellP8
I probably need to drill down a bit further.
031815 1718 PowerShellP9
It looks like that address is part of a block that belongs to Amazon. Excellent. How about putting all of this together?
#requires -version 3.0
Function Get-GeoIP {
<#
.Synopsis
Get geographic location for a given IPv4 address.
.Description
This command will analyze an IPv4 address and show its related geographic location. You can also show the registered organization.
.Parameter IPAddress
An IPv4 address. This parameter has an alias of IP.
.Parameter WhoIs
Include registered organzation information.
.Example
PS C:\> get-geoip 54.215.12.190
IP                                     CountryName                            CountryCode
--                                     -----------                            -----------
54.215.12.190                          United States                          USA
.Example
PS C:\>  get-geoip 208.67.222.222 -WhoIs | format-list
IP              : 208.67.222.222
CountryName     : United States
CountryCode     : USA
RegisteredOwner : OpenDNS, LLC
.Notes
version: 2.0
updated: March 18, 2015
Learn more about PowerShell:
Essential PowerShell Learning Resources
**************************************************************** * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED * * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF * * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, * * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. * **************************************************************** .Link Invoke-RestMethod New-WebServiceProxy #> [cmdletbinding()] Param( [Parameter(Position=0,Mandatory, HelpMessage="Enter an IPv4 address", ValueFromPipeline,ValueFromPipelineByPropertyName)] [ValidatePattern({\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}})] [Alias("IP")] [string[]]$IPAddress, [switch]$WhoIs ) Begin { Write-Verbose -Message "Starting $($MyInvocation.Mycommand)" #create a web service proxy Write-Verbose "Creating web service proxy" $px = New-WebServiceProxy "http://www.webservicex.net/geoipservice.asmx" #define a quick function to get WhoIs information Function Get-WhoIs { [cmdletbinding()] Param([string]$IP) Write-Verbose "Getting WhoIs org for $IP" $baseURL = 'http://whois.arin.net/rest' $uri = "$baseUrl/ip/$ip" Try { $r = Invoke-Restmethod $uri -ErrorAction Stop #write the registered org name to the pipeline $r.net.orgRef.name } Catch { Write-Warning $_.Exception.Message } } } #begin Process { Foreach ($IP in $IPAddress) { Write-Verbose -Message "Processing $IP" Try { $r = $px.GetGeoIP($IP) #continue processing if the method was successful if ($r.returnCode) { $data = $r | Select IP,CountryName,CountryCode if ($WhoIs) { #Add WhoIs information $data | Add-Member -MemberType NoteProperty -Name RegisteredOwner -Value (Get-WhoIS $IP) -PassThru } else { #write the data to the pipeline $data } } #if returncode = 1 else { Write-Warning "Failed to resolve IP $IP. $($r.ReturnCodeDetails)" #throw an exception so the Catch block will run Throw } } #Try Catch { #If there was an error running Invoke-RestMethod #create a custom object. $data = [pscustomobject]@{ IP = $IP CountryName = "Unknown" CountryCode = "UNK" } if ($WhoIs) { $data | Add-Member -MemberType NoteProperty -Name RegisteredOwner -Value $Null -PassThru } else { $data } } #catch } #foreach } #process End { Write-Verbose -Message "Ending $($MyInvocation.Mycommand)" } #end } #end Get-GeoIP

My Get-GeoIP function by default gets geographic information only.

But I added an optional WhoIs parameter that will include the associated organizational name. Instead of ignoring errors, I included error handling via Try/Catch so I don’t miss any IP addresses. Now I can process a log file like this, assuming the heading is IP or IPAddress.

​
I can now analyze and filter all I want.
Analyzing and filtering our data. (Image Credit: Jeff Hicks)
Analyzing and filtering our data. (Image Credit: Jeff Hicks)
84 unresolved IP addresses. (Image Credit: Jeff Hicks)
84 unresolved IP addresses. (Image Credit: Jeff Hicks)
Looks like there were 84 addresses that I couldn't resolve. But that's my problem. The point is that PowerShell and a few web cmdlets made it easy to analyze raw data and put some meaning to it.