Moby: تتجاوز شبكة Docker جدار الحماية ، ولا يوجد خيار للتعطيل

تم إنشاؤها على ١٤ أبريل ٢٠١٦  ·  114تعليقات  ·  مصدر: moby/moby

ناتج docker version :

Client:
 Version:      1.10.3
 API version:  1.22
 Go version:   go1.5.3
 Git commit:   20f81dd
 Built:        Thu Mar 10 15:54:52 2016
 OS/Arch:      linux/amd64

Server:
 Version:      1.10.3
 API version:  1.22
 Go version:   go1.5.3
 Git commit:   20f81dd
 Built:        Thu Mar 10 15:54:52 2016
 OS/Arch:      linux/amd64

ناتج docker info :

Containers: 14
 Running: 5
 Paused: 0
 Stopped: 9
Images: 152
Server Version: 1.10.3
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 204
 Dirperm1 Supported: false
Execution Driver: native-0.2
Logging Driver: json-file
Plugins: 
 Volume: local
 Network: bridge null host
Kernel Version: 3.13.0-58-generic
Operating System: Ubuntu 14.04.4 LTS
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 7.793 GiB
Name: brm-pheonix-dev
ID: Y6Z4:6D53:RFOL:Z3CM:P7ZK:H6HL:RLV5:JT73:LZMC:DTBD:7ILK:2RS5
Username: benjamenmeyer
Registry: https://index.docker.io/v1/

تفاصيل إضافية عن البيئة (AWS و VirtualBox والمادية وما إلى ذلك):
Rackspace Cloud Server ، Ubuntu 14.04 ، لكن هذا لا ينبغي أن يكون مهمًا حقًا

خطوات إعادة إظهار المشكلة:

  1. قم بإعداد النظام بجدار حماية مغلق
  2. قم بإنشاء مجموعة من حاويات الرصيف ذات المنافذ المكشوفة
  3. تحقق من جدار الحماية ؛ سوف عامل الميناء باستخدام "أي مكان" كمصدر ، وبالتالي تكون جميع الحاويات مكشوفة للجمهور.

صِف النتائج التي تلقيتها:
root @ brm-pheonix-dev : ~ / rse # iptables --list DOCKER
Chain DOCKER (1 مراجع)
الهدف حماية وجهة المصدر
قبول tcp - في أي مكان 172.17.0.2 tcp dpt: 6379

صِف النتائج التي توقعتها:
root @ brm-pheonix-dev : ~ / rse # iptables --list DOCKER
Chain DOCKER (1 مراجع)
الهدف حماية وجهة المصدر
قبول tcp - 127.0.0.0/24 172.17.0.2 tcp dpt: 6379
قبول tcp - 172.16.0.0/16 172.17.0.2 tcp dpt: 6379

معلومات إضافية تعتبرها مهمة (على سبيل المثال ، تحدث المشكلة من حين لآخر فقط):

بشكل افتراضي ، يقوم عامل الإرساء بتدوير جدار الحماية بطريقة تكسر الأمان - فهو يسمح لكل حركة المرور من جميع أجهزة الشبكة بالوصول إلى المنافذ المكشوفة على الحاويات. ضع في اعتبارك موقعًا يحتوي على حاويتين: تعرض الحاوية A 443 Nginx قيد التشغيل ، وتقوم الحاوية B بتشغيل واجهة برمجة تطبيقات على المنفذ 8000. من المستحسن فتح الحاوية A للجمهور للاستخدام ، ولكن إخفاء الحاوية B تمامًا حتى تتمكن من التحدث إلى المضيف المحلي فقط (للاختبار من قبل المستخدم) وشبكة الرصيف (للتحدث إلى الحاوية أ). قد يكون من المرغوب أيضًا لأغراض الاختبار أن تكون الحاوية C قاعدة بيانات مستخدمة بواسطة الحاوية B مع نفس النوع من القيود.

لقد وجدت هذا بسبب مراقبة السجلات على خدمة اعتقدت أنها لم تكن مفتوحة للجمهور. بعد العثور على إدخالات السجل من المصادر التي تحاول الاختراق ، راجعت قواعد جدار الحماية ووجدت أنه لا يوجد حد لعناوين المصدر أو الواجهات. أنا أستخدم UFW وأسمح لـ SSH فقط بالدخول إلى هذا المربع المعين ، وأفضّل الاحتفاظ به على هذا النحو. يمكن أن يؤثر هذا بشكل كبير على استخدام حاويات Docker لنشر الخدمات ويؤدي إلى مشاكل أمنية محتملة إذا لم يكن الأشخاص حذرين.

قد تكون أفضل ممارسة أمنية هي تقييد الشبكة افتراضيًا للعمل مثل مثال التأثير المطلوب أعلاه ، ثم السماح للمستخدم بإضافة جدار الحماية المناسب ، وما إلى ذلك من القواعد لتجاوز مثل هذا السلوك ، أو لديه خيار للعودة إلى السلوك الحالي. أعلم أنه لأسباب موروثة من غير المحتمل أن يؤدي ذلك إلى كسر الكثير من الأشياء عند التحديث ؛ لذلك على الأقل وجود خيار لتمكين ما سبق والذي يمكن تشغيله الآن سيكون خطوة أولى جيدة ، وربما لاحقًا بعد الكثير من التحذير ، اجعله السلوك الافتراضي. بافتراض أن السلوك الافتراضي آمن ، فإن امتلاك وظيفة لإدارة هذا (جدار الحماية-> تمكين المنفذ العام ، IP) في docker-compose yml سيكون طريقة رائعة لجعله معروفًا بما يجري.

لقد وجدت الخيار --iptables = false ، ومع ذلك ، لا أريد أن أضطر إلى تعيين جميع القواعد بنفسي. الشيء الوحيد الذي أعترض عليه هو إعداد المصدر للقواعد.

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

arenetworking versio1.10

التعليق الأكثر فائدة

إن القضية التي يسلطها بن على الضوء حقيقية ومدهشة (مزيج سيء). العديد من المشرفين ، مثلي ، يستخدمون جدار الحماية ufw المجرب والصحيح. يقوم Docker بالعمل والتشغيل النهائي حول ufw وتغيير قواعد iptables بطريقة تجعله 1) يتسبب في أن ufw يخطئ في الإبلاغ عن الحالة الحالية لقواعد تصفية الحزم ، و 2) يعرض خدمات خاصة على ما يبدو للشبكة العامة. من أجل أن يظل عامل الميناء في النعم الجيد لمجتمع مسؤول النظام ، يجب وضع نهج آخر. يوجد الآن العديد من المسؤولين ، الذين ، مثل بن وأنا ، قاموا عن غير قصد بفتح منافذ للإنترنت الأوسع. على عكس بن وأنا ، لم يكتشفوا الأمر بعد.

ال 114 كومينتر

ملاحظة: لقد لاحظت في https://github.com/docker/docker/blob/master/vendor/src/github.com/docker/libnetwork/iptables/iptables.go أنه لا يوجد حتى خيار موجود لتعيين المصدر ، لذلك فهو يستخدم فقط إعدادات iptables الافتراضية لمصدر IP / الجهاز.

إنه ليس # 14041 تمامًا لأن هذه المشكلة تتحدث عن المنافذ المكشوفة. يهدف الكشف عن المنافذ إلى جعلها متاحة للجمهور ، لأن هذه هي الطريقة التي تعرض بها الخدمات للعالم الخارجي. إذا كنت تعمل في بيئة تطوير ، فيمكنك إما تعطيل الوصول إلى المنافذ من خارج جهاز الكمبيوتر الخاص بك باستخدام جدار حماية مضيف ، أو ببساطة عدم كشف المنافذ والوصول إلى الخدمات مباشرة ، أو من حاويات أخرى على نفس الشبكة.

أوصي باستخدام ميزات شبكة عامل الإرساء الأحدث لإعداد شبكات خاصة للخدمات التي لا تريد كشفها على الإطلاق ، راجع https://docs.docker.com/engine/userguide/networking/

هذا ما فكرت به أولاً. ولكن كان مرتبكًا بعض الشيء ، لأن _exposing_ منفذ ( EXPOSE ) ، لا يفعل شيئًا في الواقع ، ولكن _publishing_ منفذ ( -p / -P ) يعرضه فعليًا على مضيف.

إذا كنت تتحدث بالفعل عن "النشر" ، فهذا مصمم على النحو التالي ؛

في المثال الخاص بك ، يجب ألا تنشر الحاوية B و C منفذيها ، ويمكن للحاوية A الاتصال بها من خلال Docker Network، e، g.

docker network create mynet

docker run -d --net=mynet --name=api api-image
docker run -d --net=mynet --name=db database-image
docker run -d --net=mynet --name=web -p 443:443 nginx

ينشر هذا فقط حاوية "الويب" إلى المضيف ، ويمكن لحاوية الويب الوصول إلى حاويات "API" و "قاعدة البيانات" من خلال أسمائها (أي http: // api : 80 / و db: 3306 (بافتراض MySQL))

justincormack لذلك لا أعتقد أن استخدام شبكة خاصة يحل المشكلة. في حالتي ، أستخدم شبكة خاصة بين الحاويات ، ولا تزال مكشوفة للجمهور لأن جدار حماية المضيف غير مهيأ للحد من التعرض للشبكة الخاصة.

thaJeztah ، لا تزال المشكلة تتعلق بدعم جدار الحماية - لا يوجد دعم لجدار الحماية في عامل

الآن أقوم بتشغيل هذا عبر docker-compose ؛ ومع ذلك ، فهي ليست مشكلة إنشاء عامل الإرساء تمامًا نظرًا لأن وظيفة libnetwork لديها _لا_ القدرة على تقييد الشبكة في قواعد جدار الحماية - لا تحتوي قواعد iptables على مواصفات المصدر ، لذا بغض النظر عن كيفية تكوين الفرد للشبكة طالما يعتمد المرء على عامل الإرساء لإنشاء قواعد جدار الحماية (التي يجب على المرء أن يفعلها لأنه من المرجح أن تحصل عليها بشكل صحيح) ثم تصبح هذه مشكلة. ضع في اعتبارك ما يلي في ملف docker-compose.yml:

nginx:
    build: ./docker/nginx/.
    ports:
        - "127.0.0.1:8080:80"
        - "127.0.0.1:443:443"
    environment:
        DESTINATION_HOST: repose
    links:
        - repose
repose:
    build: ./docker/repose/.
    ports:
        - "127.0.0.1:80:8080"
    environment:
        DESTINATION_HOST: phoenix
        DESTINATION_PORT: 8888
    links:
        - phoenix
curryproxy:
    build: ./docker/curryproxy/.
    ports:
        - "127.0.0.1:8081:8081"
    external_links:
        - rse_rse_1
        - rse_rse_2
        - rse_rse_3
phoenix:
    build: .
    ports:
        - '127.0.0.1:88:8888'
    links:
        - curryproxy:curry
    external_links:
        - rse_rse_1:rse
        - rse_rse_2
        - rse_rse_3
        - rse_cache_1:cache
    volumes:
        - .:/home/phoenix

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

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

إذا كان هذا عن طريق التصميم ، فهو نموذج أمان ضعيف لأنك تعرض الآن جميع المطورين لمخاطر شديدة عند الاتصال بشبكات غير مألوفة (مثل السفر).

كما قلت ، لا أتوقع أن يتغير الإعداد الافتراضي على الفور ولكن وجود الخيار سيكون خطوة أولى جيدة.

أنا في حيرة من أمري إذن ، هل يمكنك إعطاء بعض الأمثلة خارجيًا لما يمكنك الاتصال به؟ ستكون خدمات الواجهة الخلفية (افتراضيًا) على شبكة 172.17.0.0/16 ، والتي لن تكون قادرًا على الوصول إليها خارجيًا لن أفكر أولاً لأنك لن يكون لديك مسار إلى ذلك المحدد من مضيف خارجي.

هناك مشكلة محتملة إذا كان عنوان IP الخارجي الخاص بك هو أيضًا عنوان IP خاص ، فلن يتم إسقاط حركة المرور التي يتم توجيهها للشبكات الداخلية (بينما يجب أن تكون من عام إلى خاص) - هل هذه هي المشكلة؟

justincormack لذلك أقوم في الأساس بإعداد

firewall:
    external:
        ports:
            - 80
            - 443

الآن يمكن التخفيف من الموقف إلى حد ما عن طريق تقييد تعيين الشبكة على _ المضيف_ إلى 127.0.0.1 بدلاً من الخريطة الافتراضية 0.0.0.0. لاحظ أن هذا هو ما يخفف من حدته حقًا لأنه بخلاف ذلك ، سيعمل الجسر على إعادة توجيه منفذ المضيف إلى شبكة عامل الإرساء.

ونعم ، لقد تحققت من أن الأعمال المحددة ؛ ومع ذلك ، فإنه لا يزال يترك الثغرات الأمنية المحتملة في مكانها وقواعد جدار الحماية لا تتطابق مع ما يتم فعله بالفعل.

كمثال آخر ، كانت هناك ثغرة أمنية في Linux Kernel منذ فترة وجيزة (تواجه مشكلة في العثور عليها في الوقت الحالي) والتي كانت مرتبطة بالمنافذ التي تم وضع علامة عليها في IPtables على أنها مفتوحة للاستخدام من قبل التطبيقات ، ولكن بعد ذلك لم يتم توصيلها فعليًا بتطبيق - على سبيل المثال ، أن تكون على منفذ مضيف محلي ولكن ليس منفذ IP عام. من المحتمل أن يؤدي هذا إلى إعداد ذلك ، وسيكون من الأفضل تقييد قواعد IPtables على الشبكات المتوقعة بدلاً من تركها مفتوحة للاتصال من أي مكان. كما قلت ، على الأقل لديك خيار التحديد. من المحتمل أنهم أصلحوا هذه المشكلة بالذات ولكن لماذا تركوا الاحتمال مفتوحًا؟

IOW ، الأمر كله يتعلق بالأمن.

BenjamenMeyer إذا كنت لا تريد الوصول إلى الخدمات الأخرى ، فلماذا تنشر "127.0.0.1:8081:8081" غير مطلوب إذا تم الوصول إليه فقط من خلال شبكة Docker (تتصل الخدمات الأخرى مباشرة عبر شبكة Docker)

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

على سبيل المثال ، أقوم بتشغيل بيئة Jenkins في بضع حاويات. العقدة الرئيسية "منشورة" ، لكن عليّ أن أصنع بعض قواعد iptables المعقدة جدًا لإغلاقها حتى لا يتمكن سوى المكتبين اللذين لدينا فقط من الوصول إليها.

هل هناك طريقة للتغلب على هذا المضمّن حاليًا في Docker؟ أو على الأقل ممارسة موصى بها؟ لقد رأيت في الوثائق كيف يمكنك تقييد الوصول إلى عنوان IP واحد ؛ لكن ليس عدة. المشكلة الأخرى في هذا الأمر هي أنه إذا كان لديك خادم يحتوي بالفعل على تكوين iptables ، فقد تعيد تعيين جميع القواعد قبل تطبيق القواعد الخاصة بك (ومن هنا جاءت القواعد الملتوية التي كان علي إعدادها).

لدي مشكلة مشابهة لتلك التي ذكرهاSeerUK. يوجد انتهاك صارخ للتوقعات عندما لا تنطبق قواعد جدار الحماية الموجودة مسبقًا على منافذ الحاوية المنشورة. السلوك المطلوب هو كما يلي (بالنسبة لي على الأقل)

  1. تتم تصفية محاولة اتصال المستخدم بناءً على تكوينات INPUT ، إلخ
  2. يتم بعد ذلك إعادة توجيه حركة المرور كالمعتاد بناءً على قواعد FORWARD المضافة بواسطة عامل الإرساء

هل هناك طريقة مختصرة لتحقيق ذلك في iptables ، أم أنها لا تسمح بمثل هذا البناء بسهولة. أنا محدودة بشكل خاص في معرفتي بـ iptables لذا احمل معي. لقد التقطت مؤخرًا معلومات عنها أثناء محاولتي فهم تفاعلات عامل الرصيف معها.

ما لجأت إليه بالفعل في الوقت الحالي ، نظرًا لأنني أقوم بالفعل بتشغيل هذه الحاويات على خادم مخصص قوي جدًا ، فقد قمت بإعداد KVM VM يعمل Docker ، ثم استخدم بعض قواعد iptables القياسية لتقييد الوصول من المضيف . يحتوي الجهاز الظاهري على واجهة شبكة خاصة به يمكن الوصول إليها فقط من الخادم ، لذلك يجب أن أضيف قواعد للسماح صراحة بالوصول إلى المنافذ في iptables على المضيف. لقد فقدت القليل من الأداء ، لكن ليس كثيرًا.

thaJeztah أريد أن أتمكن من الوصول إليه من النظام المحلي ، واختباره بسهولة. على سبيل المثال ، قم بإعداد واجهة برمجة تطبيقات RESTful HTTP التي تحتوي على نقطة نهاية صحية والقدرة على تشغيل curl بشكل موثوق ضدها باستخدام المضيف المحلي (لا بد لي من توثيق هذا للآخرين والحصول على عناوين IP التي لا يمكن الاعتماد عليها ). في معظم الحالات بالنسبة لبيئة التطوير الخاصة بي ، أريد فقط أن تتحدث الحاويات مع بعضها البعض ، لكنني أريد أيضًا أن أتمكن من الوصول إليها من المضيف.

بالنسبة لحالةSeerUK ، فإن القدرة على تعيين كتلة IP (5.5.0.0/16 - معلمة صالحة لعنوان المصدر في قواعد iptables) ستكون شيئًا جيدًا جدًا. IPtables لديها بالفعل القدرة على القيام بالحد ، لكن عامل الإرساء لا يستفيد منه.

thaJeztah لقد قمت بتعيين "127.0.0.1:8081:8081" صراحة لإبقائه خارج الشبكة الخارجية ؛ لقد وجدت سجلات في حاويات عامل الإرساء الخاصة بي من أشخاص يحاولون اختراق الحاويات عبر المنافذ المكشوفة.

عملي الآن هو إيقاف تشغيل حاويات عامل الإرساء قبل مغادرتي لهذا اليوم لأنني لا أستطيع ضمان البيئة التي أريد أن أكون خارجية في الواقع _is_ خارجية ، أو أن البيئة محدودة بشكل صحيح لأغراض الأمان.

BenjamenMeyer إحدى الطرق للقيام بذلك هي تشغيل تلك الاختبارات في حاوية ، على سبيل المثال

docker run --net -it --rm --net=mynetwork healthchecker 

إن القضية التي يسلطها بن على الضوء حقيقية ومدهشة (مزيج سيء). العديد من المشرفين ، مثلي ، يستخدمون جدار الحماية ufw المجرب والصحيح. يقوم Docker بالعمل والتشغيل النهائي حول ufw وتغيير قواعد iptables بطريقة تجعله 1) يتسبب في أن ufw يخطئ في الإبلاغ عن الحالة الحالية لقواعد تصفية الحزم ، و 2) يعرض خدمات خاصة على ما يبدو للشبكة العامة. من أجل أن يظل عامل الميناء في النعم الجيد لمجتمع مسؤول النظام ، يجب وضع نهج آخر. يوجد الآن العديد من المسؤولين ، الذين ، مثل بن وأنا ، قاموا عن غير قصد بفتح منافذ للإنترنت الأوسع. على عكس بن وأنا ، لم يكتشفوا الأمر بعد.

thaJeztah الذي يفترض أنني أفعل ذلك عبر سطر الأوامر وليس باستخدام أداة أخرى حيث يتعين علي فقط تعيين عنوان IP.

على سبيل المثال ، أنا أعمل على API. لدي أداة يمكنني استخدامها للعمل مع واجهة برمجة التطبيقات تلك في الإنتاج لدعمها ؛ لتطوير الأداة وواجهة برمجة التطبيقات ، أريد فقط توجيه الأداة إلى واجهة برمجة التطبيقات المرسومة. الأداة لا تعرف شيئًا عن عامل الإرساء ، ولا ينبغي لها ذلك. ولا أرغب بالضرورة في وضع الأداة في عامل الإرساء لمجرد استخدامها - يجب أن يكون توجيهها إلى منفذ مكشوف فقط للمضيف المحلي كافياً.

jcheroske أوافق ، لكنني لا أعرف أن هناك حلًا جيدًا لهذا الجانب. لذلك ، ربما يحتاج ufw إلى أن يكون أكثر ذكاءً حتى تتمكن من البحث والإبلاغ عن القواعد التي لم تشارك في إنشائها. هناك الكثير من البرامج التي يمكنها ضبط قواعد iptables بطرق لا يعرفها ufw (أو جدار الحماية AFAIK ، إلخ). ليس هناك حقًا حل بسيط لإصلاح ذلك أيضًا.

ومع ذلك ، سيكون من الجيد أن يتكامل Docker مع أولئك الذين يتخلصون من ملفات التكوين المناسبة لتتمكن من تمكينها / تعطيلها ، أو التكامل مع تلك الأدوات بحيث يتم ربطها وتفريغ المعلومات بشكل مناسب ، ومع ذلك ، مع الأخذ في الاعتبار هناك حلول أفضل لا أعتقد أن هذا الجانب سيتم حله حقًا. هنا ، يتعلق الأمر فقط بتحديد نطاق قواعد iptables التي يتم إنشاؤها لتقليل التأثيرات المحتملة على الأقل من خلال السماح بمواصفات المصدر (lo ، eth0 ، 127.0.0.0/24 ، إلخ).

إذا كنت على استعداد للقيام بذلك ، فإن استخدام iptables يجعل هذا ممكنًا تمامًا.

هذا مثال مختصر لكيفية استخدامه: https://gist.github.com/SeerUK/b583cc6f048270e0ddc0105e4b36e480

يمكنك أن ترى أنه في الجزء السفلي مباشرة ، تم منح 1.2.3.4 حق الوصول صراحةً إلى المنفذ 8000 (الذي يعرضه Docker) ، ثم يتم إسقاط أي شيء آخر إلى هذا المنفذ. يتم إدخال سلسلة PRE_DOCKER لتكون قبل سلسلة DOCKER بحيث يتم الضغط عليها أولاً ، مما يعني أن DROP يوقف الطلبات المحظورة من الوصول إلى سلسلة DOCKER.

إنه أمر مزعج بعض الشيء أن Docker لا يحتوي على هذه الوظيفة المضمنة ، ولكن من الممكن حلها الآن.

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

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

من الواضح أن هذا ليس حلاً رائعًا إذا كنت قد أنشأت بالفعل مجموعة معقدة بشكل معقول من قواعد جدار الحماية حول UFW. رغم ذلك ، فإنه يجعل استخدام أشياء مثل iptables-persistent أمرًا سهلاً للغاية. يمكنك أيضًا استخدام طرق بديلة للسماح بالوصول بهذه الطريقة التي تبدو أكثر "طبيعية" في iptables.

هل فكرت في BenjamenMeyer في استخدام docker network معرّف من قبل المستخدم مع خيار الشبكة الفرعية ونطاق IP وتعيين عنوان IP ثابت للحاويات واستخدامها في التنمية المحلية بحيث لا تضطر إلى الاعتماد عليها عنوان IP ثابت افتراضي مثل 127.0.0.1؟ سيؤدي ذلك إلى تجنب الحاجة إلى تعيين المنافذ معًا لتلك الحاويات الخاصة بالمضيف.

docker network create --subnet=30.1.0.0/16 --ip-range=30.1.0.0/24 mynetwork
docker run --net=mynetwork --ip=30.1.1.1 --name=myservice1 xxxx
docker run --net=mynetwork --ip=30.1.1.2 --name=myservice2 yyyy

من خلال هذا الإعداد ، يمكن أن تصل myservice2 إلى myservice1 بالاسم myservice1 ولا داعي حتى للاعتماد على عنوان IP الثابت. كما يمكن للمضيف الوصول إلى عنوان IP الثابت بحرية دون الحاجة إلى تعيين المنافذ.

أيضًا باستخدام الإنشاء 1.7 ، يمكنك تحديد عنوان IP ثابت للحاويات وتحديد الشبكات الفرعية والنطاقات.

لقد وجدت حلاً بسيطًا.

1) تحرير / etc / default / docker: DOCKER_OPTS="--iptables=false"

2) أضف قاعدة ufw: ufw allow to <private_ip> port <port>

بسيط جدًا لدرجة أنه يجعلني أتساءل حقًا لماذا لا يكون الخيار --iptables=false هو الخيار الافتراضي. لماذا تخلق مثل هذا الموقف عندما يتعين على كل عامل الإرساء أن يقول ، "مرحبًا ، إذا كنت تشغل جدارًا ناريًا ، فسيتعين عليك إحداث ثقب من خلاله!" ماذا ينقصني؟

https://fralef.me/docker-and-iptables.html
http://blog.viktorpetersson.com/post/101707677489/the-dangers-of-ufw-docker

لا يمكنني الحصول على عامل ميناء للتوقف عن تعديل iptables لإنقاذ حياتي. حاولت تحديث / etc / default / docker دون جدوى على Ubuntu 16.04

enzeart جرب /lib/systemd/system/docker.service .

تضمين التغريدة

enzeart لتكوين برنامج خفي يعمل على مضيف يستخدم systemd ، من الأفضل عدم تحرير ملف docker.unit نفسه ، ولكن استخدام ملف "drop in". بهذه الطريقة ، لن تواجه مشكلات عند ترقية عامل الإرساء (في حالة وجود ملف docker.unit أحدث). راجع https://docs.docker.com/engine/admin/systemd/#custom -docker-daemon-options لمزيد من المعلومات.

يمكنك أيضًا استخدام ملف تكوين daemon.json ، راجع https://docs.docker.com/engine/reference/commandline/daemon/#daemon -configuration-file

mavenugo هناك بالفعل شبكة عامل ميناء في المكان.

jcheroske يعمل ، ولكن كما أشرت ، فإن هذا يعني أن _end-user_ (أنا) سيتعين بعد ذلك التأكد من أن جميع قواعد iptables صحيحة ، وهذا ليس هو الأمثل وليس من المرجح أن يحدث مثل جعل docker يفعل ذلك تلقائيًا ، وبالتالي هذه المشكلة.

مرحبًا ، من فضلك. أعتقد أن مشكلته أيضًا. يجب أن تكون سلسلة الحاويات في Iptables تتبع القواعد الرئيسية وألا تتعرض للعالم افتراضيًا.

أود حقًا أن أرى Docker (و docker-compose) لديه القدرة على إضافة عناوين IP إلى القائمة البيضاء أو القائمة السوداء التي يمكنها الوصول إلى هذا المنفذ.

خذ هذا المثال:

nginx:
    ports:
      - "8000:8000"
    whitelist:
      - 10.6.20.2

قد يعني أن عنوان IP المصدر 10.6.20.2 فقط يمكنه الوصول إلى المنفذ 8000 على هذا المضيف.

StefanPanait أحب هذه الفكرة حقًا. يمكن أن يعمل أيضًا مع بناء جملة مشابه لوحدات التخزين وقوائم الوصول / الرفض ، مثل:

nginx:
  access:
  - "10.0.1.6:allow"
  - "deny"

بالطبع لا يزال يتعين عليها السماح بأشياء مثل الاتصال بين الحاويات.

SeerUK يجب أن يكون الاتصال بين الحاويات افتراضيًا ، ولكن لماذا لا يمكنك منع حاوية واحدة من التحدث إليها؟ قد يكون ذلك مفيدًا للغاية لتصحيح الأخطاء ...

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

nginx: access: - "10.0.1.6:allow" - "webapi:allow" - "database:deny" - "deny"
يمكن أن يكون مفيدا ... السؤال هو ، هل هو مفيد بما يكفي لتبرير التنفيذ إلى هذه الدرجة؟ انا لا اعرف.

في الوقت الحالي ، أرغب في حل المشكلة الأصلية ، ثم يمكن إضافة ميزات مثل هذه إذا لم يكن من المنطقي تصميمها في الدقة لتبدأ بها (ربما).

لماذا لا تستطيع منع حاوية واحدة من التحدث إليها؟ يمكن أن يكون مفيدًا للغاية في التصحيح

كان هذا docker network disconnect هو؟ يمكنك فصل حاوية من الشبكة لتصحيح الأخطاء ، وإعادة إرفاقها بـ docker network attach

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

تقدم Ubuntu 16.04 مع UFW و Docker تحديات جديدة. لقد فعلت كل الخطوات كما هو موضح هنا: https://svenv.nl/unixandlinux/dockerufw ولكن لم أتمكن من الحصول على عامل ميناء بالإضافة إلى UFW للعمل على 16.04. بعبارة أخرى ، بغض النظر عما فعلته ، أصبحت جميع منافذ الرصيف معرضة عالميًا للإنترنت. حتى وجدت هذا: http://blog.samcater.com/how-to-set-docker-1-12-to-not-interfere-with-iptables-firewalld/
اضطررت إلى إنشاء الملف: /etc/docker/daemon.json وأدخل ما يلي:

{
"iptables": خطأ
}

أصدرت بعد ذلك sudo service docker stop ثم sudo service docker start FINALLY docker يتبع ببساطة القواعد المناسبة في UFW.

بيانات إضافية: https://chjdev.com/2016/06/08/docker-ufw/

تضمين التغريدة

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

وماذا لو كان مطلوبًا أن يظل لديك اتصال بالشبكة؟ مثال: اختبار فشل التحقق من الصحة من الخادم في الحاوية B للحاوية A أثناء استمرار تقديم الخدمات بواسطة الحاويات C و D و E. أسهل فقط لمنع الحاوية B من النقل إلى الحاوية A بدلاً من إغلاق الشبكة بالكامل - قد تكون الحاويات C أيضًا تعتمد على الوصول إلى الحاوية B لاجتياز الفحص الصحي.

ومع ذلك ، هذا لا يصمد أمام "دعنا نصلح المشكلة الأصلية".

@ gts24 تجد مثيرة للاهتمام.

IMHO ، المشكلة برمتها هي أن Docker ، مثل جميع البرامج الأخرى حرفيًا ، يجب ألا يلمس جدار الحماية (iptables أو غير ذلك) على الإطلاق. عندما أقوم بتثبيت (على سبيل المثال) اباتشي وأقول ذلك للاستماع على 0.0.0.0:80 انها قراري لفتح المنفذ 80 في جدار الحماية أم لا، أين يمكنني تحديد أي قواعد لذلك أود أن.

بدلاً من إعادة اختراع قواعد جدار الحماية على ملفات تكوين عامل الإرساء (و / أو إنشاء) ، يجب إهمال ميزة PUBLISH بالكامل ، وإنشاء ميزة LISTEN جديدة للعمل مثل جميع البرامج الأخرى. في أفضل الأحوال ، يمكن لـ docker إنشاء خدمات جدار الحماية الافتراضية المعطلة لكل منفذ / حاوية ، على الأنظمة التي تستخدمها.

gcscaglia عيّن --iptables=false على البرنامج الخفي ويجب أن تحصل عليه

thaJeztah هذه الميزة غير مجدية لأن Docker لا يقدم أي بديل للحصول على قواعد جدار الحماية الضرورية (أو المزيد من

thaJeztah بالضبط ما قاله Taladar.

يجب إعادة تسمية --iptables=false إلى --networking=false لأنه لا يعمل حتى مع الشبكات الداخلية للحاويات إلى الحاوية. إن خيار جعل الحاويات تستمع إلى مجموعة من المنافذ / الواجهة دون إحداث ثقوب في قواعد جدار الحماية الداخلي (على سبيل المثال ، LISTEN ) من شأنه أن يحل كل هذا ، ويكون متوافقًا مع الإصدارات السابقة ويسمح باستخدام --iptables=true .

مع وضع الاستماع هذا ، يمكن لأولئك الذين يريدون "العمل فقط" الاستمرار في استخدام PUBLISH ، ويمكن لأولئك الذين يريدون التحكم استخدام LISTEN .

gcscaglia حسنًا ، لذلك إذا كنت تريد أن يقوم عامل الميناء بإعداد القواعد الأساسية والتعامل مع شبكات الحاويات والحاويات ولكن ليس "النشر". يمكنك إبقاء --iptables ممكّنًا ، لكن _لا تستخدم -p / --publish . يجب أن تكون قادرًا على تعيين قواعد IPTables يدويًا لإعادة توجيه المنافذ إلى الحاويات. تستمع الحاوية بالفعل إلى عنوان IP الخاص بها ، والمنافذ التي تستمع إليها الخدمة الموجودة في الحاوية الخاصة بك.

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

مثال بسيط. نستخدم حاوية Docker لتشغيل وظائف Jenkins. يفضحون منفذ SSH الخاص بهم حتى يتمكن Docker من الاتصال بهم. يتم تدميرها بمجرد انتهاء المهمة. لا يوفر Docker أي طريقة لجعل هذا يعمل مع --iptables = false لأنه ليس لديك طريقة لإخبار Jenkins (باستخدام Docker API لتشغيل الحاوية) بمنفذ المضيف وليس لديك طريقة حتى لتشغيل برنامج نصي للإعداد قواعد جدار الحماية اللازمة.

تعمل فكرتك فقط في حالة الاستخدام البسيط السخيف المتمثل في إطلاق حاويات دائمة لا تتغير أبدًا يدويًا. حتى عملية إعادة التشغيل البسيطة = دائمًا في الحاوية ستتعطل في هذا الإعداد ما لم يكن للحاوية عنوان IP ثابت.

taladar أقوم بالرد على حالة استخدام gcscaglia ، التي طلبت ميزة حيث لا يدير عامل الإرساء IPTables لفتح المنافذ ، وحيث يتحكمون في IPTables ؛ على سبيل المثال ، لا يتم كشف أي حاوية ، ما لم يتم ذلك يدويًا. أيضًا ، في ردي شرحت لـ _ لا_ استخدم --iptables=false ، ولكن لإبقائه ممكّنًا ، لكن لا تستخدم ميزة -p / --publish (التي تخبر عامل الشحن أن يفعل تلك المنافذ التي يمكن الوصول إليها من خلال IPTables).

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

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

أعتقد أنه لا يمكنك الحصول على كل شيء ، لكنه بالتأكيد محبط. هل يستحق الأمر فتح طلب ميزة بخصوص فكرتي LISTEN ، وإلا فلن يهتم فريق Docker بمثل هذه الميزة؟

ماذا سيفعل LISTEN ؟ يوجد EXPOSE ، والذي يسمح لك بالتعليق على المنافذ التي تستمع إليها الحاوية. بالنسبة إلى المشغلات ، يمكنك الاستماع إلى عامل الإرساء events .

لا أقول أنه لا يوجد مجال للتحسين هنا (أعلم أنه يتم النظر في الأمر) ، فقط أتساءل عما تتوقعه

حاليًا ، كما قلت ، ترتبط جميع الخدمات التي تعمل في حاوية بعنوان IP الخاص للحاوية (إذا كنت لا تستخدم --net=host أو ما شابه). هذا جيد ومرغوب فيه لأن هذا العزل بين المضيف والحاويات هو بالضبط نقطة بيع Docker.

ولكن ، في الوقت الحالي ، إذا كنت أريد تطبيقًا يعمل خارج أي حاوية (سواء كان ذلك على المضيف أو في أي مكان آخر على الشبكة) للوصول إلى خدمة تعمل داخل حاوية ، فأنا بحاجة إلى وسائل لجعل هذه الخدمة تستمع إلى إحدى واجهات شبكة المضيف. لحل هذه المشكلة دون الكشف عن واجهات أي مضيف للحاوية ، أنشأ Docker الميزة -p / --publish ، والتي:

  1. ينشئ قواعد iptables لإعادة توجيه منفذ مُختار على واجهة مضيف مُختار إلى منفذ مُختار على عنوان IP الخاص بالحاوية (وهو ما نتوقعه جميعًا لأن هذا ما طلبناه)
  2. يخبر iptables للسماح لأي شخص من أي مكان في العالم بالوصول إلى هذا المنفذ على واجهة المضيف المختار (وهو أمر غير ضروري لإعادة التوجيه للعمل وبالتالي يفاجئ الكثير منا)

ما أقترحه هو ميزة (تسمى LISTEN أو غير ذلك) تعمل فقط "1" وتتيح "2" لتقدير المستخدم ، كما تفعل جميع الخدمات / البرامج الأخرى عادةً.

بالنسبة إلى EXPOSE ، فإن AFAIK هو عبارة عن بيانات وصفية فقط في صور Docker ، لذا فإن البرنامج الخفي يعرف ما يجب فعله عندما يحدد المستخدم -P (نشر كل شيء). ربما أكون مخطئًا في ذلك ، ويمكن إعادة توجيه المنافذ "المكشوفة" إليها بطريقة مقاومة إعادة التشغيل (بدون الوصول إلى جميع أنحاء العالم)؟

--خارج الموضوع--

يسأل IMHO OP الخاص بهذه المشكلة بالضبط لماذا يقوم -p "2" وكيفية منع Docker من القيام بذلك. بينما يمكن أن يحل إعداد مستوى البرنامج الخفي (بخلاف تعطيل الشبكات) ، من أجل الحفاظ على توافق الأشياء مع الإصدارات السابقة ، فإن الأفضل هو ميزة جديدة (مثل LISTEN أو اسم آخر).

في حين أن العديد من المستخدمين مثل هذا التأثير "يعمل خارج الصندوق" ، لا يتوقع مسؤول النظام أن تقوم برامج أخرى بخلاف iptables / firewalld الخاصة بهم بالانتقال إلى فتح المنافذ على جدار الحماية ، وحتى أقل من ذلك بطريقة لا يقوم برنامج إدارة جدار الحماية الخاص بهم بالإبلاغ عنها.

أرى أن هناك ثلاث مشاكل رئيسية:

  1. تتجاوز طريقة Docker في نشر / عرض المنافذ قواعد جدار الحماية الشائعة مثل UFW.
  2. لا يبدو أن الحقيقة المذكورة أعلاه موثقة جيدًا (إنها غير متوقعة تمامًا نظرًا لعدم وجود خدمات Linux أخرى أعرفها تتجاوز قواعد جدار الحماية نفسها).
  3. لا توجد طريقة بسيطة لتكييف iptables مع طريقة Docker للنشر / الكشف عن المنافذ أو الطرق التي يعرفها الناس ليست سهلة التشغيل ولا يتم توثيق أي منها.

ربما يكون من غير العملي من الناحية الفنية تنفيذ تعريض المنفذ على جدول FILTER وبالتالي فإن إصلاح 1 غير ممكن. على الأقل ، يجب أن يحصل هذا على تحذير كبير في مكان ما (الإصلاح 2) ولكن من الناحية المثالية يمكن حل 3 بخيارات جديدة مثل الأشخاص الذين اقترحوا هنا مثل allow أو deny والذي سيضيف قواعد جدار حماية إضافية تلقائيًا للسماح أو رفض عناوين IP محددة للمنافذ المكشوفة / المنشورة.

على سبيل المثال ، allow: "tcp:{your_trusted_ip}" للحاوية المسماة "elasticsearch" منفذ النشر 9200 قد يفعل شيئًا مثل:

iptables -t mangle -N DOCKER-elasticsearch
iptables -t mangle -A DOCKER-elasticsearch -s {your_trusted_ip} -j RETURN
iptables -t mangle -A DOCKER-elasticsearch -j DROP
iptables -t mangle -I PREROUTING -p tcp --dport 9200 -j DOCKER-elasticsearch

لقد وجدت هذا مفيدًا جدًا من مستندات Docker: https://docs.docker.com/engine/userguide/networking/default_network/container-communic/#communicating -to-the-outside-world

تسمح قواعد Docker للأمام بجميع عناوين IP الخارجية للمصدر بشكل افتراضي. للسماح فقط لعنوان IP أو شبكة محددة بالوصول إلى الحاويات ، أدخل قاعدة مرفوضة في الجزء العلوي من سلسلة تصفية DOCKER. على سبيل المثال ، لتقييد الوصول الخارجي بحيث لا يتمكن سوى مصدر IP 8.8.8.8 من الوصول إلى الحاويات ، يمكن إضافة القاعدة التالية:

$ iptables -I DOCKER -i ext_if! -س 8.8.8.8 -j إسقاط

jmimico نعم لقد صادفت ذلك من قبل. كيف تقيد الوصول من 2 أو أكثر من عناوين IP؟

ما هو الأمر الصعب للغاية بشأن Docket مجرد إضافة خيار لتشغيل برنامج نصي شل في أي مكان حيث يقوم الآن بإنشاء قواعد iptables مع تمرير جميع معلومات Docker الداخلية إلى البرنامج النصي كمعلمات؟ سيسمح ذلك للجميع بإنشاء القواعد التي يحتاجون إليها بالضبط. أضف طريقة ما لبدء إعادة تنفيذ البرامج النصية للحاويات النشطة التي يمكن للأشخاص الاتصال بها بعد قيامهم باستعادة iptables أو مسح السلاسل لبعض الأسباب الأخرى وتكون قد انتهيت.

لا يحتاج Docker إلى إعادة إنشاء جميع أنواع سيناريوهات جدار الحماية المبنية مسبقًا كما يقترح بعض الأشخاص هنا ، والتي يمكن إنشاؤها فوق نظام كهذا عن طريق مجموعات توزيع البرامج النصية للربط. على الأكثر ، قد يكون من المنطقي شيئًا مثل التعريض على المضيف المحلي فقط والعرض العالمي (كما يفعل Docker الآن). تتمتع IPTables بمرونة كبيرة جدًا بحيث لا يأمل Docker في تصميم جميع السيناريوهات مباشرةً في الإعدادات.

كانت هذه التذكرة موجودة على ما يبدو إلى الأبد ، والسلوك الحالي يجعل Docker الحدودي غير قابل للاستخدام (يبدو أنه الطريقة القياسية لتنفيذ الميزات في هذا المشروع ، على سبيل المثال عدم وجود GC مضمنة مناسبة أو بالكاد تخزين فعال وخالي من أخطاء kernel backend ، ...) وهناك حل سهل للسماح للأشخاص بتنفيذ حلولهم الخاصة التي تناسب بيئاتهم.

StefanPanait سؤال جيد. أراهن أنك ستحتاج إلى الاستفادة من استخدام مجموعات الكائنات. قم بتعبئة مجموعات الكائنات باستخدام عناوين IP المدرجة في القائمة البيضاء ثم استخدم مجموعة الكائنات هذه في السطر الأول من سلسلة DOCKER.

مثال:
iptables -N docker-allow.png
iptables -A docker-allow -s 1.1.1.1 -j قبول
iptables -A docker-allow -s 2.2.2.2 -j قبول
iptables -A docker-allow -s 3.3.3.3 -j قبول
iptables -A docker-allow -j DROP.j

iptables -I DOCKER -i ext_if -j docker-allow

أليست القواعد المضافة إلى سلسلة DOCKER تتداخل مع أشياء مثل إعادة تشغيل البرنامج الخفي؟ أعتقد أن المشكلة في الحلول اليدوية هي أنه من الصعب القيام بها بشكل صحيح ، وبالتالي هناك حجة قوية لتقديم دعم أفضل للحالات الشائعة (حظر / السماح بعناوين IP الفردية) بشكل مباشر.

ربما يكون البرنامج المساعد هو المكان المناسب لدعم هذا؟ على سبيل المثال ، ربما يمكن أن يضيف المكون الإضافي "ufw" قواعد بطريقة متوافقة مع ufw حتى يتمكن المستخدم من إدارة جدار الحماية بشكل فعال من خلال سلسلة أدوات جدار الحماية العادية ، وستعمل خدمات عامل الإرساء مثل خدمات المضيف العادية.

أليست القواعد المضافة إلى سلسلة DOCKER تتداخل مع أشياء مثل إعادة تشغيل البرنامج الخفي؟ أعتقد أن مشكلة الحلول اليدوية هي أنه من الصعب القيام بها بشكل صحيح ، وبالتالي هناك حجة قوية لدعم الحالات الشائعة بشكل أفضل (حظر / السماح بعناوين IP الفردية) بشكل مباشر.

يبدو أن إضافة قاعدة الإسقاط إلى سلسلة DOCKER-USER تعمل بشكل أفضل في جعلها ثابتة عبر عمليات إعادة تشغيل عامل الإرساء.

مع Docker v.17.06 ، توجد سلسلة iptables جديدة تسمى DOCKER-USER. هذا واحد لقواعدك المخصصة ، راجع إجابتي على serverfault: https://serverfault.com/questions/704643/steps-for-limiting-outside-connections-to-docker-container-with-iptables/886257#886257

كما علقت على SF ، أفتقد سبب اختلاف سلسلة DOCKER-USER هذه عن أي سلسلة أخرى مضافة من قبل المستخدم .. لا تحتوي على مرشح مطبق مسبقًا عليها وتقوم بتصفية جميع حركة المرور وليس فقط حركة المرور المخصصة لرسو السفن لا يزال يتعين عليك تحديد أسماء الواجهة بنفسك ولا تزال عرضة لارتكاب خبراء غير تابعين لـ iptables أخطاء جسيمة.

من ناحية أخرى ، لا يزال الأمر متوافقًا مع عقلية "Docker هو مستخدم iptables الوحيد" التي تمتص الأشخاص الذين يرغبون في استخدام iptables لأكثر من مجرد Docker. لذلك فهو سيء لمجموعة كاملة من المستخدمين المحتملين إلى جانب ربما الأشخاص الذين يكرسون مضيفين كاملين لأي شيء سوى Docker.

حسنًا ، لذا فإن استخدام DOCKER-USER يحل مشكلة ترتيب الإدخالات من خلال التأكد من أنها تأتي دائمًا في السلسلة قبل القواعد الأخرى المتعلقة بـ Docker. ومع ذلك ، فإنه لا يجعل إدراج حركة المرور في القائمة البيضاء إلى حاوية حسب رقم المنفذ أسهل كثيرًا نظرًا لأن --dport في هذه المرحلة هو منفذ الخدمة داخل حاوية عامل الإرساء ، وليس المنفذ المكشوف. مثال:

انشر المنفذ 9900 لعرض خدمة عامل ميناء تستمع داخليًا على 9000.

$ sudo iptables -A DOCKER-USER -m limit --limit 20/min -j LOG --log-prefix "IPTables: "
$ docker run --rm -it -p '192.168.56.101:9900:9000' alpine nc -l 9000

من جهاز آخر على الشبكة:

$ telnet 192.168.56.101 9900

ما يتم تسجيله:

IPTables: IN=enp0s8 OUT=docker0 MAC=08:00:27:b6:8d:d6:0a:00:27:00:00:04:08:00 SRC=192.168.56.1 DST=172.17.0.2 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=14127 DF PROTO=TCP SPT=51208 DPT=9000 WINDOW=64240 RES=0x00 SYN URGP=0
IPTables: IN=docker0 OUT=enp0s8 PHYSIN=veth05ba007 MAC=02:42:0f:f9:76:4c:02:42:ac:11:00:02:08:00 SRC=172.17.0.2 DST=192.168.56.1 LEN=40 TOS=0x00 PREC=0x00 TTL=63 ID=23041 DF PROTO=TCP SPT=9000 DPT=51208 WINDOW=0 RES=0x00 ACK RST URGP=0

لذا كما ترى لا توجد فرصة في هذه المرحلة لتصفية حركة المرور إلى المنفذ 9900. بالتأكيد ، يمكنني تصفية حركة المرور إلى 9000 ولكن هذه مشكلة لأن المنفذ الداخلي قد يتداخل عن غير قصد بين عدة حاويات أو حتى خدمات تعمل على المضيف. هذه إحدى نقاط البيع الرائعة لـ Docker حيث يمكنك تشغيل خدمات متعددة على مضيف واحد ولا تقلق بشأن تعارضات المنافذ. لذلك ، تم تصميم العديد من الحاويات للاستماع فقط على منفذ ويمكن للمستخدم استخدام الخيار --publish لتغيير المنفذ الذي يتم عرضه على أي واجهة:

$ docker run -d -p 7777:6379 --name data1 redis
$ docker run -d -p 8888:6379 --name data2 redis

ومع ذلك ، لا يمكنني استخدام DOCKER-USER (من فضلك صححني إذا كنت مخطئًا) للتأثير على حركة البيانات 1 دون التأثير أيضًا على حركة البيانات 2 ما لم أستخدم نوعًا من الاستبطان لاكتشاف عنوان IP لحاوية الوجهة وهو عابر مما يعيدك إلى المربع الأول حول إيجاد طريقة بسيطة وموثوقة للخدمات المنشورة بواسطة جدار الحماية بدون برمجة نصية واستبطان.

للتوضيح ، هذا لا يعمل:

$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 192.168.56.0/24 --dport 7777 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 10.0.24.0/24 --dport 8888 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp --dport 7777 -j DROP
$ sudo iptables -A DOCKER-USER -p tcp -m tcp --dport 8888 -j DROP

يعمل هذا بالفعل ، ولكن النتيجة هي أن كلتا الخدمتين تتعرضان لكل من CIDRs المدرجة في القائمة البيضاء:

$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 192.168.56.0/24 --dport 6379 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 10.0.24.0/24 --dport 6379 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp --dport 6379 -j DROP

لذلك يبدو أن DOCKER-USER مفيد فقط لتعريض جميع المنافذ لعناوين IP محددة ولكن لا يعرض منافذ معينة لعناوين IP محددة إلا إذا كنت لا تمانع في كتابة قواعد iptables للإشارة إلى أرقام المنافذ الداخلية وليس لديك عدة حاويات تستخدم نفس أرقام المنافذ الداخلية. يبدو أن الجميع يفقدون هذه النقاط ويعملون مع DOCKER-USER كحل وأعتقد أن هذا يستحق حلاً جديدًا أفضل.

تضمين التغريدة
الحل المنشور في https://gist.github.com/SeerUK/b583cc6f048270e0ddc0105e4b36e480 لم يعمل معي. هل باستطاعتك رجاءا المساعدة؟

خطأ عامل الإرساء هو استخدام iptables (جدار حماية النظام) للقيام بتوجيه التطبيق. سيخلق مشاكل وفوضى إلى الأبد. تغيير iptables أمر خطير للغاية. لإضافة هذه الوظيفة المضمنة في عامل الإرساء ، فإنه ليس من السهل جدا. بالإضافة إلى ذلك ، يمكن أن يكون لها أيضًا حالة غير متسقة متزامنة إذا قمت بتنفيذ عامل الإرساء بطريقة متزامنة.

إنها طبقات iptables لها سلوكيات غريبة إذا قمت بتغيير iptables أثناء تشغيل عامل الإرساء. إذا قمت بإيقاف docker ، فقم بتعيين iptables و docker تعمل جميعها على النحو المتوقع. قلقي هو ... إذا كان علي تغيير iptables في الإنتاج؟

إنها طبقات iptables لها سلوكيات غريبة إذا قمت بتغيير iptables أثناء تشغيل عامل الإرساء.

iptables هو iptables ، ولا يهمه ما إذا كان عامل الإرساء يعمل أم لا ..

من الأفضل إجراء الكثير من الاختبارات من قبل ... أن تخبر أن iptables هو مجرد حشو. هو اقتراحي :)

أعتقد أن وجهة نظره كانت أن iptables لا يتصرف بشكل مختلف عندما يعمل Docker كما اقترح تعليقك. من الواضح أن هذه مشكلة في Docker في الطريقة التي يستخدمون بها iptables كما لو أن لا أحد يحتاجها على نفس النظام.

لا أرى سبب عدم حل DOCKER-USER لهذا الأمر.
يمكنك استخدام iptables للتصفية كيفما تشاء: المنفذ المصدر ، المنفذ الهدف ، عنوان المصدر ، حركة المرور غير المحلية ، إلخ.

بيت القصيد من DOCKER-USER هو أنه يدير أي قواعد يريد المستخدم تشغيلها قبل تشغيل أي قواعد عامل تشغيل ، وهذا يسمح لك بفعل ما تريده مع حركة المرور قبل أن تصل إلى عامل الإرساء.

@ cpuguy83 المشكلة الأساسية هي أن عامل

لا يمكن لـ DOCKER-USER حل ذلك لأنه لا يربط أيضًا شبكات عامل الإرساء بواجهة شبكة معينة أو عنوان IP محدد (fe 127.0.0.1).

حسب طلبي الأصلي:
1.يجب أن يربط Docker نفسه بعنوان IP محدد - بناءً على تكوين Docker Network - ثم السماح للمستخدم بإضافة قواعد لفضح نظام الحاوية خارج النظام (باستخدام الأدوات التي يختارونها) ؛ بشكل افتراضي ، يجب ألا تتعرض الحاوية خارج النظام.

  1. لا يمكن القيام بذلك بدون فترة انتقالية بسبب اعتماد بعض الأشخاص على الأقل على السلوك التاريخي.

IMHO ، المشكلة برمتها هي أن Docker ، مثل جميع البرامج الأخرى حرفيًا ، يجب ألا يلمس جدار الحماية (iptables أو غير ذلك) على الإطلاق. عندما أقوم بتثبيت (على سبيل المثال) apache وأطلب منه الاستماع على 0.0.0.0:80 ، فإن قراري فتح المنفذ 80 على جدار الحماية أم لا ، حيث يمكنني تحديد أي قواعد أرغب في ذلك.
بدلاً من إعادة اختراع قواعد جدار الحماية على ملفات تكوين عامل الإرساء (و / أو إنشاء) ، يجب إهمال ميزة النشر بالكامل ، وإنشاء ميزة LISTEN جديدة للعمل مثل جميع البرامج الأخرى. في أفضل الأحوال ، يمكن لـ docker إنشاء خدمات جدار الحماية الافتراضية المعطلة لكل منفذ / حاوية ، على الأنظمة التي تستخدمها.

قال حسنا @ gcscaglia ! والأمر المحير هو أنه لا يوجد أي ذكر أو ذكر لكل هذا في https://docs.docker.com/engine/reference/run/#expose -incoming-ports ، والذي أعتقد أنه المكان الذي يبحث فيه معظم أولئك الذين يهتمون القليل من الوثائق لتكملة التعلم بالمثال ينتهي به الأمر في. يجب أن يكون هناك مربع أحمر فاتح في مكان ما يشرح مخاطر تجاوز Docker لقواعد iptables الموجودة مسبقًا.

إذا كنت لا تريد أن يقوم عامل الإرساء بإدارة iptables ، فقم بتعيين --iptables-=false
إذا كنت تريد فقط أن يفتح عامل الإرساء المنافذ على واجهة معينة ، فيمكنك أيضًا تعيين ذلك في التكوين الخفي.

تضمين التغريدة
يمكنك حظر كل حركة المرور في DOCKER-USER والسماح بمرور ما تريد فقط.

يمكنك حظر كل حركة المرور في DOCKER-USER والسماح فقط بما تريد.

@ cpuguy83 من فضلك قل لي إذا كان أي شيء أقوله هنا غير صحيح:

$ docker run -d -p 7777:6379 --name data1 redis
$ docker run -d -p 8888:6379 --name data2 redis

ومع ذلك ، لا يمكنني استخدام DOCKER-USER (من فضلك صححني إذا كنت مخطئًا) للتأثير على حركة البيانات 1 دون التأثير أيضًا على حركة البيانات 2 ما لم أستخدم نوعًا من الاستبطان لاكتشاف عنوان IP لحاوية الوجهة وهو عابر مما يعيدك إلى المربع الأول حول إيجاد طريقة بسيطة وموثوقة للخدمات المنشورة بواسطة جدار الحماية بدون برمجة نصية واستبطان.

للتوضيح ، هذا لا يعمل:

$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 192.168.56.0/24 --dport 7777 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 10.0.24.0/24 --dport 8888 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp --dport 7777 -j DROP
$ sudo iptables -A DOCKER-USER -p tcp -m tcp --dport 8888 -j DROP

يعمل هذا بالفعل ، ولكن النتيجة هي أن كلتا الخدمتين تتعرضان لكل من CIDRs المدرجة في القائمة البيضاء:

$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 192.168.56.0/24 --dport 6379 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 10.0.24.0/24 --dport 6379 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp --dport 6379 -j DROP

لذلك لا توجد طريقة للتحكم في حركة المرور من / إلى حاوية data1 بشكل مستقل عن حاوية data2 باستخدام DOCKER-USER . بالنسبة لي هذا لا يجعل من DOCKER-USER حلًا كبيرًا.

تضمين التغريدة

إذا كانت لديك قاعدة إسقاط عامة في DOCKER-USER ، فكيف يختلف هذا عما إذا كان عامل الإرساء مُلحقًا مقابل قاعدة الانتقال الرئيسية؟

@ cpuguy83 وجهة نظري ليست ضد التجاوز في حد ذاته. ما أقوله هو أن وجود Docker يتجاوز قواعد iptables الموجودة مسبقًا يجب أن يكون بالتأكيد ميزة اختيار ، وليس ميزة إلغاء الاشتراك.

وحتى في حالة إلغاء الاشتراك - وهو ما لا ينبغي أن يكون كذلك - يجب توثيقه جيدًا للغاية لأنه غير متوقع تمامًا ومن الصعب إلى حد ما تصحيحه. لا سيما بالنظر إلى عدد المستخدمين الذين يستخدمون ufw . لا أعرف أي برنامج آخر يفعل شيئًا كهذا دون تحذيرات صريحة جدًا وسأبتعد شخصيًا عن مثل هذه البرامج.

علاوة على ذلك ، يتفاقم هذا بسبب حقيقة أن معظم مستخدمي Docker - على الأقل في تجربتي - يبدأون في استخدامه في بيئات حيث تحجب البنية التحتية للشبكة الإضافية المشكلة ، مما يعزز الافتراض بأن الجهاز قد تم تكوينه كما يعتقدون.

آمل أن ينتقل Docker إلى نهج الاستماع فقط ، كما يتضح من gcscaglia .

إذا كانت لديك قاعدة إسقاط عامة في DOCKER-USER ، فكيف يختلف هذا عما إذا كان عامل الإرساء مُلحقًا مقابل تم إلحاقه مسبقًا بقاعدة القفز الرئيسية؟

لا أعتقد أنني أفهم سؤالك ... يرجى تجاهل تعليقي في 22 أبريل 2017 لأن هذا يتعلق فقط بالإصرار الذي يحلّه DOCKER-USER بالفعل. المشكلة التي أشرت إليها لا تتعلق بالمثابرة.

taladar ما الذي

تضمين التغريدة

أولاً ، أعتقد أن جميع المشرفين يتفقون على أن السلوك الحالي ليس مثاليًا. لسوء الحظ ، كان السلوك موجودًا منذ ذلك الحين إلى الأبد. إن تغيير الإعداد الافتراضي لشيء يستخدمه ملايين الأشخاص ليس حقًا شيئًا يمكننا القيام به هنا. هذا أحد أسباب إضافة DOCKER-USER حتى يتمكن الأشخاص على الأقل من إدخال أي قواعد يحتاجون إليها.

ومع ذلك ، لا يمكننا الالتفاف حول الحاجة إلى استخدام iptables (أو ebpf ، أو بعض حلول nating الأخرى) وتوفير الوظيفة التي يوفرها -p ... الجانب الآخر ، إذا كنت تريد منع الأشخاص من إحداث ثقوب في جدار الحماية ، عدم السماح لهم باستخدام -p .

للتلخيص ، يمكنك:

  1. أخبر عامل الإرساء بالربط (افتراضيًا) بعنوان معين (العنوان الافتراضي هو بالطبع 0.0.0.0 ، أو جميع الواجهات) ... لكن هذا لن يمنع أي شخص من تحديد عنوان يدويًا في -p spec (على سبيل المثال ، -p 1.2.3.4:80:80 )
  2. أدخل القواعد المخصصة في DOCKER-USER ، بما في ذلك رفض الكل
  3. تعطيل إدارة iptables مع --iptables=false

هل هناك شيء آخر يمكنك اقتراحه لا يشمل كسر المستخدمين الحاليين؟

@ cpuguy83 أفهم ذلك. أنا لا أدعو إلى حدوث مثل هذا التغيير بشكل جذري من نسخة إلى أخرى. أعتقد أنه سيكون تغييرًا جيدًا للتخطيط على مدار عدد من الإصدارات. لا أعتقد أيضًا أن على Docker التوقف عن استخدام iptables تمامًا. يختلف إعادة التوجيه عن السماح ، وبقدر ما أفهمه ، يجب أن يكون Docker قادرًا على إعادة التوجيه افتراضيًا دون السماح بالوصول إلى أي شخص في مكان بشكل افتراضي.

بقدر ما يمكن القيام به الآن ، يجب أن يكون التوثيق الإضافي حول هذا هو الأول والأخير. ما هي القناة الأنسب لرفع هذا الأمر مع مشرفي docker.com؟

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

أوافق على الدعوة لإضافة وثائق إضافية لهذه الوظيفة. بقدر ما أستطيع أن أقول أنه مذكور فقط على https://docs.docker.com/network/iptables/. لقد اكتشفت هذه المشكلة فقط بعد محاولة معرفة سبب إتاحة الخدمة التي قمت بتقييدها لعنوان IP محدد من خلال جدار الحماية للجمهور. كان هذا السلوك غير متوقع تمامًا بالنسبة لي لأنه يتعارض مع كل خدمة شبكية أخرى تعاملت معها على الإطلاق.

