Kaip apsaugoti savo viešą svetainę naudojant ESNI

Sveiki, Habr, mano vardas Ilja, aš dirbu „Exness“ platformos komandoje. Kuriame ir įdiegiame pagrindinius infrastruktūros komponentus, kuriuos naudoja mūsų produktų kūrimo komandos.

Šiame straipsnyje norėčiau pasidalinti savo patirtimi diegiant šifruotą SNI (ESNI) technologiją viešųjų svetainių infrastruktūroje.

Kaip apsaugoti savo viešą svetainę naudojant ESNI

Šios technologijos naudojimas padidins saugumo lygį dirbant su vieša svetaine ir atitiks Bendrovės priimtus vidinius saugumo standartus.

Visų pirma norėčiau atkreipti dėmesį į tai, kad technologija nėra standartizuota ir vis dar yra juodraštyje, tačiau „CloudFlare“ ir „Mozilla“ ją jau palaiko (į juodraštis01). Tai paskatino mus tokiam eksperimentui.

Teorijos tiek

ESNI yra TLS 1.3 protokolo plėtinys, leidžiantis SNI šifravimą TLS rankos paspaudimo pranešime „Klientas sveikas“. Štai kaip atrodo „Client Hello“ su ESNI palaikymu (vietoj įprasto SNI matome ESNI):

Kaip apsaugoti savo viešą svetainę naudojant ESNI

 Norėdami naudoti ESNI, jums reikia trijų komponentų:

  • DNS; 
  • Klientų palaikymas;
  • Serverio pusės palaikymas.

DNS

Turite pridėti du DNS įrašus - AIr TXT (TXT įraše yra viešasis raktas, kuriuo klientas gali užšifruoti SNI) – žr. toliau. Be to, turi būti parama DoH (DNS per HTTPS), nes galimi klientai (žr. toliau) neįgalina ESNI palaikymo be DoH. Tai logiška, nes ESNI reiškia šaltinio, prie kurio mes pasiekiame, pavadinimo šifravimą, tai yra, nėra prasmės pasiekti DNS per UDP. Be to, naudojimas DNSSEC leidžia apsisaugoti nuo apsinuodijimo talpykla atakų pagal šį scenarijų.

Šiuo metu galimas keli DoH teikėjai, tarp jų:

CloudFlare pareiškia (Patikrinkite Mano naršyklę → Šifruotas SNI → Sužinokite daugiau), kad jų serveriai jau palaiko ESNI, tai yra, CloudFlare serveriams DNS turime bent du įrašus - A ir TXT. Toliau pateiktame pavyzdyje pateikiame užklausą dėl Google DNS (per HTTPS): 

А įrašas:

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 įrašas, užklausa sugeneruojama pagal šabloną _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."
}

Taigi, iš DNS perspektyvos, turėtume naudoti DoH (geriausia su DNSSEC) ir pridėti du įrašus. 

Pagalba klientams

Jei mes kalbame apie naršykles, tai šiuo metu palaikymas įdiegtas tik „FireFox“.. Čia Čia pateikiamos instrukcijos, kaip suaktyvinti ESNI ir DoH palaikymą „FireFox“. Kai naršyklė bus sukonfigūruota, turėtume pamatyti kažką panašaus:

Kaip apsaugoti savo viešą svetainę naudojant ESNI

Nuoroda norėdami patikrinti naršyklę.

Žinoma, ESNI palaikymui turi būti naudojamas TLS 1.3, nes ESNI yra TLS 1.3 plėtinys.

Siekdami išbandyti užpakalinę programą su ESNI palaikymu, įdiegėme klientą go, Bet apie tai vėliau.

Serverio pusės palaikymas

Šiuo metu ESNI nepalaiko žiniatinklio serveriai, tokie kaip nginx/apache ir kt., nes jie dirba su TLS per OpenSSL/BoringSSL, kurie oficialiai nepalaiko ESNI.

Todėl nusprendėme sukurti savo priekinį komponentą (ESNI atvirkštinį tarpinį serverį), kuris palaikytų TLS 1.3 nutraukimą su ESNI ir tarpinio serverio HTTP(S) srautą į aukštesnįjį srautą, kuris nepalaiko ESNI. Tai leidžia technologiją naudoti jau esamoje infrastruktūroje, nekeičiant pagrindinių komponentų – tai yra naudojant esamus žiniatinklio serverius, nepalaikančius ESNI. 

Aiškumo dėlei čia yra diagrama:

Kaip apsaugoti savo viešą svetainę naudojant ESNI

Atkreipiu dėmesį, kad tarpinis serveris buvo sukurtas taip, kad būtų galima nutraukti TLS ryšį be ESNI, palaikyti klientus be ESNI. Be to, ryšio protokolas prieš srovę gali būti HTTP arba HTTPS su žemesne nei 1.3 TLS versija (jei prieš srovę nepalaiko 1.3). Ši schema suteikia maksimalų lankstumą.

ESNI paramos įgyvendinimas ant go mes skolinomės iš CloudFlare. Iš karto norėčiau pastebėti, kad pats diegimas yra gana nereikšmingas, nes jis apima standartinės bibliotekos pakeitimus crypto/tls todėl reikia „pataisyti“ GOROOT prieš surinkimą.

ESNI raktams generuoti naudojome esnitool (taip pat „CloudFlare“ idėja). Šie raktai naudojami SNI šifravimui / iššifravimui.
Мы протестировали сборку с использованием go 1.13 на Linux (Debian, Alpine) и MacOS. 

Keletas žodžių apie veikimo ypatybes

ESNI atvirkštinis tarpinis serveris teikia metriką Prometheus formatu, pvz., RPS, priešpriešinio delsos ir atsako kodus, nesėkmingus / sėkmingus TLS rankų paspaudimus ir TLS rankos paspaudimo trukmę. Iš pirmo žvilgsnio to pakanka norint įvertinti, kaip tarpinis serveris tvarko srautą. 

Taip pat prieš naudojimą atlikome apkrovos testavimą. Rezultatai žemiau:

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 

Mes atlikome grynai kokybinius apkrovos testus, kad palygintume schemą naudodami ESNI atvirkštinį tarpinį serverį ir be jo. Mes „išliejome“ srautą vietoje, kad pašalintume „trukdžius“ tarpiniuose komponentuose.

Taigi, turėdami ESNI palaikymą ir tarpinį serverį prieš srovę nuo HTTP, iš vieno egzemplioriaus gavome apie 550 aps./s, o ESNI atvirkštinio tarpinio serverio vidutinis CPU/RAM suvartojimas:

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

Kaip apsaugoti savo viešą svetainę naudojant ESNI

Palyginimui, RPS tam pačiam nginx prieš srovę be TLS (HTTP protokolo) nutraukimo yra ~ 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 на более мощных ресурсах).

Baigdamas pažymiu kad ESNI technologija atrodo gana daug žadanti. Vis dar yra daug neišspręstų klausimų, pavyzdžiui, viešo ESNI rakto saugojimo DNS ir ESNI raktų kaitaliojimo klausimai - šie klausimai yra aktyviai diskutuojami, o naujausia ESNI projekto versija (rašymo metu) jau yra 7.

Šaltinis: www.habr.com

Pirkite patikimą prieglobą svetainėms su DDoS apsauga, VPS VDS serveriais 🔥 Įsigykite patikimą svetainių talpinimą su DDoS apsauga, VPS VDS serveriais | ProHoster