Bash: Reverse DNS Lookup of Active IP Addresses

I have a one-line command that lists the top 10 most active IP addresses from a web server access log:

cat access.log | awk '{print $1}' | sort | uniq -c | sort -n | tail -n10

A sample result set (with only 3 entries for simplicity) would be:

20 12.34.56.7
22 3.67.89.201
29 9.0.203.255

As you can see, the count precedes the IP address, with the two separated by a blank space. There are actually blank spaces preceding the count too but I can't get them to show here.

I like to do a reverse DNS lookup of the IP addresses so that it will look like this:

20 12.34.56.7 (d12-34-56-7.abhsia.telus.net)
22 3.67.89.201 (customer.vpls.net)
29 9.0.203.255 (9-0-203-255.hlrn.qwest.net)

How can I do this without resorting to a script (that is, sticking to a one-line command)? Any advice is much appreciated.


Solution 1:

You can use dig +noall +answer -x <IP> to look up an IP address.

To simply loop over a file that contains a list of IP addresses:

while read ip; do dig +noall +answer -x $ip; done < ips.txt

Or, pipe the output of your counting command. This time we get the count and the IP addresses separately and then print them on one line:

cat access.log | awk '{print $1}' | sort | 
uniq -c | sort -n | tail -n10 |
while read count ip; do printf "%d " $count; printf "%s " $ip; dig +noall +answer -x $ip; done

Example (sorry for the UUOC):

cat test | while read count ip; do printf "%d " $count; printf "%s " $ip; dig +noall +answer -x $ip; done
20 8.8.8.8 8.8.8.8.in-addr.arpa.    52767   IN  PTR google-public-dns-a.google.com.
22 8.8.4.4 4.4.8.8.in-addr.arpa.    61369   IN  PTR google-public-dns-b.google.com.

You can further pipe dig's output into awk to just get the host name:

cat test | while read count ip; do printf "%d " $count; printf "%s " $ip; echo $(dig +noall +answer -x $ip | awk '{ print $(NF) }'); done
20 8.8.8.8 google-public-dns-a.google.com.
22 8.8.4.4 google-public-dns-b.google.com.