Bei einem erfolgreichen SSH-Login auf meinem RaspberryPi möchte ich eine Benachrichtigung per E-Mail erhalten, so dass ich unautorisierte Logins frühzeitig erkennen und Gegenmaßnahmen einleiten kann.

Mit folgenden einfachen Schritten lässt sich eine einfache Login-Überwachung und -Alarmierung mit Linux-Boardmitteln (Named Pipes) umsetzen:

1. In /etc/ssh/sshd_config dafür sorge tragen, dass eine korrekte Login-Facility eingetragen ist.

# Logging
SyslogFacility AUTH
LogLevel INFO

2. Anschließen den Syslog-Daemon anpassen, so dass die Daten in eine Named Pipe geschrieben werden. Daher passend zur sshd_config folgenden Eintrag zur rsyslog.conf hinzufügen und den Syslog-Daemon mit sudo service rsyslog restart neu starten:

# Auth-Logs zusätzlich zu /var/logs/auth.log auch in die Named Pipe schreiben 
auth.*                          |/var/run/sshwatcher.pipe

3. Anschließen das Skript zur Überwachung erstellen und mit chmod 755 /usr/local/sbin/sshwatcher.sh  ausführbar machen. Beim erstellen des Scriptes darauf achten, dass die Konfigurationsparameter am Anfang des Scriptes entsprechend angepasst werden. Mit dem Whitelisting-Parameter können IP-Adressen bzw. DDNS-Namen hinterlegt werden von denen aus ein Login ohne Benachrichtigung aus möglich sein soll.

#!/bin/bash

# Pfad zur Named-Pipe, die überwacht werden soll
P=/var/run/sshwatcher.pipe

# Einstellungen für den E-Mailversand
rcpt="empfaenger@mailadresse.de"
sender="absender@mailadresse.de"
konto="username"
passwrd="passwort"
provider="mailserver.domain.de"

# Liste mit IP-Adressen und Domain-Namen, von denen beim Einloggen keine 
# E-Mail versendet werden soll. IP-Adressen können host oder Class-C 
# Netzwerkadressen (z.B. 192.168.1.0) sein
whitelist_ips=('192.168.0.0' '192.168.0.2')
whitelist_ddns=( 'test.dyndns.com' )

# Hilfsfunktion prüft, ob ein Element in einer Liste vorkommt
elementIn () {
  local e
  for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
  return 1
}

# Wenn die Named-Pipe nicht existiert, dann anlegen.
test -p $P || mkfifo $P

# Beispieleintrag in der Logdatei
# "Jun 22 22:44:16 raspberrypi sshd[17597]: Accepted publickey for user from 
#                  192.168.100.123 port 3011 ssh2

while read x <$P; do

        # IP-Adresse extrahieren, von der eingeloggt wurde
        ip=`echo $x | sed -re 's/^.*sshd\[.*Accepted.*from (([0-9]{1,3}\.){3}[0-9]{1,3}).*$/\1/'`
        # aus der IP-Adresse Class-C-Netz machen
        net=`echo $ip | sed -re 's/[0-9]{1,3}$/0/'`

        # Vollständige Whitelist generieren (inkl. Namensauflösung )
        whitelist=("${whitelist_ips[@]}")
        for i in "${whitelist_ddns[@]}" ; do
                whitelist=("${whitelist[@]}" `host $i | cut -f 4 -d ' '`)
        done

        # wenn die Login-IP nicht in der Whitelist ist, dann eine Mail generieren
        if ! (elementIn "$ip" "${whitelist[@]}" || elementIn "$net" "${whitelist[@]}" ) ; then
                datum=`date +"%Y-%m-%d | %T"`
                subject="[Raspi] SSH-Login am $datum"
                message=`echo $x | grep -E "sshd[[0-9]*\]: Accepted" | sed -r 's/^.+: //'`

                logger "[sshwatcher.sh] Sending email (RCP: $rcpt Subject: $subject Text: $text)"
                ret=`sendEmail -f $sender -t $rcpt -u $subject -m $message -s $provider -xu $konto -xp $passwrd -o tls=yes`
                # Damit sendEmail TLS/SSL funktioniert muss /usr/share/perl5/IO/Socket/SSL.pm 
                # hin Zeile 308 angepasst werden:
                # Ersetze:
                #       m{^(!?)(?:(SSL(?:v2|v3|v23|v2/3))|(TLSv1[12]?))$}i
                # durch:
                #       m{^(!?)(?:(SSL(?:v2|v3|v23|v2/3))|(TLSv1[12]?))}i
                logger "[sshwatcher.sh] SendEmail returned: $ret"
        else
                logger "[sshwatcher.sh] Login from whitelisted IP/Net (IP: $ip); no mail sent"
        fi;

        unset  whitelist
done;

4. Nun kann das Script geprüft werden. Dazu das Script einfach als Root starten und einloggen. Wenn alles korrekt funktioniert, sollte unter /var/log/syslog entsprechende Meldungen beim einloggen auftauchen. Wenn die IP-Adresse nicht in der Whitelist ist und die Zugangsdaten für den E-Mail-Account korrekt gesetzt wurden, sollte auch eine Mail verschickt werden.

Aufgrund eines Fehler funktioniert die SSL/TLS-verschlüsselte Übertragung der E-Mail mit dem Programm sendEmail leider nicht korrekt. Bei mir hat es gereicht die Datei /usr/share/perl5/IO/Socket/SSL.pm wie im Script beschrieben anzupassen. Alertnativ kann die Option -o tls=no bei sendEmail verwendet werden. Dann werden allerdings die Zugangsdaten im Klartext übertragen.

5. Abschließend muss noch dafür Sorge getragen werden, dass das Script beim Systemstart ausgeführt wird. Dazu folgenden Eintrag in der /etc/inittab ergänzen und danach den inittab mit sudo init q  neu laden:

sw0:2345:respawn:/usr/local/sbin/sshwatcher.sh