Last active
October 4, 2022 15:56
-
-
Save JonathanLPoch/bb958e0069b6cd604d18381215caa253 to your computer and use it in GitHub Desktop.
Lightweight Nmap Topology Scanning
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
DEFAULTNMAPOPTIONS="-T4 -sV -Pn --top-ports 5000 -R" | |
NMAPOPTIONS="$DEFAULTNMAPOPTIONS" | |
die() { | |
printf '\033[38;5;9m%s\033[0m\n\n' "$1" >&2 | |
display_usage | |
exit 1 | |
} | |
user_abort() { | |
printf '\033[38;5;9mAborting.\033[0m\n' | |
exit 0 | |
} | |
display_usage() { | |
printf 'Carve Systems Nmap network scanner.\n' | |
printf 'Usage: ./nmap-diff.sh [options].\n\n' | |
printf 'REQUIRED\n' | |
printf '%s: The input file with an IP list.\n' "-f|-f" | |
printf '%s: Your email address.\n' "-e" | |
printf '%s: The output directory.\n' "-o|--output" | |
printf '%s: Public IP. Set a required public IP to scan from.\n\n' "-i" | |
printf 'OPTIONAL\n' | |
printf '%s: Display this help summary.\n' "-h|--help" | |
printf "%s: Nmap options. Default is \"$DEFAULTNMAPOPTIONS\"\n\n" "-n" | |
printf 'EXAMPLE\n' | |
printf '%s\n\n' "./nmap-diff.sh -f ips.txt -e email@gmail.com -o output/dir/nmap-scanning/ -i 1.2.3.4" | |
} | |
prompt() { | |
printf "%s (y/n)" "$1" | |
read -r reply | |
[ "$reply" == "${reply#[Yy]}" ] && return 1 | |
return 0 | |
} | |
send_mail() { | |
diff=$1 | |
date=$2 | |
email=$3 | |
if prompt "Send mail?"; | |
then | |
printf "Sending %s mail.\n" "$diff" | |
if [ "$diff" = diff ] | |
then | |
if ! printf "Hi,\n\n Note that this is an automated email.\n\nPlease see the following message and attachments for the results of your network topology scan and let us know if you have any questions.\n\n***NDIFF SCAN RESULTS:\n%s and $date***\n\n%s\n\n" "$(readlink scan-prev.xml | cut -d "/" -f1)" "$(tail -n +2 "$date/diff-$date")" | EMAIL="$email" mutt -s "Nmap Scan Results - Periodic Diff Scan" -a "$date/scan-$date.nmap" "$date/diff-$date" -- "$email" > /dev/null; | |
then | |
printf 'Mailing failed - ensure mutt is installed properly. You can find your results in \033[1m%s\033[0m\n' "$output_dir/$date/*" | |
fi | |
else | |
if ! printf "Hi,\n\n Note that this is an automated email.\n\nPlease see the following message and attachments for the results of your network topology scan and let us know if you have any questions.\n\n%s\n\n" "$(tail -n +2 "$date/scan-$date.nmap")" | EMAIL="$email" mutt -s "Nmap Scan Results - Initial Baseline Scan" -a "$date/scan-$date.nmap" -- "$email" > /dev/null; | |
then | |
printf 'Mailing failed - ensure mutt is installed properly. You can find your results in \033[1m%s\033[0m\n' "$output_dir/$date/*" | |
fi | |
fi | |
else | |
printf '\nSkipping - you can find your results in \033[1m%s\033[0m\n\n' "$output_dir/$date/*" | |
fi | |
} | |
while getopts 'e:f:hi:n:o:' OPTION; do | |
case $OPTION in | |
e ) | |
if [ -n "$OPTARG" ]; then | |
EMAIL="$OPTARG" | |
else | |
die 'ERROR: Missing user email.' | |
fi | |
;; | |
f ) | |
if [ -n "$OPTARG" ]; then | |
FILE="$OPTARG" | |
else | |
die 'ERROR: Missing file argument.' | |
fi | |
;; | |
h ) | |
display_usage | |
exit | |
;; | |
n ) | |
if [ -n "$OPTARG" ]; then | |
NMAPOPTIONS=$OPTARG | |
else | |
die 'ERROR: Missing nmap options.' | |
fi | |
;; | |
i ) | |
if [ -n "$OPTARG" ]; then | |
PUBLICIP=$OPTARG | |
else | |
die 'ERROR: Missing public IP.' | |
fi | |
;; | |
o ) | |
if [ -n "$OPTARG" ]; then | |
output_dir=$OPTARG | |
else | |
die 'ERROR: Missing output directory.' | |
fi | |
;; | |
\? ) | |
display_usage | |
exit | |
;; | |
esac | |
done | |
shift "$((OPTIND -1))" | |
if [ -z "$FILE" ] || [ -z "$EMAIL" ] || [ -z "$output_dir" ] || [ -z "$PUBLICIP" ]; then | |
die 'ERROR: Missing required arguments.' | |
display_usage | |
fi | |
if [ -n "$PUBLICIP" ]; | |
then | |
publicip=$(dig @resolver1.opendns.com ANY myip.opendns.com +short) | |
if ! [ "$publicip" = "$PUBLICIP" ]; then | |
printf 'Public IP does not match what was specified. Aborting scan.\n' | |
exit 2 | |
fi | |
fi | |
if ! [ "$FILE" ]; | |
then | |
die 'ERROR: An input file is required.' | |
fi | |
if ! [ -e "$FILE" ]; | |
then | |
die 'ERROR: Invalid input file.' | |
fi | |
if ! [ "$EMAIL" ]; | |
then | |
die 'ERROR: An email is required.' | |
fi | |
if ! [ "$output_dir" ]; | |
then | |
die 'ERROR: An output directory is required.' | |
fi | |
case "$output_dir" in | |
/*) ;; | |
*) output_dir="$(pwd)/$output_dir" ;; | |
esac | |
if [ -d "$output_dir" ]; then | |
dir_exists=true | |
else | |
dir_exists=false | |
fi | |
if [ "$dir_exists" = true ] ; then | |
printf 'Using output directory \033[1m%s\033[0m\n' "$output_dir" | |
if ! prompt "Are you sure?"; then | |
user_abort | |
fi | |
else | |
printf 'Directory does not currently exist. Creating directory %s\n' "$output_dir" | |
if prompt "Are you sure?"; then | |
printf '\nCreating %s...\n' "$output_dir" | |
mkdir -p "$output_dir" | |
else | |
user_abort | |
fi | |
fi | |
printf '\033[1m\nInitiating scan from public IP: %s for the following IPs:\n%s\033[0m\n\n' "$publicip" "$(cat "$FILE")" | |
date=$(date '+%Y-%m-%d %I-%M %p') | |
cd "$output_dir" | |
mkdir -p "$output_dir/$date" | |
if ! nmap $NMAPOPTIONS -iL "../$FILE" -oA "$output_dir/$date/scan-$date" > /dev/null; | |
then | |
die 'ERROR: nmap scan failed. Rerun scan manually.' | |
fi | |
printf 'Nmap scan completed. ' | |
if prompt "Display results?"; then | |
printf '\n\033[1m*** NMAP RESULTS ***\n\n' | |
cat "$date/scan-$date.nmap" | |
printf '\033[0m\n' | |
else | |
printf 'Skipping - you can find your results in %s\n' "$date/scan-$date.*" | |
fi | |
if [ -L scan-prev.xml ]; then | |
printf 'Found previous scan. Performing ndiff...\n\n' | |
ndiff "scan-prev.xml" "$date/scan-$date.xml" > "$date/diff-$date" | |
code=$? | |
echo $code | |
if [ $code -eq 2 ]; | |
then | |
die 'ERROR: ndiff failed. Ensure ndiff is in your PYTHONPATH and try again.\n\n' | |
else | |
if [ $code -eq 0 ]; | |
then | |
printf "No differences detected. " | |
send_mail diff "$date" "$EMAIL" | |
fi | |
if [ $code -eq 1 ]; | |
then | |
printf 'Network changes detected. Please review:\n\n' | |
printf '\033[1m*** NDIFF RESULTS ***\n' | |
cat "$output_dir/$date/diff-$date" | |
printf '\033[0m\n' | |
send_mail diff "$date" "$EMAIL" | |
fi | |
fi | |
printf 'Ndiff scan completed. To automate this process, create a cronjob:\n\n' | |
else | |
send_mail baseline "$date" "$EMAIL" | |
printf 'First scan completed. To automate this process, create a cronjob:\n\n' | |
fi | |
printf '\033[38;5;11m1. crontab -e\033[0m\n' | |
printf '\033[38;5;11m2. Within the crontab:\n# Nmap Scanning - 2AM Daily\n0 2 * * * cd /home/user/nmap-topology-scanner && yes | sh nmap-diff.sh\033[0m\n' | |
ln -sf "$date/scan-$date.xml" scan-prev.xml |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment