bg-tutorials

كيفية تكوين شهادة SSL في HAProxy

HAProxy هو موازن تحميل من نوع TCP وHTTP يقوم بإنهاء TLS، أي أنه يفك تشفير حركة المرور عند الطرف الخارجي ويمرر HTTP عادي إلى خوادمك الخلفية. هذا ما يجعله الجهاز الوحيد في المسار الذي يحتاج إلى الشهادة، وهو يريد تلك الشهادة بشكل محدد: ملف واحد يضم الشهادة، وأي شهادات وسيطة، والمفتاح الخاص.

يغطي هذا الدليل المسار بأكمله: إنشاء CSR، وتجميع ملف PEM، وكتابة الواجهة الأمامية والخلفية، والتحقق من الإعدادات، وإعادة التحميل دون قطع الاتصالات الحية. تم تنفيذ الأوامر على HAProxy 3.4، وهو الفرع الحالي المدعوم لفترة طويلة، والذي صدر في يونيو 2026 ويستمر دعمه حتى الربع الثاني من عام 2031.

ما الذي يتوقعه HAProxy: ملف PEM واحد

تأخذ معظم الخوادم الشهادة والسلسلة والمفتاح كثلاثة إعدادات منفصلة. أما HAProxy فيأخذها كملف واحد. يصف دليل إعداداته الكلمة المفتاحية crt بأنها تحدد “ملف PEM يحتوي على الشهادات المطلوبة وأي مفاتيح خاصة مرتبطة بها”، ويتم بناؤه عن طريق دمج ملفات PEM، ويضيف أنه “إذا كانت جهة الإصدار (CA) الخاصة بك تتطلب شهادة وسيطة، يمكن أيضًا دمجها في هذا الملف”.

هناك سلوكان يستحقان المعرفة قبل البدء، لأنهما يوفران عليك الجهد لاحقًا:

  • يمكن أن يكون المفتاح موجودًا بجانب الشهادة بدلاً من داخلها. إذا لم يحتوِ الملف على مفتاح خاص بداخله، يبحث HAProxy عن نفس المسار مع إضافة .key. لذلك فإن mydomain.pem بالإضافة إلى mydomain.pem.key يعمل تمامًا كملف واحد مدمج.
  • يمكنك توجيه crt إلى مجلد. يقوم HAProxy بتحميل كل ملف يجده هناك ويختار الشهادة الصحيحة لكل طلب باستخدام SNI. بهذه الطريقة يمكنك خدمة عدة مواقع من واجهة أمامية واحدة دون الحاجة إلى سطر bind منفصل لكل موقع.

إنشاء CSR والمفتاح الخاص

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

openssl req -new -newkey rsa:2048 -nodes 
  -keyout mydomain.key -out mydomain.csr 
  -subj "/C=US/ST=California/L=San Jose/O=Your Company/CN=mydomain.com" 
  -addext "subjectAltName=DNS:mydomain.com,DNS:www.mydomain.com"

سطر -addext ليس اختياريًا عمليًا. توقفت المتصفحات منذ سنوات عن مطابقة أسماء المضيفين مع الاسم الشائع (Common Name)، وأصبحت تقرأ فقط اسم الموضوع البديل (Subject Alternative Name)، لذا فإن CSR الذي يحتوي فقط على CN ينتج عنه شهادة تفشل في كل متصفح حديث. أدرج كل اسم يجب أن تغطيه الشهادة، بما في ذلك النطاق المجرد وصيغة www إذا كنت تخدم كليهما.

احذف خياري -subj و-addext إذا كنت تفضل أن يُطلب منك إدخال كل حقل. في كلتا الحالتين، ستحصل على ملفين: mydomain.csr لتقديمه، وmydomain.key للاحتفاظ به. تأكد من أن CSR يحتوي على ما تتوقعه قبل تقديمه، إما باستخدام أداة فك تشفير CSR الخاصة بنا أو محليًا:

openssl req -noout -text -verify -in mydomain.csr

تحقق من إدراج مدخلات SAN ومن أن التوقيع يتم التحقق منه بنجاح. إذا كنت تفضل عدم استخدام سطر الأوامر على الإطلاق، فإن مولد CSR الخاص بنا ينتج نفس الزوج داخل المتصفح. يمكنك الاطلاع على المزيد من المعلومات الأساسية حول الأوامر الأساسية في دليلنا حول أوامر OpenSSL.

إصدار الشهادة

قدّم CSR إلى جهة الإصدار (CA)، واختر نوع الشهادة الذي يتناسب مع ما تحميه، وأكمل عملية التحقق. تغطي الشهادة أحادية النطاق اسم مضيف واحد، وتغطي شهادة wildcard كل نطاق فرعي من المستوى الأول، وتغطي شهادة متعددة النطاقات (SAN) قائمة من الأسماء غير المرتبطة ببعضها. خلف موازن التحميل، يُعد اختيار الشهادة متعددة النطاقات الخيار الشائع، حيث يخدم مثيل HAProxy واحد عادةً عدة مواقع.

تعيد جهة الإصدار أرشيفًا يحتوي على شهادتك والسلسلة الوسيطة، عادةً في شكل ملف حزمة CA. كلاهما بالفعل بصيغة PEM، وهو ما تحتاجه. خطط للتجديد الآن بدلاً من لاحقًا: اعتبارًا من 15 مارس 2026، لا يمكن أن تكون شهادة TLS الموثوقة علنًا صالحة لأكثر من 200 يومًا، لتنخفض إلى 100 يوم في مارس 2027 و47 يومًا في مارس 2029، لذا فإن الاستبدال اليدوي سيتوقف عن كونه عمليًا قريبًا جدًا.

إنشاء ملف PEM الذي سيقرأه HAProxy

أنشئ مجلدًا للشهادات وقم بتجميع الملف هناك. احتفظ بكل شيء في مكان واحد منذ البداية؛ فتقسيم هذا بين المجلد الشخصي و/etc/haproxy و/etc/ssl هو ما يجعل الناس ينتهون بتعديل ملف واحد بينما يقرأ HAProxy ملفًا آخر.

sudo mkdir -p /etc/haproxy/certs
sudo chmod 700 /etc/haproxy/certs

ادمج الشهادة، ثم الشهادات الوسيطة، ثم المفتاح الخاص. يجب أن يعمل إعادة التوجيه كمستخدم جذر (root)، لذا قم بالتمرير عبر tee بدلاً من كتابة sudo cat ... > /etc/haproxy/certs/...، والتي تفشل مع خطأ في الأذونات لأن الصدفة (shell) تفتح ملف الإخراج كمستخدمك الخاص قبل تشغيل sudo أصلاً:

cat mydomain.crt intermediate.crt mydomain.key 
  | sudo tee /etc/haproxy/certs/mydomain.pem > /dev/null

يحتوي ذلك الملف الآن على مفتاحك الخاص بنص عادي، لذا قم بتقييد الوصول إليه قبل المضي قدمًا:

sudo chown root:root /etc/haproxy/certs/mydomain.pem
sudo chmod 600 /etc/haproxy/certs/mydomain.pem

الأذونات المقتصرة على المستخدم الجذر (root) صحيحة هنا، وليست عائقًا. يُشغّل HAProxy بامتيازات المستخدم الجذر، وهو ما يشير دليله إلى أنه مطلوب حتى يتمكن لاحقًا من التبديل إلى مستخدمه الخاص غير المميز، ويقرأ الشهادة أثناء تلك المرحلة من بدء التشغيل. لا حاجة لتوسيع الأذونات حتى يتمكن مستخدم haproxy من قراءة المفتاح، ولا ينبغي لك ذلك.

إذا أنشأت CSR على جهاز مختلف، قم بنسخ الملفات أولاً واحذف النسخ من مجلد النقل بعد ذلك:

scp mydomain.crt intermediate.crt mydomain.key sysadmin@haproxy-server:/home/sysadmin/

إعداد HAProxy

افتح /etc/haproxy/haproxy.cfg في محرر نصوص طرفي على الخادم نفسه، مثل nano أو vim. عدّله في مكانه بدلاً من محطة عمل، حتى لا تعيد تحميل ملف يختلف عن الملف الذي اختبرته.

الواجهة الأمامية (frontend)

يمكن لواجهة أمامية واحدة أن تقبل كلاً من HTTP العادي وHTTPS. اربط المنفذ 80 لإعادة التوجيه، واربط المنفذ 443 بالشهادة، وأرسل كل شيء آخر إلى الواجهة الخلفية:

frontend web_frontend
    mode http
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/mydomain.pem alpn h2,http/1.1

    http-request redirect scheme https code 301 unless { ssl_fc }

    default_backend web_servers

يقدم alpn h2,http/1.1 بروتوكول HTTP/2 ويعود إلى HTTP/1.1 عند الحاجة. يتم تفعيل إعادة التوجيه فقط عندما لا يصل الطلب عبر TLS، وهذا ما يختبره ssl_fc، لذا فإن الطلبات على المنفذ 443 تمر مباشرة.

ضع كل خيارات TLS في سطر bind الواحد ذاك

هذه هي النقطة التي غالبًا ما تسوء فيها إعدادات HAProxy، وتفشل بهدوء. غالبًا ما تقدم الأدلة تقوية TLS كخطوة ثانية، وتُظهر سطر bind جديد للمنفذ 443 مع خيارات إضافية عليه. إذا أضفت ذلك السطر بدلاً من تعديل السطر الحالي، ستنتهي بسطري bind لنفس المنفذ، ولن يشتكي HAProxy. سيبدأ التشغيل، وسيفتح مقبسين استماع منفصلين على المنفذ 443 بإعدادات TLS مختلفة. أي مقبس سيستقبل اتصالاً معينًا ليس أمرًا تتحكم فيه، لذا فإن تقويتك الأمنية تغطي تقريبًا نصف حركة المرور لديك فقط.

لا يكتشف فحص الإعدادات هذا الأمر أيضًا، ويوضح توثيقه الخاص السبب: يقوم -c “بإجراء فحص لملفات الإعدادات فقط ويخرج قبل محاولة الربط (bind)“. المستمع المكرر (duplicate listener) هو حالة تحدث وقت الربط، لذا فإن فحص الصياغة لن يكتشفه أبدًا.

عيّن الإعدادات الافتراضية العامة بدلاً من ذلك، بحيث يرث كل سطر bind في الملف تلك الإعدادات ولا يكون هناك ما يُكرَّر:

global
    ssl-default-bind-options ssl-min-ver TLSv1.2 prefer-client-ciphers
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256

يستحق أن تعرفه قبل نسخ ذلك المقطع في أي مكان: يكون ssl-min-ver بالفعل مضبوطًا افتراضيًا على TLSv1.2، بحسب كلام HAProxy نفسه. ضبطه على TLSv1.2 لا يغير شيئًا ويوثق النية فقط، وهذا أمر جيد، لكنه ليس التحسين الأمني الذي يُقدَّم غالبًا على أنه كذلك. إعدادا التشفير الاثنان يقومان بعمل حقيقي، وهما منفصلان عن قصد: ينطبق ssl-default-bind-ciphers على TLS 1.2 وما دونها، بينما ينطبق ssl-default-bind-ciphersuites على TLS 1.3. إذا ضبطت الأول فقط، ستبقى مجموعات TLS 1.3 على إعداداتها الافتراضية.

الواجهة الخلفية (backend)

أعطِ كل خادم عنوانًا حقيقيًا. هذا أمر أكثر أهمية مما يبدو عليه:

backend web_servers
    mode http
    balance roundrobin
    option httpchk GET /
    server web1 10.0.0.11:80 check
    server web2 10.0.0.12:80 check

سطر خادم مكتوب على الشكل server web1 :80 check، مع حذف العنوان، لا يثير أي خطأ. يقبله HAProxy ويحلل العنوان المفقود إلى 0.0.0.0، والذي يعامله دليله كقيمة خاصة تعني أن الاتصال يُعاد توجيهه إلى نفس عنوان IP الذي اتصل به العميل. ذلك العنوان هو HAProxy نفسه، لذا فإن الواجهة الخلفية تشير بهدوء إلى المنفذ 80 الخاص بـ HAProxy ذاته، وهو الواجهة الأمامية التي قمت للتو بإعدادها. تدور حركة المرور مرة أخرى إلى إعادة التوجيه بدلاً من الوصول إلى أي تطبيق، وتبدو فحوصات الصحة سليمة لأن شيئًا ما يستمع فعلًا. إذا كان موازن التحميل يجيب على كل طلب HTTPS بإعادة توجيه إلى نفسه، تحقق من أسطر الخادم أولاً.

نظرًا لأن HAProxy ينهي TLS، تستقبل الواجهات الخلفية HTTP عادي على المنفذ 80 ولا تحتاج إلى شهادة خاصة بها. إذا كانت السياسة تتطلب التشفير على تلك المرحلة أيضًا، أضف ssl verify required وملف CA إلى أسطر الخادم ووجّهها إلى المنفذ 443 بدلاً من ذلك.

مرّر المخطط (scheme) الأصلي إلى الواجهة الخلفية. نظرًا لأن الواجهة الخلفية تستقبل الآن HTTP عادي، فإن التطبيق الذي يولّد عناوين URL مطلقة، كما تفعل WordPress وDjango وRails جميعها، سيولّدها بـ http://، مما يظهر كمحتوى مختلط أو كحلقة إعادة توجيه يخلقها التطبيق نفسه. أضف سطرًا واحدًا إلى الواجهة الأمامية:

http-request set-header X-Forwarded-Proto https if { ssl_fc }

وسطرًا واحدًا إلى الواجهة الخلفية، الذي يمرر أيضًا عنوان IP الحقيقي للعميل:

option forwardfor

تحتاج معظم أطر العمل بعد ذلك إلى إبلاغها بالوثوق بتلك الترويسات (headers)؛ يتم إعداد هذا الجزء في التطبيق نفسه، وليس في HAProxy.

تحقق من الإعدادات قبل تطبيقها

لا تعد تشغيل موازن التحميل مطلقًا على ملف لم يتم التحقق منه. تحقق أولاً:

sudo haproxy -c -V -f /etc/haproxy/haproxy.cfg

باستخدام -V، يطبع Configuration file is valid عند النجاح ويعيد رمز خروج صفر. بدونه، يكون النجاح صامتًا. يتم الإبلاغ عن أي تحذيرات سواء كان الملف صالحًا أم لا، لذا اقرأ المخرجات بدلاً من الثقة في غياب النص الأحمر.

أعد التحميل بدلاً من إعادة التشغيل

sudo systemctl reload haproxy

الفرق حقيقي على موازن تحميل. تبدأ إعادة التحميل عملية جديدة وتُرسل إشارة إلى العملية القديمة “لإنهاء ما تقوم به ثم المغادرة”، لذا فإن الطلبات الجارية بالفعل تكتمل بشكل طبيعي. أما إعادة التشغيل فترسل إشارة إلى العملية القديمة “للإنهاء الفوري دون إتمام ما كانت تفعله”، مما يقطع الاتصالات الحية، بما في ذلك عمليات الرفع (uploads) واستدعاءات API طويلة الأمد. استخدم إعادة التشغيل فقط عندما لا تستطيع إعادة التحميل استيعاب التغيير، مثل بعد تعديل إعدادات العمليات في القسم العام (global).

تأكد من أن الخدمة عادت وتستمع على كلا المنفذين:

sudo systemctl status haproxy
sudo ss -tlnp | grep haproxy

مقبس استماع واحد بالضبط لكل منفذ هو ما تريده هنا. وجود اثنين على المنفذ 443 يعني أن لديك سطر bind المكرر الموصوف أعلاه.

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

تحقق مما يقدمه HAProxy فعليًا، بما في ذلك السلسلة، من الخادم نفسه:

openssl s_client -connect mydomain.com:443 -servername mydomain.com < /dev/null

اقرأ قسم Certificate chain في أعلى المخرجات. يجب أن تظهر شهادتك عند العمق 0 والشهادة الوسيطة عند العمق 1. إذا كان العمق 1 مفقودًا، فإن الشهادة الوسيطة لم تصل إلى ملف PEM أبدًا، وسيعمل الموقع في بعض المتصفحات بينما يفشل في أخرى. تجاهل سطر Verify return code عند الحكم على هذا: فهو يبلّغ فقط عن حكم السلسلة، ويمكن أن يظهر كناجح في حالات لا علاقة لها بما تختبره.

ثم تأكد من الخارج، حيث تعكس النتيجة ما يحصل عليه الزوار الحقيقيون. تقوم أداة SSL Checker الخاصة بنا بالإبلاغ عن الشهادة والسلسلة وتاريخ انتهاء الصلاحية.

التجديدات والأتمتة

استبدال ملف PEM هو إجراء التجديد بأكمله: أعد بناءه من الشهادة الجديدة ونفس المفتاح أو مفتاح جديد، ثم أعد التحميل. لا شيء في إعدادات HAProxy يشير إلى تاريخ انتهاء الصلاحية، لذا لا حاجة إلى أي تعديل في الإعدادات طالما بقي مسار الملف كما هو.

مع تقلص فترات صلاحية الشهادات، يستحق إعداد الأتمتة الاهتمام الآن. اكتسب HAProxy عميل ACME مدمجًا في الإصدار 3.2، يُهيَّأ من خلال قسم acme. تعامل معه حاليًا كمعاينة أكثر منه كبنية تحتية للإنتاج: فهو ما زال يُصنَّف تجريبيًا في 3.4 ويتطلب expose-experimental-directives في القسم العام، ويدعم فقط أنواع التحديات http-01 وdns-01 وdns-persist-01، ويجب تفريغ الشهادات التي يولّدها من مقبس الإحصائيات (stats socket) للوصول إلى القرص. يستخدم نوع dns-persist-01، المضاف في 3.4، سجل TXT ثابتًا يُضبط مرة واحدة ولا يتغير بين التجديدات، لذا فهو لا يتطلب صلاحية كتابة إلى واجهة برمجة تطبيقات مزود DNS في كل تجديد. البديل الراسخ هو تشغيل عميل ACME خارجي وجعل خطوة النشر (deploy) الخاصة به تعيد بناء ملف PEM وتعيد تحميل HAProxy، وهو نفس النمط الموصوف في دليل ACME الخاص بنا لـ Apache وNGINX.

الأسئلة الشائعة

بأي ترتيب توضع الشهادة والسلسلة والمفتاح في ملف PEM؟

شهادتك أولاً، ثم أي شهادات وسيطة، ثم المفتاح الخاص. يصف دليل HAProxy الملف بأنه يُبنى عن طريق دمج ملفات PEM، ويقول إن الشهادة الوسيطة يمكن دمجها فيه أيضًا. إذا كنت تفضل إبقاء المفتاح منفصلاً، احذفه تمامًا واحفظه بنفس المسار مع إضافة .key، والذي يقوم HAProxy بتحميله تلقائيًا.

لماذا يعيد موقعي HTTPS توجيه نفسه في حلقة مستمرة؟

عادةً بسبب سطر خادم في الواجهة الخلفية بدون عنوان، مثل server web1 :80 check. يحلل HAProxy العنوان الفارغ إلى 0.0.0.0، وذلك العنوان يعني أن الاتصال يُعاد توجيهه إلى نفس عنوان IP الذي اتصل به العميل، وهو HAProxy نفسه. لذلك تشير الواجهة الخلفية إلى المنفذ 80 الخاص بـ HAProxy نفسه، وهو الواجهة الأمامية التي تصدر إعادة التوجيه من HTTP إلى HTTPS. أعطِ كل سطر خادم عنوان IP حقيقي أو اسم مضيف.

هل يمكنني وضع سطري bind للمنفذ 443 في نفس الواجهة الأمامية؟

يمكنك ذلك، وهذه هي المشكلة. لا يقوم HAProxy بدمجهما ولا بالتحذير منهما، ويجتاز haproxy -c الفحص لأنه يخرج قبل محاولة الربط. ستحصل على مقبسي استماع على منفذ واحد بأي خيارات TLS مختلفة يحملها كل سطر، لذا فإن أي إعداد موجود في أحدهما فقط ينطبق على جزء فقط من حركة مرورك. احتفظ بسطر bind واحد لكل منفذ وضع إعدادات TLS المشتركة في ssl-default-bind-options.

هل إضافة ssl-min-ver TLSv1.2 تعزز أي شيء؟

ليس بمفرده. يوثق HAProxy القيمة الافتراضية لـ ssl-min-ver على أنها TLSv1.2 بالفعل، لذا فإن ضبطها على نفس القيمة يسجل نيتك دون تغيير السلوك. التعزيز الحقيقي يأتي من إعدادات التشفير، وتذكر أن TLS 1.3 يحتاج إلى ssl-default-bind-ciphersuites بينما تستخدم TLS 1.2 وما دونها ssl-default-bind-ciphers.

هل تحتاج خوادمي الخلفية إلى شهادات أيضًا؟

ليس في الإعداد القياسي. ينهي HAProxy TLS عند الطرف الخارجي ويمرر HTTP عادي، وهذا سبب امتلاك موازن التحميل فقط للشهادة. أضف ssl verify required مع ملف CA على أسطر الخادم فقط إذا كانت سياستك تتطلب تشفير المرحلة الداخلية أيضًا.

كيف أخدم عدة نطاقات من مثيل HAProxy واحد؟

وجّه crt إلى مجلد بدلاً من ملف. يقوم HAProxy بتحميل كل شهادة فيه ويختار الشهادة الصحيحة لكل طلب باستخدام SNI، لذا يغطي سطر bind واحد كل هذه الشهادات. الشهادة متعددة النطاقات (SAN) هي الطريق الآخر، وتناسب مجموعة من الأسماء التي تُجدَّد معًا.

ما الإصدار من HAProxy الذي يجب أن أستخدمه؟

الفرع 3.4، الذي صدر في يونيو 2026، هو الإصدار الحالي المدعوم لفترة طويلة ويستمر دعمه حتى الربع الثاني من عام 2031. فروع HAProxy ذات الأرقام الزوجية هي فروع LTS، وتحصل على نحو خمس سنوات من الصيانة، بينما تحصل الفروع ذات الأرقام الفردية مثل 3.3 على 12 إلى 18 شهرًا. كل ما في هذا الدليل ينطبق على 3.0 وما بعده؛ فقط عميل ACME المدمج يتطلب 3.2 أو أحدث.

إذا كانت الشهادة مثبتة لكن المتصفحات لا تزال تشتكي، فإن أدلتنا حول أخطاء SSL الشائعة تغطي الأسباب المعتادة، وأكثرها شيوعًا سلسلة غير مكتملة أو اسم لا تدرجه الشهادة.

وفِّر 10% على شهادات SSL عند الطلب اليوم!

إصدار سريع، وتشفير قوي، وثقة في المتصفح بنسبة 99.99%، ودعم مخصص، وضمان استرداد المال خلال 25 يومًا. رمز القسيمة: SAVE10

صورة مفصلة لتنين أثناء طيرانه

كاتب محتوى متمرس متخصص في شهادات SSL. تحويل موضوعات الأمن السيبراني المعقدة إلى محتوى واضح وجذاب. المساهمة في تحسين الأمن الرقمي من خلال السرد المؤثر.

Avatar of Sergiu Rosca
Technical Review by Sergiu Rosca

Sergiu Rosca is the core web developer behind SSL Dragon. He manages the technical infrastructure, platform performance, and backend integrations that keep the site running smoothly and securely. At SSL Dragon, Sergiu shares practical insights on web development, site optimization, and technical troubleshooting.

All SSL Dragon installation guides are tested on live server environments and undergo a strict peer-review process to ensure your infrastructure remains secure. Read our full Editorial Policy.