Hur man skyddar sin offentliga webbplats med ESNI

Hej Habr, jag heter Ilya och jag arbetar i plattformsteamet pÄ företaget Exness. Vi utvecklar och implementerar grundlÀggande infrastrukturella komponenter som vÄra produktutvecklingsteam anvÀnder.

I den hÀr artikeln skulle jag vilja dela med mig av erfarenheten av att implementera teknologin encrypted SNI (ESNI) i infrastrukturen för publika webbplatser.

Hur man skyddar sin offentliga webbplats med ESNI

AnvÀndningen av denna teknologi kommer att öka sÀkerhetsnivÄn vid arbete med publika webbplatser och uppfylla interna sÀkerhetsstandarder som antagits av företaget.

Först och frÀmst vill jag pÄpeka att teknologin inte Àr standardiserad och fortfarande Àr i utkast, men CloudFlare och Mozilla stöder den redan (i draft01). Det Àr vad som motiverade oss till detta experiment.

Lite teori

ESNI Àr en utvidgning av TLS 1.3-protokollet som möjliggör kryptering av SNI i meddelandet 'Client Hello' under TLS-handshake. SÄ hÀr ser 'Client Hello' ut med ESNI-stöd (istÀllet för det vanliga SNI ser vi ESNI):

Hur man skyddar sin offentliga webbplats med ESNI

 För att anvÀnda ESNI behövs tre komponenter:

  • DNS; 
  • Klientstöd;
  • Serverstöd.

DNS

TvĂ„ DNS-poster mĂ„ste lĂ€ggas till – A, och TXT (TXT-posten innehĂ„ller den offentliga nyckeln som klienten kan anvĂ€nda för att kryptera SNI) – se nedan. Dessutom mĂ„ste stöd för DoH (DNS over HTTPS) finnas, eftersom tillgĂ€ngliga klienter (se nedan) inte aktiverar ESNI-stöd utan DoH. Detta Ă€r logiskt, eftersom ESNI innebĂ€r kryptering av resursnamnet vi anropar, det vill sĂ€ga det Ă€r meningslöst att anropa DNS via UDP. Dessutom möjliggör anvĂ€ndningen av DNSSEC att skydda sig mot 'cache poisoning'-attacker i detta scenario.

För nÀrvarande finns det flera DoH-leverantörer, bland dem:

CloudFlare uttalar (Check My Browser → Encrypted SNI → Learn More), att deras servrar redan nu stöder ESNI, det vill sĂ€ga för CloudFlare-servrar har vi minst tvĂ„ poster i DNS – A och TXT. I exemplet nedan anropar vi Google DNS (över HTTPS): 

A post:

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 post, begÀran formuleras enligt mallen _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."
}

SÄ ur ett DNS-perspektiv bör vi anvÀnda DoH (helst med DNSSEC) och lÀgga till tvÄ poster. 

Support frÄn kunden

Om vi talar om webblÀsare, sÄ Àr det för nÀrvarande stöd implementerat endast i FireFox. HÀr hÀr Àr en instruktion för hur man aktiverar stöd för ESNI och DoH i FireFox. NÀr webblÀsaren Àr konfigurerad, bör vi se nÄgot i stil med:

Hur man skyddar sin offentliga webbplats med ESNI

LÀnk för att kontrollera webblÀsaren.

SjÀlvklart mÄste TLS 1.3 anvÀndas för att stödja ESNI, eftersom ESNI Àr en tillÀgg till TLS 1.3.

För testÀndamÄl av backend med stöd för ESNI har vi implementerat en klient pÄ go, men mer om det senare.

Support frÄn servern

För nÀrvarande stöds inte ESNI av webbservrar som nginx/apache m.fl., eftersom de arbetar med TLS via OpenSSL/BoringSSL, dÀr ESNI inte officiellt stöds.

DĂ€rför har vi beslutat att skapa vĂ„r egen front-end-komponent (ESNI reverse proxy) som skulle stödja TLS 1.3-terminering med ESNI och proxy HTTP(S)-trafik till en upstream som inte stöder ESNI. Detta möjliggör anvĂ€ndning av teknologin i en redan etablerad infrastruktur, utan att förĂ€ndra grundkomponenterna – det vill sĂ€ga att anvĂ€nda nuvarande webbservrar som inte stöder ESNI. 

För tydlighetens skull, hÀr Àr ett diagram:

Hur man skyddar sin offentliga webbplats med ESNI

Jag vill pÄpeka att proxyn designades för att kunna terminera TLS-anslutningar utan ESNI, för att stödja klienter som inte har ESNI. Dessutom kan protokollet för kommunikation med upstream vara bÄde HTTP och HTTPS med en TLS-version under 1.3 (om upstream inte stöder 1.3). Detta schema ger maximal flexibilitet.

Implementeringen av ESNI-support pÄ go har vi lÄnat frÄn CloudFlare. Jag vill genast pÄpeka att sjÀlva implementeringen Àr ganska icke-trivialiskt, eftersom den krÀver Àndringar i standardbiblioteket crypto/tls och dÀrför krÀver "patchning" GOROOT innan byggnation.

För att generera ESNI-nycklar anvÀnde vi esnitool (ocksÄ ett projekt frÄn CloudFlare). Dessa nycklar anvÀnds för kryptering/avkryptering av SNI.
Vi testade bygget med go 1.13 pÄ Linux (Debian, Alpine) och MacOS. 

NÄgra ord om driftsÀkerhetsaspekter

ESNI reverse proxy erbjuder metrics i Prometheus-format, sÄsom rps, upstream latens & responskoder, misslyckade/lyckade TLS-handshakes & TLS-handshake varaktighet. Vid första anblick sÄg detta tillrÀckligt ut för att bedöma hur proxy klarar av trafiken. 

Innan vi anvÀnde den genomförde vi Àven belastningstestning. Resultaten nedan:

wrk -t50 -c1000 -d360s 'https://esni-rev-proxy.npw:443' --timeout 15s
Kör 6m test @ https://esni-rev-proxy.npw:443
 50 trÄdar och 1000 anslutningar
 TrĂ„dstatistik   Genomsnitt   Stdev     Max   +/− Stdev
  Latens      1.77s     1.21s    7.20s    65.43%
  BegÀrningar/Sek    13.78      8.84   140.00     83.70%
  206357 begÀrningar pÄ 6.00m, 6.08GB lÀsta
BegÀrningar/s:    573.07
Överföring/s:     17.28MB 

Vi genomförde belastningstestningen av rent kvalitativa skÀl, för att jÀmföra scheman med och utan ESNI reverse proxy. Vi "matade" trafiken lokalt för att utesluta "störningar" i mellanliggande komponenter.

SÄ, med stöd för ESNI och proxytjÀnst till upstream med HTTP, fick vi cirka ~ 550 rps frÄn en instans, medan den genomsnittliga CPU/RAM-anvÀndningen för ESNI reverse proxy:

  • 80% CPU-anvĂ€ndning (4 vCPU, 4 GB RAM-vĂ€rdar, Linux)
  • 130 MB Mem RSS

Hur man skyddar sin offentliga webbplats med ESNI

I jÀmförelse, RPS för samma upstream nginx utan TLS-terminering (HTTP-protokoll) ~ 1100:

wrk -t50 -c1000 -d360s 'http://lb.npw:80' –-timeout 15s
Kör 6m test @ http://lb.npw:80
 50 trÄdar och 1000 anslutningar
 TrĂ„dstatistik   Genomsnitt   Stdev     Max   +/− Stdev
  Latens      1.11s     2.30s   15.00s    90.94%
  BegÀrningar/Sek    23.25      13.55   282.00     79.25%
  393093 begÀrningar pÄ 6.00m, 11.35GB lÀsta
  Socket-fel: anslut 0, lÀs 0, skriv 0, timeout 9555
  Icke-2xx eller 3xx svar: 8111
BegÀrningar/s:   1091.62
Överföring/s:     32.27MB 

NÀrvaron av timeouts tyder pÄ att det finns brist pÄ resurser (vi anvÀnde 4 vCPU, 4 GB RAM-vÀrdar, Linux), och faktiska potentiella RPS Àr högre (vi fick siffror upp till 2700 RPS pÄ kraftfullare resurser).

Avslutningsvis vill jag nĂ€mna att teknologin ESNI ser ganska lovande ut. Det finns fortfarande mĂ„nga öppna frĂ„gor, sĂ„som lagring av den offentliga ESNI-nyckeln i DNS och rotation av ESNI-nycklar – dessa frĂ„gor diskuteras aktivt, och den senaste versionen av utkastet (vid tidpunkten för skrivandet) ESNI redan 7.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster