8

Is there a way to check to reverse DNS check for loads of IPs, I have a list of IP I want to check?

I know you're are able to do these individually:

host <ip-address>

and

dig -x <ip-address>

Also, is there a way to export them?

2
  • Yes, very much possible. I'll write a small script in a minute. Please wait Aug 17, 2016 at 9:17
  • You can use Nirsoft FastResolver on Windows Oct 6, 2018 at 11:47

4 Answers 4

10

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
10
  • Sorry for my ignorance but where in the script do I define the list of the IPs?
    – Yen Deng
    Aug 17, 2016 at 9:47
  • @YenDeng the IP addresses are given on command line. I'll add a little more info about that in a second. Aug 17, 2016 at 9:50
  • @YenDeng I added more info to the answer. Also added alternative script version. That should be more reliable Aug 17, 2016 at 10:03
  • Hi Serg, sorry for being annoying. It says that ./reverse_dns_look.sh: /bin/bash^M: bad interpreter: No such file or directory Unsure what is wrong with this
    – Yen Deng
    Aug 17, 2016 at 10:36
  • 1
    @YenDeng You need to be in the folder where both ip_addresses.txt and ./reverse_dns_lookup‌​.sh resides. If you omit ./ before script name, it won't run, even if it is executable. Because it is not in your environment variable (PATH).
    – user311189
    Aug 17, 2016 at 14:45
4

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.
5
  • How would I export the results?
    – Yen Deng
    Aug 17, 2016 at 11:50
  • Do you intend to save to a file?
    – user311189
    Aug 17, 2016 at 11:50
  • Yes, if that's possible
    – Yen Deng
    Aug 17, 2016 at 11:51
  • Simply append >> my-log-filename.txt to the end of the command.
    – user311189
    Aug 17, 2016 at 11:53
  • 1
    @YenDeng I edited my answer and fixed some stuff. Might be more useful now.
    – user311189
    Aug 17, 2016 at 14:39
3

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 like 1.1.1.1.

1

Inspired by the shell example shown in another answer I decided a Perl version suited me better so I created this file "batch_dns_by_ip.pl". You put a list of IP address in a text file that you will pipe into the program.

The code should look like this and you will want to make the file executable:

#!/usr/bin/perl
use strict;
my @domains;
my $address;
while (<>) {
  chomp;
  $address = $_;
  $address =~ s/ *//g;
  @domains = ();
  @domains = `dig -x "$address" +short`;
  chomp(@domains);
  if ( "$domains[0]" eq "" ) {
    $domains[0] = "NULL";
  }
  printf( "addr: %15s names: %s", $address, $domains[0] );
  if ( "$domains[1]" eq "" ) {
    print "\n";
  }
  else {
    printf( ", %s\n", $domains[1] );
  }
}

A run might look like this:

$ cat myips | ./batch_dns_by_ip.pl
addr:  216.58.219.238 names: lga25s41-in-f14.1e100.net., lga25s41-in-f238.1e100.net.
addr:  151.101.129.69 names: NULL
addr:         8.8.8.8 names: google-public-dns-a.google.com.
addr:     10.49.11.62 names: nyalbdnsvip01.miscny.nyenet., nyalbcwgbvip01-vlan401.miscny.nyenet.
addr:  69.172.201.153 names: NULL

I hope that helps!

1
  • This works, but note that the input file must have have each IP on its own separate line.
    – devius
    Feb 21, 2018 at 11:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .