Com protegir el vostre lloc web públic amb ESNI

Hola Habr, em dic Ilya, treballo a l'equip de plataforma d'Exness. Desenvolupem i implementem els components bàsics de la infraestructura que utilitzen els nostres equips de desenvolupament de productes.

En aquest article, m'agradaria compartir la meva experiència en la implementació de la tecnologia SNI xifrada (ESNI) a la infraestructura de llocs web públics.

Com protegir el vostre lloc web públic amb ESNI

L'ús d'aquesta tecnologia augmentarà el nivell de seguretat quan es treballa amb un lloc web públic i complirà amb els estàndards de seguretat interna adoptats per l'Empresa.

En primer lloc, m'agradaria assenyalar que la tecnologia no està estandarditzada i encara està a l'esborrany, però CloudFlare i Mozilla ja la donen suport (en esborrany01). Això ens va motivar per a aquest experiment.

Una mica de teoria

ESNI és una extensió del protocol TLS 1.3 que permet l'encriptació SNI al missatge "Client Hello" de TLS. A continuació es mostra l'aspecte de Client Hello amb el suport d'ESNI (en lloc de l'SNI habitual, veiem ESNI):

Com protegir el vostre lloc web públic amb ESNI

 Per utilitzar ESNI, necessiteu tres components:

  • DNS; 
  • Suport al client;
  • Suport del costat del servidor.

DNS

Heu d'afegir dos registres DNS: AI TXT (El registre TXT conté la clau pública amb la qual el client pot xifrar SNI) - vegeu a continuació. A més, hi ha d'haver suport Doh (DNS sobre HTTPS) perquè els clients disponibles (vegeu més avall) no habiliten el suport d'ESNI sense DoH. Això és lògic, ja que ESNI implica xifratge del nom del recurs al qual estem accedint, és a dir, no té sentit accedir a DNS per UDP. A més, l'ús DNSSEC us permet protegir-vos dels atacs d'enverinament de la memòria cau en aquest escenari.

Disponible actualment diversos proveïdors de DoH, entre ells:

CloudFlare declara (Consulta el meu navegador → SNI xifrat → Més informació) que els seus servidors ja admeten ESNI, és a dir, per als servidors CloudFlare del DNS tenim almenys dos registres: A i TXT. A l'exemple següent consultem el DNS de Google (a través d'HTTPS): 

А entrada:

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 registre, la sol·licitud es genera segons una plantilla _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."
}

Per tant, des d'una perspectiva de DNS, hauríem d'utilitzar DoH (preferiblement amb DNSSEC) i afegir dues entrades. 

Atenció al client

Si estem parlant de navegadors, de moment El suport només s'implementa a FireFox. Aquí Aquí teniu instruccions sobre com activar el suport ESNI i DoH a FireFox. Un cop configurat el navegador, hauríem de veure alguna cosa com això:

Com protegir el vostre lloc web públic amb ESNI

Enllaç per comprovar el navegador.

Per descomptat, s'ha d'utilitzar TLS 1.3 per donar suport a ESNI, ja que ESNI és una extensió de TLS 1.3.

Amb el propòsit de provar el backend amb suport d'ESNI, hem implementat el client go, Però sobre això més endavant.

Suport del costat del servidor

Actualment, ESNI no és compatible amb servidors web com nginx/apache, etc., ja que funcionen amb TLS mitjançant OpenSSL/BoringSSL, que oficialment no admeten ESNI.

Per tant, vam decidir crear el nostre propi component de front-end (proxy invers ESNI), que admetria la terminació de TLS 1.3 amb ESNI i el trànsit HTTP(S) del proxy cap a l'aigües amunt, que no és compatible amb ESNI. Això permet utilitzar la tecnologia en una infraestructura ja existent, sense canviar els components principals, és a dir, utilitzant servidors web actuals que no admeten ESNI. 

Per a més claredat, aquí teniu un diagrama:

Com protegir el vostre lloc web públic amb ESNI

Tinc en compte que el proxy es va dissenyar amb la possibilitat de finalitzar una connexió TLS sense ESNI, per donar suport als clients sense ESNI. A més, el protocol de comunicació amb upstream pot ser HTTP o HTTPS amb una versió TLS inferior a 1.3 (si upstream no admet 1.3). Aquest esquema ofereix la màxima flexibilitat.

Implementació del suport ESNI a go vam agafar en préstec CloudFlare. M'agradaria assenyalar de seguida que la implementació en si no és gens trivial, ja que implica canvis a la biblioteca estàndard. cripto/tls i per tant requereix un "pegat" GOROOT abans del muntatge.

Per generar les claus ESNI hem utilitzat esnitool (també la creació de CloudFlare). Aquestes claus s'utilitzen per al xifratge/desxifrat SNI.
Vam provar la compilació utilitzant go 1.13 a Linux (Debian, Alpine) i MacOS. 

Unes paraules sobre les característiques operatives

El servidor intermediari invers ESNI proporciona mètriques en format Prometheus, com ara rps, latència amunt i codis de resposta, encaixades de mans TLS fallides/encertades i durada de l'enllaç TLS. A primera vista, això semblava suficient per avaluar com el servidor intermediari gestiona el trànsit. 

També hem realitzat proves de càrrega abans del seu ús. Resultats a continuació:

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 

Hem realitzat proves de càrrega purament qualitatives per comparar l'esquema utilitzant el proxy invers ESNI i sense. Hem "abocat" el trànsit localment per tal d'eliminar les "interferències" en components intermedis.

Per tant, amb el suport d'ESNI i el proxy a aigües amunt des d'HTTP, vam obtenir al voltant de 550 rps d'una instància, amb el consum mitjà de CPU/RAM del servidor intermediari invers ESNI:

  • 80% d'ús de la CPU (amfitrions de 4 vCPU, 4 GB de RAM, Linux)
  • 130 MB Mem RSS

Com protegir el vostre lloc web públic amb ESNI

Per comparar, RPS per al mateix nginx aigües amunt sense terminació TLS (protocol HTTP) és ~ 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 

La presència de temps d'espera indica que hi ha una manca de recursos (hem utilitzat 4 vCPU, hosts de 4 GB de RAM, Linux), i de fet l'RPS potencial és més alt (hem rebut xifres de fins a 2700 RPS en recursos més potents).

En conclusió, anoto que la tecnologia ESNI sembla força prometedora. Encara hi ha moltes preguntes obertes, per exemple, els problemes d'emmagatzemar la clau ESNI pública al DNS i la rotació de les claus ESNI; aquests problemes s'estan discutint activament i la darrera versió de l'esborrany d'ESNI (en el moment d'escriure aquest escrit) ja està 7.

Font: www.habr.com

Compreu allotjament fiable per a llocs amb protecció DDoS, servidors VPS VDS 🔥 Compra allotjament web fiable amb protecció DDoS, servidors VPS VDS | ProHoster