Hoe om jou publieke webwerf met ESNI te beskerm

Hallo Habr, my naam is Ilya, ek werk in die platformspan by Exness. Ons ontwikkel en implementeer die kerninfrastruktuurkomponente wat ons produkontwikkelingspanne gebruik.

In hierdie artikel wil ek graag my ervaring deel van die implementering van geïnkripteer SNI (ESNI) tegnologie in die infrastruktuur van openbare webwerwe.

Hoe om jou publieke webwerf met ESNI te beskerm

Die gebruik van hierdie tegnologie sal die vlak van sekuriteit verhoog wanneer daar met 'n publieke webwerf gewerk word en voldoen aan interne sekuriteitstandaarde wat deur die Maatskappy aanvaar is.

Eerstens wil ek daarop wys dat die tegnologie nie gestandaardiseer is nie en steeds in die konsep is, maar CloudFlare en Mozilla ondersteun dit reeds (in konsep01). Dit het ons gemotiveer vir so 'n eksperiment.

'N bietjie teorie

ESNI is 'n uitbreiding van die TLS 1.3-protokol wat SNI-enkripsie in die TLS-handdruk "Client Hello"-boodskap toelaat. Hier is hoe Client Hello lyk met ESNI-ondersteuning (in plaas van die gewone SNI sien ons ESNI):

Hoe om jou publieke webwerf met ESNI te beskerm

 Om ESNI te gebruik, benodig jy drie komponente:

  • DNS; 
  • Kliënte ondersteuning;
  • Bedienerkant ondersteuning.

DNS

Jy moet twee DNS-rekords byvoeg – AEn TXT (Die TXT-rekord bevat die publieke sleutel waarmee die kliënt SNI kan enkripteer) - sien hieronder. Boonop moet daar ondersteuning wees DvG (DNS oor HTTPS) omdat beskikbare kliënte (sien hieronder) nie ESNI-ondersteuning sonder DoH aktiveer nie. Dit is logies, aangesien ESNI enkripsie impliseer van die naam van die hulpbron waartoe ons toegang het, dit wil sê, dit maak geen sin om toegang tot DNS oor UDP te verkry nie. Verder, die gebruik DNSSEC laat jou toe om teen kasvergiftigingsaanvalle in hierdie scenario te beskerm.

Tans beskikbaar verskeie DoH-verskaffers, tussen hulle:

CloudFlare state (Gaan na My blaaier → Geënkripteerde SNI → Kom meer te wete) dat hul bedieners reeds ESNI ondersteun, dit wil sê, vir CloudFlare-bedieners in die DNS het ons ten minste twee rekords - A en TXT. In die voorbeeld hieronder vra ons Google DNS (oor HTTPS): 

А inskrywing:

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 rekord, versoek word gegenereer volgens 'n sjabloon _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."
}

Dus, vanuit 'n DNS-perspektief, moet ons DoH gebruik (verkieslik met DNSSEC) en twee inskrywings byvoeg. 

Klientediens

As ons praat oor blaaiers, dan op die oomblik ondersteuning word slegs in FireFox geïmplementeer. Hier Hier is instruksies oor hoe om ESNI- en DoH-ondersteuning in FireFox te aktiveer. Nadat die blaaier opgestel is, behoort ons iets soos hierdie te sien:

Hoe om jou publieke webwerf met ESNI te beskerm

Link om die blaaier na te gaan.

Natuurlik moet TLS 1.3 gebruik word om ESNI te ondersteun, aangesien ESNI 'n uitbreiding van TLS 1.3 is.

Vir die doel om die backend met ESNI-ondersteuning te toets, het ons die kliënt geïmplementeer op go, Maar later meer daaroor.

Bedienerkant ondersteuning

Tans word ESNI nie deur webbedieners soos nginx/apache, ens. ondersteun nie, aangesien hulle met TLS werk via OpenSSL/BoringSSL, wat nie ESNI amptelik ondersteun nie.

Daarom het ons besluit om ons eie front-end-komponent (ESNI-omgekeerde instaanbediener) te skep, wat TLS 1.3-beëindiging met ESNI en proxy HTTP(S)-verkeer na die stroomop sal ondersteun, wat nie ESNI ondersteun nie. Dit laat toe dat die tegnologie in 'n reeds bestaande infrastruktuur gebruik word, sonder om die hoofkomponente te verander - dit wil sê, die gebruik van huidige webbedieners wat nie ESNI ondersteun nie. 

Vir duidelikheid, hier is 'n diagram:

Hoe om jou publieke webwerf met ESNI te beskerm

Ek neem kennis dat die instaanbediener ontwerp is met die vermoë om 'n TLS-verbinding sonder ESNI te beëindig, om kliënte sonder ESNI te ondersteun. Die kommunikasieprotokol met stroomop kan ook HTTP of HTTPS wees met 'n TLS-weergawe laer as 1.3 (indien stroomop nie 1.3 ondersteun nie). Hierdie skema gee maksimum buigsaamheid.

Implementering van ESNI-ondersteuning op go ons het geleen by CloudFlare. Ek wil dadelik daarop let dat die implementering self redelik nie-triviaal is, aangesien dit veranderinge in die standaardbiblioteek behels kripto/tls en vereis dus "patching" GOROOT voor samestelling.

Ons het gebruik om ESNI-sleutels te genereer esnitool (ook die breinkind van CloudFlare). Hierdie sleutels word gebruik vir SNI-enkripsie/dekripsie.
Ons het die bou getoets met go 1.13 op Linux (Debian, Alpine) en MacOS. 

'N Paar woorde oor operasionele kenmerke

ESNI-omgekeerde instaanbediener verskaf maatstawwe in Prometheus-formaat, soos rps, stroomop latensie en reaksiekodes, mislukte/suksesvolle TLS-handdrukke en TLS-handdrukduur. Met die eerste oogopslag het dit genoeg gelyk om te evalueer hoe die proxy verkeer hanteer. 

Ons het ook vragtoetse uitgevoer voor gebruik. Resultate hieronder:

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 

Ons het suiwer kwalitatiewe lastoetse uitgevoer om die skema te vergelyk met ESNI omgekeerde instaanbediener en sonder. Ons het plaaslik verkeer "uitgegooi" om "inmenging" in intermediêre komponente uit te skakel.

Dus, met ESNI-ondersteuning en proxying na stroomop van HTTP, het ons ongeveer ~550 rps vanaf een geval gekry, met die gemiddelde SVE/RAM-verbruik van ESNI omgekeerde instaanbediener:

  • 80% SVE-gebruik (4 vCPU, 4 GB RAM-gashere, Linux)
  • 130 MB Mem RSS

Hoe om jou publieke webwerf met ESNI te beskerm

Ter vergelyking is RPS vir dieselfde nginx stroomop sonder TLS (HTTP-protokol) beëindiging ~ 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 

Die teenwoordigheid van time-outs dui daarop dat daar 'n gebrek aan hulpbronne is (ons het 4 vCPU's, 4 GB RAM-gashere, Linux gebruik), en in werklikheid is die potensiële RPS hoër (ons het syfers van tot 2700 RPS op kragtiger hulpbronne ontvang).

Ten slotte merk ek op dat ESNI-tegnologie nogal belowend lyk. Daar is nog baie oop vrae, byvoorbeeld die kwessies van die stoor van die publieke ESNI-sleutel in die DNS en roterende ESNI-sleutels - hierdie kwessies word aktief bespreek, en die nuutste weergawe van die ESNI-konsep (ten tyde van die skryf daarvan) is reeds 7.

Bron: will.com

Voeg 'n opmerking