ब्लॉग

किन क्लाइंट्स को वास्तव में अपना VM चाहिए? एक टियर-आधारित Docker आइसोलेशन योजना

हर क्लाइंट के लिए VM अति-आवश्यक है। यहाँ बताया गया है कि प्रत्येक टेनेंट को कितने अलगाव की आवश्यकता है—और निर्णय को स्वचालित करें।

सारांश

एजेंसियां अक्सर घबरा जाती हैं जब कोई क्लाइंट पूछता है कि उनका डेटा अन्य टेनेंट्स से कितना अलग है। Docker के नेमस्पेस और cgroups वास्तविक अलगाव देते हैं, लेकिन वे हार्डवेयर सीमा के समान नहीं हैं। हर क्लाइंट को VM पर चलाने के बजाय—या इससे भी बदतर, सभी क्लाइंटों के साथ एक जैसा व्यवहार करने के बजाय—आइसोलेशन टियर्स का एक छोटा सेट बनाएं और प्रत्येक क्लाइंट को डेटा संवेदनशीलता, विश्वास और अनुपालन के आधार पर एक से मैच करें। एक लॉक-डाउन कंटेनर (गैर-रूट, कैपेबिलिटीज़ हटाई गईं, seccomp, रीड-ओनली रूट) अधिकांश साइटों को कवर करता है; विनियमित या शत्रुतापूर्ण वर्कलोड को VM या VM के अंदर कंटेनर हाइब्रिड मिलता है। यह पोस्ट एक दोहराने योग्य निर्णय प्रवाह, एक तुलना तालिका, और एक ईमानदार नज़र देता है कि कब अधिक अलगाव अतिशयोक्ति है।

क्या आप सेल्स कॉल में उस बिंदु पर हैं जहां नया क्लाइंट कहता है “हम हेल्थकेयर हैं, दिखाओ कि हमारा डेटा आपके अन्य क्लाइंट्स से अलग है” और आप किसी और चीज़ के बारे में बात करना पसंद करेंगे?

यह एजेंसी की समस्या है: एक आदर्श डिप्लॉयमेंट नहीं, बल्कि एक ही भरोसेमंद डिप्लॉयमेंट को अलग-अलग बजट, जोखिम प्रोफाइल और अनुपालन मांगों वाले दर्जनों क्लाइंट्स पर दोहराना। यहाँ ईमानदार संस्करण है। Docker अलगाव वास्तविक है, लेकिन यह विशिष्ट है। नेमस्पेस प्रत्येक कंटेनर को प्रक्रियाओं, नेटवर्किंग और फाइलसिस्टम का अपना दृश्य देते हैं; cgroups CPU, मेमोरी और डिस्क I/O को सीमित करते हैं ताकि टेनेंट एक-दूसरे को भूखा न रख सकें। जो चीज़ आपको नहीं मिलती वह कंटेनर और होस्ट कर्नेल के बीच एक हार्डवेयर दीवार है। यदि कोई हमलावर कंटेनर से बच निकलता है, तो वे आपके पास मौजूद एकमात्र कर्नेल के अंदर होते हैं। इस लेख का शेष भाग उस असुविधाजनक तथ्य को एक दोहराने योग्य निर्णय में बदल देता है: प्रत्येक क्लाइंट को डेटा संवेदनशीलता और विश्वास के आधार पर वर्गीकृत करें, एक बेसलाइन हार्डनिंग प्रोफ़ाइल लागू करें, और केवल तभी VM का उपयोग करें जब उल्लंघन की लागत VM की लागत से अधिक हो।

रुको, क्या कंटेनर पहले से अलग नहीं हैं?

Docker Linux नेमस्पेस और cgroups पर चलता है, और ये शब्द वास्तविक काम कर रहे हैं। नेमस्पेस प्रोसेस आईडी, नेटवर्क स्टैक, माउंट पॉइंट्स और उपयोगकर्ताओं को अलग करते हैं ताकि एक कंटेनर में प्रोसेस दूसरे की प्रोसेस टेबल न देख सके। Cgroups सीमाएँ निर्धारित करते हैं: एक कंटेनर को 0.5 CPU, 512 MB मेमोरी, और एक निश्चित ब्लॉक I/O वेट दें, और यह ठीक वही पाता है। एक टेनेंट में भागता हुआ लूप पड़ोसी को नीचे लाने के बजाय थ्रॉटल हो जाता है। यदि आपने सीमाएँ कॉन्फ़िगर नहीं की हैं, तो आप सबसे बुनियादी चीज़ को छोड़ चुके हैं जिसके लिए cgroups हैं।

