Si të mbroni faqen tuaj publike me ESNI

Përshëndetje Habr, quhem Ilja dhe punoj në ekipin e platformës së kompanisë Exness. Ne zhvillojmë dhe implementojmë komponentët bazë të infrastrukturës që përdoren nga ekipet tona të zhvillimit të produkteve.

Në këtë artikull dua të ndaj përvojën tonë të implementimit të teknologjisë encrypted SNI (ESNI) në infrastrukturën e faqeve publike në internet.

Si të mbroni faqen tuaj publike me ESNI

Përdorimi i kësaj teknologjie ju lejon të rrisni nivelin e sigurisë gjatë punës me një faqe publike dhe të përmbushni standardet e brendshme të sigurisë të miratuara në kompani.

Para së gjithash, dua të theksoj se kjo teknologji nuk është e standardizuar dhe është ende në draft, megjithatë CloudFlare dhe Mozilla tashmë e mbështesin atë (në draft01). Pikërisht kjo na motivoi për një eksperiment të tillë.

Pak teori

ESNI Ă«shtĂ« njĂ« zgjerim i protokollit TLS 1.3 qĂ« mundĂ«son enkriptimin e SNI nĂ« mesazhin “Client Hello” tĂ« TLS handshake. Ja si duket Client Hello me mbĂ«shtetje pĂ«r ESNI (nĂ« vend tĂ« SNI tĂ« zakonshĂ«m, shohim ESNI):

Si të mbroni faqen tuaj publike me ESNI

 Për të përdorur ESNI, nevojiten tre përbërës:

  • DNS; 
  • MbĂ«shtetje nga ana e klientit;
  • MbĂ«shtetje nga ana e serverit.

DNS

Duhet tĂ« shtohen dy regjistrime DNS – A, dhe TXT (regjistrimi TXT pĂ«rmban çelĂ«sin publik me tĂ« cilin klienti mund tĂ« enkriptojĂ« SNI) – shih mĂ« poshtĂ«. PĂ«rveç kĂ«saj, duhet tĂ« ketĂ« mbĂ«shtetje pĂ«r DoH (DNS over HTTPS), pasi klientĂ«t e disponueshĂ«m (shih mĂ« poshtĂ«) nuk e aktivizojnĂ« mbĂ«shtetjen pĂ«r ESNI pa DoH. Kjo Ă«shtĂ« logjike, pasi ESNI nĂ«nkupton enkriptimin e emrit tĂ« burimit qĂ« po aksesojmĂ«, ndaj nuk ka kuptim t'i drejtohemi DNS pĂ«rmes UDP. PĂ«r mĂ« tepĂ«r, pĂ«rdorimi i DNSSEC ju lejon tĂ« mbroheni nga sulmet “cache poisoning” nĂ« kĂ«tĂ« skenar.

Aktualisht janë të disponueshëm disa ofrues DoH, ndër ta:

CloudFlare deklaron (Check My Browser → Encrypted SNI → Learn More) se serverĂ«t e tyre tashmĂ« mbĂ«shtesin ESNI, pra pĂ«r serverĂ«t e CloudFlare nĂ« DNS kemi tĂ« paktĂ«n dy regjistrime – A dhe TXT. NĂ« shembullin mĂ« poshtĂ« po dĂ«rgojmĂ« njĂ« kĂ«rkesĂ« te Google DNS (over HTTPS): 

A regjistrimi:

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 regjistrimi, kërkesa formohet sipas modelit _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."
}

Pra, nga pikëpamja e DNS, duhet të përdorim DoH (mundësisht me DNSSEC) dhe të shtojmë dy regjistrime. 

Mbështetja nga ana e klientit

Nëse flasim për shfletuesit, atëherë për momentin mbështetja është zbatuar vetëm në FireFox. Këtu janë dhënë udhëzimet se si të aktivizohet mbështetja për ESNI dhe DoH në FireFox. Pasi të konfigurohet shfletuesi, duhet të shohim afërsisht një pamje të tillë:

Si të mbroni faqen tuaj publike me ESNI

Lidhja për të kontrolluar shfletuesin.

Natyrisht, për mbështetjen e ESNI duhet të përdoret TLS 1.3, pasi ESNI është një zgjerim i TLS 1.3.

Për qëllime të testimit të backend-it me mbështetje për ESNI, ne implementuam një klient në go, por për këtë do të flasim pak më vonë.

Mbështetja nga ana e serverit

Aktualisht ESNI nuk mbështetet nga web-serverë si nginx/apache etj., pasi ata punojnë me TLS përmes OpenSSL/BoringSSL, ku ESNI nuk mbështetet zyrtarisht.

Prandaj vendosëm të krijojmë komponentin tonë front-end (ESNI reverse proxy), i cili do të mbështeste terminimin e TLS 1.3 me ESNI dhe proksimin e trafikut HTTP(S) drejt upstream-it që nuk mbështet ESNI. Kjo mundëson përdorimin e teknologjisë në infrastrukturën ekzistuese pa ndryshuar komponentët kryesorë, pra duke përdorur web-serverët aktualë që nuk mbështesin ESNI. 

Për qartësi, po paraqesim skemën:

Si të mbroni faqen tuaj publike me ESNI

Vlen të theksohet se proxy u konceptua me mundësinë për të terminuar lidhjen TLS edhe pa ESNI, për të mbështetur klientët pa ESNI. Gjithashtu, protokolli i komunikimit me upstream-in mund të jetë si HTTP, ashtu edhe HTTPS me një version TLS më të ulët se 1.3 (nëse upstream-i nuk mbështet 1.3). Kjo skemë ofron fleksibilitet maksimal.

Implementimin e mbështetjes për ESNI në go e huazuam nga CloudFlare. Menjëherë vlen të theksohet se vetë implementimi është mjaft jo trivial, pasi nënkupton ndryshime në bibliotekën standarde crypto/tls dhe për këtë arsye kërkon «patching» të GOROOT para ndërtimit.

Për gjenerimin e çelësave ESNI ne përdorëm esnitool (gjithashtu një krijim i CloudFlare). Këta çelësa përdoren për enkriptimin/dekriptimin e SNI.
Ne e testuam build-in duke përdorur go 1.13 në Linux (Debian, Alpine) dhe MacOS. 

Disa fjalë për veçoritë e funksionimit

ESNI reverse proxy ofron metrika në formatin Prometheus, për shembull si rps, upstream latency & response codes, failed/successful TLS handshakes & TLS handshake duration. Në pamje të parë, kjo u duk e mjaftueshme për të vlerësuar se si proxy e përballon trafikun. 

Gjithashtu, përpara përdorimit ne kryem testim ngarkese. Rezultatet janë më poshtë:

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 

Testimin e ngarkesës e kryem thjesht në mënyrë cilësore, për të krahasuar skemën me përdorimin e ESNI reverse proxy dhe pa të. Trafikun e gjeneruam lokalisht për të përjashtuar "ndërhyrjet" në komponentët ndërmjetës.

Pra, me mbështetjen e ESNI dhe proxying drejt upstream përmes HTTP, morëm rreth ~ 550 rps nga një instancë e vetme, ndërsa konsumi mesatar i CPU/RAM i ESNI reverse proxy ishte:

  • 80% CPU Usage (hoste me 4 vCPU, 4 GB RAM, Linux)
  • 130 MB Mem RSS

Si të mbroni faqen tuaj publike me ESNI

Për krahasim, RPS për të njëjtin upstream nginx pa terminim TLS (protokolli HTTP) është ~ 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 

Prania e timeout-eve tregon se ka mungesë burimesh (ne përdorëm hoste me 4 vCPU, 4 GB RAM, Linux), dhe në praktikë RPS potencial është më i lartë (ne morëm shifra deri në 2700 RPS me burime më të fuqishme).

NĂ« pĂ«rfundim, do tĂ« theksoj se teknologjia ESNI duket mjaft premtuese. Ka ende shumĂ« çështje tĂ« hapura, pĂ«r shembull ruajtja e çelĂ«sit publik ESNI nĂ« DNS dhe rotacioni i çelĂ«save ESNI – kĂ«to çështje po diskutohen nĂ« mĂ«nyrĂ« aktive, ndĂ«rsa versioni mĂ« i fundit i draftit (nĂ« momentin e shkrimit) pĂ«r ESNI tashmĂ« 7.

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster