Hallo Habr, mäin Numm ass Ilya, ech schaffen am Plattformteam bei Exness. Mir entwéckelen an implementéieren d'Kärinfrastrukturkomponenten déi eis Produktentwécklungsteams benotzen.
An dësem Artikel géif ech gär meng Erfahrung vun der Ëmsetzung vun verschlësselte SNI (ESNI) Technologie an der Infrastruktur vun ëffentleche Websäiten ze deelen.

D'Benotzung vun dëser Technologie wäert den Niveau vun der Sécherheet erhéijen wann Dir mat enger ëffentlecher Websäit schafft an entsprécht intern Sécherheetsnormen, déi vun der Firma ugeholl goufen.
Als éischt wëll ech drop hiweisen datt d'Technologie net standardiséiert ass an nach ëmmer am Entworf ass, awer CloudFlare a Mozilla ënnerstëtzen et scho (an ). Dëst huet eis fir esou en Experiment motivéiert.
E bësse vun der Theorie
ESNI ass eng Extensioun vum TLS 1.3 Protokoll deen SNI Verschlësselung am TLS Handshake "Client Hallo" Message erlaabt. Hei ass wéi Client Hello mat ESNI Support ausgesäit (amplaz vum üblechen SNI gesi mir ESNI):

Fir ESNI ze benotzen, braucht Dir dräi Komponenten:
- DNS;
- Client Ënnerstëtzung;
- Server Säit Ënnerstëtzung.
DNS
Dir musst zwee DNS records addéieren - Aan txt (Den TXT Rekord enthält den ëffentleche Schlëssel mat deem de Client SNI verschlëssele kann) - kuckt hei ënnen. Ausserdeem muss et Ënnerstëtzung ginn DoH (DNS iwwer HTTPS) well verfügbare Clienten (kuckt hei ënnen) net ESNI Ënnerstëtzung ouni DoH aktivéieren. Dëst ass logesch, well ESNI implizéiert Verschlësselung vum Numm vun der Ressource déi mir zougoen, dat heescht, et mécht kee Sënn fir Zougang zu DNS iwwer UDP ze kréien. Ausserdeem, d'Benotzung erlaabt Iech géint Cache Vergëftung Attacken an dësem Szenario ze schützen.
Momentan verfügbar , ënnert hinnen:
CloudFlare (Check My Browser → Encrypted SNI → Learn More) datt hir Server scho ESNI ënnerstëtzen, dat heescht, fir CloudFlare Serveren an der DNS hu mir op d'mannst zwee records - A an TXT. Am Beispill hei drënner froe mir Google DNS (iwwer HTTPS):
А Entrée:
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 Rekord, Ufro gëtt no enger Schabloun generéiert _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."
}
Also, aus enger DNS Perspektiv, sollte mir DoH benotzen (virun allem mat DNSSEC) an zwee Entréen derbäi.
Client Ënnerstëtzung
Wa mir iwwer Browser schwätzen, dann am Moment . Hei sinn Instruktioune wéi Dir ESNI an DoH Support am FireFox aktivéiert. Nodeems de Browser konfiguréiert ass, sollte mir eppes wéi dat gesinn:

de Browser ze kontrolléieren.
Natierlech muss TLS 1.3 benotzt ginn fir ESNI z'ënnerstëtzen, well ESNI eng Extensioun op TLS 1.3 ass.
Fir den Zweck de Backend mat ESNI Support ze testen, hu mir de Client implementéiert op go, Awer méi iwwer dat spéider.
Server Säit Ënnerstëtzung
De Moment gëtt ESNI net vu Webserver wéi nginx/apache, etc. ënnerstëtzt, well se mat TLS iwwer OpenSSL/BoringSSL schaffen, déi net offiziell ESNI ënnerstëtzen.
Dofir hu mir décidéiert eisen eegene Front-End Komponent (ESNI Reverse Proxy) ze kreéieren, deen TLS 1.3 Terminatioun mat ESNI a Proxy HTTP(S) Traffic op den Upstream ënnerstëtzt, deen net ESNI ënnerstëtzt. Dëst erlaabt d'Technologie an enger scho bestehender Infrastruktur ze benotzen, ouni d'Haaptkomponenten z'änneren - dat ass, aktuell Webserver ze benotzen déi ESNI net ënnerstëtzen.
Fir Kloerheet, hei ass en Diagramm:

Ech bemierken datt de Proxy mat der Fäegkeet entworf gouf eng TLS Verbindung ouni ESNI z'ënnerbriechen, fir Clienten ouni ESNI z'ënnerstëtzen. Och de Kommunikatiounsprotokoll mat Upstream kann entweder HTTP oder HTTPS mat enger TLS Versioun manner wéi 1.3 sinn (wann Upstream net 1.3 ënnerstëtzt). Dëse Schema gëtt maximal Flexibilitéit.
Ëmsetzung vun ESNI Ënnerstëtzung op go mir geléint vun . Ech wëll direkt bemierken datt d'Ëmsetzung selwer zimlech net trivial ass, well et Ännerungen an der Standardbibliothéik implizéiert Krypto/tls an dofir erfuerdert "Patchen" GOROOT virun der Assemblée.
Fir ESNI Schlësselen ze generéieren hu mir benotzt (och de Brainchild vu CloudFlare). Dës Schlëssele gi fir SNI Verschlësselung / Entschlësselung benotzt.
Mir hunn de Build mat go 1.13 getest Linux (Debian, Alpine) a MacOS.
E puer Wierder iwwer operationell Funktiounen
ESNI Reverse Proxy liwwert Metriken am Prometheus Format, sou wéi rps, Upstream Latenz & Äntwert Coden, gescheitert / erfollegräich TLS Handshake & TLS Handshake Dauer. Op den éischte Bléck schéngt dëst genuch ze evaluéieren wéi de Proxy de Traffic handhabt.
Mir hunn och Lasttest virum Gebrauch gemaach. Resultater ënnert:
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
Mir hunn reng qualitativ Belaaschtungstest gemaach fir de Schema mat ESNI Reverse Proxy ze vergläichen an ouni. Mir hunn den Traffic lokal "gegoss" fir "Interferenz" an Zwëschenkomponenten ze eliminéieren.
Also, mat ESNI Ënnerstëtzung a Proxying op Upstream vum HTTP, hu mir ongeféier ~550 rps vun enger Instanz kritt, mam duerchschnëttleche CPU / RAM Konsum vum ESNI Reverse Proxy:
- 80% CPU-Auslastung (4 vCPU, 4 GB RAM-Hosten, Linux)
- 130 MB Mem RSS

Zum Verglach, RPS fir deeselwechten Nginx Upstream ouni TLS (HTTP Protokoll) Terminatioun ass ~ 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
D'Präsenz vun Timeouts weist drop hin, datt et e Manktem u Ressourcen gëtt (mir hunn 4 vCPU, 4 GB RAM Hosts benotzt, Linux), an tatsächlech ass de potenziellen RPS méi héich (mir hunn Zuelen vu bis zu 2700 RPS op méi staark Ressourcen kritt).
Zum Schluss notéieren ech datt d'ESNI Technologie ganz villverspriechend ausgesäit. Et ginn nach vill oppe Froen, zum Beispill, d'Froen vum ëffentlechen ESNI Schlëssel am DNS ze späicheren an ESNI Schlësselen rotéieren - dës Themen ginn aktiv diskutéiert, an déi lescht Versioun vum ESNI Entworf (zu Schreiwen) ass scho .
Source: will.com
