ما الذي يهاجم خادماً جديداً فعلياً — وما الذي يسلبه منك فعلياً
وجِّه عنوان IPv4 جديداً نحو الإنترنت، وستصلك حركة مرور غير مرغوبة بعد لحظات تقريباً. ليس لأن أحداً لاحظك: فمساحة العناوين بأكملها تُمسح باستمرار، وأي مضيف يستجيب على المنفذ 22 ينضم ببساطة إلى طابور كان يعمل أصلاً. خلال اليوم الأول، يسجّل الخادم الجديد النموذجي ما بين بضع مئات وبضع عشرات الآلاف من محاولات مصادقة SSH، جُلّها تقريباً ضد root وadmin وubuntu وtest ودزينة أخرى من الأسماء المتوقَّعة، بكلمات مرور من قائمة لم تتغيّر كثيراً منذ عقد. الأمر يبدو كهجوم. لكنه أقرب إلى الطقس.
هذا الفرق مهم، لأنه يحدد أي الضوابط يستحق دقائقك الخمس عشرة. تخمين كلمات المرور بهذا الحجم لا يقل بإيقاف تشغيل المصادقة بكلمة المرور — بل يُلغى تماماً. لا يبقى خطر متبقٍّ لإدارته، ولا ضبط دقيق، ولا معدّل لمراقبته. في المقابل، الأمران اللذان يفقدان فعلاً الخوادم الصغيرة لأصحابها غير برّاقَين: تطبيق مواجه للإنترنت يشغّل إصداراً به ثغرة منشورة عمرها أشهر، وبيانات دخول تسرّبت من مكان آخر وظلّت تعمل هنا. لا هذا ولا ذاك غريب، ولا علاقة لأيٍّ منهما بالمنفذ الذي يستمع عليه SSH.
وثمة نمط فشل ثالث، وهو الأكثر شيوعاً على الإطلاق على مضيف لم يسألك يوماً من أنت: أن تُقفِل الوصول عن نفسك. لدى مزوِّد تقليدي، هذه مجرد تذكرة دعم مزعجة: تجيب عن بعض الأسئلة، تثبت أنك الشخص المسجَّل في بيانات الفوترة، ويعيد أحدهم ضبط الوصول لك. هنا، هذا المسار غير موجود أصلاً — ليس كخيار سياسي مُتَّخَذ على مضض، بل لأن الهوية التي كانت ستُفحص لم تُجمَع قط. ما هو موجود بدلاً من ذلك هو وصول مرتبط بـالحساب لا بشخص: طرفية طوارئ من نوع KVM-over-VNC في اللوحة، ولقطات كل ساعة بفترة احتفاظ سبعة أيام، والقدرة على الإقلاع من شيء آخر كلياً. هذا يكفي. لكنه يكفي فقط إن كنت قد استخدمته مرة قبل أن تحتاجه.
لذلك قائمة التحقق أدناه مرتَّبة بحسب النتائج لا بحسب الرواج. الضوابط التي تُلغي فئة هجوم كاملة تأتي أولاً، وتلك التي تُقلِّل الضوضاء تأتي أخيراً، أما الخطوة التي لا تكلِّف شيئاً وتُنقِذ أمسيتك — إثبات أنك ما زلت قادراً على الدخول — فتأتي قبل كل ما سواها.
| ما الذي يقلق الناس | كيف يصل فعلياً | ما الذي يوقفه | ما الذي لا يوقفه |
|---|---|---|---|
| تخمين كلمات مرور SSH | عمليات مسح آلية، بالآلاف يومياً، بقوائم أسماء مستخدمين عامة | PasswordAuthentication no — كلياً | منفذ غير قياسي؛ كلمة مرور أطول |
| خدمة معروفة بثغرة | ماسح يطابق راية إصدارك بعد أسابيع من صدور التصحيح | تحديثات أمنية تلقائية مع سياسة إعادة تشغيل | جدار حماية، إن كان المنفذ مضطراً للبقاء مفتوحاً أصلاً |
| بيانات دخول معاد استخدامها أو مسرَّبة | دخول صحيح من أول محاولة، من عنوان لم تره من قبل | المصادقة بالمفتاح فقط؛ بيانات دخول فريدة لكل خدمة | تحديد المعدّل — محاولة واحدة ليست طفرة |
| خدمة داخلية مكشوفة | قاعدة بيانات أو ذاكرة تخزين مؤقت أو نقطة مقاييس مربوطة بالعنوان الشامل | الربط بـ loopback؛ الرفض الافتراضي للوارد على العائلتين معاً | افتراض أنها خاصة لأنك لم تربطها بشيء قط |
| فقدان وصولك الخاص | تُحصِّن، وتخرج، ويتضح أن التغيير الذي أجريته كان خاطئاً | جلسة ثانية مفتوحة، ولقطة، وطرفية مُختبَرة | الثقة |
ابنِ طريق الخروج قبل أن تُغلق الباب
إليك التسلسل الذي يُحاصر الناس، مع أن كل خطوة فيه صحيحة بمفردها: عدِّل إعداد SSH، انقل المنفذ، عطِّل تسجيل الدخول بكلمة المرور، فعِّل جدار الحماية، أعد تحميل الخدمة، أغلق الطرفية. الخطأ ليس في أي تغيير بمفرده. الخطأ أن الجلسة التي كنت تكتب فيها كانت الدليل الوحيد على أن أياً منها نجح، وقد تخلَّصت منها قبل أن تتحقق.
القاعدة التي تجعل قائمة التحقق كلها آمنة تتلخص في جملة واحدة: أبقِ الجلسة العاملة مفتوحة، وأثبِت التغيير من جلسة ثانية. افتح طرفية جديدة، اتصل من جديد، شغِّل id، وارتقِ بالصلاحيات عبر sudo. إن نجح ذلك، فالتغيير حقيقي وتصبح الجلسة الأولى قابلة للتخلص منها. وإن فشل، يبقى لديك shell تستطيع به التراجع عن ذلك. ينطبق هذا على جدار الحماية، وعلى sshd، وعلى مفتاح مستخدم جديد، وعلى أي شيء آخر قادر على رفضك عند الباب.
قبل كل ذلك، جهِّز المسار خارج النطاق (out-of-band). في لوحة BitVPS، يحمل كل صف خادم زر الطرفية الذي يفتح جلسة KVM-over-VNC على شاشة الجهاز الافتراضي. إنه ليس shell عبر الشبكة — بل هو شاشة الجهاز ولوحة مفاتيحه — لذا يظل يعمل حين يرفض sshd البدء، وحين يُسقِط جدار الحماية كل حزمة واردة، وحين يكون إعداد الشبكة خاطئاً. افتحه مرة واحدة، الآن، على خادم لم تُفسِده بعد. تأكَّد من ظهور موجِّه تسجيل الدخول لك. يستغرق ذلك ثلاثين ثانية، وهو الفارق بين خطأ وانقطاع تام.
خذ لقطة أيضاً. إنها كل ساعة بفترة احتفاظ سبعة أيام على كل خطة، وتُستعاد خلال نحو ثلاثين ثانية، ما يختصر عبارة "لصقت قاعدة nft خاطئة" من أمسية كاملة من الاستعادة إلى مجرد تراجع بسيط. وبالنسبة للتغييرات التي لست متأكداً منها فعلاً، يكفي سطر واحد لتفعيل مفتاح الرجل الميت: systemd-run --on-active=10min /usr/sbin/ufw --force disable يُسلِّح مؤقِّتاً يُلغي جدار الحماية خلال عشر دقائق ما لم تُلغِه أنت. إن نجحت القواعد الجديدة، تُلغيه. وإن أقفلت الوصول عنك، يعيدك الجهاز إلى الداخل دون أن تكون موجوداً هناك.
SSH: التوجيهات الأربعة التي تؤدي العمل — والملف الذي يتجاوزها
ولِّد المفتاح على جهازك الخاص، لا على الخادم أبداً: ssh-keygen -t ed25519 -C "laptop-2026". يُعَدّ Ed25519 الخيار الافتراضي الصحيح في 2026 — مفاتيح قصيرة، وتحقّق سريع، ولا خيارات معاملات يمكن أن تُخطئ فيها، ومدعوم من كل نسخة OpenSSH بُنيت خلال العقد الأخير. RSA بطول 4096 بت ليس غير آمن، إنه فقط أكبر وأبطأ دون أي فائدة إضافية. عيِّن عبارة مرور على المفتاح الخاص؛ ssh-agent يعني أنك تكتبها مرة واحدة فقط لكل جلسة، وهي الشيء الوحيد الفاصل بين حاسوب محمول مسروق وكل خادم تملكه.
انسخ النصف العام باستخدام ssh-copy-id، وتأكَّد من قدرتك على تسجيل الدخول به قبل أن تُعطِّل أي شيء. الصلاحيات مهمة، وOpenSSH صارم بشأنها بحكم التصميم: ~/.ssh بصلاحية 700، وauthorized_keys بصلاحية 600، وكلاهما مملوك للمستخدم. المفتاح الذي يفشل بصمت هو غالباً مشكلة صلاحيات، وسيخبرك sshd -e -d في الواجهة الأمامية بذلك في سطر واحد.
بعد ذلك، تؤدي أربعة توجيهات في /etc/ssh/sshd_config كل العمل تقريباً. كل ما عداها في ذلك الملف مجرد تفضيل شخصي.
| التوجيه | اضبطه على | ماذا يفعل | ما الذي يتعطَّل إذا أخطأت فيه |
|---|---|---|---|
PasswordAuthentication | no | يُزيل كلمات المرور كوسيلة تسجيل دخول تماماً — فطوفان هجمات القوة الغاشمة بأكمله يصبح مستحيلاً لا مجرد أبطأ | ستُقفَل خارجاً إن لم يكن مفتاحك مثبَّتاً فعلياً. اختبر أولاً، من جلسة ثانية |
KbdInteractiveAuthentication | no | يُغلق الباب الثاني إلى الغرفة نفسها — فمسار PAM التفاعلي عبر لوحة المفاتيح لا يزال قادراً على قبول كلمة مرور حتى مع ضبط التوجيه الأول | يُعطِّل إعدادات المصادقة الثنائية الشرعية المعتمدة على PAM. اتركه مفعَّلاً فقط إن كنت تستخدم واحدة |
PermitRootLogin | prohibit-password | لا يزال بإمكان root تسجيل الدخول بمفتاح (مفيد للأتمتة) لكن أبداً بكلمة مرور | no أكثر صرامة ومناسب — شرط أن يعمل مستخدم sudo لديك. تحقَّق من ذلك أولاً |
PubkeyAuthentication | yes | الطريقة التي تحتفظ بها. التصريح الواضح أفضل من الاعتماد على الافتراضي هنا | لا شيء، لكن يستحق ذكره صراحةً كي لا يُسقطه تعديل مستقبلي بصمت |
AllowUsers / AllowGroups | مستخدمك أو مجموعتك | اختياري، وهو أعلى الأسطر الاختيارية قيمةً — إذ ترفض الخدمة كل حساب آخر قبل المصادقة | خطأ إملائي واحد يرفض الجميع. اضبطه أخيراً، ومن جلسة ثانية |
والآن الجزء الذي يوقع حتى ذوي الخبرة. في Debian 12 وUbuntu 22.04 وكل ما هو أحدث، يبدأ /etc/ssh/sshd_config بسطر Include /etc/ssh/sshd_config.d/*.conf، ويعتمد OpenSSH أول قيمة يحصل عليها لكل كلمة مفتاحية. تُشحَن صور الأنظمة السحابية بملفات إعداد فرعية في ذلك المجلد — غالباً ملف يضبط PasswordAuthentication yes — ولأن سطر Include يقع في الأعلى، يتغلَّب ذلك الملف الفرعي على السطر الذي عدَّلته بعناية بعد مئتي سطر لاحقاً. الملف يقول شيئاً والخدمة تفعل شيئاً آخر.
الحل هو ألا تثق بالملف مطلقاً. اسأل الخدمة عمّا استقرَّت عليه فعلياً: sshd -T | grep -Ei 'passwordauth|permitrootlogin|kbdinteractive|pubkeyauth' يطبع الإعداد الفعلي بعد تطبيق كل تضمين وكتلة تطابق وقيمة افتراضية. هذا الأمر وحده يستحق أكثر من بقية هذا القسم. اقرنه بـsshd -t، الذي يتحقَّق من صحة الصياغة ويخرج برمز غير صفري عند وجود خطأ، وعندها فقط نفِّذ systemctl reload ssh — إعادة التحميل لا تُخِلّ بالجلسات القائمة، لذا حتى إعادة تحميل سيئة تُبقي shell جلستك الحالية حياً.
أما نقل SSH من المنفذ 22، فهو يُزيل ربما 95% من حجم سجلاتك وصفر بالمئة من خطرك. كل ماسح يستحق القلق بشأنه يمسح كل المنافذ الـ65,535، والماسحات التي لا تفعل ذلك لم تكن لتتجاوز المصادقة بالمفتاح فقط أصلاً. انقله إن كانت الضوضاء تزعجك أو إن كان ذلك يُسكِت تنبيه مراقبة، لكن لا تُسجِّله كضابط أمني — وإن نقلته فعلاً، أبقِه تحت 1024، لأن العمليات ذات الامتيازات فقط يمكنها الربط بتلك المنافذ، بحيث لا تستطيع أي عملية غير مميَّزة الاستيلاء على المنفذ إن توقفت الخدمة يوماً.
جدار الحماية: الرفض الافتراضي للوارد، والنصف الذي ينساه الجميع
لجدار الحماية على خادم أحادي الغرض مهمة واحدة: أن يجعل مجموعة المنافذ التي يمكن الوصول إليها مطابقة لمجموعة المنافذ التي تملك سبباً لتسميتها. ارفض الوارد افتراضياً، واسمح بالصادر، واسمح بعودة الاتصالات القائمة والمرتبطة، ثم افتح الشيئين أو الثلاثة التي تُشغِّلها فعلياً. إن كنت على Debian أو Ubuntu، فـufw أربعة أوامر لا أكثر وصحيحة؛ وإن كنت تفضِّل امتلاك ملف قواعد واحد قابل للقراءة، فإن nftables هو الجواب الحديث المدمج في النواة، والشيء الذي يكتب إليه ufw من تحت.
الترتيب مهم في مكان واحد بالضبط: اسمح بمنفذ SSH قبل أن تُفعِّل السياسة. ufw allow 22/tcp ثم ufw default deny incoming ثم ufw enable. وإن عكست الترتيب، تُسقِط خطوة التفعيل الجلسة التي تكتب فيها الآن — وهذا أمر يمكن النجاة منه إن كنت قد نفَّذت القسم السابق ولا يزال لديك طرفية، وإلا فهي الطريقة الكلاسيكية لإنهاء أمسيتك مبكراً.
النصف المنسي هو IPv6. كل خادم هنا يأتي بكتلة /64 موجَّهة، والخدمات تُربط بالعائلتين معاً افتراضياً. مجموعة قواعد مكتوبة بـiptables وحدها تحكم IPv4 ولا تقول شيئاً البتة عن IPv6، فتبقى قاعدة البيانات التي حصَّنتها بعناية قابلة للوصول من الإنترنت بأكمله عبر البروتوكول الآخر. يتعامل ufw مع كليهما حين يُضبط IPV6=yes في /etc/default/ufw (وهو الافتراضي في الإصدارات الحالية — تحقَّق بدلاً من الافتراض)، بينما تتفادى nftables المشكلة هيكلياً: مجموعة قواعد table inet واحدة تغطي العائلتين بمجموعة قواعد واحدة. إن كنت ستكتب سطر إعداد جدار حماية واحداً يدوياً، فاجعله هذا السطر.
ثم يأتي Docker، الذي لا يتجاوز جدار حمايتك بقدر ما يصل من تحته. نشر منفذ باستخدام -p 5432:5432 يُدرِج قواعد DNAT في جدول nat، وتلك القواعد تُقيَّم قبل سلاسل التصفية التي يديرها ufw. والنتيجة حاوية يمكن الوصول إليها من الإنترنت بينما يُظهر ufw status أن المنفذ مغلق، وهذا يفاجئ كل عام أشخاصاً يُشغِّلون قاعدة بيانات في حاوية خلف ما ظنّوه سياسة رفض شامل. انشر إلى loopback بدلاً من ذلك — -p 127.0.0.1:5432:5432 — أو ضع الحاوية على شبكة داخلية وصِلها من حاوية أخرى بالاسم.
| ما تعتقده | ما هو صحيح فعلياً | كيف تتحقق بأمر واحد |
|---|---|---|
| "جدار الحماية يرفض كل ما لم أسمح به" | صحيح لـIPv4 فقط، إن كنت قد كتبت قواعد خاصة بـIPv4 وحده | ip6tables -L -n أو nft list ruleset |
| "قاعدة البيانات غير مكشوفة، إنها داخل حاوية" | المنفذ المنشور قابل للوصول بصرف النظر عن سياسة التصفية | docker ps --format '{{.Ports}}' |
| "لا شيء يستمع على ذلك المنفذ" | شيء ما أُعيد تشغيله وأُعيد ربطه بعد آخر مرة نظرت فيها | ss -tulpn |
| "المنفذ مغلق، هذا ما يقوله مسحي" | المسح من الجهاز نفسه يختبر loopback، لا الإنترنت | امسح من مضيف ثانٍ، أو من حاسوبك المحمول |
ما الذي يستمع فعلياً — الأمر الذي ينهي التخمين
أمر واحد يجيب عن أهم سؤال متعلق بتعرُّض الخادم: ss -tulpn. يسرد هذا الأمر كل مقبس TCP وUDP في وضع الاستماع مع العملية المالكة له، والعمود المهم هو العنوان المحلي (Local Address). 127.0.0.1:5432 يعني أن هذا الجهاز وحده يستطيع الاتصال. 0.0.0.0:5432 يعني أن أي عنوان يصل إلى الجهاز يستطيع ذلك، رهناً بجدار الحماية فقط. [::]:5432 يعني الشيء نفسه عبر IPv6، وهو السطر الذي يتخطاه الناس مروراً سريعاً.
الجناة المتكررون هم دائماً الحفنة نفسها. Redis، الذي ظل معظم تاريخه مربوطاً بشكل واسع ويُشحن دون مصادقة. PostgreSQL وMySQL، حين يُعدَّل ملف إعداد ليقبل اتصالات "من التطبيق" ثم ينتقل التطبيق. MongoDB وElasticsearch، اللذان أنتجا معاً عقداً من عناوين الأخبار عن تسريب البيانات لهذا السبب بالضبط. Memcached، الذي أصبح مستمع UDP الخاص به مضخِّم نطاق ترددي مفضَّلاً. Prometheus node_exporter، الذي يروي بسعادة تفاصيل مضيفك الداخلية لأي من يسأل. واجهة برمجة Docker على المنفذ 2375، وهي تنفيذ أكواد عن بُعد يرتدي واجهة REST. وخادم تطوير بدأه أحدهم "لدقيقة فقط" في لوحة tmux منذ أحد عشر شهراً.
القاعدة بسيطة ولا تتطلب حكماً شخصياً: إن لم تكن الخدمة بحاجة لأن تكون قابلة للوصول من الإنترنت، فاربطها بـ loopback. كل ما تحتاج أنت شخصياً للوصول إليه من أجله يستمر في العمل — ssh -L 5432:127.0.0.1:5432 user@server يمنحك منفذاً محلياً يمرُّ عبر النفق فوق الاتصال الذي تثق به أصلاً، وإن احتاجت عدة أجهزة إلى الوصول، فإن واجهة WireGuard خاصة تمنحها نطاق عناوين لا يلامس الإنترنت العام أبداً. لا يكلِّف أي منهما شيئاً، وكلاهما يُزيل الخدمة من سطح الهجوم تماماً بدلاً من الدفاع عنها.
تحقَّق من الخارج، لا من الداخل. المنفذ الذي يُبلغ جهازك نفسه أنه مصفَّى هو مجرد ادِّعاء بشأن مكدس loopback لديك؛ أما المنفذ الذي لا يستطيع جهاز ثانٍ الوصول إليه فهو دليل. اتصل من حاسوبك المحمول، أو من خادم آخر، وتحقَّق من المنافذ التي تتوقع أنها مفتوحة ومنفذ واحد تتوقع أنه مغلق — فالاختبار الذي لا يمكنه إلا أن ينجح ليس اختباراً.
| الخدمة | الافتراضي المعتاد | ما الذي تُسلِّمه نسخة مكشوفة | الحل |
|---|---|---|---|
| Redis | ربط واسع، وتاريخياً بلا كلمة مرور | قراءة/كتابة كاملة، ومسار معروف جيداً لكتابة ملفات بصلاحية مستخدم redis | اربط بـ loopback؛ اضبط requirepass؛ أبقِ protected-mode مفعَّلاً |
| PostgreSQL / MySQL | loopback، حتى يُعدِّله أحدهم | كامل مجموعة بياناتك، إن كانت بيانات الدخول ضعيفة أو معاد استخدامها | اربط بـ loopback؛ صِله عبر SSH أو WireGuard |
| واجهة Docker البرمجية | مغلقة — ما لم يكن قد فعَّلها درس تعليمي | تنفيذ أكواد يعادل صلاحيات root على المضيف | لا تُعرِّضها أبداً؛ استخدم SSH context بدلاً من ذلك |
| node_exporter / المقاييس | كل الواجهات، المنفذ 9100 | أسماء المضيفين، ونقاط الوصل، والإصدارات، والعمليات الجارية | اربط بـ loopback؛ اجمع المقاييس عبر الواجهة الخاصة |
| إرسال البريد، ولوحات إدارة الويب | كل الواجهات بالضرورة | سطح تخمين كلمات مرور لا يمكن للمفاتيح حمايته | هنا فعلاً مكان تحديد المعدّل |
Fail2ban وCrowdSec: ما قيمتهما بعد اختفاء كلمات المرور
هذا هو البند الذي تضعه معظم قوائم التحقق قرب القمة والذي يبالغ معظم المشغِّلين في تقدير قيمته، لذا يستحق الدقة. مع PasswordAuthentication no، لا يمكن لتخمين كلمة مرور أن ينجح — لا نادراً، ولا بصعوبة، بل إطلاقاً. حظر عنوان بعد خمس محاولات فاشلة لا يجعل مصادقة مستحيلة أشد استحالة. ما يمنحك إياه fail2ban على مستوى SSH هو auth.log أهدأ، ومعالج أقل قليلاً يُنفق على إعداد الاتصال، ورسوم بيانية مراقبة أسهل قراءة. هذه فوائد حقيقية. لكنها نظافة تشغيلية، لا ضابط أمني، وتصنيفها تحت العنوان الخاطئ هو كيف ينتهي بالناس الأمر بملف سجل محصَّن وتطبيق غير مُصحَّح.
المكان الذي تكسب فيه هذه الفئة من الأدوات مكانتها فعلاً هو كل طبقة لا تزال فيها كلمة المرور موجودة: نموذج تسجيل دخول لتطبيق ويب، أو منفذ إرسال بريد، أو لوحة إدارة Nextcloud أو WordPress، أو خادم IMAP. هذه لا يمكن تحويلها إلى المصادقة بالمفتاح العام، لذا يبقى التخمين ممكناً ويكون تحديد المعدّل هو الدفاع الفعلي. تضيف CrowdSec تغذية سمعة مشتركة فوق ذلك، وهي مفيدة بشكل ملموس على مستوى HTTP — إذ تستفيد من عناوين رآها آخرون بالفعل تسيء التصرف — وشبه عديمة الأهمية على مستوى SSH بمجرد أن تصبح المفاتيح إلزامية.
ثمة فخّان ذاتيان يستحقان الذكر. الأول هو حظر نفسك بنفسك، عادةً أثناء اختبار شيء ما في الثالثة صباحاً؛ اضبط ignoreip لتشمل نطاقاتك الخاصة، وتذكَّر أن عنواناً مشتركاً أو من نوع carrier-grade NAT يعني أن حظر "مهاجم" قد يحظر أيضاً بضع مئات من أشخاص لا علاقة لهم بالأمر. والثاني هو أن الأداة يجب أن تكون قادرة على قراءة السجلات التي تُصفِّيها: على التوزيعات التي تُسجِّل فقط إلى journal الخاص بـ systemd، تراقب الواجهة الخلفية الافتراضية القائمة على الملفات بصمتٍ ملفاً لم يعد يستقبل شيئاً، ويبقى الـjail هناك يبدو سليماً دون أن يفعل شيئاً.
التوصية الصادقة: ثبِّته إن كانت الضوضاء تزعجك، واضبطه لطبقة تطبيقك حيث يهمّ فعلاً، ولا تحتسبه مرتين. إن أردت الهدوء نفسه دون أي شيء تصونه، فإن MaxStartups وLoginGraceTime في خدمة SSH إضافةً إلى المصادقة بالمفتاح فقط تُنجز معظم المهمة ولا يمكنها أن تُقفِل الوصول عنك إلى جهازك الخاص.
التصحيح: الضابط المُمِل الذي يمنع معظم الاختراقات الحقيقية
اقرأ أي تقرير حادثة يخص خادماً صغيراً مواجهاً للإنترنت وسيتكرر النمط نفسه: كانت للثغرة رقعة تصحيح، وكانت متاحة منذ أسابيع أو أشهر، ولم يُطبِّقها أحد. فهرس الثغرات المعروفة المُستغَلة التابع لـCISA هو القراءة المفيدة هنا، تحديداً لأنه ليس قائمة خطورة نظرية — إنه قائمة بأشياء تُستغَل في الواقع الآن، ويهيمن عليها مشاكل لها إصلاحات منشورة. لذا فإن التحديثات الأمنية التلقائية هي أعلى خمس عشرة ثانية عائداً في هذه الصفحة بأكملها.
على Debian وUbuntu، ثبِّت unattended-upgrades، وفعِّله بـdpkg-reconfigure -plow unattended-upgrades، وتأكَّد أن مصدر الأمان هو المُحدَّد في /etc/apt/apt.conf.d/50unattended-upgrades. تحقَّق من أنه يفعل شيئاً فعلياً باستخدام unattended-upgrades --dry-run --debug، الذي يطبع بالضبط الحزم التي سيأخذها ولماذا — وصفحة ويكي Debian هي المرجع. على Rocky وAlma، تؤدي dnf-automatic مع apply_updates = yes وتفعيل المؤقِّت المهمة نفسها. الاقتصار على مستودع الأمان مقصود: فهو الإعداد الذي لا يُعطِّل شيئاً تقريباً أبداً، وهو النوع الوحيد من الأتمتة الذي يتركه الناس مفعَّلاً.
بعد ذلك، قرِّر أمر إعادة التشغيل صراحةً، لأن هذا هو المكان الذي يتسرَّب منه الضابط عادةً. تثبيت حزمة نواة جديدة لا يستبدل النواة التي تُشغِّلها فعلياً، واستبدال مكتبة مشتركة لا يُعيد تشغيل الخدمات التي حمَّلت النسخة القديمة إلى الذاكرة أصلاً. تسرد needrestart على Debian وUbuntu بدقة الخدمات التي لا تزال ممسكة بمكتبات محذوفة؛ تحديث النواة يتطلب إعادة تشغيل، نقطة انتهى، والترقيع الحي (live-patching) ميزة مدفوعة لن تصل إلى نسخة بسعر 8.50$. إما أن تضبط Unattended-Upgrade::Automatic-Reboot مع Automatic-Reboot-Time هادئ، أو تضع إعادة تشغيل شهرية في تقويمك وتعاملها كصيانة لا كحادثة.
أخيراً، اعرف ما لا تغطيه التحديثات التلقائية، لأن الفجوة هي حيث يُمسَك بالناس. أي شيء مثبَّت خارج مدير الحزم غير مرئي له: ملف تنفيذي مسحوب من إصدار على GitHub، أو اعتمادية بيئة تشغيل لغة برمجة من pip أو npm أو cargo، أو قالب أو إضافة داخل تطبيق ويب، وقبل كل شيء صور الحاويات. مضيف يُبلِّغ بصفر تحديثات معلَّقة قد يُشغِّل صورة أساس بُنيت قبل عامين، ولا شيء على الجهاز سيخبرك بذلك. إن كنت تُشغِّل حاويات، فإعادة البناء وإعادة السحب وفق جدول زمني جزء من التصحيح، لا نشاط منفصل.
| النظام | الآلية | ما الذي تغطيه | ما الذي تُفوِّته بصمت |
|---|---|---|---|
| Debian / Ubuntu | unattended-upgrades، مصدر الأمان فقط | حزم التوزيعة، تُطبَّق كل ليلة | النواة قيد التشغيل والمكتبات المحمَّلة حتى إعادة التشغيل |
| Rocky / Alma | dnf-automatic مع apply_updates = yes | الأمر نفسه، عبر مؤقِّت systemd | فجوة إعادة التشغيل نفسها؛ تحقَّق بـdnf needs-restarting |
| الحاويات | لا شيء، افتراضياً | لا شيء | كل شيء — الصورة مجمَّدة عند وقت البناء |
| اعتماديات لغة البرمجة | لا شيء، افتراضياً | لا شيء | سطح الهجوم الفعلي لتطبيقك |
المستخدمون، وsudo، والأبواب التي تُعاود الانفتاح بصمت
أنشئ مستخدماً عادياً، أضفه إلى sudo أو wheel، ثبِّت مفتاحك هناك، وتوقَّف عن تسجيل الدخول كـroot. السبب ليس أن root بمفتاح خطير بحد ذاته — بل لأنه حساب أحادي العامل باسم معروف عالمياً وبلا سجل لمعرفة أي إنسان استخدمه. حساب باسم محدَّد مع sudo ينتج سجل تدقيق، ويسمح بأكثر من مشغِّل واحد دون مشاركة بيانات الدخول، ويجعل سؤال "من نفَّذ ذلك" لاحقاً قابلاً للإجابة. لكن لا تمنحه NOPASSWD لكل شيء ثم تُعيد استخدام الحساب نفسه لخدمة ويب.
لا ينبغي للخدمات أن تعمل بصلاحية root أيضاً، ويجعل systemd النسخة الرخيصة من ذلك شبه مجانية. ملف إعداد فرعي يُنشأ بـsystemctl edit <unit> ويحتوي على NoNewPrivileges=yes وProtectSystem=strict وProtectHome=yes وPrivateTmp=yes يحصر خدمة مخترَقة داخل واجهة نظام ملفات للقراءة فقط بلا مسار للتصعيد — أربعة أسطر، موصوفة في توثيق systemd.exec، تُحوِّل كثيراً من ثغرات التطبيقات من "root على المضيف" إلى "خطأ في سجل". يُقيِّم systemd-analyze security كل وحدة على الجهاز ويخبرك بأيها يستحق الدقائق الخمس.
حافظ على صدق authorized_keys. مفتاح واحد لكل جهاز، ولكل منها تعليق يسمِّي الجهاز، واحذف أي شيء لا يمكنك التعرُّف عليه. أعِد قراءة الملف بعد تشغيل أي أداة تجهيز، لأن cloud-init وخطوط أنابيب إنشاء الصور ولوحات التحكم تُلحق جميعها إدخالاتها الخاصة، والمفتاح الذي لم تُضِفه أنت هو مفتاح لا تستطيع إلغاءه. الأمر نفسه ينطبق على الحسابات: مستخدم افتراضي خلَّفته صورة، بكلمة مرور ضبطها سكربت ولم تُستخدم منذ ذلك الحين، هو تسجيل دخول أنت لا تراقبه.
أدق بند في هذه القائمة هو توجيه الوكيل (agent forwarding). يسمح ForwardAgent yes لعملية على المضيف البعيد باستخدام مفتاحك الخاص المحلي طوال مدة اتصالك — وهذا بالضبط ما صُمِّم لفعله، وهو السبب في أن root على جهاز لا تتحكم فيه بالكامل يستطيع استعارة مفتاحك للوصول إلى كل خادم آخر يثق به. استخدم ProxyJump (ssh -J bastion target) بدلاً من ذلك: فهو يمنحك القدرة نفسها على الوصول عبر عمل نفق للاتصال، ولا يصبح مفتاحك أبداً قابلاً للاستخدام على المضيف الوسيط. إن اضطررت إلى توجيه وكيل، فافعل ذلك لكل مضيف على حدة في ~/.ssh/config، لا عالمياً أبداً.
النسخ الاحتياطي: الضابط الذي يُحوِّل يوماً سيئاً إلى مجرد بعد ظهر
كل ما سبق يُقلِّل احتمال حدوث يوم سيئ. النسخ الاحتياطي هو ما يحدِّد كلفة ذلك اليوم السيئ، وعلى مزوِّد لا يستطيع التعرُّف عليك عمداً، تصبح أهم من المعتاد: لا يوجد مسار دعم يُعيد بناء جهازك من نسخة شخص آخر، ولا مسار استرداد حساب يمنحك بصمت استعادة، ولا سجل فوترة مرتبط برقم هاتف. ما تملكه هو فقط ما أخذته أنت بنفسك.
الشكل الذي ينجح غير مثير. restic أو borg، مع التشفير على الخادم بحيث تصبح البيانات غير قابلة للقراءة أصلاً قبل أن تعبر الشبكة، وتُدفع إلى جهاز ثانٍ — ويُفضَّل أن يكون في ولاية قضائية ثانية، وهذا مجرد خانة تُحدَّد لا مشروع كامل حين تعرض اللوحة نفسها آيسلندا وهولندا ورومانيا وسويسرا. اللقطات كل ساعة المُدرجة مع كل خطة خط دفاع أول جيد فعلاً وتغطي حالة "أفسدتُ الإعداد قبل ساعة" تماماً. لكنها لا تغطي ملفاً حذفته قبل خمسة أسابيع، وهي تعيش على البنية التحتية نفسها التي تحميها. اللقطات والنسخ الاحتياطي يحلان مشكلتين مختلفتين؛ استخدم كليهما.
اجعل المستودع بوضع الإلحاق فقط (append-only). هذا هو التفصيل الذي يفصل النسخة الاحتياطية عن مجرد نسخة: فالخادم المخترَق يحمل بيانات دخول هدف نسخه الاحتياطي الخاص به، وأي شيء قادر على الحذف سيُطلَب منه الحذف. يفرض كل من borg serve --append-only وأمر restic rest-server --append-only ذلك على جانب الاستقبال، بحيث يستطيع الجهاز كتابة لقطات جديدة ولا يستطيع إزالة القديمة. قلِّم من مكان آخر، وفق جدول زمني، ببيانات دخول لم يرها الخادم قط.
أمران أخيران، يتجاوزهما الناس عادةً كلاهما. عبارة مرور المستودع يجب ألا تعيش فقط على الجهاز الذي تحميه — اكتبها، وضعها في مدير كلمات مرور في مكان آخر، وعامِلها كما تُعامِل عبارة البذرة (seed phrase) التي هي فعلياً كذلك. واستعِدها مرة واحدة. النسخة الاحتياطية التي لم تستعدها قط مجرد فرضية؛ والطريقة المعتادة لاكتشاف أن قاعدة استثناء تجاهلت بصمت تفريغ قاعدة البيانات هي أثناء عملية الاستعادة التي لا يمكنك تحمُّل أن تسوء فيها الأمور. شغِّل نسخة Starter، واستعِد فيها، وتحقَّق من البيانات، ثم دمِّرها. يكلِّف ذلك 8.50$ وساعة واحدة، وهي الطريقة الوحيدة كي تصبح بقية هذه الصفحة يوماً بروفة بدلاً من محاولة أولى.
ما لا يحميك منه التحصين
لا يحمي القرص من شخص يمسك بالقرص نفسه. كل ضابط في هذه الصفحة يفترض أن نظام التشغيل يعمل ويفرض قواعده الخاصة؛ ولا ينطبق أي منها على جهاز مُطفَأ أُخذت صورة من تخزينه. تلك مشكلة مختلفة ولها إجابة مختلفة — انظر تشفير القرص الكامل، والفتح عن بُعد، وما تسترجعه المصادرة فعلياً — والخلاصة الصادقة هي أن التحصين والتشفير يدافعان ضد تهديدات منفصلة تماماً. فعل أحدهما لا يُنجز جزءاً من الآخر.
لا يُصلح التطبيق الذي تُشغِّله. يمكن لخادم أن يجتاز كل فحص هنا ومع ذلك يُفقَد بسبب منتدى قديم الإصدار، أو نقطة نهاية إدارية بلا مصادقة، أو محرِّك قوالب يُقيِّم مُدخلات المستخدم، أو رمز وصول مرفوع في مستودع عام. تحصين المضيف يُقلِّل نطاق الضرر من اختراق تطبيق — وهو بالضبط ما يهدف إليه حصر systemd أعلاه — لكنه لا يُدقِّق كودك، وأكثر طريقة شائعة يُؤخذ بها خادم صغير لا تزال شيئاً ثبَّته المشغِّل نفسه.
لا يُغيِّر من يعرف أنك استأجرت الجهاز. جهاز محصَّن تماماً دُفع ثمنه من حساب منصة تداول موثَّق الهوية، وطُلب ببريد إلكتروني شخصي، هو جهاز محصَّن تماماً وعليه اسمك. طبقة الأمان وطبقة الهوية مستقلتان، والثانية تُحسم عند الدفع لا عند الـshell — ويغطي مدى إمكانية تتبّع الاستضافة بالعملات المشفرة فعلياً أين تتشكَّل الروابط فعلياً.
ولا يفعل شيئاً حيال تحليل حركة المرور. مراقِب موضوع لرصد اتصالاتك يتعرَّف على شكلها — التوقيت، والحجم، ومن يتحدث إلى من — بصرف النظر عن مدى إتقان ضبط الطرفين. التشفير يُخفي المحتوى، لا المحادثة، ولا يُغيِّر من ذلك أي قدر من ضبط sshd.
قائمة التحقق، بترتيب تنفيذها
ثماني خطوات. الأربع الأولى هي الدقائق الخمس عشرة الواردة في العنوان، وهي تُلغي فئات خطر كاملة؛ أما الأربع الأخيرة فتستغرق وقتاً أطول وهي ما يفصل خادماً تستطيع الدفاع عنه عن خادم اكتفيت بإعداده فقط. يتضمَّن كل صف كيف تعرف أنه نجح، لأن خطوة تحصين لم تتحقق منها هي خطوة تحصين لم تتَّخِذها فعلياً.
| # | الخطوة | كيف تعرف أنها نجحت |
|---|---|---|
| 1 | افتح طرفية اللوحة، تأكَّد من ظهور موجِّه تسجيل الدخول، وخذ لقطة | رأيت الموجِّه على خادم لم يكن معطَّلاً |
| 2 | أنشئ مستخدماً غير root، ثبِّت مفتاح ed25519 الخاص بك، اختبر sudo | طرفية ثانية تسجِّل الدخول بذلك المستخدم وتصعِّد الصلاحيات |
| 3 | عطِّل المصادقة بكلمة المرور والمصادقة التفاعلية عبر لوحة المفاتيح | sshd -T يُبلِّغ passwordauthentication no |
| 4 | جدار حماية برفض افتراضي للوارد يغطي IPv4 وIPv6 | nft list ruleset يُظهر العائلتين معاً؛ ومسح من مضيف آخر يؤكِّد ذلك |
| 5 | دقِّق المقابس التي في وضع الاستماع، وأعِد ربط الخدمات الداخلية بـloopback | ss -tulpn لا يُظهر أي ربط شامل لا تستطيع تبريره |
| 6 | فعِّل التحديثات الأمنية التلقائية وسياسة إعادة تشغيل | unattended-upgrades --dry-run --debug يختار مصدر الأمان |
| 7 | احصر الخدمات بواسطة systemd، ورتِّب authorized_keys | درجات systemd-analyze security تتحسَّن؛ ولكل مفتاح اسم |
| 8 | نسخ احتياطي مشفَّر بوضع الإلحاق فقط وخارج الموقع، استُعيد مرة واحدة | استعدت البيانات في نسخة يمكن التخلص منها وكانت البيانات موجودة |
لا شيء من هذا غريب، وهذا هو المغزى بالضبط. الضوابط المهمة على خادم صغير هي تلك التي تُلغي فئة مشكلة بدلاً من إدارتها: لا كلمات مرور، ولا مستمعون غير متوقَّعين، ولا حزم غير مُصحَّحة، ولا نسخة وحيدة من البيانات. كل ما عدا ذلك مجرد تفضيل، والتفضيل رخيص بمجرد أن تكون التغييرات الأربعة الحاملة للثقل مطبَّقة ومُتحقَّقاً منها.
إن كنت تُجهِّز الجهاز الآن بدلاً من القراءة مسبقاً، فإن التسلسل يتسع بارتياح داخل الجلسة الأولى: انشر نسخة، وافتح الطرفية مرة لإثبات أنها تعمل، ونفِّذ الخطوات الثماني بالترتيب قبل أن تُثبِّت أي شيء إطلاقاً. خادم مُحصَّن قبل أن تكون عليه أي خدمة لا يحمل إرثاً قديماً للتعامل معه — وهي الميزة الوحيدة التي يملكها جهاز جديد، وهي تدوم نحو يوم واحد.