ক্লাউড সীমান্তে VPN ক্লায়েন্টের IP সংরক্ষণ করুন বা SNAT করুন
উৎস সংরক্ষণ প্রতিটি লগে ক্লায়েন্টের পরিচয় রাখে, SNAT রাউটিং টেবিল ছোট রাখে। তিনটি শর্ত বলে অ্যাপ্লিকেশনটির কোনটি দরকার।
VPN ক্লায়েন্টের ঠিকানা অ্যাপ্লিকেশন পর্যন্ত ধরে রাখলে প্রতিটি লগ লাইন আর প্রতিটি অ্যালাউলিস্ট এন্ট্রি একই অর্থ বহন করে। ক্লাউড এজে এটি পুনর্লিখন করলে রাউটিং টেবিল সরল হয় আর লগ কম উপযোগী হয়। দুটি বেছে নেওয়ার কোনোটিই নিজে নিজে ভুল নয়, আর যে যুক্তিটি এটি নির্ধারণ করে তা খুব কমই পারফরম্যান্স নিয়ে। তিনটি শর্ত এটি ঠিক করে: অ্যাপ্লিকেশনকে জানতে হবে কোন মানুষটি সংযুক্ত হয়েছিল কি না, ক্লাউড ফ্যাব্রিক আপনি যে উৎস পাঠাতে চান তা গ্রহণ করবে কি না, এবং পরে কে রিটার্ন রুটটির দায়িত্ব নিতে রাজি।
তিনটি শর্তই এটি ঠিক করে
অ্যাপ্লিকেশনের প্রয়োজনীয়তা দিয়ে শুরু করুন, নেটওয়ার্ক ডায়াগ্রাম দিয়ে নয়। যদি অনুমোদন বা অডিট নির্দিষ্ট ক্লায়েন্ট ঠিকানার উপর নির্ভর করে, তবে তা সংরক্ষণ করা একটি কার্যকরী প্রয়োজন এবং অনুবাদ একটি রিগ্রেশন। যদি অ্যাপ্লিকেশনটির শুধু জানা দরকার যে ট্রাফিক রিমোট অ্যাক্সেস পথে এসেছে, তবে অনূদিত ঠিকানাই যথেষ্ট এবং পরিচালনার জন্য অনেক সস্তা।
দ্বিতীয় শর্তটি যান্ত্রিক। একটি ভার্চুয়াল নেটওয়ার্ক এমন প্যাকেটকে স্বয়ংক্রিয়ভাবে বিশ্বাস করে না যা প্রেরকের ইন্টারফেসে বরাদ্দ হয়নি এমন ঠিকানা দাবি করে। অধিকাংশ ক্লাউড ফ্যাব্রিক এটি বিভিন্ন উপায়ে ও বিভিন্ন নামে প্রয়োগ করে, আর যে ডিজাইন এটি উপেক্ষা করে তা ডায়াগ্রামে সঠিক দেখাবে আর প্রোডাকশনে নীরবে ড্রপ করবে।
তৃতীয়টি সাংগঠনিক। উৎস সংরক্ষণ মানে অ্যাপ্লিকেশন সাবনেটের রাউট টেবিলকে ক্লায়েন্ট প্রিফিক্সের জন্য গেটওয়ের দিকে ফিরে তাকাতে হবে, আর পরে যে দলই একটি সাবনেট যোগ করবে তাদের সেই রুটটি সামঞ্জস্যপূর্ণ রাখতে হবে। এটি একবারে ছোট খরচ, আর কয়েক ডজন অ্যাকাউন্ট জুড়ে পুনরাবৃত্ত খরচ। আচরণের প্রতিশ্রুতি দেওয়ার আগেই ঠিক করুন কে এটি বহন করবে।
রুট মানে স্পুফ করার অনুমতি নয়
একটি রিটার্ন রুট যোগ করা আপনার সাবনেটকে বলে উত্তরগুলি কোথায় যাবে। এটি ফ্যাব্রিককে বলে না যে ওই প্যাকেটগুলি ফরোয়ার্ড করা ইনস্ট্যান্সটি বিদেশি উৎস দিয়ে সেগুলি পাঠাতে অনুমোদিত। AWS-এ প্রাসঙ্গিক নিয়ন্ত্রণটি হলো সোর্স ও ডেস্টিনেশন চেকিং, আর এটি প্রতি ইনস্ট্যান্সে দেখা যায়:
aws ec2 describe-instances --instance-ids i-0a1b2c3d4e5f60718 \
--query "Reservations[].Instances[].SourceDestCheck"
aws ec2 modify-instance-attribute --instance-id i-0a1b2c3d4e5f60718 \
--no-source-dest-check
এটি শুধু সেই ইনস্ট্যান্সের জন্য বন্ধ করুন যার নথিভুক্ত কাজ ফরোয়ার্ডিং, আর অন্য কিছুর জন্য নয়। যে প্রতিটি অ্যাপ্লিকেশন VM চেক চালু রাখে সেটি এমন একটি মেশিন কম যা ধার করা উৎস দিয়ে ট্রাফিক পাঠাতে ব্যবহার করা যাবে। আপনার প্ল্যাটফর্ম AWS না হলে সমতুল্য অ্যান্টি-স্পুফিং বা অনুমোদিত-ঠিকানা সেটিং খুঁজুন, আচরণটি কেবল চলে যাবে ধরে নেওয়ার বদলে।
দ্রুত একটি প্যাকেট ক্যাপচার কনসোল পড়ার চেয়ে প্রশ্নটির নিষ্পত্তি দ্রুত করে। যদি উত্তর বেরিয়ে যায় আর ক্লায়েন্ট তা কখনও না দেখে, তবে অ্যাপ্লিকেশন ব্যর্থ হচ্ছে না, ফ্যাব্রিকই স্পুফ করা উৎসটি ফেলে দিচ্ছে।
অনুবাদ কী কিনে দেয় আর কী খরচ করায়
গেটওয়েতে উৎস পুনর্লিখন করলে রিটার্ন পাথের সমস্যা ভেঙে পড়ে। অ্যাপ্লিকেশন এমন একটি ঠিকানা দেখে যা সে ইতিমধ্যেই পৌঁছানোর উপায় জানে, আর ক্লায়েন্ট প্রিফিক্সকে কখনও ক্লাউড রাউট টেবিলে আসতে হয় না। Linux-এ নিয়মটি এক লাইন, আর আপনি যে সংকীর্ণতম সংস্করণ লিখতে পারেন তা লেখারই যোগ্য:
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s 172.20.8.0/24 -o ens5 -j SNAT --to-source 10.40.3.10
খেয়াল করুন অ্যাপ্লিকেশন এখন কী রেকর্ড করে: প্রতিটি ব্যবহারকারীর জন্য 10.40.3.10, প্রতিটি সংযোগে, চিরকাল। ওই মানের উপর গড়া যেকোনো ঠিকানা অ্যালাউলিস্ট এখন পুরো রিমোট অ্যাক্সেস জনসংখ্যার জন্য অ্যাক্সেস দেয়, আর যেকোনো ইনসিডেন্ট পর্যালোচনায় এ কে ছিল তা উত্তর দিতে গেটওয়েতে ফিরতে হবে।
সমাধান অনুবাদ ছেড়ে দেওয়া নয়, ঠিকানাটিকে পরিচয় বলে ধরে নেওয়া বন্ধ করা। ক্লায়েন্ট পরিচয়টি একটি প্রমাণীকৃত ক্ষেত্রে বহন করুন, গেটওয়েতে অনূদিত টাপলের সাথে তা লগ করুন, আর অ্যাপ্লিকেশনকে তার উপর জয়েন করতে দিন। জয়েন কী ছাড়া অনুবাদ একটি নেটওয়ার্ক সমস্যাকে চিরস্থায়ী ফরেনসিক সমস্যায় বদলে দেয়।
রিলে হলো ভিন্ন একটি ইন্টারফেস
অ্যাপ্লিকেশনের সামনে একটি রিভার্স প্রক্সি রাউটেড-পাথ প্রশ্নটি সম্পূর্ণ এড়িয়ে যায়। প্রক্সি তার নিজের ব্যাকএন্ড সংযোগ খোলে, তাই ক্লায়েন্ট প্রিফিক্সকে ভার্চুয়াল নেটওয়ার্কের ভিতরে কখনও রাউটেবল হতে হয় না, আর অ্যাপ্লিকেশন প্রক্সি যে হেডার সেট করে তাতে পরিচয় পেতে পারে।
সেই হেডার কেবল তখনই বিশ্বাসযোগ্য যখন ব্যাকএন্ড তা প্রক্সির কাছ থেকে গ্রহণ করে এবং অন্য কিছুর কাছ থেকে নয়। nginx-এর ভাষায় এর মানে হলো বিশ্বস্ত পিয়ারকে স্পষ্টভাবে নাম দেওয়া, যা-ই আসুক তা বিশ্বাস করার বদলে:
set_real_ip_from 10.40.3.10;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
যে কোনও ক্লায়েন্ট সরাসরি ব্যাকএন্ডে পৌঁছাতে পারে সে একই হেডার জাল করতে পারে, তাই প্রক্সি ছাড়া ব্যাকএন্ডে পৌঁছানো যাবে না। এটি ফায়ারওয়ালের সত্য, কনফিগারেশনের মত নয়, আর স্নিপেট কপি করার সময় মানুষ ঠিক এই অনুমানটিই এড়িয়ে যায়।
রিলে আপনি কী কিনছেন তাও বদলে দেয়। আপনি অ্যাপ্লিকেশন-স্তরের পরিচয় আর তা লগ করার স্বাভাবিক জায়গা পান; আপনি সাধারণত্ব হারান, কারণ প্রতিটি নতুন প্রোটোকলের নিজস্ব প্রক্সি সমর্থন দরকার। HTTP সেবার জন্য এই বিনিময় সাধারণত ভালো, আর যা HTTP নয় তার জন্য সাধারণত তা আদৌ পাওয়া যায় না।
প্রতিটি সীমান্ত কী দেখে তা লিখে রাখুন
আপনি যা-ই বেছে নিন, ডিজাইন পর্যালোচনা শেষ হওয়া উচিত একটি টেবিলে যা প্রতিটি হপে উৎস ঠিকানা আর প্রমাণযোগ্য পরিচয়ের নাম দেয়। তা ছাড়া প্রথম ইনসিডেন্টেই তিনটি দল উঠে আসে, যারা প্রত্যেকে ভিন্ন একটি ক্লায়েন্টের বর্ণনা দেয়।
| Boundary | Source the next hop sees | What is actually proven |
|---|---|---|
| Client to gateway | 172.20.8.14 | A certificate or credential was presented |
| Gateway to app subnet, preserved | 172.20.8.14 | The same session, if the return route exists |
| Gateway to app subnet, translated | 10.40.3.10 | Only that traffic came through the gateway |
| Proxy to backend | 10.40.3.10 plus a header | The proxy asserted an identity it authenticated |
তারপর বেছে নিন। উৎস সংরক্ষণ করুন যখন অ্যাপ্লিকেশনের অনুমোদন সত্যিই ক্লায়েন্ট ঠিকানার উপর নির্ভর করে এবং আপনি রুটটির দায়িত্ব নিতে পারেন। অনুবাদ করুন যখন তা নয় এবং আপনি পরিচয় ব্যান্ডের বাইরে বহন করতে পারেন, এবং প্ল্যাটফর্ম-নির্দিষ্ট ফরোয়ার্ডিং সেটিংসের জন্য AWS ফরোয়ার্ডিং-ইনস্ট্যান্স নির্দেশিকা ব্যবহার করুন। রিলের কাছে যান যখন সেবাটি HTTP-তে কথা বলে এবং আপনি চান পরিচয় আর ঠিকানা না-ই থাকুক।