कंटेनर A में एक साधारण PHP ऐप लें। यह अपना स्वयं का फाइलसिस्टम, अपना स्वयं का नेटवर्क इंटरफ़ेस, अपना स्वयं का PID 1 देखता है। कंटेनर B के पास समान है, लेकिन एक अलग दृश्य। वह नेमस्पेस है। अब दूर चले जाएं और मेमोरी सीमा को छोड़ दें: कंटेनर A होस्ट की RAM भर सकता है और कंटेनर B को रेंगने पर मजबूर कर सकता है। cgroups इसी को रोकने के लिए मौजूद हैं। लेकिन दो कंटेनर नेमस्पेस द्वारा एक-दूसरे से अलग हो सकते हैं और फिर भी होस्ट कर्नेल साझा कर सकते हैं, जो हर कंटेनर-एस्केप कहानी का हिस्सा है। एक एक्सप्लॉइट जो कर्नेल तक पहुंचता है, संभावित रूप से उस होस्ट पर हर टेनेंट तक पहुंच सकता है।

“Docker अलग है” एक आधा-सच वाक्य है। सटीक संस्करण है “Docker नेमस्पेस और cgroups से अलग करता है, और एक कर्नेल भेद्यता विस्फोट त्रिज्या है।” इससे पहले कि आप किसी टेनेंट पर अविश्वसनीय कोड चलाने का भरोसा करें, उस विचार के साथ एक मिनट बैठें। उत्तर “कभी कंटेनर का उपयोग न करें” नहीं है—यह आसान घबराहट है। उत्तर एक टियर प्रणाली है।

तो कुछ क्लाइंट्स को नेमस्पेस से अधिक की आवश्यकता क्यों है?

ईमानदार उत्तर यह है कि अलगाव एक स्विच नहीं है, यह एक स्पेक्ट्रम है। एक छोर पर आपके पास एक पूरी तरह से साझा कंटेनर होता है जहां हर कोई प्रभावी रूप से एक ऐप में होता है। दूसरे छोर पर आपके पास अपने स्वयं के कर्नेल के साथ प्रति टेनेंट एक अलग VM होता है। अधिकांश एजेंसी काम असहज मध्य में रहता है, और मध्य “Docker ठीक है” और “सभी के लिए VM चलाएं” के बीच एक द्विआधारी विकल्प नहीं है।

एक क्लाइंट को दाईं ओर धकेलने वाली चीज़ उसका आकार नहीं है। यह चार प्रश्न हैं:

  • क्या वे विनियमित डेटा संग्रहीत करते हैं? स्वास्थ्य रिकॉर्ड, भुगतान कार्ड विवरण, कुछ भी जिसे एक नियामक संवेदनशील कहेगा।
  • क्या उनके टेनेंट पर उल्लंघन का दूसरे टेनेंट तक यथार्थवादी मार्ग है? यदि वे मनमाना कोड चला सकते हैं, हाँ।
  • क्या आप कोड और उसे तैनात करने वाले लोगों पर भरोसा करते हैं? एक क्लाइंट जो सबसे सस्ता फ्रीलांसर किराए पर लेता है, वह उस क्लाइंट के समान विश्वास स्तर नहीं है जिसकी डेव टीम आप जानते हैं।
  • क्या उनके अनुबंध में “समर्पित,” “पृथक,” या “निजी” लिखा है? यदि ऐसा है, तो आप पहले से ही एक टियर का वादा कर चुके हैं; अब केवल सही चुनने का काम है।

यदि आप अभी उन प्रश्नों का उत्तर नहीं दे सकते हैं, तो क्लाइंट को एक बेसलाइन टियर में रखें और धारणाओं को लिख लें। यह एक सुरक्षा ऑडिट नहीं है; यह एक सेनेटी जांच है जिसे आप हर ऑनबोर्डिंग पर दोहराते हैं।

मैं हर बार सुरक्षा ऑडिट चलाए बिना प्रति क्लाइंट कैसे निर्णय लूं?

एक छोटी तालिका बनाएं और उसके लिए प्रतिबद्ध हों। आपको चालीस सेल वाले मैट्रिक्स की आवश्यकता नहीं है। चार टियर एजेंसी द्वारा देखे जाने वाले लगभग हर क्लाइंट को कवर करेंगे।

क्लाइंट की स्थितिवास्तव में उन्हें क्या अलग करता हैकब उपयोग करें
Tier 1: साझा ऐप/कंटेनरकेवल एप्लिकेशन लॉजिकआंतरिक उपयोगिताएँ, कम जोखिम वाला डेटा, ऐसे प्रोजेक्ट जहां हर कोई स्पष्ट रूप से एक लॉगिन प्रणाली में है
Tier 2: एक ही होस्ट, अलग कंटेनरनेमस्पेस और cgroupsअधिकांश मार्केटिंग साइटें, संपर्क फॉर्म, कोई संवेदनशील डेटा नहीं
Tier 3: लॉक-डाउन कंटेनरTier 2 + गैर-रूट, हटाई गई कैपेबिलिटीज़, seccomp, रीड-ओनली रूट, नेटवर्क विभाजनई-कॉमर्स, PII, कस्टम कोड जिस पर आप पूरी तरह भरोसा नहीं करते
Tier 4: प्रति-टेनेंट VMहाइपरवाइज़र और एक अलग कर्नेलहेल्थकेयर, वित्त, अनुपालन कागजी कार्रवाई, अविश्वसनीय कोड, शोरगुल वाले पड़ोसी

यहाँ बताया गया है कि व्यवहार में यह कैसे काम करता है। एक संपर्क फॉर्म और एक Instagram लिंक वाला बेकरी क्लाइंट Tier 2 में जाता है: एक साझा होस्ट पर एक कंटेनर, डिफ़ॉल्ट Docker नेटवर्किंग, संसाधन सीमाएँ, काम हो गया। एक ऑनलाइन स्टोर जो ग्राहकों के नाम, पते और भुगतान रीडायरेक्ट संग्रहीत करता है, Tier 3 में जाता है: समान साझा होस्ट, लेकिन कंटेनर एक गैर-रूट उपयोगकर्ता के रूप में चलता है, कोई अतिरिक्त कर्नेल कैपेबिलिटी नहीं है, seccomp प्रोफ़ाइल का उपयोग करता है, और केवल पोर्ट 443 को उजागर करता है। एक चिकित्सा प्रवेश पोर्टल जो संरक्षित स्वास्थ्य जानकारी संग्रहीत करता है, Tier 4 में जाता है: प्रति टेनेंट एक VM, क्योंकि उल्लंघन की लागत “हम इसे साफ कर देंगे” नहीं है, बल्कि “हम क्लाइंट को नहीं दिखा सकते कि हमने उन्हें गंभीरता से लिया।”

पूरी तरकीब यह है कि आप हर क्लाइंट के लिए आर्किटेक्चर पर पुनर्विचार नहीं कर रहे हैं। आप एक ऐसी तालिका से एक पंक्ति चुन रहे हैं जिस पर आप पहले ही सहमत हो चुके हैं। इस तरह एक पांच-व्यक्ति एजेंसी सौ अलग-अलग सुरक्षा जुनून के बिना सौ साइटें चला सकती है। इसका मतलब यह भी है कि अगले क्लाइंट को ऐसा उत्तर नहीं मिलता जो इस बात पर निर्भर करता है कि फोन किस टीम सदस्य ने उठाया। उन विकल्पों के पीछे गहन आर्किटेक्चर बहस के लिए, मल्टी-टेनेंट आइसोलेशन स्तरों को डिजाइन करने पर यह गाइड ट्रेड-ऑफ्स को अधिक विस्तार से कवर करता है।

एक लॉक-डाउन कंटेनर वास्तव में कैसा दिखता है?

चलिए “लॉक डाउन” कहना बंद करें और ठोस हो जाएं। एक सामान्य WordPress या PHP क्लाइंट के लिए Tier 3 का यही अर्थ है।

