I often find myself looking at web logs when researching anomalous traffic on our servers. It’s not uncommon for a poorly written web scraper to come through the system and generate spurious errors, and I start looking at what IP addresses are generating the most hits to see if I can pinpoint who it is.
One of my first steps is run a reverse lookup on the IP to see if there is a PTR record registered in DNS that might identify them. For example, Amazon’s EC2 servers have registered PTR records:
> nslookup 184.169.245.120 Name: ec2-184-169-245-120.us-west-1.compute.amazonaws.com Address: 184.169.245.120
Running nslookup by hand is fine if I need to look up just one or two sites, but sometimes I found myself with a long list of addresses that I want to look up. I could easily write a script around nslookup, but the output was too verbose (usually 5 or 6 lines per IP address) to easily scan through the results.
I also wanted to take it a step further than just a PTR lookup. Many IPs have no PTR record, but over time I have accumulated a list of IPs that I have identified and recognize. For example, I have a long list of Akamai servers that are frequently intermediate nodes for traffic on our Akamai urls. I also have the IPs of proxy servers for several clients that have large numbers of users sharing a single address. I wanted to combine the results of my home-grown list with the reverse lookup in easy-to-use command.
I ended up writing a powershell script to do just that. It takes a list of IPs (or a single IP on a command line), and runs an nslookup. Rather than spitting many lines of output, it parses the results to extract the part I am interested – the name record. It then also checks the IP address against my known list of IPs, and then finally outputs it in a tab-delimited, easy-to-read format with one IP per line:
> ip_lookup.ps1 -k knownips.txt -f input_ips.txt 204.236.179.177 ec2-204-236-179-177.us-west-1.compute.amazonaws.com 204.236.188.194 ec2-204-236-188-194.us-west-1.compute.amazonaws.com 204.236.188.206 ec2-204-236-188-206.us-west-1.compute.amazonaws.com 209.170.118.215 NOT FOUND Akamai 216.246.87.201 unknown.scnet.net Akamai 50.18.0.118 ec2-50-18-0-118.us-west-1.compute.amazonaws.com
As I run the tool looking at different issues, I learn about new IPs and add them to my known IP list, saving me troubleshooting time in the future.
Here is the powershell script:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$stop = $args.Count | |
$inputIP = "" | |
$inputFile = "" | |
$knownIPFile = "" | |
$showUsage = 0 | |
$verbose = 0 | |
for ($i = 0; $i -lt $stop; $i++) | |
{ | |
if ($args[$i] -eq "-f") { | |
if ( ($i + 1) -eq $stop) { | |
$showUsage = 1 | |
} | |
else { | |
$i++ | |
$inputFile = $args[$i] | |
} | |
} | |
elseif ($args[$i] -eq "-k") { | |
if ( ($i + 1) -eq $stop) { | |
$showUsage = 1 | |
} | |
else { | |
$i++ | |
$knownIPFile = $args[$i] | |
} | |
} | |
elseif ($args[$i] -eq "-verbose") { | |
$verbose = 1 | |
} | |
else { | |
if ( ($i + 1) -eq $stop) { | |
$inputIP = $args[$i] | |
} | |
else { | |
$showUsage = 1 | |
} | |
} | |
} | |
if ($stop -eq 0) { | |
$showUsage = 1 | |
} | |
if ($showUsage) { | |
Write-Host "Usage: ip_lookup.ps1 [-multiline] [-k <KNOWN_IP_FILE] -f <FILENAME>" | |
Write-Host " ip_lookup.ps1 [-multiline] [-k <KNOWN_IP_FILE] <IP_ADDRESS>" | |
Write-Error "Bad Input" | |
exit | |
} | |
$knownIPs = @{} | |
function LoadKnownIPs($knownIPList) | |
{ | |
# File should be IP<TAB>Description | |
$reader = [System.IO.File]::OpenText($knownIPList) | |
$line = $reader.ReadLine() | |
while( $line) | |
{ | |
$result = $line.Split("`t") | |
if ($result.Count -le 2) { | |
$knownIPs[$result[0].Trim()] = $result[1] | |
} | |
else { | |
Write-Output ("–" + $result[0].Trim() + "–") | |
Write-Output "Error at $line with " + $result.Count | |
} | |
$line = $reader.ReadLine() | |
} | |
$reader.Close() | |
} | |
if ( $knownIPFile -ne "" ) { | |
LoadKnownIPs($knownIPFile) | |
} | |
function LookupIP($ip) { | |
$result = nslookup $ip 2> $null | select-string –pattern "Name:" | |
if ( ! $result ) { $result = "" } | |
$result = $result.ToString() | |
if ($result.StartsWith("Name:")) { | |
$result = $result.Split() | |
$result = $result[$result.Count -1 ] | |
} | |
else { | |
$result = "NOT FOUND" | |
} | |
$knownMatch = "" | |
if ($knownIPs.ContainsKey($ip)) { | |
$knownMatch = $knownIPs[$ip] | |
} | |
if ($verbose) { | |
Write-Output $ip | |
Write-Output $result | |
Write-Output $knownMatch | |
} | |
else { | |
Write-Output "$ip `t $result `t $knownMatch" | |
} | |
} | |
if ( $inputFile -ne "") { | |
$reader = [System.IO.File]::OpenText($inputFile) | |
$line = $reader.ReadLine() | |
while( $line) | |
{ | |
LookupIP $line.Trim() | |
$line = $reader.ReadLine() | |
} | |
$reader.Close() | |
} | |
else { | |
LookupIP $inputIP | |
} |
Or you can download it directly from GitHub at https://gist.github.com/jrothmanshore/2656003.
Nice work1
Would be better without the null error on PS cmdline PIPE to file, but it still works!!!
It worked. THANKs.
What is knownips.txt for ?
It allows you to maintain a list of IP addresses that you recognize that may not have an associated reverse IP looked or the reverse may give cryptic information. It’s useful if you do this regularly and want to avoid researching mysterious IP addresses multiple times because you forgot what they were.
Seems the script was pulled down?
Odd, thank you for bringing that to my attention. The link to the script was there, and I’m not sure why it stopped displaying it. I updated the post and it has magically re-appeared.
🙂 !!! Worked like a charm. I was about to write my own reverse lookup by IP and found your script while researching. Thanks for sharing your work 🙂 made my day easier !!
Absolute legend, I tried to use other scripts like this one here:
http://community.spiceworks.com/scripts/show/1201-powershell-script-dns-forward-lookup-script-with-auto-generate-excel-file
I substituted the “GetHostAddresses” with “GetHostByAddress” and turned off the piping into Add-Member, but although it works pretty well, if $FWDIP is $null, when you change the for loop to have an if else statement, the variable $FWDIP never saves the $null value, plus if it is $null or leads to an error… then it takes soo long to execute.
This script on the other hand is bad ass and does all the hard leg work for you. Thanks for sharing this with the world, you my friend are a legend! 😀
Doesn’t work
Never mind… Mybad
nice work – even for me as a total newbie it worked fine.
I have a huge list of IP-Adresses I want to lookup. is there a way to write/save the output directly to a file?
Thanks!
You should be able to redirect the output using the standard “>” character.
Thanks!
Thanks a bunch. This will save me loads of time each week.
Forgive my ignorance, but I am new to PS and am having problems executing this script against my list of IPs. Could you please advise how to correctly run this script and which where the IP list file needs to be located? much appreciated
Just put the two files in the same directory as the script, and then run it like this: ip_lookup.ps1 -k knownips.txt -f input_ips.txt
i cant understand. show me error
./ip_lookup.ps1: line 1: =: command not found
./ip_lookup.ps1: line 2: =: command not found
./ip_lookup.ps1: line 3: =: command not found
./ip_lookup.ps1: line 4: =: command not found
./ip_lookup.ps1: line 5: =: command not found
./ip_lookup.ps1: line 6: =: command not found
./ip_lookup.ps1: line 7: syntax error near unexpected token `(‘
./ip_lookup.ps1: line 7: `for ($i = 0; $i -lt $stop; $i++)’
Worked great! Thank you, very much!!