# TLS

## Hvad det er

TLS, Transport Layer Security, er den protokol, en klient og en server kører,
før de udveksler data, så det, der følger, er privat, ikke kan ændres
ubemærket og når frem til den part, klienten ville have fat i. I produktmenuer
og hos certifikatforhandlere hedder det stadig ofte SSL efter Secure Sockets
Layer, den protokol, TLS afløste. RFC 7568 erklærede den sidste SSL-version for
forældet i juni 2015, så alt, der i dag kaldes SSL, er TLS nedenunder, eller
burde være det.

TLS ligger mellem en applikationsprotokol og transporten under den. HTTPS er
HTTP inde i en TLS-forbindelse, og samme lag beskytter afsendelse af mail,
IMAP, databaseforbindelser og Gemini-protokollen. HTTP/3 går et skridt videre og
kører over QUIC, der bygger håndtrykket fra TLS 1.3 direkte ind i transporten i
stedet for at lægge det oven på TCP, som RFC 9001 beskriver.

Den gældende version er TLS 1.3 fra RFC 8446, udgivet i august 2018, som
afløste specifikationen for TLS 1.2. En forbindelse begynder med et håndtryk.
Klienten sender en ClientHello med de versioner, cipher suites og nøgleandele,
den understøtter, og med Server Name Indication (SNI), det værtsnavn, den vil
have fat i, så én adresse kan betjene mange sites. Serveren vælger, svarer med
sin egen nøgleandel, og fra det øjeblik er alt krypteret, også certifikatet,
serveren viser frem. Certifikatkæden binder serverens nøgle til en
certifikatudsteder, klienten allerede stoler på. Klienten kontrollerer kæden,
navnet og datoerne, og serveren beviser, at den har den private nøgle, ved at
signere håndtrykket.

Tre ting adskiller 1.3 fra 1.2. Et fuldt håndtryk kræver én tur frem og tilbage
i stedet for to. Hver nøgleudveksling er flygtig, så en optagelse af dagens
trafik forbliver lukket, selv hvis serverens private nøgle slipper ud næste år;
den egenskab hedder forward secrecy. Og en klient, der vender tilbage, kan sende
»early data« allerede i sin første besked, kendt som 0-RTT, til en pris, som
RFC'en skriver ligeud: de data har hverken forward secrecy eller beskyttelse mod
at blive afspillet igen på en anden forbindelse.

## Hvorfor det betyder noget

At bruge TLS er afgjort for længst. Tilbage står to beslutninger: hvilke
versioner man accepterer, og hvor den krypterede forbindelse ender.

Først versionerne. RFC 8996 fra marts 2021 siger, at TLS 1.0 og 1.1 ikke må
bruges. RFC 9325, den gældende bedste praksis (BCP 195), kræver understøttelse
af 1.2, anbefaler 1.3 og siger, at 1.3 skal foretrækkes, når begge ender kan
tale det. Den siger også, at 1.2 sat op efter dens anvisninger er lige så
sikkert som 1.3: ECDHE-nøgleudveksling for forward secrecy, AES-GCM og ingen af
CBC-suiterne. Det reelle valg står derfor mellem »1.2 og 1.3« og »kun 1.3«. En
server med kun 1.3 har en mindre angrebsflade og en kortere konfiguration, og
den lukker alle klienter ude, der højst taler 1.2: en ældre telefon, en
betalingsterminal, en samarbejdspartners integration på en gammel Java-runtime.
Det valg er billigt at træffe på et oplyst grundlag. Log den forhandlede version
i et par uger, og beslut ud fra tallene frem for ud fra, hvad der lyder
moderne.

Dernæst termineringen. Der, hvor TLS ender, ligger den private nøgle, og der
bliver trafikken til klartekst igen. Der er tre almindelige steder:

- **Et CDN eller en load balancer i skyen.** Udbyderen har nøglen eller et
  certifikat, den selv har udstedt, tager belastningen fra håndtrykkene og ser
  hver forespørgsel i klartekst. Strækningen derfra til origin-serveren skal
  have sin egen TLS, ellers krydser den netværket ukrypteret.
- **En reverse proxy på værten,** for eksempel Nginx, Apache, HAProxy eller
  Caddy. Én proces har nøglerne til alle sites på maskinen og sender
  forespørgslerne ukrypteret videre til programmerne bag sig over loopback eller
  en lokal socket.
- **Selve applikationen.** Hver tjeneste har sin egen nøgle. Det egner sig til
  trafik mellem tjenester og til mutual TLS, hvor klienten også viser et
  certifikat, og det mangedobler antallet af steder, hvor et certifikat skal
  fornys.

De fleste miljøer blander alle tre. Det afgørende er, at nogen for hver
strækning kan sige, hvor klarteksten findes, og hvem der kan læse den.

## Sådan ser det ud i praksis

Virksomhedens egen produktionsvært viser, hvor lidt TLS-terminering kræver. Det
er en cloudinstans med én kerne, 512 MB hukommelse, hvoraf omkring 464 MB kan
bruges, og 10 GB disk. På den
[terminerer webserveren TLS for syv domæner](/da/portfolio/ran-the-whole-company-on-one-512mb-host-109/)
side om side med git-forgen, en Tor onion-tjeneste, en Gemini-server, en
Gopher-server, krypterede backups og blokering af indtrængere. Det er
terminering på værten i sin enkleste form: én webserver svarer for alle syv
sites, og krypteringen af dem koster hverken en ekstra maskine eller en ekstra
tjeneste. Designet behandlede hukommelsen som den bindende begrænsning, og alt
på listen, termineringen medregnet, kører inden for de 464 MB.

Reglen, virksomheden arbejder efter, står på dens
[sikkerhedsside](/da/security/): kryptering under overførsel overalt, med
certifikater, der udstedes og fornys automatisk, og en fornyelse, der
overvåges. Begrundelsen er, at TLS oftest svigter på grund af et certifikat,
som ingen overvågede. Fejlene nedenfor er dem, der er tilbage, når fornyelsen
kører af sig selv.

## Hvor det går galt

**Nogle klienter bliver afvist med en håndtryksfejl, mens browsere forbinder
fint.** De to ender har ingen version eller cipher suite til fælles. Nogen har
strammet serveren til kun 1.3 eller til en kort liste af suiter, og en ældre
klient har intet af det at byde på; eller en server, der stadig kun tilbyder
CBC-suiter, møder en klient, der har droppet dem. Fejlbeskeden lyder »handshake
failure« eller »protocol version« og siger ikke meget mere. Test hver version
udefra:

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

Log den forhandlede version og suite, før noget strammes, og behold 1.2 med
ECDHE og AES-GCM ved siden af 1.3, indtil loggene viser, at ingen bruger den.

**Browsere stoler på certifikatet, mens scripts, curl og mobilapps afviser
det.** Serveren sender sit eget certifikat uden det mellemcertifikat, der
forbinder det med roden. Browsere udfylder ofte hullet med mellemcertifikater,
de har mødt før, eller henter selv det manglende; de fleste TLS-biblioteker gør
ingen af delene og melder en ukendt udsteder. Konfigurér hele kædefilen,
serverens eget certifikat først og derefter mellemcertifikaterne, og test med en
klient uden cache: `openssl s_client`-linjen ovenfor viser den kæde, serveren
faktisk sendte.

**Certifikatkontrollen slås fra »indtil videre«, og indstillingen ender i
produktion.** En testserver med et selvsigneret certifikat eller en
virksomhedsproxy, der gensignerer trafikken, og nogen tilføjer `verify=False`,
`curl -k`, `InsecureSkipVerify` eller `NODE_TLS_REJECT_UNAUTHORIZED=0`.
Forbindelsen er stadig krypteret, bare til hvem der end svarer: enhver
undervejs kan vise sit eget certifikat og læse det hele. Læg det rigtige
CA-certifikat i klientens tillidslager, eller peg klienten direkte på det, og
lad CI fejle på de flag.

**Nogle besøgende får et certifikat til et helt andet site.** Serveren viser sit
standardcertifikat, når en ClientHello nævner en vært, som den mangler
konfiguration til, eller slet ikke nævner en vært. Det sker, når et nyt domæne
peges på adressen, før dets serverblok findes, og når en overvågningsprobe
eller en gammel klient udelader SNI. Browseren melder en navnefejl, og på en
delt vært afslører den samtidig, hvilke andre sites der bor der. Giv hvert
offentligt navn sin egen blok og et certifikat, der dækker det, og lad
standardblokken afvise håndtrykket frem for at vise et fremmed certifikat.

**En betaling eller en anden forespørgsel bliver udført to gange.**
Termineringen tager imod 0-RTT early data, en POST kommer med i dem, og en
angriber eller et automatisk genforsøg sender de samme bytes igen på en ny
forbindelse. RFC 8446 lader serveren tage imod early data og overlader
beskyttelsen mod genafspilning mellem forbindelser til applikationen. Tag kun
imod early data for forespørgsler, der tåler at blive gentaget, eller lad
termineringen afvise dem for alt andet; RFC 8470 definerer statuskoden 425 Too
Early til netop den overdragelse.

## Læs mere

- [RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3](https://www.rfc-editor.org/rfc/rfc8446)
  — håndtrykket, record-laget og appendikset om, hvorfor 0-RTT-data kan
  afspilles igen.
- [RFC 9325: Recommendations for Secure Use of TLS and DTLS](https://www.rfc-editor.org/rfc/rfc9325)
  — BCP 195: hvilke versioner der skal tillades, hvilke cipher suites til 1.2
  der bør beholdes, og reglerne for SNI.
- [RFC 8996: Deprecating TLS 1.0 and TLS 1.1](https://www.rfc-editor.org/rfc/rfc8996)
  — den formelle afslutning på de to ældre versioner og begrundelsen for den.
- [RFC 8470: Using Early Data in HTTP](https://www.rfc-editor.org/rfc/rfc8470) —
  hvordan en terminering og en server bliver enige om, hvilke forespørgsler der
  må sendes som 0-RTT, og statuskoden 425.

<https://engineer.company/da/glossary/tls/>
