جدران الحماية وأمن الشبكات

Docker على خادم VPS: لماذا تتجاوز المنافذ المنشورة ufw وكيف تؤمّن المنافذ والمقبس وواجهة API

المنافذ التي ينشرها Docker تتجاوز قواعد ufw، ومجموعة docker تعادل صلاحيات الجذر. اربط بالعنوان 127.0.0.1 واستخدم DOCKER-USER واحمِ المقبس.

تاريخ النشر
مدة القراءة
6 دقائق
الكاتب
SKYLINE Engineering

يسهّل Docker تشغيل قاعدة بيانات وذاكرة تخزين مؤقت وتطبيق ويب على خادم VPS واحد، لكنه يحمل معه ثلاث مفاجآت أمنية يقع فيها كثير من الفرق: فالمنافذ التي تنشرها قد تكون متاحة من الإنترنت حتى لو أظهر ufw أنها مغلقة، وكل من يستطيع التخاطب مع خدمة Docker يملك فعلياً صلاحيات الجذر على المضيف، وواجهة API الخاصة بالخدمة يجب ألا تُكشف دون حماية. يشرح هذا الدليل كل مشكلة منها مع الحلول التي يوصي بها توثيق Docker نفسه.

لماذا تتجاوز المنافذ المنشورة ufw وfirewalld

ينشئ Docker قواعد جدار حماية خاصة به لتنفيذ نشر المنافذ. ويوضح توثيق تصفية الحزم أن الحركة الموجهة إلى منفذ حاوية منشور يُعاد توجيهها في جدول nat قبل أن تصل إلى السلسلتين INPUT وOUTPUT اللتين يستخدمهما ufw، فتُتجاهل إعدادات جدار الحماية فعلياً. وتكرر أدلة التثبيت على Debian وUbuntu التحذير نفسه: مع ufw أو firewalld تتجاوز منافذ الحاويات المكشوفة قواعدَ جدار الحماية. كما يذكر Docker أن القواعد المنشأة مباشرة بالأمر nft غير مدعومة على مضيف مثبّت عليه Docker.

وصفحة نشر المنافذ صريحة في أن نشر منافذ الحاويات غير آمن افتراضياً؛ فدون تحديد عنوان للمضيف ينشر الخيار -p 8080:80 المنفذ على جميع عناوين المضيف في IPv4 وIPv6.

الحل الأول: لا تنشر إلا ما يجب أن يكون عاماً

تستطيع الحاويات الموجودة على الشبكة نفسها المعرّفة من المستخدم الوصول إلى بعضها باسم الخدمة دون نشر أي منفذ. انشر الوكيل العكسي فقط (80/443)، واربط كل ما تحتاجه من المضيف نفسه بعنوان loopback، مثل قاعدة بيانات يصل إليها سكربت النسخ الاحتياطي أو لوحة إدارة تصل إليها عبر نفق SSH:

# docker run
docker run -d -p 127.0.0.1:8080:80 nginx

# docker compose
services:
  db:
    image: postgres:16
    ports:
      - "127.0.0.1:5432:5432"

ثم تحقق مما يستمع فعلاً على العناوين العامة:

docker ps --format '{{.Names}}  {{.Ports}}'
sudo ss -tlnp

أي مدخل يبدأ بـ 0.0.0.0: أو [::]: في عمود Ports يمكن الوصول إليه من الخارج ما لم يحجبه شيء أمام الخادم.

الحل الثاني: غيّر عنوان الربط الافتراضي

لجعل loopback هو الافتراضي عندما لا يُحدَّد عنوان للمضيف، يوثّق Docker إعدادين في الملف /etc/docker/daemon.json: الإعداد "ip" لشبكة bridge الافتراضية، والإعداد default-network-opts لشبكات bridge المعرّفة من المستخدم مثل تلك التي ينشئها Compose:

{
  "ip": "127.0.0.1",
  "default-network-opts": {
    "bridge": {
      "com.docker.network.bridge.host_binding_ipv4": "127.0.0.1"
    }
  }
}

sudo systemctl restart docker

تحتفظ الحاويات الحالية بعناوين ربطها القديمة إلى أن يُعاد إنشاؤها. ويحذّر Docker أيضاً من أن الأجهزة الموجودة في مقطع الشبكة نفسه من الطبقة الثانية كانت تستطيع، في الإصدارات الأقدم من 28.0.0، الوصول إلى المنافذ المنشورة على localhost؛ لذا افحص الإصدار بالأمر docker version ولا تعتمد على الربط بـ loopback وحده في الإصدارات القديمة.

الحل الثالث: صفِّ المنافذ المنشورة في DOCKER-USER

عندما يجب نشر منفذ مع السماح لمصادر محددة فقط بالوصول إليه، تشير صفحة iptables في توثيق Docker إلى السلسلة DOCKER-USER التي تُعالَج قبل قواعد Docker نفسها. ويحجب مثالها الحركة من كل المصادر عدا شبكة واحدة على الواجهة الخارجية:

sudo iptables -I DOCKER-USER -i ext_if ! -s 192.0.2.0/24 -j DROP
sudo iptables -I DOCKER-USER -m state --state RELATED,ESTABLISHED -j ACCEPT

