Foundationপ্রথম নীতি থেকে
LEVEL 7লেসন ৬/২২কঠিন৪৫ মিনিট

IPv6 — 128-bit ঠিকানা ও নতুন header-এর দর্শন

IPv6 Addressing and Header Design

৪.৩ বিলিয়ন ঠিকানা ফুরিয়ে গেল যখন, ইন্টারনেট নতুন ঠিকানা-দর্শন নিল — 128-bit, fixed 40-byte header, checksum-শূন্য forwarding, আর broadcast-বিহীন এক নতুন জগৎ।

এই লেসন শেষে আপনি পারবেন

  • IPv6 address-এর anatomy বর্ণনা করতে পারবেন — hextet, :: compression-এর তিনটা নিয়ম, /64 boundary-র দুই ভাগ — আর যেকোনো ঠিকানা RFC 5952 canonical form-এ লিখতে পারবেন
  • IPv4-এর ঠিকানা-সংকটের প্রকৃত সংখ্যা দিয়ে exhaustion-এর গল্প বলতে ও 128-bit কী মাপের জায়গা তা অনুভবযোগ্য উপমায় ব্যাখ্যা করতে পারবেন
  • IPv4 আর IPv6 header পাশাপাশি রেখে বলতে পারবেন কী ফেলা হয়েছে (checksum, router fragmentation, options) এবং প্রতিটা বাদের নিরাপত্তা-যুক্তি দিতে পারবেন
  • SLAAC-এর দুই পথ — EUI-64 আর privacy extensions — হাতে-হাতে compare করে MAC-derived ঠিকানার privacy ঝুঁকি বলতে পারবেন
  • Link-local fe80::-এর ভূমিকা, multicast/anycast-এর broadcast-প্রতিস্থাপন, আর dual-stack/tunneling/NAT64 transition-পথগুলো আলাদা করে চিনতে পারবেন

আগে যা বোঝা থাকা দরকার

আগে এটা বুঝি

গত লেসনে দেখলাম CIDR ঠিকানা-অপচয় কমিয়েছে — কিন্তু অপচয় কমানো আর সৃষ্টি করা এক কথা নয়। IPv4-এর মোট জলখাবার ঠিকানা 2^32 ≈ ৪.২৯ বিলিয়ন। আজ পৃথিবীতে মাথাপিছু একাধিক internet-connected device — phone, laptop, TV, bulb, meter — সব মিলিয়ে device-সংখ্যা এই সংখ্যাকে অনেক আগেই টপকেছে। ফলাফল ইতিহাসে লেখা আছে: ৩ ফেব্রুয়ারি 2011 IANA-র মুক্ত ঠিকানা-pool আনুষ্ঠানিকভাবে শেষ; ২০১১–২০২০-এর মধ্যে পাঁচটা regional registry-র সঞ্চয়ও ফুরোয়। NAT (আসছে কয়েক লেসন পরে) দিন গড়িয়ে দিল, কিন্তু hack-টা স্থায়ী সমাধান হতে পারে না — end-to-end connectivity তো তার খুন হয়।

আসল সমাধান হলো ঠিকানা-জগতটাই নতুন করে ভাবা: IPv6, 128-bit ঠিকানা। কত বড় সংখ্যা? 2^128 ≈ 340 undecillion — পৃথিবীর সব land-area-কে মিলিয়ে হিসাব করলে প্রতি বর্গমিটার ভূপৃষ্ঠে প্রায় ৬৬ হাজার কোটি ঠিকানা। এখন আর ঠিকানা বাঁচানোর চিন্তা নেই — তাই ডিজাইনাররা সুযোগটাকে দর্শন-পরিবর্তন হিসেবে নিয়েছেন: যা IPv4-এ patch-করে টানানো হয়েছিল, তা সব ভেতর থেকে ঠিক করা।

আজকের লেসনের map:

  • 128-bit ঠিকানা লেখা-পড়ার নিয়ম — :: compression-এর শাসন
  • নতুন header: কী ফেলে দেওয়া হলো, আর কেন ফেলা নিরাপদ
  • SLAAC: router-এর অনুমতিতে self-configured ঠিকানা, আর তার privacy
  • Broadcast-এর মৃত্যু, link-local-এর দৈনন্দিন ভূমিকা
  • Transition: পুরনো জগতের সাথে সহাবস্থানের তিন কৌশল

মূল ধারণা

ঠিকানা-anatomy — আটটা hextet

IPv6 ঠিকানা ১২৮ bit, লেখা হয় ৮টা 16-bit group-এ — নাম hextet — hexadecimal-এ, প্রতিটার মাঝে colon:

2001:0db8:0000:0000:0000:ff00:0042:8329
└─┬─┘ └─┬─┘ └─┬─┘ ...
 hextet  hextet  ...        ৮ × 16 bit = 128 bit

Hex-এ 16-bit মানে ঠিক ৪ digit — এজন্যই hex বেছে নেওয়া; decimal- এ 39-digit সংখ্যা লিখে কেউ বাঁচবে না। Leading zeros বাদ দেওয়া যায় (0db8 → db8), আর টানা শূন্য hextet-দের একবার গুটিয়ে :: লেখা যায়:

2001:0db8:0000:0000:0000:ff00:0042:8329
        ↓
2001:db8::ff00:42:8329

Edge cases দেখুন — নিয়মগুলো কাজে নামে এভাবেই:

2001:db8:0:0:1:0:0:1     →  দুইটা সম-দৈর্ঘ্যর run (দুই-দুটো hextet)
                            → বাঁ-দিকেরটা গুটায়: 2001:db8::1:0:0:1
2001:db8:0001:0001:0001:0001:0000:0000
                         →  trailing run: 2001:db8:1:1:1:1::
0:0:0:0:0:0:0:1          →  loopback:  ::1
0:0:0:0:0:0:0:0          →  unspecified: ::

দুই ভাগের ঠিকানা — prefix আর interface ID

CIDR-এর সেই ভাবনা এখানেও — বরং আরও কড়াভাবে: প্রায় সব unicast ঠিকানা /64-এ ভাগ হয়:

2001:db8:1234:5678 : 0000:0000:0000:abcd
└────── network /64 ───┘└── interface ID /64 ──┘
     (routing prefix)      (device-এর নিজস্ব অর্ধেক)

প্রথম অর্ধেক routing — ISP আপনার site/home-কে দেয় /48 বা /56, ভেতরে আপনি প্রতিটা LAN-এ /64 ভাগ করেন। দ্বিতীয় অর্ধেক device নিজেই বানায় — কোনো server-কে জিজ্ঞেস করার দরকারই নেই। এই স্বয়ংক্রিয় ভাগটাই SLAAC — একটু পরে।

নতুন header — কী ফেলল, কেন নিরাপদ

IPv6-এর সবচেয়ে বড় সাহস: header নিজেই নতুন করে ভাবা। Side-by-side:

দিকIPv4IPv6
Size20–60 B, variablefixed 40 B
Addresses32-bit দুটো128-bit দুটো
Checksumheader checksum আছেনেই
Fragmentationযেকোনো router ভাঙতে পারেশুধু sender
TTLTTL fieldHop Limit (একই ভাব, নতুন নাম)
Optionsheader-এর ভেতরেইআলাদা extension headers
Configmanual/DHCP প্রায় বাধ্যতামূলকSLAAC built-in

তিনটা বড় বাদ — প্রতিটার যুক্তি:

Checksum বাদ: IPv4-এ প্রতিটা router প্রতিটা hop-এ TTL কমায়, তাই header বদলায়, তাই checksum আবার হিসাব করতেই হয় — প্রতি hop- এ বিনা-প্রয়োজনে গণিত। ভুল-শোধন আসলে কোথায় হয়? Link-layer-এ (Ethernet-এর CRC32) আর transport-layer-এ (TCP checksum; IPv6-তে UDP checksum বাধ্যতামূলক)। মাঝের স্তরের duplicate check-টা redundant — তাই বাদ। Router fast-path থেকে পুরো কাজটা উধাও।

Router fragmentation বাদ: IPv4-এ যেকোনো মাঝের router ছোট MTU-র link-এ packet ভাঙতে পারত — router-এর জন্য ভার, sender-এর জন্য অদৃশ্য জটিলতা। IPv6 নিয়ম দেয়: packet ভাঙার দায় শুধু sender- এর। মাঝপথে ছোট MTU পেলে router নীরবে ফেলে না, বরং ICMP Packet Too Big message ফেরত দেয়; sender নিজের packet-size ঠিক করে (PMTUD — path MTU discovery)। Minimum MTU 1280 byte ধরে নেওয়া বাধ্যতামূলক — তার ছোট link-কে ইন্টারনেটের ভেতরে ঢোকাই যাবে না।

Options → extension headers: IPv4-এর options header-কে variable length করত — hardware parser-দের দুশ্চিন্তা। IPv6-এ base header fixed; বাড়তি feature চাইলে extension header-এর চেইন — প্রতিটার Next Header field-এ পরেরটার নম্বর:

Base header (40B)
  └─ Next Header: Hop-by-Hop (0) → Routing (43) → Fragment (44)
       → AH (51) / ESP (50) → Destination Options → TCP (6)/UDP (17)

Router সাধারণত শুধু base header পড়েই forwarding করে — চেইনটা destination-ই খোলে। Fixed-size-first design-ই ASIC-ভিত্তিক আজকের router-এর গতির একটা ভিত্তি।

SLAAC — router নেই তবু ঠিকানা

DHCP-server ছাড়াই IPv6 device নিজের ঠিকানা বানাতে পারে। Router মাঝে মাঝে RA (Router Advertisement) বিলিয়ে দেয় network-prefix-টা (যেমন 2001:db8:abcd::/64)। Device সেই prefix-এর পিছনে নিজের interface ID জুড়ে দেয়। Interface ID বানানোর দুই পথ:

EUI-64 (ঐতিহাসিক): NIC-এর MAC (48-bit)-কে ফুলিয়ে 64 করা —

MAC:      f8:1f:32 : ab:cd:e9
ফাঁকে ff:fe বসাও:   f8:1f:32:ff:fe:ab:cd:e9
প্রথম byte-এর U/L-bit উল্টাও (XOR 02): f8 → fa
Interface ID:  fa1f:32ff:feab:cde9
ঠিকানা:        fe80::fa1f:32ff:feab:cde9   (link-local scope-এ)

Privacy extensions (RFC 4941): EUI-64-এর সমস্যা — IID-তে MAC স্পষ্ট! একই device যেখানে যায়, তার IID একই → সারা ইন্টারনেটে activity-trackable identity। Privacy extensions random IID বানিয়ে ঘণ্টা/দিন-ব্যাপী বদলায়; modern OS-রা default হিসেবে temporary address ব্যবহার করে outbound connection-এ, stable-random IID (RFC 7217 hash-based) রাখে inbound-এর জন্য।

IPv6-এ broadcast নেই — প্রতিস্থাপক multicast: এক packet, স্বেচ্ছাচয়িত গোষ্ঠী। ff02::1 এই link-এর সব node, ff02::2 সব router। আরও চতুর: solicited-node multicast — কারো ঠিকানা resolve করতে ARP-র মতো সবাইকে না ডেকে শুধু ঐ specific ঠিকানার মালিককেই ডাকা হয়: টার্গেটের শেষ 24-bit ff02::1:ff-এর পিছনে জুড়ে। পুরো ARP-broadcast-ঝামেলাটাই হ্রাস।

আর link-local fe80::/64: প্রতিটা interface-এ স্বয়ংক্রিয়ভাবে জন্ম নেয়, router ছাড়াই কাজ করে, আর কখনো route হয় না। Neighbor Discovery, RA-গ্রহণ, default-gateway-এর next-hop — সবই এই scope-এ। এজন্য এক interface-এ একাধিক IPv6 ঠিকানা স্বাভাবিক: এক link-local + এক global (+temporary)। Same-link traffic-এ destination লেখা হয় fe80::…%eth0 — %zone বলে দেয় কোন interface।

ভেতরে কী ঘটছে

Canonical form — কেন RFC 5952 লাগল

একই ঠিকানা অনেকভাবে লেখা যায় — log-analysis আর ACL-matching-এ এটা দুঃস্বপ্ন। RFC 5952 নির্ধারণ করে এক লেখা: lowercase hex, leading zeros বাদ, দীর্ঘতম zero-run ::, tie-তে বাঁ দিক। আপনার monitoring-system যদি এক ঠিকানাকে দুইভাবে লেখে, grep মিস করে — production bug-এর একটা সত্যিকার উৎস ঠিক এটাই। তাই build-section-এর compressor-এ canonical rules হুবহু implement করা হবে।

Neighbor Discovery — ARP-এর উত্তরাধিকার

IPv6-এ ARP নেই; তার জায়গা NDP — নিজেই ICMPv6-এর উপর দাঁড়ানো। Flow: device তার link-local-কে multicast solicited-node ঠিকানায় Neighbor Solicitation পাঠায়; মালিক Neighbor Advertisement-এ উত্তর দেয়। একই যন্ত্র DAD (Duplicate Address Detection)-ও চালায়: নতুন ঠিকানায় প্রথমে নিজেই solicitation পাঠিয়ে দেখে — কেউ উত্তর দিলে ঠিকানা duplicate। এই পুরো ব্যবস্থা broadcast-নির্ভর না হওয়ায় large L2 domain-এ IPv4-এর ARP-flood চাপটা IPv6-এ নেই।

Transition — তিন পথের সহাবস্থান

পুরনো IPv4 ইন্টারনেট রাতারাতি মরে না; তাই তিনটা পথ:

Dual-stack: device/server/interface দুই protocol-ই বহন করে — DNS উত্তরে A আর AAAA record দুটোই দেয়, application যেটা পারে সেটা বেছে নেয়। Browser-রা Happy Eyeballs algorithm-এ প্রায়-সমান্তরালে দুই connect শুরু করে, যেটা আগে জেতে সেটা — IPv6 ভাঙা থাকলেও user আটকায় না।

