Hoe je je publieke website kunt beschermen met ESNI

Hallo Habr, mijn naam is Ilya, ik werk bij het platformteam van Exness. We ontwikkelen en implementeren basisinfrastructuurcomponenten die door onze productontwikkelingsteams worden gebruikt.

In dit artikel wil ik mijn ervaringen delen met de implementatie van encrypted SNI (ESNI) technologie in de infrastructuur van openbare websites.

Hoe je je publieke website kunt beschermen met ESNI

Het gebruik van deze technologie zal het beveiligingsniveau bij het beheren van een openbare website verhogen en voldoen aan de interne beveiligingsnormen die binnen het bedrijf zijn vastgesteld.

Allereerst wil ik benadrukken dat de technologie nog niet is gestandaardiseerd en zich nog in de draftfase bevindt, maar CloudFlare en Mozilla ondersteunen deze al (in draft01). Dit heeft ons gemotiveerd om met deze experimenten te beginnen.

Een beetje theorie

ESNI is een uitbreiding van het TLS 1.3-protocol die het mogelijk maakt om SNI in het "Client Hello"-bericht van de TLS-handshake te versleutelen. Zo ziet een Client Hello met ondersteuning voor ESNI eruit (in plaats van de gebruikelijke SNI zien we ESNI):

Hoe je je publieke website kunt beschermen met ESNI

 Om ESNI te gebruiken zijn drie componenten nodig:

  • DNS; 
  • Ondersteuning van de client;
  • Ondersteuning van de server.

DNS

Er moeten twee DNS-records worden toegevoegd - A, en TXT (Het TXT-record bevat de openbare sleutel waarmee de client SNI kan versleutelen) - zie hieronder. Daarnaast moet er ondersteuning zijn voor DoH (DNS over HTTPS), aangezien de beschikbare clients (zie hieronder) geen ondersteuning voor ESNI activeren zonder DoH. Dit is logisch, omdat ESNI betekent dat de naam van de bron die we aanroepen versleuteld moet worden, wat betekent dat het zinloos is om DNS via UDP aan teroepen. Bovendien biedt het gebruik van DNSSEC bescherming tegen 'cache poisoning'-aanvallen in deze scenario.

Op dit moment zijn er enkele DoH-providers, waaronder:

CloudFlare beveelt aan (Check My Browser → Encrypted SNI → Learn More), dat hun servers al ESNI ondersteunen, wat betekent dat we voor CloudFlare-servers in DNS minstens twee records hebben - A en TXT. In het onderstaande voorbeeld vragen we Google DNS (over HTTPS) aan: 

A record:

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 record, het verzoek wordt volgens sjabloon gevormd _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 het oogpunt van DNS, moeten we DoH (bij voorkeur met DNSSEC) gebruiken en twee records toevoegen. 

Ondersteuning van de klant

Als we het over browsers hebben, dan is op dit moment de ondersteuning alleen geïmplementeerd in FireFox. Hier hier is een instructie over hoe je ESNI en DoH in FireFox activeert. Nadat de browser is ingesteld, zouden we een afbeelding moeten zien zoals:

Hoe je je publieke website kunt beschermen met ESNI

Link voor het controleren van de browser.

Uiteraard moet TLS 1.3 worden gebruikt om ESNI te ondersteunen, omdat ESNI een uitbreiding is van TLS 1.3.

Voor testdoeleinden van de backend met ESNI-ondersteuning hebben we een client geïmplementeerd op go, maar daarover later meer.

Ondersteuning van de server

Op dit moment wordt ESNI niet ondersteund door webservers zoals nginx/apache, omdat ze met TLS werken via OpenSSL/BoringSSL, waarin ESNI officieel niet wordt ondersteund.

Daarom hebben we besloten een eigen front-end component te creëren (ESNI reverse proxy) dat TLS 1.3 met ESNI kan termineren en HTTP(S) verkeer kan proxen naar upstream dat ESNI niet ondersteunt. Dit stelt ons in staat om de technologie in een reeds bestaande infrastructuur toe te passen, zonder de belangrijkste componenten te wijzigen - dat wil zeggen, het huidige webservers te gebruiken die ESNI niet ondersteunen. 

Ter illustratie geven we een schema:

Hoe je je publieke website kunt beschermen met ESNI

Ik wil opmerken dat de proxy is ontworpen met de mogelijkheid om een TLS-verbinding zonder ESNI te termineren, voor de ondersteuning van klanten zonder ESNI. Bovendien kan het communicatieprotocol met upstream zowel HTTP als HTTPS zijn met een versie van TLS lager dan 1.3 (als de upstream 1.3 niet ondersteunt). Dit schema biedt maximale flexibiliteit.

De implementatie van ESNI-ondersteuning op go hebben we overgenomen van CloudFlare. Laat me meteen benadrukken dat de implementatie zelf vrij complex is, aangezien deze veranderingen in de standaardbibliotheek vereist. crypto/tls en daarom 'patching' vereist GOROOT voor de build.

Voor het genereren van ESNI-sleutels hebben we esnitool (ook een creatie van CloudFlare) gebruikt. Deze sleutels worden gebruikt voor de encryptie/decryptie van SNI.
We hebben de build getest met go 1.13 op Linux (Debian, Alpine) en MacOS. 

Een paar woorden over operationele kenmerken

De ESNI reverse proxy biedt metrics in Prometheus-formaat, zoals rps, upstream latentie & responsecodes, mislukte/succesvolle TLS-handshakes & de duur van de TLS-handshake. Op het eerste gezicht leek dit voldoende om te beoordelen hoe de proxy omgaat met verkeer. 

Daarnaast hebben we voor gebruik een stresstest uitgevoerd. De resultaten zijn hieronder:

wrk -t50 -c1000 -d360s 'https://esni-rev-proxy.npw:443' --timeout 15s
Running 6m test @ https://esni-rev-proxy.npw:443
  50 threads en 1000 verbindingen
  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 gelezen
Requests/sec:    573.07
Transfer/sec:     17.28MB 

De stresstest was puur kwalitatief, om de scenario's met en zonder de ESNI reverse proxy te vergelijken. We 'injecteerden' verkeer lokaal om eventuele 'interferentie' in tussenliggende componenten uit te sluiten.

Dus, met ondersteuning voor ESNI en upstream proxied via HTTP, kregen we ongeveer ~ 550 rps van één instantie, met een gemiddeld CPU/RAM verbruik van de ESNI reverse proxy:

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

Hoe je je publieke website kunt beschermen met ESNI

Ter vergelijking, RPS voor dezelfde upstream nginx zonder TLS-terminatie (HTTP-protocol) ~ 1100:

wrk -t50 -c1000 -d360s 'http://lb.npw:80' --timeout 15s
Running 6m test @ http://lb.npw:80
  50 threads en 1000 verbindingen
  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 gelezen
  Socketfouten: connect 0, read 0, write 0, timeout 9555
  Niet-2xx of 3xx responses: 8111
Requests/sec:   1091.62
Transfer/sec:     32.27MB 

De aanwezigheid van timeouts duidt op een tekort aan middelen (we hebben 4 vCPU, 4 GB RAM hosts, Linux) en in werkelijkheid ligt het potentieel RPS hoger (we haalden cijfers tot 2700 RPS op krachtigere middelen).

Tot slot wil ik opmerken, dat de ESNI-technologie veelbelovend lijkt. Er zijn nog veel open vragen, zoals de opslag van de publieke ESNI-sleutel in DNS en het roteren van ESNI-sleutels - deze kwesties worden actief besproken, en de laatste versie van de draft (ten tijde van schrijven) van ESNI is al 7.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster