#!/bin/sh : <<=cut =head1 NAME sshd_log - Munin plugin to monitor auth.log or journald for sshd server events. =head1 CONFIGURATION This plugin requires read permission for the logfile or journald. On busy servers you can change value type to COUNTER and set min to 0 to avoid minus peaks at logrotate. The following environment variables are used by this plugin: logfile - path to the auth log file, or "journald" to use journald. default: /var/log/secure journalctlargs - space separated list of arguments to pass to journalctl to get the sshd logs. default: _COMM=sshd type - "GAUGE" or "DERIVE" default: GAUGE If the "logfile" environment variable is set to "journald" the sshd logs are read from journald, filtering on program "sshd". The filtering may be changed using "journalctlargs". Config examples for /etc/munin/plugin-conf.d/munin-node: [sshd_log] user root group root env.logfile /var/log/messages Config example with journald: [sshd_log] group systemd-journal env.logfile journald Config example with journald on the sshd.service unit only: [sshd_log] group systemd-journal env.logfile journald env.journalctlargs --unit=sshd.service Config example with journald and type DERIVE: [sshd_log] group systemd-journal env.logfile journald env.type DERIVE =head1 MAGIC MARKERS #%# family=auto #%# capabilities=autoconf =head1 AUTHOR Revision 2.0 2016/11/11 15:42:00 Thomas Riccardi Revision 1.2 2010/03/19 15:03:00 pmoranga Revision 1.1 2009/04/26 23:28:00 ckujau Revision 1.0 2009/04/22 22:00:00 zlati =cut # Script parameters: # # config (required) # autoconf (optional - used by munin-config) LOG=${logfile:-/var/log/secure} JOURNALCTL_ARGS=${journalctlargs:-_COMM=sshd} TYPE=${type:-GAUGE} if [ "$LOG" = "journald" -a "$TYPE" = "DERIVE" ]; then TYPE=ABSOLUTE fi if [ "$1" = "autoconf" ]; then if [ "$LOG" = "journald" ]; then # shellcheck disable=SC2086,SC2034 if journalctl --no-pager --quiet --lines=1 $JOURNALCTL_ARGS | read -r DUMMY; then echo "yes" else echo "no (journald empty log for '$JOURNALCTL_ARGS' not found)" fi else if [ -r "$LOG" ]; then echo "yes" else echo "no (logfile '$LOG' not readable)" fi fi exit 0 fi if [ "$1" = "config" ]; then echo 'graph_title SSHD login stats from' "$LOG" echo 'graph_args --base 1000 -l 0' echo 'graph_vlabel logins' echo 'graph_category' security echo 'LogPass.label Successful password logins' echo 'LogPass.min 0' echo 'LogPass.type' "$TYPE" echo 'LogPassPAM.label Successful login via PAM' echo 'LogPassPAM.min 0' echo 'LogPassPAM.type' "$TYPE" echo 'LogKey.label Successful PublicKey logins' echo 'LogKey.min 0' echo 'LogKey.type' "$TYPE" echo 'NoID.label No identification from user' echo 'NoID.min 0' echo 'NoID.type' "$TYPE" echo 'rootAttempt.label Root login attempts' echo 'rootAttempt.min 0' echo 'rootAttempt.type' "$TYPE" echo 'InvUsr.label Invalid user login attempts' echo 'InvUsr.min 0' echo 'InvUsr.type' "$TYPE" echo 'NoRDNS.label No reverse DNS for peer' echo 'NoRDNS.min 0' echo 'NoRDNS.type' "$TYPE" echo 'Breakin.label Potential Breakin Attempts' echo 'Breakin.min 0' echo 'Breakin.type' "$TYPE" exit 0 fi if [ "$LOG" = "journald" -a "$TYPE" = "ABSOLUTE" ]; then CURSOR_FILE="$MUNIN_STATEFILE" # read cursor # format: "journald-cursor " CURSOR= if [ -f "$CURSOR_FILE" ]; then CURSOR=$(awk '/^journald-cursor / {print $2}' "$CURSOR_FILE") fi else CURSOR_FILE= fi if [ "$LOG" = "journald" ]; then # shellcheck disable=SC2086 if [ "$TYPE" = "ABSOLUTE" ]; then journalctl --no-pager --quiet --show-cursor ${CURSOR:+"--after-cursor=$CURSOR"} $JOURNALCTL_ARGS else journalctl --no-pager --quiet --since=$(date -dlast-sunday +%Y-%m-%d) $JOURNALCTL_ARGS fi else cat "$LOG" fi | \ awk -v cursor_file="$CURSOR_FILE" 'BEGIN{c["LogPass"]=0;c["LogKey"]=0;c["NoID"]=0;c["rootAttempt"]=0;c["InvUsr"]=0;c["LogPassPAM"]=0;c["Breakin"]=0;c["NoRDNS"]=0; } /sshd\[.*Accepted password for/{c["LogPass"]++} /sshd\[.*Accepted publickey for/{c["LogKey"]++} /sshd\[.*Did not receive identification string/{c["NoID"]++} /sshd\[.*Failed password for root/{c["rootAttempt"]++} /sshd\[.*Invalid user/{c["InvUsr"]++} /sshd\[.*POSSIBLE BREAK-IN ATTEMPT!/{c["Breakin"]++} /sshd\[.*keyboard-interactive\/pam/{c["LogPassPAM"]++} /sshd\[.*reverse mapping checking getaddrinfo/{c["NoRDNS"]++}a END{if (cursor_file != "") { print "journald-cursor " $3 > cursor_file };for(i in c){print i".value " c[i]} }'