Tunneling: IPv6 packet-কে IPv4 packet-এর পেটে ঢুকিয়ে island- দুটোর মধ্যে bridge — 6in4, carrier-দের DS-Lite, ঐতিহাসিক Teredo। আজ বেশিরভাগ tunneling ISP-পর্যায়ে, user-এর চোখের আড়ালে।

Translation (NAT64 + DNS64): IPv6-only client-কে IPv4-only server-এর সাথে মেলানো — DNS64 বানায় কৃত্রিম AAAA (64:ff9b:: prefix-এ IPv4-টা encode করে), NAT64 gateway সেই ঠিকানার traffic- কে সত্যিকারের IPv4-এ translate করে। Mobile operator-রা IPv6-only SIM চালাতে ঠিক এটাই ব্যবহার করে — বিস্তারিত nat লেসনে।

Adoption — সংখ্যায় বাস্তবতা

Google-এর measurement অনুযায়ী user-side IPv6 adoption আজ ৪৫–৫০% ঘরে — India, USA, France-এ এর চেয়ে বেশি; মোবাইল carrier-গুলো সবচেয়ে আগে এগিয়েছে কারণ CGNAT-এর খরচ তাদের সবচেয়ে চেনা। বড় content-provider-রা অনেক আগেই dual-stack সম্পূর্ণ করেছে। অর্থাৎ আজ নতুন service বানানো মানে by default দুই protocol-ই সামলানো — firewall rule, logging, monitoring সবখানে দুই format।

উদাহরণ

Compression-expansion পূর্ণ drill

তিনটা ঠিকানা ধরুন, প্রতিটা expansion → compression দুই দিকেই:

# ১ — মাঝখানে বড় zero-run
full:  2001:0db8:0000:0000:0000:0000:0000:0042
runs:  শূন্য-hextet ৬টা টানা → run length 6 ≥ 2 ✓
short: 2001:db8::42

# ২ — tie-এর বাঁ-পক্ষ
full:  2001:0db8:0000:0000:0001:0000:0000:0001
runs:  অবস্থান ৩–৪ (len 2) আর অবস্থান ৬–৭ (len 2) — সমান
       বাঁ দিকের জেতে (RFC 5952)
short: 2001:db8::1:0:0:1        ← 2001:db8:0:0:1::1 অবৈধ!

# ৩ — trailing zeros
full:  2001:0db8:0001:0001:0001:0001:0000:0000
run:   শেষের দুই hextet
short: 2001:db8:1:1:1:1::

# ৪ — এক hextet গুটানো নিষিদ্ধ
full:  2001:0db8:0000:1234:0000:0000:0000:0000
runs:  শেষে len-3 ✓ (মাঝের single 0 আলাদা)
short: 2001:db8:0:1234::

SLAAC-এর জন্ম trace

একটা phone Wi-Fi-তে ঢুকল — ঘটনাক্রম:

1. Interface up → নিজের link-local বানায়: fe80::fa1f:32ff:feab:cde9
2. DAD: solicited-node ff02::1:ffab:cde9-তে NS পাঠায় → নীরবতা = unique
3. RS (optional) অথবা RA-র অপেক্ষা → router RA-তে prefix:
   2001:db8:aabb::/64, flag: "SLAAC করো"
4. IID বানায় — আজকের OS: stable-random + temporary pair
   stable:    2001:db8:aabb::d41d:8cd9:8f00:b204  (hash-based, গোপন seed)
   temporary: 2001:db8:aabb::71e4:c0ff:ee21:99aa  (random, ঘণ্টা-ব্যাপী rotate)
5. Default route নেয় RA-sender-এর link-local থেকে:
   default via fe80::1 dev wlan0

লক্ষ্য করুন: DHCP-server একবারও দেখা দেয়নি, তবু ঠিকানা, gateway, DNS (RDNSS option-এ) — সব সেট। আর MAC থেকে ঠিকানা অনুমান EUI-64 যুগের গল্প — আজকের phone-এর outbound ঠিকানা প্রতি ঘণ্টায় বদলাচ্ছে।

ছবিতে

ঠিকানার অঙ্গসংস্থান

128 bit-এর ভেতরে কী কী বাস করে
  1. Routing prefix (/48 বা /56)ISP দেয় site/home-কে — global routing table-এ এই অংশ
  2. Subnet ID (/64 পর্যন্ত)site-এর ভেতরে কোন LAN — আপনার বেছে নেওয়া ভাগ
  3. Interface ID (শেষ 64 bit)SLAAC বানায় — stable-random বা rotating temporary
  4. Scopefe80:: link-only, fc00::/7 unique-local, 2000::/3 global unicast

Header পাশাপাশি

IPv4 (20–60 B)                     IPv6 (40 B fixed)
┌──────────────────┐               ┌──────────────────┐
│ Ver/IHL │ ToS    │               │ Ver│TC│ Flow Label│
│ Total Length     │               │ Payload Length   │
│ Identification   │ ← বাদ          │ Next Header      │
│ Flags/FragOffset │ ← বাদ          │ Hop Limit        │
│ TTL              │ → Hop Limit    ├──────────────────┤
│ Protocol         │ → Next Hdr     │ Source  (128 b)  │
│ Header Checksum  │ ← বাদ!         ├──────────────────┤
│ Source  (32 b)   │                │ Dest.   (128 b)  │
│ Dest.   (32 b)   │                └──────────────────┘
│ Options (0–40 B) │ ← extension headers-এ সরেছে
└──────────────────┘
IPv4-এর variable header বনাম IPv6-এর fixed 40-byte — ডান দিকের সাদা ঘরগুলোই বাদ পড়া field; router fast-path-এর গতির রহস্য ওখানেই।

Extension-header চেইন

┌───────────┐ NH=0 ┌────────────┐ NH=43 ┌───────────┐ NH=44
│ Base hdr  │─────►│ Hop-by-Hop │──────►│ Routing   │────► Fragment
│ (fixed40) │      │  (routers  │       │           │        │ NH=6
└───────────┘      │   পড়ে)      │       └───────────┘        ▼
                   └────────────┘                        TCP segment
প্রতিটা header-এর Next Header field-ই পরেরটার ঠিকানা — router সাধারণত প্রথম box পড়েই কাজ শেষ, চেইন খোলে শুধু ঠিকানার মালিক।

নিজে চালিয়ে দেখুন

EXPERIMENT

নিজের machine কি IPv6 জানে? — addr, ping, traceroute তিন পরীক্ষা

Linux / macOS· ১৫ মিনিট

ধাপ ১ — ঠিকানা inspect:

# Linux
ip -6 addr show
# macOS
ifconfig en0 | grep inet6

Output-এ তিন জাত খুঁজুন: fe80::... (link-local, সবসময় থাকবে), 2001: বা 240x:-দিয়ে শুরু global SLAAC ঠিকানা, আর Linux-এ temporary বা macOS-এ secured/ephemeral flag — privacy extension- এর স্বাক্ষর। একই interface-এ ৩–৪টা ঠিকানা স্বাভাবিক।

ধাপ ২ — IPv6-দিয়েই ping:

ping -6 google.com          # পুরনো macOS-এ: ping6 google.com

উত্তর এলে আপনার পুরো পথ — router থেকে ISP পর্যন্ত — IPv6 সচেতন। Reply-র source-টা খেয়াল করুন: সেটা Google-এর global 2607:f8b0::-family ঠিকানা — আপনি সত্যিকারের v6-internet পেরিয়েছেন। ব্যর্থ হলে আপনার network-এ v6 নেই — ধাপ ৩ তবু কাজ করবে link-local-এ।

ধাপ ৩ — দুই protocol-এর traceroute পাশাপাশি:

traceroute6 google.com      # v6-পথ
traceroute google.com       # v4-পথ (default)

Hop-count আর latency তুলনা করুন। প্রায়ই v6-পথ এক-দুই hop কম — carrier-দের flat topology-র প্রতিধ্বনি। কোনো hop * * * হলে ভয় নেই: অনেক router ICMP-time-exceeded কম priority-তে দেয়।

ধাপ ৪ (ঐচ্ছিক) — browser-এর Happy Eyeballs নিজে দেখুন:

curl -6 -s https://ipv6.google.com -o /dev/null -w '%{remote_ip}\n'
curl -4 -s https://ipv6.google.com -o /dev/null -w '%{remote_ip}\n'

দুই লাইনে দুই family-র IP — একই hostname, দুই জগৎ। আপনার browser প্রতিটা page-load-এ নীরবে এই দুই রাস্তার race চালায়।

এটা কী প্রমাণ করে

আপনার device ইতিমধ্যেই link-local ঠিকানা নিজে বানিয়েছে, পারলে global SLAAC-ও নিয়েছে — IPv6 theory-নির্ভর নয়, আজ থেকেই আপনার দৈনন্দিন traffic-এর অংশ।

নিজে বানান

BUILD IT

RFC 5952 canonical compressor/expander — edge-case tests সহ

Python · ●●○○○
  1. expand(): text থেকে ৮টা integer hextet — :: split, missing fill, validation
  2. নিয়ম enforce: :: একবার, অন্তত দুই hextet compressed, প্রতি group ≤ 4 hex-digit
  3. compress(): leading-zero strip → longest zero-run (tie: বাঁ দিক) → ::
  4. round-trip assert: compress(expand(text)) প্রতিটা case-এ canonical
  5. edge-case battery: ::1, ::, trailing run, double-run tie, invalid input

লক্ষ্য: RFC 5952-এর তিন নিয়ম কোডে হুবহু নামানো — আর নিজের implementation-কে নিজেরই তৈরি edge-case-এ কষ্ট দেওয়া।

import re

def expand(text):
    """Text → ৮টা int hextet। Invalid হলে ValueError।"""
    if text.count('::') > 1:
        raise ValueError(':: একবারই বৈধ')
    head, sep, tail = text.partition('::')
    lhs = [g for g in head.split(':') if g]
    rhs = [g for g in tail.split(':') if g]
    if sep:                                  # :: আছে
        missing = 8 - len(lhs) - len(rhs)
        if missing < 1:                      # অন্তত ১টা গুটাতে হবে
            raise ValueError(':: দিয়ে শূন্য group সংকোচন অবৈধ')
        groups = lhs + ['0'] * missing + rhs
    else:
        groups = lhs
    if len(groups) != 8:
        raise ValueError(f'৮টা group দরকার, পেলাম {len(groups)}')
    out = []
    for g in groups:
        if len(g) > 4 or not re.fullmatch(r'[0-9a-fA-F]{1,4}', g):
            raise ValueError(f'অবৈধ hextet: {g!r}')
        out.append(int(g, 16))
    return out

def compress(groups):
    """ints → RFC 5952 canonical string।"""
    s = [f'{g:x}' for g in groups]           # lowercase, no leading zeros
    bi = bl = -1                             # best index, best length
    i = 0
    while i < 8:
        if s[i] == '0':
            j = i
            while j < 8 and s[j] == '0':
                j += 1
            if j - i >= 2 and j - i > bl:    # strict > ⇒ tie-এ বাঁ জেতে
                bi, bl = i, j - i
            i = j
        else:
            i += 1
    if bl < 0:
        return ':'.join(s)                   # গুটানোর মতো run-ই নেই
    left, right = s[:bi], s[bi + bl:]
    return ':'.join(left) + '::' + ':'.join(right)

def canon(text):
    return compress(expand(text))

TESTS = [
    ('2001:0db8:0000:0000:0000:ff00:0042:8329', '2001:db8::ff00:42:8329'),
    ('0:0:0:0:0:0:0:1',                          '::1'),
    ('0:0:0:0:0:0:0:0',                          '::'),
    ('2001:0db8:0000:0000:0001:0000:0000:0001',  '2001:db8::1:0:0:1'),
    ('2001:0db8:0001:0001:0001:0001:0000:0000',  '2001:db8:1:1:1:1::'),
    ('2001:0db8:0000:1234:0000:0000:0000:0000',  '2001:db8:0:1234::'),
    ('2001:db8::1:0:0:1',                        '2001:db8::1:0:0:1'),  # already canonical
]
for raw, want in TESTS:
    got = canon(raw)
    assert got == want, f'{raw}: {got} != {want}'
    assert canon(got) == got                 # canonical স্থির-point

for bad in ('1::2::3', '12345::', '1:2:3'):
    try:
        canon(bad); raise AssertionError(f'{bad} গ্রহণ হলো!')
    except ValueError:
        pass
print('সব edge-case পাস ✓')

প্রত্যাশিত output:

সব edge-case পাস ✓

Test-tabel-টা খেয়াল করুন — দ্বিতীয় tie-case-টা (::1:0:0:1) RFC 5952-এর সবচেয়ে ভুল-হওয়া নিয়ম; naive implementation ডান-run গুটিয়ে ফেলে। আর invalid-input তিনটা আপনার parser-কে production- hardening শেখায়: দুই ::, ৫-digit group, অসম্পূর্ণ ঠিকানা।

নিজে বাড়ান:

  1. Embedded IPv4 tail support করুন — ::ffff:192.168.1.20 parse করে last two hextet-এ 32-bit encode
  2. ipaddress.IPv6Address-কে oracle বানিয়ে random 1000 ঠিকানায় fuzz-test চালান
  3. Prefix-aware printer লিখুন — canon('2001:db8::/32') format-ও সামলায়

বাস্তব সিস্টেমে

বাস্তব জগতে IPv6 আজ

Mobile carrier-দের সাফল্যগল্প। বড় operator-রা (US-এর T-Mobile, India-র Jio-র মতো নেটওয়ার্ক) mobile-data-তে IPv6-mostly বা IPv6-only চালায় — পেছনে NAT64 দিয়ে v4-legacy ছোঁয়া হয়। কারণ বাস্তব: কোটি device-কে public IPv4 দেওয়া অসম্ভব, CGNAT port-exhaustion আর আইনি log-চাপ বেশি। আপনার phone-এর বেশিরভাগ photo-upload হয়তো ইতিমধ্যেই v6-এ।

Content-side প্রস্তুতি। Google, Meta, Cloudflare — সবাই বহু বছর ধরে full dual-stack। নতুন CDN-customer onboarding-এ AAAA record default। অর্থাৎ server-engineer-এর জন্য প্রশ্ন আর “IPv6 লাগবে কি”, প্রশ্ন হলো “v6-only client-এর error-log কি পড়তে পারছি”।

Happy Eyeballs-এর নীরব রক্ষা। Browser, curl, এমনকি OS resolver- রা v4/v6 দুই connect প্রায় একসাথে শুরু করে যেটা আগে SYN-ACK পায়। এই fallback-ই কারণ ভাঙা v6-deployment (যেমন firewall-এ ICMPv6 block!) user-কে ধীর লাগে কিন্তু আটকায় না। শিক্ষা: IPv6 deploy মানে ICMPv6 খুলে দেওয়া — PMTUD আর NDP তার উপরই দাঁড়ানো।

Enterprise-এ এখনো দুই জগৎ। অফিস-network-গুলো প্রায়ই v4-centric; security-team-দের tooling (IDS signature, netflow analysis) v6-তে ঐতিহাসিকভাবে দুর্বল ছিল — তাই কেউ v6 disable করে রাখে। Modern practice উল্টো: enable করে monitoring-ও v6-সচেতন করা, কারণ shadow-v6 (enable না-জেনে হয়ে-যাওয়া) সবচেয়ে বিপজ্জনক অবস্থা।

যে ভুলগুলো সবাই করে

“IPv6 মানে IPv4-এর মতোই, শুধু ঠিকানা বড়।”

ঠিকানা বড় হয়েছে সত্যি, কিন্তু সাথে header redesign: checksum নেই, router-fragmentation নেই, broadcast নেই, ARP-এর জায়গায় NDP, options-এর জায়গায় extension-header chain, config-এর জায়গায় SLAAC। IPv4-এর habit নিয়ে v6-তে গেলে (যেমন ICMP block, DHCP ছাড়া কিছু হবে না ভাবা) deployment-ই ভাঙে।

“`::` যেকোনো zero-কে গুটায়, চাইলে একাধিকবারও চলে।”

:: একবার, দীর্ঘতম run, অন্তত দুই hextet — এক hextet গুটানো অবৈধ। 2001:db8:0:0:1:0:0:1-এর canonical রূপ 2001:db8::1:0:0:1, 2001:db8:0:0:1::1 নয় — tie-তে বাঁ-দিকের run জেতে। নিয়মটা receiver-এর ambiguity-বাঁচার নিয়ম, stylistic নয়।

“Checksum বাদ দেওয়ায় IPv6-এ data-corruption ধরা পড়ে না।”

Link-layer (Ethernet CRC) corruption ধরে, transport-layer (TCP checksum, আর IPv6-তে বাধ্যতামূলক UDP checksum) বাকিটা ধরে। যা বাদ গেল তা মাঝের router-দের redundant re-checksumming — যেটা প্রতিটা hop-এ TTL-change-এর জন্য বাধ্য হতো। Error-detection শক্তি কমেনি, ব্যয় কমেছে।

“EUI-64 থেকে MAC leak হয়, তাই IPv6 inherently tracking-friendly।”

EUI-64 আজ legacy; সব modern OS default-এ privacy extensions — outbound-এ rotating random IID, inbound-এ hash-based stable IID। Tracking-ঝুঁকি তখনই সত্যি যখন admin সচেতনভাবে SLAAC-privacy off রাখে (কিছু enterprise policy করে)। Device-identifier হিসেবে v6-IID ধরার আগে আজকের default যাচাই করুন।

“IPv6-তেও NAT লাগবে — security-র জন্য।”

NAT security দেয় না, stateful firewall দেয় — দুটো আলাদা যন্ত্র। IPv6-এর মূল লক্ষ্য-ই end-to-end restore; NAT66/NPTv6 spec-এই discouraged। v6-network-এ বাইরে-থেকে-ঢোকা আটকায় default- deny firewall policy, ঠিকানা-rewrite নয়। nat লেসনে এই ভেদটা মূল বিষয়।

বুঝেছেন কি না দেখুন

1

`::-compression-এর তিনটা নিয়ম লিখুন। কোনটা সবচেয়ে প্রায়ই ভাঙা হয়?

স্মরণ

(১) এক ঠিকানায় :: সর্বোচ্চ একবার; (২) দীর্ঘতম zero-run গুটানো হয়, সম-দৈর্ঘ্যে বাঁ দিকেরটা; (৩) অন্তত দুই hextet লাগবে — একটা গুটানো যায় না। সবচেয়ে প্রায়ই ভাঙে তৃতীয়টা আর tie-rule — …:0:0:1:: জাতীয় লেখা প্রচুর দেখা যায়।

2

2001:0db8:0000:0000:0000:0000:0000:0042-এর canonical রূপ লিখুন, আর ::1 কোন বিশেষ ঠিকানা?

প্রয়োগ

Six-zero run → 2001:db8::42। ::1 হলো loopback — নিজের-machine ঠিকানা, IPv4-এর 127.0.0.1-এর প্রতিরূপ; :: unspecified।

3

MAC 3c:22:fb:12:34:56 থেকে EUI-64 interface ID বানান — প্রতিটা conversion-ধাপসহ।

প্রয়োগ

মাঝে ff:fe ঢোকান: 3c:22:fb:ff:fe:12:34:56; U/L-bit উল্টাতে প্রথম byte XOR 0x02: 3c=00111100 → 00111110=3e। Interface ID = 3e22:fbff:fe12:3456; link-local ঠিকানা fe80::3e22:fbff:fe12:3456।

4

Fixed 40-byte header hardware-forwarding-এর জন্য কেন গুরুত্বপূর্ণ? Variable-length-এর ঠিক কোন সমস্যাটা দূর হলো?

যুক্তি

ASIC/parser একবারই 40 byte পড়ে সব decision-field পায় — offset constant, pipeline predictable। Variable header-এ (IPv4 options) parser-কে প্রতিটা packet-এ length পড়ে branch করতে হয়, options-এর দৈর্ঘ্য আগে জানা নেই — silicon-এ এটা slow-path। তাই options সরিয়ে extension-chain-এ দেওয়া: common-case থেকে জটিলতা সরানো।

5

Broadcast বাদ দিয়ে solicited-node multicast কী সমস্যা সমাধান করল? ARP-তুলনায় ব্যয়-পার্থক্য বলুন।

যুক্তি

ARP প্রতিটা resolve-এ সবাইকে interrupt করত (L2 broadcast) — বড় segment-এ প্রতিটা host CPU জাগিয়ে তারপর filter করত। Solicited-node multicast-এ frame পৌঁছায় শুধু সেই NIC-এ যার hash-filter ওই multicast- group-এ subscribe করেছে — অন্যরা hardware-level-এই ignore করে। Resolve-cost একই, collateral-cost প্রায় শূন্য।

6

আপনার app-এর user IPv6-only phone-এ, আর origin-server IPv4-only। Traffic কীভাবে পৌঁছাবে — দুইটা সম্ভাব্য পথ আঁকুন, কোনটা কখন বেছে নেবেন?

ডিজাইন

পথ ১ — NAT64+DNS64: DNS64 origin-এর A-record থেকে কৃত্রিম AAAA বানায় (64:ff9b::/96-এ v4 encode), carrier-NAT64 gateway translate করে। Carrier-controlled, app-কে কিছু করতে হয় না — কিন্তু literal IPv4-address hardcode করা app ভাঙে। পথ ২ — dual-stack front-door: CDN/load-balancer v6 গ্রহণ করে পেছনে v4-origin-এ যায়। নিজের-control বেশি, তাই production-service-এ এটাই পছন্দ; carrier-NAT64 তখন fallback।

এরপর কী

এরপর কী

ঠিকানার জগৎ সাজল — কিন্তু একটা ঠিকানা থেকে অন্যটায় পৌঁছাতে হলে রাস্তা লাগে। আপনার home-router পুরো ইন্টারনেটের map জানে না; তবু আপনার packet Sydney-র datacenter পৌঁছায়। সেই জাদুর নাম routing — আর তার সবচেয়ে বড় যন্ত্র, যেটা continent-গুলোকে একসাথে সেলাই করে: BGP।

পরের লেসনে:

  • Forwarding বনাম routing — data-plane আর control-plane-এর ভেদ
  • Longest-prefix-match — kernel ঠিক কোন route বেছে নেয়
  • RIP-র count-to-infinity দুর্ঘটনা থেকে OSPF-এর link-state
  • BGP: policy-based routing — যেখানে অর্থ দূরত্বকে হার মানায়

আজকের /64-ভাগ আর aggregation-জ্ঞান সেখানেই কাজে লাগবে — পুরো ইন্টারনেট আসলে একটা giant prefix-tree।

আরও পড়ুন

  • RFC 8200 — Internet Protocol, Version 6 (IPv6) Specification — S. Deering, R. Hinden, IETF · Header format ও extension-header chain-এর authoritative spec
  • RFC 4291 — IP Version 6 Addressing Architecture — R. Hinden, S. Deering, IETF · ঠিকানার ধরন, scope, solicited-node multicast-এর মূল সংজ্ঞা
  • RFC 5952 — A Recommendation for IPv6 Address Text Representation — S. Kawamura, M. Kawashima, IETF · :: compression-এর canonical নিয়ম — build section-এর বিচারক