Foundationপ্রথম নীতি থেকে
LEVEL 7লেসন ৪/২২অ্যাডভান্সড৫৫ মিনিট

IP Datagram — best-effort delivery-র contract

The IP Datagram

Continent-crossing-এর চুক্তিপত্র — 20-byte header-এর bit-level dissection, best-effort-এর দর্শন, আর fragmentation-যুগের শেষ হওয়ার গল্প।

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

  • IPv4 header-এর প্রতিটা field — version/IHL, DSCP, total length, identification/flags/offset, TTL, protocol, header checksum, src/dst — একটা hexdump-এ bit-position ধরে চিনে বলতে পারবেন
  • 'Best-effort' contract-এর ঠিক সীমা টানতে পারবেন: IP কী promise করে না (ordering, dedup, delivery), আর reliability উপরের layer-দের দায়িত্ব কেন
  • Fragmentation-এর গণিত — offset 8-byte unit, MF flag, reassembly-at-destination — আর আধুনিক stack কেন DF-set-করে fragmentation avoid করে, তা যুক্তি দিয়ে বলতে পারবেN
  • TTL-এর loop-containment ভূমিকা আর traceroute-এর সাথে সম্পর্ক ব্যাখ্যা করতে পারবেন
  • Protocol-number field কীভাবে TCP(6)/UDP(17)/ICMP(1)-এ demux হয়, আর IPv6 header-checksum ছুঁড়ে ফেলল কেন safe — তা বলতে পারবেন

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

আগে এটা বুঝি

আমাদের packet এখন gateway-র দরজায়। ঘরের ভেতরের L2 জগৎ শেষ — এখন থেকে সে ভ্রমণ করবে এমন এক container-এ যেটা পৃথিবীর যেকোনো router খুলে দেখতে পারবে, যেখানে লেখা আছে চূড়ান্ত গন্তব্য, জীবন- সময়ের বাকি অংশ, আর ভেতরে কোন protocol বসে আছে। Container-টা হলো IP datagram, আর তার প্রথম 20 byte — ইন্টারনেটের সবচেয়ে বেশি photocopy হওয়া diagram।

কিন্তু এই লেসনের আসল বিষয় header-এর আগে একটা দার্শনিক সিদ্ধান্ত, ১৯৭৪-এ Cerf-Kahn-এর সবচেয়ে সাহসী bet: IP কোনো guarantee দেবে না। Packet হারাতে পারে, duplicate হতে পারে, উল্টো ক্রমে আসতে পারে। Internet-এর পুরো ইতিহাস এই ‘অদক্ষ’ সিদ্ধান্তের ফসল — নিচের স্তর যত বোকা, উপরের স্তর তত স্বাধীন।

আজ শিখব: প্রতিটা field ঠিক কী বলে, best-effort-এর সীমানা কোথায়, fragmentation কেন ছিল ভুল-হয়ে-যাওয়া feature, আর TTL কীভাবে routing-loop-কে অনন্ত হতে দেয় না।

মূল ধারণা

Header — bit by bit

RFC 791-এর diagram-টাই মূল মানচিত্র (প্রতি row = 32 bit):

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
┌─┴───────┴─┴─────┴──────────────────────────────────────────────┐
│Ver│ IHL │DSCP │ECN│                Total Length                  │
├──────────────────┬───────────────────────────────────────────────┤
│   Identification │Flags(3)│        Fragment Offset               │
├────────┬─────────┼───────────────────────────────────────────────┤
│  TTL   │ Protocol│           Header Checksum                     │
├────────┴─────────┼───────────────────────────────────────────────┤
│                 Source Address                                   │
├──────────────────┼───────────────────────────────────────────────┤
│              Destination Address                                 │
├──────────────────┼                                               │
│      Options     │             Padding (IHL>5 হলেই)              │
└──────────────────┴───────────────────────────────────────────────┘

Field-by-field:

FieldBitsকাজ
Version44 — এই datagram-এর dialect
IHL4Header-length 32-bit word-এ (5–15 → 20–60 byte)
DSCP6Quality-class mark (voice/video/bulk — QoS-এর ভিত্তি)
ECN2Congestion-এর সৌজন্য-সংকেত (congestion-control লেসনে)
Total Length16Header+data, max 65,535 byte
Identification16Fragment-family-র গর্ভধারণ-ID
Flags3R(reserved), DF(don’t fragment), MF(more fragments)
Frag Offset13এই খণ্ডটা মূল data-র কোথায় — 8-byte unit-এ!
TTL8প্রতি hop-এ 1 কমে; 0 হলে মৃত্যু+ICMP-time-exceeded
Protocol8ভেতরে কে: 1=ICMP, 6=TCP, 17=UDP
Header Checksum16শুধু header-এর ones’-complement যোগফল
Src / Dst32+32end-to-end ঠিকানা — পথে কখনো বদলায় না*

(* NAT ব্যতিক্রম — nat লেসনে দেখব; তবু principle: router IP-field rewrite করে না, TTL ছাড়া।)

Best-effort — চুক্তির পুরো লেখা

IP-র promise-list শূন্য:

✗ Delivery guarantee      — packet হারাতে পারে (buffer-full drop)
✗ Ordering guarantee      — পরে-পাঠানো আগে পৌঁছাতে পারে (ভিন্ন route!)
✗ Uniqueness guarantee    — duplicate আসতে পারে (retransmit-confusion)
✗ Bandwidth/timing        — কোনো reservation নেই
✓ শুধু একটা প্রতিশ্রুতি: চেষ্টা করা হবে। Best effort.

কেন এই ‘অদক্ষতা’ genius ছিল: network-কে stateless রাখে (router per-packet decision, connection-memory শূন্য → scale-infinity), failure-tolerant (node মরলে পথ বদল), আর innovation-decoupled — TCP, QUIC, RTP সবাই নিজের মতো policy বসাতে পারে একই dumb substrate-এ। Reliability-র আসল দায়িত্ব transport-এ — tcp-reliability লেসনের পুরো বিষয়।

Fragmentation — যে feature কাউকে ভালো লাগে না

Link MTU ভিন্ন হলে (1500 Ethernet, 1492 PPPoE, 1480 tunnel…) বড় datagram ভাঙতে হয়। Mechanics:

4000-byte datagram @ MTU 1500:
frag#1: total=1500, id=X, MF=1, offset=0       data[0..1479]
frag#2: total=1500, id=X, MF=1, offset=185     data[1480..2959]
frag#3: total=1040, id=X, MF=0, offset=370     data[2960..3999]
        (offset unit = 8 byte: 185×8=1480 ✓)
  • এক router ভাঙে, কিন্তু reassembly শুধু destination-এ — মাঝের router-রা আবার জোড়া দেয় না (stateless থাকার মূল্য)
  • ID+offset+total মিলিয়ে receiver puzzle-solve করে
  • একটা খণ্ড হারালে পুরো family বাতিল — 3-fragment datagram- এ loss-rate ৩ গুণ!

তাই আধুনিক stack প্রায় সবসময় DF set করে এবং PMTUD চালায়: path-এর সবচেয়ে ছোট MTU আগে-থেকে জেনে সেই size-ই পাঠায়। DF-set packet ছোট link-এ গেলে router drop করে + ICMP ‘frag needed’ (next-hop MTU সহ) পাঠায় — sender size কমায়। icmp-ping-traceroute লেসনে এই ICMP-টা experiment-এ হাতে ধরা হবে।

TTL — অমরত্বের বিরুদ্ধে বীমা

Routing-table bug বা transient-loop-এ দুই router একে-অপরের দিকে packet ফেলতেই থাকতে পারে — bandwidth-এর অগ্নিস্বাংশ। প্রতিষেধ: TTL 64 (Linux)/128 (Windows)-এ জন্ম, প্রতি hop-এ decrement, 0-তে drop+ICMP-time-exceeded। Loop তাহলে অনন্ত নয় — সর্বোচ্চ 64 hop- এর আয়ু। Side-effect জাদু: traceroute ইচ্ছাকৃতভাবে TTL=1,2,3… পাঠিয়ে প্রতিটা router-কে self-disclose করায় — icmp-ping-traceroute লেসনের engine।

Protocol number — demux-এর দরজা

Receiver-এ IP-layer ভেতরের payload কাকে দেবে? Protocol-field:

ValueProtocolগ্রহীতা
1ICMPping/diagnostics (icmp lesson)
6TCPtransport-এর ভারী ভাই
17UDPtransport-এর হালকা ভাই

udp/tcp-handshake লেসনে দেখব — ওরা নিজেরাও port-number দিয়ে application-এ demux করে; IP-র protocol-field সেই chain-এর প্রথম সংযোগ।

Checksum — আর তার IPv6-মৃত্যু

IPv4 header-checksum শুধু header cover করে (data-র জন্য L4-checksum); প্রতি hop-এ TTL— হওয়ায় প্রতি hop-এ recompute-ও লাগে। IPv6 এটা ছুঁড়ে ফেলল — যুক্তি: L2-র FCS (CRC32) transit-error ধরে, L4-checksum (TCP/UDP-তে pseudo-header সহ) content ধরে; মাঝের স্তরের checksum redundancy-ই বাদে CPU বাঁচে, routers দ্রুত হয়। Lesson: error- detection একবার-ই দরকার প্রতি medium-এ, প্রতি স্তরে নয়।

ভেতরে কী ঘটছে

DSCP — যে field enterprise জীবন্ত-রেখেছে

TOS-byte থেকে DSCP: প্রথম ৬ bit = 64 class; EF(46)=voice-priority, AF-classes assured। Home-ISP উপেক্ষা-করে; corporate-WAN-এ voice/video queue-jump — ভিড়েও Zoom-audio crisp-এর কারণ। Marking edge-এ, enforcement core-এ।

Identification-field-এর দ্বিতীয় জীবন

Fragmentation-মৃত্যুপথে, কিন্তু ID-field-নতুন-কাজে: Linux per-destination hash off-path-injection-বিরুদ্ধে; researchers ID-entropy OS-fingerprint। IPv6 fragment-extension-header-এও একই field পুনর্জন্ম — concept-অমর, ঠিকানা-বদলেছে।

Reassembly-buffer-bomb

Attacker হাজার খণ্ড MF=1-সহ, শেষ-খণ্ড-ছাড়া — receiver-buffer timeout (~30 s) পর্যন্ত-ধরে: teardrop-family-attack-এর কৌশল। Modern-kernel per-source-memory-quota; firewall fragment-log আজও-আলাদা — feature-এর প্রতিটা-দরজা attack-surface।

কেন offset-ঠিক 8-byte unit

13-bit offset × 8 = 65,520 — max-total-length-এর-গা-ঘেঁষে। ছোট-field- এ-বড়-space: শর্ত, non-final fragment payload 8-গুণিতক। এই-packing-trick QUIC-varint-এও-ফিরবে।

NAT-আসার-আগে-শেষ-কথা: ঠিকানার অপরিবর্তনশীলতা

Src/dst-constancy-ই traceroute/mtr/firewall-rule-ভিত্তি। NAT ভাঙে (nat lesson); তবু ৩০-বছর invariant-এ internet দাঁড়িয়েছিল — invariant-ভাঙা free-সিদ্ধান্ত-নয়।

উদাহরণ

একটা আসল hexdump-এর পূর্ণ autopsy

Gateway-কে ping করলে wire-এ যা গেল (frame-এর IP-part):

45 00 00 54 12 ab 40 00 40 01 f6 7a c0 a8 01 14
c0 a8 01 01

Byte-by-byte decode:

45          version=4, IHL=5 (20B, options নেই)
00          DSCP=0 ECN=0 (best-effort class)
00 54       total length = 84 (20B header + 64B ICMP)
12 ab       identification = 0x12ab
40 00       flags+off: DF=1 (010 …), offset=0  ← PMTUD-era!
40          TTL = 64 (Linux-জাত)
01          protocol = 1 (ICMP)
f6 7a       header checksum (verify: নিচে build-এ)
c0 a8 01 14 source = 192.168.1.20
c0 a8 01 01 dest   = 192.168.1.1

লক্ষ্য করুন তিনটা সমসাময়িক signature: DF=1 (কেউ আর fragment চায় না), TTL=64 (OS-fingerprint!), checksum শুধু header-এ।

ভিন্ন route-এ ordering-ভাঙা

Sender A→B seq 1,2,3; congestion-এ route-flip: pkt2-ধীর-পথ (52 ms), pkt1/pkt3-দ্রুত (30/31 ms) — B-দেখা-ক্রম 1, 3, 2। IP-কিছুই-করবে- না; reordering TCP-র job। Best-effort-এর মূল্য: নিচের-স্তর-সরল, উপরের-স্তর-complexity-বহন — trade-off ইচ্ছাকৃত, ৫০-বছর-ধরে-জেতে।

ছবিতে

┌──────────────────── Ethernet frame (hop-local, প্রতি link-এ নতুন) ─────────────────┐
│ DST MAC │ SRC MAC │ 0x0800 │ ┌──────────── IP datagram (end-to-end) ────────┐ │ FCS │
│                            │ IP hdr │ ┌──── TCP segment ────┐            │ │     │
│                            │ 20–60B │ │ TCP hdr │ app bytes │            │ │     │
│                            │        │ └─────────────────────┘            │ │     │
│                            └───────────────────────────────────────────────┘ │     │
└──────────────────────────────────────────────────────────────────────────────────┘
Encapsulation-এর সম্পূর্ণ ছবি — আজকের container মাঝখানে; ভেতরে TCP, বাইরে frame।
Original 4000B, MTU 1400:
per-frag data ≤ 1400−20 = 1380, আর offset-unit-এর নিয়মে
প্রতিটা non-final খণ্ডে data = 8-এর গুণিতক → 1376

[hdr id=7 MF=1 off=0   ][data 0000..1375]   wire: 20+1376=1396 ≤1400 ✓
[hdr id=7 MF=1 off=172 ][data 1376..2751]   ← 172×8 = 1376 ✓
[hdr id=7 MF=0 off=344 ][data 2752..3999]   ← শেষ খণ্ড: 1248B, MF=0

offset-field-এ যা যায় (8-byte unit): 0, 172, 344
frag#2 হারালে? receiver frag#1+#3 buffer-এ ধরে রাখে…
timeout পর্যন্ত, তারপর পুরো family বাতিল ✗
Fragmentation-এর পরিবার — ID এক, offsets গুণিতক-৮, MF flag শেষ-খণ্ড পর্যন্ত জ্বলে; এক খণ্ড-হারানো = পুরো ব্যাচ বাতিল।

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

EXPERIMENT

Path-MTU probe আর live header-dissection

Linux / macOS (tcpdump-এ sudo)· ২০ মিনিট

ধাপ ১ — binary-search করে PMTU:

ping-এ -s = ICMP-data-size; মোট IP-size = s + 28 (IP20+ICMP8):

for sz in 1472 1452 1400 1350; do
  echo "== payload $sz → IP $((sz+28)) =="
  ping -c 2 -W 1 -M do -s $sz example.com   # Linux (-M do = DF set)
  # macOS: ping -c 2 -W 1000 -D -s $sz example.com   (-D = DF)
done

