Linux host discovery with Nmap
Not everyone has the budget to buy an expensive software suite to do host discovery on the network. Fortunately there are some great open source alternatives. By combining the right tools we can discover hosts and filter the ones we are looking for.
In this article we have the goal to determine what systems on our network are running Linux. Of course it is easy to swap out some pieces in the examples to do the same for Windows, Mac OS or BSDs.
Setting up the toolkit
First of all we need to install the proper tools. For our toolkit and this article, these are:
- nmap
- xmllint
For both tools it is better to have one of the latest versions. This is especially true for a better precision of the host detection capabilities in nmap.
Debian/Ubuntu:
apt install nmap libxml2-utils
After installation check if both commands work, so we are sure they are available.
Scan the network
Next step is to scan the network. Since we want to know the operating system, we use the -O option with Nmap. For best results we save the data in a XML file, so we can query that later and extract the data we need.
nmap -O -oX nmapscan.txt 10.0.1.1/16
It might take nmap a while to scan the network. To see the progress press enter and it will show an estimated guess on how far it analyzed the network, discovered hosts and related services.
Parse the data
After a while Nmap is finished and we are ready to look at the scan results. With the data already being exported in XML, we can easily parse the data.
In our case we want to show only the systems which are most likely running Linux. Since we are interested in the IP addresses for further follow-up, we only list entries which have an actual IPv4 address. So we search the XML file for Host entries, where the Status has a value “up” for the state field. Additionally we want only the entries within Os, which fall under the OS family of Linux. For these entries we check if there is a IPV4 filled in and then show it on screen.
echo "xpath //host[status[@state='up'] and os[osmatch/osclass[@osfamily='Linux']]]/address[@addrtype='ipv4']/@addr" | xmllint --shell nmapscan.txt
The output might look like this:
While no option is 100% precise, we consider a system to be “Linux” if the osfamily key is set to this value. Some false positives might show up, like appliances which also run Linux. With the gathered data it is usually easy to determine if we have “strange” machine, for example when doing a reverse lookup on the IP address.
For easier export of the data to a file, use a grep together awk, and we have our list of systems running Linux.
echo "xpath //host[status[@state='up'] and os[osmatch/osclass[@osfamily='Linux']]]/address[@addrtype='ipv4']/@addr" | xmllint --shell nmapscan.txt | grep "content=" | awk -F= '{ print $2 }'
With this information we can run a script against this list to check if SSH is accessible, do reverse lookups, or simple store them for later analysis.