Saluton Habr, mia nomo estas Ilya, mi laboras en la platforma teamo ĉe Exness. Ni disvolvas kaj efektivigas bazajn infrastrukturajn komponantojn, kiujn niaj produktaj disvolvaj teamoj uzas.
En ĉi tiu artikolo, mi ŝatus dividi mian sperton pri efektivigo de ĉifrita SNI (ESNI) teknologio en la infrastrukturo de publikaj retejoj.

La uzo de ĉi tiu teknologio pliigos la nivelon de sekureco dum laborado kun publika retejo kaj plenumos la internajn sekurecnormojn adoptitajn de la Kompanio.
Unue, mi volas atentigi, ke la teknologio ne estas normigita kaj ankoraŭ estas en skizo, sed CloudFlare kaj Mozilla jam subtenas ĝin (en ). Tio estas kio instigis nin fari tian eksperimenton.
Iom teorio
ESNI – estas etendaĵo al la protokolo TLS 1.3, kiu permesas ĉifri SNI en la mesaĝo "Client Hello" de TLS-manpremo. Jen kiel aspektas Klienta Saluto kun ESNI-subteno (anstataŭ la kutima SNI, ni vidas ESNI):

Por uzi ESNI, necesas tri komponantoj:
- DNS;
- Klienta subteno;
- Servila flanko subteno.
DNS
Vi bezonas aldoni du DNS-rekordojn – Akaj TXT (TXT-registro enhavas la publikan ŝlosilon per kiu la kliento povas ĉifri SNI) – vidu sube. Krome, devus esti subteno DoH (DNS per HTTPS), ĉar la disponeblaj klientoj (vidu sube) ne aktivigas ESNI-subtenon sen DoH. Ĉi tio estas logika, ĉar ESNI implicas ĉifradon de la rimeda nomo, kiun ni aliras, t.e., ne havas sencon aliri DNS per UDP. Krome, uzante permesas al vi protekti kontraŭ atakoj de kaŝmemora venenado en ĉi tiu scenaro.
Nuntempe havebla , inter ili:
CloudFlare (Kontrolu Mian Retumilon → Ĉifrita SNI → Lerni Pli), ke iliaj serviloj jam subtenas ESNI, tio estas, por CloudFlare-serviloj en DNS ni havas almenaŭ du rikordojn - A kaj TXT. En la suba ekzemplo, ni petas Google DNS (per HTTPS):
А eniro:
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 rikordo, peto estas generita laŭ ŝablono _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."
}
Do, el DNS-perspektivo, ni devus uzi DoH (prefere kun DNSSEC) kaj aldoni du rikordojn.
Klienta subteno
Se ni parolas pri retumiloj, tiam nuntempe . Instrukcioj pri kiel aktivigi ESNI kaj DoH-subtenon en Fajrovulpo estas provizitaj. Post kiam la retumilo estas agordita, ni devus vidi ion tian:

por kontroli la retumilon.
Kompreneble, TLS 1.3 devas esti uzata por subteni ESNI, ĉar ESNI estas etendaĵo de TLS 1.3.
Por testi la internan servon kun ESNI-subteno, ni efektivigis klienton sur go, Sed pli pri tio poste.
Servila flanko subteno
Nuntempe ESNI ne estas subtenata de retserviloj kiel nginx/apache ktp., ĉar ili funkcias kun TLS per OpenSSL/BoringSSL, kiuj ne oficiale subtenas ESNI.
Tial ni decidis krei nian propran front-end-komponenton (ESNI-inversa prokurilo), kiu subtenus TLS 1.3-finadon kun ESNI kaj prokurilon de HTTP(S)-trafiko al la suprenflua linio, kiu ne subtenas ESNI. Ĉi tio permesas uzi la teknologion en jam ekzistanta infrastrukturo, sen ŝanĝi la ĉefajn komponentojn - tio estas, uzi nunajn retservilojn, kiuj ne subtenas ESNI.
Por klareco, jen diagramo:

Mi ŝatus rimarkigi, ke la prokurilo estis desegnita kun la kapablo fini TLS-konekton sen ESNI, por subteni klientojn sen ESNI. Ankaŭ, la protokolo por komuniki kun la suprenflua servo povas esti aŭ HTTP aŭ HTTPS kun TLS-versio sub 1.3 (se la suprenflua servo ne subtenas 1.3). Ĉi tiu skemo provizas maksimuman flekseblecon.
Efektivigo de ESNI-subteno pri go ni pruntis de Mi tuj rimarkos, ke la efektivigo mem estas tute netriviala, ĉar ĝi implicas ŝanĝojn en la norma biblioteko. kripto/tls kaj tial postulas "flikadon" GOROOT antaŭ la muntado.
Por generi ESNI-ŝlosilojn ni uzis (ankaŭ kreaĵo de CloudFlare). Ĉi tiuj ŝlosiloj estas uzataj por ĉifri/malĉifri SNI.
Ni testis la konstruon uzante go 1.13 sur Linux (Debian, Alpa) kaj MacOS.
Kelkaj vortoj pri funkciaj trajtoj
ESNI-inversa prokurilo provizas metrikojn en Prometheus-formato, kiel ekzemple rps, kontraŭfluan latentecon kaj respondkodojn, malsukcesajn/sukcesajn TLS-manpremojn kaj daŭron de TLS-manpremoj. Unuavide, tio ŝajnis sufiĉa por taksi kiel la prokurilo traktas trafikon.
Ni ankaŭ faris ŝarĝtestadon antaŭ uzo. La rezultoj estas sube:
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
Ni faris pure kvalitan ŝarĝtestadon por kompari la skemon kun kaj sen ESNI-inversa prokurilo. Ni "enverŝis" trafikon loke por forigi "interferon" en interaj komponantoj.
Do, kun ESNI-subteno kaj kontraŭflua prokurilo per HTTP, ni ricevis ĉirkaŭ ~550 rps de unu instanco, kun la averaĝa CPU/RAM-konsumo de ESNI-inversa prokurilo:
- 80% CPU-uzado (4 vCPU, 4 GB RAM-gastigantoj, Linux)
- 130 MB Mem RSS

Por komparo, RPS por la sama nginx kontraŭflue sen TLS-fino (HTTP-protokolo) estas ~ 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 ĉeesto de templimoj indikas, ke mankas rimedoj (ni uzis 4 vCPU-ojn, 4 GB da RAM-gastigantoj, Linux), kaj fakte la ebla RPS estas pli alta (ni ricevis ciferojn ĝis 2700 RPS ĉe pli potencaj rimedoj).
Konklude, mi ŝatus rimarkigi, ke ke ESNI-teknologio aspektas sufiĉe promesplena. Ankoraŭ ekzistas multaj malfermaj demandoj, ekzemple, la aferoj pri konservado de la publika ESNI-ŝlosilo en DNS kaj rotaciado de ESNI-ŝlosiloj - ĉi tiuj aferoj estas aktive diskutataj, kaj la plej nova versio de la skizo (dum la verkado de ĉi tiu artikolo) de ESNI jam estas... .
fonto: www.habr.com
