Tere, Habr! Minu nimi on Ilja, ma töötan Exnessi platvormimeeskonnas. Me arendame ja rakendame põhistruktuuri komponente, mida kasutavad meie toote arendusmeeskonnad.
Selles artiklis soovin jagada kogemusi tehnoloogia encrypted SNI (ESNI) rakendamise kohta avalike veebisaitide infrastruktuuris.

Selle tehnoloogia kasutamine võimaldab suurendada avaliku veebisaidi turvalisust ja vastata organisatsiooni sissepoliitilistele turvastandarditele.
Enne kui alustan, tahan märkida, et tehnoloogia ei ole veel standardiseeritud ja on ikka veel mustand, kuid CloudFlare ja Mozilla toetavad seda juba ( ). See motiveeris meid selliseks eksperimendiks.
Natuke teooriat
ESNI on TLS 1.3 protokolli laiendus, mis võimaldab SNI-d krüpteerida TLS handshake'i "Client Hello" sõnumis. Nii näeb välja Client Hello, mis toetab ESNI-d (tavapärase SNI asemel näeme ESNI-d):

ESNI kasutamiseks on vajalik kolm koostisosade:
- DNS;
- Kliendi poolne tugi;
- Serveri poolne tugi.
DNS
On vaja lisada kaks DNS kanta - A, ja TXT (TXT-kirje sisaldab avalikku võtit, millega klient saab SNI-d krüpteerida) – vt allpool. Lisaks peab olema tugi DoH (DNS üle HTTPS), kuna saadaval olevad kliendid (vt allpool) ei aktiveeri ESNI tuge ilma DoH-ta. See on mõistlik, kuna ESNI eeldab ressurssi nime krüpteerimist, millega me ühendust võtame, seega pole mõtet pöörduda DNS-i poole UDP kaudu. Veelgi enam, kasutamine aitab kaitsta 'cache poisoning' rünnakute eest selles stsenaariumis.
Praeguseks on saadaval , nende hulgas:
CloudFlare (Check My Browser → Encrypted SNI → Learn More), et nende serverid toetavad juba praegu ESNI-d, st CloudFlare'i serverite jaoks DNS-is on vähemalt kaks kirjet – A ja TXT. Allolevas näites küsime Google DNS-i (HTTPS-i kaudu):
A kirje:
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 kirje, päring koostatakse mallil _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."
}Seega, DNS-i seisukohalt peame kasutama DoH (eelistatavalt DNSSEC-iga) ja lisama kaks kirjet.
Kliendi tugi
Kui räägime brauseritest, siis hetkel . Siin on juhised, kuidas aktiveerida ESNI ja DoH tugi FireFoxis. Kui brauser on konfigureeritud, peaksime nägema umbes sellist pilti:

brauseri kontrollimiseks.
Muidugi peab ESNI toe tagamiseks olema kasutusel TLS 1.3, kuna ESNI on TLS 1.3 laiendus.
ESNI toe edendamiseks oleme realiseerinud kliendi go, kuid sellest natuke hiljem.
Serveri tugi
Praegu ei toeta ESNI veebiserverid nagu nginx/apache jne, kuna need töötavad TLS-iga OpenSSL/BoringSSL kaudu, kus ESNI ametlikult ei ole toetatud.
Seetõttu otsustasime luua oma front-end komponendi (ESNI tagasiproks), mis toetaks TLS 1.3 terminaatorit koos ESNI-ga ning HTTP(S) liikluse silumist allavoolu, mis ei toeta ESNI-d. See võimaldab tehnoloogia rakendamist juba olemasolevas infrastruktuuris, ilma põhikomponente muutes — st kasutada olemasolevaid veebiservereid, mis ei toeta ESNI-d.
Toome selguse huvides välja skeemi:

Tähtis on märkida, et proks on mõeldud TLS-i ühenduse lõpetamiseks ilma ESNI-ta, et toetada kliente, kes ei kasuta ESNI-d. Samuti võib suhtlusprotokoll allavoolu olla nii HTTP kui ka HTTPS, koos TLS-i versiooniga madalam kui 1.3 (kui allavool ei toeta 1.3). Selline skeem annab maksimaalse paindlikkuse.
ESNI toe rakendamise go me laenasime . Tõstaksin esile, et rakendamine on üsna keeruline, kuna see eeldab muudatusi standardraamatukogus crypto/tls ja seetõttu nõuab see 'patchimist' GOROOT enne kokkupanekut.
ESNI võtmete genereerimiseks kasutasime (mille on ka loonud CloudFlare). Need võtmed on mõeldud SNI krüpteerimiseks/dekrüpteerimiseks.
Testisime kogumist, kasutades go 1.13 Linuxis (Debian, Alpine) ja MacOS-iga.
Mõned sõnad tööpõhimõtete kohta
ESNI pöördproksi pakub metrikat Prometheuse formaadis, näiteks rps, ülemineku latentsus & response codes, ebaõnnestunud/edukad TLS-käeulatused & TLS-käeulatused kestus. Esmapilgul tundus, et see on piisav, et hinnata, kuidas proksi liiklust haldab.
Enne kasutamist viisime läbi koormustesti. Tulemused on järgmised:
wrk -t50 -c1000 -d360s 'https://esni-rev-proxy.npw:443' --timeout 15s
Käimas 6m test @ https://esni-rev-proxy.npw:443
50 lõime ja 1000 ühendust
Lõime statistika Keskmine Standardhälve Max +/– Standardhälve
Latentsus 1.77s 1.21s 7.20s 65.43%
Req/Sec 13.78 8.84 140.00 83.70%
206357 päringut 6.00m jooksul, 6.08GB loetud
Päringud/s: 573.07
Ülekanded/s: 17.28MB Koormustesti viisime läbi puhtalt kvaliteetsete, et võrrelda skeeme kasutades ESNI pöördproksi ja ilma. Suunates liiklust kohalikult, soovisime välistada 'häireid' vahekomponentides.
Nii, ESNI toe ja HTTP ülemineku korral saime umbes ~ 550 rps ühe instantsi kohta, samal ajal kui keskmine CPU/RAM tarbimine ESNI pöördproksi oli:
- 80% CPU kasutus (4 vCPU, 4 GB RAM hostid, Linux)
- 130 MB Mem RSS

Võrdluseks: RPS sama ülemineku nginx-i jaoks ilma TLS-terminatsiooni (HTTP protokoll) ~ 1100:
wrk -t50 -c1000 -d360s 'http://lb.npw:80' –-timeout 15s
Käivitame 6-minutilise testi aadressil http://lb.npw:80
50 lõime ja 1000 ühendust
Lõimete statistika Avg Stdev Max +/- Stdev
Latentsus 1.11s 2.30s 15.00s 90.94%
Req/Sec 23.25 13.55 282.00 79.25%
393093 päringut 6.00 minutiga, 11.35GB loetud
Soketivead: ühendamine 0, lugemine 0, kirjutamine 0, timeout 9555
Mitte-2xx või 3xx vastused: 8111
Päringud/s: 1091.62
Ülekanded/s: 32.27MB Aegade puudumine viitab sellele, et ressursse on vähe (kasutasime 4 vCPU, 4 GB RAM hoste, Linux), ja tegelikult on potentsiaalne RPS kõrgem (oleme saanud numbreid kuni 2700 RPS võimsamates seadmete puhul).
Kokkuvõtteks märgin, et ESNI tehnoloogia näib olema päris lootustandev. On veel palju avatud küsimusi, näiteks avaliku ESNI võtme ladustamise küsimused DNS-is ja ESNI võtmete rotatsioon – neid küsimusi arutatakse aktiivselt, ja viimane projekti versioon (käesoleva kirjutamise hetkel) ESNI on juba .
Allikas: habr.com
