176 lines
3.2 KiB
Bash
Executable file
176 lines
3.2 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
function echoerr { echo "$@" 1>&2; }
|
|
|
|
### Parse attributes ###
|
|
|
|
INPUT=""
|
|
DEBUG=false
|
|
PORT_RANGE="1-65535"
|
|
NMAP_ARGS=""
|
|
KNOWN_PORTS=()
|
|
IPv=""
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-h|--host) HOST="$2"; shift;;
|
|
-p|--portrange) PORT_RANGE="$2"; shift;;
|
|
-k|--known) KNOWN_PORTS+=($2); shift;;
|
|
-d|--debug) DEBUG=true;;
|
|
-4|--ipv4) IPv="";;
|
|
-6|--ipv6) IPv="-6";;
|
|
-i|--input)
|
|
INPUT="$2"
|
|
if [ ! -f "$INPUT" ]; then
|
|
echoerr "The specified input file '$INPUT' does not exist"
|
|
exit 3
|
|
fi
|
|
shift;;
|
|
--) shift; NMAP_ARGS="$@"; shift $#;;
|
|
-?|--help)
|
|
echo "Check nmap portscan. Arguments:"
|
|
echo "--host HOSTNAME/IP: Host that shall be scanned by nmap"
|
|
echo "--portrange RANGE: Ports that shall be scanned (nmap format)"
|
|
echo "--known PORTNUMBER: Port number that is expected to be open"
|
|
echo "--ipv6: Use IPv6 for the scan (IPv4 if not specified)"
|
|
exit 0
|
|
;;
|
|
*)
|
|
echoerr "Unknown argument: $1"
|
|
exit 3
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ -z "$HOST" -a -z "$INPUT" ]; then
|
|
echoerr "Missing host argument (-h)"
|
|
exit 3
|
|
fi
|
|
|
|
if ! command -v nmap &> /dev/null; then
|
|
echoerr "Missing nmap executable"
|
|
exit 3
|
|
fi
|
|
|
|
function log {
|
|
if $DEBUG; then
|
|
echo " > $@"
|
|
fi
|
|
}
|
|
function logLine {
|
|
if $DEBUG; then
|
|
echo " : $@"
|
|
fi
|
|
}
|
|
NL=$'\n'
|
|
|
|
log "INPUT: $INPUT"
|
|
log "PORT_RANGE: $PORT_RANGE"
|
|
log "KNOWN_PORTS: ${KNOWN_PORTS[@]}"
|
|
|
|
function runNmap {
|
|
local $portrange
|
|
if [ -n "$PORT_RANGE" ]; then
|
|
portrange="-p$PORT_RANGE"
|
|
else
|
|
portrange=""
|
|
fi
|
|
|
|
local $input
|
|
if [ -n "$INPUT" ]; then
|
|
while read -r line; do
|
|
parseLine "$line"
|
|
done < $INPUT
|
|
else
|
|
local $cmd
|
|
cmd="nmap $portrange $IPv $NMAP_ARGS -- $HOST"
|
|
log "$cmd"
|
|
while read -r line; do
|
|
parseLine "$line"
|
|
done <<< $($cmd)
|
|
result=$?
|
|
log "nmap exited with $result"
|
|
if [ $result -ne 0 ]; then
|
|
echoerr "CRITICAL - nmap exited with $result"
|
|
exit 2
|
|
fi
|
|
fi
|
|
}
|
|
|
|
NOW_PORTS=false
|
|
PORT_STATES=()
|
|
PORT_NAMES=()
|
|
function parseLine {
|
|
local line="$1"
|
|
if ! $NOW_PORTS; then
|
|
if [[ "$line" == PORT*STATE*SERVICE ]]; then
|
|
NOW_PORTS=true
|
|
fi
|
|
else
|
|
if [ -z "$line" ]; then
|
|
NOW_PORTS=false
|
|
else
|
|
local split
|
|
read -ra split <<< "$line"
|
|
local number=${split[0]/\/*}
|
|
local state=${split[1]}
|
|
local name=${split[2]}
|
|
PORT_STATES[$number]=$state
|
|
PORT_NAMES[$number]=$name
|
|
fi
|
|
fi
|
|
}
|
|
|
|
ERROR=false
|
|
UNEXP_OPEN_PORTS=()
|
|
function comparePorts {
|
|
log ${KNOWN_PORTS[@]}
|
|
KNOWN_PORTS=($(for each in ${KNOWN_PORTS[@]}; do echo $each; done | sort))
|
|
log ${KNOWN_PORTS[@]}
|
|
|
|
for port in "${!PORT_STATES[@]}"; do
|
|
if [[ "${PORT_STATES[$port]}" != open* ]]; then
|
|
continue;
|
|
fi
|
|
|
|
skip=false
|
|
for j in "${KNOWN_PORTS[@]}"; do
|
|
if [ $j -eq $port ]; then
|
|
skip=true
|
|
break
|
|
fi
|
|
done
|
|
if ! $skip; then
|
|
log Unexpected open port: $port
|
|
UNEXP_OPEN_PORTS+=($port)
|
|
fi
|
|
done
|
|
if [ ${#UNEXP_OPEN_PORTS[@]} -gt 0 ]; then
|
|
ERROR=true
|
|
fi
|
|
}
|
|
|
|
function print {
|
|
if $ERROR; then
|
|
echo -n "CRITICAL - These ports should not be open: ${UNEXP_OPEN_PORTS[@]}"
|
|
else
|
|
echo -n "OK"
|
|
fi
|
|
|
|
echo -n " | "
|
|
|
|
for port in "${!PORT_STATES[@]}"; do
|
|
echo -n "'${PORT_NAMES[$port]} ($port): ${PORT_STATES[$port]}'=0 "
|
|
done
|
|
}
|
|
|
|
runNmap
|
|
comparePorts
|
|
print
|
|
|
|
if $ERROR; then
|
|
exit 2
|
|
else
|
|
exit 0
|
|
fi
|
|
|