أفهم أن هناك حلولاً بديلة ، لكنني أعتقد أنه ينبغي النظر في هذا من أجل تغيير طويل المدى لعمل Docker. تعجبني فكرة ضبطه على LISTEN على أحد المنافذ ، والسماح للقواعد التي يحددها المستخدم بالبناء على ذلك.

كما هو مقترح ، أضفت قاعدة DROP إلى DOCKER-USER لمنع تعرض الحاويات للخارج عن طريق الخطأ (وهو ما حدث بشكل مثير للقلق).

ومع ذلك ، لدي الآن خدمة واحدة أرغب في الكشف عنها. ولكن كما أوضح colinmollenhour ، نظرًا لأن NAT يحدث قبل التصفية ، لا يمكنني التصفية إلا على docker ip (الذي لم يتم إصلاحه) ورقم المنفذ الداخلي (والذي يمكن أن يكون هو نفسه للعديد من الحاويات).

فكيف يمكنني الكشف عن هذه الخدمة الواحدة؟

SystemParadox هذا أحد الأسباب العديدة التي تجعل DOCKER-USER ليس حلاً حقيقيًا للمشكلة.

يارب احفظها
يعجبني حل LISTEN المقترح ، ولم أدافع أبدًا عن تغيير جذري من إصدار إلى آخر ؛ ولكن بدلاً من ذلك ، دافع عن إجراء التغيير على سلسلة من الإصدارات بإشعارات مناسبة تخرج ب / ج ، فأنا أدرك أن الكثير من الأشخاص يستخدمون Docker وأن إجراء تغيير مفاجئ من إصدار إلى آخر سيكون ضارًا للجميع.

أوافق أيضًا على أن تحديث وثائق Docker بخصوص -p و EXPOSE ، إلخ ، يجب أن يكون أولوية يتم إجراؤها على الفور لجذب الوعي بالمشكلة على الأقل. من واقع خبرتي ، فإن معظم الأشخاص الذين يستخدمون Docker ليسوا خبراء في جدار الحماية ، لذا فهم يثقون في أن يقوم Docker بما يتوقعونه ، وهو ما لم يكن موجودًا في التصميم الحالي.

علاوة على ذلك ، فإن حلول الملخصات في https://github.com/moby/moby/issues/22054#issuecomment -425580301 لا تعمل حقًا أيضًا. لماذا ا؟ لا أقوم بتشغيل Docker بشكل مباشر ، بل أجري عبر Docker Compose - استنادًا إلى YAML ؛ عناوين IP ديناميكية (يتحكم فيها Docker) وغالبًا ما أقوم بنشر خدمات متعددة داخل نفس شبكة Docker التي تحتاج إلى التفاعل مع بعضها البعض. وبالتالي فإن كلا من استخدام -p واستخدام ربط العنوان (الخيار 1 في الملخص) لا يعدان حلين. لا يحل DOCKER-USER أي شيء كما أشار إليه الآخرون (الخيار 2 في الملخص) وتعطيل جداول IP تمامًا (الخيار 3 في الملخص) أيضًا لا يساعد أي شيء b / c الآن كل شيء معطل (IPs ديناميكية لذا من الصعب كتابة حل برمجيًا ؛ تعطلت الشبكات بين الحاويات ب / ج يعتمد Docker على IPTables للتنقل بين الحاويات ؛ إلخ).

مرة أخرى ، لا توجد دعوة في هذا الموضوع لتغيير القطع بين نسختين ؛ ولكن دعوة إلى نهج مخطط مرحلي يُمكّن الأشخاص من الهجرة بشكل مناسب.

كحل بديل ، يمكنك الوصول إلى منفذ الوجهة الأصلي باستخدام -m conntrack --ctorigdstport .

لذلك في حالتي لدي ما يلي:

-A DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow docker out
-A DOCKER-USER -s 172.17.0.0/16 -j ACCEPT
# Allow access to docker service mapped to host 8702 (the service is actually listening on port 8088 in the container)
-A DOCKER-USER -p tcp -m conntrack --ctorigdstport 8702 -j ACCEPT
# Prevent access to docker from outside
-A DOCKER-USER -j DROP

تضمين التغريدة

الصيحة لحل iptables الصحيح! 🍻

لم أسمع أبدًا عن --ctorigdstport لكنني أعتقد أن السبب في ذلك هو أنني لم أقرأ عن كل امتداد ممكن لـ iptables وجربته وأنت أول من ذكرها في هذا السياق على حد علمي.

لقد اختبرت وهذا بالفعل يعمل:

$ docker run -d -p 7777:6379 --name data1 redis
$ docker run -d -p 8888:6379 --name data2 redis
$ sudo iptables -N DOCKER-USER-redis1
$ sudo iptables -A DOCKER-USER-redis1 -s 192.168.56.0/24 -p tcp -m tcp -j RETURN
$ sudo iptables -A DOCKER-USER-redis1 -j REJECT --reject-with icmp-port-unreachable
$ sudo iptables -N DOCKER-USER-redis2
$ sudo iptables -A DOCKER-USER-redis2 -s 10.0.24.0/24 -p tcp -m tcp -j RETURN
$ sudo iptables -A DOCKER-USER-redis2 -j REJECT --reject-with icmp-port-unreachable
$ sudo iptables -A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 7777 -j DOCKER-USER-redis1
$ sudo iptables -A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 8888 -j DOCKER-USER-redis2

أعتقد أن مثالًا كهذا ينتمي إلى المستندات لأنه ربما يغطي ما يبحث عنه 99٪ من المستخدمين: القدرة على كشف المنافذ باستخدام -p ولكن لا يزال بإمكانك التحكم في حركة المرور إليهم باستخدام عوامل تصفية شائعة مثل -s .

لقد أنشأت طلبًا لتحديث وثائق Docker بخصوص iptables.

https://github.com/docker/docker.github.io/issues/8087

الحل مدرج هناك في https://unrouted.io/2017/08/15/docker-firewall/
يبدو أنه شيء مشابه ، حيث أنشأ سلسلة iptables إضافية تسمى FILTERS
إلى حيث تقفز السلاسل INPUT و DOCKER-USER.

SystemParadoxcolinmollenhour بعد اختبار --ctorigdstport أستطيع أن أؤكد أنها تعمل، ولكن مع التحذير صغيرة.

في حالتي ، لدي تطبيق PHP مُرسى على Apache يستمع على المنفذ 80. القواعد التي تسمح بـ 1.2.3.4 فقط هي كما يلي:

-A DOCKER-USER -s 1.2.3.4/32 -i eth0 -p tcp -m conntrack --ctorigdstport 80 -j ACCEPT
-A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 80 -j DROP

لذا فإن قاعدة الإسقاط الخاصة بي أكثر تحديدًا من قواعدك ، حيث يتم إسقاط الحزم فقط لتصل إلى خادم الويب الخاص بي - أو هكذا اعتقدت. في الواقع ، كان يتم إسقاط الحزم الموجهة إلى خادم الويب الخاص بي وكذلك الحزم التي تعود مع الردود من الطلبات التي قدمها تطبيق PHP إلى خوادم الطرف الثالث.

هذا يرجع إلى حقيقة أن --ctorigdstport لا يتطابق مع منفذ الوجهة على الحزمة التي يتم تصفيتها ، ولكن مع الحزمة التي بدأت الاتصال. لذا ، فإن الردود على الطلبات الخارجة من Docker إلى خوادم أخرى سيكون لها SPT=80 وستتطابق أيضًا مع --ctorigdstport 80 .

إذا أراد أي شخص الحصول على تحكم أكثر إحكامًا في قواعد DROP ، فيجب أيضًا إضافة --ctdir :

-A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 80 --ctdir ORIGINAL -j DROP

في الواقع ، يجب أيضًا إضافة --ctdir لجميع القواعد التي تسمح بالاتصال للتعبير عن معناها بالضبط:

-A DOCKER-USER -s 1.2.3.4/32 -i eth0 -p tcp -m conntrack --ctorigdstport 80 --ctdir ORIGINAL -j ACCEPT

@ jest نجاح باهر من المهم حقًا أن تعرف! لم أكن أدرك أنه يمكن أن تطابق الحزم في الاتجاه الآخر. من المنطقي عندما تفكر في الأمر ، لأنه يتطابق مع حالة الاتصال بالكامل ، ولكن من السهل تفويته عند قراءة المستندات.

SystemParadox نعم ، لم تتح لي الفرصة لإبلاغ نفسي من خلال المستندات وفوجئت بطلبات من Docker كانت معلقة في انتظار الردود. :)

أستمر في الدوران في دوائر مع أسباب الحاجة إلى --ctdir ORIGINAL . من ناحية ، فإن الشرح المقدم من

أعتقد أن الاختلاف هو أن لديّ -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT كقاعدة أولى ، لذا فإن بقية القواعد لا ترى أي حزم رد. في هذه الحالة ، أعتقد أن --ctdir ORIGINAL ليس مطلوبًا تمامًا ، على الرغم من أنه قد يكون من الأكثر أمانًا تضمينه على أي حال.

jest ، هل توافق على هذا؟ من المفترض أنه ليس لديك قاعدة ESTABLISHED,RELATED -j ACCEPT مبكرة ، فلماذا يحدث هذا فرقًا بالنسبة لك؟

jest رسالتك كانت مساعدة عظيمة ، شكرا.

هل نهجك مطلوب فقط للأشياء التي يديرها عامل الميناء ، أم لكل شيء؟ على سبيل المثال ، منفذ ssh (22) الخاص بي لا علاقة له برافعة السفن. هل أحتاج إلى استخدام -m tcp --dport 22 كالمعتاد ، أم يجب أن أستخدم -m conntrack --ctorigdstport 22 --ctdir ORIGINAL ؟

أفترض أن نهجك مطلوب فقط لحركة المرور التي يديرها عامل الإرساء ، حيث تخضع هذه الحزم للتشويه / النتوء قبل أن تصل إلي في جدول المرشحات. ولكن ، أنا جديد على iptables ، لذا أريد أن أتأكد من شخص يعرف أكثر مني!

@ lonix1 تتم إضافة القواعد بواسطة عامل الإرساء إلى سلسلة DOCKER فقط إذا قمت بكشف منفذ ، وربما فقط عندما تكون الحاوية قيد التشغيل. إذا لم تعرض المنفذ 22 في أي من الحاوية الخاصة بك ، فيجب أن تعمل قواعد جدار الحماية لديك بدون تعديل.

SystemParadox لقد مر بعض الوقت ولا يمكنني الوصول إلى هذا الخادم للتحقق ، ولكن إذا كنت أتذكر بشكل صحيح ، كانت هناك قواعد ESTABLISHED,RELATED (يديرها UFW ، في ufw-before-input chain). ومع ذلك ، في حالتي ، لن يتطابقوا مع الحزمة الأولى (SYN) من الاتصالات التي تم إجراؤها من عامل الإرساء إلى مضيفي الإنترنت على المنفذ 80. وسيتم إسقاطها من خلال القاعدة المتوافقة في DOCKER-USER عندما لا يكون هناك --ctdir .

@ Ionix1 ،

على سبيل المثال ، بالنظر إلى IP الخارجي 10.0.0.1 وحاويتين مع -p 4000:80 و -p 4001:80 ، سترى حزم بالخصائص التالية:

INPUT:
dst 10.0.0.1 dport 80 ctorigdst 10.0.0.1 ctorigdstport 80
FORWARD/DOCKER-USER:
dst 172.17.0.5 dport 80 ctorigdst 10.0.0.1 ctorigdstport 4000
dst 172.17.0.6 dport 80 ctorigdst 10.0.0.1 ctorigdstport 4001

لذلك يمكنك استخدام --dport 80 بأمان لقواعد INPUT ، لأنها في سلاسل منفصلة تمامًا. كما ترى ، سيظل --ctorigdstport 80 متطابقًا ، ولكن ما لم تكن تقوم أيضًا بتغيير المدخلات لسبب ما ، فربما لن أفعل ذلك.

قد تلاحظ أيضًا أنه يمكنك بالفعل استخدام --dport 80 مع --dst 172.17.0.5 لتصفية الحزم لحاوية عامل إرساء معينة ، لكن عنوان IP هذا لا يمكن التنبؤ به ، وهذا هو سبب استخدامنا --ctorigdstport .

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

jest شكرا ، يبدو أن هذا يؤكد تفكيري.

لذا ، فأنا بحاجة إلى القليل من التوجيه ... للتبديل من UFW إلى iptables ...
هل أقوم بإيقاف تشغيل UFW عبر "تعطيل ufw"؟
-هل أقوم بإنشاء ملف .sh الخاص بي ، أم أن هناك ملفًا موجودًا (أنا Ubuntu على DigitalOcean)؟
-أريد فقط أن أخبر Docker "--iptables = false"؟ (هذا كل شيء لـ Docker؟)
تم إنشاء -DOCKER-USER بالفعل وتقييده بواسطة Docker؟

fredjohnston يمكنك الاستمرار في استخدام /etc/ufw . المشكلة هنا هي أن Docker لن يظهر ب / ج ، ولا يوجد ملف تعريف للتطبيق مدرج في /etc/ufw/applications.d (نفس الشيء بالنسبة لأية أداة جدار حماية أخرى وتكوينها).

يعني تعطيل IPTables في Docker أنه لن يكون لديك الكثير من أي شبكة في Docker ، فقط عناوين IP والحاويات لن تكون قادرة على التحدث مع بعضها البعض. DOCKER_USER هو اختراق لمنحك بعض التحكم ، لكنه في الحقيقة لا يحل المشكلة - التي تتعلق حقًا بعدم جعل حاويات Docker عامة على الشبكة افتراضيًا ، ولكن مقفلة على عنوان IP للحاوية.

في الوقت الحالي ، أوصيك بالاستمرار في استخدام أي أداة جدار حماية تشعر بالراحة معها (ufw ، إلخ) ولكن كن مدركًا أن حاويات Docker ستكون عامة على شبكتك.

نظرًا لأنني هنا بأي طريقة - فأنا أواجه مشكلة ذات صلة الآن حيث هذه مشكلة على الأنظمة الأساسية بخلاف Linux أيضًا. ضع في اعتبارك ما يلي:

  • يحتوي المشروع A على حاويتين ، واحدة لقاعدة بيانات والأخرى لتطبيق.
  • يحتوي المشروع B على حاويتين ، واحدة لقاعدة بيانات والأخرى لتطبيق.
  • كلا المشروعين معزولان عن بعضهما البعض (مستودعات مصدر منفصلة ، تكوينات ، إلخ)
  • تتم إدارة كلا المشروعين ضمن Docker Compose
  • يعرض كلا المشروعين منافذ قاعدة البيانات الخاصة بهما لأغراض التنمية المحلية
  • يستخدم كلا المشروعين نفس خادم قاعدة البيانات (postgres ، mysql ، إلخ)

افترض الآن أنك تريد تشغيل كلا المشروعين محليًا - على سبيل المثال للعمل في مكتبة مشتركة يستخدمها كلا المشروعين بحيث يمكنك سحبها بسهولة إلى التعليمات البرمجية الخاصة بهم للاختبار.

