Pozdrav Habru, moje ime je Ilya, radim u timu za platforme u Exnessu. Razvijamo i implementiramo osnovne komponente infrastrukture koje koriste naši timovi za razvoj proizvoda.
U ovom članku želio bih podijeliti svoje iskustvo implementacije kriptirane SNI (ESNI) tehnologije u infrastrukturu javnih web stranica.
Korištenje ove tehnologije povećat će razinu sigurnosti pri radu s javnom web stranicom i uskladiti se s internim sigurnosnim standardima koje je usvojilo Društvo.
Prije svega, želio bih istaknuti da tehnologija nije standardizirana i još uvijek je u nacrtu, ali CloudFlare i Mozilla je već podržavaju (u
Malo teorije
ESNI je proširenje protokola TLS 1.3 koje omogućuje SNI enkripciju u TLS poruci rukovanja "Pozdrav klijentu". Evo kako Client Hello izgleda s ESNI podrškom (umjesto uobičajenog SNI-ja vidimo ESNI):
Za korištenje ESNI-ja potrebne su vam tri komponente:
- DNS;
- Podrška klijentima;
- Podrška na strani poslužitelja.
DNS
Morate dodati dva DNS zapisa – AI TXT (TXT zapis sadrži javni ključ s kojim klijent može šifrirati SNI) - vidi dolje. Osim toga, mora postojati podrška DOH (DNS preko HTTPS-a) jer dostupni klijenti (vidi dolje) ne omogućuju ESNI podršku bez DoH-a. To je i logično, jer ESNI podrazumijeva enkripciju naziva resursa kojem pristupamo, odnosno nema smisla pristupati DNS-u preko UDP-a. Štoviše, korištenje
Trenutno dostupan
CloudFlare
А unos:
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, zahtjev se generira prema predlošku _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."
}
Dakle, iz perspektive DNS-a, trebali bismo koristiti DoH (po mogućnosti s DNSSEC-om) i dodati dva unosa.
Korisnička podrška
Ako govorimo o preglednicima, onda u ovom trenutku
Naravno, TLS 1.3 mora se koristiti za podršku ESNI-ju, budući da je ESNI proširenje TLS-a 1.3.
Za potrebe testiranja pozadine s ESNI podrškom implementirali smo klijent na go, Ali o tome kasnije.
Podrška na strani poslužitelja
Trenutno ESNI ne podržavaju web poslužitelji kao što su nginx/apache itd., budući da rade s TLS-om putem OpenSSL/BoringSSL, koji službeno ne podržavaju ESNI.
Stoga smo odlučili stvoriti vlastitu front-end komponentu (ESNI reverse proxy), koja bi podržavala TLS 1.3 završetak s ESNI i proxy HTTP(S) prometom prema uzvodnom, koji ne podržava ESNI. To omogućuje korištenje tehnologije u već postojećoj infrastrukturi, bez mijenjanja glavnih komponenti – odnosno korištenjem trenutnih web poslužitelja koji ne podržavaju ESNI.
Radi jasnoće, ovdje je dijagram:
Napominjem da je proxy dizajniran s mogućnošću prekidanja TLS veze bez ESNI-ja, za podršku klijentima bez ESNI-ja. Također, komunikacijski protokol uzvodno može biti HTTP ili HTTPS s TLS verzijom nižom od 1.3 (ako uzvodno ne podržava 1.3). Ova shema daje maksimalnu fleksibilnost.
Implementacija ESNI podrške na go posudili smo od
Za generiranje ESNI ključeva koristili smo
Testirali smo verziju koristeći go 1.13 na Linuxu (Debian, Alpine) i MacOS-u.
Nekoliko riječi o operativnim značajkama
ESNI obrnuti proxy pruža metriku u Prometheus formatu, kao što su rps, uzvodna latencija i kodovi odgovora, neuspješna/uspješna TLS rukovanja i trajanje TLS rukovanja. Na prvi pogled, ovo se činilo dovoljnim za procjenu kako proxy obrađuje promet.
Također smo izvršili testiranje opterećenja prije upotrebe. Rezultati ispod:
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
Proveli smo čisto kvalitativno testiranje opterećenja kako bismo usporedili shemu koja koristi ESNI obrnuti proxy i bez njega. Lokalno smo "točili" promet kako bismo eliminirali "smetnje" u međukomponentama.
Dakle, s podrškom za ESNI i proxyjem za upstream od HTTP-a, dobili smo oko ~550 rps iz jedne instance, s prosječnom potrošnjom CPU/RAM-a ESNI obrnutog proxyja:
- 80% upotrebe CPU-a (4 vCPU-a, 4 GB RAM-a, Linux)
- 130 MB Mem RSS
Za usporedbu, RPS za isti nginx uzvodno bez završetka TLS (HTTP protokola) 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
Prisutnost timeouta ukazuje na nedostatak resursa (koristili smo 4 vCPU-a, hostove od 4 GB RAM-a, Linux), a zapravo je potencijalni RPS veći (dobili smo brojke do 2700 RPS na snažnijim resursima).
Zaključno napominjem da ESNI tehnologija izgleda prilično obećavajuće. Još uvijek ima puno otvorenih pitanja, na primjer, pitanja pohranjivanja javnog ESNI ključa u DNS i rotiranja ESNI ključeva - o tim se pitanjima aktivno raspravlja, a najnovija verzija nacrta ESNI (u vrijeme pisanja) već je
Izvor: www.habr.com