প্যাটার্ন: 1472-তে ‘message too long’/silent, ছোট-তে reply → path-MTU মাঝে। Binary-search exact-খুঁজুন; VPN হলে 1400-ঘেঁষা — tunnel-overhead-র জীবন্ত-প্রমাণ।

ধাপ ২ — header চোখের সামনে (sudo):

sudo tcpdump -i any -v -n -c 4 'icmp and host example.com'
# অন্য terminal: ping -c 3 example.com

Annotated দেখুন:

IP (tos 0x0, ttl 64, id 12345, offset 0, flags [DF],
    proto ICMP (1), length 84)
    192.168.1.20 > 93.184.216.34: ICMP echo request
...
IP (tos 0x0, ttl 51, id 54321, ...)           ← reply-এ ttl কম!

ttl 64→51 = ফেরত-পথে 13 hop — asymmetric-route-এর প্রথম-প্রমাণ। id প্রতি-packet-এ বদল, DF স্থির।

ধাপ ৩ — ঐচ্ছিক: কোনো site-এ বড় download চলাকালে capture-এ ‘bad frag’/fragment-lines খুঁজুন — rare, কিন্তু tunnel-যুগে এখনো দেখা যায়। না পেলে সেটাই ফলাফল: modern internet ≈ fragment-free।

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

-M do দিয়ে DF-set ping পথের সবচেয়ে ছোট MTU নিজেই খুঁজে বের করে, আর tcpdump -v-তে TTL/ID/flags live বদলাতে দেখা যায় — textbook-এর field-গুলো আসলে প্রতি সেকেন্ডে আপনার NIC-এ ঘুরছে।

নিজে বানান

BUILD IT

IPv4 Toolkit — header parse, build, checksum verify, আর fragment-reassembly demo

Python · ●●●○○
  1. struct.unpack দিয়ে fixed-fields পড়ুন — bit-masking দিয়ে version/IHL/flags/offset বের করুন
  2. ones-complement checksum compute+verify function লিখুন — build আর verify একই code-path
  3. build() দিয়ে synthetic datagram বানান — নিজের parse() দিয়ে round-trip verify
  4. fragment(): MTU-অনুযায়ী 8-byte-aligned খণ্ডে ভাঙুন, ID/MF/offset set করুন
  5. reassemble(): offset-order sort, gap-detect, overlap-detect — mini-protocol-engine

লক্ষ্য: RFC 791-এর প্রতিটা rule একবার executable করা — parse, verify, build, fragment, reassemble — পাঁচ দক্ষতা এক file-এ।

#!/usr/bin/env python3
"""ip_toolkit.py — IPv4 header parse/build/checksum/fragmentation।"""
import struct, random

def checksum(data: bytes) -> int:
    """RFC 1071 ones'-complement sum (16-bit words)।"""
    if len(data) % 2: data += b"\x00"
    total = sum(struct.unpack(f"!{len(data)//2}H", data))
    while total >> 16:                       # carry fold-back
        total = (total & 0xFFFF) + (total >> 16)
    return (~total) & 0xFFFF

def parse(ip: bytes) -> dict:
    ver_ihl, tos, total_len, ident, fl_off, ttl, proto, \
        cks, src, dst = struct.unpack("!BBHHHBBH4s4s", ip[:20])
    ver, ihl = ver_ihl >> 4, ver_ihl & 0xF
    df, mf, off = bool(fl_off & 0x4000), bool(fl_off & 0x2000), (fl_off & 0x1FFF) * 8
    ip_str = lambda b: ".".join(map(str, b))
    return dict(ver=ver, ihl_words=ihl, dscp=tos >> 2, ecn=tos & 3,
                total=total_len, ident=ident, df=df, mf=mf, offset=off,
                ttl=ttl, proto={1:"ICMP",6:"TCP",17:"UDP"}.get(proto, str(proto)),
                cks_ok=(checksum(ip[:10] + b"\x00\x00" + ip[12:20]) == cks),
                src=ip_str(src), dst=ip_str(dst),
                opts_bytes=(ihl - 5) * 4)

def build(src, dst, proto=17, ttl=64, ident=None, df=True, payload=b""):
    ident = random.randint(0, 65535) if ident is None else ident
    flags_off = (0x4000 if df else 0)          # DF set, offset 0
    hdr = struct.pack("!BBHHHBBH4s4s",
                      0x45, 0, 20 + len(payload), ident, flags_off,
                      ttl, proto, 0,
                      bytes(int(x) for x in src.split(".")),
                      bytes(int(x) for x in dst.split(".")))
    hdr = hdr[:10] + struct.pack("!H", checksum(hdr)) + hdr[12:]
    return hdr + payload

def fragment(datagram: bytes, mtu: int):
    ihl = (datagram[0] & 0xF) * 4
    hdr, data = datagram[:ihl], datagram[ihl:]
    chunk = ((mtu - ihl) // 8) * 8              # 8-byte align!
    frags, off = [], 0
    while off < len(data):
        piece = data[off : off + chunk]
        more = off + len(piece) < len(data)
        fo = struct.unpack("!H", hdr[6:8])[0] & 0xE000
        fo |= (off // 8) | (0x2000 if more else 0)
        fh = hdr[:6] + struct.pack("!H", fo) + hdr[8:]
        fh = fh[:10] + struct.pack("!H", checksum(fh)) + fh[12:]
        frags.append(fh + piece)
        off += len(piece)
    return frags

def reassemble(frags: list[bytes]) -> bytes | None:
    pieces, ident = {}, None
    for f in frags:
        ihl = (f[0] & 0xF) * 4
        ident = struct.unpack("!H", f[4:6])[0]
        mf, off = bool(int.from_bytes(f[6:8],"big") & 0x2000), \
                  (int.from_bytes(f[6:8], "big") & 0x1FFF) * 8
        pieces[off] = f[ihl:]                    # overlap silently wins — real stacks detect!
    if any(mf for f in frags):                   # last frag missing?
        if not any((struct.unpack("!H", f[6:8])[0] & 0x2000) == 0
                   for f in frags): pass
    expected, got = 0, sorted(pieces)
    for o in got:                                # gap check
        if o != expected: return None
        expected += len(pieces[o])
    print(f"  reassembled id={ident}: {expected} bytes")
    return b"".join(pieces[o] for o in got)

payload = bytes(random.getrandbits(8) for _ in range(300))
dgram = build("192.168.1.20", "93.184.216.34", ident=777, payload=payload)
info = parse(dgram)
print("parsed:", {k: info[k] for k in ("ver","ihl_words","total",
      "ident","df","proto","cks_ok","src","dst")})
frags = fragment(dgram, mtu=128)
print(f"fragmented into {len(frags)} pieces @MTU128:")
for i, f in enumerate(frags):
    p = parse(f)
    print(f"  #{i} len={p['total']:4d} MF={int(p['mf'])} off={p['offset']}")
back = reassemble(frags)
assert back == payload and back is not None
print("roundtrip OK: fragments == original payload")

প্রত্যাশিত আউটপুর skeleton:

parsed: {'ver': 4, 'ihl_words': 5, 'total': 320, 'ident': 777,
         'df': True, 'proto': 'UDP', 'cks_ok': True,
         'src': '192.168.1.20', 'dst': '93.184.216.34'}
fragmented into 3 pieces @MTU128:
  #0 len= 124 MF=1 off=0
  #1 len= 124 MF=1 off=112
  #2 len=  96 MF=0 off=224
  reassembled id=777: 300 bytes
roundtrip OK: fragments == original payload

সূক্ষ্ম শিক্ষা: fragment()-এ // 8 * 8 — offset-alignment-এর contract না-মানলে real receiver আপনার খণ্ড ফেলে দেবে; reassemble()- এ gap-detect — হারানো খণ্ডে None ফেরা বাধ্যতামূলক behavior।

নিজে বাড়ান:

  1. reassemble()-এ overlap-detection যোগ করুন (teardrop-attack-এর defense) — দুই খণ্ড same-range দিলে reject
  2. DF-set datagram fragment করতে চাইলে exception ছুড়ুন — router-এর আসল behavior
  3. parse()-কে options-aware করুন: IHL>5 হলে option-TLV পড়ুন (record-route খুঁজুন)

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

PMTUD blackhole — সবচেয়ে নীরব production-killer

Firewall ICMP ‘frag-needed’ block-করলে DF-set 1500B ছোট-MTU-link-এ নীরব-drop, sender অন্ধ — ‘connects-but-page-never-loads’। Diagnosis: ping -M do-sweep; fix: MSS-clamping। Career-এ একবার-হলে এই-lesson মনে-পড়বে।

Cloud-TTL-budget

AWS/Azure-তে microservice-proxy-stack গভীর হলে internal-TTL-শেষ → ‘time-exceeded’ — deep service-graph debug-এ internal-subnet-traceroute-ও দরকার।

DSCP-র enterprise-জীবন

VoIP-deployment EF-marking edge-এ, priority-queue core-এ — ভিড়েও call-quality constant। SD-WAN DSCP-কে path-selection-signal-ও করেছে: video→fiber, bulk→cheap-link।

Fragmentation-free future

QUIC-এ DPLPMTUD (ICMP-ছাড়া probing), IPv6 router-fragmentation নেই-ই। 50-year arc: feature → anti-pattern → sender-responsibility — দায়িত্ব user-এর-কাছে-সরানোই protocol-evolution।

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

“IP packet হারালে network নিজেই retransmit করবে।”

না — IP চুক্তি মতো চুপ; হারানো packet-এর খবরও নেই। Retransmission transport-এর দায়: TCP করে (tcp-reliability), UDP করে না (app করলে তার ইচ্ছা)। Layering-এর মূল পাঠ: প্রতিটা guarantee-র একটা নির্দিষ্ট ঠিকানা আছে।

“Router-রা packet reorder করে বলেই out-of-order আসে।”

Reorder কোনো device-এর ইচ্ছা নয় — parallel paths, ECMP-hash, queue- timing-এর side-effect। Router প্রতিটা packet independent ভেবে route করে (stateless design); ক্রম রাখা receiver/TCP-র দায়।

“Fragmentation এখনো প্রতিদিন ঘটে, তাই প্রতিটা host-এর ভালো fragment-handling দরকার।”

Modern internet-এ DF-default + PMTUD + MSS-clamping-এ transit-fragmentation practically extinct — ব্যতিক্রম tunnel/legacy। Attack-surface হিসেবে তবু জীবন্ত (bypass-filter tricks), তাই firewall-গুলো আজও fragment strictly handle করে। Feature-এর মৃত্যু ≠ vulnerability-র মৃত্যু।

“Header checksum পুরো packet-এর integrity রক্ষা করে।”

শুধু header — data-র জন্য L4-checksum (TCP/UDP) বা TLS। আর transit-accidents-এর জন্যই — malicious tampering-এ attacker নতুন checksum হিসাব করেই দেয় (CRC-section মনে করুন)। Integrity-of-intent- এর জন্য keyed crypto, point।

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

1

Fixed IPv4 header-এর ছয়টা প্রধান field-এর নাম ও width বলুন (options ছাড়া যেগুলো সবসময় থাকে)।

স্মরণ

Version+IHL (1B), TOS/DSCP (1B), Total Length (2B), ID+Flags+ Offset (4B), TTL+Protocol (2B), Checksum (2B), Src (4B), Dst (4B) — মোট 20B।

2

MTU 1500-এ 2500-byte datagram কয়টা fragment-এ যাবে? প্রতিটার offset-value কী হবে?

প্রয়োগ

Per-frag data ≤ 1500−20 = 1480 (8-গুণিতক ✓)। ভাঙা: 1480B (off=0, MF=1) + বাকি 1020B (off=185, MF=0) — মোট ২টা। Trap: ‘2500÷1480 round-up = 3’ লেখা — header-space আগে-বাদ, পরে alignment-check।

3

কেন reassembly destination-এ, মাঝের router-রা কেন আবার জোড়া দেয় না?

যুক্তি

Statelessness: মাঝে-জোড়া দিতে-হলে router per-flow-reassembly-memory — scale/failure/DDoS ভাঙে। Destination-only → মাঝের-network-zero-state, memory-pressure end-host-এ (capacity বেশি, controllable)। e2e-principle- এর প্রথম-পাঠ।

4

Reply-এ TTL=57 এলে ফেরত-পথে কয়টা router? Sender-এর initial TTL 128 হলে তাহলে?

প্রয়োগ

Initial 64 হলে 64−57=7 hop। Initial 128 হলে 71 — কিন্তু 71-router return-path অসম্ভব-ish বলে inference: sender Windows (init 128), path ~71? না — সম্ভবত init-128 আর path 71 নয়, বরং আপনি init-assumption ভুল করেছেন। তাই TTL-থেকে-hop-count-এ initial-guess আগে ঠিক করুন (OS-fingerprint)।

5

IPv6 header-checksum ফেলে দিল কেন safe? কোন দুই স্তর error-coverage দেয় তার জায়গায়?

যুক্তি

L2-FCS (CRC32) প্রতি-hop-এ medium-error ধরে; L4-checksum (pseudo-header সহ) end-to-end header+content। মাঝের IP-checksum redundant — দাম প্রতি-hop recompute। Coverage-diversity দরকার, duplication নয়।

6

আপনার VPN-এর ভেতরে বড় HTTPS-download মাঝেমধ্যে hang করে, ছোট request চলে। Physical-MTU 1500, tunnel-overhead 80। Hypothesis আর test-plan?

ডিজাইন

Hypothesis: PMTU-blackhole — tunnel-এ inner-MTU 1420 দরকার, DF-set 1440+-packet drop, ICMP-feedback blocked বলে TCP নীরবে stall (ছোট packet পথে থাকে বলে চলে)। Test: ping -M do sweep 1392..1472 দিয়ে exact-PMTU; fix: interface-MTU clamp বা MSS-clamp firewall-এ। এই তিন-step প্যাটার্নই real-world SRE-debugging।

এরপর কী

এরপর কী

Datagram এখন পথে। কিন্তু প্রশ্ন রইল — 93.184.216.34-এর মতো ঠিকানা এলো কোথা থেকে? কোন অংশ network, কোন অংশ host? কে কাকে aggregate করে?

পরের লেসনে:

  • Dotted-decimal ↔ 32-bit binary fluency — চোখ-বন্ধ-করে হিসাব
  • Classful-যুগের waste-story আর CIDR-এর জন্ম
  • Netmask/prefix, network/broadcast/host-range — 2^(32-n)−2
  • /24 → two /25 split-এর bit-level walkthrough
  • RFC1918 private-space আর NAT-preview
  • Route-aggregation-এ table-size-গণিত

আজ শিখলাম container পড়া; পরের লেসনে শিখব ঠিকানার গণিত — পুরো internet-এর address-book যে নিয়মে সাজানো।

আরও পড়ুন

  • RFC 791 — Internet Protocol — J. Postel (ISI) · IPv4-র মূল spec — header diagram ও fragmentation-এর authoritative ভাষা
  • TCP/IP Illustrated, Volume 1: The Protocols — Chapter 3 (IP) — W. Richard Stevens · Header fields, fragmentation আর path-MTU-র wire-level উদাহরণ
  • Computer Networking: A Top-Down Approach — Network Layer chapter — Kurose & Ross · Datagram format আর best-effort service-model-এর পাঠ্যপুস্তক আলোচনা