# Ubuntu Server absichern (Hardening) – Leitfaden für Ubuntu 24.04 LTS

**Zielgruppe:** Systemintegratoren, Admins und alle, die einen frisch installierten Ubuntu-Server produktiv betreiben wollen
**Plattform:** Ubuntu Server 24.04 LTS (prinzipiell übertragbar auf 22.04 LTS und Debian)
**Ergebnis:** Ein nach Best Practices abgesicherter Server – minimierte Angriffsfläche, gehärteter SSH-Zugang, aktive Firewall, Brute-Force-Schutz, automatische Sicherheitsupdates, Kernel- und Dateisystem-Härtung sowie Logging/Auditing.

---

## 1. Grundprinzipien & Vorbereitung

Bevor ein einziger Befehl läuft, gelten vier Grundregeln:

* **Minimalismus:** Was nicht installiert ist, kann nicht angegriffen werden.
* **Least Privilege:** Jeder Dienst und jeder Benutzer bekommt nur die Rechte, die er wirklich braucht.
* **Defense in Depth:** Nie auf eine einzelne Maßnahme verlassen – Firewall UND sichere SSH-Config UND Fail2ban.
* **Nachvollziehbarkeit:** Jede Änderung dokumentieren; Änderungen an Config-Dateien vorher sichern (`sudo cp datei datei.bak`).

Alle folgenden Befehle laufen als frisch angelegter Benutzer mit sudo-Rechten bzw. initial als root auf einem Neu-System.

> **Wichtig:** Diese Schritte niemals ungetestet per Copy & Paste auf einem Produktivsystem ausführen. Bei Remote-Servern immer eine zweite SSH-Session offen halten, bevor Firewall- oder SSH-Änderungen aktiviert werden – sonst droht der Selbstausschluss.

---

## 2. System aktualisieren

Der erste Schritt nach jeder Installation: alle Pakete auf den neuesten Stand bringen, um bereits bekannte Lücken zu schließen.

```bash
sudo apt update && sudo apt full-upgrade -y
sudo apt autoremove -y
sudo reboot
```

* `apt update` aktualisiert die Paketlisten, `full-upgrade` installiert alle Updates inkl. Abhängigkeitsänderungen.
* `autoremove` entfernt verwaiste Abhängigkeiten.
* Der Reboot stellt sicher, dass ein eventuell aktualisierter Kernel auch geladen wird.

Nach dem Neustart prüfen, ob der aktuelle Kernel läuft:

```bash
uname -r
```

---

## 3. Benutzer- und Rechteverwaltung

### 3.1 Dedizierten Admin-Benutzer anlegen

Niemals dauerhaft als root arbeiten. Einen eigenen Benutzer anlegen und in die sudo-Gruppe aufnehmen:

```bash
sudo adduser deploy
sudo usermod -aG sudo deploy
```

* `adduser` legt Benutzer inkl. Home-Verzeichnis und Passwort an.
* Die Mitgliedschaft in der Gruppe `sudo` erlaubt das Ausführen von Admin-Befehlen mit eigenem Passwort.

### 3.2 Root-Login sperren

Das root-Konto hat kein Passwort-Login nötig – sperren verhindert direkte root-Anmeldungen:

```bash
sudo passwd -l root
```

* `-l` (lock) sperrt das Passwort; root kann weiterhin über `sudo -i` oder `su` von sudo-Berechtigten genutzt werden.

### 3.3 Passwort-Richtlinien erzwingen

```bash
sudo apt install libpam-pwquality -y
sudo nano /etc/security/pwquality.conf
```

Empfohlene Werte (Zeilen einkommentieren/anpassen):

```
minlen = 14
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1
maxrepeat = 3
```

* Erzwingt mindestens 14 Zeichen sowie Groß-/Kleinbuchstaben, Ziffern und Sonderzeichen.
* Gilt für alle lokalen Passwortänderungen (`passwd`).

### 3.4 sudo absichern

```bash
sudo visudo
```

* `visudo` prüft die Syntax vor dem Speichern – ein Tippfehler in `sudoers` kann sonst alle Admins aussperren.
* Optional: Logging aller sudo-Befehle aktivieren, indem folgende Zeile ergänzt wird:

