Zum Inhalt springen
sw
en

Tippe um zu suchen

Linux

Linux-Server-Hardening: Sicherheits-Checkliste für KMU

CIS-Benchmarks, SELinux/AppArmor, auditd, automatische Updates und Fail2ban richtig kombinieren, um Linux-Server im KMU-Umfeld nachhaltig abzusichern.

12 Min Lesezeit Expert Zuletzt aktualisiert:

Warum Hardening kein “Nice-to-have” ist

Ein frisch installierter Linux-Server ist nie fertig gehärtet – egal ob Ubuntu Server, Debian oder RHEL/Rocky. Die Standard-Installation priorisiert Kompatibilität und Bedienbarkeit, nicht Sicherheit. Genau das nutzen automatisierte Scanner aus: Innerhalb von Minuten nach dem ersten Internet-Kontakt registrieren SSH-Ports auf ungeschützten Servern tausende Brute-Force-Versuche pro Tag.

Für ein Schweizer KMU mit begrenztem IT-Team bedeutet das: Du kannst nicht jeden Server manuell nach Bauchgefühl absichern. Du brauchst eine wiederholbare, dokumentierte und im Idealfall automatisierte Checkliste – genau das liefern CIS-Benchmarks in Kombination mit den Werkzeugen in diesem Artikel.

CIS-Benchmark-Grundlagen

Das Center for Internet Security (CIS) veröffentlicht für praktisch jede relevante Distribution einen eigenen Benchmark – kostenlos als PDF unter cisecurity.org, mit rund 150–300 Einzelkontrollen je nach OS und Version. Die Kontrollen sind in zwei Profile aufgeteilt:

  • Level 1 (L1): Praxistaugliche Basis-Härtung ohne relevante Funktionseinbussen. Für praktisch jeden Server geeignet – das ist dein Startpunkt.
  • Level 2 (L2): Defense-in-Depth für Hochsicherheitsumgebungen. Kann Funktionalität einschränken (z.B. deaktivierte USB-Speicher, sehr restriktive Kernel-Parameter) – vorher testen.

Jede Kontrolle folgt demselben Schema: Beschreibung, Rationale, Audit-Befehl (wie prüfst du den Ist-Zustand), Remediation (wie behebst du Abweichungen) und Referenzen (z.B. MITRE ATT&CK, NIST 800-53).

Typische L1-Kontrollen im Überblick

BereichBeispielkontrollePrüfbefehl
Dateisystem/tmp mit noexec,nosuid mountenmount | grep /tmp
Kernel-ModuleUnnötige Protokolle (z.B. dccp, sctp) deaktivierenmodprobe -n -v dccp
NetzwerkIP-Forwarding aus, wenn kein Routersysctl net.ipv4.ip_forward
SSHRoot-Login per Passwort verbotensshd -T | grep permitrootlogin
Auditingauditd aktiv und Regeln geladenauditctl -s
ZugriffPasswort-Ablauf max. 365 Tagegrep PASS_MAX_DAYS /etc/login.defs
DiensteUnnötige Dienste deaktiviert (avahi, cups, rpcbind)systemctl is-enabled avahi-daemon

Compliance automatisiert prüfen: OpenSCAP und Lynis

Statt jede Kontrolle manuell durchzuklicken, nutzt du Scanner, die gegen den Benchmark prüfen:

# OpenSCAP: offizielle SCAP-Content-Pakete für RHEL/Rocky/Ubuntu
sudo dnf install -y openscap-scanner scap-security-guide

# Verfügbare Profile auflisten (u.a. CIS-Profile)
oscap info /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

# CIS-Level-1-Scan fahren und HTML-Report erzeugen
sudo oscap xccdf eval \
  --profile xccdf_org.ssgproject.content_profile_cis \
  --report /root/cis-report.html \
  /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
# Lynis: schnellerer, distributionsunabhängiger Health-Check
sudo apt install -y lynis        # Debian/Ubuntu
sudo lynis audit system

