> ## Content Index
> Fetch the complete content index at: https://arabroot.io/llms.txt
> Use this file to discover other available public pages before exploring further.

# Bastion Host أم Jump Server؟ نقطة الدخول الآمنة إلى سيرفراتك
- URL: https://arabroot.io/articles/ما-هو-bastion-host-و-jump-server/
- Published: 2026-10-08T13:00:00.000Z
- Updated: 2026-10-09T13:01:40.000Z
- Description: لماذا لا يفتح كل سيرفر منفذ الإدارة للإنترنت، وكيف تبني نقطة دخول واحدة مقواة تمر عبرها إلى سيرفراتك بأمان.
- Author: فريق عرب رووت
- Tags: الأدلة التقنية, الشبكات والبنية التحتية, الشبكات والوصول, لينكس والسيرفرات, الاستضافة الذاتية

إذا كان لديك خمسة سيرفرات وكل واحد منها يفتح المنفذ 22 للإنترنت، فأنت في الحقيقة تدير خمسة أبواب أمامية، وكل باب منها يصله كل يوم عدد كبير من محاولات الدخول الآلية التي تجرب أسماء المستخدمين وكلمات المرور، ويكفي أن ينسى أحد الفريق تحديث سيرفر واحد أو أن يترك عليه حساباً قديماً بكلمة مرور ضعيفة حتى يصبح هذا السيرفر الطريق إلى بقية الشبكة. والأمر نفسه يحدث مع خوادم Windows التي تفتح منفذ RDP، بل هو أخطر، لأن RDP كما سوف نرى لم يصمم ليكون مكشوفاً للإنترنت أصلاً.

