Monday, April 2, 2007

Using nmap to Generate Host Lists

An easy way to get a list of hosts from a single domain that you are a part of, is to query DNS

host -l mydomain.com

But that is not always practical. Sometimes you have machines that are in different domains, but they all are part of a network you manage. Rather than trying write a script that pings hosts and reports the output, just use nmap for a very fast scan.

To scan all hosts in a list of subnets

1) Create a subnets.dat file with one subnet on each line:

$ cat subnets.dat
192.168.0.*
192.168.1.*

2) Run nmap with the subnets.dat file as input

$ nmap -sP -R -iL subnets.dat
Reading target specifications from FILE: subnets.dat

Starting nmap V. 3.00 ( www.insecure.org/nmap/ )
Host (192.168.0.0) appears to be down.
Host box1.mydomain.com (192.168.0.1) appears to be up.
Host box2.mydomain.com (192.168.0.2) appears to be down.
Host box3.mydomain.com (192.168.0.3) appears to be up.
Host (192.168.0.4) appears to be up.
...

Notice how names are resolved for existing hosts, but only an IP is returned, if there is no DNS record (e.g. 192.168.0.0).

3) Write a script to report on the output you want
e.g. for a list of all hosts that respond to ping

$ cat nmap_servers.sh
#!/bin/sh
OUTFILE=hosts_scanned.dat

# clean up old file
[ -f hosts_scanned.dat ] && rm hosts_scanned.dat
echo "nmap -sP -R -iL subnets.dat | grep "to be up" | awk '{print \$2}' "
echo ""

# write all hosts to file, but print only hosts that appear to be up.
nmap -sP -R -iL subnets.dat -oN $OUTFILE | grep "to be up" | awk '{print $2}'

Of course this output can always be redirected to a file, if desired. The output file "hosts_scanned.dat" will contain any host nmap found in DNS, and whether it was up or down.

----------
Sample output after grep and awk:
box1.mydomain.com
box3.mydomain.com
(192.168.0.4)

Notice that I use awk to print the second field. That's because some entries might have an IP address, but not a DNS entry. So the second field is whatever comes after Host, which is either an IP address, or a hostname. In this case, I want to find any IP's without hostnames, so I can fix DNS, but you may want to just keep the ip in the list,so you can ssh to it later.

To get rid of the parenthesis, I redirected the output to hosts_up.dat, and piped the output to grep and awk to illustrate:

cat hosts_up.dat | grep \( | awk -F[\(\)] '{print $2}

More detail on these commands will be posted on http://www.systemnotes.org/linux




2 comments:

Anonymous said...

Creating a subnet.dat file like this:
echo 192.168.1.{1..254} >subnet.dat ?

scottm said...

That was not exactly what I had in mind, Anonymous.
The subnet.dat file does not need to have each host in the subnet, since nmap can take the wildcard input. So nmap would automatically expand 192.168.1.* to each host in the subnet.

Your example creates multiple host entries, when all we need to know is what subnets to scan.

Here is a way to create the subnet.dat file:
$ for i in {1..10}; do echo 192.168.${i}.*;done > subnet.dat

$ cat subnet.dat
192.168.1.*
192.168.2.*
192.168.3.*
192.168.4.*
192.168.5.*
192.168.6.*
192.168.7.*
192.168.8.*
192.168.9.*
192.168.10.*

For further information on this topic, see http://systemnotesorg.blogspot.com/2007/12/ping-multiple-hosts-using-bash-nmap-and.html and http://systemnotesorg.blogspot.com/search/label/for%20loop