# Ergebnis: Hardening-Index (0-100) + priorisierte Empfehlungen
# Logfile für spätere Auswertung:
cat /var/log/lynis-report.dat

Lynis liefert dir einen “Hardening Index” als Kennzahl – ideal, um Fortschritt über Zeit zu dokumentieren (z.B. für interne Audits oder Kundennachweise). OpenSCAP ist formaler und mappt direkt auf CIS-Kontrollnummern, was für externe Auditoren oft verlangt wird.

SELinux vs. AppArmor: Mandatory Access Control richtig einsetzen

Klassische Unix-Rechte (rwx für User/Group/Other) sind Discretionary Access Control (DAC) – der Dateibesitzer entscheidet über Zugriff. Das Problem: Wird ein Prozess kompromittiert (z.B. eine verwundbare Webanwendung), erbt der Angreifer automatisch alle Rechte dieses Prozesses. Mandatory Access Control (MAC) setzt eine zusätzliche, vom Kernel erzwungene Ebene darüber, die selbst root nicht ohne Weiteres umgehen kann.

Beide Systeme sind Kernel-Module (Linux Security Modules, LSM) und schliessen sich gegenseitig aus – du kannst nicht beide gleichzeitig aktiv nutzen.

KriteriumSELinuxAppArmor
ModellLabel-basiert (Security-Context je Datei/Prozess)Pfad-basiert (Profile pro Programmpfad)
Standard beiRHEL, Rocky Linux, AlmaLinux, Fedora, CentOS StreamUbuntu, Debian, SUSE, openSUSE
LernkurveSteil – Contexts, Types, Booleans, Policy-ModuleFlacher – Profile lesen sich fast wie Klartext
GranularitätSehr fein (auch Netzwerk-Sockets, Capabilities)Gröber, dateisystemorientiert
Troubleshootingaudit2allow, ausearch, SELinux-Logs in auditdaa-logprof, dmesg, eigenes AppArmor-Log
Container-IsolationStärker (MCS trennt Container sauber voneinander)Schwächer, kein MCS-Äquivalent
Typischer Modus in Produktionenforcingenforce

SELinux in der Praxis

# Aktuellen Modus prüfen
getenforce
# Ergebnis: Enforcing / Permissive / Disabled

# Temporär auf Permissive schalten (nur für Troubleshooting!)
sudo setenforce 0

# Dauerhaft in /etc/selinux/config setzen
sudo sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config

# Security-Context einer Datei anzeigen
ls -Z /var/www/html/index.html

# Häufigstes Problem: Webserver kann Datei nicht lesen, obwohl DAC-Rechte passen
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/webdata(/.*)?"
sudo restorecon -Rv /srv/webdata

# Verweigerte Zugriffe der letzten Stunde analysieren
sudo ausearch -m avc -ts recent
# Sauberer Workflow: aus Denials ein eigenes Policy-Modul bauen
sudo ausearch -m avc -ts recent | audit2allow -M mein_modul
sudo semodule -i mein_modul.pp

AppArmor in der Praxis

# Status und geladene Profile anzeigen
sudo aa-status

# Profil eines Programms im "complain mode" testen (loggt, blockiert aber nicht)
sudo aa-complain /usr/sbin/nginx

# Nach Testphase in den Enforce-Modus wechseln
sudo aa-enforce /usr/sbin/nginx

# Profil aus geloggten Ereignissen interaktiv verfeinern
sudo aa-logprof

Entscheidungshilfe für den KMU-Alltag: Bleib auf der Distribution, die dein Team bereits kennt – ein schlecht gepflegtes SELinux-System (weil “disabled” gesetzt) ist schlechter als ein sauber konfiguriertes AppArmor-System. Wenn du frei wählst und Container-Workloads (Docker/Kubernetes) im Fokus stehen, spricht die stärkere Container-Isolation für RHEL-Familie mit SELinux.

