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
