SSL-Zertifikat reparieren: Abgelaufene Zertifikate, Mixed Content & HTTPS-Redirects
SSL-Zertifikatsprobleme diagnostizieren und beheben. Let's Encrypt erneuern, Mixed Content beheben, HTTPS-Redirect-Schleifen lösen.
Kurzfassung
SSL-Zertifikatsfehler lassen sich in drei Kategorien einteilen: abgelaufene oder ungültige Zertifikate, Mixed-Content-Warnungen (HTTP-Ressourcen auf HTTPS-Seiten) und HTTPS-Redirect-Schleifen. Die Diagnose erfolgt mit openssl s_client und den Browser-Entwicklertools. Zertifikate lassen sich mit Certbot erneuern, Mixed Content durch das Ersetzen von http://-Referenzen beseitigen und Redirect-Schleifen durch die Korrektur der Webserver-Konfiguration auflösen. Mit automatischer Zertifikatserneuerung gehören abgelaufene Zertifikate der Vergangenheit an.
Voraussetzungen
- Root- oder Sudo-Zugriff auf den Webserver
- Certbot installiert (
apt install certbotoderyum install certbot) - OpenSSL installiert (bei den meisten Linux-Distributionen vorinstalliert)
- Zugriff auf die DNS-Einträge der Domain (für Wildcard-Zertifikate)
- Grundkenntnisse der Webserver-Konfiguration (Apache oder Nginx)
Schritt-für-Schritt-Anleitung
1. Fehlerdiagnose
Bevor man etwas repariert, muss man genau verstehen, was kaputt ist. Mit openssl s_client lassen sich Zertifikatsdetails direkt auf der Kommandozeile abrufen:
# Zertifikatsdetails anzeigen
openssl s_client -connect beispiel.de:443 -servername beispiel.de /dev/null | openssl x509 -noout -dates -subject -issuer
Die Ausgabe zeigt Subject, Issuer und Gültigkeitszeitraum. Prüfen Sie, ob das notAfter-Datum in der Vergangenheit liegt.
# Vollständige Zertifikatskette anzeigen
openssl s_client -connect beispiel.de:443 -servername beispiel.de -showcerts &1 | grep -E '(Certificate chain|s:|i:| [0-9]+ s:)'
Im Browser öffnen Sie die Entwicklertools (F12) und wechseln zum Reiter Sicherheit (Chrome) oder klicken auf das Schloss-Symbol. Dort sehen Sie, ob es sich um ein abgelaufenes Zertifikat, eine Namensabweichung, ein fehlendes Zwischenzertifikat oder Mixed Content handelt.
Für eine umfassende externe Prüfung eignet sich SSL Labs. Der Dienst bewertet die Konfiguration und zeigt konkrete Probleme wie schwache Cipher-Suites, unvollständige Ketten oder Protokollfehler auf.
# Stimmt das Zertifikat mit der Domain überein?
openssl s_client -connect beispiel.de:443 -servername beispiel.de /dev/null | openssl x509 -noout -text | grep -A1 'Subject Alternative Name'
2. Let's-Encrypt-Zertifikate erneuern
Ist das Zertifikat abgelaufen oder läuft es demnächst ab, schafft Certbot schnell Abhilfe.
# Automatische Erneuerung aller Certbot-Zertifikate testen
sudo certbot renew --dry-run
# Bei erfolgreichem Testlauf die tatsächliche Erneuerung durchführen
sudo certbot renew
Schlägt die automatische Erneuerung fehl, kann das Zertifikat manuell neu ausgestellt werden. Wählen Sie die Methode, die zu Ihrem Setup passt:
# Für Nginx
sudo certbot certonly --nginx -d beispiel.de -d www.beispiel.de
# Für Apache
sudo certbot certonly --apache -d beispiel.de -d www.beispiel.de
# Webroot-Methode (funktioniert mit jedem Webserver)
sudo certbot certonly --webroot -w /var/www/html -d beispiel.de -d www.beispiel.de
Nach der Erneuerung muss der Webserver neu geladen werden:
# Nginx
sudo systemctl reload nginx
# Apache
sudo systemctl reload apache2 # Debian/Ubuntu
sudo systemctl reload httpd # RHEL/CentOS
Prüfen Sie anschließend, ob das neue Zertifikat aktiv ist:
echo | openssl s_client -connect beispiel.de:443 -servername beispiel.de 2>/dev/null | openssl x509 -noout -dates
3. Mixed-Content-Warnungen beheben
Mixed Content entsteht, wenn eine HTTPS-Seite Ressourcen (Bilder, Skripte, Stylesheets) über unverschlüsseltes HTTP nachlädt. Browser blockieren "aktiven" Mixed Content (Skripte, iFrames) und warnen bei "passivem" Mixed Content (Bilder).
Zunächst die problematischen Referenzen finden:
# Codebase nach hartcodierten http://-URLs durchsuchen
grep -rn 'http://' /var/www/html --include='*.html' --include='*.php' --include='*.css' --include='*.js' | grep -v 'http://localhost' | grep -v '# http://'
# In datenbankgestützten CMS wie WordPress
wp search-replace 'http://beispiel.de' 'https://beispiel.de' --dry-run
wp search-replace 'http://beispiel.de' 'https://beispiel.de'
Als Sofortmaßnahme kann ein Content-Security-Policy-Header gesetzt werden, der HTTP-Anfragen automatisch auf HTTPS hochstuft:
# Nginx — im Server-Block hinzufügen
add_header Content-Security-Policy "upgrade-insecure-requests" always;
# Apache — in .htaccess oder VHost-Konfiguration
Header always set Content-Security-Policy "upgrade-insecure-requests"
Alternativ als Meta-Tag im HTML:
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
Hinweis: upgrade-insecure-requests ist eine Übergangslösung. Die korrekte Behebung besteht darin, alle Referenzen auf https:// oder protokollrelative URLs (//) umzustellen.
4. HTTPS-Redirect-Schleifen korrigieren
Eine Redirect-Schleife entsteht typischerweise, wenn sowohl der Webserver als auch die Anwendung (oder ein Reverse Proxy) jeweils versuchen, HTTPS zu erzwingen — das führt zu einem endlosen Hin-und-Her.
Nginx — korrekte HTTP-zu-HTTPS-Weiterleitung:
# Eigener Server-Block für Port 80 — nur Weiterleitung
server {
listen 80;
server_name beispiel.de www.beispiel.de;
return 301 https://$host$request_uri;
}
# HTTPS-Server-Block — KEINE Weiterleitung hier
server {
listen 443 ssl;
server_name beispiel.de www.beispiel.de;
ssl_certificate /etc/letsencrypt/live/beispiel.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/beispiel.de/privkey.pem;
# weitere Konfiguration
}
Befindet sich der Server hinter einem Load Balancer oder Reverse Proxy, der SSL terminiert, sieht das Backend nur HTTP. In diesem Fall den X-Forwarded-Proto-Header prüfen:
# Nur weiterleiten, wenn die ursprüngliche Anfrage HTTP war
server {
listen 80;
server_name beispiel.de;
if ($http_x_forwarded_proto = "http") {
return 301 https://$host$request_uri;
}
}
Apache — korrekte .htaccess-Weiterleitung:
# Korrekt: HTTPS-Umgebungsvariable prüfen
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Hinter einem Load Balancer den Forwarded-Proto-Header prüfen
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Redirect testen:
curl -ILs http://beispiel.de 2>&1 | grep -E '(HTTP/|Location:)'
Erwartet wird genau ein 301-Redirect gefolgt von einem 200 OK.
5. Probleme mit der Zertifikatskette
Ein fehlendes Zwischenzertifikat (Intermediate Certificate) ist einer der häufigsten SSL-Fehler. Der Browser vertraut dem Zertifikat möglicherweise trotzdem, weil er Zwischenzertifikate zwischenspeichert — andere Clients wie mobile Apps, API-Konsumenten oder curl lehnen die Verbindung aber ab.
# Zertifikatskette verifizieren
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt /etc/letsencrypt/live/beispiel.de/fullchain.pem
# Prüfen, was der Server tatsächlich ausliefert
openssl s_client -connect beispiel.de:443 -servername beispiel.de &1 | grep -E '(depth|verify)'
Bei Let's Encrypt immer fullchain.pem verwenden (enthält das Zwischenzertifikat), nicht cert.pem allein:
# Richtig
ssl_certificate /etc/letsencrypt/live/beispiel.de/fullchain.pem;
# Falsch — Zwischenzertifikat fehlt
# ssl_certificate /etc/letsencrypt/live/beispiel.de/cert.pem;
Bei Zertifikaten anderer Anbieter müssen Zertifikat und Zwischenzertifikat(e) in eine Datei zusammengefügt werden:
cat ihre_domain.crt intermediate.crt > combined.crt
6. Wildcard- vs. Einzelzertifikate
Ein Wildcard-Zertifikat (*.beispiel.de) deckt alle Subdomains der ersten Ebene ab (z. B. app.beispiel.de, api.beispiel.de), aber weder die Apex-Domain selbst noch verschachtelte Subdomains (tief.sub.beispiel.de).
Für ein Wildcard-Zertifikat von Let's Encrypt ist die DNS-01-Challenge erforderlich:
# Wildcard-Zertifikat mit DNS-Challenge
sudo certbot certonly --manual --preferred-challenges dns \
-d beispiel.de -d '*.beispiel.de'
# Automatisiert mit einem DNS-Plugin (z. B. Cloudflare)
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d beispiel.de -d '*.beispiel.de'
Wildcard-Zertifikate eignen sich für viele oder dynamisch erzeugte Subdomains. Einzelzertifikate sind vorzuziehen, wenn es wenige, stabile Subdomains gibt — sie begrenzen den Schaden bei einem kompromittierten Schlüssel.
Fehlersuche
| Symptom | Wahrscheinliche Ursache | Lösung |
|---|---|---|
NET::ERR_CERT_DATE_INVALID | Zertifikat abgelaufen | certbot renew ausführen und Webserver neu laden |
NET::ERR_CERT_COMMON_NAME_INVALID | Zertifikat für falsche Domain ausgestellt | Zertifikat mit den richtigen -d-Parametern neu ausstellen |
NET::ERR_CERT_AUTHORITY_INVALID | Zwischenzertifikat fehlt oder selbstsigniert | fullchain.pem verwenden; mit openssl verify prüfen |
ERR_TOO_MANY_REDIRECTS | HTTPS-Redirect-Schleife | Sicherstellen, dass nur eine Schicht (Webserver ODER Anwendung) weiterleitet |
| Mixed-Content-Warnungen in der Konsole | HTTP-Ressourcen auf HTTPS-Seite | http://-Referenzen ersetzen; upgrade-insecure-requests setzen |
| Certbot-Erneuerung schlägt mit 403 fehl | .well-known/acme-challenge nicht erreichbar | Webroot-Pfad prüfen; sicherstellen, dass keine Rewrite-Regeln blockieren |
SSL funktioniert im Browser, aber curl schlägt fehl | Unvollständige Zertifikatskette | Vollständige Kette inkl. Zwischenzertifikat ausliefern |
| Zertifikat erneuert, aber altes wird weiterhin geliefert | Webserver nicht neu geladen | systemctl reload nginx (bzw. apache2/httpd) ausführen |
Bei fehlgeschlagener Certbot-Erneuerung die Logs prüfen:
sudo cat /var/log/letsencrypt/letsencrypt.log | tail -50
# ACME-Challenge-Pfad auf Erreichbarkeit testen
curl -I http://beispiel.de/.well-known/acme-challenge/test
Vorbeugung
Automatische Erneuerung per Cron
# In die Crontab von root eintragen: sudo crontab -e
0 3 * * * certbot renew --quiet --deploy-hook "systemctl reload nginx" >> /var/log/certbot-renew.log 2>&1
Automatische Erneuerung per Systemd-Timer
Die meisten Certbot-Pakete liefern einen Systemd-Timer mit. Prüfen Sie, ob er aktiv ist:
sudo systemctl status certbot.timer
sudo systemctl enable --now certbot.timer
# Nächsten Ausführungszeitpunkt anzeigen
systemctl list-timers certbot.timer
Um nach der Erneuerung automatisch den Webserver neu zu laden:
# Deploy-Hook-Skript erstellen
sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploy
sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-webserver.sh > /dev/null <<'EOF'
#!/bin/bash
systemctl reload nginx
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-webserver.sh
Zertifikatsablauf überwachen
# Einfaches Skript zur Prüfung der Restlaufzeit
DOMAIN="beispiel.de"
EXPIRY=$(echo | openssl s_client -connect "$DOMAIN:443" -servername "$DOMAIN" 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s 2>/dev/null || date -jf "%b %d %T %Y %Z" "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
TAGE_UEBRIG=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 ))
echo "$DOMAIN: $TAGE_UEBRIG Tage bis zum Ablauf des Zertifikats"
if [ "$TAGE_UEBRIG" -lt 14 ]; then
echo "WARNUNG: Zertifikat läuft in weniger als 14 Tagen ab!" >&2
fi
Checkliste zur Vorbeugung
- Immer
fullchain.pemverwenden, niemalscert.pemallein - Nach jeder Serveränderung die Erneuerung mit
--dry-runtesten - Nach jeder Zertifikats- oder Konfigurationsänderung einen SSL-Labs-Test durchführen
- Monitoring-Alarme einrichten, wenn Zertifikate in weniger als 14 Tagen ablaufen
- Im gesamten Code nur
https://oder protokollrelative URLs verwenden - Nur eine Weiterleitungsebene einsetzen — entweder Webserver oder Anwendung, nicht beides
- Dokumentieren, welche Domains und Subdomains jedes Zertifikat abdeckt
- Certbot-Zugangsdateien (für DNS-Plugins) mit strikten Berechtigungen speichern (
chmod 600)
Experten-Hilfe gebraucht?
Immer noch fest? Ich behebe EIN SSL-Problem in 30 Min für €39. Geld-zurück-Garantie.
Jetzt buchen — €39100% Geld-zurück-Garantie