Repository
Munin (contrib)
Last change
2021-11-11
Graph Categories
Family
auto
Capabilities
Keywords
Language
Shell
Authors

sshd_log

Example graph: day Example graph: month

Name

sshd_log - Munin plugin to monitor auth.log or journald for sshd server events.

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

warning  - defines a general warning level
           default: UNSET (meaning not configured -> no warnings)

critical - defines a general critical level
           default: UNSET (meaning not configured -> no criticals)

logpass_warning  - defines a warning level for successful password logins
                   default: same value as "warning", so effectively UNSET (not
                   configured) if "warning" also is not configured

logpass_critical - defines a critical level for successful password logins
                   default: same value as "critical", so effectively UNSET (not
                   configured) if "critical" also is not configured

logpasspam_warning   - same as "logpass_warning" but for successful PAM logins

logpasspam_critical  - same as "logpass_critical" but for successful PAM logins

logkey_warning   - same as "logpass_warning" but for successful PublicKey
                   logins

logkey_critical  - same as "logpass_critical" but for successful PublicKey
                   logins

noid_warning   - same as "logpass_warning" but for attempts with no user
                 identification

noid_critical  - same as "logpass_critical" but for attempts with no user
                 identification

rootattempt_warning  - same as "logpass_warning" but for root login attempts

rootattempt_critical - same as "logpass_critical" but for root login attempts

invusr_warning   - same as "logpass_warning" but for invalid user login
                   attempts

invusr_critical  - same as "logpass_critical" but for invalid user login
                   attempts

nordns_warning - same as "logpass_warning" but for connections with reverse
                 DNS for peer

nordns_critical  - same as "logpass_critical" but for connections with reverse
                   DNS for peer

breakin_warning  - same as "logpass_warning" but for potential breakin
                   attempts

breakin_critical - same as "logpass_critical" but for potential breakin
                   attempts

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

Config example setting general warning and critical values and specific ones for root login attempts:

[sshd_log]
    env.warning 100
    env.critical 500
    env.rootattempt_warning 1
    env.rootattempt_critical 100

Magic Markers

#%# family=auto
#%# capabilities=autoconf

Author

Copyright (C) 2009 zlati

Copyright (C) 2009 ckujau

Copyright (C) 2010 pmoranga

Copyright (C) 2016 Thomas Riccardi

#!/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

 warning  - defines a general warning level
            default: UNSET (meaning not configured -> no warnings)

 critical - defines a general critical level
            default: UNSET (meaning not configured -> no criticals)

 logpass_warning  - defines a warning level for successful password logins
                    default: same value as "warning", so effectively UNSET (not
                    configured) if "warning" also is not configured

 logpass_critical - defines a critical level for successful password logins
                    default: same value as "critical", so effectively UNSET (not
                    configured) if "critical" also is not configured

 logpasspam_warning   - same as "logpass_warning" but for successful PAM logins

 logpasspam_critical  - same as "logpass_critical" but for successful PAM logins

 logkey_warning   - same as "logpass_warning" but for successful PublicKey
                    logins

 logkey_critical  - same as "logpass_critical" but for successful PublicKey
                    logins

 noid_warning   - same as "logpass_warning" but for attempts with no user
                  identification

 noid_critical  - same as "logpass_critical" but for attempts with no user
                  identification

 rootattempt_warning  - same as "logpass_warning" but for root login attempts

 rootattempt_critical - same as "logpass_critical" but for root login attempts

 invusr_warning   - same as "logpass_warning" but for invalid user login
                    attempts

 invusr_critical  - same as "logpass_critical" but for invalid user login
                    attempts

 nordns_warning - same as "logpass_warning" but for connections with reverse
                  DNS for peer

 nordns_critical  - same as "logpass_critical" but for connections with reverse
                    DNS for peer

 breakin_warning  - same as "logpass_warning" but for potential breakin
                    attempts

 breakin_critical - same as "logpass_critical" but for potential breakin
                    attempts

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

Config example setting general warning and critical values and specific ones for
root login attempts:

  [sshd_log]
      env.warning 100
      env.critical 500
      env.rootattempt_warning 1
      env.rootattempt_critical 100

=head1 MAGIC MARKERS

  #%# family=auto
  #%# capabilities=autoconf

=head1 AUTHOR

Copyright (C) 2009 zlati

Copyright (C) 2009 ckujau

Copyright (C) 2010 pmoranga

Copyright (C) 2016 Thomas Riccardi

=cut


# Script parameters:
#
#       config   (required)
#       autoconf (optional - used by munin-config)


LOG=${logfile:-/var/log/secure}
JOURNALCTL_ARGS=${journalctlargs:-_COMM=sshd}
TYPE=${type:-GAUGE}

