مرحبًا حبر، اسمي إيليا، وأعمل ضمن فريق المنصة في Exness. نقوم بتطوير وتنفيذ مكونات البنية التحتية الأساسية التي تستخدمها فرق تطوير المنتجات لدينا.
في هذه المقالة، أود أن أشارك تجربتي في تطبيق تقنية SNI المشفرة (ESNI) في البنية التحتية للمواقع العامة.
سيؤدي استخدام هذه التقنية إلى زيادة مستوى الأمان عند العمل مع موقع ويب عام والامتثال لمعايير الأمان الداخلي التي تعتمدها الشركة.
بادئ ذي بدء، أود أن أشير إلى أن التكنولوجيا ليست موحدة ولا تزال في المسودة، ولكن CloudFlare وMozilla يدعمانها بالفعل (في
بعض نظرية
إسني هو امتداد لبروتوكول TLS 1.3 الذي يسمح بتشفير SNI في رسالة مصافحة TLS "Client Hello". إليك ما يبدو عليه Client Hello مع دعم ESNI (بدلاً من SNI المعتاد الذي نراه ESNI):
لاستخدام ESNI، تحتاج إلى ثلاثة مكونات:
- DNS ؛
- دعم العميل؛
- دعم جانب الخادم.
DNS
تحتاج إلى إضافة سجلين DNS – Aو TXT (يحتوي سجل TXT على المفتاح العام الذي يمكن للعميل من خلاله تشفير SNI) - انظر أدناه. وبالإضافة إلى ذلك، يجب أن يكون هناك دعم دوه (DNS عبر HTTPS) لأن العملاء المتاحين (انظر أدناه) لا يقومون بتمكين دعم ESNI بدون DoH. هذا أمر منطقي، نظرا لأن ESNI يعني تشفير اسم المورد الذي نصل إليه، أي أنه لا معنى للوصول إلى DNS عبر UDP. علاوة على ذلك، الاستخدام
متاح حاليا
كلودفلاري
А دخول:
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) وإضافة إدخالين.
دعم العملاء
إذا كنا نتحدث عن المتصفحات، ففي الوقت الحالي
بالطبع، يجب استخدام 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. أيضًا، يمكن أن يكون بروتوكول الاتصال مع المنبع إما HTTP أو HTTPS بإصدار TLS أقل من 1.3 (إذا كان المنبع لا يدعم 1.3). هذا المخطط يعطي أقصى قدر من المرونة.
تنفيذ دعم ESNI على go اقترضنا من
استخدمنا لإنشاء مفاتيح ESNI
لقد اختبرنا البنية باستخدام go 1.13 على Linux (Debian وAlpine) وMacOS.
بضع كلمات حول الميزات التشغيلية
يوفر الوكيل العكسي 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 دورة في الثانية من مثيل واحد، مع متوسط استهلاك وحدة المعالجة المركزية/ذاكرة الوصول العشوائي للوكيل العكسي ESNI:
- استخدام وحدة المعالجة المركزية بنسبة 80% (4 وحدات معالجة مركزية افتراضية، ومضيفات ذاكرة الوصول العشوائي سعة 4 جيجابايت، ونظام التشغيل Linux)
- 130 ميغابايت ميم آر إس إس
للمقارنة، فإن 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
يشير وجود المهلات إلى نقص الموارد (استخدمنا 4 وحدات معالجة مركزية افتراضية، ومضيفات ذاكرة الوصول العشوائي بسعة 4 جيجابايت، ونظام التشغيل Linux)، وفي الواقع فإن عدد RPS المحتمل أعلى (لقد تلقينا أرقامًا تصل إلى 2700 RPS على موارد أكثر قوة).
وفي الختام، أشير أن تقنية ESNI تبدو واعدة جدًا. لا تزال هناك العديد من الأسئلة المفتوحة، على سبيل المثال، مشكلات تخزين مفتاح ESNI العام في DNS وتدوير مفاتيح ESNI - تتم مناقشة هذه المشكلات بشكل نشط، وتم بالفعل إصدار أحدث إصدار من مسودة ESNI (في وقت كتابة هذا التقرير)
المصدر: www.habr.com