Let's Encrypt: «تعذّر الحصول على شهادة المُصدر» (خطأ 2)، إعادة الإصدار القسرية وحدود المعدل

قد ترفض عملية تثبيت أو إعادة بناء Discourse شهادة Let’s Encrypt صالحة مع ظهور الخطأ التالي:

C=US, O=Let's Encrypt, CN=YR2
error 2 at 1 depth lookup: unable to get issuer certificate
error fullchain.cer: verification failed

تمكنت من إعادة إنتاج هذا الخطأ مباشرة بعد إصدار شهادة RSA بنجاح. يؤدي الفشل في الفحص إلى طلب غير ضروري باستخدام --force، مما قد يؤدي إلى ظهور أخطاء HTTP 429 / rateLimited / “عدد كبير من الشهادات”. في التثبيت الخاص بي، تم حظر إصدار شهادات ECDSA ولم يبدأ HTTPS.

مع سلاسل الشهادات المتأثرة، يمكن لكل عملية إعادة بناء أو إعادة تشغيل للحاوية أن تُطلق إعادة إصدار قسرية غير ضرورية لشهادات RSA وECDSA، حتى لو كانت لا تزال صالحة. تستهلك عمليات إعادة الإصدار الناجحة حصة Let’s Encrypt، لذا فإن إعادة البناء أو إعادة التشغيل المتكررة يمكن أن تصل بسرعة إلى حد المعدل.

قد يبقى هذا الأمر دون ملاحظة بينما يستمر HTTPS في العمل باستخدام الشهادات المثبتة بالفعل. حذف مثيل وإعادة تثبيته باستخدام اسم المضيف (hostname) نفسه لا يعيد ضبط تلك الحصة. إذا كانت الشهادات المطلوبة مفقودة في التثبيت الجديد، يمكن أن يمنع إصدار الشهادات المقيد بالمعدل بدء تشغيل HTTPS.

الإصلاح

في templates/web.letsencrypt.ssl.template.yml، داخل cert_exists()، استبدل:

- openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer
+ openssl verify -untrusted ca.cer fullchain.cer

اترك بقية الدالة كما هي. يجب تضمين القالب المُصحح في إعادة بناء الحاوية التالية لتحديث /usr/local/bin/letsencrypt.

إذا كنت مقيدًا بالمعدل بالفعل، فإن هذا التصحيح لا يعيد ضبط الحصة. قم بتطبيق الإصلاح والالتزام بوقت retry after قبل محاولة أي إصدار إضافي.

PR: FIX: preserve the Let's Encrypt issuer chain in cert_exists - Pull Request #1136 - discourse/discourse_docker - GitHub

تأكيد مشكلة التحقق من السلسلة

من داخل الحاوية، من دليل الشهادة المتأثر (/shared/letsencrypt/<hostname>، أو <hostname>_ecc)، قارن بين:

openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer
openssl verify -untrusted ca.cer fullchain.cer

في الحالة المعاد إنتاجها، يفشل الأمر الأول مع الخطأ 2؛ بينما يعيد الأمر الثاني:

fullchain.cer: OK

السبب والتحقق

يقوم openssl x509 -in ca.cer بقراءة الشهادة الأولى فقط من حزمة المُصدر. في سلسلة YR2 المرصودة، يُسقط الشهادة Root YR الموقعة بشكل متقاطع (cross-signed) اللازمة للوصول إلى ISRG Root X1.

يقدم -untrusted ca.cer حزمة المُصدر الكاملة مع الحفاظ على نقاط الثقة (trust anchors) في مخزن النظام، مما يحافظ على نية إصلاح عام 2021 (#576).

تحققت من سلاسل RSA وECDSA الفعلية داخل الحاوية. أعادت إعادة البناء الكاملة مع التصحيح استخدام كلا الشهادتين الموجودتين مسبقًا: رسالتا Skip، وتم تثبيت كلا السلسلتين، ونجح اختبار nginx -t.

تقارير ذات صلة

411097
413078

PR: FIX: preserve the Let's Encrypt issuer chain in cert_exists - Pull Request #1136 - discourse/discourse_docker - GitHub

6 إعجابات

يرجى نشر الشهادة الجيدة وسلسلة الشهادات هنا حتى نتمكن من تقييمها.

3 إعجابات

شكرًا لك @supermathie على بحثك في هذه المسألة. لقد أرفقتُ ملفي fullchain.cer و ca.cer من النسخة المتأثرة.
fullchain.cer.txt (5.9 ك.ب)
ca.cer.txt (3.8 ك.ب)

يُظهر مخرَج OpenSSL أدناه أن أمر التحقق الأصلي يفشل بالخطأ رقم 2، بينما ينجح الأمر باستخدام -untrusted مع الشهادة والسلسلة نفسيهما.

openssl version
openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer
openssl verify -show_chain -untrusted ca.cer fullchain.cer

OpenSSL 3.5.7 9 Jun 2026 (Library: OpenSSL 3.5.7 9 Jun 2026)
C=US, O=Let's Encrypt, CN=YR2
error 2 at 1 depth lookup: unable to get issuer certificate
error fullchain.cer: verification failed
fullchain.cer: OK
Chain:
depth=0: CN=hubprod.surikai.fr (untrusted)
depth=1: C=US, O=Let's Encrypt, CN=YR2 (untrusted)
depth=2: C=US, O=ISRG, CN=Root YR (untrusted)
depth=3: C=US, O=Internet Security Research Group, CN=ISRG Root X1

واجهتُ هذه المشكلة في بيئتين منفصلتين. لقد كنتُ أطبّق الحل على نسختي التطويرية منذ أن فتحتُ طلب الدمج (PR)، وقد كان يعمل كما هو متوقع.

إعجابَين (2)

للاستئناس، يقوم عميل ACME بإنشاء الملفات ذات الصلة التالية في ${LETSENCRYPT_DIR}:

  • ${DISCOURSE_HOSTNAME}.cer: يحتوي على الشهادة الصادرة
  • ca.cer: يحتوي على سلسلة الشهادات، واسمه مُربك إلى حد ما
  • fullchain.cer: يجمع بين الملفين المذكورين أعلاه

أصح أمر هو:

openssl verify -untrusted ca.cer ${DISCOURSE_HOSTNAME}.cer

الأمر الحالي فوضوي (وغير صحيح لأنه لا يختبر فعليًا صحة السلسلة حتى الجذر النظامي)، وأي أمر آخر يعتمد على آثار جانبية أو افتراضات. سأقوم بتحديث طلب الإرسال (PR).

إعجابَين (2)

هذا منطقي. التحقق من شهادة الورقة (leaf certificate) مباشرةً أنظف من الاعتماد على قراءة OpenSSL للشهادة الأولى فقط في ملف fullchain.cer.

سأغلق طلب الإرسال #1136 لصالح طلبك.

سعيد باختبار طلب الإرسال الجديد إذا لزم الأمر.

إعجاب واحد (1)

تم الدمج :partying_face:

شكرًا لك @jmx على تحديد المشكلة بوضوح واقتراح الإصلاح - كان اقتراحك جيدًا، لكنني أردت فقط أن أفعل المزيد.

إعجابَين (2)

تم إغلاق هذا الموضوع تلقائيًا بعد 14 ساعة. لم يعد بوسعك الرد.