UFW এবং IPv6 নিরাপত্তা ঝুঁকি সমাধান
আপনার VPS-এ IPv4 সুরক্ষিত থাকলেও IPv6 এর মাধ্যমে পোর্টে আক্রমণের ঝুঁকি থাকে। UFW এবং ক্লাউড ফায়ারওয়াল কনফিগার করে এই গ্যাপটি কীভাবে বন্ধ করবেন তা জানুন।
এক লাইনে IPv6 ফায়ারওয়াল ট্র্যাপ
আপনার ফায়ারওয়াল IPv4 সুরক্ষিত রাখে। আপনার VPS-এ প্রায় নিশ্চিতভাবে একটি পাবলিক IPv6 অ্যাড্রেস রয়েছে এবং ডিফল্টভাবে অনেক সার্ভিস এতে লিসেন (listen) করে। আপনার ফায়ারওয়াল যদি শুধুমাত্র IPv4 কভার করে, অথবা আপনি যদি এমন কোনো ক্লাউড ফায়ারওয়াল ব্যবহার করেন যা কেবল IPv4 ফিল্টার করে, তবে আপনার IPv4 অংশটি সুরক্ষিত দেখালেও সেই সার্ভিসগুলো IPv6-এর মাধ্যমে পুরো ইন্টারনেট থেকে অ্যাক্সেস করা সম্ভব। আপনি curl দিয়ে একটি পোর্ট টেস্ট করে 'refused connection' দেখতে পান এবং নিরাপদ বোধ করেন। কিন্তু একজন আক্রমণকারী একই পোর্টে IPv6 দিয়ে কানেক্ট করে সহজেই প্রবেশ করতে পারে।
এই গাইডটি একটি সাধারণ Ubuntu 24.04 VPS-এ এই গ্যাপ বা ফাঁক কোথা থেকে তৈরি হয়, আপনি ঠিক কী কী এক্সপোজ (expose) করছেন তা কীভাবে দেখবেন এবং এটি কীভাবে বন্ধ করবেন তা দেখাবে। এখানে UFW কোনো সমস্যা নয়। আধুনিক Ubuntu ইন্সটলেশনে UFW ইতিমধ্যেই IPv6 হ্যান্ডেল করে। এই এক্সপোজারটি ঘটে এর চারপাশের লেয়ারগুলো এবং এমন কিছু সার্ভিস থেকে যা আপনি জানতেন না যে সেগুলো লিসেন করছে।
কেন আপনার 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আপনার IPv4 অ্যাড্রেসের মতোই সেই 2001:db8:2a::1 ইন্টারনেট থেকে যেকোনো জায়গা থেকে রাউট করা সম্ভব। এখন দেখুন কোন সার্ভিসগুলো কানেকশন গ্রহণ করছে:
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 কলামটি মনোযোগ দিয়ে দেখুন। 0.0.0.0:22 মানে হলো "প্রতিটি IPv4 অ্যাড্রেসে লিসেন করা।" [::]:22 মানে হলো "প্রতিটি IPv6 অ্যাড্রেসে লিসেন করা।" 127.0.0.1:5432 শুধুমাত্র loopback-এর সাথে যুক্ত এবং এটি পাবলিক নয়, তাই Postgres লাইনটি নিরাপদ। দুটি [::] লাইন IPv6-এর মাধ্যমে পুরো ইন্টারনেট থেকে রেসপন্স দেয়, আর docker-proxy লাইনটি হলো এমন একটি কানেকশন যা আপনি চালু করেছেন তা ভুলে যেতে পারেন।
অধিকাংশ ডেমোন (daemon) ডিফল্টভাবে ::-এ বাইন্ড হয়, কারণ Linux-এ একটি :: সকেট সাধারণত IPv4-ও গ্রহণ করতে পারে। তাই একটি নতুন সার্ভারের ডিফল্ট অবস্থা হলো "উভয় স্ট্যাকে সব জায়গায় রেসপন্স করা।" আপনার ফায়ারওয়ালই একমাত্র বাধা হিসেবে কাজ করে; এই কারণেই যে ফায়ওয়াল শুধুমাত্র একটি স্ট্যাক দেখতে পায়, তা একটি বড় সমস্যা।
IPv6 গ্যাপ বা ব্যবধান আসলে কেন তৈরি হয়
এর চারটি সাধারণ উৎস রয়েছে। একটি নির্দিষ্ট সার্ভারে এর মধ্যে একটি বা একাধিক সমস্যা থাকতে পারে।
1. শুধুমাত্র IPv4 ফিল্টার করে এমন একটি ক্লাউড ফায়ারওয়াল। অনেক প্রোভাইডারের ফায়ারওয়াল এবং security-group পণ্য IPv4 কেন্দ্রিক তৈরি করা হয়েছে। এগুলো হয় IPv6 উপেক্ষা করে, অথবা আলাদা IPv6 রুলস প্রয়োজন হয় যা আপনাকে হাতে যোগ করতে হবে। যদি আপনার একমাত্র ফায়ারওয়ালটি প্রোভাইডার ড্যাশবোর্ডের ফায়ারওয়াল হয় এবং সেটি IPv6 সাপোর্ট না করে, তবে আপনার [::] সার্ভিসগুলো উন্মুক্ত থাকবে, এমনকি IPv4-এর port 22 সম্পর্কে সেটি যা-ই বলুক না কেন। আপনার প্রোভাইডারের ফায়ারওয়াল ডকুমেন্টেশন পড়ুন এবং বিশেষভাবে 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 বলে যে পোর্টটি নিষিদ্ধ। আধুনিক Docker-এ IPv6-এর ক্ষেত্রেও একই নিয়ম প্রযোজ্য। কেন Docker, UFW বাইপাস করে এবং কীভাবে কন্টেইনার পোর্ট সঠিকভাবে ফিল্টার করবেন এখানে মেকানিজম এবং সমাধান ব্যাখ্যা করা হয়েছে। এই পাবলিশ করা পোর্টগুলো কীভাবে ঘোষণা করা হয় তা জানতে VPS-এ Docker Compose-এর মৌলিক বিষয়সমূহ দেখুন।
4. IPv6 বন্ধ থাকা অবস্থায় UFW ব্যবহার করা। UFW, IPv6 হ্যান্ডেল করতে পারে, কিন্তু শুধুমাত্র তখনই যখন এটিকে নির্দেশ দেওয়া হয়। সুইচটি পরীক্ষা করুন:
grep IPV6 /etc/default/ufwআধুনিক Ubuntu-তে IPV6=yes থাকে, তাই UFW প্রতিটি রুল উভয় স্ট্যাকের জন্যই প্রয়োগ করে। আপনি যদি কোনো পুরনো ইমেজ বা গাইড থেকে IPV6=no দেখেন, তবে আপনার লেখা প্রতিটি UFW রুল শুধুমাত্র IPv4-এর জন্য এবং IPv6 আনম্যানেজড অবস্থায় থেকে যায়।
আপনি ঠিক কী প্রকাশ করছেন তা নিশ্চিতভাবে দেখুন
অনুমান করবেন না। বাইরে থেকে এটি পরিমাপ করুন। প্রথমে আপনার listeners তালিকাভুক্ত করুন এবং ::-এ bound থাকা প্রতিটি listener লক্ষ্য করুন:
sudo ss -tlnp | grep '::'এরপর, অন্য একটি machine থেকে server-এর public IPv6 address-এ কানেক্ট করুন এবং একটি বন্ধ port পরীক্ষা করার চেষ্টা করুন:
curl -6 -v http://[2001:db8:2a::1]:8080/যদি এটি কোনো page বা banner প্রদান করে, তবে IPv6-এ port-টি open আছে। একটি closed port আপনাকে Connection refused অথবা timeout প্রদান করবে। সম্পূর্ণ চিত্র পেতে, server-এর বাইরে থেকে nmap দিয়ে IPv6 address-টি scan করুন:
nmap -6 2001:db8:2a::1nmap যে প্রতিটি port-কে IPv6-এর মাধ্যমে open হিসেবে রিপোর্ট করে, সেটিই হলো এমন একটি port যা পুরো internet থেকে অ্যাক্সেস করা সম্ভব, আপনার IPv4 scan যা-ই দেখাক না কেন। IPv4 এবং IPv6 scan পাশাপাশি তুলনা করা হলো ব্যবধান খুঁজে পাওয়ার দ্রুততম উপায়: -6-এ যা open কিন্তু IPv4-এ closed, সেটি হলো এমন একটি service যা আপনার firewall মিস করছে।
ব্যবধান কমিয়ে আনুন
UFW-কে উভয় স্ট্যাকের জন্য ব্যবহার করুন এবং ডিফল্টভাবে 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 ইতিমধ্যে সক্রিয় থাকে, তবে sudo ufw reload না চালানো পর্যন্ত পরিবর্তনটি কার্যকর হবে না।
ufw status প্রতিটি rule দুবার তালিকাভুক্ত করে, একবার সাধারণ এবং একবার (v6) suffix সহ। যখন আপনি (v6) লাইনগুলো দেখবেন, তখন বুঝবেন UFW IPv6 ফিল্টার করছে:
22/tcp ALLOW IN Anywhere
22/tcp (v6) ALLOW IN Anywhere (v6)আপনি যদি হাতে iptables পরিচালনা করেন, তবে ip6tables-এ প্রতিটি rule mirror করুন, অথবা nftables ব্যবহার করুন। nftables-এর inet tables IPv4 এবং IPv6 উভয়কেই এক জায়গায় কভার করে এবং এই ধরনের ভুল দূর করে। আপনি যদি নিজে rule লিখেন, তবে একটি মাত্র nftables inet filter table ব্যবহার করা সবচেয়ে কার্যকর সমাধান।
যেসব সার্ভিস আপনি পাবলিকলি রাখতে চান না, সেগুলোকে loopback-এ bind করুন। একটি database, admin panel, অথবা metrics endpoint-এর সাধারণত পাবলিক অ্যাড্রেসের প্রয়োজন হয় না। এগুলোকে 127.0.0.1 এবং ::1-এ bind করুন যাতে এগুলো কোনো routable অ্যাড্রেসে listen না করে। Postgres-এর জন্য listen_addresses = 'localhost' সেট করুন। একটি app server-এর জন্য, এটিকে 127.0.0.1-এ bind করুন এবং সামনে একটি reverse proxy ব্যবহার করুন। ফায়ারওয়াল দিয়ে রক্ষা করার চেয়ে listener বন্ধ করে দেওয়া বেশি কার্যকর, কারণ তখন সেখানে পৌঁছানোর মতো কিছু থাকবে না।
Docker-এর published ports সুরক্ষার জন্য UFW-এর ওপর নির্ভর করবেন না। কন্টেইনার পোর্টগুলো সব interface-এর পরিবর্তে একটি নির্দিষ্ট অ্যাড্রেসে publish করুন, যেমন -p 127.0.0.1:8080:80; এতে পোর্টটি শুধুমাত্র host এবং আপনার নির্ধারিত proxy থেকে অ্যাক্সেস করা যাবে। যখন কোনো কন্টেইনারের সত্যিই পাবলিক হওয়া প্রয়োজন, তখন সেটিকে a Traefik reverse proxy-এর পেছনে রাখুন এবং শুধুমাত্র proxy-টি publish করুন, প্রতিটি app নয়।
আপনার প্রোভাইডারের ফায়ারওয়াল-এ IPv6 rules যোগ করুন, অথবা মেনে নিন যে এটি আপনার IPv6 ফায়ারওয়াল নয় এবং সেই কাজের জন্য host-এ থাকা UFW বা nftables ব্যবহার করুন।
নিশ্চিত করুন যে আপনি সত্যিই সংযোগ বিচ্ছিন্ন করেছেন
আপনার পরিবর্তনগুলো করার পর পুনরায় একই এক্সটার্নাল টেস্টটি চালান:
curl -6 -v http://[2001:db8:2a::1]:8080/
nmap -6 2001:db8:2a::1আগে যে port-টি রেসপন্স করেছিল, সেটি এখন রিফিউজ (refuse) বা টাইম-আউট (time out) হওয়া উচিত। nmap রিপোর্ট অনুযায়ী এটি filtered বা closed দেখাবে। যদি কোনো port এখনও open থাকে, তবে উপরের চারটি কারণ পুনরায় পরীক্ষা করুন: কোনো সার্ভিস যদি কোনো রুল ছাড়াই ::-এর সাথে যুক্ত থাকে, Docker রুল যদি UFW-এর আগে থাকে, অথবা কোনো প্রোভাইডার ফায়ারওয়াল যদি IPv6 শনাক্ত করতে না পারে।
সেনসিটিভ সার্ভিসগুলোকে সম্পূর্ণভাবে পাবলিক ইন্টারনেট থেকে দূরে রাখা আরও বেশি নিরাপদ। SSH এবং admin panels-কে WireGuard VPN-এর আড়ালে রাখুন এবং তাদের port-গুলো ফায়ারওয়াল দিয়ে সুরক্ষিত করুন যাতে সেগুলো শুধুমাত্র টানেলের মাধ্যমে রেসপন্স করে; এতে IPv6 এক্সপোজারের বিষয়টি তাদের ক্ষেত্রে আর প্রযোজ্য হবে না। পাবলিকলি থাকা সার্ভিসগুলোর ওপর brute-force স্ক্যান ধীর করার জন্য, একটি default-deny ফায়ারওয়ালের সাথে SSH-এর সামনে Fail2ban ব্যবহার করুন।
আপনি যদি port সম্পর্কে নতুন হন, তবে প্রথমে port কী এবং সার্ভিস কীভাবে listen করে নিবন্ধটি পড়ুন।
FAQ
UFW কি ডিফল্টভাবে IPv6 ব্লক করে?
আধুনিক Ubuntu 24.04 ইন্সটলেশনে, হ্যাঁ। UFW /etc/default/ufw থেকে IPV6=yes রিড করে এবং প্রতিটি রুল IPv4 এবং IPv6 উভয় ক্ষেত্রেই প্রয়োগ করে। ufw status এ (v6) সাফিক্স সহ IPv6 রুলগুলো দেখা যায়। সমস্যাটি তখন ঘটে যখন আপনি 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-এ ক্লোজড দেখাচ্ছে, সেটিই আপনার সিকিউরিটি গ্যাপ।
UFW ব্লক করার কথা বলা সত্ত্বেও আমি কেন আমার Docker কন্টেইনারের পোর্ট অ্যাক্সেস করতে পারছি?
আপনি যখন -p দিয়ে কোনো পোর্ট পাবলিশ করেন, তখন Docker UFW এর আগে তার নিজস্ব ফায়ারওয়াল রুল ইনসার্ট করে। ফলে ufw status দিয়ে রুলটি ডিনাইড (denied) দেখালেও পাবলিশ করা পোর্টটি অ্যাক্সেস করা যায়। এটি IPv4 এবং IPv6 (যদি Docker-এর IPv6 সাপোর্ট অন থাকে) উভয় ক্ষেত্রেই ঘটে। -p 127.0.0.1:8080:80 এর মতো নির্দিষ্ট অ্যাড্রেসে পাবলিশ করুন, অথবা কন্টেইনারটিকে একটি reverse proxy এর পেছনে রাখুন এবং শুধুমাত্র প্রক্সিটি পাবলিশ করুন।
আমার IPv4 ফায়ারওয়াল মজবুত হলে কি আমার এখনও IPv6 ফায়ারওয়াল প্রয়োজন?
হ্যাঁ। IPv4 এবং IPv6 হলো আলাদা নেটওয়ার্ক স্ট্যাক এবং এদের ফায়ারওয়াল রুলও আলাদা। IPv4 রুলের একটি নিখুঁত সেট IPv6 ট্রাফিককে সুরক্ষা দিতে পারে না। যদি আপনার VPS-এ একটি পাবলিক IPv6 অ্যাড্রেস থাকে (যা প্রায় সব VPS-এই থাকে), তবে :: তে কোনো সার্ভিস লিসেন করলে সেটি IPv6 দিয়ে অ্যাক্সেস করা সম্ভব হবে, যতক্ষণ না কোনো IPv6 ফায়ারওয়াল রুল বা loopback binding এটি থামায়।
আমি কীভাবে একটি সার্ভিসকে শুধুমাত্র IPv4 অথবা শুধুমাত্র localhost-এ লিসেন করাব?**
সার্ভিসের নিজস্ব কনফিগারেশনে bind address সেট করুন। শুধুমাত্র IPv4 loopback-এর জন্য 127.0.0.1 এ বাইন্ড করুন, অথবা কোনো IPv6 লিসেনার ছাড়া সব IPv4 অ্যাড্রেসের জন্য 0.0.0.0 ব্যবহার করুন। Postgres listen_addresses ব্যবহার করে, SSH ListenAddress ব্যবহার করে, এবং বেশিরভাগ অ্যাপ সার্ভারে host বা bind ফ্ল্যাগ থাকে। sudo ss -tlnp দিয়ে ফলাফল নিশ্চিত করুন এবং চেক করুন যে Local Address এ আর [::] দেখাচ্ছে না।