SELinux-Modul für NRPE und check_fail2ban erstellen
Wenn es darum geht, einen Linux-Host gegen unautorisierten Zugriff abzusichern, ist fail2ban ein sehr praktischer Dienst. Die Anwendung überwacht Protokolldateien von zahlreichen Diensten, erkennt fehlgeschlagene Login-Versuche und kann so die IP-Adressen der Angreifer sperren. Insbesondere auf öffentlichen Hosts ist es unabdingbar, einen solchen Schutz auf prominente Dienste, wie SSH, anzuwenden.
Für die Überwachung der Sperren bietet das Projekt ein eigenes Nagios-/Icinga-Plugin names check_fail2ban
an: [klick mich!]
Dieses verwendet intern das Programm fail2ban-client
zur Überprüfung der Sperren - hierfür ist übrigens auch eine sudo
-Regel für NRPE notwendig, beispielsweise für EL7:
1nrpe ALL = (root) NOPASSWD: /usr/lib64/nagios/plugins/check_fail2ban
In meiner Umgebung funktionierte das Plugin jedoch leider nicht wie erhofft.
Troubleshooting
Ein manuelles Aufrufen des konfigurierten Checks auf dem Monitoring-Server war nicht von Erfolg gekrönt:
1mon$ lib/nagios/plugins/check_nrpe -H myhost.localdomain.loc -c check_fail2ban
2NRPE: Unable to read output
Diese Fehlermeldung kann Vieles bedeuten - ein Blick in die Protokolldatei des NRPE sollte hier mehr Informationen liefern. In der dazugehörigen Konfigurationsdatei lässt sich das Debug-Protokoll aktivieren, welches etwaige Fehlermeldungen in der Regel zum Vorschein bringt:
1# vi /etc/nagios/nrpe.cfg
2...
3debug=1
4
5ESC ZZ
6
7# service nrpe restart
Je nachdem wie rsyslog
(bzw. der verwendete Logging-Dienst) konfiguriert ist, landen die Ausgaben in einer dedizierten Protokolldatei - unter EL7 muss ein Blick in die Datei /var/log/messages
geworfen werden:
1# tail -f /var/log/messages
2...
3May 27 23:59:12 myhost nrpe[11919]: Allowing connections from: 127.0.0.1,xx.xx.xx.xx
4May 27 23:59:12 myhost systemd: Started NRPE.
Unter EL7 finden sich hier leider keinerlei Informationen zu gestarteten Prozessen und Checks - bei anderen Linux-Distributionen scheint dies der Fall zu sein, etwa ein Bug?
Als nächsten Schritt aktivierte ich eine Login-Shell für den von NRPE verwendeten Benutzer und führte das Kommando mithilfe runuser
manuell aus:
1# chsh -s /bin/bash nrpe
2# runuser -l nrpe -c "/usr/lib64/nagios/plugins/check_fail2ban"
Hier gab es sachdienliche Hinweise - anscheinend machte mir sudo
einen Strich durch die Rechnung:
1sudo: sorry, you must have a tty to run sudo
sudo erwartet eine vollwertige Terminal-Sitzung zur Freigabe von erweiterten Rechten - was bei NRPE nicht der Fall ist.
Dieses Verhalten lässt sich in der sudo-Konfiguration deaktivieren:
1# visudo
2...
3#Defaults requiretty
4
5ESC ZZ
Alternativ lässt sich auch für den NRPE-Benutzer (hier nrpe
) eine Ausnahme definieren - beispielsweise in der Datei, die auch für das check_fail2ban
-Plugin benötigt wird:
1nrpe ALL = (root) NOPASSWD: /usr/lib64/nagios/plugins/check_fail2ban
2Defaults:nrpe !requiretty
Nach dem Anpassen der Konfigurationsdatei wurde der Test erneut ausgeführt - erneut war er nicht von Erfolg gekrönt. Zeit, mal einen Blick auf SELinux zu werfen und es temporär zu deaktivieren:
1# setenforce 0
2# service nrpe restart
Und siehe da, nun funktioniert das Plugin:
1mon$ lib/nagios/plugins/check_nrpe -H myhost.localdomain.loc -c check_fail2ban
2CHECK FAIL2BAN ACTIVITY - OK - 1 detected jails with 0 current banned IP(s)
Also scheint ein passendes SELinux-Modul für das Monitoring-Plugin zu fehlen, aber dazu gleich noch mehr.
Nachdem der NRPE-Benutzer als Fehlerquelle ausgeschlossen werden konnte, empfiehlt es sich, die Login-Shell wieder zu wechseln und SELinux zu aktivieren:
1# chsh -s /sbin/nologin nrpe
2# setenforce 1
SELinux-Modulbau
Wie so oft, ist SELinux hier die Fehlerquelle. Das Verhaltensmuster des Plugins ist SELinux nicht bekannt - daher wird der Zugriff unterbunden. Glücklicherweise gibt es zahlreiche Werkzeuge, um entsprechende Ausnahmeregelungen zu definieren. Sämtliche Verletzungen des Regelwerks werden in der Regel in der Datei /var/log/audit/audit.log
vermerkt - auf Basis der dort hinterlegten Informationen lassen sich entsprechende SELinux-Module erstellen, die den Zugriff erlauben. Mithilfe des Programms audit2allow
lassen sich Entwürfe solcher Module erstellen, die dann später mit semodule_package
in entsprechende Binärmodule übersetzt werden können.
Vor der Erstellung eines Modulentwurfs empfiehlt es sich, das Audit-Protokoll zu leeren und das beschränkte Programm erneut aufzurufen. Nur so ist sichergestellt, dass nur die benötigten Ausnahmen definiert werden. Laufen zum gleichen Zeitpunkt weitere Programme, die von SELinux unterdrückt werden, besteht die Gefahr, dass zu viele Ausnahmen erstellt werden. checkmodule
überprüft den korrekten Syntax des SELinux Modul-Entwurfs, semodule
installiert das Modul.
1# > /var/log/audit/audit.log
2# service nrpe restart
3(Check ausführen)
4# audit2allow >> nrpe_fail2ban.te << /var/log/audit/audit.log
5# checkmodule -M -m -o nrpe_fail2ban.mod nrpe_fail2ban.te
6# semodule_package -o nrpe_fail2ban.pp -m nrpe_fail2ban.mod
7# semodule -i nrpe_fail2ban.pp
Mithilfe von semodule
kann auch überprüft werden, ob das eben erstellte Modul geladen wurde:
1# semodule -l | grep nrpe
2nrpe_fail2ban 1.0
Zeit, den Test nochmal auszuführen - in diesem Zuge kann es nicht schaden, NRPE neu zu starten:
1# service nrpe restart
In meinem Fall wurden nun weitere Aufrufe von SELinux verworfen - also das Gleiche nochmal von vorne:
1# > /var/log/audit/audit.log ; service nrpe restart
2(Check ausführen)
3# audit2allow >> nrpe_fail2ban.te << /var/log/audit/audit.log
Mit dem audit2allow
-Aufruf haben wir einfach die erkannten Regelverstöße in Modulsyntax konvertiert und an den bereits vorhandenen Modul-Entwurf (*.te
-Datei) angehängt. Um den Syntax aufrecht zu erhalten, müssen diese nun innerhalb der Datei weiter nach oben verschoben werden. Anschließend wird erneut der Modul-Syntax überprüft, das Modul erstellt und installiert.
1# checkmodule -M -m -o nrpe_fail2ban.mod nrpe_fail2ban.te
2# semodule_package -o nrpe_fail2ban.pp -m nrpe_fail2ban.mod
3# semodule -r nrpe_fail2ban ; semodule -i nrpe_fail2ban.pp
Vor der Installation des neuen SELinux-Moduls muss das vorher aktivierte Module mit semodule -r
entfernt werden!
Ich habe den Vorgang ca. 8x wiederholt, bis ich alle benötigten Berechtigungen dokumentiert hatte:
1# cat nrpe_fail2ban.te
2
3module nrpe_fail2ban 1.0;
4
5require {
6 type nrpe_t;
7 class unix_dgram_socket sendto;
8 class file execute;
9 class file getattr;
10 class file { read getattr open };
11 class file execute_no_trans;
12 type fail2ban_client_exec_t;
13 class file { ioctl getattr };
14 class file { read open };
15 class file execute_no_trans;
16 type fail2ban_var_run_t;
17 class sock_file write;
18 class file ioctl;
19 type fail2ban_t;
20 class unix_stream_socket connectto;
21}
22
23#============= nrpe_t ==============
24allow nrpe_t self:unix_dgram_socket sendto;
25allow nrpe_t fail2ban_client_exec_t:file getattr;
26allow nrpe_t fail2ban_client_exec_t:file execute;
27allow nrpe_t fail2ban_client_exec_t:file { read open };
28allow nrpe_t fail2ban_client_exec_t:file execute_no_trans;
29allow nrpe_t fail2ban_client_exec_t:file ioctl;
30allow nrpe_t fail2ban_var_run_t:sock_file write;
31allow nrpe_t fail2ban_t:unix_stream_socket connectto;