पहले, उपयोगकर्ता बदलें। अधिकांश आधिकारिक इमेज अभी भी डिफ़ॉल्ट रूप से रूट के रूप में चलती हैं; अपने Dockerfile में, एक गैर-रूट उपयोगकर्ता बनाएं और ऐप को उस उपयोगकर्ता के रूप में चलाएं। यह तुरंत सबसे सामान्य तरीके को हटा देता है जिससे कंटेनर समझौता होस्ट समझौता बन जाता है। दूसरा, उन कैपेबिलिटीज़ को हटा दें जिनकी आपको आवश्यकता नहीं है। --cap-drop ALL के साथ चलाएं और केवल एक को वापस जोड़ें, आमतौर पर NET_BIND_SERVICE ताकि ऐप पोर्ट 80 पर सुन सके। अकेले यह बदलाव अधिकांश लोगों की अपेक्षा से बड़ा है। तीसरा, रूट फाइलसिस्टम को --read-only के साथ रीड-ओनली बनाएं, और लिखने योग्य निर्देशिकाओं (अपलोड, डेटाबेस डेटा निर्देशिका) को वॉल्यूम या tmpfs के रूप में माउंट करें। चौथा, एक seccomp प्रोफ़ाइल लागू करें और, यदि आपका होस्ट समर्थन करता है, तो AppArmor या SELinux। अंत में, कंटेनर को एक समर्पित Docker नेटवर्क पर रखें और केवल उन पोर्ट्स को उजागर करें जिन तक वास्तव में पहुंचने की आवश्यकता है।

आइए एक WordPress उदाहरण देखें। बेस इमेज शायद रूट के रूप में चलती है, इसलिए आप एक useradd चरण और एक USER निर्देश जोड़ते हैं। आप मेमोरी सीमा और CPU सीमा के साथ कंटेनर चलाते हैं, ताकि प्लगइन ट्रैफ़िक का विस्फोट पड़ोसी को नुकसान न पहुंचाए। आप /var/www/html/wp-content/uploads को एक लिखने योग्य वॉल्यूम के रूप में माउंट करते हैं। आप --read-only सेट करते हैं। आप इसे एक ऐसे नेटवर्क से जोड़ते हैं जिसके पास कहीं भी --privileged फ्लैग नहीं है। परिणाम एक कंटेनर है जो पहले “एक WordPress साइट” था और अब “एक WordPress साइट है जो अधिकांश वर्चुअल प्राइवेट सर्वरों की तुलना में अधिक लॉक-डाउन है।”

यदि यह सब हाथ से करना नाजुक लगता है, तो एक आसान मध्य मार्ग है: Docker की एन्हांस्ड कंटेनर आइसोलेशन, जो उपयोगकर्ता नेमस्पेस अलगाव और एक सुरक्षित कंटेनर रनटाइम का उपयोग करता है। यह एक वैध शॉर्टकट है, लेकिन यह गैर-रूट या कैपेबिलिटी हटाने को छोड़ने के लिए एक मुफ्त पास नहीं है। टेनेंट को अभी भी एक समझदार इमेज की आवश्यकता है। अंतर यह है कि कर्नेल-सामना करने वाली हमले की सतह छोटी हो जाती है, बिना आपको रातों-रात seccomp विशेषज्ञ बने। यदि आप एकल टेनेंट के लिए सटीक अनुक्रम चाहते हैं, तो चरण-दर-चरण आइसोलेशन हार्डनिंग गाइड इस अनुभाग को कॉपी-पेस्ट कमांड में बदल देता है।

मैं लेयरिंग कब बंद करूं और उन्हें सिर्फ VM दे दूं?

यहाँ विपरीत हिस्सा है: अधिक अलगाव स्वतः बेहतर नहीं है। VM आपको हार्डवेयर-स्तर का अलगाव, एक अलग कर्नेल, और यदि गेस्ट कर्नेल गिर जाता है तो बहुत छोटी हमले की सतह देते हैं। हेल्थकेयर और वित्त क्लाइंट ठीक यही उम्मीद करते हैं जब वे कहते हैं “हम अलग होना चाहते हैं।” लेकिन हर VM पैचिंग, बैकअप और कंप्यूट लागत जोड़ता है, और बेड़े को अपडेट रखने के काम को कई गुना बढ़ा देता है। यदि आप हर क्लाइंट को VM देते हैं क्योंकि एक क्लाइंट ने एक बार कहा था कि Docker से वे डर गए, तो आपने असली पैसे से सुरक्षा थिएटर खरीदा है।

VM सही उत्तर है जब प्रति टेनेंट जोखिम प्रति टेनेंट VM की परिचालन लागत से अधिक हो। इसका मतलब है विनियमित डेटा, लिखित अनुपालन आवश्यकताएं, अविश्वसनीय तृतीय-पक्ष कोड, या एक क्लाइंट जिसे शोरगुल वाले पड़ोसी को हटाने की आवश्यकता है। यह सही उत्तर तब भी है जब क्लाइंट का अनुबंध सचमुच समर्पित वातावरण का वादा करता है, क्योंकि जब वे “समर्पित” पर हस्ताक्षर करते हैं तो “कंटेनर” नहीं जो वे चित्रित कर रहे हैं।

