Slik beskytter du din offentlige nettside med ESNI

Hei Habr, jeg heter Ilya, og jeg jobber i plattformteamet hos Exness. Vi utvikler og implementerer grunnleggende infrastrukturkomponenter som produktutviklingsteamene våre bruker.

I denne artikkelen vil jeg dele mine erfaringer med implementering av kryptert SNI-teknologi (ESNI) i infrastrukturen til offentlige nettsteder.

Slik beskytter du din offentlige nettside med ESNI

Bruken av denne teknologien vil øke sikkerhetsnivået når man jobber med et offentlig nettsted og overholde de interne sikkerhetsstandardene som er vedtatt av selskapet.

Først og fremst vil jeg påpeke at teknologien ikke er standardisert og fortsatt er i utkastfasen, men CloudFlare og Mozilla støtter den allerede (i utkast01). Dette var grunnen til at vi ble bedt om å gjennomføre et slikt eksperiment.

Litt teori

ESNI – er en utvidelse av TLS 1.3-protokollen som lar deg kryptere SNI i TLS-håndtrykkmeldingen «Client Hello». Slik ser en Client Hello med ESNI-støtte ut (i stedet for den vanlige SNI-en ser vi ESNI):

Slik beskytter du din offentlige nettside med ESNI

 For å bruke ESNI kreves tre komponenter:

  • DNS; 
  • Kundestøtte;
  • Støtte på serversiden.

DNS

Du må legge til to DNS-oppføringer – AOg TXT (TXT-oppføringen inneholder den offentlige nøkkelen som klienten kan kryptere SNI med) – se nedenfor. I tillegg bør det være støtte for Doh (DNS over HTTPS), siden de tilgjengelige klientene (se nedenfor) ikke aktiverer ESNI-støtte uten DoH. Dette er logisk, siden ESNI innebærer kryptering av ressursnavnet vi har tilgang til, dvs. det gir ingen mening å få tilgang til DNS over UDP. Dessuten, bruk av DNSSEC lar deg beskytte mot cache-forgiftningsangrep i dette scenariet.

Tilgjengelig for øyeblikket flere DoH-leverandører, blant dem:

CloudFlare stater (Sjekk nettleseren min → Kryptert SNI → Lær mer), at serverne deres allerede støtter ESNI, det vil si at for CloudFlare-servere i DNS har vi minst to poster - A og TXT. I eksemplet nedenfor ber vi om Google DNS (over HTTPS): 

А inngang:

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, forespørselen genereres i henhold til en mal _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å, fra et DNS-perspektiv, bør vi bruke DoH (helst med DNSSEC) og legge til to poster. 

Kundestøtte

Hvis vi snakker om nettlesere, så for øyeblikket støtte er kun implementert i FireFox. Her Instruksjoner om hvordan du aktiverer ESNI- og DoH-støtte i FireFox er gitt. Etter at nettleseren er konfigurert, bør vi se noe slikt:

Slik beskytter du din offentlige nettside med ESNI

Ссылка for å sjekke nettleseren.

Selvfølgelig må TLS 1.3 brukes for å støtte ESNI, siden ESNI er en utvidelse av TLS 1.3.

For å teste backend-systemet med ESNI-støtte, implementerte vi en klient på go, men mer om det senere.

Støtte på serversiden

For øyeblikket støttes ikke ESNI av webservere som nginx/apache osv., ettersom de fungerer med TLS via OpenSSL/BoringSSL, som ikke offisielt støtter ESNI.

Derfor bestemte vi oss for å lage vår egen front-end-komponent (ESNI reverse proxy), som ville støtte TLS 1.3-terminering med ESNI og proxying av HTTP(S)-trafikk til oppstrøms, som ikke støtter ESNI. Dette tillater bruk av teknologien i en allerede eksisterende infrastruktur, uten å endre hovedkomponentene – det vil si å bruke nåværende webservere som ikke støtter ESNI. 

For klarhetens skyld, her er et diagram:

Slik beskytter du din offentlige nettside med ESNI

Jeg vil bemerke at proxyen ble designet med muligheten til å avslutte en TLS-tilkobling uten ESNI, for å støtte klienter uten ESNI. Protokollen for kommunikasjon med oppstrømsleverandøren kan også være enten HTTP eller HTTPS med en TLS-versjon under 1.3 (hvis oppstrømsleverandøren ikke støtter 1.3). Denne ordningen gir maksimal fleksibilitet.

Implementering av ESNI-støtte på go vi lånte fra CloudFlareJeg vil umiddelbart bemerke at selve implementeringen er ganske enkel, siden den innebærer endringer i standardbiblioteket. krypto/tls og krever derfor "patching" GOROOT før montering.

For å generere ESNI-nøkler brukte vi esnitool (også en CloudFlare-kreasjon). Disse nøklene brukes til å kryptere/dekryptere SNI.
Vi testet bygget med go 1.13 på Linux (Debian, Alpine) og MacOS. 

Noen ord om driftsfunksjoner

ESNI reverse proxy tilbyr målinger i Prometheus-format, som rps, oppstrøms latens og responskoder, mislykkede/vellykkede TLS-håndtrykk og TLS-håndtrykkvarighet. Ved første øyekast virket dette tilstrekkelig for å vurdere hvordan proxyen håndterer trafikk. 

Vi utførte også belastningstesting før bruk. Resultatene er nedenfor:

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 

Vi utførte rent kvalitativ belastningstesting for å sammenligne skjemaet med og uten ESNI reverse proxy. Vi "pumpet" trafikk lokalt for å eliminere "forstyrrelser" i mellomliggende komponenter.

Så, med ESNI-støtte og oppstrøms proxy med HTTP, fikk vi rundt ~550 rps fra én instans, med gjennomsnittlig CPU/RAM-forbruk for ESNI reverse proxy:

  • 80 % CPU-bruk (4 vCPU, 4 GB RAM-verter, Linux)
  • 130 MB minne-RSS

Slik beskytter du din offentlige nettside med ESNI

Til sammenligning er RPS for samme nginx oppstrøms uten TLS-terminering (HTTP-protokoll) ~ 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 

Tilstedeværelsen av tidsavbrudd indikerer at det er mangel på ressurser (vi brukte 4 vCPU, 4 GB RAM-verter, Linux), og faktisk er den potensielle RPS høyere (vi mottok tall opptil 2700 RPS på kraftigere ressurser).

Avslutningsvis vil jeg bemerke at at ESNI-teknologien ser ganske lovende ut. Det er fortsatt mange åpne spørsmål, for eksempel spørsmålene om lagring av den offentlige ESNI-nøkkelen i DNS og rotasjon av ESNI-nøkler – disse problemstillingene diskuteres aktivt, og den nyeste versjonen av utkastet (i skrivende stund) av ESNI er allerede klar. 7.

Kilde: www.habr.com

Kjøp pålitelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere 🔥 Kjøp pålitelig webhotell med DDoS-beskyttelse, VPS VDS-servere | ProHoster