How to check a bulk of ip for reverse dns?

xargs provides an optin --arg-file. With -L1 option to treat each line as argument, the simplest command we can make is as follows

$ xargs -L1 --arg-file=ip-addr.txt dig +short -x
google-public-dns-a.google.com.
resolver2.opendns.com.

If it's necessary to display the IP address next to the resolved domain, we can also do:

$ xargs -L1 --arg-file=ip-addr.txt sh -c 'printf "%s: " "$1"; dig +short -x "$1"' sh
8.8.8.8: google-public-dns-a.google.com.
208.67.220.220: resolver2.opendns.com.

Of course, xargs is an extra process. What if we wanted to only use shell and dig ? With bash version 4 and over, we can use mapfile or readarray to get lines of the text file into array, and then process items in a loop:

$ mapfile -t -d $'\n' < ip-addr.txt
$ for i in "${MAPFILE[@]}" ; do printf "%s:" "$i"; dig +short -x "$i"; done
8.8.8.8:google-public-dns-a.google.com.
208.67.220.220:resolver2.opendns.com.

If the IP addresses are few and don't require a long text file, POSIXly, we could use set to define values as positional parameters:

$ set -- 8.8.8.8 208.67.220.220
$ for i ; do printf "%s:" "$i"; dig +short -x "$i"; done
8.8.8.8:google-public-dns-a.google.com.
208.67.220.220:resolver2.opendns.com.

We can also use dig -x $IP_ADDRESS +short in a script like so:

#!/bin/bash
export LC_ALL=C
# without specifying 'in' part, bourne-like shells default
# to iterating over positional parameters
for item
do
     domain=$(dig -x "$item"  +short)
     # this logic can also be reversed with
     # [ "x$domain" = "x" ] && echo "empty" || echo "$domain"
     if [ -n "$domain"  ] ;
     then
         echo "$domain"
     else
         echo "$item" result is NULL
     fi
done

Demo of sample usage(all ip addresses given as space separeted):

$ ./reverse_dns_lookup.sh 8.8.8.8 74.125.193.94 151.101.193.69                 
google-public-dns-a.google.com.
ig-in-f94.1e100.net.
151.101.193.69 result is NULL

As you can see , in the last example our DNS server didn't find domain for the ip address we gave it. In such case we can use a different DNS server, for instance open_dns with dig @208.67.220.220 $IP_ADDRESS +short

In the demo above, the ip addresses are provided on command line, like ./reverse_dns_lookup.sh ADDRESS1 ADDRESS2 ADDRESS2 but you also can use a file for that, like so:

$ cat ip_addresses.txt |  xargs ./reverse_dns_lookup.sh                          <
google-public-dns-a.google.com.
resolver2.opendns.com.
192.30.253.112 result is NULL

Alternative script version:

Here's alternative version of the script that prints the AUTHORITY section from dig's output. This may be much better and more reliable than just +short version. NOTE: this uses 8.8.8.8 , which is Google's public DNS. Use a different server if you feel necessary.

#!/bin/bash
export LC_ALL=C
for item
do
 domain=$(dig @8.8.8.8  -x "$item" +noall +authority +answer)
 if [ -n "$domain"  ] ;
 then
     echo "$domain"
 else
     echo "$item" result is NULL
 fi
done

Demo:

$ cat ip_addresses.txt |  xargs ./reverse_dns_lookup.sh 

; <<>> DiG 9.10.3-P4-Ubuntu <<>> @8.8.8.8 -x 8.8.8.8 +noall +authority +answer
; (1 server found)
;; global options: +cmd
8.8.8.8.in-addr.arpa.   21390   IN  PTR google-public-dns-a.google.com.

; <<>> DiG 9.10.3-P4-Ubuntu <<>> @8.8.8.8 -x 208.67.220.220 +noall +authority +answer
; (1 server found)
;; global options: +cmd
220.220.67.208.in-addr.arpa. 6674 IN    PTR resolver2.opendns.com.

; <<>> DiG 9.10.3-P4-Ubuntu <<>> @8.8.8.8 -x 192.30.253.112 +noall +authority +answer
; (1 server found)
;; global options: +cmd
253.30.192.in-addr.arpa. 10 IN  SOA ns1.p16.dynect.net. ops.github.com. 6 3600 600 604800 60

Here is a quick and dirty one liner: Contents of ip-addresses.txt:

$ cat ip-addresses.txt
    1.2.3.4
    1.1.1.1
    222.222.222.222
    23.12.34.56
    8.8.8.8
    208.67.222.220

Replace txt with your file that contains addresses, separated by newlines:

$ cat ip-addresses.txt | xargs -I % bash -c 'echo "%:$(dig -x % +short)"' >> dig-output.txt

If you append to dig-output.txt like above, contents of that file will be like below, if reverse DNS lookup is successfull, IP:NAME, if not, IP:(NULL)

$ cat dig-output.txt
1.2.3.4:
1.1.1.1:
222.222.222.222:
23.12.34.56:a23-12-34-56.deploy.static.akamaitechnologies.com.
8.8.8.8:google-public-dns-a.google.com.
208.67.222.220:resolver3.opendns.com.

If IP addresses are coming from another process, you can directly pipe to xargs.

Edit: If you must have a word such as null (inspired by @Serg) in case of a lookup failure, you can use the command below:

$ cat ip-addresses.txt | xargs -I % bash -c '{ query=$(dig -x % +short); if [ -z $query ]; then query=null;fi; echo %:$query; }'
  • cat ip-addresses.txt # Print IP addresses to STDOUT. If you don't want to cat from file, you can directly pipe from another process like command | xargs ...
  • xargs -I % bash -c # Take each line from left of pipe, use % as placeholder, run bash command that follows within single quotes
  • dig IP address that comes from placeholder % by xargs, assign to variable query. If result happens to be null (zero length), assign string 'null' word to query variable, then print as IP:result

Demo:

$ cat ip-addresses.txt | xargs -I % bash -c '{ query=$(dig -x % +short); if [ -z $query ]; then query=null;fi; echo %:$query; }'
1.2.3.4:null
1.1.1.1:null
222.222.222.222:null
23.12.34.56:a23-12-34-56.deploy.static.akamaitechnologies.com.
8.8.8.8:google-public-dns-a.google.com.
208.67.222.220:resolver3.opendns.com.

nmap

You can just

 nmap -R -sL -Pn 1.2.3.0/24 | grep '('
  • -n/-R Never do DNS resolution/Always resolve [default: sometimes]
  • -sL List Scan - simply list targets to scan
  • -Pn Treat all hosts as online -- skip host discovery. Remove this to get just what respond to ping.

The grep leave just resolved reverse DNS and some useful lines.

Add --dns-servers x.x.x.x to use a specific DNS server.