Cumu prutegge u vostru situ web publicu cù ESNI

Ciao Habr, mi chjamu Ilya, travagliu in a squadra di a piattaforma in Exness. Sviluppemu è implementemu i cumpunenti di l'infrastruttura core chì i nostri squadre di sviluppu di produttu utilizanu.

In questu articulu, vogliu sparte a mo sperienza di implementà a tecnulugia SNI (ESNI) criptata in l'infrastruttura di i siti web publichi.

Cumu prutegge u vostru situ web publicu cù ESNI

L'usu di sta tecnulugia aumenterà u livellu di sicurità quandu travaglia cù un situ web publicu è rispettu i normi di sicurezza interna aduttati da a Cumpagnia.

Prima di tuttu, vogliu nutà chì a tecnulugia ùn hè micca standardizzata è hè sempre in u prugettu, ma CloudFlare è Mozilla sò digià supportatu (in draft01). Questu ci hà motivatu per un tali esperimentu.

Un pocu di tiurìa

ESNI hè una estensione di u protocolu TLS 1.3 chì permette a criptografia SNI in u messagiu "Client Hello" di TLS handshake. Eccu ciò chì Client Hello s'assumiglia cù u supportu ESNI (invece di u solitu SNI vedemu ESNI):

Cumu prutegge u vostru situ web publicu cù ESNI

 Per utilizà ESNI, avete bisognu di trè cumpunenti:

  • DNS; 
  • supportu à i clienti;
  • Supportu di u latu di u servitore.

DNS

Avete bisognu di aghjunghje dui registri DNS - Ae TXT (U registru TXT cuntene a chjave publica cù quale u cliente pò criptà SNI) - vede quì sottu. Inoltre, deve esse supportu DOH (DNS sopra HTTPS) perchè i clienti dispunibili (vede quì sottu) ùn permettenu micca u supportu ESNI senza DoH. Questu hè logicu, postu chì ESNI implica a criptografia di u nome di a risorsa chì accedemu, vale à dì, ùn hà micca sensu per accede à DNS per UDP. Inoltre, l'usu DNSSEC permette di prutege contra l'attacchi di avvelenamentu di cache in questu scenariu.

Attualmente dispunibule parechji fornitori di DoH, trà elli:

CloudFlare dichjara (Verificate My Browser → Encrypted SNI → Learn More) chì i so servitori supportanu digià ESNI, vale à dì, per i servitori CloudFlare in u DNS avemu almenu dui registri - A è TXT. In l'esempiu quì sottu, dumandemu Google DNS (sopra HTTPS): 

А entrata:

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, a dumanda hè generata secondu un mudellu _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."
}

Dunque, da una perspettiva DNS, duvemu aduprà DoH (preferibbilmente cù DNSSEC) è aghjunghje duie entrate. 

Supportu à i clienti

Sè avemu parlatu di navigatori, allora in u mumentu U supportu hè implementatu solu in FireFox. Eccu struzzioni nantu à cumu attivà u supportu ESNI è DoH in FireFox. Una volta chì u navigatore hè cunfiguratu, duvemu vede qualcosa cum'è questu:

Cumu prutegge u vostru situ web publicu cù ESNI

a lea per verificà u navigatore.

Di sicuru, TLS 1.3 deve esse usatu per supportà ESNI, postu chì ESNI hè una estensione à TLS 1.3.

Per u scopu di pruvà u backend cù u supportu ESNI, avemu implementatu u cliente go, Ma più nantu à questu dopu.

Supportu di u latu di u servitore

Attualmente, ESNI ùn hè micca supportatu da i servitori web cum'è nginx / apache, etc., postu chì travaglianu cù TLS via OpenSSL / BoringSSL, chì ùn supportanu micca ufficialmente ESNI.

Dunque, avemu decisu di creà u nostru propiu cumpunente front-end (ESNI reverse proxy), chì sustene a terminazione TLS 1.3 cù ESNI è u trafficu HTTP (S) proxy à u upstream, chì ùn sustene micca ESNI. Questu permette di utilizà a tecnulugia in una infrastruttura digià esistente, senza cambià i cumpunenti principali - vale à dì, aduprà i servitori web attuali chì ùn sustene micca ESNI. 

Per a chiarezza, quì hè un schema:

Cumu prutegge u vostru situ web publicu cù ESNI

Aghju nutatu chì u proxy hè statu cuncepitu cù a capacità di finisce una cunnessione TLS senza ESNI, per sustene i clienti senza ESNI. Inoltre, u protocolu di cumunicazione cù upstream pò esse HTTP o HTTPS cù una versione TLS più bassa di 1.3 (se upstream ùn sustene micca 1.3). Stu schema dà a massima flessibilità.

Mise en œuvre du support ESNI sur go avemu prestitu da CloudFlare. Vogliu nutà subitu chì l'implementazione stessa hè abbastanza micca triviale, postu chì implica cambiamenti in a biblioteca standard. crypto/tls è dunque richiede "patching" GOROOT prima di l'assemblea.

Per generà e chjave ESNI avemu usatu esnitool (ancu l'idea di CloudFlare). Queste chjavi sò aduprate per a criptografia / decrittografia SNI.
Avemu pruvatu a custruzzione cù go 1.13. Linux (Debian, Alpine) è MacOS. 

Uni pochi parolle nantu à e caratteristiche operative

U proxy inversu ESNI furnisce metriche in u formatu Prometheus, cum'è rps, latenza upstream è codici di risposta, handshake TLS falluti / successi è durata TLS handshake. À u primu sguardu, questu pareva abbastanza per valutà cumu u proxy gestisce u trafficu. 

Avemu ancu realizatu teste di carica prima di l'usu. Risultati quì sottu:

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 

Avemu fattu una prova di carica puramente qualitativa per paragunà u schema utilizendu un proxy inversu ESNI è senza. Avemu "versatu" u trafficu in u locu per eliminà "interferenza" in cumpunenti intermedi.

Dunque, cù u supportu ESNI è u proxy à upstream da HTTP, avemu circa ~ 550 rps da una istanza, cù u cunsumu mediu CPU / RAM di proxy inversu ESNI:

  • 80% d'usu di a CPU (4 vCPU, 4 GB di RAM, Linux)
  • 130 MB Mem RSS

Cumu prutegge u vostru situ web publicu cù ESNI

Per paragone, RPS per u stessu nginx upstream senza terminazione TLS (protokollu HTTP) hè ~ 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 

A prisenza di timeouts indica chì ci hè una mancanza di risorse (avemu utilizatu 4 vCPU, host di 4 GB di RAM, Linux), è in fatti u putenziale RPS hè più altu (avemu ricevutu cifre finu à 2700 RPS nantu à risorse più putenti).

In cunclusioni, aghju nutatu chì a tecnulugia ESNI pare assai promettente. Ci sò sempre parechje dumande aperte, per esempiu, i prublemi di almacenà a chjave ESNI publica in u DNS è rotazione di e chjave ESNI - sti prublemi sò attivamente discututi, è l'ultima versione di u prugettu ESNI (à u mumentu di a scrittura) hè digià. 7.

Source: www.habr.com

Cumprate un hosting affidabile per i siti cù prutezzione DDoS, servitori VPS VDS 🔥 Cumprate un hosting di siti web affidabile cù prutezzione DDoS, servitori VPS VDS | ProHoster