Zum Inhalt springen

Services, Wiki-Artikel, Blog-Beiträge und Glossar-Einträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen
Linux Server Härtung: Schritt-für-Schritt Praxis-Guide für Ubuntu/Debian und - Betriebssystem-Sicherheit und Systemhaertung
Netzwerk- & Endpoint Security

Linux Server Härtung: Schritt-für-Schritt Praxis-Guide für Ubuntu/Debian und RHEL

Linux Server nach der Installation systematisch absichern: SSH-Härtung, Firewall-Konfiguration (UFW/firewalld), Fail2ban, unattended-upgrades, AppArmor/SELinux, systemd-Unit-Isolation, rootkit-Erkennung mit rkhunter und auditd für Compliance-Logging. Checklisten für Ubuntu 24.04 und RHEL 9.

Vincent Heinen Vincent Heinen Abteilungsleiter Offensive Services
12 Min. Lesezeit
OSCP+ OSCP OSWP OSWA

TL;DR

Ein frisch installierter Linux

Diese Zusammenfassung wurde KI-gestützt erstellt (EU AI Act Art. 52).

Inhaltsverzeichnis (11 Abschnitte)

Ein frisch installierter Linux-Server ist alles andere als sicher: Standard-Passwörter, offene Ports, veraltete Pakete und unnötige Dienste stellen Angriffsflächen dar. Die gute Nachricht: Linux-Server-Härtung folgt einem gut dokumentierten Prozess der in wenigen Stunden automatisiert angewendet werden kann und die Angriffsfläche dramatisch reduziert.

Grundprinzip: Minimale Angriffsfläche

Härtungs-Philosophie:

  1. Minimalprinzip:  Nur das installieren was gebraucht wird
  2. Least Privilege: Prozesse mit minimalen Rechten
  3. Defense in Depth: Mehrere Sicherheitsschichten
  4. Monitoring:       Was man nicht sieht, kann man nicht schützen

Härtungsreihenfolge:
  [1] System-Update
  [2] Benutzer und SSH
  [3] Firewall
  [4] Fail2ban / Brute-Force-Schutz
  [5] Automatische Updates
  [6] Audit-Logging (auditd)
  [7] Mandatory Access Control (AppArmor/SELinux)
  [8] Zusätzliche Tools (rkhunter, chkrootkit)
  [9] Kernel-Härtung (sysctl)
  [10] CIS-Benchmark-Prüfung

Schritt 1: System-Update und Pakete aufräumen

Direkt nach der Installation:

# Ubuntu/Debian:
apt update && apt upgrade -y
apt autoremove -y
apt autoclean

# RHEL/Rocky Linux/AlmaLinux:
dnf update -y
dnf autoremove -y

Unnötige Pakete entfernen (Beispiele):
  # Ubuntu: Typische unnötige Dienste nach Minimalinstall
  systemctl list-unit-files --type=service --state=enabled
  # Prüfen: Was ist aktiviert? Was wird wirklich gebraucht?

  # Häufig unnötig (je nach Verwendungszweck):
  systemctl disable bluetooth.service
  systemctl disable cups.service         # Drucker
  systemctl disable avahi-daemon.service # mDNS/Zeroconf
  systemctl disable rpcbind.service      # NFS (wenn nicht benötigt)
  systemctl disable telnet              # Immer deaktivieren!

  # Ubuntu: Snap-Pakete reduzieren (falls kein Snap gewünscht):
  snap list
  snap remove lxd  # Falls nicht benötigt

Dienste aufräumen (RHEL):
  systemctl disable postfix     # Falls kein lokaler MTA benötigt
  systemctl disable NetworkManager-wait-online.service  # Boot beschleunigen

Schritt 2: Benutzer und Sudo

Sichere Benutzer-Konfiguration:

Root-Login deaktivieren (nach sudo-Konfiguration!):
  # Sudo-Benutzer erstellen:
  useradd -m -s /bin/bash -G sudo admin-user  # Ubuntu
  useradd -m -s /bin/bash -G wheel admin-user # RHEL

  # Passwort setzen:
  passwd admin-user

  # Root-Passwort deaktivieren (optional, nach Sudo-Test!):
  passwd -l root

Sudo-Konfiguration (/etc/sudoers.d/admin-user):
  # IMMER visudo verwenden (Syntaxcheck)!
  visudo -f /etc/sudoers.d/admin-user

  # Inhalt:
  admin-user ALL=(ALL) ALL
  # Oder mit Passwort-Anforderung (empfohlen):
  admin-user ALL=(ALL) ALL
  # Timestamp-Timeout reduzieren:
  Defaults:admin-user timestamp_timeout=5

  # KEIN NOPASSWD für privilegierte User in Production!
  # Ausnahme: CI/CD-Accounts mit eng definierten Befehlen:
  deploy-user ALL=(ALL) NOPASSWD: /bin/systemctl restart myapp

Password-Policy (PAM):
  # /etc/security/pwquality.conf (Ubuntu):
  minlen = 14
  dcredit = -1  # mindestens 1 Ziffer
  ucredit = -1  # mindestens 1 Großbuchstabe
  lcredit = -1  # mindestens 1 Kleinbuchstabe
  ocredit = -1  # mindestens 1 Sonderzeichen
  maxrepeat = 3

  # /etc/login.defs:
  PASS_MAX_DAYS   90
  PASS_MIN_DAYS   1
  PASS_WARN_AGE   14

Schritt 3: SSH-Härtung

SSH-Konfiguration (/etc/ssh/sshd_config):

# ------- AUTHENTICATION -------
PermitRootLogin no                # Root-Login verboten!
PasswordAuthentication no         # NUR SSH-Keys erlaubt!
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PermitEmptyPasswords no
MaxAuthTries 3                    # Nach 3 Fehlversuchen Verbindung trennen
MaxSessions 2                     # Maximal 2 parallele Sessions pro Verbindung

# ------- PROTOCOL -------
Protocol 2                        # SSHv1 verboten
Port 22222                        # Alternativer Port (security through obscurity, minimal)
AddressFamily inet                # Nur IPv4 (oder inet6 für IPv6)

# ------- CIPHERS (moderne Kryptographie) -------
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com

# ------- FEATURES DEAKTIVIEREN -------
X11Forwarding no                  # X11 nicht weiterleiten
AllowAgentForwarding no           # Agent Forwarding (potenziell gefährlich)
AllowTcpForwarding no             # TCP Forwarding (wenn nicht benötigt)
PrintMotd no
PermitUserEnvironment no          # Keine Environment-Manipulation

# ------- TIMEOUTS -------
ClientAliveInterval 300           # 5 Minuten Inaktivität → Verbindung trennen
ClientAliveCountMax 2
LoginGraceTime 30                 # 30 Sekunden für Login-Prozess

# ------- BANNER -------
Banner /etc/ssh/banner.txt        # Rechtliche Warnung (wichtig für Strafverfolgung!)

# Restart:
systemctl restart sshd

# Konfiguration testen (neuen Test-SSH-Client ZUERST einloggen lassen!):
ssh -p 22222 -i ~/.ssh/id_ed25519 admin-user@server

Schritt 4: Firewall (UFW / firewalld)

Firewall-Konfiguration:

Ubuntu/Debian - UFW:
  # UFW aktivieren:
  ufw default deny incoming    # Alles blockieren
  ufw default allow outgoing   # Ausgehend erlaubt

  # Nur notwendige Dienste erlauben:
  ufw allow 22222/tcp comment 'SSH'     # Angepasster SSH-Port
  ufw allow 443/tcp comment 'HTTPS'
  ufw allow 80/tcp comment 'HTTP'

  # SSH-Quell-IP einschränken (wenn Management-IP bekannt):
  ufw allow from 10.0.0.0/8 to any port 22222 proto tcp

  # UFW aktivieren:
  ufw enable
  ufw status verbose

RHEL/Rocky - firewalld:
  # Status:
  firewall-cmd --state

  # Service dauerhaft erlauben:
  firewall-cmd --permanent --add-service=https
  firewall-cmd --permanent --add-service=http
  firewall-cmd --permanent --add-port=22222/tcp  # Angepasster SSH-Port

  # Standard SSH-Port entfernen (falls angepasst):
  firewall-cmd --permanent --remove-service=ssh

  # Reload:
  firewall-cmd --reload
  firewall-cmd --list-all

nftables direkt (für fortgeschrittene Konfiguration):
  # /etc/nftables.conf:
  table inet filter {
    chain input {
      type filter hook input priority 0; policy drop;

      # Established connections:
      ct state established,related accept
      # Loopback:
      iifname lo accept
      # ICMP (ping erlauben):
      ip protocol icmp accept
      # SSH (nur von Management-Netz):
      ip saddr 10.0.0.0/8 tcp dport 22222 accept
      # HTTPS:
      tcp dport 443 accept
    }
    chain output {
      type filter hook output priority 0; policy accept;
    }
    chain forward {
      type filter hook forward priority 0; policy drop;
    }
  }

Schritt 5: Fail2ban

Fail2ban - Brute-Force-Schutz:

Installation und Konfiguration:

  apt install fail2ban  # Ubuntu
  dnf install fail2ban  # RHEL

  # /etc/fail2ban/jail.local (NICHT jail.conf editieren!):
  [DEFAULT]
  bantime = 1h           # IP für 1 Stunde sperren
  findtime = 10m         # Innerhalb von 10 Minuten
  maxretry = 5           # 5 Fehlversuche
  banaction = ufw        # Für UFW (oder iptables, nftables)
  # Bei langen Angriffen: aggressive Einstellung:
  # bantime = 86400      # 24h
  # bantime.increment = true  # Exponentiell wachsende Ban-Zeit!
  # bantime.maxtime = 604800  # Max 7 Tage

  [sshd]
  enabled = true
  port = 22222           # Angepasster SSH-Port!
  filter = sshd
  logpath = /var/log/auth.log  # Ubuntu
  # logpath = /var/log/secure  # RHEL
  maxretry = 3           # SSH: strenger als Default

  # Weitere Jails (Nginx, Apache, etc.):
  [nginx-http-auth]
  enabled = true
  filter = nginx-http-auth
  port = http,https
  logpath = /var/log/nginx/error.log

  # Service starten:
  systemctl enable fail2ban
  systemctl start fail2ban

  # Status:
  fail2ban-client status
  fail2ban-client status sshd

  # Manuelle Entsperrung:
  fail2ban-client set sshd unbanip 192.168.1.100

Schritt 6: Automatische Updates

Unattended-Upgrades (Ubuntu):

  apt install unattended-upgrades

  # /etc/apt/apt.conf.d/50unattended-upgrades:
  Unattended-Upgrade::Allowed-Origins {
      "${distro_id}:${distro_codename}";
      "${distro_id}:${distro_codename}-security";  // Nur Security-Updates!
      // "${distro_id}:${distro_codename}-updates"; // Alle Updates (optional)
  };
  Unattended-Upgrade::Package-Blacklist {
      // "nginx";  // Pakete die NICHT automatisch updated werden
  };
  Unattended-Upgrade::AutoFixInterruptedDpkg "true";
  Unattended-Upgrade::Remove-Unused-Dependencies "true";
  Unattended-Upgrade::Mail "admin@unternehmen.de";
  Unattended-Upgrade::Automatic-Reboot "false";  // Reboot manuell!
  Unattended-Upgrade::Automatic-Reboot-Time "02:00";  // Falls Reboot aktiviert

  # Aktivieren:
  dpkg-reconfigure --priority=low unattended-upgrades

DNF Automatic (RHEL):
  dnf install dnf-automatic
  # /etc/dnf/automatic.conf:
  [commands]
  upgrade_type = security  # Nur Security-Updates
  apply_updates = yes
  reboot = never

  systemctl enable dnf-automatic-install.timer
  systemctl start dnf-automatic-install.timer

Schritt 7: Audit-Logging (auditd)

auditd - Kernel-Level Audit-Logging:

  # Installation:
  apt install auditd   # Ubuntu
  dnf install audit    # RHEL

  # /etc/audit/rules.d/security.rules:
  # Alle Datei-Attribute-Änderungen:
  -a always,exit -F arch=b64 -S chmod,chown,fchmod,fchown -k file_perms
  -a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -k chown_ops

  # sudo-Nutzung:
  -w /usr/bin/sudo -p x -k sudo_exec

  # SSH-Keys:
  -w /root/.ssh -p rwa -k ssh_root
  -w /home -p rwa -k ssh_home

  # Crontab-Änderungen:
  -w /etc/crontab -p rwa -k cron
  -w /var/spool/cron -p rwa -k cron

  # Benutzer/Gruppen:
  -w /etc/passwd -p rwa -k user_mgmt
  -w /etc/shadow -p rwa -k user_mgmt
  -w /etc/group -p rwa -k user_mgmt

  # Setuid/Setgid ausführbare Dateien:
  -a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -k root_commands

  # Netzwerkverbindungen:
  -a always,exit -F arch=b64 -S connect -k network_connect

  # Regeln laden:
  auditctl -R /etc/audit/rules.d/security.rules
  systemctl enable auditd
  systemctl restart auditd

  # Logs auswerten:
  ausearch -k sudo_exec   # Alle sudo-Ausführungen
  aureport -au            # Authentication-Report
  aureport --failed       # Fehlgeschlagene Events

Schritt 8: Kernel-Härtung (sysctl)

Kernel-Härtung via sysctl:

# /etc/sysctl.d/99-hardening.conf:

# ------- NETZWERK -------
# IP-Forwarding deaktivieren (außer bei Router/VPN-Server):
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

# ICMP Redirects ignorieren:
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0

# Source-Route-Pakete ablehnen:
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

# SYN-Flood-Schutz:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_syn_retries = 5
net.ipv4.tcp_synack_retries = 2

