ťařina
Obsah Soubory
markdown

TLS-a-HTTPS.md

6.2 kB 131 řádků Změněno Zobrazit na GitHubu Stáhnout
markdown
# TLS a HTTPS prakticky Reverse proxy je z velké části správa TLS, takže bez téhle stránky nedávají ty další smysl. Nejde tu o kryptografii, ale o věci, které tě reálně potkají v konfiguraci. Když tě zajímá, co se pod tím děje, je to na [TLS handshake krok za krokem](TLS-handshake). ## Co TLS řeší Tři věci naráz, a je užitečné je oddělovat: **Šifrování** — nikdo po cestě nepřečte obsah. **Integrita** — nikdo po cestě obsah nezmění, aniž by to bylo poznat. **Autenticita** — mluvíš se serverem, za který se vydává. Tohle dělá certifikát a je to ta část, která nejčastěji zlobí. Šifrování bez autenticity je k ničemu. Kdyby ti stačilo šifrování, útočník se prostě postaví doprostřed a šifruje s tebou sám. ## Průběh spojení ```mermaidsequenceDiagram    participant K as Klient    participant S as Server    K->>S: ClientHello (umím tyto šifry, chci doménu X)    S->>K: ServerHello + certifikát    K->>K: ověří podpis proti CA a datum platnosti    K->>S: výměna klíčů    Note over K,S: dál je vše šifrované    K->>S: GET / HTTP/1.1``` To „chci doménu X" v prvním kroku je **SNI** a je klíčové pro pochopení reverse proxy. Tohle je zjednodušení. V TLS 1.3 přiloží klient svou část výměny klíčů rovnou do prvního paketu, takže celý handshake trvá jedno kolo a certifikát letí už zašifrovaný — rozbor je na [TLS handshake krok za krokem](TLS-handshake), samotná výměna na [Diffie-Hellman](Diffie-Hellman). ## SNI Na jedné IP adrese může běžet sto webů. Server ale musí vybrat certifikát **dřív**, než se spojení zašifruje a než uvidí HTTP hlavičku `Host`. Řeší to SNI: klient v úvodním nešifrovaném pozdravu pošle jméno domény, na kterou se chce připojit. Podle toho server vybere certifikát. Praktické důsledky: **Jméno domény jde po drátě nešifrovaně.** Obsah nikdo nepřečte, ale to, na které weby chodíš, ano. Řeší to až Encrypted Client Hello, které se teprve nasazuje. **Reverse proxy může podle SNI rozhodovat, aniž by TLS rozbalovala.** Tomu se říká SNI routing. **Bez SNI dostaneš výchozí certifikát.** Když se připojíš na IP adresu místo na jméno, server neví, co chceš, a pošle první certifikát v pořadí — proto to varování v prohlížeči. ## Řetěz certifikátů Certifikát sám o sobě nic nedokazuje. Důvěra se odvozuje řetězem: ```kořenová CA (v prohlížeči a v OS)    └── mezilehlá CA            └── tvůj certifikát pro example.cz``` Server musí poslat **svůj certifikát i mezilehlé**. Kořenový ne, ten už klient má. Tohle je nejčastější chyba při ručním nasazení certifikátů. Projeví se tak, že web funguje v prohlížeči na desktopu (ten si mezilehlý certifikát domyslí z keše) a nefunguje v `curl`, na mobilu nebo v jiné aplikaci. Ověř si to: ```bashopenssl s_client -connect example.cz:443 -servername example.cz < /dev/null``` V hlavičce výstupu je `Certificate chain` — musí tam být víc než jedna položka. A na konci `Verify return code: 0 (ok)`. Online kontrola: [ssllabs.com/ssltest](https://www.ssllabs.com/ssltest/), která ti ukáže i „chain issues". [Caddy](Caddy) a [Traefik](Traefik) tenhle problém nemají, protože řetěz sestavují samy. ## Verze a šifry Jednoduše: **TLS 1.2 a 1.3, nic staršího.** TLS 1.0 a 1.1 jsou vyřazené, SSL v jakékoliv verzi je prolomené. Rozumná konfigurace pro nginx: ```nginxssl_protocols TLSv1.2 TLSv1.3;ssl_prefer_server_ciphers off;ssl_session_cache shared:SSL:10m;ssl_session_timeout 1d;ssl_session_tickets off;``` U TLS 1.3 se seznam šifer neladí — protokol nabízí jen bezpečné. To `ssl_prefer_server_ciphers off` je dnes doporučení, protože klient obvykle ví lépe, co má hardwarově akcelerované. To `ssl_session_tickets off` na posledním řádku není kosmetika: tikety šifruje server dlouhodobým klíčem, a když se ten nerotuje a unikne, dá se zpětně dešifrovat provoz všech obnovených relací. Vysvětlení je v [TLS handshake](TLS-handshake#obnovení-relace). Generátor konfigurací pro všechny běžné servery: [ssl-config.mozilla.org](https://ssl-config.mozilla.org/). ## HSTS Hlavička, kterou serveru řekneš prohlížeči „na tuhle doménu chodím vždycky přes HTTPS": ```nginxadd_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;``` Chrání proti útoku, kdy tě někdo při prvním requestu na `http://` přesměruje jinam. **Pozor na `includeSubDomains`.** Platí to na rok a prohlížeč si to zapamatuje. Když máš pod doménou něco, co běží jen na HTTP, přestane to fungovat a nedá se to jednoduše vzít zpět. Nasazuj nejdřív s krátkým `max-age`, třeba 300, a zvyšuj až po ověření. ## Ukončení TLS a co dál Reverse proxy TLS obvykle ukončí a dovnitř posílá nešifrované HTTP. Je to standardní a v důvěryhodné síti v pořádku — vnitřní provoz mezi proxy a aplikací neopouští stroj nebo důvěryhodný segment. Alternativy: **TLS passthrough** — proxy nerozbaluje, jen podle SNI přepošle dál. Nutné, když aplikace potřebuje vidět klientský certifikát. **Re-encrypt** — proxy rozbalí a k aplikaci naváže nové TLS. Užitečné, když provoz jde přes nedůvěryhodnou síť, třeba mezi VM na různých hostitelích. Pro homelab je ukončení na proxy správná volba. ## Časté chyby **„NET::ERR_CERT_AUTHORITY_INVALID"** → chybí mezilehlý certifikát, nebo je certifikát podepsaný sám sebou. Případně ho vystavila [vlastní CA](Vlastni-certifikacni-autorita), kterou tenhle klient nezná. **Funguje v prohlížeči, ne v `curl`** → skoro vždycky chybějící mezilehlý certifikát. **„certificate has expired"** → neproběhla obnova. Viz [certifikáty a Let's Encrypt](Certifikaty-a-Lets-Encrypt). **Aplikace generuje odkazy s `http://`** → aplikace neví, že běží za proxy. Chybí hlavička `X-Forwarded-Proto`, viz [reverse proxy](Reverse-proxy). **Přesměrovací smyčka** → proxy přesměrovává na HTTPS a aplikace taky, přičemž aplikace vidí interní HTTP a myslí si, že je potřeba přesměrovat znovu. Řeší se stejnou hlavičkou.