Fehlermeldung
curl: (60) SSL certificate problem: self-signed certificate
Auch ausgegeben als
- curl: (60) SSL certificate problem: self signed certificate
- curl: (60) SSL certificate OpenSSL verify result: self-signed certificate (18)
OpenSSL ab 3.0 gibt „self-signed certificate“ aus; OpenSSL 1.1.1 schreibt „self signed certificate“. Neuere curl-Releases (in unserem Test 8.22.0) formulieren es als „SSL certificate OpenSSL verify result: self-signed certificate (18)“. Verwechsle das nicht mit „self-signed certificate in certificate chain“: Dort gibt es eine CA-Kette, die bei einem nicht vertrauenswürdigen Root-Zertifikat endet.
curl (OpenSSL backend) — CURLE_PEER_FAILED_VERIFICATION, X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT (18)
Was der Fehler bedeutet
Der Server hat ein einzelnes Zertifikat präsentiert, das mit seinem eigenen Schlüssel signiert ist (Aussteller gleich Subject), und genau dieses Zertifikat hat curl nicht in seinem Trust Store. Dahinter steht keine CA, die curl nachschlagen könnte, deshalb endet die Prüfung bei Tiefe 0. Das ist bei Entwicklungsservern und Appliances normal und lässt sich nie durch die Installation eines Zwischenzertifikats beheben.
Warum der Fehler auftritt
Ein Entwicklungs- oder Testserver mit generiertem Zertifikat
häufigLokale HTTPS-Server, docker-compose-Stacks und Test-Fixtures erzeugen beim Start oft ein selbstsigniertes Zertifikat (zum Beispiel mit openssl req -x509). Jede Neugenerierung erzeugt ein neues Zertifikat, sodass eine Kopie, der du gestern vertraut hast, heute womöglich nicht mehr passt.
Ein Gerät oder Produkt verwendet noch sein Werkszertifikat
häufigRouter, NAS-Geräte, Drucker, iDRAC-/iLO-Oberflächen sowie Installationen von Proxmox, Jenkins oder Elasticsearch werden mit einem selbstsignierten Zertifikat ausgeliefert, bis jemand ein richtiges installiert.
Ein Proxy oder Ingress liefert sein Standardzertifikat aus
gelegentlichPasst kein Zertifikat zum angefragten Namen, liefert ingress-nginx „Kubernetes Ingress Controller Fake Certificate“ aus und Traefik „TRAEFIK DEFAULT CERT“, beide selbstsigniert. Das eigentliche Problem liegt dann beim Routing oder bei SNI, nicht beim Vertrauen.
Der Server verweist auf die falsche Datei
seltenEine Konfiguration, die statt des ausgestellten Zertifikats auf ein vorläufiges selbstsigniertes Zertifikat verweist (snakeoil.pem unter Debian, localhost.crt aus einem Paket), erzeugt diesen Fehler, obwohl ein echtes Zertifikat auf der Festplatte liegt.
So behebst du den Fehler
- 1.
Genau diesem Zertifikat vertrauen, nachdem du es geprüft hast
Speichere für einen einzelnen internen Endpunkt das Zertifikat, bestätige seinen SHA-256-Fingerabdruck über einen vertrauenswürdigen Kanal (die Konsole des Geräts, den Admin, der es erstellt hat) und übergib es mit --cacert. curl akzeptiert dann für diesen Aufruf genau dieses Zertifikat und sonst keines.
bash # Fetch the certificate once, compare its fingerprint out of band, then trust exactly that file openssl s_client -connect api.example.com:8443 -servername api.example.com </dev/null 2>/dev/null \ | openssl x509 -out api.example.com.pem openssl x509 -in api.example.com.pem -noout -fingerprint -sha256 curl --cacert api.example.com.pem https://api.example.com:8443/ - 2.
Entwicklung: Zertifikate von einer lokalen CA ausstellen
Mit einer lokalen CA (mkcert, step-ca oder einem selbst erstellten Root-Zertifikat) vertraust du einmalig einem einzigen Root-Zertifikat und stellst Zertifikate für beliebig viele Entwicklungshosts aus. Die Zertifikate sind dann nicht mehr selbstsigniert, deshalb verschwindet der Fehler überall, wo das Root-Zertifikat installiert ist.
bash # mkcert creates a local CA, installs it into the system and browser stores, # and issues certificates signed by it (no longer self-signed) mkcert -install mkcert api.example.test localhost 127.0.0.1 - 3.
Öffentliche Hosts: Zertifikat einer öffentlichen CA installieren
Alles, was andere Menschen oder Clients von Dritten erreichen, sollte ein Zertifikat einer öffentlich vertrauenswürdigen CA präsentieren; ACME-Clients wie certbot, lego oder Caddy beziehen und erneuern es automatisch.
bash # Public names: get a certificate from a public CA, e.g. with certbot (ACME) sudo certbot certonly --nginx -d api.example.com - 4.
Vorübergehende Diagnose: Dienst bei abgeschalteter Prüfung testen
Mit -k überspringt curl die Zertifikatsprüfung; ein Status 200 bestätigt dann, dass nur das Vertrauen fehlt. Behalte es nicht bei: Ein selbstsigniertes Zertifikat, das ungeprüft akzeptiert wird, kann jederzeit gegen das eines Angreifers ausgetauscht werden, ohne dass curl es bemerkt.
bash # Diagnostic only: confirms the service answers when certificate checks are skipped curl -sS -k -o /dev/null -w '%{http_code}\n' https://api.example.com:8443/
Verwandte Fehler
curl: (60) SSL certificate problem: self-signed certificate in certificate chaincurl (OpenSSL backend)curl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)verify error:num=18:self-signed certificateOpenSSL CLI (openssl s_client / openssl verify)code: 'DEPTH_ZERO_SELF_SIGNED_CERT'Node.js tls / https / fetch