root / plugins / ssh / sshd_log @ aa3ee6dc
Historique | Voir | Annoter | Télécharger (5,11 ko)
| 1 |
#!/bin/sh |
|---|---|
| 2 |
|
| 3 |
: <<=cut |
| 4 |
|
| 5 |
=head1 NAME |
| 6 |
|
| 7 |
sshd_log - Munin plugin to monitor auth.log or journald for sshd |
| 8 |
server events. |
| 9 |
|
| 10 |
=head1 CONFIGURATION |
| 11 |
|
| 12 |
This plugin requires read permission for the logfile or journald. |
| 13 |
|
| 14 |
On busy servers you can change value type to COUNTER and set min to 0 |
| 15 |
to avoid minus peaks at logrotate. |
| 16 |
|
| 17 |
The following environment variables are used by this plugin: |
| 18 |
|
| 19 |
logfile - path to the auth log file, or "journald" to use journald. |
| 20 |
default: /var/log/secure |
| 21 |
|
| 22 |
journalctlargs - space separated list of arguments to pass to |
| 23 |
journalctl to get the sshd logs. |
| 24 |
default: _COMM=sshd |
| 25 |
|
| 26 |
type - "GAUGE" or "DERIVE" |
| 27 |
default: GAUGE |
| 28 |
|
| 29 |
If the "logfile" environment variable is set to "journald" the sshd |
| 30 |
logs are read from journald, filtering on program "sshd". The filtering |
| 31 |
may be changed using "journalctlargs". |
| 32 |
|
| 33 |
|
| 34 |
Config examples for /etc/munin/plugin-conf.d/munin-node: |
| 35 |
|
| 36 |
[sshd_log] |
| 37 |
user root |
| 38 |
group root |
| 39 |
env.logfile /var/log/messages |
| 40 |
|
| 41 |
Config example with journald: |
| 42 |
|
| 43 |
[sshd_log] |
| 44 |
group systemd-journal |
| 45 |
env.logfile journald |
| 46 |
|
| 47 |
Config example with journald on the sshd.service unit only: |
| 48 |
|
| 49 |
[sshd_log] |
| 50 |
group systemd-journal |
| 51 |
env.logfile journald |
| 52 |
env.journalctlargs --unit=sshd.service |
| 53 |
|
| 54 |
Config example with journald and type DERIVE: |
| 55 |
|
| 56 |
[sshd_log] |
| 57 |
group systemd-journal |
| 58 |
env.logfile journald |
| 59 |
env.type DERIVE |
| 60 |
|
| 61 |
=head1 MAGIC MARKERS |
| 62 |
|
| 63 |
#%# family=auto |
| 64 |
#%# capabilities=autoconf |
| 65 |
|
| 66 |
=head1 AUTHOR |
| 67 |
|
| 68 |
Copyright (C) 2009 zlati |
| 69 |
|
| 70 |
Copyright (C) 2009 ckujau |
| 71 |
|
| 72 |
Copyright (C) 2010 pmoranga |
| 73 |
|
| 74 |
Copyright (C) 2016 Thomas Riccardi |
| 75 |
|
| 76 |
=cut |
| 77 |
|
| 78 |
|
| 79 |
# Script parameters: |
| 80 |
# |
| 81 |
# config (required) |
| 82 |
# autoconf (optional - used by munin-config) |
| 83 |
|
| 84 |
|
| 85 |
LOG=${logfile:-/var/log/secure}
|
| 86 |
JOURNALCTL_ARGS=${journalctlargs:-_COMM=sshd}
|
| 87 |
TYPE=${type:-GAUGE}
|
| 88 |
if [ "$LOG" = "journald" -a "$TYPE" = "DERIVE" ]; then |
| 89 |
TYPE=ABSOLUTE |
| 90 |
fi |
| 91 |
|
| 92 |
|
| 93 |
if [ "$1" = "autoconf" ]; then |
| 94 |
if [ "$LOG" = "journald" ]; then |
| 95 |
# shellcheck disable=SC2086,SC2034 |
| 96 |
if journalctl --no-pager --quiet --lines=1 $JOURNALCTL_ARGS | read -r DUMMY; then |
| 97 |
echo "yes" |
| 98 |
else |
| 99 |
echo "no (journald empty log for '$JOURNALCTL_ARGS' not found)" |
| 100 |
fi |
| 101 |
else |
| 102 |
if [ -r "$LOG" ]; then |
| 103 |
echo "yes" |
| 104 |
else |
| 105 |
echo "no (logfile '$LOG' not readable)" |
| 106 |
fi |
| 107 |
fi |
| 108 |
exit 0 |
| 109 |
fi |
| 110 |
|
| 111 |
if [ "$1" = "config" ]; then |
| 112 |
echo 'graph_title SSHD login stats' |
| 113 |
echo 'graph_info SSHD login stats from' "$LOG" |
| 114 |
echo 'graph_args --base 1000 -l 0' |
| 115 |
echo 'graph_vlabel logins' |
| 116 |
echo 'graph_category' security |
| 117 |
|
| 118 |
echo 'LogPass.label Successful password logins' |
| 119 |
echo 'LogPass.min 0' |
| 120 |
echo 'LogPass.type' "$TYPE" |
| 121 |
|
| 122 |
echo 'LogPassPAM.label Successful login via PAM' |
| 123 |
echo 'LogPassPAM.min 0' |
| 124 |
echo 'LogPassPAM.type' "$TYPE" |
| 125 |
|
| 126 |
echo 'LogKey.label Successful PublicKey logins' |
| 127 |
echo 'LogKey.min 0' |
| 128 |
echo 'LogKey.type' "$TYPE" |
| 129 |
|
| 130 |
echo 'NoID.label No identification from user' |
| 131 |
echo 'NoID.min 0' |
| 132 |
echo 'NoID.type' "$TYPE" |
| 133 |
|
| 134 |
echo 'rootAttempt.label Root login attempts' |
| 135 |
echo 'rootAttempt.min 0' |
| 136 |
echo 'rootAttempt.type' "$TYPE" |
| 137 |
|
| 138 |
echo 'InvUsr.label Invalid user login attempts' |
| 139 |
echo 'InvUsr.min 0' |
| 140 |
echo 'InvUsr.type' "$TYPE" |
| 141 |
|
| 142 |
echo 'NoRDNS.label No reverse DNS for peer' |
| 143 |
echo 'NoRDNS.min 0' |
| 144 |
echo 'NoRDNS.type' "$TYPE" |
| 145 |
|
| 146 |
echo 'Breakin.label Potential Breakin Attempts' |
| 147 |
echo 'Breakin.min 0' |
| 148 |
echo 'Breakin.type' "$TYPE" |
| 149 |
|
| 150 |
exit 0 |
| 151 |
fi |
| 152 |
|
| 153 |
if [ "$LOG" = "journald" -a "$TYPE" = "ABSOLUTE" ]; then |
| 154 |
CURSOR_FILE="$MUNIN_STATEFILE" |
| 155 |
# read cursor |
| 156 |
# format: "journald-cursor <cursor>" |
| 157 |
CURSOR= |
| 158 |
if [ -f "$CURSOR_FILE" ]; then |
| 159 |
CURSOR=$(awk '/^journald-cursor / {print $2}' "$CURSOR_FILE")
|
| 160 |
fi |
| 161 |
else |
| 162 |
CURSOR_FILE= |
| 163 |
fi |
| 164 |
|
| 165 |
if [ "$LOG" = "journald" ]; then |
| 166 |
# shellcheck disable=SC2086 |
| 167 |
if [ "$TYPE" = "ABSOLUTE" ]; then |
| 168 |
journalctl --no-pager --quiet --show-cursor ${CURSOR:+"--after-cursor=$CURSOR"} $JOURNALCTL_ARGS
|
| 169 |
else |
| 170 |
journalctl --no-pager --quiet --since=$(date -dlast-sunday +%Y-%m-%d) $JOURNALCTL_ARGS |
| 171 |
fi |
| 172 |
else |
| 173 |
cat "$LOG" |
| 174 |
fi | \ |
| 175 |
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; }
|
| 176 |
/sshd\[.*Accepted password for/{c["LogPass"]++}
|
| 177 |
/sshd\[.*Accepted publickey for/{c["LogKey"]++}
|
| 178 |
/sshd\[.*Did not receive identification string/{c["NoID"]++}
|
| 179 |
/sshd\[.*Failed password for root/{c["rootAttempt"]++}
|
| 180 |
/sshd\[.*Invalid user/{c["InvUsr"]++}
|
| 181 |
/sshd\[.*POSSIBLE BREAK-IN ATTEMPT!/{c["Breakin"]++}
|
| 182 |
/sshd\[.*keyboard-interactive\/pam/{c["LogPassPAM"]++}
|
| 183 |
/sshd\[.*reverse mapping checking getaddrinfo/{c["NoRDNS"]++}a
|
| 184 |
END{if (cursor_file != "") { print "journald-cursor " $3 > cursor_file };for(i in c){print i".value " c[i]} }'
|