auditd: Sicherheitsrelevante Ereignisse lückenlos protokollieren

Standard-Syslog protokolliert, dass etwas passiert ist (“Service gestartet”). auditd protokolliert wer wann was mit welcher Datei oder welchem Systemaufruf gemacht hat – bis auf Kernel-Ebene, unveränderbar für normale User, und das ist genau das, was du für Incident-Response und Compliance-Nachweise brauchst.

# Installation (meist vorinstalliert, sonst nachholen)
sudo apt install -y auditd audispd-plugins    # Debian/Ubuntu
sudo dnf install -y audit audit-libs          # RHEL/Rocky

# Dienst aktivieren
sudo systemctl enable --now auditd

Sinnvolle Basis-Regeln für KMU-Server

Regeln liegen in /etc/audit/rules.d/ (persistente Regeln, überleben Neustart und werden von augenrules kompiliert):

# /etc/audit/rules.d/hardening.rules

## Alle Änderungen an Nutzer- und Gruppendatenbanken
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/sudoers -p wa -k sudoers_change
-w /etc/sudoers.d/ -p wa -k sudoers_change

## SSH-Konfigurationsänderungen
-w /etc/ssh/sshd_config -p wa -k sshd_config

## Fehlgeschlagene Zugriffsversuche auf Dateien (EACCES/EPERM)
-a always,exit -F arch=b64 -S open,openat -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access_denied

## Nutzung von privilegierten Befehlen (Rechteausweitung nachvollziehbar machen)
-a always,exit -F arch=b64 -S execve -F path=/usr/bin/sudo -k privilege_escalation

## Änderungen an Systemzeit (typisch bei Log-Manipulation)
-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time_change

## Regeln nach dem Booten unveränderbar machen (nur nach ausgiebigem Testen!)
-e 2
# Regeln laden und Status prüfen
sudo augenrules --load
sudo auditctl -l
sudo systemctl restart auditd

# Ereignisse durchsuchen
sudo ausearch -k sudoers_change
sudo ausearch -k identity --start today

# Kompakte Zusammenfassung pro Regel-Key
sudo aureport --summary
sudo aureport -au   # Authentifizierungs-Report

Die Zeile -e 2 am Ende macht die Audit-Konfiguration erst nach einem Neustart wieder änderbar – das verhindert, dass ein Angreifer mit root-Rechten seine Spuren durch Anpassen der Audit-Regeln verwischt. Setze das aber erst produktiv, wenn du sicher bist, dass die Regeln stimmen, sonst brauchst du für jede Anpassung einen Reboot.

Automatische Sicherheitsupdates: unattended-upgrades und dnf-automatic

Die statistisch häufigste Einfallschneise ist keine Zero-Day-Lücke, sondern eine seit Monaten bekannte, ungepatchte CVE. Automatisierte Security-Updates schliessen dieses Fenster, ohne dass du jeden Server einzeln per Hand patchen musst.

Debian/Ubuntu: unattended-upgrades

sudo apt install -y unattended-upgrades apt-listchanges
sudo dpkg-reconfigure --priority=low unattended-upgrades
# /etc/apt/apt.conf.d/50unattended-upgrades (Auszug)
Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}-security";
    "${distro_id}ESMApps:${distro_codename}-apps-security";
};

// Automatischer Reboot bei kernelrelevanten Updates
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "03:30";

// Nicht mehr benötigte Pakete gleich mit entfernen
Unattended-Upgrade::Remove-Unused-Dependencies "true";

// Bei Fehlern Mail an das IT-Team
Unattended-Upgrade::Mail "it-team@firma.ch";
Unattended-Upgrade::MailOnlyOnError "true";
# /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
# Trockenlauf zur Kontrolle, bevor produktiv aktiviert wird
sudo unattended-upgrade --dry-run --debug

RHEL/Rocky/AlmaLinux: dnf-automatic

sudo dnf install -y dnf-automatic
# /etc/dnf/automatic.conf (Auszug)
[commands]
upgrade_type = security
apply_updates = yes

