#!/usr/bin/env bash

ports=(
	# Known open ports
	80 443
	# Known closed/reject ports
	110
	119
	# Potentially blocked ports
	25	# SMTP
	137-139	# NetBIOS over TCP
	111	# SunRPC Portmapper
	123	# NTP (usually only UDP)
	135	# MS RPC Portmapper
	445	# SMBv2
	1900	# SSDP
	646	# MPLS LDP
	3306	# MySQL
	3389	# MS RDP
	5000	# UPnP
)

ports="${ports[*]}"
ports="${ports// /,}"

targets=("$@")

nmap=(
	# Slightly rate-limit probes so that we don't miss any ICMP errors.
	--scan-delay 0.2s
)

for target in "${targets[@]}"; do
	sudo nmap --reason "${nmap[@]}" -p "$ports" "$target" | awk '
	BEGIN {
		GRN = "\033[92m"
		YLW = "\033[93m"
		RED = "\033[91m"
		BLK = "\033[90m"
		CLR = "\033[m"
	}
	/^PORT/ { table = 1 }
	/^$/    { table = 0 }
	!table  { print "  " $0 }
	table {
		should_be_open = ($1 == "80/tcp" || $1 == "443/tcp")

		if ($2 == "open") {
			if (should_be_open) {
				print GRN "✔ " $0 BLK " (correctly open)" CLR
			} else {
				print YLW "! " $0 CLR " (unexpected open)"
			}
		}
		else if ($2 == "filtered" && $4 == "no-response") {
			print RED "? " $0 CLR " (dropped by firewall)"
		}
		else if ($2 == "filtered" && $5 == "from") {
			# Reject by a different host
			print RED "! " $0 CLR
		}
		else if ($2 == "filtered" && $4 == "admin-prohibited") {
			# Reject by the host itself
			if (should_be_open) {
				print RED "! " $0 CLR " (unexpected filter)"
			} else {
				print GRN "✔ " $0 BLK " (correctly rejected)" CLR
			}
		}
		else if ($2 == "filtered") {
			# Supposedly by the host itself, but wrong code...
			print YLW "! " $0 CLR " (wrong reject type)"
		}
		else if ($2 == "closed") {
			print BLK "- " $0 CLR
		}
		else {
			print "  " $0
		}
	}
	'
done