WARNING=${warning:-UNSET}
CRITICAL=${critical:-UNSET}
LOGPASS_WARNING=${logpass_warning:-$WARNING}
LOGPASS_CRITICAL=${logpass_critical:-$CRITICAL}
LOGPASSPAM_WARNING=${logpasspam_warning:-$WARNING}
LOGPASSPAM_CRITICAL=${logpasspam_critical:-$CRITICAL}
LOGKEY_WARNING=${logkey_warning:-$WARNING}
LOGKEY_CRITICAL=${logkey_critical:-$CRITICAL}
NOID_WARNING=${noid_warning:-$WARNING}
NOID_CRITICAL=${noid_critical:-$CRITICAL}
ROOTATTEMPT_WARNING=${rootattempt_warning:-$WARNING}
ROOTATTEMPT_CRITICAL=${rootattempt_critical:-$CRITICAL}
INVUSR_WARNING=${invusr_warning:-$WARNING}
INVUSR_CRITICAL=${invusr_critical:-$CRITICAL}
NORDNS_WARNING=${nordns_warning:-$WARNING}
NORDNS_CRITICAL=${nordns_critical:-$CRITICAL}
BREAKIN_WARNING=${breakin_warning:-$WARNING}
BREAKIN_CRITICAL=${breakin_critical:-$CRITICAL}

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'
        echo 'graph_info 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"
        if [ "$LOGPASS_WARNING" != "UNSET" ]; then
                echo 'LogPass.warning' "$LOGPASS_WARNING"
        fi
        if [ "$LOGPASS_CRITICAL" != "UNSET" ]; then
                echo 'LogPass.critical' "$LOGPASS_CRITICAL"
        fi

        echo 'LogPassPAM.label Successful login via PAM'
        echo 'LogPassPAM.min 0'
        echo 'LogPassPAM.type' "$TYPE"
        if [ "$LOGPASSPAM_WARNING" != "UNSET" ]; then
                echo 'LogPassPAM.warning' "$LOGPASSPAM_WARNING"
        fi
        if [ "$LOGPASSPAM_CRITICAL" != "UNSET" ]; then
                echo 'LogPassPAM.critical' "$LOGPASSPAM_CRITICAL"
        fi

        echo 'LogKey.label Successful PublicKey logins'
        echo 'LogKey.min 0'
        echo 'LogKey.type' "$TYPE"
        if [ "$LOGKEY_WARNING" != "UNSET" ]; then
                echo 'LogKey.warning' "$LOGKEY_WARNING"
        fi
        if [ "$LOGKEY_CRITICAL" != "UNSET" ]; then
                echo 'LogKey.critical' "$LOGKEY_CRITICAL"
        fi

        echo 'NoID.label No identification from user'
        echo 'NoID.min 0'
        echo 'NoID.type' "$TYPE"
        if [ "$NOID_WARNING" != "UNSET" ]; then
                echo 'NoID.warning' "$NOID_WARNING"
        fi
        if [ "$NOID_CRITICAL" != "UNSET" ]; then
                echo 'NoID.critical' "$NOID_CRITICAL"
        fi

        echo 'rootAttempt.label Root login attempts'
        echo 'rootAttempt.min 0'
        echo 'rootAttempt.type' "$TYPE"
        if [ "$ROOTATTEMPT_WARNING" != "UNSET" ]; then
                echo 'rootAttempt.warning' "$ROOTATTEMPT_WARNING"
        fi
        if [ "$ROOTATTEMPT_CRITICAL" != "UNSET" ]; then
                echo 'rootAttempt.critical' "$ROOTATTEMPT_CRITICAL"
        fi

        echo 'InvUsr.label Invalid user login attempts'
        echo 'InvUsr.min 0'
        echo 'InvUsr.type' "$TYPE"
        if [ "$INVUSR_WARNING" != "UNSET" ]; then
                echo 'InvUsr.warning' "$INVUSR_WARNING"
        fi
        if [ "$INVUSR_CRITICAL" != "UNSET" ]; then
                echo 'InvUsr.critical' "$INVUSR_CRITICAL"
        fi

        echo 'NoRDNS.label No reverse DNS for peer'
        echo 'NoRDNS.min 0'
        echo 'NoRDNS.type' "$TYPE"
        if [ "$NORDNS_WARNING" != "UNSET" ]; then
                echo 'NoRDNS.warning' "$NORDNS_WARNING"
        fi
        if [ "$NORDNS_CRITICAL" != "UNSET" ]; then
                echo 'NoRDNS.critical' "$NORDNS_CRITICAL"
        fi

        echo 'Breakin.label Potential Breakin Attempts'
        echo 'Breakin.min 0'
        echo 'Breakin.type' "$TYPE"
        if [ "$BREAKIN_WARNING" != "UNSET" ]; then
                echo 'Breakin.warning' "$BREAKIN_WARNING"
        fi
        if [ "$BREAKIN_CRITICAL" != "UNSET" ]; then
                echo 'Breakin.critical' "$BREAKIN_CRITICAL"
        fi

        exit 0
fi

if [ "$LOG" = "journald" -a "$TYPE" = "ABSOLUTE" ]; then
        CURSOR_FILE="$MUNIN_STATEFILE"
        # read cursor
        # format: "journald-cursor <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]} }'