लेकिन VM एक लापरवाह कंटेनर को माफ नहीं करता। एक आम जाल यह है कि क्लाइंट को VM में डाल दें और फिर हार्डनिंग छोड़ दें क्योंकि “VM उनकी रक्षा करता है।” VM होस्ट को टेनेंट से बचाता है, न कि टेनेंट को उसकी अपनी खराब इमेज से। आप अभी भी उस VM के अंदर गैर-रूट, हटाई गई कैपेबिलिटीज़ और seccomp चाहते हैं। हाइब्रिड दृष्टिकोण—VM के अंदर कंटेनर—अक्सर मीठी जगह होती है: VM अनुपालन वार्तालापों के लिए सीमा प्रदान करता है, और कंटेनर आपको वह तैनाती कार्यप्रवाह देता है जिसे आप पहले से जानते हैं। उस बहस का एक लंबा संस्करण क्या हर टेनेंट को अपना VM मिलना चाहिए? में है, लेकिन संक्षिप्त उत्तर यह है कि VM अनुबंध के लिए है, डर के लिए नहीं।

मैं इसे हर क्लाइंट में दोहराने योग्य कैसे बनाऊं?

आप इसे टियर प्रणाली को एक टेम्पलेट बनाकर दोहराने योग्य बनाते हैं, न कि स्मृति। Compose फ़ाइलों की एक निर्देशिका रखें, प्रति टियर एक: tier2-baseline, tier3-locked, tier4-vm-hybrid। जब एक नया क्लाइंट आता है, तो टेम्पलेट कॉपी करें, पर्यावरण चर बदलें, और आप नई इन्फ्रास्ट्रक्चर की एक पंक्ति लिखने से पहले ही अलगाव आकार जानते हैं।

फिर निर्णय लिख लें। 400-पृष्ठ की सुरक्षा रिपोर्ट नहीं, बल्कि क्लाइंट के रिपॉजिटरी में एक छोटा पैराग्राफ: वे कौन सा डेटा संग्रहीत करते हैं, वे किस टियर पर हैं, क्यों, और क्या उन्हें उच्च टियर पर ले जाएगा। वह पैराग्राफ सौ फ़ायरवॉल नियमों से अधिक मूल्यवान है, क्योंकि यह वह चीज़ है जिसे आप अगले ऑडिटर या अगले चिंतित क्लाइंट को दिखा सकते हैं। यह आपको यह याद रखने से भी रोकता है कि मूल सेल्स कॉल फीकी पड़ने के बाद बेकरी को Tier 2 और ई-कॉमर्स स्टोर को Tier 3 क्यों मिला।

उबाऊ जांचों को स्वचालित करें। अपने CI को हर क्लाइंट इमेज को स्कैन करें और बिल्ड को विफल करें यदि यह रूट के रूप में चलता है, यदि इसमें सभी कैपेबिलिटी हैं, या यदि यह टियर द्वारा अनुमत पोर्ट के अलावा कोई पोर्ट प्रकाशित करने का प्रयास करता है। इसमें से कुछ भी विदेशी नहीं है; यह सुनिश्चित करना है कि टेम्पलेट गलती से एक अच्छे इरादे वाले डेवलपर द्वारा न तोड़ा जाए। यदि आप पहले से ही चारों ओर होस्टिंग वर्कफ़्लो बना रहे हैं, तो प्रोडक्शन-रेडी Docker होस्टिंग रणनीतियाँ कंटेनरों को परिभाषित करने के बाद के भाग को कवर करता है।

इसमें से कुछ भी ग्लैमरस नहीं है। कोई ब्लॉग पोस्ट “टेनेंट आइसोलेशन” को ग्रीनफील्ड आर्किटेक्चर डायग्राम जितना रोमांचक नहीं बनाएगा। लेकिन यह एक एजेंसी के बीच का अंतर है जो “हम कितने अलग हैं?” का उत्तर उंगलियां क्रॉस करके “बिल्कुल” के साथ देती है और जो एक टियर, एक कॉन्फ़िग और एक कारण दिखा सकती है। कंटेनर एक जादुई दीवार नहीं हैं। VM एक जादुई गोली नहीं हैं। एक टियर प्रणाली सिर्फ एक निर्णय है जिसे आप लिखते हैं और पुनः उपयोग करते हैं—और एजेंसी के लिए, दोहराने योग्य होना ही पूरा खेल है।

Sources (5)