VPN-এ Docker কন্টেইনার নাগালের বাইরে? সাবনেটগুলো মিলিয়ে দেখুন
Docker এমন একটি সাবনেট দেয় যা VPN-ও দাবি করে। দুটি ঠিকানা পরিকল্পনা মিলিয়ে দেখুন, তারপর এমন মেরামত বাছুন যা পুনরায় সংযোগে টিকে থাকে।
কন্টেইনারগুলো অফিস LAN-এ সাড়া দেয়, তারপর কোম্পানির VPN সংযুক্ত হওয়ার মুহূর্তেই সাড়া দেওয়া বন্ধ করে দেয়। কন্টেইনারের ভেতরে কিছুই বদলায়নি: কোনো রিস্টার্ট নেই, ইমেজ আপডেট নেই, কনফিগ পরিবর্তন নেই। যা বদলেছে তা হলো হোস্টের রাউটিং টেবিল, যেখানে টানেলের যোগ করা একটি রুট এখন Docker যে ঠিকানা দিয়েছিল তা ঢেকে দিয়েছে। সাবনেট সম্পাদনা করার বা VPN বাদ দেওয়ার অনুরোধ করার আগে দুটি ঠিকানা পরিকল্পনা পাশাপাশি রাখুন, কারণ মেরামতগুলোর সময় খরচ খুব আলাদা।
কনফিগ বদলানোর আগে রুটটি পড়ুন
Docker আসলে যে নেটওয়ার্ক তৈরি করেছে তা দিয়ে শুরু করুন। IPAM ব্লকটি ঠিকানা পরিকল্পনা, আর সাবনেট হলো সেই লাইন যা গুরুত্বপূর্ণ:
docker network inspect project_default --format '{{json .IPAM.Config}}'
# [{"Subnet":"172.18.0.0/16","Gateway":"172.18.0.1"}]Compose ডিফল্টভাবে প্রতিটি নতুন প্রকল্পের জন্য একটি /16 বরাদ্দ করে, তাই দুটি সার্ভিস 65,536 ঠিকানার পরিসরের ভেতরে থাকতে পারে। এই প্রস্থই ওভারল্যাপ সাধারণ হওয়ার কারণ: এলোমেলোভাবে বাছাই করা একটি /16 টানেল দিয়ে আপনি যে সাইটে পৌঁছান তা গিলে ফেলার মতো যথেষ্ট বড়, এবং টানেল ওঠার আগে কেউ তা লক্ষ্য করে না।
তারপর একটি কন্টেইনার ঠিকানার জন্য রুট নির্বাচন মিলিয়ে দেখুন, একবার টানেল বন্ধ এবং একবার চালু অবস্থায়:
ip route get 172.18.0.7
# 172.18.0.7 dev br-3f2a9c src 172.18.0.1দুই ধরনের উত্তর ভিন্ন জায়গায় নিয়ে যায়। যদি আউটপুট tun0, wg0 বা অন্য কোনো টানেল ডিভাইসের নাম বলে, তাহলে VPN প্রিফিক্স ব্রিজ রুটের চেয়ে কম নির্দিষ্ট নয় এবং প্যাকেটটি কখনোই কন্টেইনারে পৌঁছায় না. যদি এটি এখনো ব্রিজের নাম বলে, তাহলে হোস্ট কন্টেইনারে পৌঁছাতে পারে, আর আপনার ত্রুটি হলো ফিল্টারিং, DNS, বা এমন ফেরার পথ যা কেবল এক দিকেই ব্যর্থ হয়।
কেন /16 সংঘর্ষ সহজেই ঘটে
Docker প্রাইভেট পুল থেকে ব্রিজ নেটওয়ার্ক নেয়, আর ডিফল্ট পুল আসে 172.16.0.0/12 ব্লক থেকে /16 টুকরোয়। কর্পোরেট নেটওয়ার্ক প্রায়ই একই প্রাইভেট স্পেস ব্যবহার করে, এবং রিমোট-অ্যাক্সেস VPN সেই প্রিফিক্সগুলো প্রতিটি সংযুক্ত ক্লায়েন্টে ঠেলে দেয়। যখন দুই পক্ষই মনে করে তারা 172.18.0.0/16-এর মালিক, তখন একটি রাউটিং টেবিল দুইটি পরস্পরবিরোধী দাবি ধারণ করে।
প্রিফিক্সের দৈর্ঘ্যই বিজয়ী নির্ধারণ করে, রুটগুলো যে ক্রমে দেখা যায় তা নয়। যে টানেল 10.0.0.0/8 ঠেলে দেয় তা ব্রিজ রুট 172.18.0.0/16-কে হারাতে পারে না, কারণ /8 কম নির্দিষ্ট। যে টানেল 172.18.0.0/16, বা তার ভেতরের 172.18.5.0/24 ঠেলে দেয়, তা পারে। এজন্যই একটি ল্যাপটপ অফিস নেটওয়ার্কে কাজ করে আর একই VPN নিয়ে হোটেলের Wi-Fi-তে ব্যর্থ হয়: ক্লায়েন্ট ভিন্ন ভিন্ন প্রিফিক্স পায়।
একই টেবিল বিপরীত দিকও নিয়ন্ত্রণ করে। যে কন্টেইনার 10.8.4.20 ঠিকানায় একটি অভ্যন্তরীণ হোস্ট দরকার, সে প্যাকেটটি তার ব্রিজ গেটওয়েতে পাঠায়, আর হোস্ট পরে সেটি টানেলে রাউট করে। এই পথ সাধারণত কাজ করে কারণ হোস্ট NAT করে, কিন্তু এটি ব্যর্থ হয় যখন কর্পোরেট পক্ষ কেবল ল্যাপটপের VPN ঠিকানা গ্রহণ করে, বা যখন রিভার্স-পাথ ফিল্টারিং অসমমিত উত্তরটি ফেলে দেয়।
তিনটি মেরামত মিলিয়ে দেখুন
বেরোনোর পথ কেবল তিনটি, আর তারা আলাদা এই দিকে যে কে অনুমোদন দিতে হবে এবং একটি প্রয়োগ করার সময় কী ভাঙে।
| Repair | Who owns it | What it costs |
|---|---|---|
| Renumber the container network | You | Recreates the network, restarts services, invalidates literal addresses in configs and scripts |
| Exclude your range from the tunnel | Network team | Changes what every laptop sees, needs a change request and a client profile update |
| Reach the service through a published port | You and the client | One port only, no direct container-to-container routing across the tunnel |
পুনঃনম্বরকরণই একমাত্র মেরামত যা টিকিট ছাড়া শেষ করা যায়, তাই বেশিরভাগ লেখা সেখানেই থেমে যায়। নতুন প্রকল্পে এটি সস্তা আর ব্যয়বহুল হয়ে ওঠে যখন কোনো মাইগ্রেশন টুল বা সংরক্ষিত সংযোগ স্ট্রিং একটি আক্ষরিক ঠিকানা দেখায়। YAML সম্পাদনার আগে সেই রেফারেন্সগুলো গুনুন, পরে নয়।
টানেল থেকে বাদ দেওয়াই সবচেয়ে পরিচ্ছন্ন উত্তর যখন ওভারল্যাপটি এমন পরিসরে থাকে যা আপনার কোম্পানি সত্যিই মালিকানায় রাখে। এটি সবচেয়ে ধীরও, এবং ঠিকাদারের জন্য অকেজো যে ক্লায়েন্ট প্রোফাইল বদলাতে পারে না। একটি প্রকাশিত পোর্ট বা ছোট রিভার্স প্রক্সি তর্ক এড়ায়: ক্লায়েন্ট এমন ঠিকানার সাথে কথা বলে যা টানেল ইতিমধ্যে সঠিকভাবে রাউট করে, এবং কেবল সেই পোর্টটিই নাগালে থাকতে হবে।
উদ্দেশ্য নিয়ে একটি পরিসর পিন করুন
একটি প্রকল্পের জন্য compose ফাইলে সাবনেট ঘোষণা করুন যাতে প্রকল্পটি শেয়ারড পুল থেকে নেওয়া বন্ধ করে:
networks:
default:
ipam:
config:
- subnet: 10.201.7.0/24সেই পরিসরটি আপনার দলের রাখা রেজিস্ট্রি থেকে নিন, অনুসন্ধানের সময় পাওয়া কোনো উদাহরণ থেকে নয়। VPN যে প্রিফিক্স ঠেলে দেয়, মানুষ যে হোম LAN থেকে কাজ করে, এবং একই হোস্টের অন্য কন্টেইনার নেটওয়ার্কের বিপরীতে এটি যাচাই করুন। তারপর পুনঃনির্মাণের পরিকল্পনা করুন, কারণ বিদ্যমান নেটওয়ার্ক তার পুরোনো সাবনেট ধরে রাখে: docker compose down, তারপর up -d. docker network rm এন্ডপয়েন্ট সংযুক্ত থাকা অবস্থায় অস্বীকার করে, এবং ফাইলের যেকোনো ipv4_address এন্ট্রি নতুন পরিসরের ভেতরে পড়তে হবে।
Docker নিজে যে নেটওয়ার্ক তৈরি করে, তার জন্য ডেমন পুল সেট করুন /etc/docker/daemon.json-এ:
{
"default-address-pools": [
{ "base": "10.201.0.0/16", "size": 24 },
{ "base": "10.202.0.0/16", "size": 24 }
]
}পুলটি ডেমন রিস্টার্টের পরে তৈরি নেটওয়ার্কে প্রযোজ্য, আর আগে থেকে থাকা ব্রিজগুলো তাদের ঠিকানা ধরে রাখে। এটি সুবিধাজনক এবং ভুলে যাওয়া সহজ, তাই পুরোনো প্রকল্পকে ততক্ষণ ওভারল্যাপিং ধরুন যতক্ষণ না কেউ তার নেটওয়ার্ক পুনঃনির্মাণ করে। Docker-এর ইঞ্জিন নেটওয়ার্কিং ডকুমেন্টেশন বরাদ্দের নিয়ম বর্ণনা করে, যদি পর্যালোচনায় পুলটি সমর্থন করতে হয়।
Linux ব্রিজ আর Docker Desktop ভিন্নভাবে ব্যর্থ হয়
Linux হোস্টে কন্টেইনারগুলো হোস্ট নেমস্পেসের ব্রিজে থাকে। একটি টেবিলই সব ঠিক করে, তাই উপরের তুলনাটিই সম্পূর্ণ গল্প: ব্রিজ রুট পড়ুন, টানেল রুট পড়ুন, এবং দেখুন বাস্তব কন্টেইনার ঠিকানার জন্য কোনটি জেতে।
Docker Desktop কন্টেইনারগুলোকে নিজস্ব NAT সহ একটি VM-এর পেছনে রাখে। হোস্টের কন্টেইনার ঠিকানায় কোনো রুটই নেই; এটি প্রকাশিত পোর্টের মাধ্যমে সার্ভিসে পৌঁছায়, সাধারণত 127.0.0.1-এ বাইন্ড করা থাকে। তাই একটি VPN ক্লায়েন্ট কোনো সাবনেট ওভারল্যাপ ছাড়াই সার্ভিসটি ভাঙতে পারে — হয় VM-এর অভ্যন্তরীণ পরিসরের জন্য রুট বসিয়ে, নয়তো টানেল সংযুক্ত থাকা অবস্থায় loopback ট্রাফিক ব্লক করে। যদি হোস্টে ip route get কন্টেইনার ঠিকানার জন্য কোনো রুট না জানায়, তবে এটি প্রত্যাশিত, বাগ নয়।
ব্যবহারিক ফল হলো আপনি প্রথমে কোথায় দেখবেন। Linux-এ রাউটিং টেবিল দিয়ে শুরু করুন। Desktop-এ প্রকাশিত পোর্ট আর VPN ক্লায়েন্টের ফায়ারওয়াল নিয়ম দিয়ে শুরু করুন, তারপর দেখুন VM-এর অভ্যন্তরীণ সাবনেট টানেলের ঠেলে দেওয়া কিছুর সাথে সংঘর্ষ করছে কি না।
টানেল চালু রেখে যাচাই করুন
ঠিক হয়েছে বলার আগে VPN দুবার পুনঃসংযোগ করুন, কারণ যে প্রোফাইল সংযোগে রুট ঠেলে দেয় আর বিচ্ছিন্নতায় প্রত্যাহার করে, তা প্রথম চেষ্টার পরে সঠিক দেখাতে পারে। তারপর ক্লায়েন্ট যে পরীক্ষাগুলো সত্যিই চালায় সেগুলো চালান:
ip route getহোস্ট থেকে, কন্টেইনারের আসল ঠিকানা ব্যবহার করে।- অন্য কন্টেইনার থেকে একটি অনুরোধ, সার্ভিসটি নিজেই সুস্থ তা প্রমাণ করতে।
curl -sv http://127.0.0.1:8080/টানেল চালু অবস্থায় ক্লায়েন্ট থেকে, তারপরtraceroute -nLAN-এর একটি মেশিন থেকে কন্টেইনার ঠিকানায়।sysctl net.ipv4.conf.all.rp_filterযদি অনুরোধ হোস্টে পৌঁছায় কিন্তু উত্তর উবে যায়।
শেষে, বাছাই করা পরিসরটি সেই একই রেজিস্ট্রিতে লিখুন যা থেকে আপনি এটি বেছেছিলেন, তারিখ ও মালিকানা রাখা প্রকল্পসহ। পরবর্তী ওভারল্যাপ আসবে এমন প্রকল্প থেকে যা কেউ নথিভুক্ত করেনি, আর একমাত্র প্রতিরক্ষা হলো পরিসরটি উদ্দেশ্য নিয়ে সংরক্ষিত ছিল, এলোমেলোভাবে টানা নয়।