Kako zaščititi svoje javno spletno mesto z ESNI

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.

Kako zaščititi svoje javno spletno mesto z ESNI

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 osnutek01). To nas je motiviralo za tak poskus.

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):

Kako zaščititi svoje javno spletno mesto z 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 DNSSEC omogoča zaščito pred napadi zastrupitve predpomnilnika v tem scenariju.

Trenutno na voljo več ponudnikov DoH, med njimi:

CloudFlare izjavi (Preverite My Browser → Encrypted SNI → Learn More), da njihovi strežniki že podpirajo ESNI, torej imamo za strežnike CloudFlare v DNS vsaj dva zapisa - A in TXT. V spodnjem primeru poizvedujemo po Googlovem DNS (prek HTTPS): 

А 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 podpora je implementirana samo v FireFox. Tukaj Tukaj so navodila za aktiviranje podpore ESNI in DoH v FireFoxu. Ko je brskalnik konfiguriran, bi morali videti nekaj takega:

Kako zaščititi svoje javno spletno mesto z ESNI

Povezava da preverite brskalnik.

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:

Kako zaščititi svoje javno spletno mesto z ESNI

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 CloudFlare. Takoj bi rad opozoril, da je sama izvedba precej netrivialna, saj vključuje spremembe v standardni knjižnici kripto/tls in zato zahteva "krpanje" GOROOT pred montažo.

Za ustvarjanje ključev ESNI smo uporabili esnitool (tudi plod CloudFlare). Ti ključi se uporabljajo za šifriranje/dešifriranje SNI.
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

Kako zaščititi svoje javno spletno mesto z ESNI

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 7.

Vir: www.habr.com

Dodaj komentar