VPN psql আটকাচ্ছে না: আপনার ক্লায়েন্ট অন্য জায়গায় ডায়াল করছে
psql ও একটি GUI ক্লায়েন্ট একই মেশিন থেকে ভিন্ন এন্ডপয়েন্টে ডায়াল করতে পারে। VPN-কে দোষ দেওয়ার আগে হোস্ট, সকেট, ভূমিকা ও TLS মিলিয়ে দেখুন।
দুটি ক্লায়েন্টই একই ল্যাপটপে বসে আছে, একই টানেল পার হয়, আর তাদের মধ্যে কেবল একটি সংযোগ করে। এই তুলনাটি মনে হয় প্রমাণ যে VPN বাছাইপর্ব করে, অথচ অনেক বেশি সাধারণ ব্যাখ্যা হলো দুটি ক্লায়েন্ট ভিন্ন ভিন্ন ঠিকানায় ডায়াল করে। একটি GUI নিজের হোস্ট, পোর্ট, ভূমিকা ও TLS সেটিংস রাখে এবং দরকার হলে চুপচাপ একটি SSH ফরওয়ার্ড গড়ে, আর psql আপনার শেল হয়তো আগেই সেট করা libpq ডিফল্ট থেকে সংযোগ জোড়া দেয়। কাজ করা সংযোগটি পুনরুৎপাদন করা GUI-এর সেটিংস পড়ার বিষয়, টানেল পুনঃস্থাপনের নয়।
মিথ: একটি কাজ করা ক্লায়েন্টই পথ প্রমাণ করে
GUI সংযোগ করলে টানেল ট্রাফিক বহন করে, আর GUI কেবল সেটাই প্রমাণ করে। এটি বলে না psql কোন ঠিকানা রিজলভ করে, কোন ভূমিকায় প্রমাণীকরণ করে, বা এটি যে সকেট খোলে তা কখনো মেশিন ছাড়ে কি না। পথ ভাগ করা; প্যারামিটার নয়।
স্থানীয় ফরওয়ার্ড ফাঁকটা আরও বাড়ায়। GUI হয়তো SSH দিয়ে ফরওয়ার্ড করা একটি পোর্টে 127.0.0.1-এ সংযোগ করে, আর সেই শ্রবণকারী কেবল GUI সেশনের সময়কালেই থাকে। ফরওয়ার্ড ছাড়া localhost-এ নির্দেশিত psql একটি প্রত্যাখ্যাত সংযোগ পায়, যার VPN-এর সঙ্গে কোনো সম্পর্ক নেই।
GUI আসলে যে এন্ডপয়েন্ট ব্যবহার করে তা পড়ুন
সংযোগের বৈশিষ্ট্য খুলে চারটি মান কপি করুন: হোস্ট, পোর্ট, ডেটাবেস ও ভূমিকা। তারপর টানেল ট্যাব খুঁজুন, কারণ SSH ফরওয়ার্ড একটি ব্যক্তিগত ঠিকানাকে স্থানীয় পোর্টে বদলে দেয় এবং psql-কে যা বলতে হবে তা বদলে দেয়।
| Setting | What the GUI holds | What psql uses when the value is absent |
|---|---|---|
| Destination | A saved hostname, sometimes behind a forward | A local Unix socket, not the remote endpoint |
| Port | The direct port or a forwarded local port | 5432, or the port from a service file |
| Role and database | Stored per connection profile | Your operating-system user name |
| TLS identity | Its own CA bundle and verification mode | Whatever PGSSLMODE or the service file says |
| Startup files | Not read at all | Read unless -X is passed |
প্রতিটি সারি ভিন্ন স্তরে ব্যর্থ হয়, আর আপনি যে বার্তা পান তা সেই স্তরের নাম বলে। সংরক্ষিত প্রোফাইলের বন্ধুত্বপূর্ণ নাম psql-এ পেস্ট করলে উপরের কোনো মানই বহন করে না, আর একটি সেবা-নাম এমন ফাইলের মাধ্যমে রিজলভ হয় যা টার্মিনাল কখনো পড়তে নাও পারে।
libpq আপনার শেল থেকে কী উত্তরাধিকার পায়
psql হলো libpq-এর ওপর একটি পাতলা ক্লায়েন্ট, আর libpq অন্য কিছুর আগে এনভায়রনমেন্ট পড়ে। PGHOST, PGHOSTADDR, PGPORT, PGDATABASE, PGUSER, PGSERVICE ও PGSSLMODE-এর মতো ভেরিয়েবল প্রত্যেকে সংযোগের একটি অংশ পুনঃনির্দেশ করতে পারে। এগুলো টাইপ করা হয় না, উত্তরাধিকার পাওয়া হয়, তাই আপনি যে কমান্ড চালিয়েছেন তাতে এগুলোর কোনোটিই দেখা যায় না। এক্সপোর্ট করা PGSSLMODE-ও কমান্ড লাইনে একটি শব্দ ছাড়াই ক্লায়েন্ট কী গ্রহণ করে তা বদলাতে পারে।
এই ভেরিয়েবলগুলোর দুটি প্রথমেই সন্দেহের যোগ্য। PGHOSTADDR একটি সংখ্যাসূচক গন্তব্য দেয় যা নাম রিজলভিংকে অগ্রাহ্য করে, অথচ হোস্টনাম তখনো সার্টিফিকেট পরিচয় নিয়ন্ত্রণ করে, আর PGSERVICE একটি সেবা ফাইল থেকে হোস্ট, ডেটাবেস ও TLS পছন্দ টেনে নেয়। এটি ডিবাগ করতে গিয়ে পুরো এনভায়রনমেন্ট ডাম্প করা খারাপ অভ্যাস, কারণ এতে পাসওয়ার্ড ও অসম্পর্কিত টোকেন থাকতে পারে; বদলে যে ভেরিয়েবলগুলো আপনার দরকার সেগুলো বেছে নিন।
host ও hostaddr দুটোই বাদ দিলে নেটওয়ার্ক ঠিকানার বদলে একটি Unix-ডোমেইন সকেট বাছা হয়। তাই -h ছাড়া psql চালালে তা স্থানীয়ভাবে সফল হতে পারে, বা সকেট ত্রুটিতে ব্যর্থ হতে পারে, GUI যে রুট ব্যবহার করে তা কখনো স্পর্শ না করেই।
একই প্যারামিটারগুলো নিজ হাতে পাঠান
GUI-এর মানগুলো হাতে নিয়ে সেগুলো স্পষ্টভাবে পাঠান এবং স্টার্টআপ ফাইল বাদ দিন যা ওভাররাইড যোগ করতে পারে। নিচের সংযোগ স্ট্রিংটি উদাহরণমাত্র: এন্ডপয়েন্ট, পোর্ট, ডেটাবেস ও ভূমিকা আপনার প্রশাসক যে মান অনুমোদন করেছেন তা দিয়ে বদলান, আর যে ট্রাস্ট কনফিগারেশন আগেই কাজ করছে তা রেখে দিন।
psql -X "host=db.internal.example port=6432 dbname=orders user=report_ro sslmode=verify-full connect_timeout=5"সেই কমান্ডে তিনটি বিবরণ ইচ্ছাকৃত। -X psql-এর স্টার্টআপ ফাইল দমন করে, যদিও libpq-এর এনভায়রনমেন্ট বা সেবা-সংজ্ঞা দমন করে না। connect_timeout=5 একটি ফাঁকা রুটকে কয়েক মিনিটের জন্য টার্মিনাল আটকে রাখা থেকে বিরত রাখে। sslmode=verify-full সার্টিফিকেট ও হোস্টনাম যাচাই চালু রাখে, আর TLS ত্রুটি দেখা দিলে মানুষ ঠিক এই অংশটাই বন্ধ করে।
অনুমোদিত এন্ডপয়েন্ট কোনো পুলারের পিছনে থাকলে পোর্ট 6432 ও পোর্ট 5432 ভিন্ন সার্ভার পরিচয়ে একই ডেটায় পৌঁছাতে পারে, আর যাচাই ডেটাবেসের নামে নয়, পুলারের নামে ব্যর্থ হতে পারে। মোড দুর্বল করার বদলে সংযোগ স্ট্রিংয়ে নামটি ঠিক করুন।
পরবর্তী ধাপ বেছে নিক ত্রুটি বার্তা
ব্যর্থতার লেখা বলে চেষ্টাটি কতদূর গেছে, আর তা টানেল নিয়ে যেকোনো অনুমানের চেয়ে ভালো। যে নাম রিজলভ হয় না তা সকেট তৈরির আগেই ব্যর্থ হয়, টাইমআউট মানে রুট বা ফায়ারওয়াল প্যাকেট ফেলেছে, প্রত্যাখ্যান মানে কিছু উত্তর দিয়ে না করেছে, আর প্রমাণীকরণ ত্রুটি মানে নেটওয়ার্ক আগেই কাজ করছিল।
psql -X -w "host=db.internal.example port=6432 dbname=orders user=report_ro sslmode=verify-full connect_timeout=5" -c '\conninfo'
env | grep -E '^PG'
psql --version\conninfo-এর আউটপুট GUI-এর জীবন্ত সেশনের সঙ্গে মেলান: একই হোস্ট, একই পোর্ট, একই ভূমিকা, একই TLS অবস্থা। এই চারটি মিলে গেলে VPN-এর আর ব্যাখ্যা করার কিছু থাকে না। যতক্ষণ না মেলে, ততক্ষণ প্রতিটি অতিরিক্ত টানেল পরিবর্তন এমন একটি সংযোগ নিয়ে অনুমান যা টার্মিনাল কখনোই করেনি।