VPS फ़ायरवॉल: केवल VPN पोर्ट खोलें, फिर उसे सिद्ध करें
एक पोर्ट सार्वजनिक रहना ही होगा, वरना कोई क्लाइंट जुड़ेगा नहीं। बाकी को अस्वीकार करें, फ़ॉरवर्डिंग को इनपुट से अलग रखें, और पहले से परखा हुआ पुनर्प्राप्ति मार्ग छोड़ें।
केवल VPN पोर्ट की अनुमति देने वाला फ़ायरवॉल एक नियम नहीं है। ये तीन अलग निर्णय हैं जो संयोग से एक ही पोर्ट संख्या से जुड़े हैं: इनपुट श्रृंखला तय करती है कि किसी स्थानीय प्रक्रिया तक क्या पहुँच सकता है, फ़ॉरवर्ड श्रृंखला तय करती है कि टनल क्लाइंट्स की ओर से होस्ट से होकर क्या जा सकता है, और NAT तालिका बाहर जाते समय स्रोत पता फिर से लिखती है। इनमें से एक भी गलत करें तो परिणाम शायद ही कभी साफ़ बाधा होता है। आपको ऐसा होस्ट मिलता है जो क्लाइंट्स स्वीकार करता है पर कुछ लोड नहीं करता, या ऐसा होस्ट जो किसी के श्रृंखलाओं का क्रम पढ़ने तक बंद दिखता है।
वह एकमात्र पोर्ट जिसे बंद नहीं किया जा सकता
VPN श्रोता को ऐसे पतों से कनेक्शन स्वीकार करने पड़ते हैं जिन्हें आप पहले से नहीं जान सकते, इसलिए यह परिभाषा से एक सार्वजनिक सेवा है। यही वह एकमात्र अपवाद है जिस पर यह डिज़ाइन बना है: OpenVPN के लिए एक UDP पोर्ट, WireGuard के लिए एक UDP पोर्ट, SSL VPN के लिए एक TCP पोर्ट। बाकी सब कुछ टनल के पीछे है, यानी एप्लिकेशन सेवाओं को हर इंटरफ़ेस के बजाय टनल पते या loopback से बंधना चाहिए।
बंधना हालाँकि लागू करना नहीं है। 0.0.0.0 से बंधी प्रक्रिया तभी पहुँच में है जब कोई नियम उसे अनुमति दे, और डिफ़ॉल्ट नीति उस ट्रैफ़िक के लिए विकल्प है जो किसी नियम से मेल नहीं खाया, पोर्ट को नियंत्रित करने वाला नियम नहीं। आपके ड्रॉप के ऊपर रखी गई स्वीकृति भी स्वीकृति ही रहती है, और सेवा को सार्वजनिक पते से हटाना एक स्वतंत्र सुधार है, श्रृंखला का विकल्प नहीं।
इनपुट, फ़ॉरवर्ड और NAT अलग-अलग प्रश्नों के उत्तर देते हैं
इनपुट ट्रैफ़िक होस्ट के लिए ही होता है, इसलिए VPN श्रोता और प्रशासनिक मार्ग वहीं रहते हैं। फ़ॉरवर्ड ट्रैफ़िक होस्ट से होकर जाता है, और टनल क्लाइंट्स को यह net.ipv4.ip_forward=1 के साथ चाहिए। पुरानी आधी-टूटी कॉन्फ़िगरेशन बाहर जाने वाले प्रवाह की अनुमति देती है और लौटने की दिशा भूल जाती है, इसलिए क्लाइंट हैंडशेक पूरा करता है और फिर कुछ लोड नहीं होता; स्थापित और संबंधित ट्रैफ़िक के लिए conntrack नियम उस दिशा को ढक देता है।
NAT तीसरा प्रश्न है। postrouting में पुनर्लेखन के बिना, फ़ॉरवर्ड किए गए पैकेट टनल के निजी स्रोत के साथ बाहर जाते हैं और ऊपर की ओर छोड़ दिए जाते हैं, क्योंकि होस्ट से आगे कोई नेटवर्क नहीं जानता कि पूल को वापस कैसे रूट करना है। उस नियम में स्रोत प्रीफ़िक्स VPN पूल से मेल खाना चाहिए, होस्ट के अपने पते से नहीं, और क्लाइंट सबनेट का नाम लेने वाले फ़ॉरवर्ड नियम के लिए भी यही सच है।
IPv6 दूसरी नीति है, बाद का विचार नहीं। कड़ी IPv4 श्रृंखला और ip6tables पर खुली नीति वाले होस्ट ने कुछ भी बंद नहीं किया; सेवाएँ दूसरे कुल के ज़रिए अब भी पहुँच में हैं। या तो ip6tables के साथ नियम-समूह का प्रतिबिंब बनाएँ, या सार्वजनिक इंटरफ़ेस पर IPv6 जानबूझकर बंद करें, और लिखें कि आपने कौन-सा चुना।
एक पारी में पढ़ा जा सकने वाला आधार
अस्वीकार से शुरू करें, फिर केवल वही जोड़ें जो होस्ट को चाहिए। पहले loopback और उत्तर, फिर प्रशासनिक मार्ग, फिर टनल श्रोता, फिर क्लाइंट्स के लिए फ़ॉरवर्डिंग नीति:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -p udp --dport 1194 -m conntrack --ctstate NEW -j ACCEPT
sysctl -w net.ipv4.ip_forward=1
iptables -A FORWARD -i tun0 -o eth0 -s 10.8.0.0/24 -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADEइंटरफ़ेस के नाम, पोर्ट और पूल प्लेसहोल्डर हैं; उन्हें कॉपी करने के बजाय सर्वर से पढ़ें। परिणाम सहेजना उसे लिखने जितना ही ज़रूरी है, क्योंकि केवल स्मृति में जीवित नियम-समूह अगली रीबूट में गायब हो जाता है और होस्ट को चुपचाप फिर खोल देता है। वितरण की विधि से इसे स्थायी बनाएँ, और जिस दिन मशीन बूट न हो उस दिन के लिए मशीन के बाहर एक प्रति रखें।
होस्ट खोए बिना अंतिम पोर्ट बंद करना
डिज़ाइन में एक पेच है। यदि SSH केवल टनल से होकर मौजूद है, तो विफल VPN सेवा SSH को भी ले जाती है, और वापस लौटने का एकमात्र रास्ता ऐसा कंसोल हो सकता है जिसे आपने कभी नहीं खोला। अंतिम सार्वजनिक पोर्ट बंद करने से पहले पुष्टि करें कि वह कंसोल मौजूद है और आप वास्तव में उसका उपयोग कर सकते हैं, या टनल पर निर्भर न रहने वाला एक संकीर्ण प्रशासनिक मार्ग रखें: निश्चित पते से SSH, केवल कुंजियाँ, पासवर्ड प्रमाणीकरण बंद।
परिवर्तन पहले से स्थापित सत्र से लागू करें, उस कनेक्शन से नहीं जिसे आप फ़िल्टर करने वाले हैं। रोलबैक निर्धारित करें ताकि गलती स्थायी होने के बजाय समाप्त हो जाए, उदाहरण के लिए पिछला नियम-समूह बहाल करने वाला systemd-run --on-active=10min कार्य, और पहले को जाँचते समय दूसरा SSH सत्र खुला रखें। फिर सत्यापित करें कि रोलबैक कार्य वास्तव में चलता है, क्योंकि बिना परखी पुनर्प्राप्ति पुनर्प्राप्ति न होने के बराबर है।
स्क्रिप्ट नहीं, मार्ग सत्यापित करें
लोड किए गए नियम पढ़ें, वह फ़ाइल नहीं जिसे उन्हें लोड करना था। किसी अधिकृत बाहरी होस्ट से पुष्टि करें कि केवल इच्छित पोर्ट ही उत्तर देते हैं; टनल के भीतर से पुष्टि करें कि जिन सेवाओं को आप प्रकाशित करना चाहते थे वे पहुँच में हैं। डिफ़ॉल्ट-अस्वीकार नीति जो टनल ट्रैफ़िक भी अवरुद्ध करती है, तब तक काम करने वाले लॉकडाउन जैसी ही दिखती है जब तक कोई उसका उपयोग करने की कोशिश न करे।
iptables -S
iptables -t nat -S
ss -lntup
ip -4 addr showअनुमत पोर्ट, क्लाइंट पूल, टनल इंटरफ़ेस, प्रशासनिक स्रोत और कंसोल प्रक्रिया कॉन्फ़िगरेशन के बगल में दर्ज करें। पूल या इंटरफ़ेस नाम में अगला परिवर्तन फ़िल्टर और NAT नियम दोनों में मेल खाना चाहिए, वरना होस्ट किसी को पता चले बिना आधा-खुली स्थिति में लौट जाएगा।
एक आदत नियम-समूह से अधिक मूल्यवान है: हर परिवर्तन के बाद क्लाइंट अनुरोध से फ़ॉरवर्ड मार्ग और दूसरे सत्र से पुनर्प्राप्ति मार्ग सिद्ध करें। जिस लॉकडाउन का आपने उपयोग नहीं किया वह केवल एक परिकल्पना है।