استبدل ext_if باسم واجهتك العامة (راجع ip -br addr). ولأن الخيار -I يُدرج القاعدة في أعلى السلسلة، فإن تنفيذ الأمرين بهذا الترتيب يضع قاعدة ESTABLISHED فوق قاعدة DROP، فتمر الردود على الاتصالات الصادرة من الحاويات. والحزم في هذه السلسلة تكون قد تُرجمت مسبقاً إلى عنوان الحاوية ومنفذها، ولمطابقة الوجهة الأصلية يوصي Docker بخيارَي conntrack وهما --ctorigdst و--ctorigdstport. والقواعد المضافة بالأمر iptables لا تبقى بعد إعادة التشغيل ما لم تحفظها، مثلاً بحزمة iptables-persistent في Debian.

قدّم Docker في الإصدار 29.0.0 واجهة nftables تجريبية ("firewall-backend": "nftables") لا تحتوي على سلسلة DOCKER-USER ولا تعمل في وضع Swarm، فاقرأ ملاحظات الانتقال قبل التحويل.

جدار الحماية أمام الخادم

جدار الحماية السحابي الذي يصفّي الحركة قبل وصولها إلى الخادم لا يتأثر بقواعد Docker على المضيف. وفي خوادم VPS من Skyline Cloud في الرياض يُطبَّق جدار الحماية الذي تديره من لوحة التحكم خارج الخادم (نظرة عامة على VPS). اسمح فيه بالمنافذ 22 و80 و443 فقط، فيبقى منفذ قاعدة البيانات المنشور خطأً بعيداً عن متناول الإنترنت.

مجموعة docker تعني صلاحيات الجذر

ينبّه دليل ما بعد التثبيت إلى أن مجموعة docker تمنح صلاحيات بمستوى الجذر. ويشرح ملخص الأمان السبب: من يتحكم في الخدمة يستطيع تشغيل حاوية يُركَّب فيها المجلد / الخاص بالمضيف وتعديل نظام ملفاته دون قيود. وعملياً:

  • لا تضف إلى مجموعة docker إلا المسؤولين الموثوقين، وراجعها بالأمر getent group docker.
  • تعامل مع أي حاوية تُركّب /var/run/docker.sock (وهو شائع في لوحات التحكم والوكلاء ووكلاء التكامل المستمر) على أنها تملك صلاحيات الجذر على المضيف.
  • لا تكشف واجهة API الخاصة بالخدمة على منفذ TCP دون TLS أبداً. يرفض Docker العمل بمقبس TCP عبر HTTP عادي دون مصادقة، ويوصي بأن تكون الواجهة متاحة فقط من شبكة موثوقة أو VPN. وللإدارة عن بُعد يستخدم DOCKER_HOST=ssh://user@host بروتوكول SSH بدلاً من ذلك.

الوضع دون صلاحيات الجذر (Rootless)

يشغّل وضع Rootless الخدمة والحاويات معاً بصفة مستخدم عادي داخل مساحة أسماء للمستخدمين، مما يحدّ من الضرر الذي قد تسببه ثغرة في الخدمة أو في بيئة التشغيل. ويحتاج إلى الحزمة uidmap، وإلى ما لا يقل عن 65,536 معرّفاً فرعياً للمستخدم والمجموعة في /etc/subuid و/etc/subgid:

sudo apt install uidmap
# as the non-root user:
dockerd-rootless-setuptool.sh install
systemctl --user start docker.service
sudo loginctl enable-linger $USER   # start at boot

تحتاج المنافذ الأقل من 1024 إلى إعداد إضافي، إما صلاحية خاصة على rootlesskit أو ضبط net.ipv4.ip_unprivileged_port_start، كما تشرح نصائح Docker لهذا الوضع. واختبر أحمال عملك أولاً، فبعض الميزات تعمل بشكل مختلف.

ما الذي ينبغي فعله

  • شغّل docker ps وss -tlnp على كل مضيف Docker، وأزل أي منفذ منشور لا يحتاج إلى أن يكون عاماً.
  • اربط الخدمات الداخلية بالعنوان 127.0.0.1، واضبط عنوان الربط الافتراضي في daemon.json.
  • استخدم قواعد DOCKER-USER لا ufw لتقييد من يصل إلى المنافذ المنشورة، واجعلها دائمة.
  • أبقِ جدار حماية سحابياً أمام الخادم لا يسمح إلا بالمنافذ التي تقصد تقديمها.
  • راجع مجموعة docker وكل حاوية تركّب مقبس Docker، وفكّر في وضع Rootless للنشرات الجديدة.

المصادر

SKYLINE Engineering

@skyline

The engineering team at SKYLINE Industrial Solutions. We publish field-tested guides drawn from real KSA and GCC deployments.

صفحة الكاتب
SKYLINE engineering services

Need this implemented for you?

Reading is free — building it right takes a team. SKYLINE engineers ship Firewalls & Network Security for Aramco vendors, banks, hospitals and government agencies across Saudi Arabia. Talk to us before you start.

Aramco Approved Contractor ISO 9001 · ISO 27001 SAMA CSF aligned NCA ECC ready 247+ KSA clients

Comments

0 total · 0 threads
Be the first to leave a comment.