UFW और IPv6: VPS पर सुरक्षा का बड़ा खतरा कैसे रोकें
आपका फायरवॉल केवल IPv4 को सुरक्षित कर सकता है जबकि IPv6 खुला रहता है। जानें कि कैसे आपका VPS अनजाने में इंटरनेट के लिए खुला है और UFW के साथ इस सुरक्षा खामी को कैसे ठीक करें।
IPv6 फायरवॉल से जुड़ी एक वाक्य की चेतावनी
आपका फायरवॉल केवल IPv4 को सुरक्षित करता है। आपके VPS के पास लगभग निश्चित रूप से एक public IPv6 पता भी होता है, और कई services डिफ़ॉल्ट रूप से उस पर listen करती हैं। यदि आपका फायरवॉल केवल IPv4 को कवर करता है, या आप किसी ऐसे cloud firewall पर निर्भर हैं जो केवल IPv4 को filter करता है, तो वे सभी services पूरे इंटरनेट से IPv6 के माध्यम से सुलभ (reachable) हैं, जबकि आपका IPv4 पक्ष सुरक्षित दिख रहा है। आप curl के साथ किसी port का परीक्षण करते हैं, connection refused देखते हैं, और सुरक्षित महसूस करते हैं। एक हमलावर उसी port से IPv6 के माध्यम से जुड़ता है और अंदर आ जाता है।
यह गाइड दिखाती है कि एक सामान्य Ubuntu 24.04 VPS पर यह कमी कहाँ से आती है, आप जो expose कर रहे हैं उसे सटीक रूप से कैसे देखें, और इसे कैसे बंद करें। यहाँ UFW दोषी नहीं है। आधुनिक Ubuntu install पर UFW पहले से ही IPv6 को संभालता है। यह जोखिम उसके आसपास की परतों से, और उन services से आता है जिनके बारे में आपको पता भी नहीं था कि वे listen कर रही हैं।
आपका VPS शुरू से ही IPv6 पर क्यों है
आजकल लगभग हर VPS के साथ एक public IPv6 address मिलता है, जो अक्सर पूरा एक /64 होता है, और साथ में एक IPv4 address भी होता है। अपना address जाँचें:
ip -6 addr show scope global2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
inet6 2001:db8:2a::1/64 scope globalइस गाइड में दिया गया 2001:db8:2a::1, 2001:db8::/32 का एक placeholder है, जो documentation के लिए आरक्षित एक prefix है और internet पर कभी route नहीं होता। उस line में आपके सर्वर द्वारा print किया गया वास्तविक address internet पर कहीं से भी routable है, बिल्कुल आपके IPv4 address की तरह। अब देखें कि कौन सी service listen कर रही है:
sudo ss -tlnpState Recv-Q Local Address:Port Process
LISTEN 0 0.0.0.0:22 sshd
LISTEN 0 [::]:22 sshd
LISTEN 0 127.0.0.1:5432 postgres
LISTEN 0 [::]:8080 docker-proxyLocal Address column को ध्यान से पढ़ें। 0.0.0.0:22 का अर्थ है "हर IPv4 address पर listen करें।" [::]:22 का अर्थ है "हर IPv6 address पर listen करें।" 127.0.0.1:5432 केवल loopback से bound है और public नहीं है, इसलिए Postgres वाली line सुरक्षित है। दो [::] lines पूरे internet को IPv6 पर जवाब देती हैं, और docker-proxy वाली वह service है जिसे आप शुरू करना भूल गए थे।
अधिकांश daemons डिफ़ॉल्ट रूप से :: पर bind होते हैं, क्योंकि Linux पर एक :: socket आमतौर पर IPv4 को भी स्वीकार कर लेता है। इसलिए एक नए सर्वर की डिफ़ॉल्ट स्थिति यह होती है कि वह "हर जगह, दोनों stacks पर जवाब दे।" आपका firewall ही एकमात्र ऐसी चीज़ है जो इसके सामने खड़ी है, और यही कारण है कि जो firewall केवल एक stack को देखता है, वह एक गंभीर समस्या है।
IPv6 गैप वास्तव में कहाँ से आता है
इसके तीन सामान्य स्रोत हैं। किसी दिए गए सर्वर पर इनमें से एक या एक से अधिक समस्याएँ हो सकती हैं।
1. एक क्लाउड फायरवॉल जो केवल IPv4 को फ़िल्टर करता है। कई प्रदाता फायरवॉल और सिक्योरिटी-ग्रुप उत्पाद IPv4 के इर्द-गिर्द विकसित हुए हैं और या तो IPv6 को अनदेखा करते हैं या उन्हें अलग से IPv6 नियमों की आवश्यकता होती है जिन्हें आपको मैन्युअल रूप से जोड़ना पड़ता है। यदि आपका एकमात्र फायरवॉल प्रदाता डैशबोर्ड वाला है और यह IPv6 को कवर नहीं करता है, तो आपके [::] सर्वर खुले हैं, भले ही यह IPv4 पर port 22 के बारे में कुछ भी कहे। अपने प्रदाता के फायरवॉल दस्तावेज़ पढ़ें और विशेष रूप से IPv6 शब्द खोजें।
2. बिना ip6tables के मैन्युअल रूप से बनाए गए iptables। iptables कमांड केवल IPv4 टेबल्स को प्रभावित करती है। IPv6 के लिए एक पूरी तरह से अलग कमांड, ip6tables है, जिसके अपने अलग नियम होते हैं। यदि आपने iptables -A INPUT ... लाइनों से भरी एक फायरवॉल स्क्रिप्ट लिखी है और कभी भी संबंधित ip6tables नियम नहीं लिखे हैं, तो आपका IPv6 फायरवॉल खाली है, और डिफ़ॉल्ट ACCEPT पॉलिसी वाली एक खाली INPUT चेन सब कुछ अनुमति देती है:
sudo ip6tables -L INPUT -nChain INPUT (policy ACCEPT)
target prot opt source destinationवह आउटपुट एक ही स्क्रीन पर पूरी समस्या को दर्शाता है। IPv4 फ़िल्टर किया गया है, IPv6 दुनिया के लिए खुला है।
3. Docker का आपके फायरवॉल को बायपास करके पोर्ट पब्लिश करना। जब आप docker run -p 8080:80 चलाते हैं, तो Docker अपने स्वयं के नियमों को UFW के नियमों से पहले डाल देता है, इसलिए एक पब्लिश किया गया पोर्ट तब भी पहुंच योग्य होता है जब ufw status कहता है कि वह पोर्ट डिनाय है। वर्तमान Docker डिफ़ॉल्ट रूप से ip6tables नियमों को मैनेज करता है, इसलिए जब कंटेनर के नेटवर्क पर IPv6 सक्षम होता है, तो यही बात IPv6 पर भी लागू होती है। Docker UFW को बायपास क्यों करता है, और कंटेनर पोर्ट्स को ठीक से फ़िल्टर कैसे करें इसके मैकेनिज्म और समाधानों की व्याख्या करता है। ये पब्लिश किए गए पोर्ट कैसे घोषित किए जाते हैं, यह जानने के लिए VPS पर Docker Compose की मूल बातें देखें।
UFW के IPv6 स्विच पर एक नोट। UFW IPv6 को हैंडल करता है, और इसका स्विच एक फाइल में होता है। इसे चेक करें:
grep IPV6 /etc/default/ufwआधुनिक Ubuntu में IPV6=yes होता है, इसलिए UFW प्रत्येक नियम को दोनों स्टैक पर लागू करता है। यदि आप किसी पुरानी इमेज या पुरानी गाइड से IPV6=no देखते हैं, तो IPv6 खुला नहीं छोड़ा गया है। उस सेटिंग के साथ, एक सक्रिय UFW लूपबैक इंटरफ़ेस को छोड़कर सभी IPv6 ट्रैफ़िक को ड्रॉप कर देता है, इसलिए समस्या दूसरी तरफ से होती है: जिसे आप IPv6 पर सर्व करना चाहते थे, वह जवाब देना बंद कर देता है। यदि आप चाहते हैं कि UFW IPv6 को पूरी तरह से ब्लॉक करने के बजाय आपके नियमों के साथ फ़िल्टर करे, तो इसे yes पर सेट करें।
यह देखें कि आप वास्तव में क्या expose कर रहे हैं
अनुमान न लगाएँ। इसे बाहर से मापें। सबसे पहले अपने listeners की सूची बनाएँ और :: से bound हर एक को नोट करें:
sudo ss -tlnp | grep '::'फिर, एक अलग मशीन से, सर्वर के सार्वजनिक IPv6 पते से कनेक्ट करें और उस port को आज़माएँ जिसे आप बंद मानते हैं:
curl -6 -v http://[2001:db8:2a::1]:8080/यदि यह कोई पेज या banner लौटाता है, तो वह port IPv6 पर खुला है। एक बंद port आपको Connection refused या timeout देगा। ये दोनों विफलताएँ एक ही संकेत नहीं हैं, और refused और timed out के बीच का अंतर आपको बताता है कि क्या host ने उत्तर दिया और आपको मना कर दिया, या firewall ने चुपचाप आपके packet को drop कर दिया। पूरी तस्वीर के लिए, सर्वर के बाहर से nmap के साथ IPv6 पते को स्कैन करें:
nmap -6 2001:db8:2a::1nmap जो भी port IPv6 पर खुला बताता है, वह एक ऐसा port है जिसे पूरा इंटरनेट एक्सेस कर सकता है, चाहे आपके IPv4 स्कैन ने कुछ भी दिखाया हो। IPv4 और IPv6 स्कैन की तुलना करना अंतर खोजने का सबसे तेज़ तरीका है: जो कुछ भी -6 पर खुला है लेकिन IPv4 पर बंद है, वह एक ऐसी service है जिसे आपका firewall सुरक्षित नहीं कर पा रहा है।
अंतर को समाप्त करें
UFW को दोनों स्टैक कवर करने के लिए सेट करें और डिफ़ॉल्ट रूप से deny करें। स्विच की पुष्टि करें, फिर एक डिफ़ॉल्ट-deny इनबाउंड पॉलिसी सेट करें और केवल वही अनुमति दें जिसकी आपको आवश्यकता है:
sudo sed -i 's/^IPV6=no/IPV6=yes/' /etc/default/ufw
sudo ufw default deny incoming
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status verboseयदि IPV6=yes को बदलते समय UFW पहले से सक्रिय था, तो यह बदलाव तब तक प्रभावी नहीं होगा जब तक आप sudo ufw reload नहीं चलाते।
ufw status प्रत्येक नियम को दो बार सूचीबद्ध करता है, एक बार सामान्य रूप से और एक बार (v6) सफिक्स के साथ। जब आप (v6) लाइनें देखते हैं, तो UFW IPv6 को फ़िल्टर कर रहा होता है:
22/tcp ALLOW IN Anywhere
22/tcp (v6) ALLOW IN Anywhere (v6)यदि आप iptables को मैन्युअल रूप से प्रबंधित करते हैं, तो हर नियम को ip6tables में भी दोहराएं, या nftables पर स्विच करें, जिसकी inet टेबल IPv4 और IPv6 को एक ही स्थान पर कवर करती है और इस प्रकार की गलतियों की संभावना को पूरी तरह समाप्त कर देती है। जब आप स्वयं नियम लिख रहे हों, तो एक एकल nftables inet फ़िल्टर टेबल सबसे स्वच्छ समाधान है। यदि आपका VPS Ubuntu के बजाय Rocky या AlmaLinux चलाता है, तो कॉन्फ़िगर करने के लिए कोई UFW नहीं है और firewalld वह फ्रंट एंड है जिसे आप इसके बजाय प्रबंधित करते हैं, जो अपने ज़ोन नियमों को एक साथ दोनों स्टैक पर लागू करता है।
जिन सेवाओं को आप सार्वजनिक नहीं करना चाहते, उन्हें loopback पर बाइंड करें। डेटाबेस, एडमिन पैनल या मेट्रिक्स एंडपॉइंट को शायद ही कभी सार्वजनिक पते की आवश्यकता होती है। इसे 127.0.0.1 और ::1 पर बाइंड करें ताकि यह कभी भी रूट करने योग्य पते पर लिसन न करे। Postgres के लिए, listen_addresses = 'localhost' सेट करें। ऐप सर्वर के लिए, इसे 127.0.0.1 पर बाइंड करें और सामने एक reverse proxy रखें। लिसनर को बंद करना उसे फ़ायरवॉल करने से बेहतर है, क्योंकि ऐसा करने पर पहुँचने के लिए कुछ भी नहीं बचता।
Docker के पब्लिश किए गए पोर्ट्स की सुरक्षा के लिए UFW पर भरोसा न करें। कंटेनर पोर्ट्स को हर इंटरफ़ेस के बजाय एक विशिष्ट पते पर पब्लिश करें, उदाहरण के लिए -p 127.0.0.1:8080:80, ताकि पोर्ट केवल होस्ट और आपके द्वारा जानबूझकर प्रॉक्सी की गई चीज़ों से ही पहुँचा जा सके। जब किसी कंटेनर को वास्तव में सार्वजनिक होना ही हो, तो उसे Traefik reverse proxy के पीछे रखें और केवल प्रॉक्सी को पब्लिश करें, न कि प्रत्येक ऐप को।
अपने प्रदाता फ़ायरवॉल में IPv6 नियम जोड़ें, या यह स्वीकार करें कि यह IPv6 के लिए आपका फ़ायरवॉल नहीं है और होस्ट पर UFW या nftables को वह काम करने दें।
सुनिश्चित करें कि पोर्ट वास्तव में बंद हैं
अपने बदलावों के बाद बाहर से वही टेस्ट दोबारा चलाएं:
curl -6 -v http://[2001:db8:2a::1]:8080/
nmap -6 2001:db8:2a::1जो पोर्ट पहले जवाब दे रहा था, उसे अब कनेक्शन अस्वीकार (refuse) करना चाहिए या टाइम आउट हो जाना चाहिए। nmap को इसे filtered या closed रिपोर्ट करना चाहिए। यदि पोर्ट अभी भी खुला है, तो ऊपर बताए गए तीन संभावित कारणों की दोबारा जांच करें: कोई सर्विस अभी भी :: पर बाइंड है और उसके आगे कोई नियम नहीं है, UFW के आगे कोई Docker नियम मौजूद है, या प्रदाता का फायरवॉल जिसे IPv6 का पता ही नहीं चला।
संवेदनशील सेवाओं को पूरी तरह से पब्लिक इंटरनेट से दूर रखना अधिक सुरक्षित है। SSH और एडमिन पैनल को WireGuard VPN के पीछे रखें और उनके पोर्ट्स पर फायरवॉल लगाएं ताकि वे केवल टनल पर ही जवाब दें। ऐसा करने पर उन पर IPv6 एक्सपोज़र का खतरा खत्म हो जाता है। जो सेवाएं पब्लिक रहती हैं, उन पर होने वाले ब्रूट-फोर्स स्कैन को धीमा करने के लिए, डिफ़ॉल्ट-डिनाय फायरवॉल के ऊपर SSH के आगे Fail2ban लगाएं।
यदि पोर्ट्स आपके लिए नया विषय है, तो पोर्ट क्या हैं और सेवाएं कैसे लिसन करती हैं यह लेख सबसे पहले पढ़ें।
FAQ
क्या UFW डिफ़ॉल्ट रूप से IPv6 को ब्लॉक करता है?
आधुनिक Ubuntu 24.04 इंस्टॉलेशन पर, हाँ। UFW, IPV6=yes से /etc/default/ufw को पढ़ता है और प्रत्येक नियम को IPv4 और IPv6 दोनों पर लागू करता है, और ufw status, IPv6 नियमों को (v6) प्रत्यय के साथ दिखाता है। समस्या तब आती है जब आप किसी ऐसे प्रदाता फ़ायरवॉल पर निर्भर रहते हैं जो केवल IPv4 को फ़िल्टर करता है, जब हाथ से लिखे गए iptables नियमों का कोई ip6tables विकल्प नहीं होता, या जब Docker, UFW के बाहर कोई पोर्ट पब्लिश कर देता है। IPV6=no (किसी पुरानी इमेज या पुराने ट्यूटोरियल से) IPv6 को नहीं खोलता है: इसके साथ, एक सक्रिय UFW लूपबैक को छोड़कर सभी IPv6 ट्रैफ़िक को ड्रॉप कर देता है। grep IPV6 /etc/default/ufw के साथ स्विच की जाँच करें।
मैं यह कैसे जाँचूँ कि मेरा VPS IPv6 पर क्या एक्सपोज़ कर रहा है?
sudo ss -tlnp चलाएँ और प्रत्येक लिसनर को नोट करें जिसका स्थानीय पता [::] से शुरू होता है, जिसका अर्थ है कि यह हर IPv6 इंटरफ़ेस पर उत्तर देता है। फिर, एक अलग मशीन से, सर्वर के सार्वजनिक IPv6 पते का सीधे curl -6 -v http://[YOUR:IPV6::ADDR]:PORT/ के साथ परीक्षण करें, या nmap -6 YOUR:IPV6::ADDR के साथ इसे स्कैन करें। IPv6 स्कैन पर खुला कोई भी पोर्ट जो IPv4 पर बंद है, वह आपकी सुरक्षा में कमी है।
जब UFW कहता है कि मेरा Docker कंटेनर पोर्ट ब्लॉक है, तो मैं उस तक क्यों पहुँच सकता हूँ?
जब आप -p के साथ कोई पोर्ट पब्लिश करते हैं, तो Docker अपने स्वयं के फ़ायरवॉल नियमों को UFW के नियमों से पहले डाल देता है, इसलिए पब्लिश किया गया पोर्ट तब भी पहुँच योग्य होता है जब ufw status उसे डिनाइड (denied) के रूप में सूचीबद्ध करता है। यह IPv4 पर होता है, और IPv6 पर भी तब होता है जब Docker का IPv6 सपोर्ट चालू हो। किसी विशिष्ट पते जैसे -p 127.0.0.1:8080:80 पर पब्लिश करें, या कंटेनर को रिवर्स प्रॉक्सी के पीछे रखें और केवल प्रॉक्सी को ही पब्लिश करें।
यदि मेरा IPv4 फ़ायरवॉल मजबूत है, तो क्या मुझे अभी भी IPv6 फ़ायरवॉल की आवश्यकता है?
हाँ। IPv4 और IPv6 अलग-अलग नेटवर्क स्टैक हैं जिनमें अलग-अलग फ़ायरवॉल नियम होते हैं। IPv4 नियमों का एक सटीक सेट IPv6 ट्रैफ़िक के लिए कुछ नहीं करता है। यदि आपके VPS के पास एक सार्वजनिक IPv6 पता है, और लगभग सभी के पास होता है, तो :: पर लिसन करने वाली कोई भी सेवा IPv6 पर तब तक पहुँच योग्य रहती है जब तक कि कोई IPv6 फ़ायरवॉल नियम या लूपबैक बाइंडिंग उसे रोक न दे।
मैं किसी सेवा को केवल IPv4 पर, या केवल localhost पर लिसन करने के लिए कैसे सेट करूँ?
सेवा के कॉन्फ़िगरेशन में उसका बाइंड एड्रेस सेट करें। केवल IPv4 लूपबैक के लिए 127.0.0.1 पर बाइंड करें, या बिना IPv6 लिसनर के सभी IPv4 पतों के लिए 0.0.0.0 पर बाइंड करें। Postgres listen_addresses का उपयोग करता है, SSH ListenAddress का उपयोग करता है, और अधिकांश ऐप सर्वर एक होस्ट या बाइंड फ्लैग एक्सपोज़ करते हैं। sudo ss -tlnp के साथ परिणाम की पुष्टि करें और जाँचें कि Local Address अब [::] नहीं दिखाता है।