Kako zaštititi svoju javnu web stranicu pomoću ESNI-a

Zdravo Habr, moje ime je Ilya, radim u timu platforme u Exnessu. Razvijamo i implementiramo osnovne komponente infrastrukture koje koriste naši timovi za razvoj proizvoda.

U ovom članku želim podijeliti svoje iskustvo implementacije šifrirane SNI (ESNI) tehnologije u infrastrukturu javnih web stranica.

Kako zaštititi svoju javnu web stranicu pomoću ESNI-a

Upotreba ove tehnologije će povećati nivo sigurnosti pri radu sa javnom web-stranicom i biti usklađena sa internim sigurnosnim standardima koje je usvojila Kompanija.

Prije svega, želio bih istaći da tehnologija nije standardizirana i da je još uvijek u nacrtu, ali je CloudFlare i Mozilla već podržavaju (u draft01). To nas je motivisalo za ovakav eksperiment.

Malo teorije

ESNI je proširenje TLS 1.3 protokola koje omogućava SNI enkripciju u TLS rukovanju "Client Hello" poruci. Evo kako izgleda Client Hello sa ESNI podrškom (umjesto uobičajenog SNI vidimo ESNI):

Kako zaštititi svoju javnu web stranicu pomoću ESNI-a

 Da biste koristili ESNI, potrebne su vam tri komponente:

  • DNS; 
  • Podrška klijentima;
  • Podrška na strani servera.

DNS

Morate dodati dva DNS zapisa – Ai TXT (TXT zapis sadrži javni ključ kojim klijent može šifrirati SNI) - vidi dolje. Osim toga, mora postojati podrška DoH (DNS preko HTTPS-a) jer dostupni klijenti (pogledajte dolje) ne omogućavaju ESNI podršku bez DoH-a. Ovo je logično, jer ESNI podrazumijeva šifriranje imena resursa kojem pristupamo, odnosno nema smisla pristupati DNS-u preko UDP-a. Štaviše, upotreba DNSSEC omogućava vam zaštitu od napada trovanja keš memorije u ovom scenariju.

Trenutno dostupno nekoliko DoH provajdera, među njima:

CloudFlare izjavljuje (Check My Browser → Encrypted SNI → Learn More) da njihovi serveri već podržavaju ESNI, odnosno da za CloudFlare servere u DNS-u imamo najmanje dva zapisa - A i TXT. U primjeru ispod postavljamo upit za Google DNS (preko HTTPS-a): 

А 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 šablonu _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 sa DNSSEC) i dodati dva unosa. 

Korisnička podrška

Ako govorimo o pretraživačima, onda u ovom trenutku podrška je implementirana samo u FireFox-u. to je Evo instrukcija kako da aktivirate ESNI i DoH podršku u FireFox-u. Nakon što je pretraživač konfiguriran, trebali bismo vidjeti nešto poput ovoga:

Kako zaštititi svoju javnu web stranicu pomoću ESNI-a

link da proverite pretraživač.

Naravno, TLS 1.3 se mora koristiti za podršku ESNI, pošto je ESNI proširenje za TLS 1.3.

Za potrebe testiranja pozadine sa ESNI podrškom, implementirali smo klijenta na go, Ali više o tome kasnije.

Podrška na strani servera

Trenutno, ESNI nije podržan od strane web servera kao što su nginx/apache, itd., jer oni rade sa TLS-om preko OpenSSL/BoringSSL-a, koji zvanično ne podržavaju ESNI.

Stoga smo odlučili kreirati vlastitu front-end komponentu (ESNI reverse proxy), koja bi podržala TLS 1.3 terminaciju sa ESNI i proxy HTTP(S) prometom prema uzvodnom toku, koji ne podržava ESNI. Ovo omogućava da se tehnologija koristi u već postojećoj infrastrukturi, bez mijenjanja glavnih komponenti – odnosno korištenje trenutnih web servera koji ne podržavaju ESNI. 

Radi jasnoće, evo dijagrama:

Kako zaštititi svoju javnu web stranicu pomoću ESNI-a

Napominjem da je proxy dizajniran sa mogućnošću da prekine TLS vezu bez ESNI, da podrži klijente bez ESNI. Također, komunikacijski protokol sa uzvodnim putem može biti ili HTTP ili HTTPS sa TLS verzijom nižom od 1.3 (ako upstream ne podržava 1.3). Ova shema daje maksimalnu fleksibilnost.

Implementacija ESNI podrške na go pozajmili smo od CloudFlare. Želio bih odmah napomenuti da je sama implementacija prilično netrivijalna, jer uključuje promjene u standardnoj biblioteci crypto/tls i stoga zahtijeva "krpanje" GOROOT prije montaže.

Za generiranje ESNI ključeva koristili smo se esnitool (takođe zamisao CloudFlare-a). Ovi ključevi se koriste za SNI enkripciju/dešifriranje.
Мы протестировали сборку с использованием go 1.13 на Linux (Debian, Alpine) и MacOS. 

Nekoliko riječi o operativnim karakteristikama

ESNI obrnuti proxy pruža metriku u Prometheus formatu, kao što su rps, uzvodno kašnjenje i kodovi odgovora, neuspješna/uspješna TLS rukovanja i trajanje TLS rukovanja. Na prvi pogled, ovo je izgledalo dovoljno da se proceni kako proxy upravlja saobraćajem. 

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 uporedili shemu koristeći ESNI reverse proxy i bez njega. Lokalno smo „sipali“ saobraćaj kako bismo eliminisali „smetnje“ u međukomponentama.

Dakle, sa podrškom za ESNI i proxyvanjem na uzvodno od HTTP-a, dobili smo oko ~550 okretaja u sekundi iz jedne instance, uz prosječnu potrošnju CPU/RAM-a ESNI obrnutog proxyja:

  • 80% CPU Usage (4 vCPU, 4 GB RAM хосты, Linux)
  • 130 MB Mem RSS

Kako zaštititi svoju javnu web stranicu pomoću ESNI-a

Za poređenje, RPS za isti nginx uzvodno bez TLS (HTTP protokol) terminacije 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 

Наличие таймаутов говорит о том, что есть нехватка ресурсов (мы использовали 4 vCPU, 4 GB RAM хосты, Linux), и по факту потенциальный RPS выше (мы получали цифры до  2700 RPS на более мощных ресурсах).

U zaključku, napominjem da ESNI tehnologija izgleda prilično obećavajuće. Još uvijek ima mnogo 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 ESNI nacrta (u vrijeme pisanja) je već objavljena. 7.

izvor: www.habr.com

Kupite pouzdan hosting za sajtove sa DDoS zaštitom, VPS VDS servere 🔥 Kupite pouzdan web hosting sa DDoS zaštitom, VPS VDS servere | ProHoster