Hallo Habr, mijn naam is Ilya, ik werk in het platformteam bij Exness. We ontwikkelen en implementeren de kerninfrastructuurcomponenten die onze productontwikkelingsteams gebruiken.
In dit artikel wil ik mijn ervaringen delen met het implementeren van gecodeerde SNI (ESNI)-technologie in de infrastructuur van openbare websites.
Het gebruik van deze technologie zal het beveiligingsniveau verhogen bij het werken met een openbare website en voldoen aan de interne beveiligingsnormen die door het bedrijf zijn aangenomen.
Allereerst wil ik erop wijzen dat de technologie niet gestandaardiseerd is en nog in de conceptfase zit, maar dat CloudFlare en Mozilla deze al ondersteunen (in
Een beetje theorie
ESNI is een uitbreiding op het TLS 1.3-protocol dat SNI-codering mogelijk maakt in het TLS-handshakebericht "Client Hallo". Zo ziet Client Hello eruit met ESNI-ondersteuning (in plaats van de gebruikelijke SNI zien we ESNI):
Om ESNI te gebruiken, heb je drie componenten nodig:
- DNS;
- Klantenondersteuning;
- Ondersteuning aan serverzijde.
DNS
U moet twee DNS-records toevoegen: AEn TXT (Het TXT-record bevat de openbare sleutel waarmee de client SNI kan coderen) - zie hieronder. Bovendien moet er draagvlak zijn DoH (DNS via HTTPS) omdat beschikbare clients (zie hieronder) ESNI-ondersteuning niet inschakelen zonder DoH. Dit is logisch, aangezien ESNI versleuteling impliceert van de naam van de bron waartoe we toegang hebben, dat wil zeggen dat het geen zin heeft om toegang te krijgen tot DNS via UDP. Bovendien het gebruik
Nu verkrijgbaar
CloudFlare
А invoer:
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, aanvraag wordt gegenereerd volgens een 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."
}
Vanuit DNS-perspectief moeten we dus DoH gebruiken (bij voorkeur met DNSSEC) en twee vermeldingen toevoegen.
Klantenservice
Als we het over browsers hebben, dan op dit moment
Uiteraard moet TLS 1.3 worden gebruikt om ESNI te ondersteunen, aangezien ESNI een uitbreiding is op TLS 1.3.
Om de backend met ESNI-ondersteuning te testen, hebben we de client geïmplementeerd go, Maar daarover later meer.
Ondersteuning aan serverzijde
Momenteel wordt ESNI niet ondersteund door webservers zoals nginx/apache etc., omdat deze met TLS werken via OpenSSL/BoringSSL, die ESNI officieel niet ondersteunen.
Daarom hebben we besloten om onze eigen front-endcomponent (ESNI reverse proxy) te maken, die TLS 1.3-beëindiging met ESNI en proxy HTTP(S)-verkeer naar de upstream zou ondersteunen, wat ESNI niet ondersteunt. Hierdoor kan de technologie worden gebruikt in een reeds bestaande infrastructuur, zonder de hoofdcomponenten te veranderen – dat wil zeggen met behulp van huidige webservers die ESNI niet ondersteunen.
Voor de duidelijkheid, hier is een diagram:
Ik merk op dat de proxy is ontworpen met de mogelijkheid om een TLS-verbinding zonder ESNI te beëindigen, om klanten zonder ESNI te ondersteunen. Bovendien kan het communicatieprotocol met upstream HTTP of HTTPS zijn met een TLS-versie lager dan 1.3 (als upstream 1.3 niet ondersteunt). Deze regeling biedt maximale flexibiliteit.
Implementatie van ESNI-ondersteuning op go wij hebben geleend van
Om ESNI-sleutels te genereren die we hebben gebruikt
We hebben de build getest met go 1.13 op Linux (Debian, Alpine) en MacOS.
Een paar woorden over operationele kenmerken
ESNI reverse proxy biedt statistieken in Prometheus-formaat, zoals rps, upstream latentie- en responscodes, mislukte/succesvolle TLS-handshakes en TLS-handshake-duur. Op het eerste gezicht leek dit voldoende om te evalueren hoe de proxy omgaat met verkeer.
We hebben vóór gebruik ook belastingtests uitgevoerd. Resultaten 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
We hebben puur kwalitatieve belastingtests uitgevoerd om het schema te vergelijken met ESNI reverse proxy en zonder. We hebben het verkeer lokaal "gegoten" om "interferentie" in tussenliggende componenten te elimineren.
Dus met ESNI-ondersteuning en proxying upstream van HTTP haalden we ongeveer ~550 rps uit één exemplaar, met het gemiddelde CPU/RAM-verbruik van ESNI reverse proxy:
- 80% CPU-gebruik (4 vCPU, 4 GB RAM-hosts, Linux)
- 130 MB RSS-geheugen
Ter vergelijking: de RPS voor dezelfde nginx upstream zonder TLS-beëindiging (HTTP-protocol) is ~ 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
De aanwezigheid van time-outs geeft aan dat er een gebrek aan bronnen is (we gebruikten 4 vCPU's, 4 GB RAM-hosts, Linux), en in feite is de potentiële RPS hoger (we ontvingen cijfers tot 2700 RPS op krachtigere bronnen).
Concluderend merk ik op dat de ESNI-technologie er veelbelovend uitziet. Er zijn nog steeds veel open vragen, bijvoorbeeld de kwesties van het opslaan van de openbare ESNI-sleutel in de DNS en het roteren van ESNI-sleutels - deze kwesties worden actief besproken en de nieuwste versie van het ESNI-concept (op het moment van schrijven) is al beschikbaar.
Bron: www.habr.com