Ahoj Habr, volám sa Ilya, pracujem v tíme platformy v Exness. Vyvíjame a implementujeme základné komponenty infraštruktúry, ktoré používajú naše tímy pre vývoj produktov.
V tomto článku by som sa rád podelil o svoje skúsenosti s implementáciou šifrovanej technológie SNI (ESNI) do infraštruktúry verejných webových stránok.
Použitie tejto technológie zvýši úroveň bezpečnosti pri práci s verejnou webovou stránkou a bude v súlade s internými bezpečnostnými štandardmi prijatými Spoločnosťou.
V prvom rade by som chcel upozorniť, že technológia nie je štandardizovaná a je stále v návrhu, no CloudFlare a Mozilla ju už podporujú (v r.
Niektoré teórie
ESNI je rozšírenie protokolu TLS 1.3, ktoré umožňuje šifrovanie SNI v správe TLS handshake „Client Hello“. Takto vyzerá klient Hello s podporou ESNI (namiesto obvyklého SNI vidíme ESNI):
Ak chcete používať ESNI, potrebujete tri komponenty:
- DNS;
- Zákaznícka podpora;
- Podpora na strane servera.
DNS
Musíte pridať dva záznamy DNS – AA TXT (TXT záznam obsahuje verejný kľúč, ktorým môže klient šifrovať SNI) - viď nižšie. Okrem toho musí existovať podpora Doh (DNS cez HTTPS), pretože dostupní klienti (pozri nižšie) neumožňujú podporu ESNI bez DoH. Je to logické, keďže ESNI predpokladá šifrovanie názvu zdroja, ku ktorému pristupujeme, to znamená, že nemá zmysel pristupovať k DNS cez UDP. Navyše použitie
Práve dostupný
CloudFlare
А vstup:
curl 'https://dns.google.com/resolve?name=www.cloudflare.com&type=A'
-s -H 'accept: application/dns+json'
{
"Status": 0,
"TC": false,
"RD": true,
"RA": true,
"AD": true,
"CD": false,
"Question": [
{
"name": "www.cloudflare.com.",
"type": 1
}
],
"Answer": [
{
"name": "www.cloudflare.com.",
"type": 1,
"TTL": 257,
"data": "104.17.210.9"
},
{
"name": "www.cloudflare.com.",
"type": 1,
"TTL": 257,
"data": "104.17.209.9"
}
]
}
TXT záznam, žiadosť sa vygeneruje podľa šablóny _esni.FQDN:
curl 'https://dns.google.com/resolve?name=_esni.www.cloudflare.com&type=TXT'
-s -H 'accept: application/dns+json'
{
"Status": 0,
"TC": false,
"RD": true,
"RA": true,
"AD": true,
"CD": false,
"Question": [
{
"name": "_esni.www.cloudflare.com.",
"type": 16
}
],
"Answer": [
{
"name": "_esni.www.cloudflare.com.",
"type": 16,
"TTL": 1799,
"data": ""/wEUgUKlACQAHQAg9SiAYQ9aUseUZr47HYHvF5jkt3aZ5802eAMJPhRz1QgAAhMBAQQAAAAAXtUmAAAAAABe3Q8AAAA=""
}
],
"Comment": "Response from 2400:cb00:2049:1::a29f:209."
}
Takže z pohľadu DNS by sme mali použiť DoH (najlepšie s DNSSEC) a pridať dva záznamy.
Zákaznícka podpora
Ak hovoríme o prehliadačoch, tak v súčasnosti
Samozrejme, na podporu ESNI sa musí použiť TLS 1.3, pretože ESNI je rozšírením TLS 1.3.
Pre účely testovania backendu s podporou ESNI sme klienta implementovali na go, Ale o tom neskôr.
Podpora na strane servera
V súčasnosti ESNI nepodporujú webové servery ako nginx/apache atď., pretože pracujú s TLS cez OpenSSL/BoringSSL, ktoré oficiálne nepodporujú ESNI.
Preto sme sa rozhodli vytvoriť vlastný front-end komponent (ESNI reverzný proxy), ktorý by podporoval ukončenie TLS 1.3 s ESNI a proxy HTTP(S) prevádzku na upstream, ktorý ESNI nepodporuje. To umožňuje použiť technológiu v už existujúcej infraštruktúre bez zmeny hlavných komponentov – teda s využitím súčasných webových serverov, ktoré nepodporujú ESNI.
Pre prehľadnosť uvádzame schému:
Všimol som si, že proxy bol navrhnutý so schopnosťou ukončiť pripojenie TLS bez ESNI, aby podporoval klientov bez ESNI. Komunikačný protokol s upstreamom môže byť tiež HTTP alebo HTTPS s verziou TLS nižšou ako 1.3 (ak upstream nepodporuje 1.3). Táto schéma poskytuje maximálnu flexibilitu.
Implementácia podpory ESNI na go požičali sme si od
Na generovanie kľúčov ESNI sme použili
Testovali sme zostavu pomocou go 1.13 na Linuxe (Debian, Alpine) a MacOS.
Niekoľko slov o prevádzkových vlastnostiach
ESNI reverzný proxy poskytuje metriky vo formáte Prometheus, ako sú rps, upstream latencia a kódy odozvy, neúspešné/úspešné TLS handshake a trvanie TLS handshake. Na prvý pohľad sa to zdalo dostatočné na vyhodnotenie toho, ako server proxy zvláda prevádzku.
Pred použitím sme vykonali aj záťažové testy. Výsledky nižšie:
wrk -t50 -c1000 -d360s 'https://esni-rev-proxy.npw:443' --timeout 15s
Running 6m test @ https://esni-rev-proxy.npw:443
50 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.77s 1.21s 7.20s 65.43%
Req/Sec 13.78 8.84 140.00 83.70%
206357 requests in 6.00m, 6.08GB read
Requests/sec: 573.07
Transfer/sec: 17.28MB
Uskutočnili sme čisto kvalitatívne testovanie záťaže, aby sme porovnali schému pomocou reverzného proxy servera ESNI a bez neho. Lokálne sme „naliali“ dopravu, aby sme eliminovali „rušenie“ v medzizložkách.
Takže s podporou ESNI a proxy pre upstream z HTTP sme dostali približne ~550 rps z jednej inštancie, s priemernou spotrebou CPU/RAM reverznej proxy ESNI:
- 80 % využitie CPU (4 vCPU, 4 GB RAM hostitelia, Linux)
- 130 MB pamäte RSS
Pre porovnanie, RPS pre rovnaký nginx upstream bez ukončenia TLS (protokol HTTP) je ~ 1100:
wrk -t50 -c1000 -d360s 'http://lb.npw:80' –-timeout 15s
Running 6m test @ http://lb.npw:80
50 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.11s 2.30s 15.00s 90.94%
Req/Sec 23.25 13.55 282.00 79.25%
393093 requests in 6.00m, 11.35GB read
Socket errors: connect 0, read 0, write 0, timeout 9555
Non-2xx or 3xx responses: 8111
Requests/sec: 1091.62
Transfer/sec: 32.27MB
Prítomnosť časových limitov naznačuje, že je nedostatok zdrojov (použili sme 4 vCPU, 4 GB RAM hostiteľov, Linux) a v skutočnosti je potenciálna RPS vyššia (dostali sme čísla až 2700 RPS na výkonnejších zdrojoch).
Na záver podotýkam že technológia ESNI vyzerá celkom sľubne. Stále existuje veľa otvorených otázok, napríklad otázky ukladania verejného kľúča ESNI v DNS a rotácie kľúčov ESNI – o týchto problémoch sa aktívne diskutuje a najnovšia verzia návrhu ESNI (v čase písania tohto článku) je už k dispozícii
Zdroj: hab.com