#!/usr/bin/env bash # # nwatch(1) -- Slightly friendlier version of the suggested script in the # manual page for ndiff(1) from the Nmap suite, implemented in Bash. # # Usage: # $ nwatch HOSTLIST CACHEDIR # Example with root privileges: # # nwatch /etc/nwatch.mynet /var/cache/nwatch/mynet # # Prints the results of an ndiff(1) call against the last known scan to stdout; # intended to be called from cron(8): # 0 0 * * 0 nwatch /etc/nwatch.mynet /var/cache/nwatch/mynet # # I recommend you use Mail::Run::Crypt, so you don't leak your network # information in plain text in your email: # # # Please also consider whether your scan actually requires root privileges, and # could not instead be run by a dedicated user with appropriately limited # privileges. # # Author: Tom Ryder # Copyright: 2014 # License: GPLv2 (same as Nmap itself) # # Defensive umask by default; change at your own risk! umask 0077 # Some fixed values self=nwatch hostlist=${1:?} cachedir=${2:?} latest=$cachedir/${self}.scan.latest # If the cachedir doesn't exist, attempt to create it, otherwise give up if [[ ! -d "$cachedir" ]] ; then if ! mkdir -- "$cachedir" ; then exit 1 fi fi # Today's values date=$(date +%s) cache=$cachedir/${self}.scan.${date} diff=$cachedir/${self}.diff.${date} # Run the scan or give up if ! nmap -v -T4 -sV --open -iL "$hostlist" -oA "$cache" >/dev/null ; then exit 1 fi # If the link to the XML file is legible, run the diff or give up if [[ -r ${latest}.xml ]] ; then ndiff -- "$latest".xml "$cache".xml > "$diff" # Because we always want a report, only exit if an actual error condition # (1 means there's a meaningful diff in the scans) if (($? == 2)) ; then exit 1 fi fi # Create or update the links rm -f "${cache/$date/latest}".* for cachetype in "$cache".* ; do ln -s -- "$cachetype" "${cachetype/$date/latest}" done # Write diff to stdout if it exists (not an error if it doesn't) if [[ -r $diff ]] ; then awk ' /^[-+]Not shown: / { next } /^[-+]/ { diff = 1 } NF { lines[++l] = $0 } function write() { if (diff) { for (n = 1; n <= l; n++) print lines[n] print "" diff = 0 } l = 0 } !NF { write() } END { write() } ' -- "$diff" fi