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.

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

 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 ju lejon tĂ« mbroheni nga sulmet âcache poisoningâ nĂ« kĂ«tĂ« skenar.
Aktualisht janë të disponueshëm , ndër ta:
CloudFlare (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 . 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ë:

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:

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

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Ă« .
Burimi: habr.com
