Last Update: Sep 04, 2024 | Published: May 13, 2015
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. What's really interesting is what I can do with the proxy object. Pipe the object to Get-Member and discover its methods. 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. It looks like all I need to do is give it an IP address as a parameter. Let's test.
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. 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. That is very useful. I could combine this with other PowerShell commands.
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. I probably need to drill down a bit further. 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.
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.