Hopp til innhold

TLS

håndtrykket som krypterer en forbindelse

Hva det er

TLS, kort for Transport Layer Security, er protokollen en klient og en server kjører før de utveksler noen applikasjonsdata. Etterpå er det som sendes, privat, det lar seg ikke endre uten at det merkes, og det når fram til den parten klienten faktisk ville nå. Produktmenyer og sertifikatbutikker kaller det fortsatt SSL, etter Secure Sockets Layer, protokollen TLS avløste. Den siste SSL-versjonen ble erklært foreldet i RFC 7568 i juni 2015, så alt som heter SSL i dag, er TLS under panseret, eller burde være det.

TLS ligger mellom en applikasjonsprotokoll og transportlaget under den. HTTPS er HTTP fraktet inne i en TLS-forbindelse, og det samme laget beskytter innsending av e-post, IMAP, databaseforbindelser og Gemini-protokollen. HTTP/3 går et steg lenger: det kjører over QUIC, som bygger håndtrykket fra TLS 1.3 inn i selve transporten i stedet for å legge det oppå TCP, slik RFC 9001 beskriver.

Gjeldende versjon er TLS 1.3, definert i RFC 8446 fra august 2018, som erstattet spesifikasjonen for TLS 1.2. En forbindelse åpner med et håndtrykk. Klienten sender en ClientHello med versjonene, chifferpakkene (cipher suites) og nøkkelandelene den støtter, sammen med Server Name Indication (SNI), vertsnavnet den vil nå, slik at én adresse kan betjene mange nettsteder. Serveren velger, svarer med sin egen nøkkelandel, og fra det øyeblikket er alt kryptert, også sertifikatet den legger fram. Sertifikatkjeden knytter serverens nøkkel til en sertifiseringsinstans klienten allerede stoler på. Klienten sjekker kjeden, navnet og datoene, og serveren beviser at den har den tilhørende private nøkkelen ved å signere håndtrykket.

Tre ting skiller 1.3 fra 1.2. Et fullt håndtrykk tar én rundtur i stedet for to. Hver nøkkelutveksling er flyktig, så et opptak av dagens trafikk forblir forseglet selv om serverens private nøkkel lekker neste år; den egenskapen kalles forward secrecy. Og en klient som kommer tilbake, kan sende «early data» allerede i sin aller første melding, kjent som 0-RTT, til en pris RFC-en gjør rede for: tidlige data har verken forward secrecy eller vern mot å bli spilt av på nytt over en annen forbindelse.

Hvorfor det er viktig

At TLS skal brukes, er avgjort for lengst. Det som gjenstår, er hvilke versjoner du godtar, og hvor den krypterte forbindelsen slutter.

Først versjonene. RFC 8996, publisert i mars 2021, sier at TLS 1.0 og 1.1 ikke skal brukes. RFC 9325, gjeldende beste praksis (BCP 195), krever støtte for 1.2, anbefaler 1.3 og sier at 1.3 skal foretrekkes når begge ender har den. Den sier også at 1.2, satt opp slik den beskriver, er like trygg som 1.3: ECDHE-nøkkelutveksling for forward secrecy, AES-GCM og ingen av chifferpakkene i CBC-modus. Det reelle valget står derfor mellom «1.2 og 1.3» og «bare 1.3». En tjeneste med bare 1.3 har mindre angrepsflate og kortere konfigurasjon, og den stenger ute alle klienter som høyst snakker 1.2: en eldre telefon, en kortterminal, en partners integrasjon på en gammel Java-runtime. Den avveiningen er billig å avgjøre med data. Logg den forhandlede versjonen i noen uker, og bestem deg ut fra tallene heller enn ut fra hva som høres moderne ut.

Deretter termineringen. Der TLS slutter, ligger den private nøkkelen, og trafikken blir klartekst igjen. Tre steder er vanlige:

  • Et CDN eller en lastbalanserer i skyen. Leverandøren har nøkkelen, eller et sertifikat den har utstedt selv, tar belastningen fra håndtrykkene og ser hver forespørsel i klartekst. Strekningen derfra til opprinnelsesserveren trenger sin egen TLS, ellers går den ukryptert over nettet.
  • En omvendt proxy på verten, f.eks. nginx, Apache, HAProxy eller Caddy. Én prosess har nøklene for alle nettstedene på maskinen og sender forespørslene videre i klartekst til applikasjonene bak, over loopback eller en lokal socket.
  • Selve applikasjonen. Hver tjeneste har sin egen nøkkel. Det passer for trafikk mellom tjenester og for gjensidig TLS (mutual TLS), der også klienten legger fram et sertifikat, og det mangedobler antallet steder der et sertifikat må fornyes.