في ظل التصميم الحالي لتفاعل جدار الحماية - وما يؤدي جزئيًا إلى المشكلات المذكورة أعلاه حول تعريض الحاوية للشبكة العامة دون علم المستخدم - لا يمكن تشغيل عمال رصيف قاعدة البيانات لكلا المشروعين في نفس الوقت نظرًا لأنهم سيكونون في تنافس على منفذ مكشوف لقاعدة البيانات. نفس الشيء إذا كنت ترغب في الكشف عن كل من منفذ التطبيق الخاص بهم وكلاهما يستخدم نفس المنفذ لخادم التطبيق - شائع لأن واجهات برمجة التطبيقات والتطبيقات المستندة إلى HTTP شائعة للغاية الآن خاصة في التطبيقات الموجهة نحو السحابة.

بالتأكيد يمكنك اختراق طريقك لإعداد كلاهما تحت حاوية DB واحدة ؛ لكنك لا تعزلهم حسب تصميم مشروعك ، ويجب أن تكون أكثر حرصًا بشأن التكوينات ، إلخ.

يوجد هنا شقان في الحل المناسب:

  1. ستكون الحاويات مرتبطة فقط بعناوين IP الخاصة بها وستكون منافذها المكشوفة مرتبطة بعناوين IP الخاصة بها وحدها داخل شبكات Docker الخاصة بها ، وليس على النظام الذي يتطابق مع جميع عناوين IP ( 0.0.0.0 ، :: ).
  2. لن يقوم Docker أيضًا بكشف المسار علنًا إلى Docker Networks خارج النظام افتراضيًا. يمكن استخدام Docker Networking لإنشاء اتصالات بين الشبكات (شبكة عامل إرساء إلى شبكة عامل إرساء) كما هو مُصمم حاليًا ، ثم السماح أيضًا باتصالات المضيف المحلي افتراضيًا.
  3. سيكون المستخدمون بعد ذلك في وضع السطر لإضافة قواعد جدار الحماية المناسبة لعرض الحاوية للعالم الخارجي عندما وإذا رغبت في ذلك - على سبيل المثال ، عن طريق منفذ إعادة التوجيه 443 إلى المنفذ 443 من الحاوية التي يختارونها.

مرة أخرى ، يمكن القيام بذلك تدريجيًا:

  • الإصدار 1: تنفيذ الخطوتين 1 و 2 ؛ ولكن أضف توجيه غير مضيف محلي أيضًا (مؤقتًا) مع تحذير. الحفاظ على السلوك الحالي لمن يأتي أولاً يخدم أولاً للحصول على منفذ ؛ ويتم إصدار تحذير بشأن اختفاء هذا السلوك.
  • الإصدار 1 + N: قم بإسقاط التحذير وإسقاط التوجيه غير المضيف المحلي. اطلب الخطوة 3 للمستخدمين الذين يريدون Docker لكشف المنافذ خارج النظام والتأكد من توثيق ذلك جيدًا.

DOCKER_USER هو اختراق لمنحك بعض التحكم ، لكنه في الحقيقة لا يحل المشكلة - التي تتعلق حقًا بعدم جعل حاويات Docker عامة على الشبكة افتراضيًا ، ولكن مقفلة على عنوان IP للحاوية.

في الوقت الحالي ، أوصيك بالاستمرار في استخدام أي أداة جدار حماية تشعر بالراحة معها (ufw ، إلخ) ولكن كن مدركًا أن حاويات Docker ستكون عامة على شبكتك.

يوجد طلب تحديث مستند هنا https://github.com/docker/docker.github.io/pull/8357 لإنشاء تكوين iptables ثابت مثبت ولكني لست متأكدًا من حالته.

تحرير: لقد لاحظت أنك أساءت فهم معنى DOCKER-USER. لا يتم استخدامه "لجعل الحاويات مقفلة بعنوان IP للحاوية" ولكن لتصفية الوصول إلى الحاوية بقواعد iptables.

@ aki-k لكل DOCKER_USER أعلم أن DOCKER_USER لا يقفل الحاوية مقابل عنوان IP ولم ادعِ أبدًا أنها فعلت ذلك. DOCKER_USER ببساطة بتحويل مشكلة الأمان إلى المستخدم لإدارتها - مما يعني أن المستخدم يجب أن يعرف كيفية التعامل مع جدار الحماية الخاص به للتأكد من أن لديه بالفعل بيئة آمنة. يعتبر جعلها مشكلة للمستخدم غير مقبول أيضًا لأن معظم المستخدمين لا يعرفون كيفية إدارة جدار الحماية الخاص بهم - قواعد جدار الحماية صعبة ، وحتى أولئك منا الذين يعرفون الكثير عن كتابة قواعد جدار الحماية يمكن أن يخطئوا في كثير من الأحيان.

