Kort svar

En TLS-handshake fejler når klient og server ikke kan blive enige om en fælles protokolversion, en fælles cipher suite, eller når klienten ikke kan validere serverens certifikat. De fleste fejl i praksis falder i seks kategorier: protokol-mismatch, cipher mismatch, manglende eller forkert certifikat-kæde, SNI-problemer, udløbet/ugyldigt certifikat og krav om client certificate. Brug openssl s_client til at se præcis hvor det går galt.

Første diagnose: én kommando

Før du gætter, så se hvad serveren faktisk svarer. Denne kommando viser den fremforhandlede protokol, cipher og hele certifikat-kæden:

openssl s_client -connect example.com:443 -servername example.com

De vigtigste linjer i outputtet: Protocol : (hvilken TLS-version blev valgt), Cipher : (hvilken cipher suite), Verify return code: (0 = OK, alt andet er en valideringsfejl) og Certificate chain (de certifikater serveren sendte). Mangler -servername, rammer du ofte det forkerte certifikat på servere med flere domæner.

1. Protokol-mismatch

Klienten tilbyder kun TLS 1.2+ mens serveren stadig kører TLS 1.0/1.1 — eller omvendt. Moderne klienter afviser nu TLS 1.0 og 1.1. Test en specifik version:

openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3

Hvis -tls1_3 virker men din applikation fejler, kører den sandsynligvis et gammelt TLS-bibliotek. Løsningen er at opgradere klienten — ikke at slå gamle protokoller til på serveren. Se hvorfor gammel kryptografi udfases.

2. Cipher mismatch

Klient og server deler ingen fælles cipher suite. Det sker typisk efter en hardening hvor serveren kun tillader moderne ciphers, mens en gammel klient kun kan de gamle. Se serverens accepterede ciphers:

nmap --script ssl-enum-ciphers -p 443 example.com

Hvis listen kun indeholder TLS 1.3-ciphers og din klient er ældre, er det årsagen. En cipher suite beskriver nøgleudveksling, autentificering, kryptering og MAC på én gang — alle fire dele skal matche.

3. Manglende eller forkert certifikat-kæde

Den hyppigste årsag i produktion. Serveren sender sit eget certifikat men glemmer intermediate-certifikatet. Browsere har ofte intermediate'en cached og viser intet problem, mens curl, Java og mobilapps fejler. Symptomet er unable to get local issuer certificate. Se hvor mange certifikater serveren sender:

openssl s_client -connect example.com:443 -servername example.com -showcerts

Du skal se mindst to: dit leaf-certifikat og en eller flere intermediates. Ser du kun ét, mangler kæden. Løsningen er at installere det fulde chain/fullchain-certifikat på serveren.

4. SNI-problemer

På servere der hoster flere domæner på samme IP, bruger TLS Server Name Indication til at vælge det rigtige certifikat. Sender klienten ikke SNI, får den standardcertifikatet — som ofte ikke matcher. Det er derfor -servername er kritisk i testen ovenfor. Gamle klienter og visse API-biblioteker sender ikke SNI som standard.

5. Udløbet, endnu-ikke-gyldigt eller selvsigneret certifikat

Et udløbet certifikat giver Verify return code: 10. Et selvsigneret certifikat i kæden giver kode 18 eller 19. Tjek gyldighedsdatoerne direkte:

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -dates -subject -issuer

Server-ure der går forkert kan også give "not yet valid"-fejl på et helt gyldigt certifikat — tjek NTP.

6. Krav om client certificate (mTLS)

Hvis serveren kræver mutual TLS, fejler handshaken når klienten ikke præsenterer et gyldigt klientcertifikat. I s_client-output ses Acceptable client certificate CA names. Send da klientcertifikat og -nøgle med:

openssl s_client -connect api.example.com:443 -servername api.example.com \
  -cert client.crt -key client.key

Beslutningstræ: find din årsag hurtigt

Symptom Sandsynlig årsag
unable to get local issuer certificateManglende intermediate (kæde)
Virker i browser, fejler i curl/JavaManglende intermediate eller trust store
no protocols availableProtokol-mismatch
sslv3 alert handshake failureCipher mismatch eller manglende client cert
certificate has expiredUdløbet certifikat

Sådan undgår du handshake-fejl i drift

De fleste handshake-fejl i produktion stammer fra to ting: udløbne certifikater og manglende intermediate-kæder efter en fornyelse. Begge er forudsigelige. CertControl scanner jeres endpoints udefra, validerer at den fulde kæde serveres korrekt, og advarer i god tid før et certifikat udløber — så handshaken aldrig når at fejle for jeres brugere.

Ofte stillede spørgsmål

Hvad betyder "SSL handshake failed"?

At klient og server ikke kunne etablere en krypteret forbindelse, fordi de ikke kunne blive enige om protokolversion eller cipher, eller fordi serverens certifikat ikke kunne valideres. Fejlen sker før der sendes data.

Hvorfor virker siden i min browser men ikke i curl eller Java?

Næsten altid en manglende intermediate i certifikat-kæden. Browsere cacher ofte intermediates fra tidligere besøg, mens curl og Java kræver at serveren selv sender hele kæden. Installer fullchain-certifikatet på serveren.

Hvordan ser jeg hvilken TLS-version og cipher der bruges?

Kør openssl s_client -connect host:443 -servername host og kig på linjerne Protocol : og Cipher : i outputtet.

Kan et forkert server-ur give handshake-fejl?

Ja. Hvis serverens ur går markant forkert, kan et gyldigt certifikat fremstå som "not yet valid" eller udløbet. Synkronisér uret via NTP.

Hvad er forskellen på en handshake-fejl og en certifikat-advarsel?

En handshake-fejl afbryder forbindelsen helt — der kommer ingen side. En certifikat-advarsel (fx i browseren) lader brugeren vælge at fortsætte. Begge kan dog stamme fra samme årsag, fx et udløbet certifikat.