سلام هبر، اسم من ایلیا است، من در تیم پلتفرم در Exness کار می کنم. ما اجزای زیرساخت اصلی را که تیمهای توسعه محصول ما استفاده میکنند، توسعه و پیادهسازی میکنیم.
در این مقاله، من می خواهم تجربه خود را از پیاده سازی فناوری SNI رمزگذاری شده (ESNI) در زیرساخت وب سایت های عمومی به اشتراک بگذارم.

استفاده از این فناوری باعث افزایش سطح امنیت در هنگام کار با یک وب سایت عمومی و مطابقت با استانداردهای امنیتی داخلی اتخاذ شده توسط شرکت می شود.
اول از همه، من می خواهم به این نکته اشاره کنم که این فناوری استاندارد نشده است و هنوز در پیش نویس است، اما CloudFlare و Mozilla در حال حاضر از آن پشتیبانی می کنند (در ). این ما را برای چنین آزمایشی انگیزه داد.
کمی تئوری
ESNI یک برنامه افزودنی برای پروتکل TLS 1.3 است که امکان رمزگذاری SNI را در پیام "Client Hello" در دست دادن TLS فراهم می کند. در اینجا Client Hello با پشتیبانی ESNI به نظر می رسد (به جای SNI معمول، ما ESNI را می بینیم):

برای استفاده از ESNI به سه جزء نیاز دارید:
- DNS;
- پشتیبانی مشتری؛
- پشتیبانی از سمت سرور
DNS
شما باید دو رکورد DNS اضافه کنید – Aو TXT (رکورد TXT حاوی کلید عمومی است که کلاینت می تواند SNI را رمزگذاری کند) - به زیر مراجعه کنید. علاوه بر این، باید حمایت وجود داشته باشد دوه (DNS از طریق HTTPS) زیرا مشتریان موجود (به زیر مراجعه کنید) پشتیبانی ESNI را بدون DoH فعال نمی کنند. این منطقی است، زیرا ESNI به معنای رمزگذاری نام منبعی است که به آن دسترسی داریم، یعنی دسترسی به DNS از طریق UDP معنی ندارد. علاوه بر این، استفاده از در این سناریو به شما امکان می دهد در برابر حملات مسمومیت حافظه پنهان محافظت کنید.
در حال حاضر در دسترس است ، از جمله:
CloudFlare را (مرورگر من → رمزگذاری شده SNI → بیشتر بدانید) که سرورهای آنها از قبل از ESNI پشتیبانی می کنند، یعنی برای سرورهای CloudFlare در DNS حداقل دو رکورد داریم - A و TXT. در مثال زیر ما از Google DNS (از طریق HTTPS) پرس و جو می کنیم:
А ورودی:
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 رکورد، درخواست مطابق با یک الگو ایجاد می شود _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."
}
بنابراین، از دیدگاه DNS، ما باید از DoH (ترجیحاً با DNSSEC) استفاده کنیم و دو ورودی اضافه کنیم.
پشتیبانی مشتری
اگر در مورد مرورگرها صحبت می کنیم، در حال حاضر . در اینجا دستورالعمل هایی در مورد نحوه فعال کردن پشتیبانی ESNI و DoH در فایرفاکس وجود دارد. پس از پیکربندی مرورگر، باید چیزی شبیه به زیر را مشاهده کنیم:

برای بررسی مرورگر
البته، TLS 1.3 باید برای پشتیبانی از ESNI استفاده شود، زیرا ESNI پسوند TLS 1.3 است.
به منظور آزمایش باطن با پشتیبانی ESNI، ما کلاینت را روی آن پیاده سازی کردیم go، اما در ادامه بیشتر در مورد آن.
پشتیبانی از سمت سرور
در حال حاضر، ESNI توسط وب سرورهایی مانند nginx/apache و غیره پشتیبانی نمی شود، زیرا آنها با TLS از طریق OpenSSL/BoringSSL کار می کنند، که به طور رسمی ESNI را پشتیبانی نمی کنند.
بنابراین، ما تصمیم گرفتیم جزء جلویی خودمان (پراکسی معکوس ESNI) را ایجاد کنیم، که از خاتمه TLS 1.3 با ESNI و ترافیک پراکسی HTTP(S) به بالادست پشتیبانی می کند، که از ESNI پشتیبانی نمی کند. این اجازه می دهد تا این فناوری در زیرساخت های موجود استفاده شود، بدون تغییر اجزای اصلی - یعنی استفاده از وب سرورهای فعلی که از ESNI پشتیبانی نمی کنند.
برای وضوح، در اینجا یک نمودار است:

توجه داشته باشم که پروکسی با قابلیت خاتمه دادن به اتصال TLS بدون ESNI، برای پشتیبانی از مشتریان بدون ESNI طراحی شده است. همچنین، پروتکل ارتباطی با upstream می تواند HTTP یا HTTPS با نسخه TLS کمتر از 1.3 باشد (اگر upstream از 1.3 پشتیبانی نمی کند). این طرح حداکثر انعطاف پذیری را می دهد.
اجرای پشتیبانی ESNI در go وام گرفتیم . مایلم فوراً متذکر شوم که پیاده سازی به خودی خود کاملاً بی اهمیت است، زیرا شامل تغییراتی در کتابخانه استاندارد می شود. crypto/tls و بنابراین نیاز به "پچ کردن" دارد گوروت قبل از مونتاژ
برای تولید کلیدهای ESNI استفاده کردیم (همچنین زاییده فکر CloudFlare). این کلیدها برای رمزگذاری/رمزگشایی SNI استفاده می شوند.
ما این نسخه را با استفاده از go 1.13 آزمایش کردیم. Linux (Debian، آلپاین) و مک او اس.
چند کلمه در مورد ویژگی های عملیاتی
پراکسی معکوس ESNI معیارهایی را در قالب Prometheus ارائه میکند، مانند rps، کدهای تاخیر و پاسخ بالادست، دست دادنهای ناموفق/موفق TLS و مدت زمان دست دادن TLS. در نگاه اول، این برای ارزیابی نحوه مدیریت پراکسی ترافیک کافی به نظر می رسید.
ما همچنین آزمایش بار را قبل از استفاده انجام دادیم. نتایج زیر:
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
ما آزمایش بار صرفاً کیفی را برای مقایسه طرح با استفاده از پروکسی معکوس ESNI و بدون آن انجام دادیم. ما ترافیک را به صورت محلی "ریختیم" تا "تداخل" در اجزای میانی را از بین ببریم.
بنابراین، با پشتیبانی ESNI و پروکسی به بالادست از HTTP، حدود ~550 rps را از یک نمونه دریافت کردیم، با میانگین مصرف CPU/RAM پروکسی معکوس ESNI:
- ۸۰٪ استفاده از پردازنده (۴ پردازنده مجازی، ۴ گیگابایت رم هاست، Linux)
- 130 مگابایت Mem RSS

برای مقایسه، RPS برای همان nginx upstream بدون پایان TLS (پروتکل HTTP) ~ 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
وجود وقفهها نشان میدهد که کمبود منابع وجود دارد (ما از ۴ vCPU و ۴ گیگابایت رم استفاده کردیم، Linux) و در واقع RPS بالقوه بالاتر است (ما ارقامی تا ۲۷۰۰ RPS برای منابع قدرتمندتر دریافت کردیم).
در خاتمه متذکر می شوم که فناوری ESNI کاملا امیدوارکننده به نظر می رسد. هنوز سوالات باز زیادی وجود دارد، به عنوان مثال، مسائل مربوط به ذخیره کلید عمومی ESNI در DNS و چرخش کلیدهای ESNI - این موضوعات به طور فعال مورد بحث قرار می گیرند و آخرین نسخه پیش نویس ESNI (در زمان نگارش) قبلاً ارائه شده است. .
منبع: www.habr.com
