আপনার VPN-এর উপর SOCKS প্রক্সি হিসেবে SSH গতিশীল ফরওয়ার্ডিং
যে অ্যাপ্লিকেশন শুধু SOCKS বোঝে, সাধারণ VPN-এ তার কোনো প্রক্সি এন্ডপয়েন্ট নেই। দুটি হপ, একটি লুপব্যাক লিসেনার, এবং একটি নাম খোঁজা যা SSH সার্ভারকেই করতে হয়।
যে অ্যাপ্লিকেশন শুধু SOCKS বোঝে, সাধারণ VPN-এ তার কথা বলার মতো কিছু নেই, কারণ টানেল প্যাকেট বহন করে আর অ্যাপটি চায় একটি প্রক্সি এন্ডপয়েন্ট। OpenSSH সেই এন্ডপয়েন্ট দিতে পারে যখন অ্যাক্সেসের মালিক অনুমতি দেন, কারণ গতিশীল ফরওয়ার্ডিং একটি SSH সেশনকে স্থানীয় প্রক্সিতে পরিণত করে। তারপর দুটি হপ সোজা রাখতে হয়: যে টানেল SSH হোস্টে পৌঁছায়, আর সেই হোস্ট যে সংযোগ এরপর খোলে। এদের আলাদা করলে বোঝা যায় এই ব্যবস্থা কেন কাজ করে এবং যা এটি কখনোই করবে না।
SSH লিসেনার যা হয় আর যা হয় না
গতিশীল ফরওয়ার্ডিং SSH ক্লায়েন্টকে স্থানীয়ভাবে শুনতে এবং যা কিছু সংযোগ করে তার সঙ্গে SOCKS4 বা SOCKS5 বলতে বাধ্য করে। প্রতিটি অনুরোধ একটি গন্তব্য বলে দেয় এবং SSH সার্ভার পরবর্তী সংযোগটি খোলে, তাই গন্তব্যের খোঁজ দূরের প্রান্তে হতে পারে। এটি অ্যাপ্লিকেশন স্তরের TCP ফরওয়ার্ডিং, পুরো ডিভাইসের VPN নয়। এটি কোনো UDP অ্যাসোসিয়েশন, কোনো ICMP, এবং প্রক্সি সেটিংস সম্পূর্ণ উপেক্ষা করা অ্যাপ্লিকেশনের জন্য কিছুই বহন করে না। SSH সার্ভার থেকে অ্যাপ্লিকেশন পর্যন্ত হপটিও আপনার টানেলের ভিতরে নয়, যা তখন গুরুত্বপূর্ণ যখন গন্তব্য শুধু পরিচিত নেটওয়ার্ক থেকে ট্রাফিক গ্রহণ করে।
পূর্বশর্তগুলো বাস্তব: SSH হোস্টে একটি রুট, একটি অনুমোদিত অ্যাকাউন্ট, একটি যাচাই করা সার্ভার হোস্ট কী, এবং ফরওয়ার্ড করার অনুমতি। এর কোনোটিই প্রক্সি তৈরি করে না, আর শেষটি সাধারণত প্রথমেই অনুপস্থিত থাকে। অন্য কিছু ডিবাগ করার আগে চারটিই নিশ্চিত করুন, কারণ কোনটি অনুপস্থিত থাকলে ক্লায়েন্টের দিক থেকে ব্যর্থতা একই রকম দেখায়।
একটি স্পষ্ট পোর্ট দিয়ে এটিকে লুপব্যাকে চালু করুন
একটি অব্যবহৃত স্থানীয় পোর্ট বেছে নিন এবং ঠিকানাটি বাদ না দিয়ে এটিকে স্পষ্টভাবে লুপব্যাকে বাঁধুন। নিচের তিনটি অপশন প্রত্যেকটি একটি কারণে আছে।
ssh -D 127.0.0.1:1080 -NT -o ControlPath=none -o ExitOnForwardFailure=yes \
[email protected]
-N দূরের কমান্ড বাদ দেয় এবং -T সিউডো-টার্মিনাল বাদ দেয়, তাই সেশনটি কেবল ফরওয়ার্ডিংয়ের জন্য থাকে। ExitOnForwardFailure লিসেনার তৈরি না হলে ক্লায়েন্টকে বেরিয়ে যেতে দেয়, আপনি যে ফরওয়ার্ডিং চেয়েছেন তা ছাড়া চলার বদলে। ControlPath=none সেশনটিকে একটি বিদ্যমান মাল্টিপ্লেক্সড সংযোগের বাইরে রাখে যা নিজের ফরওয়ার্ডিং যোগ করতে পারে। লুপব্যাক লিসেনারকে LAN থেকে দূরে রাখে, কিন্তু ভাগ করা মেশিনে এটি কোনো অনুমোদনের সীমা নয়, কারণ অন্য স্থানীয় প্রসেসও এতে পৌঁছাতে পারে। OpenSSH ক্লায়েন্ট রেফারেন্স এই সব ফ্ল্যাগ নথিভুক্ত করে, আর লুপব্যাক সতর্কতা শোনা সকেট কী তা থেকেই আসে।
নামগুলি প্রক্সির মধ্য দিয়ে পাঠান, এর পাশ দিয়ে নয়
একটি SOCKS5 ক্লায়েন্ট গন্তব্য নিজেই সমাধান করতে পারে বা প্রক্সিকে তা করতে বলতে পারে, আর এই পছন্দই ঠিক করে কোন রিজলভার উত্তর দেবে। socks5h দিয়ে curl হোস্টনামটি প্রক্সির মধ্য দিয়ে পাঠায়, তাই খোঁজটি SSH সার্ভারে হয়। সাধারণ socks5 দিয়ে ল্যাপটপ আগে সমাধান করে এবং কেবল সংযোগটি যায়, যা নামটি অভ্যন্তরীণ হলে উদ্দেশ্যটি চুপচাপ ব্যর্থ করে। নিচের অনুরোধটি নো-প্রক্সি তালিকাও পরিষ্কার করে, তাই উত্তরাধিকারসূত্রে পাওয়া NO_PROXY মান এটিকে প্রক্সির পাশ দিয়ে নিতে পারে না।
curl -sS --noproxy '' --proxy socks5h://127.0.0.1:1080 https://app.corp.example/health
সার্টিফিকেট যাচাই এবং অ্যাপ্লিকেশনের নিজের লগইন এখনো প্রযোজ্য, কারণ প্রক্সি কোনোটিই প্রতিস্থাপন করে না। দুটি খোঁজ বাকি থাকে: ল্যাপটপকে অনুমোদিত VPN ও DNS পথ দিয়ে SSH হোস্টে পৌঁছাতে হবে, আর SSH সার্ভারকে অ্যাপ্লিকেশনের নাম নিজেই সমাধান করতে হবে। দ্বিতীয়টি কোনো ট্রাফিক প্রক্সির মধ্য দিয়ে যাওয়ার আগে আলাদাভাবে পরীক্ষা করা যায়।
ssh [email protected] getent hosts app.corp.example
একটি অনুমোদিত গন্তব্য প্রমাণ করুন, তারপর সেশনটি বন্ধ করুন
নীতিটি যে গন্তব্য অনুমোদন করে এবং যেটি প্রত্যাখ্যান করা উচিত উভয়ই পরীক্ষা করুন, কারণ কাজ করা ফরওয়ার্ড কেবল প্রমাণ করে যে লিসেনার কাজ করে, এর বেশি কিছু নয়। অ্যাপ্লিকেশনটি SSH সার্ভার যে সোর্স ঠিকানা বেছে নেয় তা দেখে, যা আপনার ল্যাপটপের টানেল ঠিকানা নয়। যেখানে দূরের প্রান্ত সোর্স অনুযায়ী সংযোগ লগ করে, সেখানে কোনো অনুরোধ প্রত্যাখ্যাত হলে ওই পার্থক্যই প্রথমে দেখার বিষয়।
সেশনটি এর মালিক প্রসেসের মাধ্যমে বন্ধ করুন, কোনো সম্পর্কহীন শেল মেরে নয়। তারপর নিশ্চিত করুন লিসেনারটি নেই, কারণ যে পোর্ট এখনো উত্তর দেয় সেটি এমন সেশন যা আপনি সত্যিই বন্ধ করেননি। কেবল এই অনুশীলনটি যে প্রক্সি সেটিং যোগ করেছে তা সরান, এবং অ্যাপ্লিকেশন কনফিগারেশনের বাকিটা অপরিবর্তিত রাখুন। ফরওয়ার্ডিং নিয়ম ধরে রাখা একটি অপরিবীক্ষিত টার্মিনাল কোনো সার্ভিস নয়, এবং স্থায়ী প্রক্সির প্রয়োজন অনুমোদিত জীবনচক্র, ভুলে যাওয়া একটি উইন্ডো নয়।
ss -ltn | grep 1080
যে ব্যর্থতাগুলো এই ব্যবস্থা সারাতে পারে না
কিছু উপসর্গ সরাসরি উপরের সীমাগুলোর দিকে ইশারা করে, আর সেগুলো আগে চিনলে প্রক্সি ডিবাগিংয়ের একটি দুপুর বেঁচে যায়। সারণিটি আপনি যা দেখেন তার সঙ্গে এর সাধারণ অর্থের মিল দেখায়। শেষ কলামের যেকোনো কিছু কনফিগারেশন ভুল নয়, বরং নকশার প্রশ্ন।
| What you see | What it usually means | Where to look |
|---|---|---|
| The app connects and nothing follows | It ignores proxy settings entirely | Its own network settings, not the SSH session |
| A name resolution error for the destination | The SSH server cannot resolve it | Server resolver and search domains |
| A UDP-only application fails | Dynamic forwarding carries TCP only | This arrangement cannot serve it |
| curl works, the browser does not | The browser is not using the socks5h endpoint | Browser proxy configuration |
| The listener answers after the session ended | Another process owns port 1080 | The ss output, then the owning process |
প্রথম তিনটি সারি সেইগুলো যা মানুষ ভুল রোগনির্ণয় করে, কারণ প্রত্যেকটি প্রক্সি সম্পর্কে ত্রুটি নয় বরং একটি সংযোগের চেষ্টা তৈরি করে। ল্যাপটপে যে নাম সমাধান হয় তা সার্ভারের রিজলভার সম্পর্কে কিছুই বলে না, আর ব্যর্থতাটি বদলে সার্টিফিকেট বা টাইমআউট সমস্যা হিসেবে পড়া হয়। শুধু UDP-ভিত্তিক অ্যাপ্লিকেশনগুলো নকশার ভিতরে নষ্ট নয়, বরং এর বাইরে থাকে, এবং কোনো অতিরিক্ত ssh অপশন তা বদলায় না। ব্রাউজার সারিটি হলো সেই সাধারণ মনে করানো যে প্রক্সি সেটিংস প্রতিটি অ্যাপ্লিকেশনের জন্য আলাদা। শেষ সারিটিই বন্ধ করার পরীক্ষা কেন আছে তার কারণ: যে পোর্ট এখনো শোনে তার মানে এখন অন্য কিছু এর মালিক।