حل مشاكل الشهادة الموقعة بشكل ذاتي لخدمة NextCloud المحلية

العديد من الأشخاص يستضيفوا خدمة nextcloud في منزلهم بشكل محلي بدون فتحها للإنترنت ويمكنه الوصل لها مباشرة إذا كان الشخص في المنزل أو عن طريق vpn من الخارج. لأنها خدمة محلية فلا يمكن الحصول على شهادة SSL من أحد الخدمات الموفرة لها لأنهم يطلبوا نطاق (domain) لأجل إنشائها، لذلك ذلك يُنشئ المستخدمون شهادة مُوقعة ذاتيًا مِن قبلهم وهذا يسبب مشكلة حيث أن الأجهزة والبرامج لن تتعرف عليها، على الرغم من أن متصفحات الويب وبرنامج nextcloud الرسمي سوف يحذرك ويترك لك اختيار الوثق بها إلا أن العديد من الخدمات الإضافية والبرامج التي تُرتبط بـnexcloud مثل الملاحظات والتقويم والتذكيرات وغيرها لن تسألك وسوف تواجهك مشكلة في الاتصال بالخادم من خلالها خصوصًا لو كنت تعمل على نظام ios أو MacOS، فهذه الأنظمة تتطلب العديد من المتطلبات في الشهادة التي تعزز من أمن الاتصال والتي لا توجد عادة في الشهادات الموقَّعَة بشكل ذاتي.

سوف أشرح في هذا المنشور طريقة إنشاء شهادة موقَّعَة ذاتيًا تتوافق مع متتطلبات أنظمة أبل -والتي سوف تعمل في مختلف الأجهزة إن شاء الله- وسوف أبين طريقة الوثوق بالشهادة في مختلف الأنظمة.

إنشاء شهادة

تهيئة البيئة وتثبيت المتطلبات

  1. في البداية تحتاج إلى بيئة آمنة لبدء العمل عليها، على سبيل المثال استخدم وحدة تخزينيَّة معماة ويُفضل أن تعمل داخل نفس الجهاز الذي ثبت فيه خادم nextcloud تفاديًا لوسائل النقل التي قد تسبب بعض المخاطر.

تحذير: أي ملف مفتاح يجب المحافظة عليه بشكل آمن ويمنع مشاركته مع أي شخص أو توزيعه على الأجهزة لكن الشهادات على عكس ذلك فيمكن مشاركتها بين الأجهزة.

  1. سوف تحتج إلى openssl لذلك عليك تثبيته مع العلم أنه موجود في أغلب توزيعات لينكس بشكل افتراضي.

  2. أنشئ مجلد للعمل

  3. أنشئ بعض المجلدات والملفات التي سنحتاجها لاحقًا بهذا الأمر

$ touch index.txt crlnumber && mkdir certs crl newcerts

إنشاء شهادة هيئة الشهادات (Certificate Authority) المعروفة بالاختصار (CA)

  1. أنشئ ملف باسم openssl-ca.cnf وألصق التالي داخله

HOME                    = .

[ ca ]
default_ca      = CA_default


[ CA_default ]
dir             = .
certs           = $dir/certs
crl_dir         = $dir/crl
database        = $dir/index.txt
new_certs_dir   = $dir/newcerts
certificate     = $dir/cacert.pem
serial          = $dir/serial
crlnumber       = $dir/crlnumber
crl             = $dir/crl.pem
private_key     = $dir/cakey.pem

unique_subject  = no

copy_extensions = copy

name_opt        = ca_default
cert_opt        = ca_default

x509_extensions = usr_cert

default_days    = 825
default_crl_days= 30
default_md      = default
preserve        = no

policy          = policy_match


[ policy_match ]
countryName             = match
stateOrProvinceName     = optional
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional


[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional


[ req ]
default_bits            = 4096
default_keyfile         = cakey.pem
distinguished_name      = req_distinguished_name
attributes              = req_attributes
x509_extensions         = v3_ca
req_extensions          = v3_req
string_mask             = utf8only
prompt                  = no


[ req_distinguished_name ]
countryName                     = SA
0.organizationName              = Private
commonName                      = Private CA 1.0


[ req_attributes ]


[ usr_cert ]
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectKeyIdentifier = hash


[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment


[ v3_ca ]
authorityKeyIdentifier = keyid,issuer
basicConstraints = critical,CA:true
keyUsage = cRLSign, keyCertSign
subjectKeyIdentifier = hash
  1. غير الثلاث خانات المخصصة التي تأتي بعد req_distinguished_name إلى رمز الدولة واسم المؤسسة والاسم الشائع (طبعًا لك الخيار في وضع أي شيء في هذه الخانات بما أنها شهادة موقعة ذاتيًا ولكنها سوف تساعدك على التمييز بين الشهادات الخاصة بك مع ملاحظة أن رمز الدولة يجب أن يتكون من خانتين وأن يعود إلى أحد الدول فعلاً)

  2. أخيرًا اكتب هذا الأمر لإنشاء شهادة ومفتاح الCA (بعدها سوف تجد ملف cakey.pem و cacert.pem)

$ openssl req -x509 -config openssl-ca.cnf -sha256 -nodes -out cacert.pem -outform PEM -days 7300

إنشاء شهادة الخادِم (Server Certificate)

  1. أنشئ ملف باسم openssl-server.cnf وألصق التالي داخله
HOME            = .

[ req ]
default_bits       = 4096
default_keyfile    = serverkey.pem
distinguished_name = server_distinguished_name
req_extensions     = server_req_extensions
string_mask        = utf8only
prompt             = no

[ server_distinguished_name ]
countryName        = SA
organizationName   = Private
commonName         = Private Server Certificate v1.0

[ server_req_extensions ]
subjectKeyIdentifier = hash
basicConstraints     = CA:FALSE
keyUsage             = digitalSignature, keyEncipherment
extendedKeyUsage     = TLS Web Server Authentication, TLS Web Client Authentication
subjectAltName       = @alternate_names

[ alternate_names ]
DNS.1  = nextdloud.example.local
DNS.2  = domain.example.local
DNS.3  = *.myserver.local
IP.1   = 127.0.0.1
IP.2   = 192.168.1.4
  1. غير الثلاث خانات المخصصة التي تأتي بعد server_distinguished_name إلى رمز الدولة واسم الموقع/الخدمة والاسم الشائع (طبعًا لك الخيار في وضع أي شيء في هذه الخانات بما أنها شهادة موقعة ذاتيًا ولكنها سوف تساعدك على التمييز بين الشهادات الخاصة بك مع ملاحظة أن رمز الدولة يجب أن يتكون من خانتين وأن يعود إلى أحد الدول فعلاً)

  2. غير الخانات المخصصة بعد alternate_names إلى النطاقات وعناوين ip الذين تريد استخدام الشهادة فيهم، يمكنك إضافة المزيد من الخانات أو تقليل عددهم على حسب رغبتك مع العلم أنه يمكنك استخدام هذه الشهادة لعدة خدمات غير nextcloud إذا حددت عناوينهم وذلك سوف يختصر عليك إنشاء شهادة مخصصة لكل خدمة تستخدمها في منزلك. (إذا كان نطاق dns محلي يمكنك استخدامه عدى ذلك يمكنك الاكتفاء بخانات الIP ويجب الإشارة إلى قدرتك على استخدام regex في الخانات)

  3. بعد ذلك اكتب الأمر التالي لإنشاء شهادة للخادم (سوف تحصل على ملف servercert.csr وserverkey.pem)

$ openssl req -config openssl-server.cnf -newkey rsa:4096 -sha256 -nodes -out servercert.csr -outform PEM
  1. في النهاية استخدم الأمر التالي لإنشاء شهادة الخادم الموقعة بواسطة مفتاح الCA للحصول على ملف servercert.pem
$ openssl ca -create_serial -config openssl-ca.cnf -policy policy_anything -extensions usr_cert -out servercert.pem -infiles servercert.csr

استخدام الشهادة في خادم nextcloud

إصدار snap

  1. انقل الملف cacert.pem وservercert.pem وserverkey.pem إلى مجلد يملك التطبيق حق الوصول له مثل /var/snap/nextcloud/common

  2. استخدم الأمر التالي بعد استبدال الاسماء بالمسارات الكامل للملفات:

sudo snap run nextcloud.enable-https custom <servercert> <serverkey> <cacert>

ملاحظة: في الاصدار الجديد من Apache ليس هناك حاجة لإدراج ملف cacert.pem لكن البرنامج ما زال يطلبها وبما أن الخطأ مُبلَّغ عنه فقد لا يتم طلبها في الإصدارات القادمة.

nginx

يمكنك وضع servercert.pem وserverkey.pem في مجلد مخصص على سبيل المثال /etc/ssl إذا كان متاح ثم أضفهم في ملف nginx.conf الخاص بالخادم الخاص بك ولا تنسى تغيير المنفذ وإضافة ssl بعده:
على سبيل المثال:

server {
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     /etc/ssl/servercert.pem;
    ssl_certificate_key /etc/ssl/serverkey.pem;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ...
}

للمزيد

أُخرى

بشكل عام الطرق متشابهة ويمكنك البحث والقرائة في الإنترنت.

الوثوق بالشهادة على أجهزتك

أولاً عليك بنقل ملف cacert.pem إلى الجهاز الذي تريده.

لينكس KDE

  1. افتح تطبيق إعدادات النظام
  2. اذهب إلى Network >> Settings ثم SSL Preferences
  3. اضغط على ADD ثم حدد ملف cacert.pem

MacOS

أعتقد أنه يمكنك إضافة الشهادة من نافذة تظهر لك بعد الضغط عليها مرتين أو يمكنك إدارتة الشهادات من تطبيق Keychain Access.

iOS أو iPadOS

  1. ضع ملف cacert.pem في تطبيق الملفات (FIles).
  2. ثم انقر على الملف، وسوف تظهر لك رسالة تخبرك أن الشهادة تم تنزيلها إلى الإعدادت.
  3. اذهب إلى الإعدادت وسوف تجد تنبيه في الصفحة الرئيسة وإذا لم تجد اذهب إلى General>VPN & Device Management سوف تجد الشهادة في DOWNLOADED PROFILES
  4. انقر على اسم الشهادة ثم انقر على Install واكتب رمز المرور الخاص بالجهاز.
  5. سوف يظهر لك تنبيه ثم ثبتها عن طريق الضغط على Install وتأكيد ذلك.
  6. بعد تثبيتها لم تثق التطبيقات بها بعد، لذلك عليك الذهاب إلى General>About>Certificat Trust Setings وتفعيل الشهادة الخاصة بك.

Android

يختلف الأمر بين الأنظمة لكن على الأغلب سوف تجد إعدادات الشهادات باسم CA certificate داخل قسم Connections أو Network ويمكنك إضافتها من هناك عن طريق متصفح الملفات.

تحديث الشهادة

بالنسبة لشهادة الـCA فعمرها 20 سنة وليس عليك القلق حيال أمرها، لكن شهادة الخادم عمرها 825 يوم لذلك يجب عليك تحديثها بعد مرور هذه المدة باستمرار عن طريق إنشاء شهادة جديدة للخادم ثم توقيهعا باستخدام مفتاح الCA باستخدام الأمرين التاليين:
ّ

$ openssl req -config openssl-server.cnf -newkey rsa:4096 -sha256 -nodes -out servercert.csr -outform PEM
$ openssl ca -batch -create_serial -config openssl-ca.cnf -policy policy_anything -extensions usr_cert -out servercert.pem -infiles servercert.csr

ثم عليك إضافتها مرة أُخرى إلى الخادم. ليس عليك القلق على الأجهزة الأُخرى فأنت لم تغير شهادة الCA ولكن فقط شهادة ومفتاح الخادم.
يمكنك أيضًا إذا أحببت أن تغير الاسم الشائع في ملف openssl-server.cnf قبل إنشاء الشهادة بإضافة v2.0 كعلامة على أنها الإصدار الثاني للشهادة.

مصادر

https://nginx.org/en/docs/http/configuring_https_servers.html
https://bob.gatsmas.de/caldav-sync-erinnerungen-app-ios-13-und-macos-1015

للاستزادة

إعجابَين (2)

شرح جميل، مع انه لم اوجه اي مشاكل مع البرامج المشهوره.
لانها كلها تاخذ الحساب من برنامج نكست كلاود الرسمي.

يمكنك الحصول على شهاده SSL مجانيه عبر let’s encrypt بدون كشف اجهزتك.
عبر DNS auth مع مقدمين مثل dnssec. عده برمجيات تدعمها مثل nginx proxy manager

اتوقع بامكانك استخدام دومين مجاني مثل .tk
ثم بعدين تعمل DNS override عبر مثلا pihole

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