Invoking WHOIS in PowerShell
Using ARIN's "RDAP" service and some custom parsing, we can now use WHOIS within PowerShell. WHOIS 172.0.0.1?
Sometime last year I needed to identify owner and location information from IPs in log files. IP registries such as ARIN contain owner information for every IP on the internet. In 2015 the RDAP protocol was created allowing registries to pull from other registries and to present data in a standardized API.
With a little bit of splitting, replacing, and custom formatting, RDAPs ‘vCards’ can be extracted and turned into a custom object!
The file can be found at the gist and embedded below.
function Get-RDAPWhois { | |
[CmdletBinding()] | |
Param( | |
[Parameter(Position = 0, Mandatory, HelpMessage = "Enter an IP Address. Both IPv4 and IPv6 are supported", ValueFromPipeline, ValueFromPipelineByPropertyName)] | |
[ValidateScript({ $_ -as [ipaddress] })] | |
[string]$IP ## Mandatory variable: IP address to query. | |
) | |
try { | |
$rdapBaseUrl = "https://rdap.arin.net/registry" ## Set the RDAP url to query. This is the ARIN RDAP server. | |
$rdapUrl = "$rdapBaseUrl/ip/$IP" ## Concatenate the RDAP url with the IP address to query. | |
$restRdap = Invoke-RestMethod -Uri $rdapUrl -ErrorAction Stop ## Invoke the RDAP query and store the results in a variable. | |
if ($restRdap.entities) { | |
# Get the vcard array, which contains non standard json response and must be parsed manually. | |
$vcard = $restRdap.entities.vcardArray | |
$vcardAddress = $vcard[1] | |
$organization = ($vcardAddress | Where-Object { $_ -match 'fn' })[3] | |
$addressLabel = ($vcardAddress | Where-Object { $_ -match 'adr' })[1].Label -replace "`n", ", " | |
$name = $restRdap.name | |
$splitAddress = $addressLabel -split ", " | |
#These are custom regex patterns to match US city and state names. | |
$USCityRegex = "^[a-zA-Z\u0080-\u024F]+(?:. |-| |')*([1-9a-zA-Z\u0080-\u024F]+(?:. |-| |'))*[a-zA-Z\u0080-\u024F]*$" | |
$USStateRegex = "^(?:(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY]))$" | |
$city, $state = $null, $null | |
foreach ($line in $splitAddress) { | |
## If the line matches the regex, and is not "United States", store the line in the $City variable. | |
if (-not $city -and $line -match $USCityRegex) { $city = $line } | |
## If the line matches the regex, store the line in the $State variable. | |
if (-not $state -and $line -match $USStateRegex) { $state = $line } | |
} | |
return [PSCustomObject]@{ | |
Name = $name | |
Organization = $organization | |
Address = $addressLabel | |
City = $city | |
State = $state | |
SplitAddress = $splitAddress | |
IPAddress = $IP | |
} | |
} | |
else { | |
Write-Error "No entities found for IP $IP" | |
} | |
} | |
catch { | |
Write-Error "Error occurred: $_" | |
} | |
} | |
Set-Alias -Name WHOIS -Value Get-RDAPWhois |