Lippe:Monitoring RAM Datendurchsatz vergebene IPs
Aus wiki.freifunk.net
Zur Navigation springenZur Suche springen
Monitoring des freien Arbeitsspeichers unter Linux
Da der freie Speicher unter Linux aufgrund der Speicherverwaltung anders gemonitort werden muss als unter Windows habe ich das folgende Script verwendet:
!/bin/sh # # Plugin to check system memory # by hugme (nagios@hugme.org) # You can find my checks here: https://github.com/hugme/Nag_checks # Nagios script to check memory usage on linux server # version 1.2.0 # ########################################################## MEMINFO="/proc/meminfo" ########################################################## # We call them functions because they're fun ########################################################## print_help() { cat << EOF Linux Memory Plugin for Nagios Copyright (c) hugme (nagios@hugme.org) Version: 1.2.0 Last Modified: 10-07-2014 License: This software can be used for free unless I meet you, then you owe me lunch. Usage: check_linux_memory -w [warning %] -c [critical %] Options: -w [0-99] = Your warning %. 20 means 20% of your memory can remain before a warning alarm. Do not use the % sign. -c [0-99] = Your critical %. 10 means 10% of your memory can remain before a critical alarm. Do not use the % sign. -d [K,M,G,T] = divider K=kilobytes, M=megabytes, G=gigabytes, T=terabytes -f = Include cached memory as free memory when calculating your percentage free EOF } invalid_type() { echo "\nInvalid $1\n" print_help exit 3 } ############################################## ## Suck in the user input ############################################## while test -n "$1"; do case $1 in --help) print_help ; exit 0 ;; -h) print_help ; exit 0 ;; -w) WARN="$2"; shift ;; -c) CRIT="$2"; shift ;; -d) DIV="$2"; shift ;; -f) FC=1 ;; esac shift done ############################################## ## Set the defaults if needed ############################################## [ -z "$WARN" ] && WARN=20 [ -z "$CRIT" ] && CRIT=10 [ -z "$DIV" ] && DIV=M [ -z "$FC" ] && FC=0 ############################################## ## Check user input ############################################## [ ! -z `echo $WARN | tr -d [:digit:]` ] && invalid_type "Warning: Warning value can only contain numbers" [ ! -z `echo $CRIT | tr -d [:digit:]` ] && invalid_type "Critical: Critical value can only contain numbers" [ "${WARN%.*}" -ge 100 ] && invalid_type "Warning: Warning must be smaller than 100%" [ "${CRIT%.*}" -ge 100 ] && invalid_type "Critical: Critical must be smaller than 100%" [ "${CRIT%.*}" -gt "${WARN%.*}" ] && invalid_type "Critical: Your Warning must be Higher than your Critical" case $DIV in k|K) DIVNUM=1;; m|M) DIVNUM=1024;; g|G) DIVNUM=1048576;; t|T) DIVNUM=1073741824;; *) invalid_type;; esac [ ! -f "$MEMINFO" ] && { echo "Your Memory info file seems to be missing" exit 1 } ############################################## ## Do the work ## Pull the memory file into awk ## grab the lines we need ## Print the information ############################################## RESULT=$(awk -v warn=$WARN -v crit=$CRIT -v div=$DIV -v divnum=$DIVNUM -v fc=$FC '/^MemTotal:/ { total=$2 } /^MemTotal:/ { tot=$2 } /^MemFree:/ { free=$2 } /^Buffers:/ { buff=$2 } /^Cached:/ { cache=$2 } /^Active:/ { active=$2 } /^Inactive:/ { inactive=$2 } END { if ( fc == 1 ) { free=free+cache+buff } { freeperct=free/tot*100 } if ( freeperct > warn ) { result="OK" ; xit="0"} if ( freeperct <= warn ) { if ( freeperct > crit ) { result="WARNING" ; xit="1" } else if ( freeperct <= crit ) { result="CRITICAL" ; xit="2" } } {print xit" MEMORY "result" - "freeperct"% Free - Total:"tot/divnum div" Active:"active/divnum div" Inactive:"inactive/divnum div" Buffers:"buff/divnum div" Cached:"cache/divnum div" |Free="freeperct";"warn";"crit";0 Active="active";0;0;0 Inactive="inactive";0;0;0 Buffers="buff";0;0;0 Cached="cache";0;0;0" } }' /proc/meminfo) echo ${RESULT#* } exit ${RESULT%% *}
Monitoring der verwendeten Bandbreite
Zum messen der verwendeten Bandbreite verwende ich das Script:
#!/bin/bash INTERVAL="1" # update interval in seconds if [ -z "$1" ]; then echo echo "example: plugin.sh HOSTNAME system interface_name time warning_mbit/s critical_mbit/s total mbit/s;" echo echo "./check_bandwidth.sh localhost linux eth0 15 80 90 100" echo "./check_bandwidth.sh switchname cisco GigabitEthernet0/1 15 80 90 100 192.192.192.192 snmp-community" exit fi name=$1 system=$2 IF=$3 sec=$4 warn=$5 crit=$6 iface_speed=$7 ip=$8 community=$9 current_pid=$$ bin_ps=`which ps` bin_grep=`which grep` bin_expr=`which expr` bin_cat=`which cat` bin_tac=`which tac` bin_sort=`which sort` bin_wc=`which wc` bin_awk=`which awk` bin_snmpwalk=`which snmpwalk` interfaces_oid=1.3.6.1.2.1.2.2.1.2 if [ "$system" = "cisco" ]; then if_index=`$bin_snmpwalk -c $community -v 2c $ip $interfaces_oid | grep $IF | sed 's/^.*\.//;s/\ .*$//'` pidfile=/tmp/"$name"_"$if_index"_check_bandwidth.pid fi if [ "$system" = "linux" ]; then pidfile=/tmp/"$name"_"$IF"_check_bandwidth.pid fi if [ -f $pidfile ]; then echo "need to reduce the check duration or increase the interval between checks" exit 1 else echo $current_pid > $pidfile fi if [ "$system" = "linux" ]; then tmpfile_rx=/tmp/"$name"_"$IF"_check_bandwidth_rx.tmp tmpfile_tx=/tmp/"$name"_"$IF"_check_bandwidth_tx.tmp reverse_tmpfile_rx=/tmp/"$name"_"$IF"_reverse_check_bandwidth_rx.tmp reverse_tmpfile_tx=/tmp/"$name"_"$IF"_reverse_check_bandwidth_tx.tmp deltafile_rx=/tmp/"$name"_"$IF"_delta_check_bandwidth_rx.tmp deltafile_tx=/tmp/"$name"_"$IF"_delta_check_bandwidth_tx.tmp elif [ "$system" = "cisco" ]; then tmpfile_rx=/tmp/"$name"_"$if_index"_check_bandwidth_rx.tmp tmpfile_tx=/tmp/"$name"_"$if_index"_check_bandwidth_tx.tmp reverse_tmpfile_rx=/tmp/"$name"_"$if_index"_reverse_check_bandwidth_rx.tmp reverse_tmpfile_tx=/tmp/"$name"_"$if_index"_reverse_check_bandwidth_tx.tmp deltafile_rx=/tmp/"$name"_"$if_index"_delta_check_bandwidth_rx.tmp deltafile_tx=/tmp/"$name"_"$if_index"_delta_check_bandwidth_tx.tmp laststate_file=/tmp/"$name"_"$if_index"_laststate.tmp fi warn_kbits=`$bin_expr $warn '*' 1000000` crit_kbits=`$bin_expr $crit '*' 1000000` iface_speed_kbits=`$bin_expr $iface_speed '*' 1000000` if [ "$system" = "linux" ]; then START_TIME=`date +%s` n=0 while [ $n -lt $sec ] do cat /sys/class/net/$3/statistics/rx_bytes >> $tmpfile_rx cat /sys/class/net/$3/statistics/tx_bytes >> $tmpfile_tx sleep $INTERVAL let "n = $n + 1" done FINISH_TIME=`date +%s` $bin_cat $tmpfile_rx | $bin_sort -nr > $reverse_tmpfile_rx $bin_cat $tmpfile_tx | $bin_sort -nr > $reverse_tmpfile_tx while read line; do if [ -z "$RBYTES" ]; then RBYTES=`cat /sys/class/net/$3/statistics/rx_bytes` $bin_expr $RBYTES - $line >> $deltafile_rx; else $bin_expr $RBYTES - $line >> $deltafile_rx; fi RBYTES=$line done < $reverse_tmpfile_rx while read line; do if [ -z "$TBYTES" ]; then TBYTES=`cat /sys/class/net/$3/statistics/tx_bytes` $bin_expr $TBYTES - $line >> $deltafile_tx; else $bin_expr $TBYTES - $line >> $deltafile_tx; fi TBYTES=$line done < $reverse_tmpfile_tx while read line; do SUM_RBYTES=`$bin_expr $SUM_RBYTES + $line` done < $deltafile_rx while read line; do SUM_TBYTES=`$bin_expr $SUM_TBYTES + $line` done < $deltafile_tx let "DURATION = $FINISH_TIME - $START_TIME" let "RBITS_SEC = ( $SUM_RBYTES * 8 ) / $DURATION" let "TBITS_SEC = ( $SUM_TBYTES * 8 ) / $DURATION" if [ $RBITS_SEC -lt $warn_kbits -o $TBITS_SEC -lt $warn_kbits ] then data_output_r=`echo "$RBITS_SEC 1000000" | $bin_awk '{ printf ("%.2f", $1/$2); }'` data_output_t=`echo "$TBITS_SEC 1000000" | $bin_awk '{ printf ("%.2f", $1/$2); }'` percent_output_r=`echo "$RBITS_SEC $iface_speed_kbits 100" | $bin_awk '{ printf ("%.2f", $1/$2*$3); }'` percent_output_t=`echo "$TBITS_SEC $iface_speed_kbits 100" | $bin_awk '{ printf ("%.2f", $1/$2*$3); }'` nagvis_perfdata_r="InUsage=$percent_output_r%;$warn_kbits;$crit_kbits" nagvis_perfdata_t="OutUsage=$percent_output_t%;$warn_kbits;$crit_kbits" pnp4nagios_perfdata_r="in=$RBITS_SEC;$warn_kbits;$crit_kbits" pnp4nagios_perfdata_t="in=$TBITS_SEC;$warn_kbits;$crit_kbits" output="IN $data_output_r Mbit/s OUT $data_output_t Mbit/s - OK, period $DURATION sec | $nagvis_perfdata_r $nagvis_perfdata_t inBandwidth="$data_output_r"Mbs outBandwidth="$data_output_t"Mbs $pnp4nagios_perfdata_r $pnp4nagios_perfdata_t" exitstatus=0 elif [ $RBITS_SEC -ge $warn_kbits -a $RBITS_SEC -le $crit_kbits ] || [ $TBITS_SEC -ge $warn_kbits -a $TBITS_SEC -le $crit_kbits ]; then data_output_r=`echo "$RBITS_SEC 1000000" | $bin_awk '{ printf ("%.2f", $1/$2); }'` data_output_t=`echo "$TBITS_SEC 1000000" | $bin_awk '{ printf ("%.2f", $1/$2); }'` percent_output_r=`echo "$RBITS_SEC $iface_speed_kbits 100" | $bin_awk '{ printf ("%.2f", $1/$2*$3); }'` percent_output_t=`echo "$TBITS_SEC $iface_speed_kbits 100" | $bin_awk '{ printf ("%.2f", $1/$2*$3); }'` nagvis_perfdata_r="InUsage=$percent_output_r%;$warn_kbits;$crit_kbits" nagvis_perfdata_t="OutUsage=$percent_output_t%;$warn_kbits;$crit_kbits" pnp4nagios_perfdata_r="in=$RBITS_SEC;$warn_kbits;$crit_kbits" pnp4nagios_perfdata_t="in=$TBITS_SEC;$warn_kbits;$crit_kbits" output="IN $data_output_r Mbit/s OUT $data_output_t Mbit/s WARNING! period $DURATION sec | $nagvis_perfdata_r $nagvis_perfdata_t inBandwidth="$data_output_r"Mbs outBandwidth="$data_output_t"Mbs $pnp4nagios_perfdata_r $pnp4nagios_perfdata_t" exitstatus=1 elif [ $RBITS_SEC -gt $warn_kbits -o $TBITS_SEC -gt $warn_kbits ] then data_output_r=`echo "$RBITS_SEC 1000000" | $bin_awk '{ printf ("%.2f", $1/$2); }'` data_output_t=`echo "$TBITS_SEC 1000000" | $bin_awk '{ printf ("%.2f", $1/$2); }'` percent_output_r=`echo "$RBITS_SEC $iface_speed_kbits 100" | $bin_awk '{ printf ("%.2f", $1/$2*$3); }'` percent_output_t=`echo "$TBITS_SEC $iface_speed_kbits 100" | $bin_awk '{ printf ("%.2f", $1/$2*$3); }'` nagvis_perfdata_r="InUsage=$percent_output_r%;$warn_kbits;$crit_kbits" nagvis_perfdata_t="OutUsage=$percent_output_t%;$warn_kbits;$crit_kbits" pnp4nagios_perfdata_r="in=$RBITS_SEC;$warn_kbits;$crit_kbits" pnp4nagios_perfdata_t="in=$TBITS_SEC;$warn_kbits;$crit_kbits" output="IN $data_output_r Mbit/s OUT $data_output_t Mbit/s CRITICAL! period $DURATION sec | $nagvis_perfdata_r $nagvis_perfdata_t inBandwidth="$data_output_r"Mbs outBandwidth="$data_output_t"Mbs $pnp4nagios_perfdata_r $pnp4nagios_perfdata_t" exitstatus=2 else output="unknown status" exitstatus=3 fi elif [ "$system" = "cisco" ]; then START_TIME=`date +%s` n=0 rx_tag=1 tx_tag=1 rx_old=0 tx_old=0 while [ $n -lt $sec -a $rx_tag -eq 1 -a $tx_tag -eq 1 ]; do rx_now=`$bin_snmpwalk -c $community -v 2c -Oqv $ip 1.3.6.1.2.1.2.2.1.10.$if_index` if [ $rx_now -ge $rx_old ]; then rx_tag=1 if [ $rx_now -gt $rx_old ]; then echo $rx_now >> $tmpfile_rx fi else rx_tag=0 fi rx_old=$rx_now tx_now=`$bin_snmpwalk -c $community -v 2c -Oqv $ip 1.3.6.1.2.1.2.2.1.16.$if_index` if [ $tx_now -ge $tx_old ]; then tx_tag=1 if [ $tx_now -gt $tx_old ]; then echo $tx_now >> $tmpfile_tx fi else tx_tag=0 fi tx_old=$tx_now sleep $INTERVAL let "n = $n + 1" done FINISH_TIME=`date +%s` data_lines_rx=`$bin_cat $tmpfile_rx | $bin_wc -l` data_lines_tx=`$bin_cat $tmpfile_tx | $bin_wc -l` if [ $data_lines_rx -le 1 -o $data_lines_rx -le 1 ]; then output=`$bin_cat $laststate_file` echo $output rm -f $tmpfile_rx rm -f $tmpfile_tx rm -f $pidfile exit 0 fi $bin_tac $tmpfile_rx > $reverse_tmpfile_rx $bin_tac $tmpfile_tx > $reverse_tmpfile_tx while read line; do if [ -z "$ROCTETS" ]; then ROCTETS=$line else $bin_expr $ROCTETS - $line >> $deltafile_rx; fi ROCTETS=$line done < $reverse_tmpfile_rx while read line; do if [ -z "$TOCTETS" ]; then TOCTETS=$line else $bin_expr $TOCTETS - $line >> $deltafile_tx; fi TOCTETS=$line done < $reverse_tmpfile_tx while read line; do SUM_ROCTETS=`$bin_expr $SUM_ROCTETS + $line` done < $deltafile_rx while read line; do SUM_TOCTETS=`$bin_expr $SUM_TOCTETS + $line` done < $deltafile_tx let "DURATION = $FINISH_TIME - $START_TIME" let "RBITS_SEC = ( $SUM_ROCTETS * 8 ) / $DURATION" let "TBITS_SEC = ( $SUM_TOCTETS * 8 ) / $DURATION" #debug block start if [ $RBITS_SEC -lt 0 ]; then timestamp=`date +%H%M%S` cp $tmpfile_rx "$tmpfile_rx"_"$timestamp" cp $reverse_tmpfile_rx "$reverse_tmpfile_rx"_"$timestamp" cp $deltafile_rx "$deltafile_rx"_"$timestamp" fi if [ $TBITS_SEC -lt 0 ]; then timestamp=`date +%H%M%S` cp $tmpfile_tx "$tmpfile_tx"_"$timestamp" cp $reverse_tmpfile_tx "$reverse_tmpfile_tx"_"$timestamp" cp $deltafile_tx "$deltafile_tx"_"$timestamp" fi #debug block finish if [ $RBITS_SEC -lt $warn_kbits -o $TBITS_SEC -lt $warn_kbits ] then data_output_r=`echo "$RBITS_SEC 1000000" | $bin_awk '{ printf ("%.2f", $1/$2); }'` data_output_t=`echo "$TBITS_SEC 1000000" | $bin_awk '{ printf ("%.2f", $1/$2); }'` percent_output_r=`echo "$RBITS_SEC $iface_speed_kbits 100" | $bin_awk '{ printf ("%.2f", $1/$2*$3); }'` percent_output_t=`echo "$TBITS_SEC $iface_speed_kbits 100" | $bin_awk '{ printf ("%.2f", $1/$2*$3); }'` nagvis_perfdata_r="InUsage=$percent_output_r%;$warn_kbits;$crit_kbits" nagvis_perfdata_t="OutUsage=$percent_output_t%;$warn_kbits;$crit_kbits" pnp4nagios_perfdata_r="in=$RBITS_SEC;$warn_kbits;$crit_kbits" pnp4nagios_perfdata_t="in=$TBITS_SEC;$warn_kbits;$crit_kbits" output="IN $data_output_r Mbit/s OUT $data_output_t Mbit/s - OK, period $DURATION sec | $nagvis_perfdata_r $nagvis_perfdata_t inBandwidth="$data_output_r"Mbs outBandwidth="$data_output_t"Mbs $pnp4nagios_perfdata_r $pnp4nagios_perfdata_t" echo $output > $laststate_file exitstatus=0 elif [ $RBITS_SEC -ge $warn_kbits -a $RBITS_SEC -le $crit_kbits ] || [ $TBITS_SEC -ge $warn_kbits -a $TBITS_SEC -le $crit_kbits ]; then data_output_r=`echo "$RBITS_SEC 1000000" | $bin_awk '{ printf ("%.2f", $1/$2); }'` data_output_t=`echo "$TBITS_SEC 1000000" | $bin_awk '{ printf ("%.2f", $1/$2); }'` percent_output_r=`echo "$RBITS_SEC $iface_speed_kbits 100" | $bin_awk '{ printf ("%.2f", $1/$2*$3); }'` percent_output_t=`echo "$TBITS_SEC $iface_speed_kbits 100" | $bin_awk '{ printf ("%.2f", $1/$2*$3); }'` nagvis_perfdata_r="InUsage=$percent_output_r%;$warn_kbits;$crit_kbits" nagvis_perfdata_t="OutUsage=$percent_output_t%;$warn_kbits;$crit_kbits" pnp4nagios_perfdata_r="in=$RBITS_SEC;$warn_kbits;$crit_kbits" pnp4nagios_perfdata_t="in=$TBITS_SEC;$warn_kbits;$crit_kbits" output="IN $data_output_r Mbit/s OUT $data_output_t Mbit/s WARNING! period $DURATION sec | $nagvis_perfdata_r $nagvis_perfdata_t inBandwidth="$data_output_r"Mbs outBandwidth="$data_output_t"Mbs $pnp4nagios_perfdata_r $pnp4nagios_perfdata_t" echo $output > $laststate_file exitstatus=1 elif [ $RBITS_SEC -gt $warn_kbits -o $TBITS_SEC -gt $warn_kbits ] then data_output_r=`echo "$RBITS_SEC 1000000" | $bin_awk '{ printf ("%.2f", $1/$2); }'` data_output_t=`echo "$TBITS_SEC 1000000" | $bin_awk '{ printf ("%.2f", $1/$2); }'` percent_output_r=`echo "$RBITS_SEC $iface_speed_kbits 100" | $bin_awk '{ printf ("%.2f", $1/$2*$3); }'` percent_output_t=`echo "$TBITS_SEC $iface_speed_kbits 100" | $bin_awk '{ printf ("%.2f", $1/$2*$3); }'` nagvis_perfdata_r="InUsage=$percent_output_r%;$warn_kbits;$crit_kbits" nagvis_perfdata_t="OutUsage=$percent_output_t%;$warn_kbits;$crit_kbits" pnp4nagios_perfdata_r="in=$RBITS_SEC;$warn_kbits;$crit_kbits" pnp4nagios_perfdata_t="in=$TBITS_SEC;$warn_kbits;$crit_kbits" output="IN $data_output_r Mbit/s OUT $data_output_t Mbit/s CRITICAL! period $DURATION sec | $nagvis_perfdata_r $nagvis_perfdata_t inBandwidth="$data_output_r"Mbs outBandwidth="$data_output_t"Mbs $pnp4nagios_perfdata_r $pnp4nagios_perfdata_t" echo $output > $laststate_file exitstatus=2 else output="unknown status" exitstatus=3 fi else output="incorrect system!" exitstatus=3 fi rm -f $tmpfile_rx rm -f $reverse_tmpfile_rx rm -f $deltafile_rx rm -f $tmpfile_tx rm -f $reverse_tmpfile_tx rm -f $deltafile_tx rm -f $pidfile echo "$output" exit $exitstatus
Da auf den GW das Problem auftrat, daß der GW keine IP adressen mehr ausgab, und CLients per FAST auf Layer 2 verbunden waren, habe ich die Lease Time auf 30 Minuten eingestellt.
Kontrolle der vergebenen IP-Adressen
Als zusätzliche Kontrolle über die vergebenen IP-Adressen dient das Script:
#!/usr/bin/env python # # Author: Hari Sekhon # Date: 2007-11-20 18:16:55 +0000 (Tue, 20 Nov 2007) # # http://github.com/harisekhon # # License: see accompanying LICENSE file # """Nagios plugin to parse the ISC Dhcp Server lease file and print out a list of all the Name/IP/MAC associations or any combination of the three. Can also be used to alert on the delegation of IPs to non-recognized MACs or Hostnames""" __author__ = "Hari Sekhon" __title__ = "Nagios Plugin for DHCPd Server Leases" __version__ = 0.8 # Due to the limited of characters that Nagios accepts from a plugin, this # output will be cut short if you have a lot of dhcp clients, which is why # the -c switch was included to compact the output to fit more in. # Remember, this program can be used without Nagios so that character limit # need not be your limit. import re import sys import signal from optparse import OptionParser # Standard Nagios return codes OK = 0 WARNING = 1 CRITICAL = 2 UNKNOWN = 3 # Default timeout. All good plugins should have a timeout to prevent hanging TIMEOUT = 30 # Regex for lease comparison and dissection RE_BINDING_STATE_ACTIVE = re.compile("\s*binding state active;") RE_LEASE = re.compile("lease") RE_HOSTNAME = re.compile("client-hostname") RE_MAC = re.compile("hardware\sethernet") RE_IP_ADDRESS = re.compile("(\d{1,3}.){3}\d{1,3}") def end(status, message): """Exits the plugin with first arg as the return code and the second arg as the message to output""" if status == OK: print "DHCP LEASES: %s" % message sys.exit(OK) elif status == WARNING: print "WARNING: %s" % message sys.exit(WARNING) elif status == CRITICAL: print "CRITICAL: %s" % message sys.exit(CRITICAL) else: print "UNKNOWN: %s" % message sys.exit(UNKNOWN) def sort_keys_by_host(dictionary): """Takes the address dictionary in the form {"ip":["hostname","mac"]}, sorts the keys by the host value, returns an ordered list of keys""" hosts = [] keys = dictionary.keys() keys.sort() keys_sorted = [] for key in keys: hosts.append(dictionary[key][0]) hosts.sort() for host in hosts: for key in keys: if dictionary[key][0] == host: keys_sorted.append(key) # ((k, v) for k, v in mydict), key=lambda i: i[1]) # dedup without losing order keys_sorted2 = [] for key in keys_sorted: if key not in keys_sorted2: keys_sorted2.append(key) keys_sorted = keys_sorted2 return keys_sorted class DhcpdLeaseTester: """Class to hold all Dhcpd Lease test state""" def __init__(self): """Instantiate variables""" self.address_dict = {} self.compact_output = False self.host_whitelist = "" self.host_blacklist = "" self.leasefile = None self.lease = "" self.leases = [] self.mac_whitelist = "" self.mac_blacklist = "" self.no_name = False self.no_summary = False self.show_mac = False self.sort_by_ip = False self.timeout = TIMEOUT self.unauthorized = False self.unauthorized_dict = {} def validate_variables(self): """Validates all variables as defined in self.__init__""" if self.compact_output == None: self.compact_output = False if self.host_whitelist == None: self.host_whitelist = "" if self.host_blacklist == None: self.host_blacklist = "" if self.leasefile == None: end(UNKNOWN, "No leasefile to test") if self.mac_whitelist == None: self.mac_whitelist = "" if self.mac_blacklist == None: self.mac_blacklist = "" if self.timeout == None: self.timeout = TIMEOUT self.validate_normalize_macs("whitelist") self.validate_normalize_macs("blacklist") try: self.timeout = int(self.timeout) except ValueError: end(UNKNOWN, "timeout invalid, must be a numeric integer") def validate_normalize_macs(self, colourlist): """Checks to make sure any Mac addresses given are in the correct format. Takes either whitelist or blacklist and then validates each mac in that list and changes the list to a normalized uppercase hex mac with no formatting or separators""" maclist = getattr(self, "mac_" + colourlist) maclist = maclist.replace(",", " ") maclist = maclist.split() maclist = [mac.replace(":","") for mac in maclist] maclist = [mac.upper() for mac in maclist] re_mac_format = re.compile("^([\dA-Fa-f]{2}[:-]?){5}[\dA-Fa-f]{2}$") for mac in maclist: if not re_mac_format.match(mac): end(UNKNOWN, "'%s' was given as a Mac address but is " % mac + "not a valid Mac") setattr(self, "mac_" + colourlist, maclist) def sighandler(self, discarded, discarded2): """Function to be called by signal.alarm to kill the plugin""" # Nop for these variables discarded = discarded2 discarded2 = discarded end(CRITICAL, "plugin has self terminated after exceeding " \ + "the timeout (%s seconds)" % self.timeout) def test_leases(self): """Initiates the test, calls parse_leases and possibly the condition checking funcs too if whitelist or blacklists are used""" self.validate_variables() signal.signal(signal.SIGALRM, self.sighandler) signal.alarm(self.timeout) # In the format {"ip":["hostname","mac"]} self.address_dict = {} result = OK try: output = self.parse_leases() except IndexError: end(CRITICAL, "Error parsing dhcp leases file '%s', possibly not " \ + "valid lease file?" % self.leasefile) self.check_unauthorized_leases() if self.unauthorized == True: unauthorized_output = self.format_unauthorized_leases() output = unauthorized_output + " || " + output result = CRITICAL # When we used to compact the whitespace out, not used any more #if self.compact_output: # output = output.replace(" - ", "-") # output = output.replace(" = ", "=") # output = output.replace(", ", ",") # output = output.replace(" (", "(") # output = output.replace(" | ", "|") return result, output def parse_leases(self): """Parse leases file and returns a string of leases with IP addreses and optional Hostname/Mac mappings""" self.leases = self.open_lease_file() security_checks_on = False if self.host_whitelist or \ self.host_blacklist or \ self.mac_whitelist or \ self.mac_blacklist: security_checks_on = True for self.lease in self.leases: if RE_BINDING_STATE_ACTIVE.search(self.lease): hostname = "" ip = "" mac = "" self.lease = self.lease.split("\n") ip = self.get_ip() # If this is not valid, there can be no lease so move on # This actually catches things like the user not using a decent # lease file, in which case this will result in no real leases # and will therefore result in a true result of no leases. # Actually forcing the correct lease file turned out to not # be fully possible since it varies among servers, so this # catches the rest if ip == "UNKNOWN": continue self.address_dict[ip] = ["Unknown Hostname", "Unknown Mac"] if not self.no_name or security_checks_on: hostname = self.get_hostname() self.address_dict[ip][0] = hostname if self.show_mac == True or security_checks_on: mac = self.get_mac() self.address_dict[ip][1] = mac msg = self.format_leases() return msg def check_unauthorized_leases(self): """Checks for and call functions to test the leases against the given whitelists/blacklists. Returns a list where the first element is a True or False overall result, and the second element is a dictionary of offending hosts with 'mac' and 'host' keys representing an array of hosts that tripped each type of rule""" if self.mac_whitelist: self.check_mac_whitelist() if self.mac_blacklist: self.check_mac_blacklist() if self.host_whitelist: self.check_host_whitelist() if self.host_blacklist: self.check_host_blacklist() if len(self.unauthorized_dict) > 0: self.unauthorized = True def check_host_whitelist(self): """Checks the self.address_dict for any hostname not in the host whitelist and returns a list of unauthorized hostnames""" host_whitelist = self.host_whitelist.replace(",", " ") host_whitelist = host_whitelist.split() host_whitelist = [host.upper() for host in host_whitelist] for ip in self.address_dict.keys(): hostname = self.address_dict[ip][0] mac = self.address_dict[ip][1] if hostname.upper() not in host_whitelist: self.unauthorized_dict[ip] = (hostname, mac) def check_host_blacklist(self): """Checks the self.address_dict for any hostname not in the host blacklist and returns a list of unauthorized hostnames""" host_blacklist = self.host_blacklist.replace(",", " ") host_blacklist = host_blacklist.split() host_blacklist = [host.upper() for host in host_blacklist] for ip in self.address_dict.keys(): hostname = self.address_dict[ip][0] mac = self.address_dict[ip][1] if hostname.upper() in host_blacklist: self.unauthorized_dict[ip] = (hostname, mac) def check_mac_whitelist(self): """Checks the self.address_dict for any macname not in the mac whitelist and returns a list of unauthorized macnames""" for ip in self.address_dict.keys(): hostname = self.address_dict[ip][0] mac = self.address_dict[ip][1] mac = mac.replace(":", "") mac = mac.upper() if mac not in self.mac_whitelist: self.unauthorized_dict[ip] = (hostname, mac) def check_mac_blacklist(self): """Checks the self.address_dict for any macname not in the mac blacklist and returns a list of unauthorized macnames""" for ip in self.address_dict.keys(): hostname = self.address_dict[ip][0] mac = self.address_dict[ip][1] mac = mac.replace(":", "") mac = mac.upper() if mac in self.mac_blacklist: self.unauthorized_dict[ip] = (hostname, mac) def format_leases(self): """Takes the address dictionary in the form {"ip":("hostname","mac")} and formats the output, returns a string.""" if self.no_name == True: self.sort_by_ip = True if self.sort_by_ip == True: address_keys_sorted = self.address_dict.keys() address_keys_sorted.sort() else: address_keys_sorted = sort_keys_by_host(self.address_dict) number_leases = len(address_keys_sorted) if number_leases == 0: msg = "No dhcp leases recorded" else: if self.no_summary: msg = "" else: if number_leases == 1: msg = "%s lease" % number_leases else: msg = "%s leases" % number_leases if not self.compact_output: msg += " - " if not self.compact_output: for ip in address_keys_sorted: if self.no_name == True: msg += "%s" % ip else: hostname = self.address_dict[ip][0] msg += "%s = %s" % (hostname, ip) if self.show_mac: mac = self.address_dict[ip][1] msg += " (%s)" % mac msg += ", " msg = msg.rstrip(", ") msg += " | 'DHCP Leases'=%s" % number_leases return msg def format_unauthorized_leases(self): """Takes the self unauthorized dictionary in the form {"ip":("hostname","mac","offending")} and formats the output, returns a string.""" if self.no_name == True: self.sort_by_ip = True if self.sort_by_ip == True: unauthorized_keys_sorted = self.unauthorized_dict.keys() unauthorized_keys_sorted.sort() else: unauthorized_keys_sorted = sort_keys_by_host(self.unauthorized_dict) number_unauthorized = len(unauthorized_keys_sorted) if number_unauthorized == 0: return "" else: if number_unauthorized == 1: msg = "%s Unauthorized Host! " % number_unauthorized else: msg = "%s Unauthorized Hosts! " % number_unauthorized for ip in unauthorized_keys_sorted: if self.no_name == True: msg += "%s" % ip else: hostname = self.unauthorized_dict[ip][0] msg += "%s = %s" % (hostname, ip) if self.show_mac: # Get original instead as Mac has changed by this point # This maintains better output consistency but relies # on the leases file being slightly sane..., but then # if your leases file is not sane, how is that my fault? # This would be a failing of dhcpd more than this plugin #mac = self.unauthorized_dict[ip][1] mac = self.address_dict[ip][1] msg += " (%s)" % mac msg += ", " msg = msg.rstrip(", ") return msg def open_lease_file(self): """Opens the lease file, tests the lease file is valid, and then returns an array of elements each containing one lease block definition""" leases_array = [] try: file_handle = open(self.leasefile) leases = file_handle.read() except IOError: end(CRITICAL, "Error reading lease file '%s'" % self.leasefile) # Check to see if it is a valid lease file. # If there are no leases, then we should check that there are some # header keywords comment that you usually seen in a dhcpd.leases file # This isn't really good enough but otherwise it can break across # different systems. Looser than I would like but the user should # really be using a valid lease file. Parse leases will also catch # this in that no leases will be created and the result will be # technically true, there are no valid leases in an incorrect file if not re.search("\n\s*lease .+{\s*\n", leases) \ and not \ re.search("(?i)\n#.*lease[s]? file .* written by.*\n", leases) \ and not re.search("\n#.*dhcpd.leases.*\n", leases) \ and not re.search("\n(?i)#.*isc-dhcp.*\n", leases): end(CRITICAL, "'%s' is not recognized as a valid dhcpd lease file" \ % self.leasefile) leases = leases.split("}")[:-1] for lease in leases: lease_parts = lease.split("{") if len(lease_parts) > 1: leases_array.append(lease_parts[1]) #else: # print >> sys.stderr, "Debug - Not valid lease:\n%s" % lease return leases def get_ip(self): """Takes an list of lines from a dhcp lease block from self.leases and returns the ip address of this lease""" ip = "" for line in self.lease: if RE_LEASE.search(line): line = line.split() if len(line) == 3: ip = line[1] else: ip = "UNKNOWN" if not RE_IP_ADDRESS.match(ip): ip = "UNKNOWN" return ip def get_hostname(self): """Takes an list of lines from a dhcp lease block from self.leases and returns the hostname of the machine with this lease""" hostname = "" for line in self.lease: if RE_HOSTNAME.search(line): line = line.split() if len(line) == 2: hostname = line[1] hostname = hostname.rstrip(";") hostname = hostname.strip('"') else: hostname = "UNKNOWN" if hostname == "" or hostname == None: hostname = "UNKNOWN" return hostname def get_mac(self): """Takes an list of lines from a dhcp lease block from self.leases and returns the Mac of the machine with this lease""" mac = "" for line in self.lease: if RE_MAC.search(line): line = line.split() if len(line) == 3: mac = line[2] mac = mac.rstrip(";") else: mac = "UNKNOWN" if mac == "" or mac == None: mac = "UNKNOWN" return mac def main(): """Main func parses command line args and calls print_leases""" tester = DhcpdLeaseTester() parser = OptionParser() parser.add_option( "-c", "--compact-output", action="store_true", dest="compact_output", help="Compact the output, do not list leases. Use this" \ + "to make sure Nagios gets perfdata as NRPE has" \ + " a limit on the number of characters before it " \ + "discards the rest") parser.add_option( "-f", "--file", "--lease-file", dest="leasefile", help="Specify the dhcp lease file to use. Should be " \ + "the current lease file that the ISC dhcp " \ + "daemon uses to track it's leases") parser.add_option( "-m", "--mac", action="store_true", dest="show_mac", help="Show mac addresses as well as Name/IP pairings") parser.add_option( "-n", "--no-name", action="store_true", dest="no_name", help="Do not display hostnames. When used by itself, " \ + "this just shows assigned IP addresses. Can be " \ + "used in conjunction with --mac in order to show " \ + "only IP/Mac pairings") parser.add_option( "-i", "--sort-by-ip", action="store_true", dest="sort_by_ip", help="Change the output order to sort by IP rather " \ + "than the default of sorting by hostname. If " \ + "using --no-name this is implied") parser.add_option( "-s", "--no-summary", action="store_true", dest="no_summary", help="Do not print the summary of the number of dhcp " \ + "leases used") parser.add_option( "-t", "--timeout", dest="timeout", help="Timeout in seconds before the plugin self " \ + "terminates. This should never be needed but the " \ + "Nagios coding guidelines recommend it and " \ + "therefore it is implemented for completeness. " \ + "Use this to specify a custom timeout period in " \ + "seconds (should be an integer/whole number). " \ + "Defaults to %s seconds" % TIMEOUT) parser.add_option( "-w", "--host-whitelist", dest="host_whitelist", help="Whitelist of known Hostnames. Raises alert" \ + " if an IP has been issued to any machine with a " \ + "Hostname not in this list. Considered weak since" \ + " the hostname can be set on the client machine " \ + "before requesting a dhcp lease. But it's there " \ + "if you want it. Can be a nice extra layer to the" \ + " defense in depth strategy when properly used " \ + "with a Mac whitelist as well. Although Mac " \ + "addresses can also be spoofed, some attackers " \ + "may not think to spoof the hostname as well as" \ + " the mac address. Should be a comma or space " \ + "separated list, enclosed in quotes if using " \ + "spaces. Hostnames are case insensitive") parser.add_option( "-x", "--host-blacklist", dest="host_blacklist", help="Blacklist of known Hostnames. Raises " \ + "alert if an IP has been handed out to a machine " \ + "with this Hostname. Can take a list of Hostnames" \ + ", comma or space separated (enclose in quotes if" \ + " using spaces). Can be combined with any " \ + "Whitelist, in which case, blacklists always take" \ + " preference over whitelists and raise an alert. " \ + "Hostnames are case insensitive") parser.add_option( "-y", "--mac-whitelist", dest="mac_whitelist", help="Whitelist of known Mac addresses. Raises " \ + "alert if an IP has been issued to any machine " \ + "with a Mac address not in this list. Although " \ + "Mac addresses can be spoofed, this may not have " \ + "been done when requesting the dhcp lease. For " \ + "extra layers combine with --host-whitelist to " \ + "form a nice additional tripwire. Should be a " \ + "comma or space separated list, enclosed in " \ + "quotes if using spaces. Valid Mac formats: " \ + "aa:bb:cc:dd:ee:ff, or aa-bb-cc-dd-ee-ff or " \ + "aabbccddeeff (case insensitive)") parser.add_option( "-z", "--mac-blacklist", dest="mac_blacklist", help="Blacklist of known Mac addresses. Raises " \ + "alert if an IP has been handed out to a machine " \ + "with this Mac address. Can take a list of Macs" \ + ", comma or space separated (enclose in quotes if" \ + " using spaces). Can be combined with any " \ + "Whitelist, in which case, blacklists always take" \ + " preference over whitelists and raise an alert. " \ + "Valid Mac formats: aa:bb:cc:dd:ee:ff, or " \ + "aa-bb-cc-dd-ee-ff or aabbccddeeff (case " \ + "insensitive)") parser.add_option( "-V", "--version", action = "store_true", dest = "version", help = "Print version number and exit" ) (options, args) = parser.parse_args() tester.compact_output = options.compact_output tester.host_whitelist = options.host_whitelist tester.host_blacklist = options.host_blacklist tester.leasefile = options.leasefile tester.mac_whitelist = options.mac_whitelist tester.mac_blacklist = options.mac_blacklist tester.no_name = options.no_name tester.no_summary = options.no_summary tester.show_mac = options.show_mac tester.sort_by_ip = options.sort_by_ip timeout = options.timeout version = options.version if args: parser.print_help() sys.exit(UNKNOWN) if version: print __version__ sys.exit(UNKNOWN) if not tester.leasefile: print "UNKNOWN: no lease file specified. See --help for details\n" parser.print_help() sys.exit(UNKNOWN) if timeout == None: timeout = TIMEOUT try: tester.timeout = int(timeout) except ValueError: end(UNKNOWN, "timeout must be a numeric integer. See --help for " \ + "details") result, output = tester.test_leases() end(result, output) if __name__ == "__main__": try: main() except KeyboardInterrupt: print "Caught Control-C..." sys.exit(UNKNOWN)
Script für die Anzeige
Zur Anzeige brauche ich dann noch folgendes Script:
! /bin/sh #result=$(sudo /usr/local/sbin/batctl tg | grep '^ [^ ]' | cut -b 39-55 | sort | uniq | wc -l) #result=$(sudo /usr/local/sbin/batctl tg | grep '^ [^ ]' | cut -b 39-55 | sort | uniq | wc -l) add_perf=$result #warn=500 warn=50 #crit=600 crit=60 count=30000 #x=$(($count / $result)) #echo "Connection OK $result|$x KBit/sec;Connections=${result};${warn},${crit};;" #echo "Connection OK $result Connections $x kbit/client |$x;${warn},${crit};;" # ##################################################################### # Add SERVICEPERFDATA # format: 'label'=value[unit-of-measure];[warn];[crit];[min];[max] # ##################################################################### #OUTPUT="$OUTPUT|banned_IP=${bcount};${warn};${crit};;" result=$(/usr/lib/nagios/plugins/check_dhcpd_leases.py -c -n -f /var/lib/dhcp/dhcpd.leases) echo "Verbindungen OK $result" exit 0