[emitters]
emit_via = stdio,command
sudo systemctl enable --now dnf-automatic.timer
systemctl list-timers dnf-automatic.timer

Für reine Nicht-Security-Updates (Funktions-Updates, neue Major-Versionen) empfiehlt sich weiterhin ein manuell getriggerter, getesteter Patch-Zyklus über eine zentrale Lösung – Details dazu unter WSUS & Patchmanagement (Prinzipien lassen sich auf Linux-Pendants wie Landscape oder Foreman/Katello übertragen).

Fail2ban und Intrusion Detection

Fail2ban überwacht Logdateien (SSH, Webserver, Mailserver, …) auf wiederholte Fehlversuche und sperrt die Quell-IP automatisch über die lokale Firewall. Es ersetzt keine echte Intrusion-Detection, reduziert aber automatisierte Brute-Force-Kampagnen drastisch – oft der grösste Teil des ungewollten Traffics auf öffentlich erreichbaren SSH-Ports.

sudo apt install -y fail2ban       # Debian/Ubuntu
sudo dnf install -y fail2ban       # RHEL/Rocky (Repo epel-release ggf. nötig)
# /etc/fail2ban/jail.local – NIEMALS jail.conf direkt editieren
[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
# Eigene Management-IPs und VPN-Range nie sperren
ignoreip = 127.0.0.1/8 ::1 10.20.0.0/24

[sshd]
enabled = true
port    = 2222
backend = systemd

[recidive]
# Wiederholungstäter (mehrfach gebannt) langfristig aussperren
enabled  = true
bantime  = 1w
findtime = 1d
maxretry = 5
sudo systemctl enable --now fail2ban

# Aktive Jails und gebannte IPs prüfen
sudo fail2ban-client status
sudo fail2ban-client status sshd

# IP manuell entsperren (z.B. eigener Aussendienst-Mitarbeiter ausgesperrt)
sudo fail2ban-client set sshd unbanip 203.0.113.44

Einordnung: Fail2ban vs. echte Intrusion Detection

Fail2ban ist reaktiv und regelbasiert (Log-Pattern-Matching), keine verhaltensbasierte Erkennung. Für tiefere Sichtbarkeit ergänzt du je nach Schutzbedarf:

WerkzeugFunktionEinsatzschwerpunkt
Fail2banLog-Pattern → IP-Ban via FirewallBrute-Force auf SSH/Web/Mail
AIDE / TripwireDatei-Integritätsprüfung (Host-based IDS)Erkennung veränderter Binaries/Configs
Wazuh / OSSECLog-Korrelation, File Integrity, Rootkit-CheckZentrales HIDS über viele Server
CrowdSecCommunity-basierte, verteilte BedrohungserkennungErgänzung/Ersatz für Fail2ban mit Threat-Intel
auditd + SIEMKernel-nahe EreignisprotokollierungForensik, Compliance, Nachvollziehbarkeit

Für ein typisches Schweizer KMU mit 5-30 Linux-Servern ist die Kombination Fail2ban + auditd + zentrales Log-Shipping in ein leichtgewichtiges SIEM (siehe SIEM & SOC Grundlagen) meist der richtige Sweet Spot zwischen Aufwand und Nutzen. AIDE lohnt sich zusätzlich für Server mit hohem Schutzbedarf (z.B. Zertifizierungsstelle, Finanzsysteme).

Minimal-Installation und Angriffsfläche reduzieren

Jeder installierte Dienst, jedes offene Paket ist potenzielle Angriffsfläche – auch wenn er “nur zufällig mitinstalliert” wurde. Das Prinzip lautet: so wenig wie möglich, so viel wie nötig.

Schritt-für-Schritt-Ablauf bei der Erstinstallation

  1. Minimal-ISO/Cloud-Image wählen statt Desktop- oder “Everything”-Variante (z.B. ubuntu-24.04-live-server, RHEL “Minimal Install”-Gruppe).
  2. Partitionierung mit getrennten Mountpoints/tmp, /var/log, /home separat mounten, damit du dort noexec, nosuid, nodev setzen kannst.
  3. Unnötige Pakete direkt nach Installation entfernen:
    # Unbenutzte Netzwerkdienste identifizieren
    sudo systemctl list-unit-files --state=enabled | grep -E 'avahi|cups|rpcbind'
    sudo systemctl disable --now avahi-daemon cups rpcbind
    sudo apt purge -y avahi-daemon cups rpcbind
  4. Offene Ports inventarisieren und alles ohne klaren Zweck schliessen:
    sudo ss -tulpn
    sudo firewall-cmd --list-all           # RHEL/firewalld
    sudo ufw status verbose                # Ubuntu/ufw
  5. Unnötige Kernel-Module blockieren (Beispiel: seltene Netzwerkprotokolle, USB-Storage auf Servern ohne physischen Zugriff):
    # /etc/modprobe.d/hardening.conf
    install dccp /bin/false
    install sctp /bin/false
    install usb-storage /bin/false
  6. Root-Login und unnötige lokale Accounts deaktivieren:
    sudo passwd -l root
    sudo usermod -L -e 1 gast_account   # Sofort ablaufen lassen statt löschen (Audit-Spur)
  7. Automatisierten Scan zur Bestätigung fahren (Lynis/OpenSCAP wie oben) und Ergebnis dokumentieren.

Entscheidungsbaum: Wie aggressiv härte ich diesen Server?

Ist der Server aus dem Internet erreichbar (Port 22/443 offen)?
├── Ja → CIS L1 + L2 wo praktikabel, Fail2ban Pflicht, auditd mit vollen Regeln,
│        automatische Security-Updates, MAC im enforcing/enforce-Modus
└── Nein, nur internes LAN
    ├── Verarbeitet er Finanz-/Personendaten (DSG/DSGVO-relevant)?
    │   ├── Ja → CIS L1 + ausgewählte L2-Kontrollen, auditd Pflicht,
    │   │        Updates automatisiert mit Testfenster, MAC enforcing
    │   └── Nein → CIS L1 als Baseline, auditd Basis-Regeln,
    │             Updates automatisiert, MAC im Default-Modus der Distro belassen

Checkliste zum Abhaken

  • Minimal-Installation verwendet, unnötige Pakete/Dienste entfernt
  • SSH: Key-Auth erzwungen, Root-Login und Passwort-Login deaktiviert, Port ggf. geändert
  • Firewall aktiv mit Default-Deny-Policy (ufw/firewalld/nftables)
  • MAC-System (SELinux/AppArmor) im enforcing/enforce-Modus, nicht disabled
  • auditd aktiv mit Basis-Regeln für /etc/passwd, /etc/sudoers, SSH-Config
  • Automatische Security-Updates konfiguriert und getestet (Dry-Run geprüft)
  • Fail2ban aktiv für SSH und alle exponierten Dienste, ignoreip korrekt gepflegt
  • Lynis/OpenSCAP-Scan durchgeführt, Ergebnis dokumentiert und Baseline festgehalten
  • Getrennte Partitionen für /tmp, /var/log, /home mit noexec/nosuid wo sinnvoll
  • Zentrales Log-Shipping an SIEM/Log-Server eingerichtet

Weiterlernen

Verwandte Themen: SSH – Grundlagen & Schlüsselverwaltung, Linux Firewall: iptables & nftables, SIEM & SOC Grundlagen, NIS-2 für KMU Schweiz, Ansible: Playbooks, Inventory, Vault, IT-Security Grundlagen für KMU

Kommentare

Frage, Verbesserungsvorschlag oder eigene Erfahrung zu diesem Artikel? Schreib einen Kommentar. Neue Beiträge erscheinen nach kurzer Moderation.

  • Lade Kommentare …
Kommentar schreiben