# Spoofing-Schutz (Reverse Path Filtering):
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Log Martians (unroutable Pakete):
net.ipv4.conf.all.log_martians = 1

# ------- KERNEL -------
# ASLR (Address Space Layout Randomization):
kernel.randomize_va_space = 2

# Core Dumps deaktivieren:
fs.suid_dumpable = 0

# kptr_restrict: keine Kernel-Adressen in /proc:
kernel.kptr_restrict = 2

# dmesg für nicht-root einschränken:
kernel.dmesg_restrict = 1

# PTrace-Scope (verhindert Prozess-Debugging durch andere User):
kernel.yama.ptrace_scope = 1

# Sysctl laden:
sysctl -p /etc/sysctl.d/99-hardening.conf

Schritt 9: AppArmor / SELinux

Mandatory Access Control:

AppArmor (Ubuntu):
  # Status:
  aa-status
  apparmor_status

  # Profile aktivieren:
  aa-enforce /etc/apparmor.d/usr.sbin.nginx
  aa-enforce /etc/apparmor.d/usr.sbin.mysqld

  # Neues Profil erstellen (Lernmodus):
  aa-genprof /usr/bin/meinprogramm
  # Programm ausführen → AppArmor lernt Access-Pattern
  aa-complain /etc/apparmor.d/meinprogramm  # Erst complain
  # Nach Tests:
  aa-enforce /etc/apparmor.d/meinprogramm   # Dann enforce

SELinux (RHEL):
  # Status:
  getenforce   # Enforcing / Permissive / Disabled
  sestatus

  # IMMER Enforcing (nie Disabled!):
  setenforce 1
  # /etc/selinux/config: SELINUX=enforcing

  # AVC-Denials anzeigen:
  ausearch -m avc -ts recent
  sealert -a /var/log/audit/audit.log

  # SELinux-Boolean setzen (Beispiel Nginx → Connect zu Backend):
  setsebool -P httpd_can_network_connect 1

  # SELinux-Kontext setzen:
  chcon -t httpd_sys_content_t /var/www/html -R
  restorecon -Rv /var/www/html

Schritt 10: CIS-Benchmark Prüfung

Automated Compliance-Prüfung:

CIS-CAT Lite (kostenlos):
  → https://www.cisecurity.org/cis-cat-lite
  → Prüft gegen CIS Benchmarks (Ubuntu, RHEL, etc.)
  → HTML-Report mit Compliance-Score

OpenSCAP (Open Source):
  # RHEL/Ubuntu:
  apt install libopenscap8 ssg-debian

  # Scan gegen CIS-Profil:
  oscap xccdf eval \
    --profile xccdf_org.ssgproject.content_profile_cis_level1_server \
    --report report.html \
    /usr/share/xml/scap/ssg/content/ssg-ubuntu2204-ds.xml

Lynis (Audit-Tool):
  apt install lynis
  lynis audit system
  # → Score + Empfehlungen + Findings
  # Typischer Hardening-Index für nicht-gehärteten Server: 40-60/100
  # Nach Härtung: 75-90/100 erreichbar

Wichtige CIS-Checks (manuell):
  □ Partition-Schema: /tmp, /var, /home auf eigenen Partitionen (noexec, nosuid)
  □ Sticky Bit auf /tmp:        chmod +t /tmp
  □ noexec auf /dev/shm:        mount -o remount,noexec,nosuid /dev/shm
  □ Keine unbekannten SUID/SGID-Dateien:
     find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -la {} \;
  □ Keine World-Writable Verzeichnisse:
     find / -type d -perm -o+w -not -path "/proc/*" -exec ls -ld {} \;
  □ Keine leeren Passwörter:
     awk -F: '($2 == "") {print $1}' /etc/shadow

Nächster Schritt

Unsere zertifizierten Sicherheitsexperten beraten Sie zu den Themen aus diesem Artikel — unverbindlich und kostenlos.

Kostenlos · 30 Minuten · Unverbindlich

Artikel teilen

Über den Autor

Vincent Heinen
Vincent Heinen

Abteilungsleiter Offensive Services

M.Sc. IT-Sicherheit mit über 5 Jahren Erfahrung in offensiver Sicherheitsanalyse. Leitet die Durchführung von Penetrationstests mit Spezialisierung auf Web-Applikationen, Netzwerk-Infrastruktur, Reverse Engineering und Hardware-Sicherheit. Verantwortlich für mehrere Responsible Disclosures.

OSCP+ OSCP OSWP OSWA
Zertifiziert ISO 27001ISO 9001AZAVBSI

Cookielose Analyse via Matomo (selbst gehostet, kein Tracking-Cookie). Datenschutzerklärung