অ্যান্ড্রয়েড এমুলেটর ও হোস্ট VPN: DNS স্ন্যাপশট এবং NAT ব্যাখ্যা
গেস্ট এমুলেটরের NAT-এর পেছনে থাকে এবং বুটের সময় কপি করা DNS তালিকা ধরে রাখে। বুটের আগে টানেল চালু করুন, তারপর গেস্টের ভেতর থেকে রেজোলিউশন পরীক্ষা করুন।
এমুলেটর যখন এমন একটি বিল্ড সার্ভারে পৌঁছাতে পারে না যা হোস্টের ব্রাউজার অনায়াসে খোলে, তখন সহায়ক প্রশ্নটি VPN কাজ করছে কি না তা নয়। প্রশ্নটি হলো গেস্টের কাছে দুটি প্রক্রিয়ার কোনটি অনুপস্থিত। ভার্চুয়াল ডিভাইসটি এমুলেটরের NAT-এর পেছনে নিজের নেটওয়ার্ক স্ট্যাক চালায়, এবং এর রিজলভার তালিকাটি বুটের সময় নেওয়া একটি কপি, তাই পরে ওঠা একটি টানেল হোস্টের পথ বদলায় কিন্তু গেস্ট যা জিজ্ঞাসা করে তা বদলায় না। এই দুটি স্তর বুঝলে এই সমস্যার প্রায় প্রতিটি রূপ ব্যাখ্যা হয়।
গেস্ট হলো স্থির NAT-এর পেছনে একটি আলাদা স্ট্যাক
QEMU-র ব্যবহারকারী মোড নেটওয়ার্কিং গেস্টকে 10.0.2.15-এ রাখে, গেটওয়ে 10.0.2.2-এ, এবং DNS সেবা 10.0.2.3 থেকে 10.0.2.6-এ। গেস্টের বহির্গামী ট্র্যাফিক হোস্ট কার্নেল ফরওয়ার্ড করে না; এটি হোস্টের দিকের সকেটে রূপান্তরিত হয়, প্রতিটি গেস্ট সংযোগের জন্য একটি, এবং সেই সকেটগুলো হোস্টের ঠিকানা স্থান থেকে বের হয়। তাই গেস্ট সংযোগ তৈরি হওয়ার মুহূর্তেই হোস্টের রাউটিং সিদ্ধান্ত উত্তরাধিকার করে, এবং তাই আপনার টানেলের নাম উল্লেখ করা কোনো রাউট টেবিল এন্ট্রি গেস্টের নেই।
একই প্রক্রিয়া গেস্টকে একটি কাজের বহির্গমনের পথ দেয়। 10.0.2.2 হলো হোস্টের লুপব্যাক ইন্টারফেসের একটি উপনাম, তাই ল্যাপটপে 127.0.0.1-এ শোনা একটি সেবা গেস্ট থেকে সেই ঠিকানায় পৌঁছানো যায়। ক্লায়েন্ট শুধু লুপব্যাকে যা প্রকাশ করে তা এইভাবে পৌঁছানো যায়, এবং এটিই নিচে বর্ণিত প্রক্সি ব্যবস্থার ভিত্তি।
গেস্ট যা করতে পারে না তা হলো হোস্ট নেটওয়ার্ককে যেন তার উপর একটি নেমস্পেস, এমনভাবে পর্যবেক্ষণ করা। কোনো ব্রিজ নেই, ভাগ করা রাউট টেবিল নেই এবং উত্তরাধিকারসূত্রে পাওয়া রিজলভার নেই, শুধু তার প্যাকেট গ্রহণকারী NAT সেবা এবং ভার্চুয়াল ডিভাইস চালু হওয়ার সময় লঞ্চার যে স্ন্যাপশট নিয়েছিল তা আছে।
DNS একটি স্ন্যাপশট, জীবন্ত দৃশ্য নয়
শুরুর সময় এমুলেটর হোস্টের রিজলভার তালিকা পড়ে এবং গেস্টকে চারটি পর্যন্ত সার্ভার দেয়, যা 10.0.2.3 থেকে 10.0.2.6 ঠিকানায় প্রকাশ পায়। সেই মুহূর্তে টানেল বন্ধ থাকলে স্ন্যাপশটে ল্যাপটপ যে পাবলিক রিজলভার ব্যবহার করেছিল তা থাকে, এবং গেস্ট সারা জীবন সেটাই জিজ্ঞাসা করে। পাবলিক নাম সমাধান হয়, অভ্যন্তরীণ নাম ব্যর্থ হয়, এবং প্রতিটি উপসর্গ VPN-এর দিকে ইশারা করে অথচ আসল পুরনো মানটি হলো টানেল ওঠার কয়েক মিনিট আগে ধরা রিজলভার তালিকা।
তাই ক্রম দিয়ে সমাধান করা কুসংস্কার নয়। আগে টানেল সংযোগ করুন, তারপর এমুলেটর পুনরায় চালু করুন, এবং স্ন্যাপশট পুনরুদ্ধারের চেয়ে কোল্ড বুট পছন্দ করুন, কারণ দ্রুত-বুট ইমেজ আগে সংরক্ষিত রিজলভার ও রাউট অবস্থা নিয়ে ফিরে আসতে পারে। গেস্ট এখন কী ব্যবহার করছে দেখতে চাইলে হোস্টকে নয়, ডিভাইসকে জিজ্ঞাসা করুন:
adb shell dumpsys connectivity | grep -i -A2 dns
adb shell ping -c 1 build.internal.exampleএমুলেটর চালুর সময় একটি স্পষ্ট রিজলভারও গ্রহণ করে, যা তখন কাজে লাগে যখন আপনি জানেন গেস্টের কোন সার্ভার ব্যবহার করা উচিত, এবং তখন বিপজ্জনক যখন সেই সার্ভারটি পাবলিক:
emulator -avd Pixel_API_34 -dns-server 203.0.113.53পাবলিক রিজলভারের অভ্যন্তরীণ জোনের কোনো কপি থাকে না, তাই একটি পিন করা ক্রমের সমস্যাকে স্থায়ী ব্যর্থতায় পরিণত করে। প্রোফাইল ব্যক্তিগত DNS চাপালে টানেলকে তা সরবরাহ করতে দিন এবং ঠিকানা হার্ডকোড না করে গেস্টকে কোল্ড বুট করুন।
সংযোগের সময় রাউটিং হোস্টকে অনুসরণ করে
যেহেতু গেস্ট সংযোগ হোস্ট সকেটে পরিণত হয়, রাউটিং সিদ্ধান্ত সকেট তৈরির সময় নেওয়া হয়। অনুরোধের আগে টানেল উঠলে অনুরোধটি প্রোফাইল রাউট অনুযায়ী টানেল দিয়ে বের হয়। শুধু নির্বাচিত প্রিফিক্স বহনকারী স্প্লিট-টানেল প্রোফাইল আপনার ব্যক্তিগত সাবনেটকে বাইরে রেখে দেবে, তাই হোস্টের নাগাল গেস্ট সম্পর্কে একটি অনুমান, ফলাফল নয়। বিদ্যমান গেস্ট সংযোগ যে পথে তৈরি হয়েছিল তা ধরে রাখে, তাই পুনরায় সংযোগ করা ক্লায়েন্ট এমুলেটরের ভেতরে আটকে যাওয়া ডাউনলোড সবসময় ঠিক করে না।
যাচাই হোস্টের ইন্টারফেসে, গেস্টের পরিসংখ্যানে নয়:
sudo tcpdump -ni tun0 'host 203.0.113.10'গেস্টের অনুরোধ টানেল ইন্টারফেসে দেখা গেলে রাউটিং কাজ করছে এবং সমস্যা তার উপরে। ভৌত ইন্টারফেসে দেখা গেলে প্রোফাইল সেই প্রিফিক্স ঢাকে না, এবং গেস্টের দিকে যতই পুনর্বিন্যাস করুন তা বদলাবে না।
যখন ক্লায়েন্ট শুধু লুপব্যাক প্রক্সি দেয়
কিছু বাণিজ্যিক ক্লায়েন্ট কোনো সিস্টেম টানেলই তৈরি করে না। তারা 127.0.0.1-এ একটি HTTP বা SOCKS শ্রোতা প্রকাশ করে এবং অ্যাপ্লিকেশন তা ব্যবহার করবে আশা করে। গেস্ট সেই সকেট সরাসরি দেখতে পারে না, কিন্তু এমুলেটরকে তা ব্যবহার করতে বলা যায়, হয় বর্ধিত নিয়ন্ত্রণের মাধ্যমে (সেটিংস, তারপর প্রক্সি, ম্যানুয়াল মোড, হোস্ট 127.0.0.1 এবং ক্লায়েন্ট যে পোর্ট ছাপে), নয়তো চালুর সময়:
emulator -avd Pixel_API_34 -http-proxy http://127.0.0.1:8080ক্লায়েন্ট উইন্ডো থেকে পোর্টটি কপি করুন; অনুমান করা পোর্ট নিঃশব্দে ব্যর্থ হয় এবং ভাঙা টানেলের মতো দেখায়। এটি কী ঢাকে মনে রাখুন: HTTP প্রক্সি সেটিং প্রক্সি-সচেতন অ্যাপ্লিকেশন মানে, আর কাঁচা সকেট তা সম্পূর্ণ উপেক্ষা করে। যদি কাজটি নিজের সংযোগ খোলা একটি নেটিভ বাইনারি হয়, প্রক্সি পথ টানেলের সমতুল্য নয় এবং তুলনাটি স্পষ্টভাবে করতে হবে।
ফলাফল গেস্টের ভেতর থেকে প্রমাণ করুন
একই সেশনে দুটি পরীক্ষা দিয়ে সমাধান ও রাউটিং আলাদা করুন। যে নাম ব্যর্থ হয় অথচ সংখ্যাগত ঠিকানা উত্তর দেয় তা DNS স্ন্যাপশটের সমস্যা, এবং সমাধান হলো ক্রম বা স্পষ্ট রিজলভার। দুটোই ব্যর্থ হলে তা রাউটিং বা নীতির দিকে ইশারা করে, এবং পরের পরীক্ষা হলো অ্যাপটি নিজের নেটওয়ার্ক নিষেধাজ্ঞাসহ কাজের প্রোফাইলে চলছে কি না।
শেষে, আপনি কোন গেস্টে পরীক্ষা করছেন তা জানুন। খুব পুরনো এমুলেটর ইমেজে গেস্টের দিকের VPN ক্লায়েন্টের প্রয়োজনীয় tun সমর্থন ছিল না, তাই সেখানে কোনো প্রোফাইলই কাজ করতে পারত না; বর্তমান ইমেজে তা আছে। বর্তমান ইমেজে ব্যর্থ ক্লায়েন্ট হলো ক্লায়েন্ট বা প্রোফাইলের সমস্যা, এবং হোস্টের টানেল পুনর্নির্মাণ করলে ফলাফল বদলাবে না।