Docker কন্টেইনার ট্রাফিক হোস্ট VPN বাইপাস করে: কীভাবে যাচাই করবেন
হোস্ট VPN কেবল হোস্ট নেমস্পেস কভার করে। এই যাচাইগুলো দিয়ে দেখুন ব্রিজ কন্টেইনার ট্রাফিক টানেলে ঢোকে, নাকি সরাসরি বেরিয়ে যায়।
আপনার হোস্ট ব্রাউজার VPN এক্সিট ঠিকানা দেখায়, কন্টেইনার আপনার বাড়ির সংযোগ জানায়, আর কেউ এটাকে লিক বলে। কিছুই লিক হয়নি। হোস্ট টানেল হলো ইন্টারফেস, রুট আর নিয়মের একটি সমষ্টি যা হোস্ট নেটওয়ার্ক নেমস্পেসের অন্তর্গত, আর ব্রিজে থাকা কন্টেইনার হলো নিজস্ব ডিফল্ট রুটসহ অন্য একটি নেমস্পেস। আমি এমন একটি Compose স্ট্যাকে বসে ছিলাম যেখানে VPN ক্লায়েন্ট সপ্তাহ ধরে সংযুক্ত ছিল আর একটিও কন্টেইনার প্যাকেট কখনো সেখানে ঢোকেনি।
ট্রে আইকনের আগে নেমস্পেস যাচাই করুন
নেমস্পেসই পুরো যুক্তি। Docker যখন ব্রিজ নেটওয়ার্কে একটি কন্টেইনার চালু করে, তখন এটি একটি নেটওয়ার্ক নেমস্পেস তৈরি করে, veth জোড়ার এক প্রান্ত তার ভিতরে যুক্ত করে, এবং সেই নেমস্পেসকে একটি ঠিকানা ও একটি ডিফল্ট রুট দেয়। টানেল ইন্টারফেস, তাকে যাই বলা হোক, হোস্ট নেমস্পেসে থাকে। কন্টেইনারের ভিতরের ট্রাফিক তা দেখতে পায় না, আর কোনো ক্লায়েন্ট সেটিং বাইরে থেকে তা বদলায় না।
বিচ্ছিন্নতা থেকে বেরোনোর দুটি সমর্থিত উপায় আছে। --network host কন্টেইনারকে হোস্ট নেমস্পেসের ভিতরে রাখে, ফলে এটি হোস্টের রুট এবং সেইসাথে টানেল উত্তরাধিকার করে। --network container:vpn অন্য একটি কন্টেইনারের নেমস্পেস ভাগ করে নেয়, আর বেশিরভাগ সাইডকার ডিজাইন এভাবেই ওয়ার্কলোডকে VPN কন্টেইনার দিয়ে পাঠায়। দুটোই স্পষ্ট পছন্দ; সাধারণত এর মধ্যে একটি-ই সেই জিনিস যা ডিপ্লয় করা ব্যক্তি বোঝাতে চেয়েছিলেন।
হোস্ট মোড কোনো বিনামূল্যের আপগ্রেড নয়। কন্টেইনার নিজের ঠিকানা রাখা বন্ধ করে, পোর্ট প্রকাশ আর প্রযোজ্য থাকে না, আর সেখানে NET_ADMIN ধরে রাখা প্রসেস হোস্টের রাউটিং পুনর্লিখন করতে পারে। এটা মেনে নেওয়া সঠিক সিদ্ধান্ত হতে পারে। এটা আগে থেকেই চালু আছে ধরে নেওয়া—এভাবেই লোকেরা সন্ধ্যা পার করে এমন একটি টানেল ডিবাগ করতে গিয়ে যা কখনো পথে ছিলই না।
ব্রিজ থেকে বেরোনো প্যাকেট অনুসরণ করুন
ব্রিজ কন্টেইনার তার প্যাকেট নিজের ডিফল্ট গেটওয়েতে পাঠায়, যা হোস্টের ব্রিজ ইন্টারফেস। এরপর হোস্ট প্যাকেটটি ফরওয়ার্ড করে এবং ডিফল্ট কনফিগারেশনে প্যাকেট বেরোনোর আগে সোর্স ঠিকানাটি নিজের ঠিকানায় রূপান্তর করে। এই রূপান্তর ধাপটিই নিঃশব্দে নীতি ব্যর্থ করে।
প্যাকেট যখন টানেল এন্ডপয়েন্টে পৌঁছায়, তখন তা হোস্টের ঠিকানা বহন করে। কন্টেইনারের মূল ঠিকানার উপর নির্ভর করা যেকোনো নিয়ম, পলিসি রুট বা স্প্লিট-টানেল সিদ্ধান্ত মেলানো বন্ধ করে দেয়, আর ভিন্ন ভিন্ন এক্সিট দিয়ে বেরোনোর কথা থাকা দুটি কন্টেইনারকে কেবল সোর্স দিয়ে আলাদা করা যায় না। আপনার যদি প্রতি-কন্টেইনার রাউটিং দরকার হয়, তবে সিদ্ধান্তটি রূপান্তরের আগে বা আপনার নিয়ন্ত্রণাধীন নেমস্পেসের ভিতরে নিতে হবে।
Docker এই নিয়মগুলো নিজেই রক্ষণাবেক্ষণ করে, ডেমন যে ফায়ারওয়াল ব্যাকএন্ড দিয়ে কনফিগার করা হোক না কেন। ফরওয়ার্ড করা ট্রাফিকের সমর্থিত হুকের বাইরে হাতে লেখা নিয়ম, DOCKER-USER, ডেমন রিস্টার্ট বা হোস্ট আপগ্রেডের সময় পুনর্বিন্যস্ত বা বাদ পড়তে পারে। Docker-এর প্যাকেট ফিল্টারিং ডকুমেন্টেশন চেইনের ক্রম দেখায়; বাস্তব কথা হলো প্রতিটি নিয়মের একটি মালিক এবং একটি রিলোড পথ দরকার যা আপনি সত্যিই পরীক্ষা করেছেন।
দুটি সিস্টেম আলাদাভাবে পরীক্ষা করুন
একটি নেমস্পেসের প্রমাণ অন্যটি সম্পর্কে কিছুই বলে না। VPN কন্টেইনারের ভিতরে চালানো একটি অনুরোধ প্রমাণ করে টানেলটি ওই কন্টেইনারের জন্য কাজ করে। এটি হোস্ট সম্পর্কে প্রমাণ নয়, আর --network host কন্টেইনার থেকে চালানো একই কমান্ড ব্রিজ সম্পর্কে প্রমাণ নয়।
# host namespace
ip route get 1.1.1.1
ip -brief addr show
# a fresh container on the same bridge network
docker run --rm --network appnet alpine sh -c 'ip route; cat /etc/resolv.conf; ip -6 route'
তারপর পরীক্ষাটি অনুরূপ কোনো ইমেজে নয়, বরং আসল অ্যাপ্লিকেশন কন্টেইনারের ভিতরে পুনরাবৃত্তি করুন। অ্যাপে অতিরিক্ত রুট, প্রক্সি এনভায়রনমেন্ট ভেরিয়েবল বা ভিন্ন রিজলভার থাকতে পারে, আর এর প্রত্যেকটি উত্তর বদলে দেয়। প্রতিবার নাম রেজলিউশন ও দ্বিতীয় ঠিকানা পরিবার যাচাই করুন: ব্যবহারকারী-নির্ধারিত ব্রিজের কন্টেইনারগুলো Docker-এর অন্তর্নির্মিত রিজলভারের মাধ্যমে 127.0.0.11-এ রিজলভ হয়, আর ব্রিজে থাকা একটি IPv6 ডিফল্ট রুট ট্রাফিক বাইরে নিয়ে যেতে পারে যখন আপনি IPv4-কেবল টানেল পরীক্ষা করছেন।
ক্রেডেনশিয়ালে হাত দেওয়ার আগে প্যাটার্নটি পড়ুন
যখন হোস্ট কাজ করে আর কন্টেইনার করে না, কারণ প্রায় প্রতিবারই কাঠামোগত, আর কী রোটেট করা বা ক্লায়েন্ট পুনরায় ইনস্টল করা একটি বিকেল নষ্ট করে। আগে লক্ষণটি সাজান, সমাধান সাধারণত নিজের নাম বলে দেয়।
| What you see | Usual cause | First check |
|---|---|---|
| Host exits through the VPN, container shows the ISP address | The container never entered the tunnel | Default route inside the container |
| Container works until the daemon restarts, then stops | Rules outside the supported hook, or a changed backend | Daemon's reported firewall backend and DOCKER-USER |
| Container loses internal hosts after the tunnel comes up | VPN prefix overlaps the Docker bridge subnet | ip route on the host, then docker network inspect |
| Small replies arrive, large ones hang | Tunnel MTU or missing MSS clamping | Link MTU on both ends of the tunnel |
| Container falls back to the ISP address when the tunnel drops | Nothing enforces the kill switch for forwarded traffic | Stop the tunnel with a request in flight |
ওভারল্যাপ সারিটি নিজের জন্য একটি বাক্য প্রাপ্য। যে VPN প্রোফাইল 172.17.0.0/16-এর জন্য, বা এমন 10.0.0.0/8-এর জন্য রুট ঠেলে দেয় যাতে আপনার ব্রিজ প্রিফিক্স পড়ে যায়, সে টানেলকে কন্টেইনার সাবনেট দাবি করায়, আর রূপান্তরিত ঠিকানায় যাওয়া উত্তর ভুল দিকে যাবে বা হারিয়ে যাবে। Docker নেটওয়ার্ক পুনঃসংখ্যায়িত করা সাধারণত ব্যতিক্রম জমানোর চেয়ে পরিষ্কার।
কভারেজ স্পষ্ট করুন, তারপর ইচ্ছাকৃতভাবে তা ভাঙুন
দুটি ডিজাইন পর্যালোচনায় টিকে থাকে। VPN কন্টেইনারের নেমস্পেস ভাগ করুন, তাহলে প্রতিটি আওতাভুক্ত ওয়ার্কলোড একটি রিস্টার্ট সীমানাসহ একটি টানেল ব্যবহার করে, যা সহজ—যতক্ষণ না কোনো একটি সার্ভিসের ভিন্ন এক্সিট বা নিজস্ব DNS পথ দরকার হয়। অথবা কন্টেইনার নেটওয়ার্ককে হোস্টের VPN গেটওয়েতে রুট করুন: ফরওয়ার্ডিং চালু, ব্রিজ প্রিফিক্স টানেলের দিকে নির্দেশিত, ফেরত ট্রাফিক স্পষ্টভাবে পরিচালিত। এটি প্রতি-নেটওয়ার্ক নিয়ন্ত্রণ দেয় এবং ডেমন ও ক্লায়েন্ট আপগ্রেড জুড়ে রক্ষণাবেক্ষণ করার মতো একটি নিয়মসমষ্টি আপনার ঘাড়ে চাপায়।
যেভাবেই হোক, যে পরীক্ষাটি গুরুত্বপূর্ণ তা হলো ব্যর্থতার ক্ষেত্রটি। কন্টেইনারের একটি অনুরোধ উড়ন্ত অবস্থায় রেখে টানেল বন্ধ করুন এবং দেখুন প্যাকেট কোথায় যায়। যদি তা সরাসরি পথে ফিরে যায়, তবে কভারেজ কখনোই বলবৎ হয়নি, কারণ ক্লায়েন্টের kill switch ক্লায়েন্টের নিজের ট্রাফিক নিয়ন্ত্রণ করে, ব্রিজ থেকে ফরওয়ার্ড করা প্যাকেট নয়। এরপর ডেমন ও হোস্ট রিস্টার্ট করুন এবং ফলাফল দ্বিতীয়বার নিশ্চিত করুন; ঠিক তখনই হাতে লেখা নিয়মগুলো হারিয়ে যায়।
শেষ বলার আগে চারটি জিনিস নিশ্চিত করুন: টানেল ইন্টারফেস ট্রাফিকের মতো একই নেমস্পেসে আছে, কন্টেইনার পরীক্ষাটি আসল কন্টেইনারের ভিতরে চলেছে, নাম রেজলিউশন ও উভয় ঠিকানা পরিবার যাচাই করা হয়েছে, এবং টানেল-ব্যর্থতার পরীক্ষাটি এখনো বন্ধ অবস্থায় ব্যর্থ হয়। তারপর ফায়ারওয়াল ব্যাকএন্ড, ক্লায়েন্ট সংস্করণ এবং প্রতিটি নিয়মের মালিক লিখে রাখুন। এই রেকর্ডটিই পরের আপগ্রেডকে পুরোনো অনুমানের একটি অনথিভুক্ত মিশ্রণ রেখে যাওয়া থেকে বিরত রাখে।