تحدد بصمة TLS البرنامج الذي يفتح اتصال HTTPS من خلال النظر في كيفية فتحه له — أي مجموعات التشفير التي يعرضها وبأي ترتيب، وأي امتدادات ومنحنيات إهليلجية يسردها — قبل إرسال أي محتوى للطلب. كل مكتبة TLS وكل إصدار متصفح يقول مرحبًا للخادم بشكل مختلف قليلاً، وهذه التحية مرئية للخادم كنص واضح حتى لو كان كل ما بعدها مشفرًا. تقوم JA3 وخليفتها JA4 بتحويل التحية إلى تجزئة قصيرة. تقارن أنظمة مكافحة الروبوتات هذه التجزئة بما كان يجب أن ينتجه المتصفح المدعى. لهذا السبب يتم اكتشاف نص Python الذي يعلن نفسه كـ Chrome، ويتصل عبر عنوان IP سكني لا تشوبه شائبة، لا يزال يتم اكتشافه: قال عنوان IP “مستخدم منزلي في برلين”؛ قالت مصافحة TLS “OpenSSL في نص برمجي.”
من أين تأتي البصمة: ClientHello
يبدأ اتصال HTTPS بمصافحة TLS. الرسالة الأولى جدًا، التي يرسلها العميل، هي ClientHello. وهي غير مشفرة — يجب أن تكون كذلك، لأن التشفير لم يتم التفاوض عليه بعد — وتحتوي، من بين أشياء أخرى، على:
- إصدار TLS الذي يدعمه العميل؛
- قائمة مجموعات التشفير التي يرغب في استخدامها، بترتيب تفضيله؛
- قائمة الامتدادات — SNI (اسم المضيف)، ALPN (بروتوكولات التطبيق، مثل
h2،http/1.1)، المجموعات المدعومة (المنحنيات الإهليلجية)، خوارزميات التوقيع، مفتاح المشاركة، تذكرة الجلسة، وما إلى ذلك — مرة أخرى بترتيب محدد؛ - المنحنيات الإهليلجية وتنسيقات النقاط التي يدعمها.
لا شيء من هذه القيم سري ولا يتم اختياره حسب الموقع؛ فهي مدمجة في مكتبة TLS والتطبيق الذي يستخدمها. يرسل Chrome 128 ClientHello معينًا؛ يرسل Firefox آخر؛ ترسل وحدة ssl في Python (OpenSSL) ثالثًا؛ وترسل crypto/tls في Go رابعًا؛ ويرسل curl خامسًا. يرى الخادم ClientHello لكل اتصال على أي حال — يجب عليه ذلك، للرد عليه. تسجيله وتجزئته لا يكلف شيئًا.
JA3 و JA4: تحويل المصافحة إلى توقيع
JA3
قدم باحثو Salesforce JA3 في عام 2017، وهو يدمج خمسة حقول من ClientHello — إصدار TLS، مجموعات التشفير، الامتدادات، المنحنيات الإهليلجية، تنسيقات نقاط المنحنى الإهليلجي — كقوائم عشرية مفصولة بفواصل، ثم يقوم بتجزئة MD5 للسلسلة. النتيجة هي بصمة مكونة من 32 حرفًا مثل cd08e31494f9531f560d64c695473da9. يمكن لأي شخص حسابه من التقاط الحزم، والقوائم التي تربط تجزئات JA3 بالعملاء المعروفين (“هذه التجزئة = Chrome 120 على Windows،” “هذه التجزئة = python-requests”) تتم مشاركتها على نطاق واسع.
لدى JA3 ضعف أصبح ميزة للمراوغة: لأنه يقوم بتجزئة قائمة الامتدادات بالترتيب، وبما أن Chrome (منذ الإصدار 110) يعشوائي ترتيب الامتدادات في كل اتصال، فإن تثبيت Chrome واحد ينتج العديد من تجزئات JA3 المختلفة. تم ذلك عمدًا لتثبيط الخوادم عن التحجر على بصمة واحدة — مما جعل JA3 أقل فائدة بكثير لتحديد المتصفحات.
JA4
تم إصدار JA4 بواسطة FoxIO في عام 2023، وقد تم تصميمه ليتحمل ذلك. فهو يفرز قوائم التشفير والامتدادات قبل التجزئة (لذلك لم يعد خلط Chrome مهمًا)، ويبقي بعض الحقول قابلة للقراءة البشرية، ويضيف المزيد من الإشارات: ما إذا كان الاتصال عبر TCP أو QUIC، ونوع SNI، وقيمة ALPN، وإصدار TLS، وعدد التشفيرات والامتدادات. تبدو بصمة JA4 مثل t13d1516h2_8daaf6152771_e5627efa2ab1: الكتلة الأولى تقول “TLS 1.3 عبر TCP، 15 تشفيرًا، 16 امتدادًا، ALPN h2،” والاثنتان الأخريان هما تجزئات مبتورة لقائمة التشفير المفرزة وقائمة الامتدادات المفرزة بالإضافة إلى خوارزميات التوقيع. JA4 هي في الواقع عائلة (JA4 لـ TLS، JA4H لترويسات HTTP، JA4S للجانب الخادم، JA4X للشهادات، وغيرها)؛ عندما يقول بائعو مكافحة الروبوتات “بصمة TLS” اليوم فإنهم عادةً ما يقصدون JA4 أو ما يعادله مملوكًا مبنيًا بنفس الطريقة.
لماذا لا يمكن للوكيل المساعدة
يقوم الوكيل بترحيل مصافحة TLS؛ ولا يعيد كتابتها. مع وكيل HTTP، يرسل العميل CONNECT host:443، ويفتح الوكيل نفق TCP، ويمر ClientHello الخاص بالعميل عبر النفق إلى الوجهة دون تغيير. مع SOCKS5 يحدث نفس الشيء على طبقة أقل. لذلك يرى الخادم الوجهة حقيقتين مستقلتين:
- عنوان IP المصدر — عنوان الوكيل، سكني ولا تشوبه شائبة؛
- ClientHello — الخاص بالعميل، يقول بالضبط أي مكتبة بنته.
يسأل منطق مكافحة الروبوتات بعد ذلك سؤالًا بسيطًا: هل تطابق بصمة TLS وكيل المستخدم؟ يدعي رأس User-Agent أنه “Chrome 128 على Windows.” يقول JA4 “OpenSSL 3.x عبر Python.” لا ينتج Chrome الحقيقي هذا JA4 أبدًا. يتم وضع علامة على الطلب — ليس لأن عنوان IP سيئ، ولكن لأن القصة غير متسقة داخليًا. هذا هو السبب الأكثر شيوعًا وراء استمرار تلقي وكيل سكني “نظيف” لاختبارات CAPTCHA على المواقع المحمية، ولهذا نقول إن الوكيل يجيب عن من أين، وليس من؛ انظر ماذا يفعل الوكيل وما لا يخفيه.
يمكن أن يكون الوكيل مهمًا في جانب واحد: بعض المزودين ينهون TLS بأنفسهم (وكيل “رجل في المنتصف” يقوم بفك التشفير وإعادة التشفير، مما يتطلب منك تثبيت شهادته). في هذه الحالة، يرى الوجهة ClientHello الخاص بالوكيل، وليس ClientHello الخاص بك — وهو عادةً أسوأ، لأنه مكتبة من جانب الخادم، وليس متصفحًا. الوكلاء العاديون لا يفعلون ذلك.
كيف يبدو كل نوع من العملاء
| العميل | ماذا تقول بصمة TLS الخاصة به | متسق مع وكيل مستخدم المتصفح؟ |
|---|---|---|
| Chrome / Firefox / Safari حقيقي | ذلك المتصفح والإصدار، على نظام التشغيل ذلك | نعم — إنه هو المتصفح |
Python requests, httpx, aiohttp | OpenSSL كما تم تكوينه بواسطة وحدة ssl في Python | لا — يمكن التعرف عليه كنص برمجي بغض النظر عن الترويسات |
Node.js fetch / axios | بناء Node's OpenSSL/BoringSSL | لا |
Go net/http | مكدس TLS الخاص بـ Go؛ مميز | لا |
| curl (البناء الافتراضي) | OpenSSL/LibreSSL كما تم بناؤه | لا |
| Headless Chrome عبر Puppeteer/Playwright | Chrome حقيقي — TLS صحيح | نعم لـ TLS؛ قد تتسرب إشارات أخرى (أعلام الأتمتة، المكونات الإضافية المفقودة) |
| عملاء “الانتحال” (curl-impersonate, curl_cffi, tls-client) | ClientHello لمتصفح مختار، معاد إنتاجه بايتًا بايت | نعم، إذا قمت أيضًا بمطابقة الترويسات مع نفس المتصفح |
كيف تحصل على بصمة متسقة
هناك ثلاثة طرق صادقة، بترتيب تصاعدي للتكلفة.
- استخدم متصفحًا حقيقيًا. قم بأتمتة Chrome أو Firefox باستخدام Playwright أو Puppeteer؛ سيكون TLS بعد ذلك حقيقيًا للمتصفح. أبطأ وأثقل من HTTP الخام، لكن بالنسبة للمواقع المحمية فهو خط الأساس. قم بإقران كل سياق متصفح بوكيل خاص به — انظر الوكلاء في Playwright وPuppeteer وSelenium.
- استخدم عميل HTTP منتحلًا. المكتبات مثل curl_cffi (Python، مبنية على curl-impersonate) و tls-client تعيد إنتاج ClientHello وإعدادات HTTP/2 لمتصفحات محددة، لذا تحصل على سرعة الكاشط مع بصمة المتصفح. يجب عليك بعد ذلك الحفاظ على جميع الترويسات الأخرى متسقة مع نفس إصدار المتصفح — User-Agent،
Accept-Language، تلميحات العميلsec-ch-ua— أو تستبدل تناقضًا بآخر. يوضح دليل Python proxy الخاص بنا التبديل منrequestsإلىcurl_cffi. - توقف عن التظاهر. إذا كان الهدف يقدم API رسميًا، فاستخدمه بهويتك الحقيقية للعميل. بصمة TLS هي مشكلة فقط عندما تتعارض البصمة مع الادعاء.
ما الذي لا ينجح: تعيين User-Agent الخاص بـ Chrome على requests. يغير ذلك رأسًا واحدًا ويترك المصافحة دون تغيير — أصبح عدم التطابق الآن أكثر حدة من ذي قبل، لأن وكيل مستخدم python-requests عادي مع بصمة OpenSSL هو على الأقل متسق ذاتيًا.
الصورة الأكبر: البصمات تتراكم
TLS هو طبقة واحدة. يقوم بائعو مكافحة الروبوتات الحديثون أيضًا ببصمة اتصال HTTP/2 (قيم إطار SETTINGS، أحجام النوافذ، ترتيب الترويسات وترتيب الترويسات الزائفة — تسمى أحيانًا بصمة Akamai)، ومكدس TCP/IP (حجم النافذة، TTL، الخيارات؛ p0f الكلاسيكي)، وبالطبع المتصفح نفسه من خلال JavaScript، الذي لا يمكن لعميل HTTP تشغيله على الإطلاق. يجب أن تحكي كل طبقة نفس القصة مثل الطبقات الأخرى ومثل عنوان IP. عنوان IP سكني مع بصمة TLS للمتصفح وإعدادات HTTP/2 للمتصفح ولكن بدون تنفيذ JavaScript لا يزال شذوذًا على موقع يتوقع تشغيل تحدي JS. لهذا السبب فإن الإجابة الصادقة على “أي وكيل يتجنب الكشف؟” هي “لا شيء بمفرده” — ولهذا تراعي تصنيفاتنا ما يقدمه المزود بالإضافة إلى عنوان IP؛ انظر مقارنة الوكلاء النخبة.
كيف ترى بصمتك الخاصة
تعكس عدة صفحات عامة JA3/JA4 التي تحسبها لاتصالك، جنبًا إلى جنب مع المتصفح الذي تعتقد أنه ينتمي إليه. قم بتحميل واحدة من متصفح حقيقي، ثم اجلبها باستخدام نصك عبر نفس الوكيل، وقارن. إذا اختلف الاثنان، فقد وجدت سبب معاملة نصك بشكل مختلف عن متصفحك — ولن يصلح أي تغيير في الوكيل ذلك. أضف هذا إلى الفحوصات في كيفية اختبار الوكيل كلما كان الهدف معروفًا بتشغيل مكافحة روبوتات المؤسسات.
الأسئلة الشائعة
ما هو JA3؟
تجزئة MD5 لخمسة حقول من ClientHello الخاص بـ TLS (الإصدار، التشفيرات، الامتدادات، المنحنيات، تنسيقات النقاط) تستخدم لتحديد برنامج العميل. يعمل جيدًا للنصوص والمكتبات؛ أصبح غير موثوق لـ Chrome بمجرد أن بدأ Chrome في عشوائية ترتيب الامتدادات.
ما هو JA4؟
خليفة JA3: يفرز القوائم قبل التجزئة بحيث لا يغير خلط الامتدادات النتيجة، ويبقي جزءًا من البصمة قابلًا للقراءة، ويتضمن النقل (TCP/QUIC) وALPN والعدادات. وهو أساس معظم اكتشاف بصمة TLS الحالي.
هل يغير الوكيل السكني بصمة TLS الخاصة بي؟
لا. يقوم الوكيل بتمرير مصافحتك دون تغيير؛ يرى الوجهة عنوان IP الخاص بالوكيل وClientHello الخاص بك. فقط برنامج العميل هو الذي يحدد البصمة.
هل يمكنني تزييف بصمة TLS لمتصفح في Python؟
نعم، باستخدام عملاء منتحلين مثل curl_cffi، الذين يعيدون إنتاج ClientHello وسلوك HTTP/2 لمتصفح مختار. يجب عليك الحفاظ على الترويسات متسقة مع نفس المتصفح. لا يمكن لـ requests/httpx العاديين فعل ذلك.
هل بصمة TLS هي نفسها بصمة المتصفح؟
لا. تقرأ بصمة TLS مصافحة الاتصال المشفر وتحدد برنامج العميل؛ تقوم بصمة المتصفح بتشغيل JavaScript وتحدد الجهاز (canvas، الخطوط، GPU). تستخدم أنظمة مكافحة الروبوتات كلاهما، بالإضافة إلى سمعة IP، وتتحقق من تطابقها.
لماذا يتم حظر نفس النص على موقع واحد وليس على آخر؟
لأن فحوصات بصمة TLS هي ميزة لمنتجات مكافحة الروبوتات للمؤسسات، وليست للويب بشكل عام. المواقع التي لا تحتوي على مثل هذه الحماية لا تنظر أبدًا إلى المصافحة؛ المواقع التي تحتوي عليها تقارنها بـ User-Agent في كل طلب.