```
Defaults logfile="/var/log/sudo.log"
```

### 3.5 Umask verschärfen

```bash
sudo nano /etc/login.defs
```

Wert `UMASK` auf `027` setzen.

* Neue Dateien sind damit standardmäßig nur für Besitzer les-/schreibbar und für die Gruppe lesbar – nicht für die ganze Welt.

---

## 4. SSH absichern

SSH ist der häufigste Angriffsvektor auf Server. Die Konfiguration erfolgt sauber über eine Drop-in-Datei statt direkt in `sshd_config`.

### 4.1 Schlüsselbasierte Anmeldung einrichten

Auf dem **lokalen Client** (nicht auf dem Server):

```bash
ssh-keygen -t ed25519 -C "deploy@server"
ssh-copy-id deploy@SERVER-IP
```

* `ed25519` ist der moderne Standard – schnell und sicher.
* `ssh-copy-id` überträgt den öffentlichen Schlüssel nach `~/.ssh/authorized_keys` auf dem Server.

**Erst nach erfolgreichem Schlüssel-Login weitermachen.**

### 4.2 sshd härten

```bash
sudo nano /etc/ssh/sshd_config.d/99-hardening.conf
```

Inhalt:

```
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
MaxAuthTries 3
LoginGraceTime 20
AllowUsers deploy
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
```

* `PermitRootLogin no` – root darf sich nie direkt per SSH anmelden.
* `PasswordAuthentication no` – nur noch Schlüssel, keine Passwort-Brute-Force mehr möglich.
* `AllowUsers deploy` – nur dieser Benutzer darf sich per SSH anmelden (Whitelist).
* `MaxAuthTries 3` / `LoginGraceTime 20` – reduziert Brute-Force-Versuche.
* Deaktivierte Forwardings verhindern Missbrauch des Servers als Tunnel/Pivot.

### 4.3 Konfiguration testen und Dienst neu starten

```bash
sudo sshd -t
sudo systemctl restart ssh
```

* `sshd -t` validiert die Konfiguration, ohne den Dienst zu stoppen. Nur bei fehlerfreier Ausgabe neu starten.
* **Zweite Session offen halten** und in einem neuen Terminal testen: `ssh deploy@SERVER-IP`.

### 4.4 Optional: SSH-Port ändern

```
Port 2222
```

* Das ist „Security by Obscurity" – es reduziert Log-Müll durch Scanner, ersetzt aber keine echte Absicherung. Bei Änderung den neuen Port in der Firewall freigeben (Kapitel 6), **bevor** man sich trennt.

---

## 5. Optional: Zwei-Faktor-Authentifizierung (2FA) für SSH

Zusätzliche Hürde: neben dem SSH-Schlüssel ein zeitbasiertes Einmalpasswort (TOTP) per Authenticator-App.

```bash
sudo apt install libpam-google-authenticator -y
google-authenticator
```

* `google-authenticator` als der SSH-Benutzer ausführen (nicht root) – es erzeugt einen QR-Code für die App (Aegis, Google Authenticator, …).
* Die angezeigten Notfall-Codes sicher verwahren.

Anschließend PAM und sshd konfigurieren:

```bash
sudo nano /etc/pam.d/sshd
```

Folgende Zeile am Ende ergänzen:

```
auth required pam_google_authenticator.so
```

In der Hardening-Drop-in-Datei ergänzen:

```
KbdInteractiveAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
```

Danach `sudo sshd -t` und `sudo systemctl restart ssh`.

* `AuthenticationMethods publickey,keyboard-interactive` erzwingt **beides**: Schlüssel UND TOTP-Code.

---

## 6. Firewall mit UFW

UFW (Uncomplicated Firewall) ist das Frontend für nftables unter Ubuntu.

```bash
sudo apt install ufw -y
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status verbose
```

* `deny incoming` – alles eingehende ist grundsätzlich verboten (Default-Deny).
* `allow OpenSSH` – öffnet Port 22 (bei geändertem Port: `sudo ufw allow 2222/tcp`).
* Für jede weitere Rolle nur gezielt freigeben, z. B. Webserver: `sudo ufw allow 'Nginx Full'`, `sudo ufw allow 443/tcp`.