طلبي - والنقطة الكاملة - في المشكلة هو أن Docker يحتاج إلى أن يكون آمنًا بشكل افتراضي ولا يعرض الحاويات للعالم الخارجي دون معرفة المستخدم أو التدخل الصريح للقيام بذلك. ووفقًا لتعليقي الأخير (https://github.com/moby/moby/issues/22054#issuecomment-552951146) فإن القيام بذلك سيكون له أيضًا بعض الفوائد التقنية الأخرى أيضًا.

طلبي - والنقطة الكاملة - في المشكلة هو أن Docker يحتاج إلى أن يكون آمنًا بشكل افتراضي ولا يعرض الحاويات للعالم الخارجي دون معرفة المستخدم أو التدخل الصريح للقيام بذلك.

أقدم تقرير مشكلة وجدته عن هذا الأمر يعود إلى 18 مارس 2014:

https://github.com/moby/moby/issues/4737

من المحتمل أنه قرار تصميم لا يريدون تغييره ومحاولة إصلاحه باستخدام سلسلة iptables DOCKER-USER. يمكنك استخدام الخيار -p لتشغيل عامل الإرساء لنشر المنفذ فقط على مضيف عامل الإرساء (-p 127.0.0.1:port:port) ولكن هذا لا يحل المشكلة أيضًا.

لنكن واضحين، عامل الميناء هو آمن افتراضيا. عليك إخبار Docker بالقيام بإعادة توجيه المنفذ.

بالنسبة للخدمات التي تحتاج إلى التواصل مع بعضها البعض ، يجب أن تستخدم الشبكات ( docker network ) لتقييد الوصول وليس إعادة توجيه المنفذ.

لنكن واضحين ، Docker _Is_ آمن افتراضيًا. عليك إخبار Docker بالقيام بإعادة توجيه المنفذ.

من فضلك لا ترفض مشكلة واقعية مع عامل ميناء يعمل على حماية iptables الخاصة بك. أنا متأكد من أنك رأيت عدد لا يحصى من تقارير المشكلات التي تناقش هذا الأمر.

لنكن واضحين ، Docker _Is_ آمن افتراضيًا. عليك إخبار Docker بالقيام بإعادة توجيه المنفذ.

بالنسبة للخدمات التي تحتاج إلى التواصل مع بعضها البعض ، يجب أن تستخدم الشبكات ( docker network ) لتقييد الوصول وليس إعادة توجيه المنفذ.

لنكن واضحين - Docker آمن حتى تريد الوصول إليه خارج شبكة عامل الإرساء. بمجرد أن ترغب في الوصول إليه حتى من المضيف المحلي (127.0.0.1) ، فإن Docker ليس آمنًا بشكل افتراضي لأنه يرتبط بـ 0.0.0.0 ويكشف الحاويات خارج النظام - متجاوزًا أي شيء يفعله المستخدم لتأمين نظامه ، دون الظهور في الأدوات بخلاف الاستخدام المباشر لـ iptables . DOCKER_USER لا ولن يكون حلاً مناسبًا على الإطلاق لأنه يتطلب من المستخدم معرفة الكثير عن نظام جدار الحماية الأساسي (iptables على نظام Linux ، وأيًا كان ما يستخدمه Mac ، وجدار حماية Windows على Windows). هذا لا يزال بحاجة إلى أن يكون آمنًا بشكل افتراضي. هناك طريقة سهلة للغاية للقيام بذلك كما أوضحت سابقًا في https://github.com/moby/moby/issues/22054#issuecomment -552951146 واستدعيت عدة مرات خلال هذه المشكلات (على الرغم من أنه ربما ليس بنفس الوضوح في ذلك تعليق).

لاحظ أيضًا أن الوثائق الخاصة بكشف منفذ لا تذكر مشكلة الأمان هذه أيضًا ، ولا تشير إلى كيفية تفاعل Docker مع جدار حماية النظام عند تعريض منفذ - وبالتالي تقليل الأمان على الأنظمة التي تم تصميمها لتكون آمنة حتى يتم استخدام Docker .

لنكن واضحين ، Docker _Is_ آمن افتراضيًا. عليك إخبار Docker بالقيام بإعادة توجيه المنفذ.
بالنسبة للخدمات التي تحتاج إلى التواصل مع بعضها البعض ، يجب أن تستخدم الشبكات ( docker network ) لتقييد الوصول وليس إعادة توجيه المنفذ.

لنكن واضحين - Docker آمن حتى تريد الوصول إليه خارج شبكة عامل الإرساء. بمجرد رغبتك في الوصول إليه حتى من مضيف محلي (127.0.0.1) ، يكون Docker _not_ آمنًا افتراضيًا لأنه يرتبط بـ 0.0.0.0 [...]

على وجه الدقة ، لا يرتبط Docker بـ 0.0.0.0. هذا هو التوقع (المعقول) للمستخدم: أن تحديد --publish على CLI ، ومن ثم التشغيل في مساحة المستخدم ، يبدأ نوعًا من البرنامج الخفي للوكيل الذي يستمع إلى المنفذ المحدد ، ويقبل الاتصالات الواردة ويدفع للخلف وللأمام جميع الحزم بين Docker والعالم الخارجي.

ولكن بدلاً من ذلك ، يقوم Docker بحقن قواعد DNAT / masquarading السحرية في جدار الحماية لإعادة كتابة العناوين الموجودة على الحزمة ، وبالتالي كسر عشوائيًا لأي نظام قواعد مثبت مسبقًا.

في رأيي ، فإن العبث بمستويات التجريد هنا هو أكبر مشكلة تربك المستخدم. لا أعرف السيناريوهات التي أخذها فريق Docker في الاعتبار عند تصميم الماكينة --publish التي نراها هنا ، لا أرى أيًا منها يبرر القرار (ربما بجانب أسباب الأداء).

لنكن واضحين ، Docker آمن افتراضيًا. عليك إخبار Docker بالقيام بإعادة توجيه المنفذ.

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

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

دعونا نقيم الوضع كما هو اليوم:

بشكل افتراضي ، لا يتم كشف أي منافذ. عليك إخبار Docker بفضح منفذ.
في الماضي ، كان Docker يقوم بإعداد iptables بحيث يتمكن أي شيء يعرف كيفية التوجيه إلى شبكة الجسر من الوصول إلى عنوان IP للحاوية (عن طريق تعيين سياسة التوجيه على "قبول") ، لكن هذا لم يعد صحيحًا.

لقد رأيت بعض الأشخاص يقولون إنهم يستخدمون -p لفضح الخدمات لبعضهم البعض ، وهو ما لا ينبغي أن يكون مطلوبًا.
على الشبكة الافتراضية ، يمكنك استخدام --link لتوصيل الخدمات معًا ، الحاوية متاحة عبر DNS.
في الشبكات غير الافتراضية (الشبكات التي يحددها المستخدم) ، يمكن للحاويات الوصول إلى بعضها البعض عن طريق DNS أيضًا ، بما في ذلك إعداد الأسماء المستعارة عبر --link ، أو حتى إلى شبكة ذات اسم مستعار محدد.

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

-p خصيصًا للدخول ، كما هو الحال في السماح للأشياء الخارجية بالوصول إلى هذه الخدمة.
الإعداد الافتراضي لـ -p هو في الواقع السماح بالمرور من أي مكان. يمكنك تغيير هذا عن طريق تحديد العنوان يدويًا للسماح به إما لكل -p أو كإعداد خفي على نطاق واسع.
نظرًا لأن -p يستخدم iptables ، فقد تم إنشاء سلسلة DOCKER-USER حتى يتمكن المستخدمون من إضافة قواعد التصفية الخاصة بهم قبل أن تصل إلى الحاوية.

نظرًا لأن -p مصمم للدخول ، أعتقد أنه من المعقول أن يكشف هذا عن حركة المرور كما هو الحال. أشعر أنه من المؤسف أن يتم إدراج قواعد Docker في الجزء العلوي من جدول التصفية ، ولكن تغيير هذا سيكون تغييرًا جذريًا لمجموعة كبيرة من المستخدمين الذين يريدون هذا السلوك.

هناك نوعان من البدائل الأخرى لـ -p :

  1. لا تستخدم -p ، اتصل بـ IP للحاوية مباشرة. يتطلب هذا القليل من العمل الإضافي حيث يتعين عليك البحث عن عنوان IP ، ولكن هذه البيانات متاحة من واجهة برمجة التطبيقات. ستحتاج أيضًا إلى التأكد من أن سياسة إعادة التوجيه على جدار الحماية تسمح بذلك (بافتراض أنك تتصل من مضيف مختلف ، يجب أن يكون المضيف نفسه جيدًا)
  2. استخدم شبكة macvlan أو ipvlan للخدمات التي تريد الوصول إليها من شبكة المضيف (أي الدخول). تمنح خيارات الشبكة هذه الحاوية عنوان IP مباشرة من واجهة شبكة المضيف (تختار الواجهة التي ترتبط بها).
  3. استخدم --net=host ، فهذا يؤدي إلى تشغيل الخدمة على مساحة اسم الشبكة المضيفة ، مما يمنح وصول الخدمة إلى البنية التحتية للشبكة الموجودة بالفعل على المضيف.

أنت تقول "اجعل هذا آمنًا بشكل افتراضي" ، ولكن كشف منفذ هو بحكم التعريف إجراء غير آمن محتمل. يبدو أيضًا أن هناك فكرة أن التعريض للمضيف المحلي آمن فقط ، ولكن ليس لأن أي شيء يتم تشغيله على المضيف يمكنه الوصول إلى المضيف المحلي (بما في ذلك جافا سكريبت في المتصفح إذا كان سطح مكتب).

ما هي حالة الاستخدام التي تحاول حلها باستخدام -p ؟
هل لديك بعض الأفكار حول التغيير الفعلي الذي ترغب في رؤيته؟

أنا على ما يرام في تغيير شيء ما لجعل هذا أفضل لسير عملك ، ولكن هناك الكثير من حالات الاستخدام المختلفة هنا وحجم واحد لا يناسب الجميع أبدًا (راجع الشكاوى حول -p ).

@ cpuguy83 هذا كل شيء على ما يرام ومدهش ، لكن لا يغير شيئًا في هذا الطلب.

يستخدم الأشخاص عامل الإرساء ويريدون الاتصال بالتطبيقات التي تعمل تحت عامل الإرساء من نظامهم المحلي - هذه حالة استخدام شائعة للغاية للمطورين خاصة عند محاولة تشخيص شيء ما أو كتابة خدمة ليست ضمن عامل الإرساء ولكنها تحتاج إلى الاتصال بالخدمات المستضافة في عامل الإرساء (لملء بيئة التطوير). لا يعد التطوير تحت Docker دائمًا تجربة جيدة أو ممتعة أو مفيدة سواء قيل:

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

هو ببساطة أمر محظور. ليست كل الأدوات متوافقة مع Docker ، ولا يجب أن تكون كذلك. لا ينبغي أن يُطلب من المستخدم أن يكون تحت Docker بالكامل للاستفادة من الخدمات التي تعمل تحت Docker. وحتى مع ذلك ، إذا تم استخدام Docker لتشغيل الخوادم ، فلن يتمكن المسؤول من التحكم فيها بسهولة عبر تكوين جدار الحماية ووظيفة Expose Port ولكن يتم تنظيمها (سطر الأوامر ، Dockerfile ، Docker Compose Config) معطل تمامًا.

علاوة على ذلك ، يستخدم الأشخاص Docker Compose لإدارة جزء كبير من البيئة ، ويحددون عبر docker-compose.yml أو Dockerfile أن المنفذ يحتاج إلى الكشف حتى يتمكنوا من الوصول إليه محليًا. لذلك فإن قول المعلمة use the -p غير صحيح لأنها لا تتفاعل أبدًا مع أمر docker مباشرة بطريقة تعمل.

كشف المنفذ لا يعني أنه يجب كسر الأمن. لقد أوضحت كيف يمكنك تعريض منفذ للنظام المحلي دون كسر الأمان (https://github.com/moby/moby/issues/22054#issuecomment-552951146) وسيؤدي ذلك إلى وضع إدارة التعرض الخارجي (إيقاف) النظام) في يد المستخدم بطريقة يمكنهم التحكم بها بسهولة باستخدام الأدوات الموجودة لديهم.

حل:

  • استخدم Docker Network
  • كشف المنافذ على شبكة Docker وحدها والمضيف المحلي
  • توقف عن ربط المنفذ بـ 0.0.0.0 - أو فعل ذلك بشكل فعال
  • مطالبة المستخدمين باستخدام أدوات جدار الحماية الخاصة بهم لعرض نظام إيقاف المنفذ (ufw ، جدار الحماية ، إلخ)
  • توفير عمليات تكامل لجدران الحماية الشائعة لتسهيل ذلك

بمعنى آخر ، بدلاً من الوصول إلى خدمة في حاوية عامل إرساء عبر 127.0.0.1:<port> تتطلب <docker container ip>:<service port> حتى من المضيف المحلي. إذا أراد الأشخاص الكشف عن الخدمة خارج النظام ، فيمكنهم إضافة قاعدة جدار حماية عبر أدواتهم (ufw ، إلخ) لإعادة التوجيه من منفذ معين إلى <docker container ip>:<service port> .

بدلاً من ذلك ، اتبع نهج Kubernetes مع تصميم Proxy الخاص بهم ، وقم بعمل فعال كما jest في https://github.com/moby/moby/issues/22054#issuecomment -554665865. مرة أخرى ، سيظل هذا بحاجة إلى أن يكون نظامًا محليًا فقط حتى يقوم المستخدم بتعريض ذلك عن قصد للشبكة الخارجية.

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

أدرك أن هناك الكثير من واجهات جدار الحماية في السوق - حتى مع iptables ، هناك جدار حماية و ufw وعشرات أخرى. لا أتوقع حقًا أن يتكامل Docker معهم (على الرغم من أن ذلك سيكون رائعًا) ، لكنني أتوقع أن يعمل Docker بطريقة لا تتجاوزهم أو تكسر أي أمان قام المستخدم بإعداده.

كحالة اختبار أساسية:

  • قم بإعداد خادم مستند إلى Debian (Debian ، Ubuntu)
  • قم بتثبيت ufw ، خادم OpenSSH
  • تشغيل ufw allow OpenSSH
  • تشغيل ufw enable

في هذه المرحلة يكون لديك خادم آمن جدًا ؛ حركة المرور الوحيدة المسموح بها هي إما (أ) تتعلق بحركة المرور الصادرة أو (ب) حركة خادم SSH.

الآن ، ابدأ حاوية عامل ميناء مع منفذ مكشوف.

الحل المقبول يفي بما يلي:

  • يجب ألا يكون المنفذ قابلاً للوصول من كمبيوتر آخر ؛ يجب أن يستمر جدار الحماية في منعه من الأنظمة الخارجية.
  • يجب أن يكون المنفذ متاحًا من الكمبيوتر المحلي (المضيف المحلي).
  • يجب أن تكون حاويات الرصيف المتعددة قادرة على كشف نفس المنفذ وعمل كل شيء ؛ يجب أن يكون الوصول إلى جميع الحاويات ذات المنفذ المكشوف متاحًا من النظام المحلي فقط.
  • لا يجب على المستخدم أن يعرف تفاصيل تكوين جدار الحماية الخاص به لتحقيق ذلك.

جرب نفس الشيء مع نظام قائم على CentOS / Fedora / RHEL firewalld .

@ cpuguy83 يتوقع أشخاص IMO أن يعمل -p على مستوى التطبيق. أي ، إذا كنت -p 80:80 ، أتوقع السلوك كما لو كان التطبيق المرتبط بالمنفذ 80 في الحاوية يعمل على المضيف.

إعادة توجيه منافذ نموذج VirtualBox أو SSH بهذه الطريقة ، لذلك يفترض الناس أن الأمر نفسه في حالة Docker.

لاستخدام توقعات أوسع موازية: من وجهة نظر المستخدم ، يجب أن تعمل كمجلدات مرتبطة بالمضيف. أنت فقط تشير إلى الدليل المضيف ، و "كالسحر" يكون مرئيًا داخل الحاوية ؛ أي تعديلات يتم إجراؤها على نظام الملفات من الجانب الآخر تعمل بنفس الطريقة ، بما في ذلك الأذونات والحصة وما إلى ذلك.

تقليص مشكلات -p لحالات جدار الحماية: في العالم الطبيعي يتوقع المستخدم أن يكون التطبيق المرتبط بـ 0.0.0.0:80 مرئيًا للعالم الخارجي. إذا أراد المستخدم تقييد الوصول ، فسيتم توجيهه في أدلة عديدة لاستخدام جدار حماية وإعداد قاعدة في سلسلة INPUT :

-P INPUT DROP
-A INPUT -s 1.2.3.4/32 -p tcp --dst-port 80 -j ACCEPT

أو استخدم أدوات مثل UFW:

ufw enable
ufw allow http

ولكن مع عامل الإرساء ، يجب أن يكون المستخدم قادرًا على إنشاء مثل هذه القواعد من اللون الأزرق:

-A DOCKER-USER -s 1.2.3.4/32 -i eth0 -p tcp -m conntrack --ctorigdstport 80 --ctdir ORIGINAL -j ACCEPT
-A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 80 --ctdir ORIGINAL -j DROP

من فضلك ، أرني دليلاً شاملاً للمستخدم العادي حول كيفية حل مثل هذه السيناريوهات الشائعة باستخدام Docker.

وعلى سبيل المثال ، لمطور متوسط ​​- الذي كنت تبيع له مفهوم "حاوية التطبيق" بالكامل - فإن عواقب الكشف عن منفذ لا يمكن التنبؤ بها.

في هذه الأيام ، لا أكشف ببساطة عن المنافذ بسبب قلة معرفتي ، وأستخدم خدمات مثل Traefik بدلاً من ذلك. ربما لا ينبغي أيضًا اقتراح --expose كغرض عام في مستندات CLI ، لأن IMO لا يفيد المستخدم العادي.

أو قم بتزويد أي شخص ليس لديه معرفة عميقة بهذه الأدوات بجهاز كمبيوتر محمول يعمل بنظام Linux ، مثل Dell أو Lenovo ، وشاهد كيف أن جهودهم الحسنة في إعداد جدران الحماية الخاصة بهم بشكل صحيح لا تحدث أي فرق على الإطلاق عندما يتمكن شخص ما من الوصول إلى قاعدة البيانات المحلية الخاصة بهم أثناء تناول القهوة في ستاربكس.

تسببت هذه المشكلة بالضبط في وجود ثغرة أمنية في النظام بالنسبة لنا اكتشفتها خلال عطلة نهاية الأسبوع. Perjacoscaz ، لقد تمكنت للتو من الاستفادة من قاعدة البيانات المحلية لمطور آخر لأنها تحتوي على منفذ منشور. سيكون من الرائع أن تقوموا جميعًا بتضمين ذلك في وثائق المقدمة حتى لا يفعل الآخرون الشيء نفسه. نحن بحاجة إلى خدمة غير معبأة في حاويات للاتصال بحاوية دون وصول أي شخص آخر على الشبكة ، لذلك فإن شبكات Docker غير واردة. يبدو أن أفضل خيار في الوقت الحالي هو الاتصال بعنوان IP المحلي للحاوية ، ما لم يكن لدى أي شخص فكرة أفضل.

dentonmwood هذا يبدو تمامًا مثل ما يجب عليك فعله. كما ذكرت أعلاه ، يمكنك حتى إعداد الخدمة للتشغيل باستخدام macvlan أو ipvlan مما يمنحها IP مباشرة على شبكتك العادية.

BenjamenMeyerjestjacoscaz

شكرا لردود الفعل الاضافية

أوافق على أن المعرفة التي نطلب من المستخدمين طرحها في هذا الصدد ليست كبيرة. نضع المسؤولية حاليًا على عاتق المستخدم (سواء كان مسؤول نظام أو مطور) لفهم ما يفعله -p ولاتخاذ الاحتياطات المناسبة لضمان تعرض الخدمة فقط لمن يعتقدون أنها تتعرض له. لقد اتخذنا هذه الخطوة إلى الأمام حتى من خلال توقع أن المطورين الذين ليس لديهم غالبًا أي سبب لمعرفة iptables سيتدخلون ويصلحون الأمر لبيئتهم الخاصة (عبر DOCKER-USER ).
نحن في هذا الموقف أساسًا بسبب مخاوف من كسر التوافق.

لدي بعض الأفكار التي لم يتح لي الوقت للتفكير فيها بشكل كامل حتى الآن ، ولكنها ستغير بشكل أساسي سلوك -p بناءً على إصدار API للعميل والتعامل مع الإدخال بشكل منفصل. لا يزال هناك تغيير كبير يقلقني ولكن يتم الاحتفاظ بالسلوك القديم على الأقل في إصدارات API القديمة.

لقد فكرت في أنه يمكننا عمل وكيل محلي (ala kubectl proxy ) لحالة استخدام الوصول المحلي ، ولكن هذا يضع المسؤولية مرة أخرى على عاتق المطور لمعرفة وفهم أكثر مما يحتاجون إليه حقًا .

أفكار؟

أعتقد أن تقديم الوكيل هو خطوة في الاتجاه الصحيح.

أقر بأن "إعادة توجيه المنفذ" هي مسؤولية مشتركة بين الحاوية والمنسق ، مماثلة في الروح لوضع Swarm. لكن الحد الأدنى من تكامل المضيف مطلوب دائمًا وعند إعطاء خيار مثل -p للمستخدم (غير الخبراء) ، يجب أن يكون الحل المقترح مفهوماً لمثل هذا الشخص.

نظرًا لأن عواقب -p على البيئة لم يتم تحديدها (على الأقل على مستوى CLI ، على ما أعتقد) ، فهناك إمكانية لتقديم تكوين سهل الاستخدام للطريقة التي يعمل بها.

على سبيل المثال ، يوجد في الوقت الحالي iptables في /etc/docker/daemon.json والذي يحدد ما إذا كان يجب التعامل مع DOCKER أم لا. يمكن تمديد التكوين بإدخال آخر ، مثل هذه المجموعة مثل iptables==true && expose_with_network_proxy==true ستعمل على تبديل السلوك الذي يشبه الخادم الوكيل.

يجب أن يكون هذا آمنًا بشكل عام للتثبيتات الجديدة ، كما كان يفضل overlay2 على aufs منذ بعض الوقت (إذا كنت أتذكر بشكل صحيح). ويمكن نشره بسهولة على هذا النحو ، لأن الترقيات لا تلمس ملفات التكوين الحالية ، ولكن التثبيتات الجديدة مجانية.

نحن في هذا الموقف أساسًا بسبب مخاوف من كسر التوافق.

أود حقًا التأكيد على حقيقة أن خطورة هذه المشكلة ، على الأقل من وجهة نظري ، تتعلق بنقص الوثائق أكثر من ارتباطها بالأسس التقنية الحالية البالغة -p . نعم ، لا أعتقد أنه يمكن القول أن الآلية الحالية "آمنة" ، ولكن يمكن إصلاح الثغرات الأمنية ولست في وضع يسمح لي بانتقاد الأسباب التي أدت إلى السيناريو الحالي. الإدراك المتأخر دائمًا هو 20/20 ، بعد كل شيء ، وأنا معجب بالالتزام بالتوافق مع الإصدارات السابقة والاستعداد لمواجهة التحديات التقنية التي يجلبها هذا الالتزام.

ما لم أحصل عليه هو سبب عدم وجود مربعات حمراء كبيرة ساطعة عبر وثائق Docker تحذر صراحة من الآثار الجانبية لاستخدام -p . لو صادفت مثل هذا التحذير ، فلا أعتقد أنني سأكون هنا في المقام الأول.

أفكار؟

يبدو خيار الوكيل معقولاً. بالإضافة إلى ذلك ، أحب فكرة أن أكون قادرًا على كشف المنافذ وإلغاء كشفها عند الحاجة بدلاً من الالتزام بالقيام بذلك أثناء إطلاق docker run .

BenjamenMeyerjestjacoscaz

شكرا لردود الفعل الاضافية

شكرا أخيرا للنظر في هذا عن كثب.

أوافق على أن المعرفة التي نطلب من المستخدمين طرحها في هذا الصدد ليست كبيرة. نضع المسؤولية حاليًا على عاتق المستخدم (سواء كان مسؤول نظام أو مطور) لفهم ما يفعله -p ولاتخاذ الاحتياطات المناسبة لضمان تعرض الخدمة فقط لمن يعتقدون أنها تتعرض له. لقد اتخذنا هذه الخطوة إلى الأمام حتى من خلال توقع أن المطورين الذين ليس لديهم غالبًا أي سبب لمعرفة iptables سيتدخلون ويصلحون الأمر لبيئتهم الخاصة (عبر DOCKER-USER ).
نحن في هذا الموقف أساسًا بسبب مخاوف من كسر التوافق.

لدي بعض الأفكار التي لم يتح لي الوقت للتفكير فيها بشكل كامل حتى الآن ، ولكنها ستغير بشكل أساسي سلوك -p بناءً على إصدار API للعميل والتعامل مع الإدخال بشكل منفصل. لا يزال هناك تغيير كبير يقلقني ولكن يتم الاحتفاظ بالسلوك القديم على الأقل في إصدارات API القديمة.

أفكار؟

  1. ابدأ بتحديث الوثائق حتى يدرك المستخدمون تأثير EXPOSE من جميع الطرق (-p ، Dockerfile ، docker-compose.yml). يمكن القيام بالكثير بسرعة. قد يساعد أيضًا في الحصول على بعض الاهتمام بشأن المشكلة للحصول على المزيد من الأشخاص الذين يقدمون المشورة / الخبرة في إيجاد حل جيد والمساعدة في الإجابة إذا كانت هناك رغبة مجتمعية في التوافق مع الإصدارات السابقة أيضًا.
  2. خطط لطريقة للانتقال من حيث يوجد Docker الآن إلى حيث يجب أن يكون Docker. يمكن أن يشمل ذلك تغييرًا مفاجئًا في مرحلة ما.

أعتقد أن خطورة الموقف تسمح بالتأكيد بتغيير جذري لإصلاحه ؛ فقط لا تفعل ذلك دون إعلام الناس. ضع جدولًا زمنيًا (6 أشهر؟ 12 شهرًا؟) حيث تتم مناقشة التغيير بشكل مكثف ، وما إلى ذلك ، وقم بإعداد المجتمع ؛ ثم في إصدار "رئيسي" إجراء التغيير. بناءً على مخطط الإصدار الخاص بك ، يبدو أن المجموعة الأولى هي العام (19) ؛ نظرًا لأننا في نهاية عام 2019 ، استخدم ما تبقى من عام 2019 ثم عام 2020 للتوصل إلى الحل والإعلان عنه ؛ قدمها كميزة اختيارية في وقت ما في عام 2020 ثم قم بترقيتها إلى المرتبة الأولى / الاستخدام الافتراضي في عام 2021.

قد يكون إصدار Dockerfile و Docker Compose Schema Version أدوات جيدة أيضًا فيما يتعلق بتعيين السلوك الافتراضي ، لكنني لن أحظر الإصدارات القديمة من القدرة على الاستفادة منها ، وسأضع تحذيرًا قويًا بشأن الحاجة إلى التحديث في مثل هذه الحالة أيضًا.

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

لقد فكرت في أنه يمكننا عمل وكيل محلي (ala kubectl proxy ) لحالة استخدام الوصول المحلي ، ولكن هذا يضع المسؤولية مرة أخرى على عاتق المطور لمعرفة وفهم أكثر مما يحتاجون إليه حقًا .

تعجبني فكرة الوكيل ، وقد يكون اقتراح

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

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

تعجبني فكرة الوكيل ، وقد يكون اقتراح

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

أنا أردد هذا. باستخدام حل الوكيل ، أعتقد أنه سيكون من الممكن التوصل إلى شيء يسمح للمستخدمين بربط الوكيل بأي مجموعة من الواجهة (الواجهات) والمنافذ (المنافذ) التي يريدونها. ومع ذلك ، إذا أُجبرت على التنازل باسم التوافق مع الإصدارات السابقة (التي أؤيدها!) أو أي سبب آخر ، فيجب إعطاء الأولوية لمطابقة توقعات الأمان المعقولة ، حتى على حساب تفويض التعرض خارج النظام للمستخدمين.

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

يتجاوز Docker جدار حماية macOS كما يفعل في Linux.

على جهاز التطوير الخاص بي (Docker Desktop for Mac) أضفت "ip": "127.0.0.1" إلى تكوين Docker daemon. بهذه الطريقة ، أي قواعد بيانات تطوير وما إلى ذلك ستكون متاحة افتراضيًا فقط من المضيف المحلي. بالنسبة لتلك الحالات النادرة التي أحتاج إلى جعل التطبيق مرئيًا للآخرين ، يمكنني نشره بشكل صريح باستخدام -p 0.0.0.0:8080:8080 .

تحرير: يبدو أن Docker Compose لا يزال ملزمًا بـ 0.0.0.0 افتراضيًا ، بغض النظر عن تكوين Docker daemon. لذلك تعمل هذه الحيلة فقط عند تشغيل Docker من سطر الأوامر. وعلى أي حال ، نظرًا لأن ملفات الإنشاء غالبًا ما تتم مشاركتها مع زملائه في الفريق الذين قد يكون لديهم تكوين نظام مختلف ، فمن الأفضل إضافة 127.0.0.1 بشكل صريح إلى ملف الإنشاء.

luontola يا له من حل أنيق.

تحرير: ما كنت أفكر فيه أيضًا ربما كان طريقة للحصول على قائمة السماح / الحظر بالعناوين التي يمكن تحديدها على سبيل المثال Docker التي سيتم إضافتها تلقائيًا إلى سلسلة DOCKER-USER iptables.

ديزي صغير يسلط الضوء على أهمية هذه المشكلة: https://github.com/docker/for-linux/issues/810 (ملخص: تمت إزالة DOCKER-USER لذا حتى إذا قمت بتكوين iptables لحظر الوصول الخارجي لعمال الرصيف ، سيتجاهل هذا التكوين الإضافي ويكشف جميع الحاويات)

يمكن لتعليقات

هممم قراءة ممتعة!

أنا أعمل على نظام التشغيل Mac OS X ولدي أيضًا جدار حماية محلي يسمى LittleSnitch. لقد ظهر مربع حوار يسأل عما إذا كان من المناسب 185.156.177.252 الاتصال بعملية com.docker.backend. لقد ضغطت على الإنكار.

كنت أتساءل كيف يمكنه فتح منفذ للأمام في جهاز التوجيه الخاص بي ، لكنني أدركت للتو أن هذا يتم بالطبع عبر UPnP! تدعم جميع أجهزة التوجيه هذا.

ما أتساءل الآن هو لماذا. لماذا يحاول شيء من 185.156.177.252 الاتصال من الخارج؟ إذا احتاجت عملية Docker المحلية الخاصة بي إلى شيء ما ، فيجب أن تتصل بالمنزل من الداخل ، وليس فتح منفذ من الخارج.

@ cpuguy83 هذا كل شيء على ما يرام ومدهش ، لكن لا يغير شيئًا في هذا الطلب.

يستخدم الأشخاص عامل الإرساء ويريدون الاتصال بالتطبيقات التي تعمل تحت عامل الإرساء من نظامهم المحلي - هذه حالة استخدام شائعة للغاية للمطورين خاصة عند محاولة تشخيص شيء ما أو كتابة خدمة ليست ضمن عامل الإرساء ولكنها تحتاج إلى الاتصال بالخدمات المستضافة في عامل الإرساء (لملء بيئة التطوير). لا يعد التطوير تحت Docker دائمًا تجربة جيدة أو ممتعة أو مفيدة سواء قيل:

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

هو ببساطة أمر محظور. ليست كل الأدوات متوافقة مع Docker ، ولا يجب أن تكون كذلك. لا ينبغي أن يُطلب من المستخدم أن يكون تحت Docker بالكامل للاستفادة من الخدمات التي تعمل تحت Docker. وحتى مع ذلك ، إذا تم استخدام Docker لتشغيل الخوادم ، فلن يتمكن المسؤول من التحكم فيها بسهولة عبر تكوين جدار الحماية ووظيفة Expose Port ولكن يتم تنظيمها (سطر الأوامر ، Dockerfile ، Docker Compose Config) معطل تمامًا.

علاوة على ذلك ، يستخدم الأشخاص Docker Compose لإدارة جزء كبير من البيئة ، ويحددون عبر docker-compose.yml أو Dockerfile أن المنفذ يحتاج إلى الكشف حتى يتمكنوا من الوصول إليه محليًا. لذلك فإن قول المعلمة use the -p غير صحيح لأنها لا تتفاعل أبدًا مع أمر docker مباشرة بطريقة تعمل.

كشف المنفذ لا يعني أنه يجب كسر الأمن. لقد أوضحت كيف يمكنك تعريض منفذ للنظام المحلي دون كسر الأمان ( # 22054 (تعليق) )

حل:

* Use Docker Network

* Expose the Ports on the Docker Network alone and local host

* Stop binding the port on 0.0.0.0 - or effectively doing so

* Require users to use their own firewall tooling to expose the port off system (ufw, firewalld, etc)

* Provide integrations for common firewalls to make this easy

بمعنى آخر ، بدلاً من الوصول إلى خدمة في حاوية عامل إرساء عبر 127.0.0.1:<port> تتطلب <docker container ip>:<service port> حتى من المضيف المحلي. إذا أراد الأشخاص الكشف عن الخدمة خارج النظام ، فيمكنهم إضافة قاعدة جدار حماية عبر أدواتهم (ufw ، إلخ) لإعادة التوجيه من منفذ معين إلى <docker container ip>:<service port> .

بدلاً من ذلك ، اتبع نهج Kubernetes مع تصميم الوكيل الخاص بهم ، وقم بعمل فعال كما jest في # 22054 (تعليق) . مرة أخرى ، سيظل هذا بحاجة إلى أن يكون نظامًا محليًا فقط حتى يقوم المستخدم بتعريض ذلك عن قصد للشبكة الخارجية.

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

أدرك أن هناك الكثير من واجهات جدار الحماية في السوق - حتى مع iptables ، هناك جدار حماية و ufw وعشرات أخرى. لا أتوقع حقًا أن يتكامل Docker معهم (على الرغم من أن ذلك سيكون رائعًا) ، لكنني أتوقع أن يعمل Docker بطريقة لا تتجاوزهم أو تكسر أي أمان قام المستخدم بإعداده.

كحالة اختبار أساسية:

* Setup a Debian-based server (Debian, Ubuntu)

* Install ufw, OpenSSH Server

* run `ufw allow OpenSSH`

* run `ufw enable`

في هذه المرحلة يكون لديك خادم آمن جدًا ؛ حركة المرور الوحيدة المسموح بها هي إما (أ) تتعلق بحركة المرور الصادرة أو (ب) حركة خادم SSH.

الآن ، ابدأ حاوية عامل ميناء مع منفذ مكشوف.

الحل المقبول يفي بما يلي:

* The port should not be accessible from another computer; the firewall should continue to block it from outside systems.

* The port should be accessible from the local computer (localhost).

* Multiple docker containers should be able to expose the same port and have everything work; all containers with an exposed port should be accessible from the local system only.

* The user should not have to know about their firewall configuration details to make this happen.

جرب نفس الشيء مع نظام قائم على CentOS / Fedora / RHEL firewalld .

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

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

كنت أعلم أن Docker قد أجرى تغييراته الخاصة على سلسلة Forward وجدول NAT .. لذلك كنت حريصًا للغاية على احترام هذه التغييرات طوال عمليتي. أيضًا ، يتم إرفاق جميع حاوياتي بشبكات يحددها المستخدم. لا يتم استخدام الشبكة المضيفة الافتراضية أبدًا. تخبرنا الوثائق الرسمية بعدم القيام بذلك.

كانت مفاجأتي الأولى أن وكيل Nginx المعبأ في حاويات كان متاحًا للإنترنت بالكامل. لدي خيار في قواعد جدار الحماية للسماح بحركة مرور الويب الواردة من العالم. لكنني لم أقم بتشغيل هذه الميزة بعد. ليس من الواضح في أي مكان في iptables الخاص بي أن HTTP 80/443 مسموح به.

تعتمد بعض تطبيقات الويب الخاصة بي على قواعد البيانات مثل MySQL. في البداية ، لم أستخدم الخيار -p في Docker Compose. كنت أعلم أنه لم يكن ضروريًا ، نظرًا لأن تطبيق الويب الخاص بي وخادم db يشتركان في نفس شبكة Docker التي يحددها المستخدم. لكن بصفتي مسؤول قاعدة بيانات سابق ، أفكر دائمًا في النسخ الاحتياطية. لذلك قمت بتنشيط الخيار -p للسماح بوظائف cron الخاصة بمضيفي وأدوات النسخ الاحتياطي بأخذ نسخ احتياطية في الوقت المناسب. لقد كتبت جدار حماية آخر _option_ للسماح بوصول SQL الخارجي. لكن مرة أخرى ، لم يتم تمكين ذلك بعد.

بعد دهشتي في Nginx ، قررت بحكمة أن أتحقق جيدًا من أن MySQL لم يتم الكشف عنها أيضًا. حاولت الاتصال (من جهاز الكمبيوتر المحمول) بقاعدة بيانات MySQL على خادم VPS البعيد. وصُدمت مرة أخرى عندما نجحت في الاتصال على الفور.

لم تتم مناقشة أي شيء أقوله بإسهاب في المشاركات السابقة. شكرا جزيلا لBenjamenMeyerjestjacoscaz للتحقيق واقتراحات مفيدة لهم. ولكن بالنسبة لأولئك الذين يسألون عن حالات الاستخدام والخبرات الحديثة؟ هنا لديك. بعد أكثر من 4 سنوات من بدء هذا الموضوع ، لا يزال الناس مثلي يواجهون هذا السلوك. وما زال يشعر بالصدمة.

نعم ، هناك الكثير من الحلول. سأتابع القليل منها على الفور. ولكن لتنفيذ ذلك ، عليك أن تعرف بالفعل

ولكن لم تتم الإشارة بوضوح إلى "سلوك تجاوز جدار الحماية" هذا ، أو التحذير منه بصوت عالٍ ، أو توثيقه على نطاق أوسع. عندما يتعلق الأمر بأمن الشبكات ، فإن المفاجآت ليست شيئًا جيدًا أبدًا.

أردت مشاركة الحل البديل الخاص بي لهذه المشكلة في حال وجده الآخرون مفيدًا. استخدام iptables و ipset. تم اختباره على Ubuntu و CentOS 7 و RHEL 7. يتم استخدام ipset نظرًا لأن عناوين IP "الموثوقة" ليست دائمًا في نفس نطاق IP (تحديد تحديد iptables).
إنه يعمل مع Docker العادي و Docker Swarm (المعروف أيضًا باسم SwarmKit).
يضمن لك الأمان افتراضيًا ، والسماح فقط لعناوين IP التي تحددها لتتمكن من الاتصال بمنافذ نظام التشغيل ومنافذ Docker (باستخدام iptables و ipset) التي تحددها يجب أن تكون مفتوحة. لديه أيضًا خيار لجعل منفذ نظام التشغيل أو منفذ Docker "عامًا" (مفتوح لجميع عناوين IP)

Ansible ليس مطلوبًا ، ولكنه يجعل الأمر أسهل .. دور Ansible: https://github.com/ryandaniels/ansible-role-iptables-docker
خطوات يدوية لـ CentOS / RHEL:
https://github.com/ryandaniels/ansible-role-iptables-docker#manual -commands-centosrhel
و Ubuntu 18.04 / 20.04:
https://github.com/ryandaniels/ansible-role-iptables-docker#manual -commands-ubuntu-2004

ستحتاج إلى تثبيت / تكوين ipset بالإضافة إلى iptables (انظر الروابط أعلاه إذا واجهت مشكلة).
مثال على تهيئة iptables (مع فتح منفذ ssh 22 للجميع):

*filter
:DOCKER-USER - [0:0]
:FILTERS - [0:0]
#Can't flush INPUT. wipes out docker swarm encrypted overlay rules
#-F INPUT
#Use ansible or run manually once instead to add -I INPUT -j FILTERS
#-I INPUT -j FILTERS
-A DOCKER-USER -m state --state RELATED,ESTABLISHED -j RETURN
-A DOCKER-USER -i docker_gwbridge -j RETURN
-A DOCKER-USER -s 172.18.0.0/16 -j RETURN
-A DOCKER-USER -i docker0 -j RETURN
-A DOCKER-USER -s 172.17.0.0/16 -j RETURN
#Below Docker ports open to everyone if uncommented
#-A DOCKER-USER -p tcp -m tcp -m multiport --dports 8000,8001 -j RETURN
#-A DOCKER-USER -p udp -m udp -m multiport --dports 9000,9001 -j RETURN
-A DOCKER-USER -m set ! --match-set ip_allow src -j DROP
-A DOCKER-USER -j RETURN
-F FILTERS
#Because Docker Swarm encrypted overlay network just appends rules to INPUT
-A FILTERS -p udp -m policy --dir in --pol ipsec -m udp --dport 4789 -m set --match-set ip_allow src -j RETURN
-A FILTERS -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FILTERS -p icmp -j ACCEPT
-A FILTERS -i lo -j ACCEPT
#Below OS ports open to everyone if uncommented
-A FILTERS -p tcp -m state --state NEW -m tcp -m multiport --dports 22 -j ACCEPT
#-A FILTERS -p udp -m udp -m multiport --dports 53,123 -j ACCEPT
-A FILTERS -m set ! --match-set ip_allow src -j DROP
-A FILTERS -j RETURN
COMMIT
هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات