সরাসরি পর্বে যান
পর্ব ১৯ · ৬২-এর মধ্যে · মডিউল ৩

NAT আর private ঠিকানা — এক public IP-তে পুরো অফিস

NAT and Private Addresses — RFC 1918, PAT/Masquerade, Port Forwarding, NAT Traversal (STUN, TURN, ICE) & Carrier-Grade NAT

Taught in Bangla, this lesson explains how NAT lets a whole office share one public IP: RFC 1918 private ranges, the translation table on the way out and back, static NAT, dynamic NAT and PAT, incremental checksum adjustment, port forwarding, timeouts and hairpinning, NAT traversal for video calls with STUN, TURN and ICE, carrier-grade NAT, and why NAT is not a firewall and breaks end-to-end design.

এই পর্বে যা শিখবেন

  • IPv4-এর ঘাটতি, RFC 1918-এর private ঠিকানা আর কেন এগুলো ইন্টারনেটে route হয় না
  • NAT router packet-এর কোন ঘর বদলায়, translation table কীভাবে চলে, আর checksum কীভাবে দ্রুত হালনাগাদ হয়
  • Static NAT, dynamic NAT, PAT, port forwarding আর hairpinning — Linux-এর nftables/iptables উদাহরণসহ
  • NAT-এর ধরন (full cone থেকে symmetric), STUN, TURN, ICE আর UDP hole punching — কখন সরাসরি সংযোগ হয়, কখন relay
  • CGNAT-এর প্রভাব, NAT আর firewall-এর পার্থক্য, protocol ভাঙা, end-to-end নীতি আর IPv6

১ · ঠিকানা ফুরিয়ে গেল — তবু সবার ইন্টারনেট চলছে কীভাবে

আপনার বাসার Wi-Fi-তে হয়তো ছয়-সাতটি যন্ত্র যুক্ত — দুটি ফোন, একটি ল্যাপটপ, একটি স্মার্ট টিভি, হয়তো একটি CCTV ক্যামেরা। প্রতিটি যন্ত্রের একটি IP ঠিকানা আছে, যেমন 192.168.0.101. এবার পাশের বাসার কাউকে জিজ্ঞেস করুন — খুব সম্ভব তাঁর ল্যাপটপের ঠিকানাও 192.168.0.101. লাখ লাখ বাসায় একই ঠিকানা! তাহলে উত্তর কার কাছে যাবে? এই ধাঁধার উত্তরই এই পর্ব: NAT (Network Address Translation).

সমস্যাটা হিসাবে: ৩২ bit যথেষ্ট নয়

IPv4 ঠিকানা ৩২ bit-এর, তাই মোট ২৩২ = ৪,২৯,৪৯,৬৭,২৯৬টি (প্রায় ৪৩০ কোটি) ঠিকানা। এর একটি বড় অংশ আবার multicast, loopback-এর মতো বিশেষ কাজে সংরক্ষিত। অথচ পৃথিবীতে মানুষই ৮০০ কোটির বেশি, আর প্রত্যেকের একাধিক যন্ত্র। নব্বইয়ের দশকের শুরুতেই বোঝা গিয়েছিল ঠিকানা ফুরোবে; তাই দুটি সমাধানের কাজ শুরু হলো — দীর্ঘমেয়াদে বড় ঠিকানার নতুন protocol (IPv6, পর্ব ২১), আর স্বল্পমেয়াদে ঠিকানা ভাগাভাগির কৌশল NAT. মজার ব্যাপার হলো, “স্বল্পমেয়াদি” কৌশলটিই তিন দশক ধরে ইন্টারনেট চালিয়ে যাচ্ছে।

১৯৯৪ সালে Kjeld Egevang আর Paul Francis RFC 1631-এ NAT-এর ধারণা প্রকাশ করেন — ১৯৯৬ সালে RFC 1918 ঠিক করে দেয় কোন তিনটি ব্লক যে-কেউ ঘরোয়া (private) কাজে ব্যবহার করতে পারবেন। পরে RFC 2663 (১৯৯৯) পরিভাষা আর RFC 3022 (২০০১) প্রচলিত NAT ও NAPT-এর বর্ণনা দেয়। ফেব্রুয়ারি ২০১১-এ IANA-র কেন্দ্রীয় ভান্ডারের শেষ IPv4 ব্লকগুলো আঞ্চলিক রেজিস্ট্রিগুলোকে দেওয়া হয়, আর এপ্রিল ২০১১-এ এশিয়া-প্যাসিফিকের রেজিস্ট্রি APNIC (বাংলাদেশ যার অধীনে) তার শেষ বড় ব্লকে পৌঁছে খুব কড়া বণ্টন-নীতিতে চলে যায়।

Private ঠিকানা — মহল্লার ভেতরের বাড়ির নম্বর

RFC 1918 তিনটি ঠিকানার ব্লক আলাদা করে রেখেছে, যেগুলো কোনো প্রতিষ্ঠানকে বরাদ্দ দেওয়া হয় না। যে-কেউ নিজের নেটওয়ার্কের ভেতরে এগুলো ব্যবহার করতে পারেন, কারও অনুমতি লাগে না। শর্ত একটাই: এগুলো ইন্টারনেটে route হয় না। ISP-র router আর ইন্টারনেটের router-গুলো এই ঠিকানার packet গন্তব্য হিসেবে পেলে কোথায় পাঠাবে জানে না, আর ভালো ISP এমন উৎস-ঠিকানার packet নিজের সীমানাতেই ফেলে দেয়। এজন্য এগুলোকে বলে private ঠিকানা, আর যেগুলো সারা পৃথিবীতে অনন্য ও route হয়, সেগুলো public ঠিকানা.

ব্লক (CIDR)পরিসরঠিকানার সংখ্যাকোথায় দেখবেন
10.0.0.0/810.0.0.0 – 10.255.255.255২২৪ = ১,৬৭,৭৭,২১৬বড় অফিস, data center, cloud-এর VPC, অনেক মোবাইল নেটওয়ার্ক
172.16.0.0/12172.16.0.0 – 172.31.255.255২২০ = ১০,৪৮,৫৭৬Docker-এর ডিফল্ট নেটওয়ার্ক (172.17.0.0/16), কিছু অফিস
192.168.0.0/16192.168.0.0 – 192.168.255.255২১৬ = ৬৫,৫৩৬প্রায় সব বাসার Wi-Fi router (192.168.0.x বা 192.168.1.x)
100.64.0.0/10100.64.0.0 – 100.127.255.255২২২ = ৪১,৯৪,৩০৪ISP-র carrier-grade NAT (RFC 6598, অংশ ৭) — RFC 1918 নয়, আলাদা “shared” ব্লক
192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24তিনটি /24প্রতিটি ২৫৬বই আর ডকুমেন্টেশনের উদাহরণ (RFC 5737) — এই পর্বের “public” ঠিকানাগুলো এখান থেকে নেওয়া

খেয়াল করুন 172.16.0.0/12-এর সীমা: 172.16 থেকে 172.31 পর্যন্ত, অর্থাৎ 172.32.0.1 একটি public ঠিকানা! এটি পরীক্ষায় খুব প্রিয় একটি ফাঁদ। এই হিসাব (/১২ মানে প্রথম ১২ bit স্থির) পর্ব ১৬-১৭-এ ধাপে ধাপে করবেন।

একটি বড় অফিসের টেলিফোন ব্যবস্থা ভাবুন। বাইরে থেকে অফিসের নম্বর একটাই — ধরুন ০২-৯৫৫৫৫৫৫. ভেতরে প্রত্যেক টেবিলে একটি এক্সটেনশন: হিসাব ১০১, HR ১০২. প্রতিটি অফিসেই “এক্সটেনশন ১০১” আছে, কারণ এক্সটেনশন শুধু ভবনের ভেতরে অর্থবহ। আর মাঝখানে বসে আছেন রিসেপশনিস্ট: ভেতর থেকে কেউ বাইরে ফোন করলে তিনি খাতায় লেখেন “১০২ নম্বর টেবিল থেকে অমুক ব্যাংকে কল গেছে”, আর ব্যাংক ফিরতি কল দিলে খাতা দেখে ঠিক ১০২-এ লাইন দেন। Private ঠিকানা = এক্সটেনশন, public ঠিকানা = অফিসের নম্বর, NAT router = রিসেপশনিস্ট আর তাঁর খাতা।

২ · NAT router আসলে কী করে — যাওয়ার পথে, ফেরার পথে

একটি NAT router-এর দুটি দিক: ভেতরের (inside, LAN) দিকে private ঠিকানা, যেমন 192.168.1.1; বাইরের (outside, WAN) দিকে ISP-র দেওয়া public ঠিকানা, এই পর্বে ধরি 203.0.113.5. ভেতরের প্রতিটি যন্ত্রের default gateway এই router. NAT-এর কাজ তিনটি ধাপে বোঝা যায়:

বাইরে যাওয়ার সময়

Packet-এর উৎস IP (private) মুছে router নিজের public IP বসায়। PAT-এ উৎস port-ও দরকারমতো বদলায়। গন্তব্য অপরিবর্তিত।

source NAT

মনে রাখা

কোন ভেতরের ঠিকানা:port কোন বাইরের port পেল, কার সাথে কথা হচ্ছে — সব লেখা থাকে translation table-এ, শেষ কখন packet গেল তার সময়সহ।

রিসেপশনের খাতা

উত্তর ফেরার সময়

উত্তরের গন্তব্য public IP:port দেখে table খুঁজে router সেটিকে আসল private IP:port-এ বদলে ভেতরে পাঠায়। মিল না পেলে packet ফেলে দেয়।

reverse translation

Port কী, তা পর্ব ২৭-এ বিস্তারিত দেখবেন। আপাতত এটুকু যথেষ্ট: একটি host-এ একসাথে অনেক কথোপকথন চলে (ব্রাউজারের দশটি ট্যাব, ইমেইল, গেম); port নম্বর হলো সেই host-এর ভেতরে একটি নির্দিষ্ট কথোপকথনের নাম — ১৬ bit-এর একটি সংখ্যা, ০ থেকে ৬৫,৫৩৫. সার্ভারের port পরিচিত (HTTPS 443, DNS 53), ক্লায়েন্টের port OS বেছে দেয় (ephemeral port). একটি TCP বা UDP কথোপকথন তাই পাঁচটি জিনিসে চেনা যায়: protocol, উৎস IP, উৎস port, গন্তব্য IP, গন্তব্য port — একে বলে 5-tuple. NAT এই 5-tuple-এর উৎস অংশটুকু বদলায়।

এবার অফিসের একটি ল্যাপটপের অনুরোধ ধরে ধরে দেখি। অফিসে আরেকটি ল্যাপটপ (192.168.1.10) আগেই একই সার্ভারে উৎস port 50000 দিয়ে সংযোগ খুলেছে — তাই router-এর public port 50000 আর খালি নেই।

  1. ল্যাপটপ192.168.1.11port 50000
  2. NAT routertable-এ নতুন সারিport 50001
  3. সার্ভার198.51.100.20port 443
  4. NAT router50001 → .11:50000উল্টো বদল
  5. ল্যাপটপউত্তর পেলNAT টেরই পায়নি
Packet-এর ঘর আর router-এর table
কোথায়
উৎস IP:port
গন্তব্য IP:port
Table-এর সারি
TTL │ checksum
  1. ল্যাপটপ একটি সাধারণ packet পাঠাল। উৎস 192.168.1.11:50000, গন্তব্য 198.51.100.20:443 (একটি HTTPS সার্ভার), TTL 64. ল্যাপটপ শুধু gateway-তে packet দিয়েছে, NAT-এর কথা সে জানে না।
  2. Router table খুঁজল, নতুন সারি বানাল। এই 5-tuple-এর জন্য কোনো সারি নেই, তাই এটি একটি নতুন কথোপকথন। Router public port বাছতে চাইল 50000 (ভেতরের port-টাই রাখা গেলে ভালো), কিন্তু সেটি .10-এর দখলে। তাই নিল পরের খালি port 50001, আর table-এ লিখল: “TCP, public 50001 ⇄ ভেতরে 192.168.1.11:50000, অপর প্রান্ত 198.51.100.20:443”. সাধারণ router-এর মতো TTL এক কমল।
  3. উৎস বদলে বাইরে পাঠাল। উৎস এখন 203.0.113.5:50001. যেহেতু IP header আর TCP header-এর ঘর বদলেছে, দুটি checksum-ই নতুন করে ঠিক করতে হলো (অংশ ৪)। সার্ভার ভেতরের ঠিকানা কখনো দেখবে না।
  4. সার্ভার উত্তর দিল। সার্ভার যেখান থেকে packet পেয়েছিল সেখানেই উত্তর পাঠায়: গন্তব্য 203.0.113.5:50001. পথে কয়েকটি router পেরিয়ে TTL 57 হয়ে router-এর WAN পাশে পৌঁছাল।
  5. Router খাতা দেখে উল্টো বদল করল। TCP, গন্তব্য port 50001 — table-এ সারি আছে, আর উৎস 198.51.100.20:443 সারির অপর প্রান্তের সাথে মেলে। তাই গন্তব্য বদলে 192.168.1.11:50000, checksum আবার হালনাগাদ, আর সারির “শেষ ব্যবহারের সময়” নতুন করা হলো (অংশ ৫-এর timeout-এর জন্য জরুরি)।
  6. ল্যাপটপ উত্তর পেল — কিছুই টের না পেয়ে। উত্তর এসেছে ঠিক যেখানে অনুরোধ গিয়েছিল সেখান থেকে। একই সময়ে .10-এর সংযোগও port 50000-এ চলছে, কোনো গোলমাল নেই, কারণ বাইরের port আলাদা।
মূল ধারণা

NAT দুটি জিনিসের ওপর দাঁড়িয়ে: (১) ভেতর থেকে শুরু হওয়া কথোপকথনের জন্য table-এ একটি সারি, আর (২) ফেরত packet-এর গন্তব্য port দিয়ে সেই সারি খুঁজে পাওয়া। যে packet-এর জন্য কোনো সারি নেই — যেমন বাইরে থেকে হঠাৎ আসা অনুরোধ — router জানেই না তাকে কোন যন্ত্রে দিতে হবে। NAT-এর প্রায় সব সুবিধা আর সব ঝামেলা এই একটি সত্য থেকে আসে।

প্রাপক কী দেখে — একটি ছোট C পরীক্ষা

NAT ঠিক কোন তথ্যটি বদলায়, তা প্রাপকের দিক থেকে দেখা যায়। UDP সার্ভার recvfrom() দিয়ে packet পড়লে OS তাকে প্রেরকের IP আর port-ও দেয় — সার্ভার এটাকেই উত্তরের ঠিকানা হিসেবে ব্যবহার করে। নিচের প্রোগ্রাম একই কম্পিউটারের loopback-এ দুটি UDP socket খোলে: একটি 127.0.0.1:47000-এ শোনে, অন্যটি 127.0.0.1:47001 থেকে পাঠায়।

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

static int udp_on(unsigned short port) {          /* UDP socket bound to 127.0.0.1:port */
    int s = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in a = {0};
    a.sin_family = AF_INET;
    a.sin_port = htons(port);
    a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    if (s < 0 || bind(s, (struct sockaddr *)&a, sizeof a) < 0) { perror("bind"); return -1; }
    return s;
}
int main(void) {
    int rx = udp_on(47000), tx = udp_on(47001);
    if (rx < 0 || tx < 0) return 1;
    struct sockaddr_in to = {0}, from;
    to.sin_family = AF_INET;
    to.sin_port = htons(47000);
    to.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    sendto(tx, "hello", 5, 0, (struct sockaddr *)&to, sizeof to);
    char buf[64];
    socklen_t len = sizeof from;
    ssize_t n = recvfrom(rx, buf, sizeof buf - 1, 0, (struct sockaddr *)&from, &len);
    if (n < 0) { perror("recvfrom"); return 1; }
    buf[n] = '\0';
    printf("receiver got \"%s\" (%zd bytes)\n", buf, n);
    printf("source as seen by receiver: %s:%u\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
    printf("a NAT on the path would replace exactly this pair with its public IP:port\n");
    close(rx); close(tx);
    return 0;
}

আউটপুট:

receiver got "hello" (5 bytes)
source as seen by receiver: 127.0.0.1:47001
a NAT on the path would replace exactly this pair with its public IP:port

প্রাপক যে 127.0.0.1:47001 দেখল, সেটা packet-এর IP header-এর উৎস ঠিকানা আর UDP header-এর উৎস port থেকে kernel পড়ে দিয়েছে। ইন্টারনেটে প্রেরক NAT-এর পেছনে থাকলে ঠিক এই জোড়াটি বদলে যেত — সার্ভার দেখত 203.0.113.5:50001-এর মতো router-এর ঠিকানা, আর উত্তর পাঠাত সেখানেই।

৩ · Static NAT, dynamic NAT আর PAT — তিন রকম খাতা

NAT-এর table কীভাবে সাজানো, তার ওপর তিনটি প্রধান ধরন:

ধরনম্যাপিংকী বদলায়কোথায় ব্যবহার
Static NATএক private ↔ এক public, স্থায়ীশুধু IPএকটি ভেতরের সার্ভারকে স্থায়ী public ঠিকানা দেওয়া; বাইরে থেকেও সংযোগ শুরু করা যায়
Dynamic NATঅনেক private → public ঠিকানার একটি pool, দরকারমতো ধারশুধু IPপুরোনো প্রতিষ্ঠানের নকশা; pool-এর ঠিকানা শেষ হলে নতুন যন্ত্র বাইরে যেতে পারে না
PAT / NAPT (“masquerade”, Cisco-তে “overload”)অনেক private → একটি (বা কয়েকটি) public, port দিয়ে আলাদাIP আর portপ্রায় সব বাসা, অফিস, মোবাইল নেটওয়ার্ক আর CGNAT

Static NAT-এর table আগে থেকে লেখা, তাই বাইরে থেকেও সংযোগ শুরু করা যায়। Dynamic NAT-এ ঠিকানা pool থেকে ধার নেওয়া হয়, অব্যবহৃত থাকলে ফেরত যায়। দুটোতেই একটি public ঠিকানা একই সময়ে একটি যন্ত্রেরই — ঠিকানা বাঁচে না বললেই চলে। PAT (Port Address Translation, RFC 3022-এর ভাষায় NAPT) এখানে বড় লাফ: port যোগ করায় একটি public ঠিকানার পেছনে একসাথে শত শত যন্ত্র চলে। আজ সাধারণ কথায় “NAT” বললে প্রায় সবসময় PAT-ই বোঝানো হয়।

একটি PAT router চালিয়ে দেখা

নিচের simulator একটি ছোট PAT router: তিনটি ভেতরের যন্ত্র বাইরে সংযোগ খোলে (দুটি একই ভেতরের port 50000 ব্যবহার করে!), তারপর কয়েকটি packet বাইরে থেকে আসে — দুটি বৈধ উত্তর, দুটি অনুরোধ-ছাড়া packet, আর একটি দেরিতে আসা UDP উত্তর। Timeout-এর মান এখানে শেখার সুবিধার জন্য ছোট রাখা (TCP 300, UDP 30 সেকেন্ড); বাস্তবের মান অংশ ৫-এ।

// PAT (NAPT) simulator: many inside hosts share one public IP 203.0.113.5.
const PUB = "203.0.113.5", TIMEOUT = { tcp: 300, udp: 30 };  // seconds (example values)
const table = new Map();          // key "proto:publicPort" -> entry
function out(t, proto, src, sport, dst, dport) {
  let p = sport;                  // keep the inside port if it is free, else next free
  while (table.has(proto + ":" + p)) p++;
  table.set(proto + ":" + p, { src, sport, dst, dport, last: t });
  console.log(`t=${t} OUT ${proto} ${src}:${sport} -> ${dst}:${dport}  rewritten src = ${PUB}:${p}`);
}
function back(t, proto, src, sport, dport) {
  const e = table.get(proto + ":" + dport);
  if (e && t - e.last > TIMEOUT[proto]) { table.delete(proto + ":" + dport);
    console.log(`t=${t} entry ${proto}:${dport} idle ${t - e.last}s > ${TIMEOUT[proto]}s -> expired`); }
  const ok = table.get(proto + ":" + dport);
  if (!ok || ok.dst !== src || ok.dport !== sport)
    return console.log(`t=${t} IN  ${proto} ${src}:${sport} -> ${PUB}:${dport}  no matching entry -> DROP`);
  ok.last = t;
  console.log(`t=${t} IN  ${proto} ${src}:${sport} -> ${PUB}:${dport}  rewritten dst = ${ok.src}:${ok.sport}`);
}
function show() {
  console.log("  proto pub-port  inside              remote               last");
  for (const [k, e] of table) console.log("  " + k.split(":")[0].padEnd(6) + k.split(":")[1].padEnd(10) +
    (e.src + ":" + e.sport).padEnd(20) + (e.dst + ":" + e.dport).padEnd(21) + "t=" + e.last);
}
out(0, "tcp", "192.168.1.10", 50000, "198.51.100.20", 443);
out(1, "tcp", "192.168.1.11", 50000, "198.51.100.20", 443);   // same inside port!
out(2, "udp", "192.168.1.12", 41000, "198.51.100.53", 53);
show();
back(3, "tcp", "198.51.100.20", 443, 50000);
back(4, "tcp", "198.51.100.20", 443, 50001);
back(5, "tcp", "192.0.2.66", 4444, 3389);                     // unsolicited
back(6, "tcp", "192.0.2.66", 4444, 50000);                    // right port, wrong remote
back(40, "udp", "198.51.100.53", 53, 41000);                  // reply came too late
show();

আউটপুট:

t=0 OUT tcp 192.168.1.10:50000 -> 198.51.100.20:443  rewritten src = 203.0.113.5:50000
t=1 OUT tcp 192.168.1.11:50000 -> 198.51.100.20:443  rewritten src = 203.0.113.5:50001
t=2 OUT udp 192.168.1.12:41000 -> 198.51.100.53:53  rewritten src = 203.0.113.5:41000
  proto pub-port  inside              remote               last
  tcp   50000     192.168.1.10:50000  198.51.100.20:443    t=0
  tcp   50001     192.168.1.11:50000  198.51.100.20:443    t=1
  udp   41000     192.168.1.12:41000  198.51.100.53:53     t=2
t=3 IN  tcp 198.51.100.20:443 -> 203.0.113.5:50000  rewritten dst = 192.168.1.10:50000
t=4 IN  tcp 198.51.100.20:443 -> 203.0.113.5:50001  rewritten dst = 192.168.1.11:50000
t=5 IN  tcp 192.0.2.66:4444 -> 203.0.113.5:3389  no matching entry -> DROP
t=6 IN  tcp 192.0.2.66:4444 -> 203.0.113.5:50000  no matching entry -> DROP
t=40 entry udp:41000 idle 38s > 30s -> expired
t=40 IN  udp 198.51.100.53:53 -> 203.0.113.5:41000  no matching entry -> DROP
  proto pub-port  inside              remote               last
  tcp   50000     192.168.1.10:50000  198.51.100.20:443    t=3
  tcp   50001     192.168.1.11:50000  198.51.100.20:443    t=4

বাইরে যাওয়া (t=0–2): প্রথম ল্যাপটপ port 50000 রেখে দিতে পারল। দ্বিতীয়টি একই 50000 চাইল, কিন্তু public পাশে 50000 দখলে — তাই 50001 পেল। ভেতরের port রেখে দেওয়ার এই চেষ্টা (port preservation) Linux-সহ অনেক NAT করে, তবে নিশ্চয়তা নেই। প্রথম table-এ তিনটি সারি — ঠিক stepper-এর মতো।

ফেরত (t=3–4): সার্ভারের দুটি উত্তর গন্তব্য port 50000 আর 50001 দিয়ে আলাদা হয়ে ঠিক দুটি ল্যাপটপে গেল। অনুরোধ-ছাড়া packet (t=5–6): 192.0.2.66 থেকে port 3389-এ (Windows Remote Desktop-এর port) আসা packet-এর কোনো সারিই নেই — DROP. পরেরটি সঠিক port 50000-এ এলেও অপর প্রান্ত সারির সাথে মেলে না (সারিটি 198.51.100.20:443-এর জন্য), তাই সেটিও DROP. এই simulator-টি Linux-এর মতো পুরো 5-tuple মেলায়; কিছু সস্তা NAT শুধু port দেখে ছেড়ে দেয় (অংশ ৬-এর “full cone”).

Timeout (t=40): DNS-এর উত্তর এল ৩৮ সেকেন্ড পরে, অথচ UDP-র timeout ৩০ — সারি আগেই মুছে গেছে, উত্তরও DROP. শেষ table-এ শুধু দুটি TCP সারি, তাদের সময় t=3 আর t=4-এ হালনাগাদ। নিজে চেষ্টা করুন: udp: 30 বদলে udp: 60 করে চালান — অনুশীলন ২-এ উত্তর আছে।

Linux-এ NAT: masquerade আর conntrack

বাসার বেশিরভাগ Wi-Fi router-এর ভেতরে আসলে একটি ছোট Linux চলে, আর NAT করে kernel-এর netfilter অংশ। নিয়ম লেখা হয় পুরোনো iptables বা নতুন nftables দিয়ে। নিচের কমান্ডগুলো root ছাড়া চলে না, আর অন্যের যন্ত্রে নয় — শুধু নিজের ল্যাব বা VM-এ চেষ্টা করবেন।

# ১. kernel-কে packet forward করতে দেওয়া (router হতে এটি লাগে)
$ sudo sysctl -w net.ipv4.ip_forward=1

# ২ক. পুরোনো iptables: LAN 192.168.1.0/24 থেকে eth0 দিয়ে বেরোলে উৎস বদল
$ sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE

# ২খ. একই কাজ nftables-এ (আধুনিক Linux-এ পছন্দের পথ)
$ sudo nft add table ip nat
$ sudo nft add chain ip nat postrouting '{ type nat hook postrouting priority srcnat; }'
$ sudo nft add rule ip nat postrouting ip saddr 192.168.1.0/24 oifname "eth0" masquerade

MASQUERADE মানে “বাইরের interface-এর বর্তমান ঠিকানাটাই উৎস হিসেবে বসানো” — ISP DHCP দিয়ে ঠিকানা বদলালেও নিয়ম কাজ করে। ঠিকানা স্থির হলে SNAT --to-source 203.0.113.5 (nftables-এ snat to 203.0.113.5) লেখা যায়। খেয়াল করুন: নিয়মটি শুধু প্রথম packet-এ দেখা হয়। তারপর kernel-এর conntrack (connection tracking) প্রতিটি কথোপকথনের দুই দিকের চেহারা মনে রাখে, আর পরের সব packet সরাসরি সেই হিসাবে বদলায় — ঠিক উপরের simulator-এর table. conntrack টুল (root লাগে) দিয়ে সেই table দেখা যায়:

$ sudo conntrack -L -p tcp
tcp  6 431995 ESTABLISHED src=192.168.1.11 dst=198.51.100.20 sport=50000 dport=443
                          src=198.51.100.20 dst=203.0.113.5 sport=443 dport=50001 [ASSURED] mark=0 use=1
$ sudo conntrack -L -p udp
udp  17 27 src=192.168.1.12 dst=198.51.100.53 sport=41000 dport=53
           src=198.51.100.53 dst=203.0.113.5 sport=53 dport=41000 mark=0 use=1

প্রতিটি সারিতে দুটি অংশ: প্রথমটি মূল দিক (ল্যাপটপ যা পাঠিয়েছিল), দ্বিতীয়টি প্রত্যাশিত উত্তর — কোথা থেকে আসবে, কোন ঠিকানা:port-এ। দ্বিতীয় অংশের dst=203.0.113.5 dport=50001-ই NAT-এর প্রমাণ। মাঝের সংখ্যাটি (431995, 27) হলো সারি মুছে যেতে আর কত সেকেন্ড বাকি। Cisco-র মতো router-এ একই কাজ “overload” শব্দে হয়:

interface GigabitEthernet0/0
 ip address 192.168.1.1 255.255.255.0
 ip nat inside
interface GigabitEthernet0/1
 ip address 203.0.113.5 255.255.255.252
 ip nat outside
!
access-list 1 permit 192.168.1.0 0.0.0.255
ip nat inside source list 1 interface GigabitEthernet0/1 overload
!
R1# show ip nat translations
Pro Inside global       Inside local        Outside local      Outside global
tcp 203.0.113.5:50001   192.168.1.11:50000  198.51.100.20:443  198.51.100.20:443

Cisco-র চারটি নাম মনে রাখার মতো: inside local (ভেতরের যন্ত্রের আসল ঠিকানা), inside global (বাইরে সেই যন্ত্র যে ঠিকানায় পরিচিত), outside global (বাইরের সার্ভারের আসল ঠিকানা), outside local (ভেতর থেকে সেই সার্ভার যে ঠিকানায় দেখা যায় — সাধারণত একই)। CCNA-ধরনের পরীক্ষায় এই চারটি প্রায়ই আসে।

৪ · ঠিকানা বদলালে checksum-ও বদলায় — দ্রুত হিসাবের কৌশল

পর্ব ০৯-এ দেখেছেন, IP header-এ একটি ১৬ bit-এর checksum থাকে: header-এর সব ১৬ bit-এর শব্দ one's complement পদ্ধতিতে যোগ করে (উপচে পড়া carry আবার নিচে যোগ করে) ফলটি উল্টে দেওয়া (RFC 1071). NAT উৎস ঠিকানা বদলালে header-এর দুটি শব্দ বদলায়, তাই checksum ঠিক না করলে পরের router packet-টি নষ্ট ভেবে ফেলে দেবে।

ঝামেলা এখানেই শেষ নয়। TCP আর UDP-র checksum শুধু নিজের header আর ডেটার ওপর নয়, একটি pseudo-header-এর ওপরও হিসাব হয় — উৎস IP, গন্তব্য IP, protocol নম্বর আর দৈর্ঘ্য, যেগুলো আসলে IP header-এর ঘর। ফল: NAT যখন শুধু IP ঠিকানা বদলায়, তখনও TCP/UDP checksum ভুল হয়ে যায়। তাই NAT-কে layer 3-এর যন্ত্র হয়েও layer 4-এর header খুলে ঠিক করতে হয় — স্তরের নিয়ম ভাঙার (layer violation) একটি ক্লাসিক উদাহরণ। (IPv4-এ UDP checksum 0 মানে “checksum নেই”; তখন NAT সেটি 0-ই রাখে।)

পুরোটা আবার না যোগ করে — RFC 1624

প্রতিটি packet-এর পুরো segment আবার যোগ করা ব্যয়বহুল। কিন্তু one's complement যোগের একটি সুন্দর গুণ আছে: যোগের ক্রম কোনো ব্যাপার নয়, আর একটি শব্দ m-কে বাদ দেওয়া মানে তার উল্টো ~m যোগ করা (কারণ one's complement-এ m + ~m = 0xFFFF, যা “শূন্য”-এর আরেক রূপ)। তাই পুরোনো checksum HC থেকে নতুনটি পাওয়া যায় শুধু বদলানো শব্দগুলো দিয়ে:

HC′ = ~( ~HC + ~m + m′ )
m = পুরোনো শব্দ, m′ = নতুন শব্দ, সব যোগ one's complement-এ (RFC 1624)

কেন ঠিক: ধরুন সব শব্দের one's complement যোগফল S, তাহলে HC = ~S, অর্থাৎ ~HC = S. একটি শব্দ m বদলে m′ হলে নতুন যোগফল S′ = S − m + m′. One's complement-এ “− m” মানে “+ ~m”, তাই S′ = ~HC + ~m + m′, আর নতুন checksum HC′ = ~S′. কয়েকটি শব্দ বদলালে প্রতিটির জন্য একটি করে (~m + m′) যোগ করলেই হয়। (আগের RFC 1141-এর সূত্র HC′ = HC + m + ~m′ একটি বিশেষ অবস্থায় one's complement-এর “দুই শূন্য” — 0x0000 আর 0xFFFF — গুলিয়ে ভুল ফল দিত; RFC 1624 সেটি শুধরে উপরের রূপ দেয়।)

নিচের কোড একটি ২০ byte-এর IPv4 header আর একটি TCP segment-এর (pseudo-header-সহ) checksum বানায়, তারপর NAT-এর মতো উৎস 192.168.1.11:50000 বদলে 203.0.113.5:50001 করে — একবার পুরো আবার হিসাব করে, একবার RFC 1624-এর সূত্রে — আর দুটি মেলায়।

// NAT changes src IP + src port: update checksums incrementally (RFC 1624) vs full recompute.
const hex = n => "0x" + n.toString(16).padStart(4, "0");
const fold = s => { while (s > 0xffff) s = (s & 0xffff) + (s >>> 16); return s; };
const csum = words => (~fold(words.reduce((a, b) => a + b, 0))) & 0xffff;   // RFC 1071
const ip = s => s.split(".").map(Number), w = (a, b) => (a << 8) | b;
const ipWords = s => { const o = ip(s); return [w(o[0], o[1]), w(o[2], o[3])]; };
// IPv4 header (20 bytes) as 10 words; word 5 = checksum, words 6-9 = src, dst
function ipHeader(src, dst) {
  return [0x4500, 60, 0x1c46, 0x4000, w(64, 6), 0, ...ipWords(src), ...ipWords(dst)];
}
// TCP: pseudo-header (src, dst, proto 6, length 20) + 20-byte header, checksum word 8
function tcpWords(src, dst, sport) {
  return [...ipWords(src), ...ipWords(dst), 6, 20,
          sport, 443, 0x0000, 0x0001, 0x0000, 0x0000, 0x5010, 0xfaf0, 0, 0];
}
const inc = (hc, olds, news) => {                  // HC' = ~(~HC + ~m + m')
  let s = (~hc) & 0xffff;
  olds.forEach((m, i) => { s += ((~m) & 0xffff) + news[i]; });
  return (~fold(s)) & 0xffff;
};
const IN = "192.168.1.11", OUT = "203.0.113.5", DST = "198.51.100.20";
const ipOld = csum(ipHeader(IN, DST)), ipNew = csum(ipHeader(OUT, DST));
const ipInc = inc(ipOld, ipWords(IN), ipWords(OUT));
console.log("IP  checksum before NAT :", hex(ipOld));
console.log("IP  full recompute      :", hex(ipNew), " incremental:", hex(ipInc),
            ipNew === ipInc ? "MATCH" : "DIFF");
const tOld = csum(tcpWords(IN, DST, 50000)), tNew = csum(tcpWords(OUT, DST, 50001));
const tInc = inc(tOld, [...ipWords(IN), 50000], [...ipWords(OUT), 50001]);
console.log("TCP checksum before NAT :", hex(tOld));
console.log("TCP full recompute      :", hex(tNew), " incremental:", hex(tInc),
            tNew === tInc ? "MATCH" : "DIFF");
console.log("words touched: IP 2 of 10, TCP 3 of 16 (pseudo-header + header)");

আউটপুট:

IP  checksum before NAT : 0x327b
IP  full recompute      : 0xb828  incremental: 0xb828 MATCH
TCP checksum before NAT : 0x03dc
TCP full recompute      : 0x8988  incremental: 0x8988 MATCH
words touched: IP 2 of 10, TCP 3 of 16 (pseudo-header + header)

দুই ক্ষেত্রেই দুই পদ্ধতির ফল হুবহু এক — MATCH. IP header-এ বদলেছে শুধু উৎস ঠিকানার দুটি শব্দ: c0a8 010b (192.168.1.11) → cb00 7105 (203.0.113.5). হাতে মিলিয়ে দেখুন: ~HC = ~0x327b = 0xcd84. যোগ করুন ~0xc0a8 = 0x3f57, তারপর 0xcb00, ~0x010b = 0xfef4, আর 0x7105: মোট 0x347d4. উপচে পড়া 3 নিচে যোগ: 0x47d4 + 3 = 0x47d7. উল্টালে 0xb828 — ঠিক নতুন checksum. TCP-তে বদলেছে তিনটি শব্দ: pseudo-header-এর দুটি (উৎস IP) আর header-এর একটি (উৎস port 50000 → 50001). পুরো segment যত বড়ই হোক, NAT-কে ছুঁতে হয় এই কয়েকটি শব্দ — এজন্যই router-এর hardware প্রতি সেকেন্ডে লাখো packet-এ এটা করতে পারে।

৫ · ভেতরের সার্ভার বাইরে দেখানো — port forwarding, timeout আর hairpinning

PAT-এর table শুধু ভেতর থেকে শুরু হওয়া কথোপকথনে তৈরি হয়। কিন্তু অফিসের 192.168.1.50-এ চলা ওয়েব সার্ভার বাইরের গ্রাহকদের দেখাতে চাইলে? বাইরে থেকে আসা অনুরোধের কোনো সারি নেই! সমাধান হলো হাতে একটি স্থায়ী নিয়ম লেখা: “public ঠিকানার TCP port 8080-এ যা আসবে, তা ভেতরের 192.168.1.50:80-এ যাবে” — এর নাম port forwarding, আর Linux-এর ভাষায় DNAT (destination NAT), কারণ এখানে বদলায় গন্তব্য. আগের অংশের masquerade ছিল SNAT — উৎস বদল।

  1. গ্রাহক198.51.100.77port 52345
  2. NAT routerDNAT নিয়ম8080 → .50:80
  3. ওয়েব সার্ভার192.168.1.50port 80
  4. NAT routerconntrackউৎস বদল
  5. গ্রাহকউত্তর পেল203.0.113.5:8080 থেকে
Packet-এর ঘর
কোথায়
উৎস IP:port
গন্তব্য IP:port
কী ঘটল
  1. বাইরের গ্রাহক সংযোগ শুরু করল। তাঁর ব্রাউজার http://203.0.113.5:8080-এ TCP SYN পাঠাল (TCP সংযোগের প্রথম packet, পর্ব ২৯)। Router-এর conntrack-এ এই কথোপকথনের কোনো সারি নেই — সাধারণ PAT হলে এখানেই DROP হতো।
  2. DNAT নিয়ম মিলল। “TCP, গন্তব্য port 8080” নিয়মে মিলে গেল, তাই router গন্তব্য বদলে করল 192.168.1.50:80, checksum ঠিক করল, আর conntrack-এ নতুন সারি লিখল। এই বদল হয় routing সিদ্ধান্তের আগে (Linux-এ PREROUTING), কারণ নতুন গন্তব্য দেখেই ঠিক হবে packet কোন interface-এ যাবে।
  3. সার্ভার আসল গ্রাহককে দেখল। সার্ভারের কাছে উৎস 198.51.100.77:52345 — গ্রাহকের আসল ঠিকানা, কারণ উৎস বদলানো হয়নি। উত্তর গেল সেই ঠিকানায়, আর সার্ভারের default gateway যেহেতু এই router, উত্তর router দিয়েই বেরোবে।
  4. Router উল্টো দিকে বদলাল। conntrack-এর সারি দেখে router বুঝল এটি port forwarding-এর উত্তর, তাই উৎস 192.168.1.50:80 বদলে 203.0.113.5:8080 বসাল। এটা না করলে গ্রাহকের কাছে এমন জায়গা থেকে উত্তর যেত যাকে তিনি চেনেনই না, আর তাঁর TCP সেটি বাতিল করত।
  5. গ্রাহক উত্তর পেল। তাঁর চোখে পুরো কথোপকথন 203.0.113.5:8080-এর সাথে। একটি public ঠিকানার আলাদা আলাদা port আলাদা ভেতরের সার্ভারে পাঠানো যায় — 8080 ওয়েবে, 2222 আরেকটি যন্ত্রের SSH-এ।
# iptables: eth0-তে TCP 8080 এলে ভেতরের 192.168.1.50:80-এ
$ sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 \
       -j DNAT --to-destination 192.168.1.50:80
# FORWARD chain-এর নীতি DROP হলে এই সংযোগটি অনুমতি দিতে হবে
$ sudo iptables -A FORWARD -p tcp -d 192.168.1.50 --dport 80 \
       -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT

# nftables-এ একই কাজ
$ sudo nft add chain ip nat prerouting '{ type nat hook prerouting priority dstnat; }'
$ sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 8080 dnat to 192.168.1.50:80

বাসার router-এর “Port Forwarding” মেনুতে একই কাজ হয়। কিছু যন্ত্র প্রোগ্রামকে নিজে থেকে নিয়ম খোলার সুযোগ দেয় — UPnP IGD, NAT-PMP (RFC 6886) বা তার উত্তরসূরি PCP (Port Control Protocol, RFC 6887). ঝুঁকি হলো, ভেতরের ক্ষতিকর প্রোগ্রাম বা দুর্বল IoT যন্ত্রও নিজের জন্য দরজা খুলতে পারে — তাই নিরাপত্তা-সচেতন নেটওয়ার্কে UPnP সাধারণত বন্ধ থাকে।

Port forwarding মানে আপনার ভেতরের একটি যন্ত্র সরাসরি সারা পৃথিবীর সামনে। স্বয়ংক্রিয় স্ক্যানার সারাক্ষণ খোলা port খোঁজে, তাই Remote Desktop (3389), পুরোনো CCTV DVR-এর ওয়েব পাতা, ডিফল্ট পাসওয়ার্ডের router-এর admin পাতা কখনো সরাসরি খোলা রাখবেন না। দূর থেকে নিজের নেটওয়ার্কে ঢোকার নিরাপদ পথ VPN (পর্ব ৪৯)।

NAT timeout — table-এর সারি কতক্ষণ বাঁচে

Table অসীম নয়, তাই অব্যবহৃত সারি একসময় মুছতে হয়। TCP-তে router সংযোগের শুরু (SYN) আর শেষ (FIN/RST) দেখতে পায়, তাই বুঝতে পারে কোন সংযোগ বন্ধ হলো; বন্ধ হলে অল্প সময় পরেই সারি মোছে। কিন্তু UDP-তে “সংযোগ” বলে কিছু নেই — router জানেই না কথোপকথন শেষ হয়েছে কি না, তাই শুধু নীরবতার সময় গোনে। ফলে UDP-র timeout অনেক ছোট।

কোথায়UDPTCP (চালু সংযোগ)
IETF-এর সুপারিশকমপক্ষে ২ মিনিট, ডিফল্ট ৫ মিনিট বা বেশি সুপারিশকৃত (RFC 4787)কমপক্ষে ২ ঘণ্টা ৪ মিনিট (RFC 5382)
Linux conntrack-এর ডিফল্ট (version ভেদে)একমুখী হলে ৩০ সেকেন্ড; দুই দিকে traffic হলে ২–৩ মিনিট৫ দিন (৪,৩২,০০০ সেকেন্ড)
বাস্তবের বাসার router আর CGNATপ্রায়ই অনেক কম — কয়েক দশ সেকেন্ড পর্যন্ত, যন্ত্রভেদে খুব আলাদাকয়েক মিনিট থেকে কয়েক ঘণ্টা — যন্ত্রভেদে আলাদা

এর বাস্তব ফল: একটি SSH সংযোগ অনেকক্ষণ ফেলে রাখলে হঠাৎ “জমে” যায় — পথের কোনো NAT সারিটি মুছে ফেলেছে, অথচ দুই প্রান্ত ভাবছে সংযোগ চালু। প্রতিকার keepalive: নির্দিষ্ট সময় পরপর ছোট একটি packet পাঠিয়ে সারিটি “জীবিত” রাখা (SSH-এ ServerAliveInterval, TCP-তে socket-এর keepalive).

Hairpinning — ভেতর থেকে নিজের public ঠিকানায়

অফিসের ভেতরের একজন কর্মী যদি ব্রাউজারে 203.0.113.5:8080 লেখেন — নিজের অফিসের সার্ভারেই, কিন্তু public ঠিকানা দিয়ে? Packet router-এ গিয়ে DNAT হয়ে ঘুরে ভেতরে ফেরে — চুলের কাঁটার মতো বাঁক, তাই নাম hairpinning (বা NAT loopback). শুধু DNAT করলে সমস্যা: সার্ভার দেখে উৎস 192.168.1.11, একই LAN-এ, তাই router এড়িয়ে সরাসরি উত্তর দেয় — আর কর্মীর কম্পিউটার এমন একটি ঠিকানা থেকে উত্তর পায় যাকে সে অনুরোধই পাঠায়নি। তাই hairpin-এ router উৎসও বদলায় (নিজের ঠিকানা বসায়), যাতে উত্তর router দিয়েই ফেরে। RFC 4787 hairpinning সমর্থন করতে বলে, কিন্তু সব বাসার router করে না; বিকল্প হলো ভেতরের DNS-এ সার্ভারের ভেতরের ঠিকানা দেওয়া (split DNS; DNS-এর কাজের ধরন পর্ব ৩৫-এ)।

৬ · দুজনেই NAT-এর পেছনে — ভিডিও কল কীভাবে সংযোগ পায়

ওয়েব ব্রাউজিং-এ NAT প্রায় অদৃশ্য, কারণ সবসময় ক্লায়েন্টই সংযোগ শুরু করে আর সার্ভারের থাকে public ঠিকানা। কিন্তু ঢাকায় আপনি আর চট্টগ্রামে আপনার বন্ধু দুজনেই বাসার Wi-Fi-তে, দুজনেই NAT-এর পেছনে। ভিডিও কলে সবচেয়ে ভালো হয় সরাসরি peer-to-peer পথে UDP পাঠালে — কম delay, মাঝের সার্ভারের খরচ নেই। সমস্যা: আপনার packet বন্ধুর router-এ পৌঁছালে তা “অনুরোধ-ছাড়া inbound” — DROP. বন্ধুর packet-ও আপনার router-এ DROP. দুজনেরই দরজা ভেতর থেকে বন্ধ। এই সমস্যার নাম NAT traversal.

NAT-এর চার ধরন — RFC 3489-এর পুরোনো নাম

কোন NAT কতটা “বন্ধুসুলভ”, তা নির্ভর করে দুটি আচরণের ওপর: ম্যাপিং (ভেতরের একই IP:port থেকে আলাদা আলাদা গন্তব্যে গেলে বাইরের port কি একই থাকে?) আর ফিল্টারিং (বাইরের কে কে সেই port-এ packet পাঠাতে পারবে?)। ২০০৩ সালের RFC 3489 (প্রথম STUN) চারটি নাম দিয়েছিল, যা আজও বই আর ইন্টারভিউতে চলে:

RFC 3489-এর নামম্যাপিংকে ঢুকতে পারেRFC 4787-এর ভাষায়
Full coneসব গন্তব্যে একই বাইরের portম্যাপিং থাকলে যে-কেউendpoint-independent mapping + endpoint-independent filtering
Restricted coneসব গন্তব্যে একই portশুধু যে IP-তে ভেতর থেকে পাঠানো হয়েছে (যেকোনো port থেকে)endpoint-independent mapping + address-dependent filtering
Port-restricted coneসব গন্তব্যে একই portশুধু যে IP:port-এ পাঠানো হয়েছেendpoint-independent mapping + address and port-dependent filtering
Symmetricপ্রতিটি নতুন গন্তব্যে নতুন বাইরের portশুধু যে IP:port-এর জন্য ম্যাপিং বানানোaddress (and port)-dependent mapping + সাধারণত একই ধরনের filtering

পরে বোঝা গেল বাস্তবের NAT এই চার বাক্সে ঠিকমতো আঁটে না। তাই ২০০৭ সালের RFC 4787 ম্যাপিং আর ফিল্টারিংকে আলাদা করে দেখে — প্রতিটির তিনটি সম্ভাব্য আচরণ (endpoint-independent, address-dependent, address and port-dependent), আর ২০০৮ সালের নতুন STUN (RFC 5389) পুরোনো শ্রেণিবিভাগ বাদ দেয়। NAT যেন বাধা কম তৈরি করে, সেজন্য RFC 4787 endpoint-independent mapping বাধ্যতামূলক (MUST) বলে।

STUN, hole punching, TURN আর ICE

  • STUN (Session Traversal Utilities for NAT, এখন RFC 8489): ইন্টারনেটে একটি সহজ সার্ভার, যাকে একটি UDP packet পাঠালে সে উত্তরে বলে “আপনার packet আমার কাছে এসেছে এই IP:port থেকে” — অর্থাৎ আপনার NAT-এর বাইরের চেহারা। একে বলে server-reflexive ঠিকানা।
  • UDP hole punching: দুজনেই নিজের বাইরের ঠিকানা একটি signaling server-এর মাধ্যমে বিনিময় করেন, তারপর একই সময়ে একে অপরের বাইরের ঠিকানায় UDP পাঠান। নিজের পাঠানো packet নিজের NAT-এ সেই গন্তব্যের জন্য “দরজা খোলে”, তাই অপর দিকের packet এলে ঢুকতে পারে।
  • TURN (Traversal Using Relays around NAT, RFC 8656): সরাসরি না হলে শেষ ভরসা — public ঠিকানার একটি relay সার্ভার, যার মাধ্যমে দুজনের সব packet যায়। সবসময় কাজ করে, কিন্তু খরচ আর delay বাড়ে।
  • ICE (Interactive Connectivity Establishment, RFC 8445): সবগুলো একসাথে চালানোর পদ্ধতি। প্রতিটি পক্ষ নিজের সব সম্ভাব্য ঠিকানা (“candidate”) — ভেতরের, STUN-এর, TURN-এর — বিনিময় করে, জোড়ায় জোড়ায় পরীক্ষা করে সেরাটি বাছে। WebRTC (ব্রাউজারের ভিডিও কল) ICE ব্যবহার করে।
  1. A (ঢাকা)10.0.0.2:5000NAT-A
  2. STUN192.0.2.1:3478আপনি কে?
  3. Signalingঠিকানা বিনিময়candidate
  4. B (চট্টগ্রাম)192.168.0.7:6000NAT-B
দুই NAT-এর অবস্থা (দুটিই port-restricted cone)
NAT-A-র ম্যাপিং
NAT-B-র ম্যাপিং
পথে কী হলো
ফল
  1. A STUN-কে জিজ্ঞেস করল। A তার UDP port 5000 থেকে STUN সার্ভারে একটি অনুরোধ পাঠাল। NAT-A ম্যাপিং বানাল: ভেতরের 10.0.0.2:5000 ⇄ বাইরের 203.0.113.5:40000. STUN উত্তরে জানাল: “আপনাকে দেখছি 203.0.113.5:40000 হিসেবে।” A এখন নিজের বাইরের চেহারা জানে।
  2. B-ও একই কাজ করল। B-র 192.168.0.7:6000 NAT-B-তে হলো 198.51.100.9:50000. দুটি NAT-ই এখন শুধু STUN সার্ভারকে চেনে — অন্য কেউ পাঠালে DROP.
  3. Signaling server দিয়ে ঠিকানা বিনিময়। কল অ্যাপের সার্ভারের মাধ্যমে A জানল B-র বাইরের ঠিকানা, আর B জানল A-র — ICE-এর ভাষায় candidate.
  4. A আগে পাঠাল — B-র দিকে DROP. A পাঠাল 198.51.100.9:50000-এ। NAT-A-র ম্যাপিং একই থাকল (cone, তাই port 40000-ই), কিন্তু এখন NAT-A মনে রাখল যে 198.51.100.9:50000-এর সাথে কথা হয়েছে — A-র দিকে “ফুটো” তৈরি হলো। NAT-B-তে packet পৌঁছাল, কিন্তু B এখনো A-কে কিছু পাঠায়নি, তাই NAT-B ফেলে দিল। এটা প্রত্যাশিত।
  5. B পাঠাল — এবার পার হলো। B পাঠাল 203.0.113.5:40000-এ। NAT-B-তে এখন A-র জন্যও ফুটো তৈরি হলো। NAT-A-তে packet এল 198.51.100.9:50000 থেকে — যাকে A আগের ধাপেই পাঠিয়েছে — তাই NAT-A ঢুকতে দিল, A পেল।
  6. দুই দিকেই পথ খোলা। A আবার পাঠাল, এবার NAT-B-ও ঢুকতে দিল — B পেল। দুজন এখন relay ছাড়া সরাসরি UDP-তে কথা বলছে। NAT-এর UDP timeout পেরিয়ে যেন সারি না মোছে, তাই দুজনে নিয়মিত keepalive পাঠায় — সাধারণত কয়েক থেকে কয়েক দশ সেকেন্ড পরপর।
  7. B symmetric NAT-এর পেছনে হলে? তখন NAT-B প্রতিটি নতুন গন্তব্যে নতুন port দেয়: STUN-এর দিকে 50000, কিন্তু A-র দিকে হয়তো 50001. A পাঠাচ্ছে 50000-এ, যা শুধু STUN-এর জন্য — DROP. আর A নিজেও port-restricted, তাই B-র নতুন port থেকে আসা packet-ও ফেলে দেয়। কোনো দিক থেকে পথ খোলে না। ICE তখন TURN relay বেছে নেয়।

সব জোড়ার জন্য ফলটা কেমন? নিচের simulator চার ধরনের NAT-এর প্রতিটি জোড়ায় উপরের পদ্ধতি চালায়: STUN দিয়ে ঠিকানা জানা, তারপর তিন দফা দুই দিক থেকে পাঠানো। কেউ packet পেলে সে অপর প্রান্তের আসল উৎস ঠিকানা শিখে নেয় (ICE-এর “peer-reflexive” candidate) আর সেখানেই পরের packet পাঠায়।

// UDP hole punching between two NATed peers, for the four classic (RFC 3489) NAT types.
const TYPES = ["full-cone", "restricted", "port-restricted", "symmetric"];
function makeNat(type, ip) {
  const maps = [], nat = { type, ip, next: 40000 };
  nat.send = (dst) => {                 // returns the public port used toward dst
    let m = maps.find(m => type !== "symmetric" || m.dst === dst);
    if (!m) { m = { dst, port: nat.next++, seen: [] }; maps.push(m); }
    m.seen.push(dst);                    // remember whom we talked to (filtering)
    return m.port;
  };
  nat.accept = (port, from) => {        // does an inbound packet pass?
    const m = maps.find(m => m.port === port);
    if (!m) return false;
    if (type === "full-cone") return true;
    if (type === "restricted") return m.seen.some(d => d.split(":")[0] === from.split(":")[0]);
    return m.seen.includes(from);        // port-restricted and symmetric
  };
  return nat;
}
function tryPunch(tA, tB) {
  const A = makeNat(tA, "203.0.113.5"), B = makeNat(tB, "198.51.100.9"), S = "192.0.2.1:3478";
  let aSeesB = B.ip + ":" + B.send(S), bSeesA = A.ip + ":" + A.send(S);  // STUN answers
  let aGot = false, bGot = false;
  for (let round = 0; round < 3; round++) {        // both keep sending a few times
    const pa = A.ip + ":" + A.send(aSeesB);         // A -> B
    if (B.accept(+aSeesB.split(":")[1], pa)) { bGot = true; bSeesA = pa; }
    const pb = B.ip + ":" + B.send(bSeesA);         // B -> A
    if (A.accept(+bSeesA.split(":")[1], pb)) { aGot = true; aSeesB = pb; }
  }
  return aGot && bGot ? "direct" : "TURN relay";
}
console.log("A \\ B".padEnd(17) + TYPES.map(t => t.padEnd(16)).join(""));
for (const a of TYPES) console.log(a.padEnd(17) + TYPES.map(b => tryPunch(a, b).padEnd(16)).join(""));

আউটপুট:

A \ B            full-cone       restricted      port-restricted symmetric
full-cone        direct          direct          direct          direct
restricted       direct          direct          direct          direct
port-restricted  direct          direct          direct          TURN relay
symmetric        direct          direct          TURN relay      TURN relay

চার ধরনের ষোলোটি জোড়ার মধ্যে মাত্র তিনটিতে relay লাগল: port-restricted + symmetric (দুই দিক থেকেই), আর symmetric + symmetric. কারণ symmetric NAT অপর প্রান্তের দিকে নতুন port খোলে, যা STUN জানায়নি; অপর পক্ষ port-restricted হলে সেই অচেনা port থেকে আসা packet ফেলে দেয়, আর symmetric হলে নিজেও নতুন port খোলে — কেউ কারও সঠিক port জানতে পারে না।

মজার ব্যাপার হলো restricted + symmetric জোড়া সফল: restricted cone শুধু IP মেলায়, port নয়। Symmetric-এর পেছনের B যখন নতুন port থেকে পাঠায়, A-র NAT ঢুকতে দেয় (A আগেই ওই IP-তে পাঠিয়েছে); A তখন B-র আসল নতুন port শিখে সেখানে উত্তর দেয়, আর B-র NAT-এ সেই port ঠিক A-র জন্যই খোলা। Simulator-এর মডেল সরল — বাস্তবে timing, port অনুমান আর packet হারানোও ফলে প্রভাব ফেলে। তবু মূল শিক্ষা ঠিক: যত বেশি symmetric NAT, তত বেশি TURN-এর খরচ।

৭ · Carrier-grade NAT — আপনার ISP-ও NAT করছে

IPv4 ফুরিয়ে যাওয়ার পর ISP-রা নিজেরাও যথেষ্ট public ঠিকানা পায় না — কিনতে হয় বাজার থেকে, বেশ দামে। সমাধান: ISP-র নেটওয়ার্কেই একটি বিশাল NAT বসানো, যার নাম carrier-grade NAT (CGNAT বা CGN). গ্রাহকের router-এর WAN পাশে তখন একটি public ঠিকানার বদলে আসে আরেকটি অ-public ঠিকানা, আর ISP-র CGNAT শত শত গ্রাহককে একটি public ঠিকানার পেছনে রাখে।

এজন্য RFC 6598 (২০১২) আলাদা একটি ব্লক দিয়েছে: 100.64.0.0/10, নাম “shared address space”. RFC 1918-এর ব্লক কেন নয়? কারণ গ্রাহকের বাসার ভেতরেই হয়তো 192.168.1.0/24 বা 10.0.0.0/8 চলছে; ISP-ও একই ব্লক ব্যবহার করলে router-এর দুই পাশে একই subnet পড়তে পারে, আর routing ভেঙে যায়। আলাদা ব্লক এই সংঘর্ষ এড়ায়। মোবাইল ডেটায় অপারেটররা অনেক সময় 10.x ঠিকানাও দেয় — ফোন তো নিজেই একক যন্ত্র, তার পেছনে আরেকটি বাসার LAN সাধারণত থাকে না।

  1. ল্যাপটপ192.168.1.10:50000বাসার LAN
  2. বাসার routerWAN 100.64.12.34NAT ১
  3. ISP-র CGNAT203.0.113.77NAT ২
  4. সার্ভার198.51.100.20:443ইন্টারনেট
উৎস ঠিকানা প্রতিটি অংশে
উৎস IP:port
কে কী মনে রাখল
এই public IP-র পেছনে
  1. ল্যাপটপ পাঠাল। সাধারণ packet, উৎস 192.168.1.10:50000. বাসার ভেতরের নকশা আগের মতোই।
  2. প্রথম NAT: বাসার router. উৎস বদলে হলো router-এর WAN ঠিকানা 100.64.12.34 — কিন্তু এটি public নয়, ISP-র shared ব্লকের ঠিকানা। Router-এর পাতায় “WAN IP” হিসেবে এই ঠিকানা দেখলে বুঝবেন আপনি CGNAT-এর পেছনে।
  3. দ্বিতীয় NAT: ISP-র CGNAT. ISP-র বড় যন্ত্র উৎস আবার বদলাল: 203.0.113.77:23517. এই public ঠিকানা আর port-এর একটি অংশ আপনার, বাকি port অন্য গ্রাহকদের। IPv4 → IPv4 → IPv4 — তিন ঠিকানার জগৎ, তাই নাম NAT444.
  4. সার্ভার দেখে শুধু ISP-র ঠিকানা। সার্ভারের কাছে আপনি আর আপনার এলাকার আরও শত শত গ্রাহক একই 203.0.113.77. কেউ বাইরে থেকে আপনার কাছে আসতে চাইলে দুটি NAT পেরোতে হবে, আর ISP-র NAT-এ আপনার কোনো নিয়ন্ত্রণ নেই — port forwarding অসম্ভব।

CGNAT-এর প্রভাব

নিজের সার্ভার চালানো যায় না

বাসা থেকে গেম সার্ভার, CCTV-র সরাসরি দেখা, ছোট ওয়েবসাইট — বাইরে থেকে আসা সংযোগ ISP-র NAT-এই আটকে যায়। সমাধান: ISP-র কাছে public (“real”) IP নেওয়া — অনেক ISP আলাদা ফি নিয়ে দেয় — অথবা বাইরের কোনো সার্ভারের মাধ্যমে tunnel বা relay সেবা।

inbound বন্ধ

এক ঠিকানা, অনেক মানুষ

একজন অপব্যবহার করলে ওয়েবসাইট গোটা ঠিকানা ব্লক করে, ফলে নিরীহ প্রতিবেশীরাও বারবার CAPTCHA বা নিষেধাজ্ঞা দেখেন।

shared reputation

Port-এর সীমা

একটি public ঠিকানায় প্রতি protocol-এ সাধারণত 1024–65535, অর্থাৎ ৬৪,৫১২টি port ব্যবহার হয়। ISP প্রত্যেক গ্রাহককে একটি port-ব্লক দিলে (ধরুন ২,০৪৮টি) একটি ঠিকানায় মাত্র ৩১ জন। অনেক ট্যাব আর অ্যাপ একসাথে চললে গ্রাহকের port ফুরিয়ে নতুন সংযোগ আটকাতে পারে।

৬৪,৫১২ ÷ ব্লক

Log রাখার দায়

কোনো অপরাধের তদন্তে “এই IP থেকে এসেছিল” বললে আর যথেষ্ট নয় — জানতে হয় কোন সময়ে, কোন port. তাই CGNAT চালানো ISP-কে বিপুল translation log রাখতে হয়, আর সার্ভারগুলোকেও উৎস port log করার পরামর্শ দেওয়া হয় (RFC 6302). প্রতি গ্রাহককে স্থির port-ব্লক দিলে (RFC 7422-এর মতো) log অনেক ছোট হয়।

সময় + IP + port

বাংলাদেশে মোবাইল ডেটা ব্যবহারকারীরা সাধারণভাবে CGNAT-এর পেছনে থাকেন বলে ধরে নেওয়া যায় — ফোনের সেটিংসে নিজের ঠিকানা প্রায়ই 10.x বা 100.x-এর মতো দেখা যায় — আর অনেক ব্রডব্যান্ড ISP-ও একই পথে হাঁটে। তবে এটি অপারেটর, এলাকা আর প্যাকেজ ভেদে আলাদা, আর সময়ের সাথে বদলায়। নিজের সংযোগ যাচাই করার সহজ পথ: router-এর পাতায় WAN ঠিকানা দেখুন, আর কোনো “আমার IP কত” ধরনের ওয়েবসাইটে যে ঠিকানা দেখায় তার সাথে মেলান। দুটি আলাদা হলে, বিশেষত WAN ঠিকানা 100.64.0.0/10-এর মধ্যে হলে, আপনি CGNAT-এর পেছনে।

৮ · NAT firewall নয়, protocol ভাঙে, আর end-to-end নীতির সাথে লড়াই

“NAT আছে, তাই নিরাপদ” — অর্ধেক সত্য

অংশ ৩-এর simulator-এ দেখেছেন, অনুরোধ-ছাড়া inbound packet DROP হয়। তাই অনেকে ভাবেন NAT-ই firewall. সূক্ষ্ম পার্থক্যটা বোঝা জরুরি। Stateful NAT (PAT) যা করে তা আসলে একটি পার্শ্বফল: router জানেই না packet কাকে দেবে, তাই ফেলে দেয়। এটা সত্যিকারের firewall-এর “ভেতরে শুরু হওয়া সংযোগের উত্তরই শুধু ঢুকবে” নীতির (stateful firewall, পর্ব ৪৯) সাথে মেলে বটে, কিন্তু তফাতগুলো বড়:

  • বাইরে যাওয়া কিছুই আটকায় না। ভেতরের ভাইরাস-আক্রান্ত যন্ত্র আক্রমণকারীর সার্ভারে নিজেই সংযোগ খুলতে পারে — NAT সানন্দে পার করে দেয়।
  • নিয়ম কম, নিয়ন্ত্রণ নেই। কোন সেবা, কোন ঠিকানা, কোন সময় — এমন নীতি NAT-এর কাজ নয়। Port forwarding আর UPnP নিজেই দরজা খোলে।
  • ভেতরের নেটওয়ার্ক রক্ষা করে না। একই LAN-এর যন্ত্রগুলো একে অপরের কাছে খোলা; অতিথির ফোন অফিসের প্রিন্টারে পৌঁছায়।
  • IPv6-এ NAT নেই বললেই চলে। NAT-কেই নিরাপত্তা ভাবলে IPv6 চালু হওয়ামাত্র সব যন্ত্র খোলা হয়ে যেত। এজন্য IPv6 router-এ ডিফল্ট stateful firewall — বাইরের অনুরোধ-ছাড়া সংযোগ বন্ধ — রাখার সুপারিশ আছে (RFC 6092).

যেসব protocol NAT-এ ভাঙে — আর ALG

NAT শুধু header বদলায়। কিন্তু কিছু protocol নিজের ডেটার ভেতরে IP ঠিকানা বা port লিখে পাঠায় — সেটা NAT দেখে না, বদলায়ও না। ক্লাসিক উদাহরণ FTP-র active mode: ক্লায়েন্ট সার্ভারকে PORT 192,168,1,11,195,80 কমান্ডে বলে “আমার এই ঠিকানা:port-এ ডেটা-সংযোগ খুলুন” (শেষ দুটি সংখ্যা port = ১৯৫ × ২৫৬ + ৮০ = ৫০,০০০)। সার্ভার একটি private ঠিকানায় সংযোগ খোলার চেষ্টা করে — ব্যর্থ। সমাধান দুটি: passive mode (ক্লায়েন্টই দ্বিতীয় সংযোগ শুরু করে, NAT-বান্ধব), অথবা router-এ একটি ALG (Application Layer Gateway) — যা FTP-র কমান্ড পড়ে ভেতরের ঠিকানা বদলে দেয় আর আগাম একটি সারিও বানিয়ে রাখে।

ALG ভঙ্গুর জোড়াতালি: প্রতিটি protocol-এর জন্য আলাদা কোড, এনক্রিপ্টেড ডেটায় অচল, আর ভুল ALG ভালো protocol-কেও ভাঙে। VoIP-এর SIP-এর ALG এর কুখ্যাত উদাহরণ — অনেক IP ফোন সমস্যার প্রথম পরামর্শই থাকে “router-এ SIP ALG বন্ধ করে দেখুন”. IPsec VPN-ও NAT-এ সমস্যায় পড়ে (ESP-তে port নেই, আর AH-এর integrity যাচাই IP ঠিকানাও ঢাকে), তাই এসেছে NAT-T: ESP-কে UDP port 4500-এ মুড়ে পাঠানো।

End-to-end নীতির সাথে টানাপোড়েন

পর্ব ০৩-এ দেখেছেন end-to-end principle: বুদ্ধি থাকবে দুই প্রান্তে, মাঝের নেটওয়ার্ক শুধু packet বহন করবে। মূল ইন্টারনেটে প্রতিটি যন্ত্র অন্য যেকোনো যন্ত্রের কাছে সরাসরি পৌঁছাতে পারত। NAT এই প্রতিশ্রুতি ভেঙেছে: এখন একটি middlebox header বদলায়, transport-এর অবস্থা মনে রাখে, অচেনা protocol দেখলে (যেমন TCP বা UDP নয় এমন নতুন transport) প্রায়ই ফেলে দেয়। এর একটি বড় ফল protocol-এর ossification: SCTP-র মতো নতুন transport protocol ইন্টারনেটে ছড়াতে পারেনি, আর QUIC (পর্ব ৩৩) ইচ্ছা করেই UDP-র ওপর তৈরি, যাতে বিদ্যমান NAT আর middlebox-গুলো তাকে পার করে দেয়। ক্ষতি বেশি হয়েছে peer-to-peer আর “সবাই সার্ভার” ধারণার।

দীর্ঘমেয়াদি উত্তর: IPv6

IPv6-এর ঠিকানা ১২৮ bit — ২১২৮ ঠিকানা, এত বেশি যে প্রতিটি বাসাকে সাধারণত পুরো একটি ব্লক দেওয়া হয় (ISP ভেদে /48 থেকে /64), আর প্রতিটি যন্ত্র পায় নিজের global ঠিকানা। তাই NAT-এর দরকার নেই, আর peer-to-peer আবার সরাসরি সম্ভব (firewall-এর অনুমতি সাপেক্ষে)। IPv6 পুরোপুরি না আসা পর্যন্ত দুই জগৎ পাশাপাশি চলে, আর মাঝের রূপান্তরে (NAT64, DNS64) NAT আবার অন্য রূপে ফেরে। IPv6-এর ঠিকানা, header আর রূপান্তরের কৌশল পর্ব ২১-এ।

আরও গভীরে: Linux-এ NAT সিদ্ধান্ত হয় একটি সংযোগের প্রথম packet-এ, netfilter-এর nat table-এ; পরের packet-গুলো conntrack-এর সারি থেকে সরাসরি বদলায়, নিয়ম আর দেখা হয় না — তাই নিয়ম বদলালেও চালু সংযোগে প্রভাব পড়ে না, যতক্ষণ না conntrack -D দিয়ে সারি মোছা হয়। সারির সর্বোচ্চ সংখ্যা nf_conntrack_max; ব্যস্ত সার্ভারে table ভরে গেলে kernel log-এ “table full, dropping packet” দেখা যায়। আর NAT-এর সবচেয়ে বড় বাস্তব প্রয়োগের একটি আছে আপনার চোখের সামনেই: Docker container-এর ঠিকানা 172.17.x.x, আর -p 8080:80 লিখলে Docker ঠিক এই পর্বের DNAT নিয়মই বসায় (পর্ব ৫৪)।

পরীক্ষা ও ইন্টারভিউতে এই বিষয়ে প্রায়ই যা জিজ্ঞেস করা হয়:

  • RFC 1918-এর তিনটি private ব্লক কী? — 10.0.0.0/8, 172.16.0.0/12 (172.16–172.31), 192.168.0.0/16; ইন্টারনেটে route হয় না।
  • Static NAT, dynamic NAT আর PAT-এর পার্থক্য? — এক-এক স্থায়ী, pool থেকে এক-এক ধার, আর port দিয়ে অনেক-থেকে-এক।
  • NAT router packet-এর কী কী বদলায়? — বাইরে যেতে উৎস IP (PAT-এ port-ও), ফেরার পথে গন্তব্য; সাথে IP checksum আর TCP/UDP checksum (pseudo-header-এর জন্য)।
  • STUN আর TURN-এর পার্থক্য? — STUN শুধু বাইরের ঠিকানা জানায়, ডেটা সরাসরি যায়; TURN নিজে relay হয়ে সব ডেটা বহন করে।
  • NAT কি firewall? — না; অনুরোধ-ছাড়া inbound আটকানো তার পার্শ্বফল, কিন্তু outbound বা ভেতরের ট্রাফিকের কোনো নীতি নেই।

৯ · AI-এর যুগে NAT, port forwarding আর NAT traversal

“আমার বাসার CCTV বাইরে থেকে দেখতে চাই, router-এ কী করব?” — AI দ্রুত ধাপগুলো বলে দেবে। কিন্তু AI আপনার আসল পরিস্থিতি (CGNAT আছে কি না) জানে না, আর সহজতম পথটি প্রায়ই সবচেয়ে অনিরাপদ। চেনা ভুলগুলো:

AI-এর ভুলকেন ভুলকীভাবে ধরবেন
“172.16.0.0/16 হলো private ব্লক” বা 172.32.x.x-কে private বলাআসল ব্লক /12: 172.16–172.31RFC 1918 খুলে দেখুন, নিজে bit গুনে মেলান (পর্ব ১৭)
Port forwarding-এর নির্দেশ, অথচ আপনি CGNAT-এর পেছনেISP-র NAT-এ নিয়ম লেখা আপনার হাতে নেই — কখনো কাজ করবে নাRouter-এর WAN ঠিকানা আর বাইরের দেখা ঠিকানা মিলিয়ে নিন
“DMZ চালু করুন” বা সব port forward করার পরামর্শপুরো যন্ত্র ইন্টারনেটের সামনে উন্মুক্তশুধু দরকারি একটি port, বা VPN; পরামর্শটির ঝুঁকি আলাদা করে জিজ্ঞেস করুন
“NAT আছে, firewall লাগবে না”NAT outbound বা ভেতরের ট্রাফিক নিয়ন্ত্রণ করে না; IPv6-এ NAT নেইঅংশ ৮-এর তালিকা ধরে যাচাই করুন
পুরোনো ifconfig, netstat -nat, বা iptables-কে একমাত্র পথ বলাআধুনিক Linux-এ ip, ss, conntrack, আর nftablesman nft, নিজের distro-র ডকুমেন্টেশন দেখুন
DNAT নিয়ম দিল, কিন্তু FORWARD-এর অনুমতি বা ip_forward ভুলে গেলনিয়ম থাকলেও packet পার হয় নাল্যাবে দুটি VM বা network namespace দিয়ে পরীক্ষা করুন, packet capture করুন (পর্ব ৫৫)
বানানো RFC নম্বর বা ভুল সালভাষার মডেল বিশ্বাসযোগ্য শোনানো নম্বর বানাতে পারেrfc-editor.org-এ শিরোনাম মেলান: STUN 8489, TURN 8656, ICE 8445, CGNAT ব্লক 6598

AI-কে NAT-এর কাজ দিলে নিজের পরিস্থিতি আর নিরাপত্তার শর্ত স্পষ্ট করে দিন:

আমার বাসার router: [মডেল আর firmware এখানে লেখো]। Router-এর WAN ঠিকানা [এখানে লেখো], আর বাইরের ওয়েবসাইটে দেখা ঠিকানা [এখানে লেখো]। আমি LAN-এর 192.168.1.50-এ চলা একটি ওয়েব সার্ভার বাইরে থেকে দেখাতে চাই। ১. আগে বলো দুটি ঠিকানা দেখে আমি CGNAT-এর পেছনে কি না, আর কেন। ২. CGNAT না হলে শুধু একটি port (TCP 8080 → 192.168.1.50:80) forward করার ধাপ দাও; DMZ বা UPnP-এর পরামর্শ দেবে না। ৩. Linux router হলে nftables দিয়ে নিয়ম লেখো, প্রতিটি লাইনের মানে বাংলায় ব্যাখ্যা করো, আর ip_forward ও forward chain-এর অনুমতি ভুলবে না। ৪. এই port খোলার ঝুঁকি আর নিরাপদ বিকল্প (VPN) কী, তা আলাদা করে বলো। ৫. কোনো RFC-র উল্লেখ করলে নম্বর আর শিরোনাম দাও; নিশ্চিত না হলে স্পষ্ট বলো।

AI-এর NAT পরামর্শ প্রয়োগের আগে — চেকলিস্ট

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।

প্র ০১NAT-কে “স্বল্পমেয়াদি” সমাধান বলা হয়েছিল ১৯৯৪ সালে। তিন দশক পরেও এটি কেন টিকে আছে, আর এটি কি IPv6-কে দেরি করিয়ে দিয়েছে?

RFC 1631-এর লেখকেরা NAT-কে দেখেছিলেন একটি সেতু হিসেবে — নতুন বড় ঠিকানার protocol তৈরি আর চালু হওয়া পর্যন্ত সময় কেনার উপায়। IPv6-এর মূল নির্দিষ্টকরণ এসেছিল ১৯৯৫ সালেই (RFC 1883), পরে ১৯৯৮ সালে RFC 2460 আর ২০১৭ সালে পূর্ণ ইন্টারনেট মান হিসেবে RFC 8200. অথচ বিশ্বজুড়ে IPv6-এর ব্যবহার উল্লেখযোগ্য হতে শুরু করে ২০১০-এর দশকে, আর আজও অনেক নেটওয়ার্ক শুধু IPv4-এ চলে।

কারণটা অর্থনীতির। NAT-এর খরচ বহন করে না সেই প্রতিষ্ঠান, যে এটি বসায়। একটি অফিস বা ISP একটি NAT বসিয়ে সঙ্গে সঙ্গে সমস্যা মেটায়; কোনো সমন্বয় লাগে না, অন্য কারও কিছু বদলাতে হয় না। IPv6-এর জন্য দরকার ছিল সবার একসাথে বদলানো — router, OS, অ্যাপ, ISP, কনটেন্ট — আর প্রথম যিনি বদলাবেন তিনি একাই খরচ বহন করবেন, সুবিধা পাবেন না, কারণ অন্যরা তখনো IPv4-এ। এটি একটি ক্লাসিক “সমন্বয়ের সমস্যা”.

NAT তাই সত্যিই IPv6-এর তাড়া কমিয়েছিল — ঠিকানার ঘাটতির ব্যথা অনুভূত হয়নি। কিন্তু উল্টো দিকটাও ভাবার মতো: NAT না থাকলে নব্বই আর দুই হাজারের দশকে ইন্টারনেটের বিস্ফোরক বৃদ্ধি, প্রতিটি বাসায় Wi-Fi, প্রতিটি হাতে ফোন — এগুলো IPv4-এর ঠিকানার অভাবে আটকে যেত, অথবা ঠিকানা হতো অত্যন্ত দামি। ঠিকানা ফুরানোর পর CGNAT আর ঠিকানা কেনাবেচার বাজার এসে IPv4-এর খরচ বাড়িয়েছে, আর তখনই বড় মোবাইল অপারেটর আর কনটেন্ট প্রতিষ্ঠানগুলো IPv6-এ গুরুত্ব দিতে শুরু করে — কারণ এখন IPv6 চালানো CGNAT-এর চেয়ে সস্তা হতে পারে।

মূল উপলব্ধি: প্রযুক্তি বদলায় যখন পুরোনো পথের খরচ নতুন পথের খরচকে ছাড়িয়ে যায়। NAT ছিল স্থানীয়ভাবে সস্তা, বৈশ্বিকভাবে ব্যয়বহুল একটি সমাধান — আর সেই বৈশ্বিক খরচ (ভাঙা P2P, জটিলতা, CGNAT) জমতে জমতে শেষে IPv6-এর পক্ষে যুক্তি তৈরি করেছে।

প্র ০২অনেক নেটওয়ার্ক প্রশাসক বলেন, “IPv6-এ NAT নেই, তাই IPv6 কম নিরাপদ।” এই যুক্তি কোথায় ঠিক আর কোথায় ভুল?

যুক্তিটির ঠিক অংশ হলো অভিজ্ঞতা: IPv4-এর বাসা আর অফিসে PAT থাকায় বহু বছর ধরে ভেতরের যন্ত্রগুলো বাইরে থেকে সরাসরি পৌঁছানো যেত না। দুর্বল প্রিন্টার, পুরোনো Windows, পাসওয়ার্ডহীন ফাইল-শেয়ার — এগুলো NAT-এর আড়ালে থেকে বেঁচে গেছে। IPv6-এ যদি প্রতিটি যন্ত্রের global ঠিকানা থাকে আর router কিছুই না আটকায়, তবে সেই আড়াল সত্যিই চলে যায়।

কিন্তু যুক্তির ভুল অংশ মৌলিক: সুরক্ষা আসছিল NAT থেকে নয়, NAT-এর ভেতরের অবস্থা মনে রাখা (state) থেকে — “ভেতর থেকে শুরু হওয়া কথোপকথনের উত্তরই শুধু ঢুকবে।” এটাই stateful firewall-এর মূল নিয়ম, আর এটি ঠিকানা না বদলিয়েও প্রয়োগ করা যায়। IETF ২০১১ সালে RFC 6092-এ বাসার IPv6 router-এর জন্য ঠিক এই ডিফল্ট আচরণের সুপারিশ করেছে: ভেতর থেকে শুরু হওয়া সংযোগ চলবে, বাইরে থেকে অনুরোধ-ছাড়া সংযোগ বন্ধ। আধুনিক বাসার router আর মোবাইল নেটওয়ার্ক সাধারণত তাই করে।

উল্টো দিকে, NAT-কে নিরাপত্তা ভাবা ক্ষতিও করেছে। এটি outbound কিছুই আটকায় না, ফলে ভেতরের আক্রান্ত যন্ত্র নিজেই বাইরের নিয়ন্ত্রণ-সার্ভারে সংযোগ খোলে — আধুনিক ম্যালওয়্যার ঠিক এভাবেই কাজ করে। UPnP দিয়ে যন্ত্র নিজেই দরজা খোলে। আর IPv4-এ “NAT আছে তো” ভেবে ভেতরের নেটওয়ার্কে আলাদা সুরক্ষা বা ভাগ (VLAN, পর্ব ১৩) না রাখায় একবার কেউ ঢুকলে সব খোলা। IPv6-এ ঠিকানার পরিসর এত বড় (একটি /64-এ ২৬৪ ঠিকানা) যে অন্ধভাবে স্ক্যান করে যন্ত্র খোঁজা IPv4-এর চেয়ে অনেক কঠিন — যদিও আক্রমণকারী DNS বা অন্য সূত্রে ঠিকানা পেতে পারে, তাই এটিকেও একমাত্র সুরক্ষা ভাবা যায় না।

মূল উপলব্ধি: নিরাপত্তা আসে ইচ্ছাকৃত নীতি থেকে — stateful filtering, ভেতরের ভাগ, হালনাগাদ সফটওয়্যার — কোনো ঠিকানা-কৌশলের পার্শ্বফল থেকে নয়। IPv6-এ সেই নীতি স্পষ্টভাবে বসাতে হয়, আর সেটা NAT-এর চেয়ে পরিষ্কার নকশা।

প্র ০৩UDP hole punching প্রথম শুনলে “হ্যাক”-এর মতো লাগে। এটি কীভাবে মূলধারায় এল, আর আজকের ভিডিও কল অ্যাপগুলো TURN-এর খরচ নিয়ে কী ভাবে?

দুই হাজারের দশকের শুরুতে peer-to-peer ফাইল-শেয়ারিং, অনলাইন গেম আর ইন্টারনেট ফোন জনপ্রিয় হচ্ছিল, অথচ ব্যবহারকারীরা প্রায় সবাই বাসার NAT-এর পেছনে। ডেভেলপাররা লক্ষ করলেন, বেশিরভাগ NAT একটি ভেতরের port থেকে যাওয়া সব packet-কে একই বাইরের port দেয়, আর নিজের পাঠানো গন্তব্যের উত্তর ঢুকতে দেয়। দুজন একসাথে পাঠালে দুই দিকের দরজাই খুলে যায়। কৌশলটি NAT-এর কোনো ত্রুটি কাজে লাগায় না — NAT ঠিক যা করার কথা তাই করে; দুজনের প্রত্যেকে নিজে থেকে “বাইরে” পাঠাচ্ছেন, তাই উত্তর ঢুকছে।

২০০৫ সালে Bryan Ford, Pyda Srisuresh আর Dan Kegel USENIX-এ “Peer-to-Peer Communication Across Network Address Translators” প্রবন্ধে পদ্ধতিটি গুছিয়ে বর্ণনা করেন, আর জানান তাঁদের পরীক্ষায় বেশিরভাগ NAT UDP hole punching সমর্থন করেছে। IETF পরে RFC 5128 (২০০৮)-এ বিষয়টি লিপিবদ্ধ করে, আর STUN, TURN আর ICE মিলিয়ে একটি মানসম্মত কাঠামো দাঁড়ায়। ২০১০-এর দশকে WebRTC ব্রাউজারেই ICE এনে দেয়, ফলে আজ ব্রাউজারের ভিডিও মিটিং, অনেক মেসেজিং অ্যাপের কল আর স্ক্রিন-শেয়ার — সবাই এই কৌশলের ওপর দাঁড়িয়ে।

TURN-এর অর্থনীতি এখানে গুরুত্বপূর্ণ। সরাসরি পথে দুজনের ভিডিও অ্যাপ প্রতিষ্ঠানের এক বাইটও খরচ করে না; TURN-এ প্রতিটি কলের পুরো ভিডিও প্রতিষ্ঠানের সার্ভার দিয়ে দুবার যায় (ঢোকা আর বেরোনো)। তাই ICE সবসময় আগে সরাসরি পথ চেষ্টা করে। কিন্তু কিছু অফিসের firewall UDP-ই বন্ধ রাখে, আর symmetric NAT বা কড়া CGNAT-এ সরাসরি পথ খোলে না — তখন TURN, কখনো TCP বা TLS-এর ওপর port 443 দিয়ে, যাতে ওয়েবের মতো দেখায়। বড় গ্রুপ কলে আবার অনেক অ্যাপ peer-to-peer ছেড়ে কেন্দ্রীয় media সার্ভার ব্যবহার করে, কারণ দশজনের প্রত্যেককে আলাদা ভিডিও পাঠানো ব্যবহারকারীর upload-এ কুলায় না।

মূল উপলব্ধি: Hole punching NAT-এর নিয়ম ভাঙে না, নিয়মের ভেতরেই দুই দিক থেকে সমন্বয় করে। বাস্তবের সিস্টেম তাই স্তরে স্তরে চেষ্টা করে — সরাসরি, STUN, তারপর relay — আর প্রতিটি স্তরের একটি খরচ আছে।

প্র ০৪CGNAT-এর পেছনে একই public IP শত শত মানুষের। এতে আইন-শৃঙ্খলা, ব্যবসা আর সাধারণ ব্যবহারকারীর ওপর কী ধরনের প্রভাব পড়ে, আর প্রকৌশলীরা কীভাবে তা সামলান?

পুরোনো ইন্টারনেটে একটি IP ঠিকানা আর একটি সময় জানলেই ISP বলতে পারত কোন গ্রাহক সংযুক্ত ছিলেন। CGNAT-এ সেই সূত্র ভেঙে যায়: একই সময়ে একই ঠিকানা হয়তো কয়েকশো গ্রাহকের। কোনো সাইবার অপরাধের তদন্তে শুধু “IP আর সময়” দিয়ে আর মানুষ চেনা যায় না — লাগে উৎস port, আর খুব সঠিক সময় (সার্ভার আর ISP-র ঘড়ির পার্থক্যও সমস্যা হতে পারে)। এজন্য RFC 6302 (২০১১) ইন্টারনেটমুখী সার্ভারগুলোকে উৎস port আর সঠিক সময় log করার সুপারিশ করে। আর ISP-কে রাখতে হয় প্রতিটি translation-এর রেকর্ড — একটি বড় নেটওয়ার্কে দিনে কোটি কোটি সারি, যার সংরক্ষণ আর খোঁজা নিজেই একটি প্রকৌশল সমস্যা।

প্রকৌশলীদের একটি কৌশল port-ব্লক বরাদ্দ: প্রতিটি কথোপকথন আলাদা log না করে প্রতিটি গ্রাহককে একটি port-এর ব্লক দেওয়া (যেমন 20480–22527), আর শুধু “এই গ্রাহক এই সময় থেকে এই ব্লক পেলেন” লেখা। আরও এগিয়ে RFC 7422 (২০১৪) deterministic mapping-এর কথা বলে — একটি সূত্রে ভেতরের ঠিকানা থেকেই বাইরের ঠিকানা আর port-ব্লক ঠিক হয়, ফলে প্রায় কোনো log লাগে না। দাম হলো নমনীয়তা: কারও বেশি port লাগলেও ব্লকের বাইরে যেতে পারেন না।

ব্যবহারকারীর দিক থেকে প্রভাব বাস্তব। একই ঠিকানার কেউ স্প্যাম পাঠালে ওয়েবসাইট পুরো ঠিকানা ব্লক করে, আর নিরীহ প্রতিবেশীরা CAPTCHA-র চক্করে পড়েন। ছোট উদ্যোক্তা বাসা থেকে সার্ভার চালাতে পারেন না, গেমাররা “strict NAT”-এর সমস্যায় পড়েন। এজন্যই অনেক ISP চায় যত বেশি ট্রাফিক সম্ভব IPv6-এ যাক — বড় কনটেন্ট প্রতিষ্ঠানগুলো IPv6 সমর্থন করলে সেই ট্রাফিক CGNAT এড়িয়ে যায়, যন্ত্রের ওপর চাপ কমে।

মূল উপলব্ধি: ঠিকানা ভাগ করা শুধু প্রযুক্তিগত সিদ্ধান্ত নয় — এটি জবাবদিহি, ব্যবসা আর ব্যবহারকারীর স্বাধীনতাকে বদলায়। CGNAT সময় কেনে, কিন্তু সেই সময়ের খরচ log, জটিলতা আর হারানো সুবিধায় শোধ করতে হয়।

প্র ০৫End-to-end নীতির প্রবক্তারা NAT-কে ইন্টারনেটের নকশার “বিশ্বাসঘাতকতা” বলেছেন। NAT কীভাবে নতুন protocol চালু করা কঠিন করেছে, আর QUIC-এর নকশা এর কী জবাব দেয়?

Jerome Saltzer, David Reed আর David Clark ১৯৮৪ সালে “End-to-End Arguments in System Design” প্রবন্ধে যুক্তি দেন: যে কাজ শুধু দুই প্রান্তের অ্যাপ্লিকেশনই ঠিকমতো করতে পারে, তা মাঝের নেটওয়ার্কে রাখলে লাভ সামান্য, ক্ষতি বেশি। ইন্টারনেটের সাফল্যের বড় কারণ এই সরলতা — router শুধু IP header দেখে, তাই নতুন অ্যাপ বা নতুন transport চালু করতে কারও অনুমতি লাগে না। RFC 2993 (২০০০) NAT-এর এই স্থাপত্যগত প্রভাবগুলো বিস্তারিত তুলে ধরে।

NAT এই সরলতা ভেঙেছে কয়েক দিক থেকে। প্রথমত, NAT-কে transport header বুঝতে হয় — port ছাড়া PAT হয় না। তাই NAT শুধু TCP, UDP আর ICMP চেনে; নতুন কোনো transport protocol (যেমন SCTP, যা ২০০০ সালে মান হয়েছিল আর টেলিফোন নেটওয়ার্কের ভেতরে ব্যবহৃত হয়) বাসার NAT পেরোতে পারে না, কারণ NAT জানে না তার port কোথায়। দ্বিতীয়ত, NAT আর অন্য middlebox TCP-র অজানা option বা অস্বাভাবিক আচরণ দেখলে অনেক সময় packet ফেলে দেয়, ফলে TCP-র নতুন বৈশিষ্ট্য (যেমন Multipath TCP) চালু করতে নকশাকারীদের পুরোনো middlebox-এর সাথে খাপ খাওয়ানোর অনেক কৌশল যোগ করতে হয়েছে। ফল: ইন্টারনেট “জমে” গেছে — শুধু TCP আর UDP-ই চলে।

QUIC (পর্ব ৩৩) এর একটি বাস্তববাদী জবাব। এটি UDP-র ওপর চলে, কারণ UDP প্রায় সব NAT পেরোয়। আর QUIC তার প্রায় সব header এনক্রিপ্ট করে, যাতে middlebox-গুলো ভেতরে কী আছে দেখে কোনো ধারণা তৈরি করতে না পারে — ভবিষ্যতে protocol বদলালেও মাঝের যন্ত্র যেন বাধা না হয়। QUIC-এর connection ID-ও NAT-এর একটি সমস্যার জবাব: NAT timeout-এ বা Wi-Fi থেকে মোবাইল ডেটায় গেলে বাইরের ঠিকানা:port বদলে যায়, TCP সংযোগ তখন ভেঙে যায়, কিন্তু QUIC connection ID দিয়ে একই সংযোগ চিনে নিতে পারে।

মূল উপলব্ধি: মাঝের নেটওয়ার্ক যত বেশি “বুদ্ধিমান” হয়, প্রান্তের উদ্ভাবন তত কঠিন হয়। আধুনিক protocol-নকশা তাই middlebox-কে অন্ধ রাখতে এনক্রিপশনকে শুধু গোপনীয়তার জন্য নয়, ভবিষ্যতে বদলানোর স্বাধীনতার জন্যও ব্যবহার করে।

অনুশীলন

খাতা-কলম নিন — table-এর সারি আর port ধরে ধরে হিসাব করুন।

  1. হিসাব (CGNAT-এর port): একটি ISP প্রতিটি public ঠিকানার 1024–65535 পরিসরের port ব্যবহার করে, আর প্রতিটি গ্রাহককে ২,০৪৮টি port-এর একটি ব্লক দেয়। (ক) একটি public ঠিকানায় কতজন গ্রাহক? (খ) ৫,০০০ গ্রাহকের জন্য কমপক্ষে কতটি public ঠিকানা লাগবে? (গ) CGNAT না থাকলে কতটি লাগত?

    (ক) ব্যবহারযোগ্য port = ৬৫,৫৩৫ − ১,০২৪ + ১ = ৬৪,৫১২. ব্লক ৬৪,৫১২ ÷ ২,০৪৮ = ৩১.৫, কিন্তু অর্ধেক ব্লক দেওয়া যায় না — তাই ৩১ জন (৩১ × ২,০৪৮ = ৬৩,৪৮৮; বাকি ১,০২৪টি port অব্যবহৃত বা অন্য কাজে)।

    (খ) ৫,০০০ ÷ ৩১ = ১৬১.২৯…, তাই উপরের দিকে গোল করে ১৬২টি ঠিকানা (১৬১টিতে ৪,৯৯১ জন হয়, ৯ জন বাদ পড়েন; ১৬২টিতে ৫,০২২ জনের জায়গা)। (গ) CGNAT ছাড়া প্রত্যেকের একটি করে: ৫,০০০টি — প্রায় ৩১ গুণ বেশি। এটাই CGNAT-এর অর্থনীতি। দাম: প্রত্যেক গ্রাহক একসাথে সর্বোচ্চ ২,০৪৮টি TCP সংযোগ (আর আলাদাভাবে UDP-তে) খুলতে পারেন; বেশি হলে নতুন সংযোগ আটকায়।

  2. আউটপুট অনুমান করুন: অংশ ৩-এর PAT simulator-এ শুধু প্রথম লাইনের udp: 30 বদলে udp: 60 করা হলো। t=40-এর লাইনগুলো আর শেষ table কেমন হবে?
    t=40 IN  udp 198.51.100.53:53 -> 203.0.113.5:41000  rewritten dst = 192.168.1.12:41000
      proto pub-port  inside              remote               last
      tcp   50000     192.168.1.10:50000  198.51.100.20:443    t=3
      tcp   50001     192.168.1.11:50000  198.51.100.20:443    t=4
      udp   41000     192.168.1.12:41000  198.51.100.53:53     t=40

    DNS-এর সারি শেষ ব্যবহৃত হয়েছিল t=2-এ; t=40-এ নীরবতা ৩৮ সেকেন্ড, যা নতুন timeout ৬০-এর কম। তাই “expired” লাইন আর ছাপা হয় না, উত্তর মিলে যায় আর 192.168.1.12:41000-এ পৌঁছায়, আর সারির সময় t=40-এ হালনাগাদ হয় — শেষ table-এ এখন তিনটি সারি। বড় timeout-এ দেরিতে আসা উত্তর টিকে যায়, কিন্তু table-এ বেশি সারি আর বেশি memory লাগে।

  3. কমান্ড লিখুন: একটি Linux যন্ত্রকে router বানাতে চান: LAN eth1 (10.10.0.0/24), WAN eth0. (ক) kernel-এ forwarding চালু করুন। (খ) nftables দিয়ে LAN-এর জন্য masquerade লিখুন। (গ) বাইরের TCP 2222 ভেতরের 10.10.0.20-এর SSH (port 22)-এ forward করুন।
    # উদাহরণ — root লাগে, শুধু নিজের ল্যাব বা VM-এ
    # (ক)
    sudo sysctl -w net.ipv4.ip_forward=1
    # (খ)
    sudo nft add table ip nat
    sudo nft add chain ip nat postrouting '{ type nat hook postrouting priority srcnat; }'
    sudo nft add rule ip nat postrouting ip saddr 10.10.0.0/24 oifname "eth0" masquerade
    # (গ)
    sudo nft add chain ip nat prerouting '{ type nat hook prerouting priority dstnat; }'
    sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 2222 dnat to 10.10.0.20:22

    খেয়াল করুন: masquerade বসে postrouting-এ (packet বেরোনোর ঠিক আগে, উৎস বদল), DNAT বসে prerouting-এ (routing সিদ্ধান্তের আগে, গন্তব্য বদল)। যন্ত্রে যদি filter table-এ forward chain-এর ডিফল্ট নীতি drop হয়, তবে নতুন DNAT সংযোগ আর চালু সংযোগের উত্তর অনুমতি দিতে আলাদা নিয়ম লাগবে (পর্ব ৪৯)। sysctl -w রিবুটে হারায়; স্থায়ী করতে /etc/sysctl.d/-এ ফাইল রাখতে হয়। SSH বাইরে খোলা রাখলে পাসওয়ার্ড বন্ধ করে key-ভিত্তিক login রাখাই নিরাপদ।

  4. হাতে হিসাব (incremental checksum): একটি IPv4 header-এর checksum 0x327b, উৎস ঠিকানা 192.168.1.11 (শব্দ দুটি c0a8 আর 010b). NAT উৎস বদলে করল 203.0.113.5. শুধু RFC 1624-এর সূত্র দিয়ে নতুন checksum বের করুন। তারপর: যদি NAT শুধু উৎস port বদলায় (IP নয়), IP header-এর checksum কি বদলাতে হবে?

    নতুন শব্দ: 203 = 0xcb, 0 = 0x00, 113 = 0x71, 5 = 0x05 → cb00 আর 7105. ধাপগুলো (সব hex): ~HC = ~327b = cd84. যোগ: cd84 + 3f57 (= ~c0a8) = 10cdb; + cb00 = 1d7db; + fef4 (= ~010b) = 2d6cf; + 7105 = 347d4. ১৬ bit-এর বাইরের 3 নিচে যোগ: 47d4 + 3 = 47d7. উল্টালে ~47d7 = b828. অংশ ৪-এর কোডের “full recompute”-এর সাথে হুবহু মেলে।

    দ্বিতীয় প্রশ্ন: শুধু port বদলালে IP header-এর কোনো ঘর বদলায় না (port আছে TCP/UDP header-এ), তাই IP checksum অপরিবর্তিত — কিন্তু TCP/UDP checksum বদলাতে হবে, কারণ port সেই checksum-এর অংশ। উল্টোটা আরও গুরুত্বপূর্ণ: শুধু IP বদলালেও TCP/UDP checksum বদলাতে হয়, pseudo-header-এর কারণে। (বাস্তবে router TTL-ও কমায়, তাই IP checksum প্রতি hop-এ এমনিতেই হালনাগাদ হয়।)

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমদুটি cone NAT-এর পেছনের দুই যন্ত্র UDP hole punching করে সরাসরি সংযোগ বানাচ্ছে — ঘটনাগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. প্রত্যেকে STUN সার্ভারে UDP পাঠিয়ে নিজের বাইরের IP:port জেনে নেয়
  2. Signaling server-এর মাধ্যমে দুজন নিজেদের বাইরের ঠিকানা বিনিময় করে
  3. প্রথম যন্ত্র অপরের বাইরের ঠিকানায় পাঠায়; নিজের NAT-এ ফুটো খোলে, অপর NAT-এ packet ফেলে দেওয়া হয়
  4. দ্বিতীয় যন্ত্র পাঠায়; প্রথম NAT ঢুকতে দেয়, কারণ সেই ঠিকানায় আগেই পাঠানো হয়েছে
  5. দুই দিকে পথ খোলা; NAT-এর সারি বাঁচিয়ে রাখতে দুজনে নিয়মিত keepalive পাঠায়

নিচের কোন IPv4 ঠিকানাটি RFC 1918-এর private ঠিকানা নয়?

  • 10.200.5.1
  • 172.31.0.9
  • 172.32.1.1
  • 192.168.100.200

একটি PAT router-এর public ঠিকানা 203.0.113.5. ভেতরের 192.168.1.11:50000 থেকে 198.51.100.20:443-এ একটি TCP packet গেল, আর router সেটিকে 203.0.113.5:50001 করে পাঠাল। সার্ভারের উত্তর router-এ পৌঁছানোর সময় তার উৎস আর গন্তব্য কী?

  • উৎস 198.51.100.20:443, গন্তব্য 192.168.1.11:50000
  • উৎস 198.51.100.20:443, গন্তব্য 203.0.113.5:50001
  • উৎস 198.51.100.20:443, গন্তব্য 203.0.113.5:50000
  • উৎস 203.0.113.5:443, গন্তব্য 198.51.100.20:50001

একটি NAT router শুধু IPv4 উৎস ঠিকানা বদলায়, port নয়। কোন checksum হালনাগাদ করতে হবে?

  • শুধু IP header-এর checksum
  • শুধু TCP/UDP checksum
  • কোনোটিই না, কারণ port অপরিবর্তিত
  • IP header-এর checksum আর TCP/UDP checksum দুটিই

A একটি port-restricted cone NAT-এর পেছনে, B একটি symmetric NAT-এর পেছনে। দুজন STUN আর UDP hole punching দিয়ে সরাসরি সংযোগ চেষ্টা করলে সাধারণত কী হয়?

  • সরাসরি পথ খোলে না; TURN relay লাগে
  • প্রথম চেষ্টাতেই সরাসরি সংযোগ হয়
  • STUN সার্ভার দুজনের ডেটা relay করে
  • UDP বাদ দিয়ে TCP ব্যবহার করলেই সরাসরি সংযোগ হয়

একজন গ্রাহকের বাসার router-এর WAN ঠিকানা 100.72.18.40, অথচ কোনো ওয়েবসাইট তাঁর ঠিকানা দেখাচ্ছে 203.0.113.77. এর সবচেয়ে সম্ভাব্য অর্থ কী?

  • ঠিকানাটি RFC 1918-এর private ঠিকানা, ভুল কনফিগারেশন
  • গ্রাহক ISP-র carrier-grade NAT-এর পেছনে; port forwarding দিয়ে বাইরে থেকে আসা সংযোগ পাওয়া যাবে না
  • WAN ঠিকানাটি public, ওয়েবসাইটটি ভুল দেখাচ্ছে
  • Router loopback ঠিকানা দেখাচ্ছে

“আমাদের অফিসে PAT আছে, তাই firewall লাগবে না” — এই দাবির সবচেয়ে বড় দুর্বলতা কোনটি?

  • PAT সব inbound packet ভেতরে ঢুকতে দেয়
  • PAT ডেটা এনক্রিপ্ট করে না
  • PAT outbound আর ভেতরের ট্রাফিকে কোনো নীতি প্রয়োগ করে না, আর port forwarding বা UPnP-এ খোলা দরজা নিয়ন্ত্রণ করে না
  • PAT শুধু TCP-তে কাজ করে

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. Private ব্লক: 10.0.0.0/8, 172.16.0.0/12 (172.16–172.31), 192.168.0.0/16 — ইন্টারনেটে route হয় না; CGNAT-এর জন্য আলাদা 100.64.0.0/10.
  2. NAT = উৎস বদল + table + ফেরার পথে উল্টো বদল. PAT port দিয়ে অনেক যন্ত্রকে এক public ঠিকানায় রাখে; সারি না থাকলে inbound packet DROP. IP আর TCP/UDP দুটি checksum-ই হালনাগাদ হয় (RFC 1624-এর ~HC + ~m + m′)।
  3. Port forwarding = DNAT (গন্তব্য বদল, prerouting); masquerade = SNAT (উৎস বদল, postrouting); conntrack প্রথম packet-এর পরে সব মনে রাখে। UDP-র timeout ছোট, তাই keepalive.
  4. NAT traversal: STUN বাইরের ঠিকানা জানায়, hole punching দুই দিক থেকে দরজা খোলে, TURN relay করে, ICE সব মিলিয়ে সেরা পথ বাছে। Symmetric NAT-এ সাধারণত relay.
  5. NAT firewall নয়, protocol ভাঙে (FTP active, SIP — ALG), end-to-end নীতি দুর্বল করে; CGNAT-এ সার্ভার চালানো যায় না, port আর log-এর সমস্যা। দীর্ঘমেয়াদি সমাধান IPv6.

পরের পর্বে: network স্তরের বার্তাবাহক — ICMP. ping আসলে কী পাঠায়, traceroute কীভাবে TTL দিয়ে পথের প্রতিটি router খুঁজে বের করে, আর “destination unreachable” বা “fragmentation needed”-এর মতো ত্রুটির বার্তা কেন নেটওয়ার্কের জন্য অপরিহার্য।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান