UFW और IPv6 security gap कैसे ठीक करें
क्या आपका VPS IPv6 पर असुरक्षित है? जानें क्यों UFW rules केवल IPv4 को सुरक्षित कर पाते हैं और IPv6 के माध्यम से होने वाले attacks को कैसे रोकें।
IPv6 firewall trap का एक वाक्य में विवरण
आपका firewall IPv4 को सुरक्षित करता है। आपके VPS में लगभग निश्चित रूप से एक public IPv6 address भी होता है, और कई services डिफ़ॉल्ट रूप से उस पर listen करती हैं। यदि आपका firewall केवल IPv4 को कवर करता है, या यदि आप ऐसे cloud firewall पर निर्भर हैं जो केवल IPv4 को filter करता है, तो IPv4 सुरक्षित दिखने के बावजूद, वे सभी services IPv6 के माध्यम से पूरे internet से reachable होती हैं। आप curl के साथ एक port को test करते हैं, connection refused देखते हैं, और सुरक्षित महसूस करते हैं। एक attacker उसी port पर IPv6 के माध्यम से connect करता है और अंदर आ जाता है।
यह guide बताती है कि एक सामान्य Ubuntu 24.04 VPS पर यह gap कहाँ से आता है, आप वास्तव में क्या expose कर रहे हैं इसे कैसे देखें, और इसे कैसे बंद करें। यहाँ UFW दोषी नहीं है। आधुनिक Ubuntu install पर UFW पहले से ही IPv6 को handle करता है। यह exposure इसके आस-पास के layers से, और उन services से आता है जिनके बारे में आपको पता नहीं था कि वे listen कर रही हैं।
आपका VPS IPv6 पर क्यों है
आजकल लगभग हर VPS में उसके IPv4 address के साथ एक public IPv6 address होता है, जो अक्सर एक पूरा /64 होता है। अपना 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 इंटरनेट पर कहीं से भी routable है, बिल्कुल आपके IPv4 address की तरह। अब देखें कि कौन listening कर रहा है:
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 IPv6 पर पूरे internet को answer देती हैं, और docker-proxy वाली line वह है जिसे आप चालू करना भूल जाते हैं।
ज़्यादातर daemons default रूप से :: से bind होते हैं, क्योंकि Linux पर एक :: socket आमतौर पर IPv4 को भी accept करता है। इसलिए एक नए server की default setting "दोनों stacks पर, हर जगह answer दें" होती है। आपका firewall ही इसे रोकने वाला एकमात्र साधन है, इसीलिए ऐसा firewall जो केवल एक stack को देखता है, एक बड़ी समस्या है।
IPv6 gap का वास्तविक कारण क्या है
इसके चार सामान्य स्रोत हैं। किसी विशेष box पर आपके पास इनमें से एक या एक साथ कई कारण हो सकते हैं।
1. केवल IPv4 को फ़िल्टर करने वाला cloud firewall. कई provider firewalls और security-group products IPv4 के आधार पर बने हैं। वे या तो IPv6 को अनदेखा करते हैं या उन्हें अलग IPv6 rules की आवश्यकता होती है जिन्हें आपको मैन्युअल रूप से जोड़ना होगा। यदि आपका एकमात्र firewall provider dashboard में है और वह IPv6 को कवर नहीं करता है, तो आपके [::] services खुले रहेंगे, चाहे IPv4 पर port 22 के बारे में कुछ भी लिखा हो। अपने provider के firewall documentation को पढ़ें और विशेष रूप से IPv6 शब्द खोजें।
2. ip6tables के बिना hand-rolled iptables. iptables command केवल IPv4 tables को प्रभावित करता है। IPv6 के लिए एक पूरी तरह से अलग command, ip6tables, है जिसके अपने अलग rules हैं। यदि आपने iptables -A INPUT ... lines से भरा firewall script लिखा है और कभी भी उसके मिलान वाले ip6tables rules नहीं लिखे, तो आपका IPv6 firewall खाली है। एक empty INPUT chain और default ACCEPT policy के साथ सब कुछ अनुमति प्राप्त (allow) हो जाता है:
sudo ip6tables -L INPUT -nChain INPUT (policy ACCEPT)
target prot opt source destinationयह output एक ही screen पर पूरी समस्या को दर्शाता है। IPv4 फ़िल्टर किया जाता है, जबकि IPv6 पूरी दुनिया के लिए खुला रहता है।
3. Docker द्वारा firewall को bypass करके ports publish करना. जब आप docker run -p 8080:80 चलाते हैं, तो Docker UFW से पहले अपने स्वयं के rules डाल देता है। इसलिए, एक published port तक तब भी पहुँचा जा सकता है जब ufw status कहे कि वह port denied है। आधुनिक Docker में यही बात IPv6 पर भी लागू होती है। Why Docker bypasses UFW, and how to filter container ports properly इस mechanism और समाधानों को समझाता है। यह जानने के लिए कि ये published ports कैसे घोषित किए जाते हैं, the basics of Docker Compose on a VPS देखें।
4. IPv6 बंद होने पर UFW. UFW, IPv6 को handle करता है, लेकिन केवल तभी जब इसे निर्देश दिया जाए। switch की जाँच करें:
grep IPV6 /etc/default/ufwआधुनिक Ubuntu में IPV6=yes आता है, इसलिए UFW प्रत्येक rule को दोनों stacks पर लागू करता है। यदि आप किसी पुराने image या पुराने guide से IPV6=no देखते हैं, तो आपके द्वारा लिखा गया प्रत्येक UFW rule केवल IPv4 के लिए है, और IPv6 बिना किसी प्रबंधन (unmanaged) के छोड़ दिया गया है।
देखें कि आप वास्तव में क्या expose कर रहे हैं
अनुमान न लगाएं। बाहर से इसका परीक्षण करें। सबसे पहले अपने listeners की सूची बनाएं और :: पर bound होने वाले सभी ports को नोट करें:
sudo ss -tlnp | grep '::'इसके बाद, किसी अन्य machine से, server के public IPv6 address से connect करें और उस port को try करें जो आपको closed लगता है:
curl -6 -v http://[2001:db8:2a::1]:8080/यदि यह कोई page या banner return करता है, तो IPv6 पर वह port open है। Closed port आपको Connection refused या timeout देगा। पूरी जानकारी के लिए, server के बाहर से nmap का उपयोग करके IPv6 address को scan करें:
nmap -6 2001:db8:2a::1nmap द्वारा IPv6 पर open बताया गया प्रत्येक port वह port है जिसे पूरा internet access कर सकता है, चाहे आपका IPv4 scan कुछ भी दिखाए। IPv4 और IPv6 scans की तुलना करना अंतर खोजने का सबसे तेज़ तरीका है: -6 पर open होने वाला लेकिन IPv4 पर closed होने वाला कोई भी service वह service है जिसे आपका firewall miss कर रहा है।
Gap को खत्म करें
UFW को दोनों stacks के लिए सक्षम करें, और default रूप से deny पर सेट करें। बदलाव की पुष्टि करें, फिर एक default-deny inbound policy सेट करें और केवल वही allow करें जिसकी आपको आवश्यकता है:
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 पहले से ही active था, तो बदलाव तब तक लागू नहीं होगा जब तक आप sudo ufw reload नहीं चलाते।
ufw status प्रत्येक rule को दो बार सूचीबद्ध करता है, एक बार plain और एक बार (v6) suffix के साथ। जब आप (v6) lines देखें, तो इसका अर्थ है कि UFW IPv6 को filter कर रहा है:
22/tcp ALLOW IN Anywhere
22/tcp (v6) ALLOW IN Anywhere (v6)यदि आप iptables को मैन्युअल रूप से manage करते हैं, तो ip6tables में भी हर rule को mirror करें, या nftables पर स्विच करें। nftables के inet tables IPv4 और IPv6 को एक ही स्थान पर cover करते हैं और इस प्रकार की गलतियों को समाप्त कर देते हैं। यदि आप स्वयं rules लिख रहे हैं, तो एक single nftables inet filter table सबसे सटीक समाधान है।
जिन services को आप public नहीं रखना चाहते, उन्हें loopback पर bind करें। Database, admin panel, या metrics endpoint को शायद ही कभी public address की आवश्यकता होती है। इन्हें 127.0.0.1 और ::1 पर bind करें ताकि वे routable address पर listen ही न करें। Postgres के लिए, listen_addresses = 'localhost' सेट करें। App server के लिए, इसे 127.0.0.1 पर bind करें और आगे एक reverse proxy लगाएं। Listener को बंद करना firewalling से बेहतर है, क्योंकि तब वहां पहुँचने के लिए कुछ बचेगा ही नहीं।
Docker के published ports की सुरक्षा के लिए UFW पर भरोसा न करें। Container ports को हर interface के बजाय एक विशिष्ट address पर publish करें, उदाहरण के लिए -p 127.0.0.1:8080:80, ताकि port केवल host और आपके द्वारा जानबूझकर proxy किए गए address से ही reachable हो। जब किसी container को वास्तव में public होना आवश्यक हो, तो उसे a Traefik reverse proxy के पीछे रखें और केवल proxy को publish करें, न कि प्रत्येक app को।
अपने provider firewall में IPv6 rules जोड़ें, या यह स्वीकार करें कि वह IPv6 के लिए आपका firewall नहीं है और उसके बजाय host पर UFW या nftables को यह काम करने दें।
पुष्टि करें कि आप वास्तव में बंद हो चुके हैं
अपने बदलावों के बाद वही बाहरी टेस्ट (outside test) फिर से चलाएं:
curl -6 -v http://[2001:db8:2a::1]:8080/
nmap -6 2001:db8:2a::1जो port पहले उत्तर दे रहा था, वह अब refuse या time out होना चाहिए, और nmap को इसे filtered या closed रिपोर्ट करना चाहिए। यदि कोई port अभी भी open है, तो ऊपर दिए गए चार कारणों की जांच करें: कोई service जो बिना किसी rule के :: से bound है, UFW से पहले लगा हुआ Docker rule, या कोई provider firewall जिसने IPv6 को देखा ही नहीं।
संवेदनशील services को पूरी तरह से public internet से दूर रखना और भी सुरक्षित है। SSH और admin panels को WireGuard VPN के पीछे रखें और उनके ports को firewall करें ताकि वे केवल tunnel पर उत्तर दें; इससे IPv6 exposure की समस्या उन पर लागू नहीं होगी। जो services public रहती हैं, उन पर होने वाले brute-force scans को धीमा करने के लिए, default-deny firewall के ऊपर SSH के सामने Fail2ban का उपयोग करें।
यदि ports आपके लिए नए विषय हैं, तो सबसे पहले ports क्या हैं और services कैसे listen करती हैं पढ़ें।
FAQ
क्या UFW डिफ़ॉल्ट रूप से IPv6 को ब्लॉक करता है?
आधुनिक Ubuntu 24.04 install पर, हाँ। UFW /etc/default/ufw से IPV6=yes पढ़ता है और प्रत्येक rule को IPv4 और IPv6 दोनों पर लागू करता है। ufw status में IPv6 rules (v6) suffix के साथ दिखाई देते हैं। समस्या तब आती है जब आप IPV6=no (पुराने image या tutorial से) का उपयोग करते हैं, जब आप ऐसे provider firewall पर निर्भर होते हैं जो केवल IPv4 को filter करता है, या जब Docker, UFW के बाद किसी port को publish करता है। grep IPV6 /etc/default/ufw के साथ switch की जाँच करें।
मैं यह कैसे जानूँ कि मेरा VPS IPv6 पर क्या expose कर रहा है?
sudo ss -tlnp चलाएँ और उन सभी listeners को नोट करें जिनका local address [::] से शुरू होता है। इसका अर्थ है कि वे प्रत्येक IPv6 interface पर response देते हैं। इसके बाद, किसी अन्य machine से, server के public IPv6 address का curl -6 -v http://[YOUR:IPV6::ADDR]:PORT/ के साथ सीधे परीक्षण करें, या nmap -6 YOUR:IPV6::ADDR के साथ इसे scan करें। IPv6 scan पर खुला हुआ लेकिन IPv4 पर बंद port आपकी security gap है।
जब UFW कहता है कि port blocked है, तो मैं अपने Docker container के port तक कैसे पहुँच पा रहा हूँ?
जब आप -p के साथ port publish करते हैं, तो Docker, UFW से पहले अपने स्वयं के firewall rules डाल देता है। इसलिए, published port तक पहुँचा जा सकता है, भले ही ufw status उसे denied के रूप में सूचीबद्ध करे। यह IPv4 पर होता है, और IPv6 पर भी होता है यदि Docker का IPv6 support चालू है। -p 127.0.0.1:8080:80 जैसे विशिष्ट address पर publish करें, या container को reverse proxy के पीछे रखें और केवल proxy को publish करें।
यदि मेरा IPv4 firewall मजबूत है, तो क्या मुझे अभी भी IPv6 firewall की आवश्यकता है?
हाँ। IPv4 और IPv6 अलग-अलग network stacks हैं जिनमें अलग-अलग firewall rules होते हैं। IPv4 rules का एक perfect set, IPv6 traffic के लिए कुछ नहीं करता है। यदि आपके VPS में public IPv6 address है (जो लगभग सभी में होता है), तो :: पर listening करने वाली कोई भी service तब तक IPv6 पर reachable रहेगी जब तक कि कोई IPv6 firewall rule या loopback binding इसे न रोक दे।
मैं किसी service को केवल IPv4 पर, या केवल localhost पर कैसे listen करवा सकता हूँ?
Service के अपने config में bind address सेट करें। केवल IPv4 loopback के लिए 127.0.0.1 पर bind करें, या बिना किसी IPv6 listener के सभी IPv4 addresses के लिए 0.0.0.0 का उपयोग करें। Postgres listen_addresses का उपयोग करता है, SSH ListenAddress का उपयोग करता है, और अधिकांश app servers में host या bind flag होता है। sudo ss -tlnp के साथ परिणाम की पुष्टि करें और जाँचें कि Local Address अब [::] नहीं दिखा रहा है।