Sicherheitssteigerung für SSH (Rate-Limiting statt blanket allow):

```bash
sudo ufw limit ssh
```

* `limit` blockiert IPs temporär, die mehr als 6 Verbindungen in 30 Sekunden aufbauen – einfacher Brute-Force-Schutz auf Firewall-Ebene.

Regeln prüfen/löschen:

```bash
sudo ufw status numbered
sudo ufw delete 3
```

---

## 7. Fail2ban – Brute-Force-Schutz

Fail2ban wertet Logdateien aus und sperrt Angreifer-IPs dynamisch per Firewall.

```bash
sudo apt install fail2ban -y
sudo nano /etc/fail2ban/jail.local
```

Inhalt:

```
[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
backend  = systemd

[sshd]
enabled = true
port    = ssh
logpath = %(sshd_log)s
```

* Nie die mitgelieferte `jail.conf` bearbeiten – lokale Anpassungen gehören in `jail.local` (update-sicher).
* `bantime 1h` – gesperrte IP bleibt 1 Stunde draußen; `maxretry 5` – nach 5 Fehlversuchen in 10 Minuten greift die Sperre.

Dienst aktivieren und prüfen:

```bash
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
```

* `fail2ban-client status sshd` zeigt aktuell gesperrte IPs und Statistiken.

---

## 8. Automatische Sicherheitsupdates

```bash
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades
```

Konfiguration prüfen/anpassen:

```bash
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
```

Empfohlene aktive Optionen:

```
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
```

* Installiert täglich automatisch Sicherheitsupdates aus den `-security`-Repositories.
* Automatischer Reboot bleibt auf Servern meist deaktiviert (`false`) – stattdessen regelmäßig prüfen:

```bash
ls /var/run/reboot-required
```

* Existiert die Datei, steht ein Neustart an (z. B. nach Kernel-Update) – im Wartungsfenster einplanen.

---

## 9. Netzwerk-Härtung (Kernel-Parameter per sysctl)

```bash
sudo nano /etc/sysctl.d/99-hardening.conf
```

Inhalt:

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

# Source Routing verbieten
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

# ICMP-Redirects ignorieren/verwerfen (kein Router!)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv6.conf.all.accept_redirects = 0

# SYN-Flood-Schutz
net.ipv4.tcp_syncookies = 1

# Pakete mit unmöglichen Absenderadressen loggen
net.ipv4.conf.all.log_martians = 1

# Fehlerhafte ICMP-Pakete ignorieren
net.ipv4.icmp_ignore_bogus_error_responses = 1
```

Aktivieren ohne Neustart:

```bash
sudo sysctl --system
```

* `rp_filter` verwirft Pakete mit gefälschten Absender-IPs.
* `send_redirects = 0` ist Pflicht auf Servern – nur Router dürfen ICMP-Redirects senden.
* `tcp_syncookies` schützt vor SYN-Flood-DoS-Angriffen.

> **IPv6:** Wird IPv6 im Netz nicht verwendet, sollte es komplett deaktiviert werden (weniger Angriffsfläche): `net.ipv6.conf.all.disable_ipv6 = 1` ergänzen. Wird es genutzt, muss die Firewall (UFW regelt das automatisch mit) und die sysctl-Härtung auch IPv6 abdecken.

---

## 10. Dienste und Software minimieren

Jeder laufende Dienst ist potenzielle Angriffsfläche.

### 10.1 Offene Ports inventarisieren

```bash
sudo ss -tulpen
```

* Zeigt alle lauschenden TCP/UDP-Ports inkl. Prozess. Alles Unbekannte recherchieren und deaktivieren.

### 10.2 Unnötige Dienste deaktivieren

```bash
systemctl list-unit-files --state=enabled
sudo systemctl disable --now DIENSTNAME
```

* Typische Kandidaten auf Servern: `cups` (Druckdienst), `avahi-daemon` (mDNS), `bluetooth`, `ModemManager`.

### 10.3 Unnötige Pakete entfernen

```bash
sudo apt purge --auto-remove PAKETNAME
sudo apt clean
```

* `purge` entfernt Paket inkl. Konfigurationsdateien.

### 10.4 Ubuntu Pro / Livepatch (optional)

```bash
sudo pro attach TOKEN
```

* Kostenloses Ubuntu-Pro-Token (bis 5 Maschinen) liefert erweiterte Sicherheitsupdates (ESM) und Kernel-Livepatching ohne Reboot: `sudo pro enable livepatch`.

---

## 11. Dateisystem-Berechtigungen & Mount-Optionen

### 11.1 /tmp absichern

```bash
sudo nano /etc/fstab
```

Eintrag ergänzen:

```
tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev 0 0
```

* `noexec` – keine Ausführung von Binaries aus /tmp (klassischer Ablageort für Malware).
* `nosuid` / `nodev` – keine SUID-Bits und Gerätedateien.
* Einhängen mit: `sudo mount /tmp` bzw. nach Reboot aktiv.

### 11.2 Problematische Berechtigungen finden

Welt-schreibbare Verzeichnisse ohne Sticky-Bit:

```bash
sudo find / -xdev -type d -perm -0002 ! -perm -1000 -ls 2>/dev/null
```

SUID/SGID-Dateien inventarisieren:

```bash
sudo find / -xdev -type f \( -perm -4000 -o -perm -2000 \) -ls 2>/dev/null
```

* Ergebnis mit dem Auslieferungszustand vergleichen – unbekannte SUID-Binaries sind ein Alarmsignal (Privilegieneskalation).

---

## 12. AppArmor – Mandatory Access Control

AppArmor schränkt Programme auf ihre erlaubten Aktionen ein – selbst bei erfolgreicher Kompromittierung.

```bash
sudo apt install apparmor apparmor-utils -y
sudo aa-status
```

* `aa-status` zeigt geladene Profile (enforce = aktiv, complain = nur Logging).
* Ubuntu bringt für viele Dienste fertige Profile mit; zusätzliche Profile liegen in `/usr/share/apparmor/extra-profiles/`.

Profil scharf schalten:

```bash
sudo aa-enforce /etc/apparmor.d/PROFILNAME
```

---

## 13. Kernel-Härtung

Weitere sysctl-Parameter in `/etc/sysctl.d/99-hardening.conf` ergänzen:

```
# Kernel-Pointer im Userspace verbergen
kernel.kptr_restrict = 2

# Kernel-Logs (dmesg) nur für root
kernel.dmesg_restrict = 1

# Hardlink/Symlink-Schutz
fs.protected_hardlinks = 1
fs.protected_symlinks = 1

# Keine Core-Dumps von SUID-Programmen
fs.suid_dumpable = 0
```

Danach `sudo sysctl --system`.

Nicht benötigte Dateisystem-/Protokoll-Module sperren:

```bash
sudo nano /etc/modprobe.d/blacklist-rare.conf
```

Inhalt:

```
install cramfs /bin/true
install freevxfs /bin/true
install hfs /bin/true
install hfsplus /bin/true
install jffs2 /bin/true
install squashfs /bin/true
install udf /bin/true
install dccp /bin/true
install sctp /bin/true
install rds /bin/true
install tipc /bin/true
```

* Verhindert das Nachladen exotischer Kernelmodule, die auf einem Server nichts zu suchen haben (Angriffsfläche im Kernel reduzieren).

USB-Speicher komplett verbieten (nur für High-Security-Umgebungen):

```
install usb-storage /bin/true
```

---

## 14. Logging, Auditing & Monitoring

### 14.1 Journald persistent machen

```bash
sudo mkdir -p /var/log/journal
sudo nano /etc/systemd/journald.conf
```

```
Storage=persistent
SystemMaxUse=500M
```

```bash
sudo systemctl restart systemd-journald
```

* Standardmäßig flüchtig (RAM). Persistent = Logs überleben Neustarts – Pflicht für forensische Auswertung.

### 14.2 Audit-Daemon

```bash
sudo apt install auditd -y
sudo systemctl enable --now auditd
```

Beispiel-Regeln für kritische Dateien (`/etc/audit/rules.d/hardening.rules`):

```
-w /etc/passwd -p wa -k user_changes
-w /etc/shadow -p wa -k credential_changes
-w /etc/ssh/sshd_config -p wa -k sshd_changes
-w /var/log/ -p wa -k log_changes
```

Aktivieren und auswerten:

```bash
sudo augenrules --load
sudo ausearch -k sshd_changes
```

* Überwacht Schreib-/Attribut-Zugriffe auf Benutzerdatenbank, SSH-Config und Logs.

### 14.3 Log-Auswertung automatisieren

```bash
sudo apt install logwatch -y
sudo logwatch --detail High --mailto admin@example.com --range today
```

* Tägliche Zusammenfassung auffälliger Log-Einträge per Mail (MTA vorausgesetzt).

### 14.4 Remote-Logging (Empfehlung)

Logs zusätzlich auf einen zentralen Syslog-Server schieben – bei einer Kompromittierung können Angreifer sonst ihre Spuren löschen. In `/etc/rsyslog.d/remote.conf`:

```
*.* @@LOGSERVER-IP:514
```

---

## 15. Zeitsynchronisation

Korrekte Zeit ist Voraussetzung für auswertbare Logs und funktionierende Zertifikate.

```bash
sudo apt install chrony -y
timedatectl status
chronyc sources
```

* `chrony` ersetzt das einfachere `systemd-timesyncd` und ist robuster.
* `chronyc sources` zeigt die aktiven Zeitserver.

---

## 16. Backups

Härtung ersetzt keine Backups – ohne getestete Wiederherstellung ist alles nichts.

**3-2-1-Regel:** 3 Kopien, 2 verschiedene Medien, 1 Kopie extern/offsite.

Einfaches Beispiel mit rsync (Konfigurationsverzeichnisse sichern):

```bash
sudo rsync -aAX --delete /etc /home /var/log /mnt/backup/$(date +%F)/
```

* `-aAX` erhält Berechtigungen, ACLs und erweiterte Attribute.
* Wichtig: Backups **verschlüsseln** (z. B. mit `restic` oder `borgbackup`) und **regelmäßig Restore-Tests** durchführen.

---

## 17. Abschließender Sicherheits-Check: Lynis

Lynis auditiert das System automatisch und liefert einen Hardening-Index mit konkreten Empfehlungen.

```bash
sudo apt install lynis -y
sudo lynis audit system
```

* Am Ende steht ein **Hardening Index** (Ziel: 80+) plus Liste von „Suggestions".
* Regelmäßig (z. B. monatlich per Cron) wiederholen und den Index im Blick behalten.

Alternativ/ergänzend für CIS-konforme Audits: **OpenSCAP** mit dem CIS-Ubuntu-24.04-Benchmark.

---

## Checkliste (TL;DR)

```bash
# 1. Updates
sudo apt update && sudo apt full-upgrade -y && sudo reboot

# 2. Admin-User, root sperren
sudo adduser deploy && sudo usermod -aG sudo deploy
sudo passwd -l root

# 3. SSH: Key-Auth, kein root, kein Passwort
sudo nano /etc/ssh/sshd_config.d/99-hardening.conf   # PermitRootLogin no, PasswordAuthentication no, AllowUsers deploy
sudo sshd -t && sudo systemctl restart ssh

# 4. Firewall
sudo ufw default deny incoming && sudo ufw default allow outgoing
sudo ufw limit ssh && sudo ufw enable

# 5. Fail2ban
sudo apt install fail2ban -y && sudo systemctl enable --now fail2ban

# 6. Auto-Updates
sudo apt install unattended-upgrades -y

# 7. Kernel/Netz härten
sudo nano /etc/sysctl.d/99-hardening.conf && sudo sysctl --system

# 8. Dienste prüfen
sudo ss -tulpen

# 9. Audit
sudo apt install lynis -y && sudo lynis audit system
```

**Merksatz:** Erst Firewall und SSH absichern (mit offener Fallback-Session!), dann alles andere. Jede Änderung dokumentieren, regelmäßig Lynis laufen lassen und Backups testen.

**Links:** Ubuntu Security [https://ubuntu.com/security](https://ubuntu.com/security) · CIS Benchmarks [https://www.cisecurity.org](https://www.cisecurity.org) · Lynis [https://cisofy.com/lynis/](https://cisofy.com/lynis/) · Fail2ban [https://github.com/fail2ban/fail2ban](https://github.com/fail2ban/fail2ban)
