Pozdravljeni Habr, moje ime je Ilya, delam v ekipi platforme pri Exnessu. Razvijamo in implementiramo ključne komponente infrastrukture, ki jih uporabljajo naše skupine za razvoj izdelkov.
V tem članku bi rad delil svoje izkušnje z implementacijo šifrirane tehnologije SNI (ESNI) v infrastrukturo javnih spletnih mest.
Uporaba te tehnologije bo povečala raven varnosti pri delu z javnim spletnim mestom in v skladu z notranjimi varnostnimi standardi, ki jih je sprejelo podjetje.
Najprej bi rad poudaril, da tehnologija ni standardizirana in je še v osnutku, vendar jo CloudFlare in Mozilla že podpirata (v
Malo teorije
ESNI je razširitev protokola TLS 1.3, ki omogoča šifriranje SNI v sporočilu TLS rokovanja »Client Hello«. Tukaj je videti Client Hello s podporo ESNI (namesto običajnega SNI vidimo ESNI):
Za uporabo ESNI potrebujete tri komponente:
- DNS;
- Podpora strankam;
- Podpora na strani strežnika.
DNS
Dodati morate dva zapisa DNS – AIn TXT (Zapis TXT vsebuje javni ključ, s katerim lahko odjemalec šifrira SNI) – glejte spodaj. Poleg tega mora obstajati podpora DoH (DNS prek HTTPS), ker razpoložljivi odjemalci (glejte spodaj) ne omogočajo podpore ESNI brez DoH. To je logično, saj ESNI pomeni šifriranje imena vira, do katerega dostopamo, torej nima smisla dostopati do DNS preko UDP. Poleg tega uporaba
Trenutno na voljo
CloudFlare
А vstop:
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 zapis, se zahteva generira po predlogi _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."
}
Torej bi morali z vidika DNS uporabiti DoH (po možnosti z DNSSEC) in dodati dva vnosa.
Pomoč strankam
Če govorimo o brskalnikih, potem trenutno
Seveda je treba za podporo ESNI uporabiti TLS 1.3, saj je ESNI razširitev TLS 1.3.
Za namene testiranja zaledja s podporo ESNI smo odjemalca implementirali na go, A več o tem kasneje.
Podpora na strani strežnika
Trenutno ESNI ne podpirajo spletni strežniki, kot je nginx/apache ipd., saj delujejo s TLS prek OpenSSL/BoringSSL, ki uradno ne podpirajo ESNI.
Zato smo se odločili ustvariti lastno front-end komponento (ESNI reverse proxy), ki bi podpirala zaključevanje TLS 1.3 z ESNI in proxy HTTP(S) prometom navzgor, ki ne podpira ESNI. To omogoča uporabo tehnologije v že obstoječi infrastrukturi, brez spreminjanja glavnih komponent – torej z uporabo trenutnih spletnih strežnikov, ki ne podpirajo ESNI.
Za jasnost je tukaj diagram:
Opažam, da je bil proxy zasnovan z možnostjo prekinitve povezave TLS brez ESNI za podporo odjemalcem brez ESNI. Tudi komunikacijski protokol z navzgornjim tokom je lahko HTTP ali HTTPS z različico TLS, nižjo od 1.3 (če navzgornji tok ne podpira 1.3). Ta shema zagotavlja največjo prilagodljivost.
Izvedba podpore ESNI na go smo si izposodili
Za ustvarjanje ključev ESNI smo uporabili
Zgradbo smo preizkusili z go 1.13 v sistemih Linux (Debian, Alpine) in MacOS.
Nekaj besed o operativnih značilnostih
Povratni posrednik ESNI zagotavlja meritve v formatu Prometheus, kot so rps, zakasnitev navzgor in odzivne kode, neuspešna/uspešna rokovanja TLS in trajanje rokovanja TLS. Na prvi pogled se je to zdelo dovolj za oceno, kako proxy obravnava promet.
Pred uporabo smo izvedli tudi obremenitveni test. Rezultati spodaj:
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
Izvedli smo izključno kvalitativno testiranje obremenitve, da bi primerjali shemo z uporabo obratnega posrednika ESNI in brez njega. Promet smo »prelili« lokalno, da bi odpravili »motenje« v vmesnih komponentah.
Torej, s podporo ESNI in proxyjem za navzgor od HTTP, smo dobili približno ~550 rps iz enega primerka, s povprečno porabo CPE/RAM-a povratnega proxyja ESNI:
- 80-odstotna poraba procesorja (gostitelji 4 vCPU, 4 GB RAM-a, Linux)
- 130 MB Mem RSS
Za primerjavo, RPS za isti nginx navzgor brez zaključka 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
Prisotnost časovnih omejitev kaže na pomanjkanje virov (uporabili smo 4 vCPU-je, gostitelje 4 GB RAM-a, Linux), dejansko pa je potencialni RPS višji (prejeli smo številke do 2700 RPS na močnejših virih).
Na koncu ugotavljam da je tehnologija ESNI precej obetavna. Še vedno je veliko odprtih vprašanj, na primer vprašanja shranjevanja javnega ključa ESNI v DNS in rotacije ključev ESNI – o teh vprašanjih se aktivno razpravlja in zadnja različica osnutka ESNI (v času pisanja) je že
Vir: www.habr.com