والحل الذي تتفق عليه أغلب أطر الأمن هو أن تجعل للإدارة باباً واحداً فقط، تقويه وتراقبه وتسجل ما يمر منه، وتبقى بقية السيرفرات في شبكة خاصة لا يصلها أحد من الخارج، وهذا الباب له اسمان تسمعهما كثيراً: **Bastion Host** و**Jump Server**، وأحياناً Jump Host أو Jump Box. وقد ذكرنا هذه الفكرة في عدة مقالات سابقة، مثل مناطق الشبكة في [الفرق بين Tiers وLayers](https://arabroot.io/articles/%D8%A7%D9%84%D9%85%D8%B9%D9%85%D8%A7%D8%B1%D9%8A%D8%A9-%D9%85%D8%AA%D8%B9%D8%AF%D8%AF%D8%A9-%D8%A7%D9%84%D8%B7%D8%A8%D9%82%D8%A7%D8%AA-tiers-%D9%88-layers/#in-practice) وخيارات الباب الإداري في [خارطة CTO لشركة SaaS ناشئة](https://arabroot.io/articles/%D8%AE%D8%A7%D8%B1%D8%B7%D8%A9-cto-%D9%84%D8%B4%D8%B1%D9%83%D8%A9-saas-%D9%86%D8%A7%D8%B4%D8%A6%D8%A9-%D8%A7%D9%84%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%A8%D9%8A%D8%A6%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D9%81%D8%B1%D9%82/#network)، وفي هذا المقال سوف نشرحها كاملة، وسوف نناقش ما يلي:

- لماذا لا يفتح كل سيرفر منفذ الإدارة للإنترنت، والحلول البسيطة التي يبدأ بها أغلبنا ولماذا لا تكفي.
- ما هو Bastion Host وما هو Jump Server، وأين يستخدم المصطلحان للشيء نفسه وأين يختلفان.
- كيف يعمل ProxyJump في OpenSSH، ولماذا هو أفضل من إعادة توجيه ال ssh-agent المعروفة باسم Agent Forwarding.
- كيف تقوي ال Bastion: المفاتيح وMFA وتقييد الحساب وتقليل الحزم والسجلات والشهادات قصيرة العمر.
- ما يقابله في Windows، والبدائل المدارة في السحابة، وبوابات الوصول المميز الحديثة.
- ما الذي تطلبه الضوابط الأساسية للأمن السيبراني NCA ECC في هذا الجانب.
- تجربة عملية كاملة بثلاثة Containers: Bastion واحد مكشوف وسيرفران داخليان دون أي منفذ منشور.

## لماذا لا يفتح كل سيرفر منفذ الإدارة للإنترنت؟

لنفرض أن لديك سيرفر تطبيق app-01 وسيرفر قاعدة بيانات db-01 وسيرفر ويب وجهاز Windows، وأن كل واحد منها له عنوان عام وينشر منفذ الإدارة، فالمشكلة هنا ليست في سيرفر بعينه، وإنما في أن سطح الهجوم Attack Surface يكبر مع كل سيرفر تضيفه، والسبب أن كل سيرفر يحتاج أن تحدث خدمة SSH فيه، وأن تراجع حساباته ومفاتيحه، وأن تراقب سجلاته، وإذا فاتك واحد فقط فهو الذي سوف يستخدمه المخترق. والصورة التالية تبين الفرق بين الحالتين:

![مخطط من لوحتين: على اليمين أربعة سيرفرات web-01 وapp-01 وdb-01 وwin-01 ينشر كل منها منفذ SSH أو RDP للإنترنت وأجهزة مسح ترسل محاولات إلى كل منفذ، وعلى اليسار السيرفرات نفسها في شبكة خاصة 10.70.0.0/24 دون منافذ عامة، وأمامها سيرفر Bastion واحد بدرع يقبل SSH بالمفاتيح فقط ويمرر الاتصال إلى السيرفرات](https://arabroot.io/content/images/2026/10/bastion-jump-01-exposure.webp)

أربعة أبواب تحتاج إلى تحديث ومراقبة، أم باب واحد مقوى والسيرفرات خلفه

وقبل أن نصل إلى ال Bastion، لنمر على الحلول التي يبدأ بها أغلبنا، لأن فهم سبب قصورها هو الذي يوضح لماذا نحتاج إلى باب واحد:

1. **تغيير المنفذ من 22 إلى رقم آخر:** يقلل الضجيج في السجلات، ولكن أدوات المسح تفحص كل المنافذ، فالخدمة ما زالت مكشوفة وما زالت تحتاج إلى التحديث والمراقبة في كل سيرفر.
2. **fail2ban على كل سيرفر:** يحظر العناوين التي تكرر المحاولات الفاشلة كما شرحنا في [تأمين سيرفر VPS من أول دخول](https://arabroot.io/articles/%D8%AA%D8%A3%D9%85%D9%8A%D9%86-%D8%AE%D8%A7%D8%AF%D9%85-vps-%D9%85%D9%86-%D8%A3%D9%88%D9%84-%D8%AF%D8%AE%D9%88%D9%84/)، وهو مفيد، ولكنه لا يحمي من ثغرة في خدمة SSH نفسها، ولا من مفتاح مسروق.
3. **قائمة العناوين المسموحة Allowlist:** تسمح للمنفذ من عنوان المكتب فقط، وهذا جيد حتى يعمل أحدكم من البيت أو من السفر، فتضيف عنوانه ثم تنسى أن تحذفه، وبعد سنة تجد القائمة طويلة لا يعرف أحد أصحابها، وعليك أن تحدثها في كل سيرفر.
4. **VPN أمام كل شيء:** حل ممتاز للوصول إلى الشبكة كما شرحنا في [ما هو VPN؟](https://arabroot.io/articles/%D9%85%D8%A7-%D9%87%D9%88-vpn-%D8%B4%D8%B1%D8%AD-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/)، ولكنه يعطي من دخل النفق طريقاً إلى الشبكة كلها إلا إذا قسمتها، ولا يسجل من دخل إلى أي سيرفر وبأي حساب. لذلك يستخدم VPN كثيراً مع ال Bastion لا بدلاً منه، فيكون ال Bastion نفسه غير مكشوف إلا داخل النفق.

والقاسم المشترك في هذه الحلول أنها تحمي كل باب على حدة، أما الفكرة التي نشرحها الآن فهي أن تغلق الأبواب كلها إلا واحداً.

## ما هو Bastion Host، وما هو Jump Server؟

يعرف [معجم NIST](https://csrc.nist.gov/glossary/term/bastion%5Fhost?ref=arabroot.io) نقلاً عن CNSSI 4009 ال Bastion Host بأنه حاسوب لغرض خاص في الشبكة، صمم وضبط خصيصاً ليصمد أمام الهجمات (A special purpose computer on a network specifically designed and configured to withstand attacks). والاسم مأخوذ من الحصون القديمة، فالبرج البارز Bastion هو الجزء الذي يتلقى الهجوم أولاً ولذلك يبنى أقوى من بقية السور. وفي الواقع العملي هو سيرفر يقف على حافة الشبكة Perimeter، أي أنه مكشوف للإنترنت أو لشبكة أقل ثقة، وكل ما عليه موجه لهدف واحد هو أن يقبل اتصالاً موثقاً ثم يمرره إلى الداخل، فلا تطبيقات عليه ولا بيانات ولا أدوات.

أما ال Jump Server أو Jump Host فهو اسم وظيفي لا تعريف رسمي له، ويقصد به السيرفر الذي يدخل إليه المدير أولاً ثم «يقفز» منه إلى السيرفرات الأخرى، وغالباً يكون داخل منطقة إدارة Management Zone خاصة، ويصل إليه المدير من شبكة المكتب أو عبر VPN، ثم يعمل عليه فعلاً: يفتح جلسة RDP إلى سطح مكتب فيه أدوات الإدارة مثل kubectl وpsql وأدوات إدارة Active Directory، وقد يحفظ عليه جلسات وكلمات مرور. وتصف Microsoft في دليل [حماية الوسطاء في الوصول المميز](https://learn.microsoft.com/en-us/security/privileged-access-workstations/privileged-access-intermediaries?ref=arabroot.io) هذا النوع بأنه سطح مكتب بعيد Remote Desktop يستخدم في سيناريوهات الإدارة ويسمى غالباً Jump Server، وتنبه إلى أن الجلسات الحساسة كلها تمر عبره، فيستطيع المخترق الذي يسيطر عليه أن يسرق بيانات الدخول بأدوات سرقة بيانات الدخول المعروفة ويعيد استخدامها.

والصورة التالية تبين الفرق بين الشكلين:

![مخطط من لوحتين: على اليمين Bastion Host يقف على خط الحافة بين الإنترنت والشبكة الخاصة، يصله حاسوب المدير الذي يبقى المفتاح عليه ويحاول المهاجمون الوصول إليه، ويمرر الاتصال إلى app-01 وdb-01 وweb-01. وعلى اليسار Jump Server داخل منطقة إدارة يصله المدير عبر VPN أو شبكة المكتب بجلسة RDP أو SSH، وعليه أدوات kubectl وpsql وRSAT وSSMS وجلسات محفوظة وبيانات دخول، ومنه يتصل بسيرفرات الإنتاج](https://arabroot.io/content/images/2026/10/bastion-jump-02-bastion-vs-jump.webp)

ال Bastion يمرر الاتصال ولا يعمل عليه أحد، وال Jump Server يعمل عليه المدير وتعيش عليه الأدوات

### أين يستخدم المصطلحان للشيء نفسه، وأين يختلفان؟

في أغلب الوثائق والمحادثات اليومية يستخدم الاسمان للشيء نفسه، فخدمة Azure تسمى Azure Bastion، ووثائق AWS تذكر «bastion hosts» و«jump boxes» معاً في الجملة نفسها، ومشروع JumpServer يقدم نفسه منصة وصول مميز. لذلك لا تتوقف عند الاسم، وإنما اسأل سؤالاً واحداً: هل يمر المستخدم عبر هذا السيرفر، أم يعمل عليه؟ والجدول التالي يلخص الفرق عندما يقصد كل اسم معناه الدقيق:

|                   | Bastion Host                                                | Jump Server                                         |
| ----------------- | ----------------------------------------------------------- | --------------------------------------------------- |
| مكانه             | على حافة الشبكة، مكشوف للإنترنت أو لشبكة أقل ثقة            | داخل منطقة إدارة، يصله المدير من الداخل أو عبر VPN  |
| طريقة الاستخدام   | يمرر الاتصال فقط Pass-through، ولا يفتح المستخدم عليه Shell | يدخل إليه المدير ويعمل عليه، ثم يتصل منه بالسيرفرات |
| ما عليه           | أقل عدد ممكن من الحزم، دون أدوات ودون مفاتيح                | أدوات الإدارة، وأحياناً جلسات وبيانات دخول محفوظة   |
| المفتاح الخاص     | يبقى على جهاز المستخدم                                      | قد يوجد على السيرفر نفسه، وهنا الخطر                |
| الشكل الشائع      | Linux مع OpenSSH وProxyJump                                 | Windows مع RDP، أو Linux بأدوات كثيرة               |
| ما يراه من الجلسة | بيانات مشفرة فقط، إلا إذا كان بوابة تنهي الجلسة             | كل شيء، لأن الجلسة تبدأ منه                         |

والنصيحة العملية أن تبني ال Bastion بالمعنى الأول، أي سيرفراً يمرر ولا يعمل عليه أحد، أما إذا احتجت فعلاً إلى سطح مكتب إداري فيه أدوات Windows، فعامله كأصل حساس بحد ذاته، وضعه خلف بوابة تتحقق من الهوية، وسجل جلساته، ولا تحفظ عليه كلمات المرور.

## كيف يعمل ProxyJump في OpenSSH؟

الطريقة القديمة للمرور عبر ال Bastion كانت أن تدخل إليه بجلسة SSH عادية، ثم تكتب منه أمر `ssh` مرة ثانية إلى السيرفر الداخلي، وهذه الطريقة تحتاج أن يكون مفتاحك على ال Bastion نفسه، أو أن تفعل Agent Forwarding حتى يستخدم ال Bastion مفتاحك من جهازك، وكلاهما سيئ كما سوف نرى. والطريقة الصحيحة هي الخيار `-J`، ويشرحه [دليل ssh](https://man.openbsd.org/ssh?ref=arabroot.io) بأنه يتصل بالسيرفر الهدف عن طريق اتصال SSH أولاً بال Jump Host، ثم إنشاء توجيه TCP منه إلى الهدف النهائي، وهو اختصار للإعداد `ProxyJump` الموجود في [دليل ssh\_config](https://man.openbsd.org/ssh%5Fconfig?ref=arabroot.io). والصورة التالية تبين الخطوات:

![مخطط من اليمين إلى اليسار: حاسوب يكتب ssh app-01 والمفتاح الخاص يبقى عليه، ثم أنبوب رمادي هو اتصال SSH الأول إلى ال bastion على المنفذ 22220 بالمستخدم jump دون Shell ومعه PermitOpen app-01:22 db-01:22، وداخله أنبوب أخضر هو اتصال SSH الثاني يمتد من الحاسوب حتى app-01 في الشبكة الخاصة 10.70.0.0/24. وأربع خطوات مرقمة: الدخول إلى ال bastion بالمفتاح، طلب قناة إلى app-01:22 بالخيار ssh -W، تحقق ال bastion من PermitOpen ثم فتح اتصال TCP، ثم اتصال SSH ثان داخل الأول لا يرى منه ال bastion إلا بيانات مشفرة](https://arabroot.io/content/images/2026/10/bastion-jump-03-proxyjump.webp)

اتصال SSH ثان يمر داخل الأول، والمفتاح لا يغادر جهازك

في الصورة أعلاه لاحظ التالي:

- الخطوة 1 دخول عادي إلى ال Bastion بمفتاحك وبحساب اسمه هنا `jump`، ولكن هذا الحساب لا يملك Shell ولا يحتاج إليه.
- في الخطوة 2 يطلب ssh من ال Bastion قناة Channel من نوع direct-tcpip إلى `app-01:22`، وهذا ما يفعله الخيار `-W` الذي يضيفه ssh تلقائياً كما سوف ترى في مخرج التجربة.
- في الخطوة 3 يتحقق ال Bastion من أن هذه الوجهة مسموحة، ثم يفتح اتصال TCP عادياً إلى السيرفر الداخلي، وهذا كل عمله.
- في الخطوة 4 يبدأ ssh على جهازك اتصالاً ثانياً كاملاً مع app-01 داخل تلك القناة، بالتحقق من مفتاح السيرفر Host Key وبالمصادقة بمفتاحك، فالتشفير هنا من جهازك إلى app-01 مباشرة، وال Bastion لا يرى الأوامر ولا المخرج، ولا يحتاج إلى أي مفتاح يخصك.

ويمكنك أن تقفز عبر أكثر من سيرفر بفصلها بفاصلة، مثل `ssh -J bastion,inner-jump app-01`، ولاحظ ملاحظة مهمة في الدليل نفسه: الخيارات التي تكتبها في سطر الأوامر مثل `-i` و`-o` تنطبق غالباً على السيرفر الهدف لا على ال Jump Host، لذلك ضع إعدادات ال Bastion في ملف `~/.ssh/config` كما سوف نفعل في التجربة.

## لماذا تفضل ProxyJump على Agent Forwarding؟

ال ssh-agent برنامج يعمل على جهازك ويحفظ مفاتيحك مفتوحة في الذاكرة، والخيار `-A` أو الإعداد `ForwardAgent yes` يجعل السيرفر الذي دخلت إليه قادراً على أن يطلب من هذا البرنامج توقيع عمليات دخول جديدة، فتستطيع أن تكتب `ssh db-01` من ال Bastion وكأن مفتاحك عليه. وقد يتساءل البعض: إذا كان المفتاح نفسه لا ينتقل، فأين المشكلة؟ والإجابة في [دليل ssh\_config](https://man.openbsd.org/ssh%5Fconfig?ref=arabroot.io) نفسه، فهو ينبه إلى أن تفعيل Agent Forwarding يجب أن يكون بحذر، لأن من يستطيع تجاوز صلاحيات الملفات على السيرفر البعيد، أي root أو من سيطر عليه، يستطيع الوصول إلى ال ssh-agent المحلي عبر الاتصال المعاد توجيهه، وصحيح أنه لا يستطيع أن يأخذ المفتاح نفسه، ولكنه يستطيع أن يستخدمه للمصادقة بالهويات المحملة فيه. ويضيف [دليل ssh](https://man.openbsd.org/ssh?ref=arabroot.io) في شرح الخيار `-A` أن البديل الأكثر أمناً قد يكون استخدام Jump Host عبر `-J`. والصورة التالية تبين الفرق:

![مخطط من لوحتين: على اليمين ssh -A ops@bastion حيث يعاد توجيه ال ssh-agent من الحاسوب إلى ال bastion فيظهر عليه الملف /tmp/ssh-…/agent.136، ثم يستخدمه root على ال bastion ليدخل إلى db-01 بالأمر ssh admin@db-01 موقعاً بال agent الخاص بك. وعلى اليسار ssh -J حيث لا يوجد agent socket على ال bastion، ويرى root بيانات مشفرة فقط، ويصل الاتصال من الحاسوب إلى db-01 مباشرة](https://arabroot.io/content/images/2026/10/bastion-jump-04-agent-forwarding.webp)

المفتاح لا يغادر جهازك في الحالتين، ولكن مع Agent Forwarding يوقع للمخترق ما دمت متصلاً

والقاعدة بسيطة: لا تفعل `ForwardAgent` إلى أي سيرفر لا تثق بكل من يملك root عليه، وال Bastion بالذات هو السيرفر المكشوف للإنترنت، أي أنه أول سيرفر نتوقع أن يهاجم. وسوف نرى هذا الخطر بمخرج حقيقي في [التجربة العملية](#lab-agent).

## كيف تقوي ال Bastion؟

ال Bastion هو السيرفر الذي اخترت أن تكشفه، لذلك يستحق أكثر من إعدادات أي سيرفر آخر، والأساسيات المشتركة مثل المستخدم العادي وتعطيل كلمة المرور وجدار الحماية شرحناها في [تأمين سيرفر VPS من أول دخول](https://arabroot.io/articles/%D8%AA%D8%A3%D9%85%D9%8A%D9%86-%D8%AE%D8%A7%D8%AF%D9%85-vps-%D9%85%D9%86-%D8%A3%D9%88%D9%84-%D8%AF%D8%AE%D9%88%D9%84/)، وفيما يلي ما يضاف إليها:

- **المفاتيح فقط Key-only:** `PasswordAuthentication no` و`KbdInteractiveAuthentication no` و`PermitRootLogin no`، والسبب أن ال Bastion يتلقى محاولات تخمين كلمات المرور طوال اليوم، والمفتاح لا يخمن.
- **المصادقة متعددة العوامل MFA:** الشكل الأبسط في SSH مفتاح من نوع `ed25519-sk` محفوظ على مفتاح أمان FIDO2، فلا يعمل إلا بوجود المفتاح ولمسه، والإعداد `PubkeyAuthOptions verify-required` في [دليل sshd\_config](https://man.openbsd.org/sshd%5Fconfig?ref=arabroot.io) يشترط التحقق من المستخدم على المفتاح نفسه بالرقم السري أو البصمة. وقد شرحنا هذه المفاتيح في [Passkeys وFIDO2](https://arabroot.io/articles/%D8%A7%D9%84%D8%AF%D8%AE%D9%88%D9%84-%D8%AF%D9%88%D9%86-%D9%83%D9%84%D9%85%D8%A9-%D9%85%D8%B1%D9%88%D8%B1-passkeys-%D9%88-fido2/)، وإضافة رمز TOTP عبر وحدات PAM في Linux في [إدارة الهوية والوصول IAM والوصول المميز PAM](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%87%D9%88%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-iam-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-%D8%A7%D9%84%D9%85%D9%85%D9%8A%D8%B2-pam/).
- **حساب يمرر ولا يعمل:** كتلة `Match User` تجعل حساب ال Bastion دون Shell عبر `ForceCommand` و`PermitTTY no`، وتسمح بالتوجيه المحلي فقط عبر `AllowTcpForwarding local`، وتحصر الوجهات المسموحة في `PermitOpen`، وتمنع Agent Forwarding وX11 والأنفاق. وينبه الدليل إلى أن منع التوجيه لا يحسن الأمن ما دام المستخدم يملك Shell، لأنه يستطيع تشغيل برنامج توجيه خاص به، ولهذا نمنع ال Shell أولاً.
- **أقل عدد ممكن من الحزم:** لا تثبت على ال Bastion أي شيء لا يحتاجه SSH، فلا أدوات تطوير ولا curl ولا Python ولا عميل قاعدة بيانات، والسبب أن كل أداة عليه هي أداة جاهزة للمخترق الذي يصل إليه، وكل حزمة هي حزمة تحتاج إلى تحديث. وفي تجربتنا لا يوجد على ال Bastion المبني من `debian:13` مع `openssh-server` أي من curl وwget وpython3 وnc وgcc.
- **السجلات خارج ال Bastion:** فعل `LogLevel VERBOSE` حتى يسجل sshd بصمة المفتاح Fingerprint الذي دخل به كل شخص، وأرسل السجلات إلى سيرفر مركزي لا يملكه مدير ال Bastion، كما شرحنا في [السجلات Logging للمطورين ومديري السيرفرات](https://arabroot.io/articles/%D8%A7%D9%84%D8%B3%D8%AC%D9%84%D8%A7%D8%AA-logging-%D9%84%D9%84%D9%85%D8%B7%D9%88%D8%B1%D9%8A%D9%86-%D9%88%D9%85%D8%AF%D9%8A%D8%B1%D9%8A-%D8%A7%D9%84%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D8%A7%D8%AA/)، والسبب أن من يصبح root على ال Bastion يستطيع أن يحذف سجلاته المحلية.
- **شهادات SSH قصيرة العمر:** بدلاً من نسخ مفاتيح الفريق إلى كل سيرفر، يثق ال Bastion والسيرفرات بجهة توقيع واحدة عبر `TrustedUserCAKeys`، وتوقع هذه الجهة مفتاح كل مهندس لساعات بالأمر `ssh-keygen -s` كما في [دليل ssh-keygen](https://man.openbsd.org/ssh-keygen?ref=arabroot.io)، فإذا غادر أحدهم لا تحتاج إلى حذف مفتاحه من أي مكان. وقد طبقنا ذلك خطوة بخطوة في [تجربة شهادات SSH](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%87%D9%88%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-iam-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-%D8%A7%D9%84%D9%85%D9%85%D9%8A%D8%B2-pam/#demo-ca)، فلا نعيده هنا.
- **السيرفرات الداخلية تقبل ال Bastion فقط:** على كل سيرفر داخلي اسمح بالمنفذ 22 من عنوان ال Bastion وحده في جدار الحماية، وأضف في sshd نفسه `AllowUsers admin@10.70.0.10` كما في التجربة، حتى لا يعتمد الحماية على طبقة واحدة.
- **ال Bastion لا يحمل شيئاً:** لا مفاتيح خاصة، ولا ملفات إعداد فيها كلمات مرور، ولا بيانات، فإذا سقط فأنت تعيد بناءه من الصفر في دقائق، ويفضل أن يكون بناؤه آلياً من ملف إعداد حتى يكون ذلك سهلاً.
- **Bastion لكل بيئة:** لا تجعل Bastion الإنتاج Production هو نفسه Bastion بيئة الاختبار، والسبب أن الوصول إلى بيئة الاختبار يعطى لعدد أكبر من الناس، ويجب ألا يكون طريقاً إلى الإنتاج.
- **حساب الطوارئ Break-Glass:** ماذا لو توقف ال Bastion نفسه؟ جهز طريقاً بديلاً موثقاً، مثل لوحة المزود Console، بحساب طوارئ محمي ومراقب، كما شرحنا في [ضوابط الوصول المميز](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%87%D9%88%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-iam-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-%D8%A7%D9%84%D9%85%D9%85%D9%8A%D8%B2-pam/#pam-controls).

⚠️

ال Bastion الذي يمرر الاتصال عبر ProxyJump لا يرى الأوامر التي تكتبها على السيرفرات الداخلية، لأن الجلسة مشفرة من جهازك إلى السيرفر مباشرة، فهو يعرف من دخل ومتى وإلى أي سيرفر ومنفذ فقط. لذلك إذا كنت تحتاج إلى تسجيل الأوامر نفسها، فسجلها على السيرفرات الداخلية بتسجيل جلسات sudo كما في [تجربة sudo](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%87%D9%88%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-iam-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-%D8%A7%D9%84%D9%85%D9%85%D9%8A%D8%B2-pam/#demo-sudo) أو بأداة auditd، أو استخدم بوابة وصول تنهي الجلسة عندها كما في [بوابات الوصول المميز](#pam-gateways).

## وماذا عن خوادم Windows وRDP؟

المنطق نفسه ينطبق على Windows، ولكن الخطر أكبر، فدليل Microsoft في [حماية الوسطاء](https://learn.microsoft.com/en-us/security/privileged-access-workstations/privileged-access-intermediaries?ref=arabroot.io) لا ينصح باتصال RDP المباشر عبر الإنترنت، والسبب أن البروتوكول يملك حماية محدودة من الهجمات الحديثة مثل رش كلمات المرور Password Spray، وينصح بأن يمر عبر بوابة. والبوابة التي تأتي مع Windows Server هي دور [Remote Desktop Gateway](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/remote-desktop-gateway-role?ref=arabroot.io) واختصاراً RD Gateway، وهي بحسب توثيقها تتيح اتصالات آمنة مشفرة بموارد Remote Desktop Services عبر الإنترنت دون الحاجة إلى VPN، وتعمل بشهادة TLS ينصح أن تكون صادرة من جهة عامة لأن البوابة مكشوفة للإنترنت. فتكون البوابة هي الباب الوحيد المكشوف، وأجهزة Windows خلفها لا تنشر المنفذ 3389 لأحد. والبديل مفتوح المصدر هو [Apache Guacamole](https://guacamole.apache.org/?ref=arabroot.io) الذي يفتح RDP وSSH وVNC من المتصفح، ونذكره مع البوابات بعد قليل.

## البدائل المدارة في السحابة

إذا كانت سيرفراتك في إحدى السحابات الكبيرة، فكل مزود يقدم خدمة تقوم بعمل ال Bastion دون أن تدير سيرفراً بنفسك، وهذه أشهرها كما يصفها توثيق كل مزود:

- **AWS Systems Manager Session Manager:** بحسب [توثيق Session Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html?ref=arabroot.io) يتيح إدارة الأجهزة دون فتح منافذ واردة Inbound Ports ودون إدارة Bastion Hosts أو مفاتيح SSH، والصلاحيات فيه تأتي من سياسات IAM، وتعمل الجلسة عبر برنامج SSM Agent المثبت على الجهاز، ويمكن حفظ سجلات الجلسات كما في [توثيق التسجيل](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-logging.html?ref=arabroot.io).
- **Azure Bastion:** بحسب [توثيق Azure Bastion](https://learn.microsoft.com/en-us/azure/bastion/bastion-overview?ref=arabroot.io) هو خدمة PaaS مدارة بالكامل توفر اتصال RDP وSSH بالأجهزة الافتراضية عبر TLS على المنفذ 443 من بوابة Azure أو من عميل SSH وRDP على جهازك، والأجهزة لا تحتاج إلى عنوان عام. ويأتي بأربع فئات SKU هي Developer وBasic وStandard وPremium، وتسجيل الجلسات Session Recording متاح في فئة Premium فقط.
- **Google Cloud IAP TCP Forwarding:** بحسب [توثيق IAP](https://cloud.google.com/iap/docs/using-tcp-forwarding?ref=arabroot.io) ينشئ نفقاً مشفراً تمرر عبره SSH وRDP وغيرهما إلى أجهزة ليس لها عنوان خارجي، فتسمح في الجدار الناري بالمنفذ 22 من النطاق `35.235.240.0/20` فقط، وتعطي المستخدم الدور IAP-Secured Tunnel User، ثم تتصل بالأمر `gcloud compute ssh` مع الخيار `--tunnel-through-iap`.

هل هذه الخدمات أفضل من Bastion تديره بنفسك؟ في أغلب الحالات نعم إذا كانت كل سيرفراتك عند المزود نفسه، والسبب أن المزود يحدثها ويراقبها، وأنها تربط الصلاحيات بحسابات IAM التي تديرها أصلاً، ودليل Microsoft السابق يصف هذه الخدمات السحابية بأنها تعطي المهاجم سطح هجوم محدوداً مقارنة بأجهزة الوصول التي يديرها فريق مشغول. ولكن لاحظ أنها تربطك بالمزود، ولا تفيدك في سيرفرات على VPS عند مزود صغير أو في مكتبك، وأن قوتها كلها مرهونة بحماية حسابات لوحة السحابة نفسها بMFA قوية.

## بوابات الوصول المميز وZero Trust

ال Bastion التقليدي يعرف المفتاح الذي دخلت به، ولكنه لا يعرف أن هذا المفتاح لفلان، ولا يعرف لماذا دخل، ولا يرى ما فعل. والخطوة التالية هي بوابة الوصول المميز Privileged Access Gateway، وهي Bastion تنهي الجلسة عندها، فتتحقق من هويتك عبر مزود الهوية بالدخول الموحد SSO وMFA، ثم تصدر لك صلاحية مؤقتة أو تأخذ السر من خزنة، وقد تطلب موافقة شخص آخر، ثم تفتح الجلسة إلى السيرفر وتسجلها كاملة. وهذا هو التطبيق العملي لفكرة Zero Trust التي شرحناها في [ما هو VPN؟](https://arabroot.io/articles/%D9%85%D8%A7-%D9%87%D9%88-vpn-%D8%B4%D8%B1%D8%AD-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/#zero-trust)، أي أن كل اتصال يتحقق منه بهوية المستخدم لا بمكانه في الشبكة. والصورة التالية تبين الفكرة، وتحتها المقابل المدار في السحابات:

![مخطط في الأعلى: المدير يدخل من المتصفح أو ssh إلى مزود الهوية بالدخول الموحد وMFA، ثم إلى بوابة فيها شهادة لساعة واحدة وتسجيل للجلسة وموافقة وصلاحية مؤقتة وسجل تدقيق، ومن البوابة إلى Linux SSH وPostgreSQL وWindows RDP دون أي منفذ وارد من الإنترنت. وفي الأسفل ثلاث بطاقات: Google Cloud IAP مع TCP forwarding والسماح للنطاق 35.235.240.0/20 فقط مع دور IAM، وAzure Bastion مع RDP وSSH عبر TLS 443 دون عنوان عام للأجهزة، وAWS Systems Manager Session Manager مع وكيل على الجهاز دون منفذ وارد مفتوح](https://arabroot.io/content/images/2026/10/bastion-jump-05-pam-gateway.webp)

البوابة تعرف المستخدم وتصدر له صلاحية مؤقتة وتسجل الجلسة، والسحابات تقدم المقابل المدار

وأشهر الأدوات مفتوحة المصدر في هذه الفئة أربع، وقد راجعنا تراخيصها بالتفصيل في [الأدوات مفتوحة المصدر للوصول المميز](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%87%D9%88%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-iam-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-%D8%A7%D9%84%D9%85%D9%85%D9%8A%D8%B2-pam/#tools)، وفيما يلي ما يخص موضوعنا منها:

- [**Teleport**](https://goteleport.com/docs/?ref=arabroot.io)**:** منصة وصول بشهادات قصيرة العمر وتسجيل للجلسات تغطي SSH وKubernetes وقواعد البيانات وWindows، والكود المصدري تحت AGPL-3.0، أما نسخة Community Edition الجاهزة فتحت [ترخيص خاص](https://github.com/gravitational/teleport/blob/master/build.assets/LICENSE-community?ref=arabroot.io) يقصرها على المؤسسات الأصغر من حد معين، فاقرأه قبل أن تعتمد عليها.
- [**Warpgate**](https://github.com/warp-tech/warpgate?ref=arabroot.io)**:** بوابة Bastion في ملف تنفيذي واحد تحت Apache-2.0، تمرر SSH وHTTPS وقواعد البيانات وتسجل الجلسات وتدعم OIDC، وهي الأقرب إلى «Bastion يعرف المستخدم» بأقل تعقيد.
- [**JumpServer**](https://github.com/jumpserver/jumpserver?ref=arabroot.io)**:** منصة PAM كاملة بواجهة ويب تحت GPL-3.0، مع مكونات تجارية في الإصدار Enterprise كما يوضح مستودعها، وتناسب من يريد إدارة أصول وأذونات كثيرة ولديه من يشغلها.
- [**Apache Guacamole**](https://guacamole.apache.org/?ref=arabroot.io)**:** بوابة من المتصفح إلى RDP وVNC وSSH تحت Apache-2.0 دون برنامج على جهاز المستخدم، مع [تسجيل الجلسات وإعادة تشغيلها](https://guacamole.apache.org/doc/gug/recording-playback.html?ref=arabroot.io)، وتناسب من يحتاج أساساً إلى سطح مكتب Windows عن بعد.

وسوف نقارن هذه البوابات الثلاث الأولى عملياً في مقال قادم بإذن الله بعنوان «بوابة الوصول المميز للسيرفرات: Teleport أم Warpgate أم JumpServer؟»، أما الصورة الكاملة للوصول المميز وضوابطه فهي في [مقال IAM وPAM](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%87%D9%88%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-iam-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-%D8%A7%D9%84%D9%85%D9%85%D9%8A%D8%B2-pam/).

## ما الذي تطلبه الضوابط الأساسية NCA ECC؟

إذا كانت جهتك ملزمة بالضوابط الأساسية للأمن السيبراني ECC-2:2024 الصادرة عن الهيئة الوطنية للأمن السيبراني، وقد شرحناها في [الضوابط الأساسية NCA ECC بلغة بسيطة](https://arabroot.io/articles/%D8%A7%D9%84%D8%B6%D9%88%D8%A7%D8%A8%D8%B7-%D8%A7%D9%84%D8%A7%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-%D9%84%D9%84%D8%A7%D9%85%D9%86-%D8%A7%D9%84%D8%B3%D9%8A%D8%A8%D8%B1%D8%A7%D9%86%D9%8A-nca-ecc-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9/)، فالضوابط لا تذكر Bastion أو Jump Server بالاسم، ولكن عدداً منها يقود إليه مباشرة، وهذه نصوصها كما في [وثيقة الضوابط](https://nca.gov.sa/ar/regulatory-documents/controls-list/ecc/?ref=arabroot.io):

| الضابط   | ما يطلبه                                                                                                                  | كيف يساعدك ال Bastion أو البوابة                                          |
| -------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| 2-2-3-2  | التحقق متعدد العناصر للدخول عن بعد وللحسابات ذات الصلاحيات الهامة، مع تحديد العناصر بناء على تقييم أثر فشل التحقق وتجاوزه | نقطة واحدة تطبق فيها MFA على كل دخول إداري، بدلاً من ضبطها في كل سيرفر    |
| 2-2-3-4  | إدارة الصلاحيات الهامة والحساسة Privileged Access Management                                                              | حساب لكل شخص، وصلاحيات مؤقتة وشهادات قصيرة العمر، وبوابة تسجل الجلسات     |
| 2-5-3-1  | العزل والتقسيم المادي أو المنطقي لأجزاء الشبكة باستخدام جدار الحماية ومبدأ الدفاع الأمني متعدد المراحل                    | السيرفرات في شبكة خاصة، وال Bastion هو الطريق الوحيد إلى منطقة الإدارة    |
| 2-5-3-5  | تقييد خدمات الشبكة وبروتوكولاتها ومنافذها وإدارتها                                                                        | منفذ إدارة واحد مكشوف بدلاً من منفذ في كل سيرفر، وPermitOpen يحصر الوجهات |
| 2-12-3-2 | تفعيل سجلات الأحداث للحسابات ذات الصلاحيات الهامة ولأحداث الدخول عن بعد                                                   | سجل واحد يجمع كل عمليات الدخول الإداري وبصمات المفاتيح والوجهات           |
| 2-12-3-5 | مدة الاحتفاظ بسجلات الأحداث، على ألا تقل عن 12 شهراً                                                                      | إرسال سجلات ال Bastion والسيرفرات إلى سيرفر مركزي يحفظها المدة المطلوبة   |

ولاحظ أن المدقق لا يكتفي بوجود ال Bastion، وإنما يطلب دليلاً على أن السيرفرات لا تقبل الإدارة إلا منه، مثل قواعد الجدار الناري ومخرج فحص من الخارج، وقد شرحنا شكل هذه الأدلة في [كيف تثبت ذلك للمدقق](https://arabroot.io/articles/%D8%A7%D9%84%D9%85%D8%B9%D9%85%D8%A7%D8%B1%D9%8A%D8%A9-%D9%85%D8%AA%D8%B9%D8%AF%D8%AF%D8%A9-%D8%A7%D9%84%D8%B7%D8%A8%D9%82%D8%A7%D8%AA-tiers-%D9%88-layers/#evidence).

## تجربة عملية: Bastion وسيرفران داخليان في Docker

الآن سوف نبني كل ما سبق على جهازك بثلاثة Containers: ال Bastion باسم `lab-bastion-gw` وهو الوحيد الذي ينشر منفذاً، وعلى العنوان `127.0.0.1:22220` فقط، وسيرفران داخليان `app-01` و`db-01` على شبكة Docker داخلية `--internal` لا تخرج إلى أي مكان ولا تنشر أي منفذ. وتحتاج إلى Docker مع Compose، وإذا لم يكن مثبتاً فانظر [تثبيت Docker على Ubuntu](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-docker-%D8%B9%D9%84%D9%89-ubuntu/)، وإلى عميل OpenSSH على جهازك، وكل الأوامر التالية تعمل من مجلد واحد، ولا تلمس ملفات `~/.ssh` الخاصة بك لأننا نمرر لكل أمر ملف إعداد خاصاً بالتجربة.

### الملفات

نبدأ بملف Dockerfile واحد للسيرفرات الثلاثة، فيه Debian 13 مع `openssh-server` فقط:

```dockerfile
FROM debian:13
RUN apt-get update \
 && apt-get install -y --no-install-recommends openssh-server \
 && rm -rf /var/lib/apt/lists/* \
 && mkdir -p /run/sshd
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["sh", "/entrypoint.sh"]
```

والملف `entrypoint.sh` ينشئ المستخدمين المذكورين في المتغير `SSH_USERS` ويضع لكل منهم مفتاحه العام بالصلاحيات الصحيحة، ثم يشغل sshd:

```bash
#!/bin/sh
# Create each user in $SSH_USERS and install its public key from /keys/<user>.pub
set -e
for u in $SSH_USERS; do
  id "$u" >/dev/null 2>&1 || useradd -m -s /bin/bash "$u"
  install -d -m 700 -o "$u" -g "$u" "/home/$u/.ssh"
  install -m 600 -o "$u" -g "$u" "/keys/$u.pub" "/home/$u/.ssh/authorized_keys"
done
exec /usr/sbin/sshd -D -e
```

وهذا إعداد ال Bastion، وهو قلب التجربة:

```bash
# /etc/ssh/sshd_config.d/bastion.conf on the bastion
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
LogLevel VERBOSE
LogVerbose *:server_request_direct_tcpip():*
# ops has a shell and exists only to show the agent-forwarding risk
AllowUsers jump ops

# jump: a pass-through account for ProxyJump, nothing else
Match User jump
    AllowTcpForwarding local
    PermitOpen app-01:22 db-01:22
    AllowAgentForwarding no
    AllowStreamLocalForwarding no
    X11Forwarding no
    PermitTunnel no
    GatewayPorts no
    PermitTTY no
    ForceCommand /usr/sbin/nologin
```

في الإعداد أعلاه لاحظ التالي:

- الحساب `jump` لا يستطيع فتح Shell بسبب `ForceCommand /usr/sbin/nologin` و`PermitTTY no`، ولكن ProxyJump لا يحتاج إلى Shell أصلاً، لأنه يطلب قناة توجيه لا جلسة.
- `AllowTcpForwarding local` يسمح بالتوجيه من جهة العميل فقط، فلا يستطيع أحد أن يفتح منفذاً عكسياً على ال Bastion بالخيار `-R`.
- `PermitOpen` يحصر الوجهات في المنفذ 22 على السيرفرين. ولاحظ ما يقوله [دليل sshd\_config](https://man.openbsd.org/sshd%5Fconfig?ref=arabroot.io): لا تجري أي مطابقة أنماط ولا أي بحث عن العناوين على الأسماء المكتوبة، أي أن `app-01:22` تسمح بالاسم فقط، ومن يطلب العنوان `10.70.0.11` يرفض، وسوف نرى ذلك بعد قليل.
- `LogVerbose` سطر سوف نشرحه في [قسم السجلات](#lab-logs).
- الحساب `ops` يملك Shell عمداً، ووجوده هنا فقط لنرى خطر Agent Forwarding على Jump Server يدخل إليه المديرون، فلا تضعه على Bastion حقيقي.

وعلى السيرفرين الداخليين إعداد أقصر، أهم ما فيه السطر الأخير الذي يقبل المستخدم `admin` من عنوان ال Bastion فقط:

```bash
# /etc/ssh/sshd_config.d/target.conf on app-01 and db-01
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
LogLevel VERBOSE
AllowUsers admin@10.70.0.10
```

وأخيراً ملف `compose.yaml`، وفيه شبكتان: `lab-bastion-edge` تمثل الإنترنت، و`lab-bastion-mgmt` شبكة داخلية للإدارة:

```yaml
name: lab-bastion
services:
  bastion:
    build: .
    image: lab-bastion-sshd:1
    container_name: lab-bastion-gw
    environment:
      SSH_USERS: "jump ops"
    volumes:
      - ./keys:/keys:ro
      - ./bastion.conf:/etc/ssh/sshd_config.d/bastion.conf:ro
    ports:
      - "127.0.0.1:22220:22"
    networks:
      edge: {}
      mgmt:
        ipv4_address: 10.70.0.10
  app-01:
    image: lab-bastion-sshd:1
    container_name: lab-bastion-app01
    hostname: app-01
    environment:
      SSH_USERS: "admin"
    volumes:
      - ./keys:/keys:ro
      - ./target.conf:/etc/ssh/sshd_config.d/target.conf:ro
    networks:
      mgmt:
        ipv4_address: 10.70.0.11
        aliases: [app-01]
  db-01:
    image: lab-bastion-sshd:1
    container_name: lab-bastion-db01
    hostname: db-01
    environment:
      SSH_USERS: "admin"
    volumes:
      - ./keys:/keys:ro
      - ./target.conf:/etc/ssh/sshd_config.d/target.conf:ro
    networks:
      mgmt:
        ipv4_address: 10.70.0.12
        aliases: [db-01]
networks:
  edge:
    name: lab-bastion-edge
  mgmt:
    name: lab-bastion-mgmt
    internal: true
    ipam:
      config:
        - subnet: 10.70.0.0/24
```

ولاحظ أن ال Bastion وحده على الشبكتين، وأنه وحده ينشر منفذاً، وعلى `127.0.0.1` حتى لا يصل إليه أحد من شبكتك المحلية أثناء التجربة.

### التشغيل

ننشئ مفتاحاً للتجربة باسم `laptop` يمثل حاسوب المدير، ونضع مفتاحه العام للمستخدمين الثلاثة في المجلد `keys` الذي يقرؤه السيرفرات، ولاحظ أن المفتاح الخاص يبقى خارج هذا المجلد، ثم نكتب ملف إعداد عميل خاصاً بالتجربة ونشغل كل شيء:

```bash
ssh-keygen -q -t ed25519 -N '' -C laptop -f laptop
mkdir keys
for u in jump ops admin; do cp laptop.pub keys/$u.pub; done
cat > lab.conf <<'EOF'
Host *
    IdentityFile ./laptop
    IdentitiesOnly yes
    UserKnownHostsFile ./known_hosts
    StrictHostKeyChecking accept-new
    ConnectTimeout 5
EOF
docker compose up -d --build
docker compose ps --format 'table {{.Name}}\t{{.Ports}}'
```

والمخرج سوف يكون كما يلي:

```text
NAME                PORTS
lab-bastion-app01
lab-bastion-db01
lab-bastion-gw      127.0.0.1:22220->22/tcp
```

ثلاثة Containers ومنفذ واحد فقط على جهازك. وقبل أن نتابع، لنتأكد من أن sshd فهم إعدادنا كما نريد، فالأمر `sshd -T` مع الخيار `-C` يطبع الإعداد النهائي لمستخدم وعنوان محددين بعد تطبيق كتل `Match`:

```bash
docker exec lab-bastion-gw sh -c "sshd -T -C user=jump,host=laptop,addr=203.0.113.5 | grep -E '^(permitopen|allowtcpforwarding|allowagentforwarding|permittty|forcecommand) '"
```

والمخرج سوف يكون كما يلي:

```text
permittty no
allowtcpforwarding local
allowagentforwarding no
forcecommand /usr/sbin/nologin
permitopen app-01:22 db-01:22
```

وهذا الأمر مفيد جداً على أي سيرفر حقيقي قبل أن تعيد تشغيل sshd، لأنه يريك ما سوف يطبق فعلاً لا ما تظن أنك كتبته. ولنتأكد أيضاً من أن ال Bastion لا يحمل أدوات:

```bash
docker exec lab-bastion-gw sh -c 'which curl wget python3 nc gcc || echo "none found"'
```

والمخرج سوف يكون كما يلي:

```text
none found
```

### الدخول المباشر يفشل

جهازك المضيف ليس مثالاً جيداً للإنترنت، لأنه هو الذي يشغل شبكات Docker، لذلك نحاول الوصول إلى app-01 من Container مؤقت على شبكة `lab-bastion-edge` التي تمثل الإنترنت، مرة بالعنوان ومرة بالاسم:

```bash
docker run --rm --network lab-bastion-edge --entrypoint ssh lab-bastion-sshd:1 -o ConnectTimeout=5 admin@10.70.0.11 hostname
docker run --rm --network lab-bastion-edge --entrypoint ssh lab-bastion-sshd:1 -o ConnectTimeout=5 admin@app-01 hostname
```

والمخرج سوف يكون كما يلي:

```text
ssh: connect to host 10.70.0.11 port 22: Connection timed out
ssh: Could not resolve hostname app-01: No address associated with hostname
```

لا يوجد طريق إلى الشبكة الداخلية، ولا يعرف من في الخارج حتى أسماء السيرفرات. وماذا لو حاول أحد أن يفتح Shell على ال Bastion بالحساب `jump`؟

```bash
ssh -F lab.conf -T -p 22220 jump@127.0.0.1
```

والمخرج سوف يكون كما يلي:

```text
This account is currently not available.
```

المفتاح صحيح والدخول نجح، ولكن `ForceCommand` أنهى الجلسة فوراً، فهذا الحساب لا يصلح إلا للمرور.

### المرور عبر ال Bastion بالخيار -J

الآن نصل إلى app-01 عبر ال Bastion، ونطلب منه أن يطبع اسمه والمتغير `SSH_CONNECTION` الذي يبين من أين جاء الاتصال:

```bash
ssh -F lab.conf -J jump@127.0.0.1:22220 admin@app-01 'hostname; echo $SSH_CONNECTION'
```

والمخرج سوف يكون كما يلي:

```text
Warning: Permanently added 'app-01' (ED25519) to the list of known hosts.
app-01
10.70.0.10 33668 10.70.0.11 22
```

لاحظ أن ssh سجل مفتاح السيرفر باسم `app-01` في ملف `known_hosts` على جهازك، أي أن التحقق من هوية السيرفر الداخلي يحدث على جهازك لا على ال Bastion، ولاحظ أن app-01 يرى الاتصال قادماً من `10.70.0.10` وهو عنوان ال Bastion، وهذا ما يجعل السطر `AllowUsers admin@10.70.0.10` يعمل. ولاحظ أيضاً أن الاسم `app-01` حله ال Bastion لا جهازك، فجهازك لا يعرف هذا الاسم أصلاً.

### ملف الإعداد: ProxyJump في \~/.ssh/config

كتابة `-J` مع كل أمر متعبة، والطريقة اليومية أن تضع الإعداد في ملف الإعداد. نضيف في بداية `lab.conf` الأسطر التالية، وفي عملك الحقيقي تضعها في `~/.ssh/config` مع عنوان ال Bastion الحقيقي:

```bash
Host bastion
    HostName 127.0.0.1
    Port 22220
    User jump

Host app-01 db-01
    User admin
    ProxyJump bastion
```

ولنسأل ssh عن الإعداد الذي سوف يطبقه على db-01، فالخيار `-G` يطبعه دون أن يتصل:

```bash
ssh -F lab.conf -G db-01 | grep -E '^(user|hostname|port|proxyjump|forwardagent) '
```

والمخرج سوف يكون كما يلي:

```text
user admin
hostname db-01
port 22
forwardagent no
proxyjump bastion
```

والآن يكفي الاسم وحده، ويعمل `scp` بالطريقة نفسها لأنه يقرأ الملف نفسه:

```bash
ssh -F lab.conf app-01 hostname
ssh -F lab.conf db-01 hostname
echo "backup-2026-10-08" > note.txt
scp -F lab.conf note.txt db-01:/tmp/ && ssh -F lab.conf db-01 cat /tmp/note.txt
```

والمخرج سوف يكون كما يلي:

```text
app-01
Warning: Permanently added 'db-01' (ED25519) to the list of known hosts.
db-01
backup-2026-10-08
```

وإذا أردت أن ترى ما يحدث في الداخل، فشغل الأمر مع `-v` واختر الأسطر المهمة:

```bash
ssh -v -F lab.conf app-01 true 2>&1 | grep -E 'Setting implicit ProxyCommand|Executing proxy|Authenticated to|channel_connect_stdio_fwd'
```

والمخرج سوف يكون كما يلي:

```text
debug1: Setting implicit ProxyCommand from ProxyJump: ssh -F lab.conf -v -W '[%h]:%p' bastion
debug1: Executing proxy command: exec ssh -F lab.conf -v -W '[app-01]:22' bastion
Authenticated to 127.0.0.1 ([127.0.0.1]:22220) using "publickey".
debug1: channel_connect_stdio_fwd: app-01:22
Authenticated to app-01 (via proxy) using "publickey".
```

في المخرج أعلاه لاحظ التالي:

- ProxyJump في الحقيقة يشغل ssh ثانياً بالخيار `-W '[app-01]:22'`، وهو الخيار الذي يربط مدخل البرنامج ومخرجه بقناة إلى الوجهة، وهذا ما كان الناس يكتبونه بأيديهم في `ProxyCommand` قبل ظهور ProxyJump.
- هناك مصادقتان منفصلتان، الأولى مع ال Bastion والثانية مع app-01 «via proxy»، وكلتاهما بمفتاحك الذي لم يغادر جهازك.

### نكسر القيود: وجهات غير مسموحة

ماذا يحدث إذا طلب أحدهم السيرفر بعنوانه بدلاً من اسمه، أو حاول أن يصل عبر ال Bastion إلى منفذ آخر مثل 80؟

```bash
ssh -F lab.conf -J jump@127.0.0.1:22220 admin@10.70.0.11 hostname
ssh -F lab.conf -p 22220 -W app-01:80 jump@127.0.0.1 </dev/null
```

والمخرج سوف يكون كما يلي:

```text
channel 0: open failed: administratively prohibited: open failed
stdio forwarding failed
Connection closed by UNKNOWN port 65535
channel 0: open failed: administratively prohibited: open failed
stdio forwarding failed
```

الرسالة `administratively prohibited` تعني أن sshd على ال Bastion رفض فتح القناة بسبب الإعداد، وهي الرسالة التي سوف تراها إذا نسيت إضافة سيرفر جديد إلى `PermitOpen`. ولاحظ أن الطلب بالعنوان رفض مع أنه يشير إلى السيرفر نفسه المسموح باسمه، والسبب كما ذكرنا أن `PermitOpen` يقارن النص كما هو، فإما أن تكتب الاسم والعنوان معاً في القائمة، أو أن تتفق مع فريقك على الأسماء فقط.

### ماذا تسجل ال Bastion؟

مع `LogLevel VERBOSE` يسجل sshd بصمة المفتاح لكل دخول، ويسجل الطلبات المرفوضة مع وجهتها، ولكنه لا يسجل الوجهات المسموحة، فهذه الرسالة في كود OpenSSH من مستوى debug. لذلك أضفنا السطر `LogVerbose *:server_request_direct_tcpip():*` الذي يرفع رسائل هذه الدالة وحدها إلى السجل، مع العلم أن [دليل sshd\_config](https://man.openbsd.org/sshd%5Fconfig?ref=arabroot.io) يصف `LogVerbose` بأنه مخصص لتتبع الأخطاء، فاختبره بعد كل ترقية لأن اسم الدالة قد يتغير. وهذا مقتطف من سجل ال Bastion بعد الأوامر السابقة:

```bash
docker logs lab-bastion-gw 2>&1 | grep -E 'Accepted publickey|direct_tcpip|denied'
```

```text
Accepted publickey for jump from 192.168.48.1 port 58118 ssh2: ED25519 SHA256:jWZY5H6ljOihK+THu6nSnZhCeOCsV/znAU99tVPsB0c
debug1: serverloop.c:server_request_direct_tcpip():424 (bin=sshd-session, pid=120): originator 127.0.0.1 port 65535, target app-01 port 22
Accepted publickey for jump from 192.168.48.1 port 58126 ssh2: ED25519 SHA256:jWZY5H6ljOihK+THu6nSnZhCeOCsV/znAU99tVPsB0c
debug1: serverloop.c:server_request_direct_tcpip():424 (bin=sshd-session, pid=128): originator 127.0.0.1 port 65535, target 10.70.0.11 port 22
Received request from 192.168.48.1 port 58126 to connect to host 10.70.0.11 port 22, but the request was denied.
```

وعلى app-01 يظهر الدخول نفسه قادماً من ال Bastion وبالبصمة نفسها:

```bash
docker logs lab-bastion-app01 2>&1 | grep 'Accepted publickey'
```

```text
Accepted publickey for admin from 10.70.0.10 port 37582 ssh2: ED25519 SHA256:jWZY5H6ljOihK+THu6nSnZhCeOCsV/znAU99tVPsB0c
```

في السجلات أعلاه لاحظ التالي:

- بصمة المفتاح `SHA256:jWZY…` هي التي تربط الدخول إلى ال Bastion بالدخول إلى app-01، ولذلك يجب أن يكون لكل شخص مفتاحه الخاص، فالمفتاح المشترك بين الفريق يجعل هذا السجل بلا قيمة.
- العنوان `192.168.48.1` هو بوابة شبكة Docker في جهازنا، وعلى Bastion حقيقي سوف ترى العنوان العام للمستخدم.
- لا يوجد في أي من السجلين أمر واحد مما كتبناه على app-01، وهذا ما ذكرناه في التحذير السابق، فتسجيل الأوامر يحدث على السيرفر الداخلي أو في بوابة تنهي الجلسة.
- هذه السجلات داخل ال Containers فقط، وفي الإنتاج ترسلها إلى سيرفر مركزي، وقد شرحنا ما يسجل وكيف يحفظ في [سجل التدقيق Audit Trail](https://arabroot.io/articles/%D8%B3%D8%AC%D9%84-%D8%A7%D9%84%D8%AA%D8%AF%D9%82%D9%8A%D9%82-audit-trail-%D9%85%D9%86-%D9%81%D8%B9%D9%84-%D9%85%D8%A7%D8%B0%D8%A7-%D9%88%D9%85%D8%AA%D9%89/).

### خطر Agent Forwarding بمخرج حقيقي

الآن نرى ما وصفه دليل ssh. نشغل ssh-agent جديداً خاصاً بالتجربة ونحمل فيه المفتاح، ثم ندخل إلى ال Bastion بالحساب `ops` مع `-A` كما يفعل كثير من المديرين على Jump Server، ونبقي الجلسة مفتوحة عشرين ثانية:

```bash
eval "$(ssh-agent -s)" >/dev/null
ssh-add laptop
ssh -F lab.conf -A -p 22220 ops@127.0.0.1 'echo "ops session: $SSH_AUTH_SOCK"; sleep 20' &
```

والمخرج سوف يكون كما يلي:

```text
Identity added: laptop (laptop)
ops session: /tmp/ssh-7mFd8bZyun/agent.136
```

وأثناء الجلسة نلعب دور مخترق وصل إلى root على ال Bastion، وهذا ما يمثله `docker exec` هنا، فيبحث عن ملفات ال agent ثم يستخدمها ليدخل إلى db-01:

```bash
docker exec lab-bastion-gw sh -c 'ls -l /tmp/ssh-*/agent.*'
docker exec lab-bastion-gw sh -c 'export SSH_AUTH_SOCK=$(ls /tmp/ssh-*/agent.*); ssh-add -l; ssh -o StrictHostKeyChecking=accept-new admin@db-01 "hostname; id -un"'
```

والمخرج سوف يكون كما يلي:

```text
srwxrwxr-x 1 ops ops 0 Oct  8 09:45 /tmp/ssh-7mFd8bZyun/agent.136
256 SHA256:jWZY5H6ljOihK+THu6nSnZhCeOCsV/znAU99tVPsB0c laptop (ED25519)
Warning: Permanently added 'db-01' (ED25519) to the list of known hosts.
db-01
admin
```

root على ال Bastion لا يملك مفتاحنا، ولم يقرأه من أي ملف، ومع ذلك دخل إلى db-01 باسم `admin`، لأن ال agent على جهازنا وقع له طلب الدخول عبر الاتصال المعاد توجيهه، وسجل db-01 سوف يظهر هذا الدخول ببصمة مفتاحنا نحن. والآن نكرر الشيء نفسه مع ProxyJump، فندخل إلى app-01 عبر ال Bastion ونبحث أثناء الجلسة عن الملفات نفسها:

```bash
ssh -F lab.conf app-01 'sleep 15' &
docker exec lab-bastion-gw sh -c 'ls -l /tmp/ssh-*/agent.*'
```

والمخرج سوف يكون كما يلي:

```text
ls: cannot access '/tmp/ssh-*/agent.*': No such file or directory
```

لا يوجد ما يستخدمه المخترق على ال Bastion، لأن ProxyJump لا يعيد توجيه ال agent إلى ال Bastion أصلاً، وال Bastion ينقل بيانات مشفرة لا يفهمها. وبعد ذلك أوقف ال agent الخاص بالتجربة بالأمر `ssh-agent -k`.

### التنظيف

نحذف ال Containers والشبكتين بالأمر `down`، ثم ال Image التي بنيناها، ثم ملفات التجربة:

```bash
docker compose down
docker image rm lab-bastion-sshd:1
rm -f laptop laptop.pub known_hosts note.txt lab.conf
rm -rf keys
```

## أي حل يناسبك؟

| حالتك                                             | الحل الأنسب                                                | والسبب                                               |
| ------------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------- |
| سيرفر أو اثنان على VPS، وتديرهما وحدك             | SSH بالمفاتيح مع جدار حماية، أو VPN صغير                   | ال Bastion هنا سيرفر إضافي تحميه دون فائدة كبيرة     |
| عدة سيرفرات Linux وفريق صغير                      | Bastion مع ProxyJump وحساب لكل شخص وشهادات قصيرة العمر     | باب واحد بسيط، ولا يحتاج إلى برنامج على أجهزة الفريق |
| كل السيرفرات عند مزود سحابي كبير                  | Session Manager أو Azure Bastion أو IAP                    | لا تدير سيرفراً، والصلاحيات من IAM الذي تديره أصلاً  |
| خوادم Windows                                     | RD Gateway أو Guacamole أو Azure Bastion، وليس RDP مكشوفاً | RDP لا يصلح للإنترنت مباشرة                          |
| جهة ملزمة بتسجيل الجلسات والموافقات، أو فريق كبير | بوابة وصول مميز مثل Teleport أو Warpgate أو JumpServer     | تعرف المستخدم وتسجل الجلسة وتصدر صلاحيات مؤقتة       |

## أخطاء شائعة

- **Bastion وما زالت السيرفرات مكشوفة:** يبنى ال Bastion ثم يبقى المنفذ 22 مفتوحاً على السيرفرات «احتياطاً»، فيصبح لديك ستة أبواب بدل خمسة. أغلق المنافذ العامة وتحقق من الخارج.
- **مفاتيح خاصة على ال Bastion:** مفتاح فريق محفوظ عليه حتى يدخل منه الجميع إلى السيرفرات، وهو أول ما سوف يأخذه من يصل إليه. استخدم ProxyJump حتى تبقى المفاتيح على أجهزة أصحابها.
- **ForwardAgent yes في `Host *`:** يعيد توجيه ال agent إلى كل سيرفر تدخل إليه، ومنها ال Bastion، وقد رأيت النتيجة في التجربة.
- **حساب مشترك:** حساب `jump` واحد بمفتاح واحد يستخدمه الفريق كله، فلا تعرف من دخل. الحساب قد يكون مشتركاً، ولكن المفتاح أو الشهادة لكل شخص، أو حساب لكل شخص.
- **ال Bastion يتحول إلى سيرفر أدوات:** يثبت عليه أحدهم عميل قاعدة البيانات «مؤقتاً»، ثم سكربتات النسخ الاحتياطي، ثم يصبح Jump Server بكل مخاطره. راجع الحزم دورياً.
- **السجلات على ال Bastion وحده:** من يصل إلى root يحذفها، والضوابط تطلب حفظها 12 شهراً على الأقل، فأرسلها إلى سيرفر مركزي.
- **Bastion واحد بلا بديل:** إذا توقف لا يستطيع أحد إصلاح السيرفرات، فجهز طريق طوارئ موثقاً ومراقباً.

## الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

- كل سيرفر يفتح منفذ الإدارة للإنترنت باب يحتاج إلى تحديث ومراقبة، والحل أن يبقى باب واحد مقوى والسيرفرات خلفه دون منافذ عامة.
- Bastion Host بتعريف NIST حاسوب صمم ليصمد أمام الهجمات، ويقف على الحافة ويمرر الاتصال، أما Jump Server فيعمل عليه المدير داخل منطقة إدارة، والاسمان يستخدمان كثيراً للشيء نفسه، فاسأل هل تمر عبره أم تعمل عليه.
- استخدم `ssh -J` و`ProxyJump` في `~/.ssh/config`، فالجلسة مشفرة من جهازك إلى السيرفر الداخلي والمفتاح لا يغادر جهازك، ولا تفعل Agent Forwarding إلى ال Bastion لأن root عليه يستطيع أن يستخدم مفتاحك ما دمت متصلاً.
- قو ال Bastion بالمفاتيح فقط وMFA، وحساب دون Shell مع `PermitOpen` بأسماء الوجهات، وأقل عدد من الحزم، وسجلات ترسل إلى خارجه، وشهادات قصيرة العمر.
- ال Bastion عبر ProxyJump يعرف من دخل وإلى أين، ولا يرى الأوامر، فإذا احتجت تسجيل الجلسات فسجلها على السيرفرات أو استخدم بوابة وصول مميز.
- في السحابة استخدم Session Manager أو Azure Bastion أو IAP، ولخوادم Windows استخدم RD Gateway أو Guacamole بدلاً من RDP مكشوف.
- الضوابط 2-2-3-2 و2-2-3-4 و2-5-3-1 و2-5-3-5 و2-12-3-2 في NCA ECC تقودك إلى هذا التصميم، والمدقق يطلب دليلاً على أن السيرفرات لا تقبل الإدارة إلا من الباب الواحد.

[![](https://arabroot.io/content/images/2026/10/iam-pam-cover-cover.webp)دليلإدارة الهوية والوصول IAM والوصول المميز PAMمن يملك صلاحية root على سيرفراتك ومنذ متى، وكيف تضبط حسابات المديرين بصلاحيات مؤقتة وجلسات مسجلة.](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%87%D9%88%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-iam-%D9%88%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-%D8%A7%D9%84%D9%85%D9%85%D9%8A%D8%B2-pam/)[![](https://arabroot.io/content/images/2026/10/secure-vps-cover-cover-2.webp)دليلتأمين سيرفر VPS على Ubuntu من أول دخولقبل أن تثبت أي تطبيق على سيرفرك الجديد، هذه الخطوات تغلق أبرز الثغرات وأولها الدخول بمفتاح SSH بدل كلمة المرور.](https://arabroot.io/articles/%D8%AA%D8%A3%D9%85%D9%8A%D9%86-%D8%AE%D8%A7%D8%AF%D9%85-vps-%D9%85%D9%86-%D8%A3%D9%88%D9%84-%D8%AF%D8%AE%D9%88%D9%84/)[![](https://arabroot.io/content/images/2026/10/tunnels-cover-cover.webp)دليلما هو النفق Tunnel في الشبكات؟ ومتى تحتاج إليهكيف تصل إلى قاعدة بيانات لا تراها من الإنترنت، وتنشر خدمة من خلف CGNAT دون فتح منافذ، ومتى تحتاج إلى VPN بدل النفق.](https://arabroot.io/articles/%D9%85%D8%A7-%D9%87%D9%88-%D8%A7%D9%84%D9%86%D9%81%D9%82-tunnel-%D9%81%D9%8A-%D8%A7%D9%84%D8%B4%D8%A8%D9%83%D8%A7%D8%AA/)[![](https://arabroot.io/content/images/2026/10/vpn-basics-cover-cover.webp)دليلما هو VPN؟ الشبكة الخاصة الافتراضية من المشكلة إلى الأنواعلماذا تحتاج شبكة خاصة افتراضية VPN، وكيف تغلف حزمك وتشفرها داخل نفق، وأي نوع منها يناسب فريقك.](https://arabroot.io/articles/%D9%85%D8%A7-%D9%87%D9%88-vpn-%D8%B4%D8%B1%D8%AD-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/)[![](https://arabroot.io/content/images/2026/10/network-segmentation-cover-cover.webp)دليلتقسيم الشبكة Network Segmentation بال VLAN وال VPCلماذا تصل كاميرا مخترقة إلى قاعدة بياناتك، وكيف تمنع ذلك بتقسيم الشبكة إلى مناطق لا يمر بينها إلا ما تسمح به.](https://arabroot.io/articles/%D8%AA%D9%82%D8%B3%D9%8A%D9%85-%D8%A7%D9%84%D8%B4%D8%A8%D9%83%D8%A9-network-segmentation-vlan-%D9%88-vpc/)[![](https://arabroot.io/content/images/2026/10/nca-ecc-cover-cover.webp)دليلالضوابط الأساسية للأمن السيبراني NCA ECC بلغة بسيطةكيف تقرأ الضوابط الأساسية ECC دون أن تضيع في أرقامها، وعلى من تنطبق، وما المطلوب من جهتك فعلاً في كل مكون.](https://arabroot.io/articles/%D8%A7%D9%84%D8%B6%D9%88%D8%A7%D8%A8%D8%B7-%D8%A7%D9%84%D8%A7%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-%D9%84%D9%84%D8%A7%D9%85%D9%86-%D8%A7%D9%84%D8%B3%D9%8A%D8%A8%D8%B1%D8%A7%D9%86%D9%8A-nca-ecc-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9/)

## سجل التحديثات

- أكتوبر 2026: كتابة المقال، وتنفيذ التجربة العملية بثلاثة Containers على Debian 13.7 مع OpenSSH 10.0p2، وعميل OpenSSH 9.9p1، وDocker Engine 29.8.0 مع Docker Compose v5.5.1.