Bonjour Habr, je m'appelle Ilya, je travaille dans l'équipe plateforme chez Exness. Nous développons et mettons en œuvre les composants d’infrastructure de base utilisés par nos équipes de développement de produits.
Dans cet article, j'aimerais partager mon expérience de mise en œuvre de la technologie cryptée SNI (ESNI) dans l'infrastructure des sites Web publics.
L'utilisation de cette technologie augmentera le niveau de sécurité lors du travail avec un site Web public et se conformera aux normes de sécurité internes adoptées par la Société.
Tout d'abord, je tiens à souligner que la technologie n'est pas standardisée et est encore à l'état de projet, mais CloudFlare et Mozilla la supportent déjà (en
Un peu de théorie
ESNI est une extension du protocole TLS 1.3 qui permet le cryptage SNI dans le message de prise de contact TLS « Client Hello ». Voici à quoi ressemble Client Hello avec le support ESNI (au lieu du SNI habituel, nous voyons ESNI) :
Pour utiliser ESNI, vous avez besoin de trois composants :
- DNS ;
- Accompagnement client ;
- Prise en charge côté serveur.
DNS
Vous devez ajouter deux enregistrements DNS – AEt TXT (L'enregistrement TXT contient la clé publique avec laquelle le client peut chiffrer SNI) - voir ci-dessous. De plus, il doit y avoir un soutien DoH (DNS sur HTTPS) car les clients disponibles (voir ci-dessous) n'activent pas la prise en charge ESNI sans DoH. C'est logique, puisque ESNI implique le cryptage du nom de la ressource à laquelle nous accédons, c'est-à-dire que cela n'a aucun sens d'accéder au DNS via UDP. De plus, l'utilisation
Actuellement disponible
CloudFlare
А enregistrement:
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 enregistrement, la demande est générée selon un modèle _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."
}
Donc, du point de vue DNS, nous devrions utiliser DoH (de préférence avec DNSSEC) et ajouter deux entrées.
Service client
Si nous parlons de navigateurs, alors pour le moment
Bien entendu, TLS 1.3 doit être utilisé pour prendre en charge ESNI, puisque ESNI est une extension de TLS 1.3.
Dans le but de tester le backend avec le support ESNI, nous avons implémenté le client sur go, Mais plus là-dessus plus tard.
Prise en charge côté serveur
Actuellement, ESNI n'est pas pris en charge par les serveurs Web comme nginx/apache, etc., car ils fonctionnent avec TLS via OpenSSL/BoringSSL, qui ne prennent pas officiellement en charge ESNI.
Par conséquent, nous avons décidé de créer notre propre composant frontal (proxy inverse ESNI), qui prendrait en charge la terminaison TLS 1.3 avec ESNI et le trafic proxy HTTP(S) vers l'amont, qui ne prend pas en charge ESNI. Cela permet d'utiliser la technologie dans une infrastructure déjà existante, sans modifier les principaux composants, c'est-à-dire en utilisant des serveurs Web actuels qui ne prennent pas en charge ESNI.
Pour plus de clarté, voici un schéma :
Je note que le proxy a été conçu avec la possibilité de mettre fin à une connexion TLS sans ESNI, pour prendre en charge les clients sans ESNI. De plus, le protocole de communication avec l'amont peut être soit HTTP, soit HTTPS avec une version TLS inférieure à 1.3 (si l'amont ne prend pas en charge 1.3). Ce schéma offre une flexibilité maximale.
Mise en œuvre du support ESNI sur go nous avons emprunté à
Pour générer les clés ESNI, nous avons utilisé
Nous avons testé la version avec go 1.13 sur Linux (Debian, Alpine) et MacOS.
Quelques mots sur les fonctionnalités opérationnelles
Le proxy inverse ESNI fournit des métriques au format Prometheus, telles que les rps, la latence en amont et les codes de réponse, les négociations TLS échouées/réussies et la durée de la négociation TLS. À première vue, cela semblait suffisant pour évaluer la manière dont le proxy gère le trafic.
Nous avons également effectué des tests de charge avant utilisation. Résultats ci-dessous :
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
Nous avons effectué des tests de charge purement qualitatifs pour comparer le schéma avec et sans proxy inverse ESNI. Nous avons « versé » le trafic localement afin d'éliminer les « interférences » dans les composants intermédiaires.
Ainsi, avec la prise en charge d'ESNI et le proxy en amont depuis HTTP, nous avons reçu environ 550 rps d'une instance, avec la consommation moyenne CPU/RAM du proxy inverse ESNI :
- Utilisation du processeur à 80 % (4 vCPU, 4 Go de RAM hôtes, Linux)
- 130 Mo de mémoire RSS
À titre de comparaison, le RPS pour le même nginx en amont sans terminaison TLS (protocole HTTP) est d'environ 1100 XNUMX :
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 présence de timeouts indique qu'il y a un manque de ressources (nous avons utilisé 4 vCPU, 4 Go de RAM hôtes, Linux), et en fait le potentiel RPS est plus élevé (nous avons reçu des chiffres allant jusqu'à 2700 RPS sur des ressources plus puissantes).
En conclusion, je note que la technologie ESNI semble très prometteuse. Il reste encore de nombreuses questions ouvertes, par exemple les problèmes de stockage de la clé ESNI publique dans le DNS et de rotation des clés ESNI - ces questions sont activement discutées et la dernière version du projet ESNI (au moment de la rédaction) est déjà
Source: habr.com