De fleste driftsmiljøer blander alle tre. Det som teller, er at noen for hvert ledd kan si hvor klarteksten finnes, og hvem som kan lese den.

Slik ser det ut i praksis

Selskapets egen produksjonsvert viser hvor lite TLS-terminering krever. Instansen i skyen har én kjerne, 10 GB disk og 512 MB minne, der rundt 464 MB kan brukes. På den terminerer webserveren TLS for sju domener og deler maskinen med git-forgen, onion-tjenesten for Tor, serverne for Gemini og Gopher, de krypterte sikkerhetskopiene og utestengingen av inntrengere. Det er terminering på verten i sin enkleste form: én webserver svarer for alle sju nettstedene, og krypteringen deres koster verken en ekstra maskin eller en ekstra tjeneste. Designet behandlet minnet som den bindende begrensningen, og alt på den listen, terminering inkludert, kjører innenfor de 464 MB.

Regelen selskapet arbeider etter, står på sikkerhetssiden: kryptering under overføring overalt, med sertifikater som utstedes og fornyes automatisk, og en fornyelse som overvåkes. Begrunnelsen der er at TLS oftest svikter på et sertifikat ingen fulgte med på. Feilene nedenfor er de som er igjen når fornyelsen går av seg selv.

Hvor det går galt

Noen klienter faller av med et mislykket håndtrykk, mens nettleserne kobler til uten problemer. Endene har ingen felles versjon eller chifferpakke. Noen har snevret serveren inn til bare 1.3, eller til en kort liste med chifferpakker, og en eldre klient tilbyr bare det serveren har strøket. Eller en server som fortsatt bare tilbyr CBC-pakker, møter en klient som har sluttet å støtte dem. Varselet sier «handshake failure» eller «protocol version» og lite mer. Test hver versjon utenfra:

openssl s_client -connect example.com:443 \
    -servername example.com -tls1_2 </dev/null

Logg den forhandlede versjonen og chifferpakken før du snevrer inn noe, og behold 1.2 med ECDHE og AES-GCM ved siden av 1.3 til loggene viser at ingen bruker den.

Nettleseren stoler på sertifikatet, mens skript, curl og mobilapper avviser det. Serveren sender sitt eget sertifikat uten mellomsertifikatet som knytter det til roten. Nettlesere fyller ofte hullet med mellomsertifikater de har møtt før, eller henter det manglende selv. De fleste TLS-biblioteker gjør ingen av delene og melder om en ukjent utsteder. Sett opp hele kjedefilen, serverens sertifikat først og deretter mellomsertifikatene, og test med en klient som ikke har noen cache: linjen med openssl s_client ovenfor skriver ut kjeden serveren faktisk sendte.

Sertifikatsjekken slås av «inntil videre», og innstillingen havner i produksjon. Det begynner med en testserver med et selvsignert sertifikat, eller en bedriftsproxy som signerer trafikken på nytt, og så legger noen til verify=False, curl -k, InsecureSkipVerify eller NODE_TLS_REJECT_UNAUTHORIZED=0. Forbindelsen er fortsatt kryptert, men til den som svarer: hvem som helst i mellom kan legge fram sitt eget sertifikat og lese alt. Legg det riktige CA-sertifikatet i klientens tillitslager, eller pek klienten eksplisitt på det, og la CI feile på disse flaggene.

Noen besøkende får et sertifikat for et annet nettsted. Serveren legger fram standardsertifikatet sitt når en ClientHello navngir en vert den mangler konfigurasjon for, eller når den ikke navngir noen vert i det hele tatt. Det skjer når et nytt domene pekes mot adressen før serverblokken finnes, og når en overvåkingsprobe eller en gammel klient sender uten SNI. Nettleseren melder at navnet avviker, og på en delt vert avslører feilen også hvilke andre nettsteder som bor der. Gi hvert offentlige navn sin egen blokk og et sertifikat som dekker det, og la standardblokken avvise håndtrykket i stedet for å vise fram en fremmeds sertifikat.

En betaling, eller en hvilken som helst annen forespørsel, blir utført to ganger. Termineringspunktet godtar tidlige data over 0-RTT, en POST kommer inne i dem, og en angriper eller et nytt forsøk i nettverket sender de samme bytene igjen over en ny forbindelse. RFC 8446 lar en server godta tidlige data og overlater gjentakelse mellom forbindelser til applikasjonen. Godta tidlige data bare for forespørsler som tåler å gjentas, eller la termineringspunktet avvise dem for alt annet; RFC 8470 definerer statuskoden 425 Too Early nettopp for den overleveringen.

Les mer

Ordliste