UFW आणि IPv6 सुरक्षा त्रुटी कशी सुधारावी
तुमच्या VPS मध्ये IPv4 सुरक्षित असूनही IPv6 द्वारे ports उघडे राहू शकतात. ही त्रुटी कशी ओळखावी आणि UFW मध्ये IPv6 नियम कसे लागू करावेत ते येथे पहा.
IPv6 firewall चा धोका एका वाक्यात
तुमचा firewall IPv4 चे संरक्षण करतो. तुमच्या VPS कडे जवळजवळ खात्रीने एक public IPv6 address देखील असते आणि अनेक services डीफॉल्टनुसार त्यावर listen करत असतात. जर तुमचा firewall फक्त IPv4 साठी असेल, किंवा तुम्ही अशा cloud firewall वर अवलंबून असाल जो फक्त IPv4 फिल्टर करतो, तर तुमची IPv4 बाजू सुरक्षित वाटत असतानाही, त्यातील प्रत्येक service संपूर्ण इंटरनेटवरून IPv6 द्वारे सुलभतेने उपलब्ध असते. तुम्ही curl वापरून port test करता, 'refused connection' पाहता आणि सुरक्षितता अनुभवता. परंतु, एखादा attacker त्याच port वर IPv6 द्वारे कनेक्ट होऊन आत प्रवेश करू शकतो.
हे guide एका सामान्य Ubuntu 24.04 VPS वर ही त्रुटी कोठे निर्माण होते, तुम्ही नेमके काय expose करत आहात हे कसे पाहायचे आणि ती त्रुटी कशी दूर करायची, हे दर्शवते. येथे UFW हा दोष नाही. आधुनिक Ubuntu install मध्ये UFW आधीच IPv6 हाताळतो. ही असुरक्षितता त्याच्या आसपासच्या layers मुळे आणि तुम्हाला माहित नसलेल्या listening services मुळे निर्माण होते.
तुमच्या VPS मध्ये IPv6 का असते
आजकाल जवळजवळ प्रत्येक VPS मध्ये IPv4 पत्त्यासोबत सार्वजनिक IPv6 पत्ता असतो, जो अनेकदा पूर्ण /64 असतो. तुमचा पत्ता तपासा:
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 पत्त्याप्रमाणेच. आता कोणते service 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 पत्त्यावर listen करणे." [::]:22 म्हणजे "प्रत्येक IPv6 पत्त्यावर listen करणे." 127.0.0.1:5432 हा loopback ला bound आहे आणि तो सार्वजनिक (public) नाही, त्यामुळे Postgres line सुरक्षित आहे. दोन [::] lines IPv6 वर संपूर्ण इंटरनेटला प्रतिसाद देतात, आणि docker-proxy ही अशी line आहे जी सुरू केल्यावर आपण विसरून जातो.
बहुतेक daemons डिफॉल्टनुसार :: ला bind होतात, कारण Linux वर :: socket सहसा IPv4 देखील स्वीकारते. त्यामुळे नवीन सर्व्हरची डीफॉल्ट स्थिती "दोन्ही stacks वर, सर्वत्र प्रतिसाद देणे" अशी असते. तुमचे firewall हे एकमेव संरक्षण आहे, म्हणूनच फक्त एका stack ला पाहणारे firewall असणे ही मोठी समस्या आहे.
IPv6 मधील त्रुटीचे (gap) नेमके कारण काय आहे
याची चार सामान्य कारणे आहेत. एखाद्या विशिष्ट सिस्टमवर यापैकी एक किंवा एकापेक्षा जास्त कारणे असू शकतात.
1. केवळ IPv4 फिल्टर करणारा क्लाउड फायरवॉल. अनेक प्रोव्हायडर फायरवॉल आणि security-group उत्पादने IPv4 साठी तयार झाली आहेत. त्यामुळे ती IPv6 कडे दुर्लक्ष करतात किंवा तुम्हाला स्वतंत्र IPv6 नियम मॅन्युअली जोडावे लागतात. जर तुमचा एकमेव फायरवॉल प्रोव्हायडर डॅशबोर्डमधील असेल आणि तो IPv6 कव्हर करत नसेल, तर IPv4 वरील port 22 बद्दल काहीही सांगितले असले तरी तुमचे [::] सर्व्हिसेस उघडे (open) राहतील. तुमच्या प्रोव्हायडरचे फायरवॉल डॉक्युमेंटेशन वाचा आणि विशेषतः IPv6 शब्दाचा शोध घ्या.
2. ip6tables शिवाय हाताने लिहिलेले iptables. iptables कमांड फक्त IPv4 टेबल्सवर काम करते. IPv6 साठी ip6tables नावाची पूर्णपणे वेगळी कमांड आणि स्वतंत्र नियम असतात. जर तुम्ही iptables -A INPUT ... ओळींचा वापर करून फायरवॉल स्क्रिप्ट लिहिली असेल आणि त्याऐवजी ip6tables नियम लिहिले नसतील, तर तुमचा IPv6 फायरवॉल रिकामी असेल. रिकामी INPUT chain आणि default ACCEPT पॉलिसीमुळे सर्व ट्रॅफिकला परवानगी मिळते:
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 मध्ये एखादा पोर्ट 'denied' दाखवला तरी तो पोर्ट उपलब्ध असतो; आधुनिक Docker मध्ये हीच स्थिती IPv6 साठी देखील लागू होते. Why Docker bypasses UFW, and how to filter container ports properly मध्ये ही प्रक्रिया आणि उपाय दिले आहेत. हे पब्लिश केलेले पोर्ट्स कसे घोषित केले जातात हे समजून घेण्यासाठी the basics of Docker Compose on a VPS पहा.
4. IPv6 बंद असलेला UFW. UFW मध्ये IPv6 सपोर्ट आहे, परंतु तो सक्षम केल्यावरच काम करतो. स्विच तपासा:
grep IPV6 /etc/default/ufwआधुनिक Ubuntu मध्ये IPV6=yes असते, त्यामुळे UFW प्रत्येक नियम दोन्ही स्टॅक्सवर लागू करते. जर तुम्हाला जुन्या इमेज किंवा गाईडमधील IPV6=no दिसले, तर तुम्ही लिहिलेले सर्व UFW नियम केवळ IPv4 साठी आहेत आणि IPv6 अनमॅनेज्ड (unmanaged) आहे.
तुम्ही नेमके काय एक्सपोज करत आहात ते तपासा
अंदाज लावू नका. बाहेरून त्याचे मोजमाप करा. प्रथम तुमचे listeners सूचीबद्ध करा आणि :: ला बाउंड असलेले सर्व listeners नोंदवून घ्या:
sudo ss -tlnp | grep '::'त्यानंतर, दुसऱ्या मशीनवरून, सर्व्हरच्या public IPv6 address ला कनेक्ट करा आणि तुम्हाला बंद वाटणारा port वापरून पहा:
curl -6 -v http://[2001:db8:2a::1]:8080/जर तुम्हाला एखादे page किंवा banner मिळाले, तर तो port IPv6 वर open आहे. बंद port तुम्हाला Connection refused किंवा timeout देईल. पूर्ण माहितीसाठी, सर्व्हरच्या बाहेरून nmap वापरून IPv6 address स्कॅन करा:
nmap -6 2001:db8:2a::1nmap द्वारे IPv6 वर open असलेला प्रत्येक port संपूर्ण इंटरनेटला उपलब्ध असतो, तुमच्या IPv4 स्कॅनमध्ये काहीही दिसले तरीही. IPv4 आणि IPv6 स्कॅनची तुलना करणे हा त्रुटी शोधण्याचा सर्वात जलद मार्ग आहे: जर -6 वर काही open असेल पण IPv4 वर बंद असेल, तर तो तुमचा firewall मिसळलेला service आहे.
Close the 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 दोनदा दिलेला आहे: एकदा साधा आणि एकदा (v6) suffix सह. जेव्हा तुम्हाला (v6) lines दिसतील, तेव्हा UFW IPv6 फिल्टर करत आहे:
22/tcp ALLOW IN Anywhere
22/tcp (v6) ALLOW IN Anywhere (v6)जर तुम्ही iptables मॅन्युअली मॅनेज करत असाल, तर ip6tables मध्ये प्रत्येक rule mirror करा, किंवा nftables कडे वळा. nftables मधील inet tables IPv4 आणि IPv6 एकाच ठिकाणी कव्हर करतात आणि या प्रकारच्या चुका टाळतात. जर तुम्ही स्वतः 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 सर्व interfaces वर publish करण्याऐवजी एका विशिष्ट address वर publish करा, उदाहरणार्थ -p 127.0.0.1:8080:80, जेणेकरून तो port फक्त host आणि तुम्ही मुद्दाम proxy केलेल्या गोष्टींकडूनच reachable असेल. जेव्हा container खरोखर public असणे आवश्यक असते, तेव्हा त्याला a Traefik reverse proxy च्या मागे ठेवा आणि फक्त proxy publish करा, प्रत्येक app नाही.
तुमच्या provider firewall मध्ये IPv6 rules जोडा, किंवा हे मान्य करा की ते IPv6 साठी तुमचे firewall नाही आणि त्याऐवजी host वरील UFW किंवा nftables ला ते काम करू द्या.
तुम्ही खरोखर बंद (closed) झाला आहे याची खात्री करा
तुमच्या बदलांनंतर पुन्हा तोच बाह्य (outside) टेस्ट रन करा:
curl -6 -v http://[2001:db8:2a::1]:8080/
nmap -6 2001:db8:2a::1आधी ज्या पोर्टने प्रतिसाद दिला होता, तो आता 'refuse' किंवा 'time out' झाला पाहिजे, आणि nmap मध्ये तो 'filtered' किंवा 'closed' असा दाखवला पाहिजे. जर एखादा पोर्ट अजूनही 'open' असेल, तर वरील चार स्रोतांची पुन्हा तपासणी करा: एखादी सर्व्हिस अजूनही :: ला बाउंड आहे आणि तिच्या समोर कोणताही नियम (rule) नाही, Docker नियम UFW च्या पुढे आहे, किंवा प्रोव्हायडर फायरवॉलने IPv6 ला अजिबात पाहिले नाही.
संवेदनशील सर्व्हिसेस पूर्णपणे पब्लिक इंटरनेटपासून दूर ठेवणे अधिक सुरक्षित आहे. SSH आणि admin panels ला WireGuard VPN च्या मागे ठेवा आणि त्यांच्या पोर्ट्सना फायरवॉल करा जेणेकरून ते फक्त टनेलवर प्रतिसाद देतील, ज्यामुळे IPv6 एक्स्पोजरचा प्रश्न त्यांच्यासाठी लागू होणार नाही. जे पोर्ट्स पब्लिक आहेत, त्यावर होणारे brute-force स्कॅन्स कमी करण्यासाठी, 'default-deny' फायरवॉलवर SSH च्या समोर Fail2ban वापरा.
जर पोर्ट्स ही संकल्पना तुमच्यासाठी नवीन असेल, तर ports काय आहेत आणि services कशा प्रकारे listen करतात हे आधी वाचा.
FAQ
UFW द्वारे IPv6 बाय डिफॉल्ट ब्लॉक केला जातो का?
आधुनिक Ubuntu 24.04 इन्स्टॉलेशनमध्ये, हो. UFW, /etc/default/ufw मधून IPV6=yes वाचते आणि प्रत्येक नियम IPv4 आणि IPv6 दोन्हीसाठी लागू करते. ufw status मध्ये IPv6 नियमांवर (v6) सफिक्स दिसते. ही समस्या IPV6=no (जुने इमेज किंवा जुने ट्यूटोरियल), केवळ IPv4 फिल्टर करणाऱ्या प्रोव्हायडर फायरवॉलवर अवलंबून असताना, किंवा Docker ने UFW च्या पलीकडे पोर्ट पब्लिश केल्यास उद्भवते. grep IPV6 /etc/default/ufw वापरून स्विच तपासा.
माझ्या VPS वर IPv6 द्वारे काय एक्सपोज होत आहे हे मी कसे तपासेन?
sudo ss -tlnp चालवा आणि ज्या प्रत्येक लिसनरचा लोकल ॲड्रेस [::] ने सुरू होतो त्याची नोंद करा; याचा अर्थ तो प्रत्येक IPv6 इंटरफेसवर प्रतिसाद देतो. त्यानंतर, दुसऱ्या मशीनवरून, curl -6 -v http://[YOUR:IPV6::ADDR]:PORT/ वापरून सर्व्हरचा पब्लिक IPv6 ॲड्रेस थेट तपासा किंवा nmap -6 YOUR:IPV6::ADDR वापरून स्कॅन करा. IPv6 स्कॅनमध्ये उघडा असलेला पण IPv4 मध्ये बंद असलेला कोणताही पोर्ट म्हणजे तुमची सुरक्षा त्रुटी (gap) आहे.
UFW ने पोर्ट ब्लॉक केला आहे असे सांगूनही मी माझ्या Docker कंटेनरचा पोर्ट का वापरू शकतो?
जेव्हा तुम्ही -p वापरून पोर्ट पब्लिश करता, तेव्हा Docker, UFW च्या आधी स्वतःचे फायरवॉल नियम समाविष्ट करते. त्यामुळे ufw status मध्ये तो पोर्ट 'denied' दिसत असूनही तो उपलब्ध असतो. हे IPv4 वर आणि Docker चा IPv6 सपोर्ट चालू असल्यास IPv6 वर देखील घडते. -p 127.0.0.1:8080:80 सारख्या विशिष्ट ॲड्रेसवर पब्लिश करा, किंवा कंटेनरला रिव्हर्स प्रॉक्सीच्या मागे ठेवा आणि फक्त प्रॉक्सी पब्लिश करा.
जर माझा IPv4 फायरवॉल सुरक्षित असेल, तर मला अजूनही IPv6 फायरवॉलची गरज आहे का?
हो. IPv4 आणि IPv6 हे वेगळे नेटवर्क स्टॅक आहेत आणि त्यांचे फायरवॉल नियम देखील वेगळे असतात. IPv4 नियमांचा IPv6 ट्रॅफिकवर कोणताही परिणाम होत नाही. जर तुमच्या VPS कडे पब्लिक IPv6 ॲड्रेस असेल (जे जवळजवळ सर्वकडे असते), तर :: वर लिसनिंग करणारी कोणतीही सर्व्हिस, जोपर्यंत IPv6 फायरवॉल नियम किंवा लूपबॅक बाइंडिंग तिला थांबवत नाही, तोपर्यंत IPv6 वर उपलब्ध राहते.
एखादी सर्व्हिस फक्त IPv4 वर किंवा फक्त localhost वर कशी चालवायची?
सर्व्हिसच्या स्वतःच्या कॉन्फिगरेशनमध्ये 'bind address' सेट करा. फक्त IPv4 लूपबॅकसाठी 127.0.0.1 ला बाइंड करा, किंवा IPv6 लिसनरशिवाय सर्व IPv4 ॲड्रेससाठी 0.0.0.0 वापरा. Postgres listen_addresses वापरते, SSH ListenAddress वापरते, आणि बहुतेक ॲप सर्व्हर्समध्ये 'host' किंवा 'bind' फ्लॅग असतो. sudo ss -tlnp वापरून निकाल तपासा आणि Local Address मध्ये आता [::] दिसत नाही याची खात्री करा.