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

ICMP, ping, traceroute — network-এর stethoscope

ICMP, Ping and Traceroute Internals

ping আর traceroute যে ICMP packet-গুলো ব্যবহার করে সেগুলোর type/code গোছানো anatomy, traceroute-এর TTL দিয়ে রাস্তার প্রতিটা router-কে কথা বলানোর চতুর কৌশল, আর ICMP বন্ধ করার লুকানো খরচ।

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

  • ICMP-এর ভেতরের কাঠামো ব্যাখ্যা করতে পারবেন — type/code/checksum জড়ো করে echo request/reply (type 0/8), destination unreachable (type 3) আর time exceeded (type 11)-কে wire-এ চিনতে পারবেন
  • ping-এর identifier + sequence number পদ্ধতি দিয়ে RTT মাপা হয় কীভাবে, আর min/avg/max/mdev পরিসংখ্যান প্রতিটার মানে কী — তা output থেকে বিশ্লেষণ করতে পারবেন
  • traceroute-এর TTL-abuse কৌশলটা step-by-step trace করতে পারবেন — কীভাবে ক্রমবর্ধমান TTL প্রতিটা hop থেকে time exceeded message 'ফসল' করে তোলে
  • UDP mode বনাম ICMP mode (-I) traceroute-এর পার্থক্য বুঝে, firewall ICMP drop করলে কোন mode-এ কোন hop অদৃশ্য হয়ে *** হয়ে যায় তা ব্যাখ্যা করতে পারবেন
  • PMTUD (Path MTU Discovery) কীভাবে ICMP frag-needed message-এর উপর নির্ভরশীল, আর ICMP পুরোপুরি block করলে কোন বাস্তব সমস্যা ঘটে — তা উদাহরণসহ বলতে পারবেন

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

আগে এটা বুঝি

network ভাঙলে সবার আগে যে দুইটা কমান্ড আঙুল থেকে বেরিয়ে আসে, সেগুলো ping আর traceroute। কিন্তু এই দুইটা tool যে protocol-এর উপর দাঁড়িয়ে আছে — ICMP — তার ভেতরটা খুব কম মানুষই দেখেছে। আজকের লেসনের কাজ সেই ভেতরটা দেখা।

একটা উপমা দিয়ে শুরু করি। হৃৎপিণ্ডের ডাক্তার রোগীর বুকে stethoscope ঠেকিয়ে শোনেন — রোগীকে কোনো ক্ষতি না করে, শুধু ভেতরের শব্দ শুনে অনুমান করেন কী চলছে। ICMP ঠিক internet-এর সেই stethoscope: data carry করে না, user-এর কোনো application-এ পৌঁছায় না, শুধু network- এর ভেতরের অবস্থা সম্পর্কে ছোট ছোট সংকেত বহন করে — “আমি জীবিত”, “ওই ঠিকানায় পৌঁছানো গেল না”, “packet-এর বয়স হয়ে গেছে, ফেরত পাঠালাম”।

আজকের follow-the-packet journey-তে আমরা একটা ছোট echo request- কে wire-এ পাঠাব আর দেখব:

  • ICMP message-টা IP datagram-এর ভেতরে ঠিক কোথায় বসে, তার 8-byte header-এর প্রতিটা field-এ কী থাকে
  • ping কীভাবে identifier + sequence number দিয়ে RTT (round-trip time) হিসাব করে — আর min/avg/max/mdev লাইনটা আসলে কী বলছে
  • traceroute কীভাবে IP-র TTL field-কে অপব্যবহার করে প্রতিটা intermediate router-কে নিজের পরিচয় ফাঁস করায়
  • আর কেউ ICMP পুরোপুরি block করে দিলে কী কী ভাঙে — শুধু আপনার diagnosis না, বড় transfer-ও

মূল ধারণা

ICMP কী, কোথায় বসে

IP নিজে সাধারণ এক delivery boy: packet নিয়ে ছুটে, best-effort — পৌঁছাল না? কেউ খোঁজ নেয় না। এই নীরবতা ঠিকঠাক চালানোর জন্য দরকার, কিন্তু ত্রুটি মোকাবিলার জন্য অপর্যাপ্ত। সেই ফাঁক পূরণ করে ICMP (Internet Control Message Protocol) — IP-রই সহোদর control protocol, যার কাজ তিনটা: error reporting, diagnostics, আর path-সম্পর্কিত তথ্য জানানো।

LayerTrace-এ জায়গাটা দেখুন — ICMP কার্যত IP-র ঠিক উপরে বসে, কিন্তু application layer-এ পৌঁছায় না:

ICMP-র স্তর-অবস্থান
  1. ApplicationHTTP, DNS, SSH — user data
  2. TCP / UDPports, reliability, streams
  3. ICMPcontrol messages — error ও diagnostics, port নেই
  4. IPaddressing ও routing — ICMP-র carrier
  5. Link / PhysicalEthernet, Wi-Fi, fiber

IP datagram-এর header-এ একটা Protocol field আছে (ip-datagram লেসনে দেখেছেন): TCP-র জন্য মান 6, UDP-র জন্য 17, আর ICMP-র জন্য 1। অর্থাৎ receiver-এর kernel IP header পড়েই বুঝে যায় — “এটা ICMP, কোনো socket-এ deliver না করে kernel-এর ICMP handler-কে দাও।”

8-byte header — প্রতিটা field

ICMP message-এর ঠিকানায় প্রথম 8 byte fixed:

ByteFieldকাজ
0TypeMessage-এর ধরন — পুরো অর্থের চাবিকাঠি
1CodeType-এর ভেতরের সূক্ষ্ম ভাগ
2–3Checksumপুরো ICMP message-এর অখণ্ডতা পরীক্ষা
4–5(Type ভেদে)Echo-তে: Identifier; Error-তে: unused/pointer
6–7(Type ভেদে)Echo-তে: Sequence number

এর পরে data অংশ। Echo message-এ এখানে arbitrary payload; error message-এ থাকে সেই original packet-এর IP header + প্রথম 8 byte — যাতে sender বুঝতে পারে ঠিক কোন packet-এর জন্য এই ভুল খবর এসেছে।

যে type/code গুলো আসলেই কাজে লাগে

শত শত type defined, কিন্তু বাস্তব জীবনে যেগুলো প্রতিদিন দেখবেন:

TypeCodeনামকে পাঠায়, কখন
80Echo Requestping — “কেউ আছিস?”
00Echo Replytarget host — “আছি!”
110Time Exceeded (TTL)router — packet-এর TTL ০ হয়ে গেছে
111Time Exceeded (reassembly)fragment reassembly timeout
30Destination Unreachable — netroute জানা নেই
31Destination Unreachable — hostfinal hop deliver করতে পারে না
33Destination Unreachable — portUDP-তে কেউ port-এ বসে নেই
34Fragmentation Neededrouter — packet MTU-র চেয়ে বড়, DF bit সেট
313Communication Administratively Prohibitedfirewall/admin বন্ধ করেছে

ping-এর অভ্যন্তরীণ যন্ত্র

ping আসলে খুব সরল state machine, প্রতি সেকেন্ডে এক পাক:

  1. একটা Identifier (process-এর জন্য প্রায় unique — পুরনো systems-এ PID) আর বাড়ন্ত Sequence Number (১, ২, ৩…) দিয়ে echo request পাঠাও, send timestamp মনে রাখো
  2. echo reply-র জন্য অপেক্ষা — reply-র identifier+seq মিলিয়ে ঠিক কোন probe-এর উত্তর তা বাছো
  3. recv_time − sent_time = RTT, রেকর্ড করো
  4. শেষে পরিসংখ্যান ছাপো

সেই শেষ লাইনটা প্রতিটা সংখ্যার মানে:

rtt min/avg/max/mdev = 10.2/12.8/21.4/2.9 ms
  • min — সবচেয়ে ভালো পাক; path-এর প্রকৃত latency-র নিচের সীমার সবচেয়ে কাছের অনুমান
  • avg — গড়; queueing delay মিলিয়ে দৈনন্দিন অভিজ্ঞতা
  • max — সবচেয়ে খারাপ পাক; একবারও বেশি ঝাঁকুনি খেলে এখানেই ধরা পড়ে
  • mdev (mean deviation) — ছড়ানো-ছিটানোর মাপ; VoIP/game- এর জন্য avg-এর চেয়ে mdev-ই বেশি গুরুত্বপূর্ণ, কারণ jitter buffer-এর আকার এটা ঠিক করে

ভেতরে কী ঘটছে

traceroute — TTL-কে অস্ত্র বানানোর গল্প

TTL field-টা ip-datagram লেসনে দেখেছেন: প্রতিটা router এক কমায়, শূন্য হলে packet ফেলে দিয়ে sender-কে time exceeded (type 11, code 0) ফেরত পাঠায়। RFC-তে এর উদ্দেশ্য ছিল routing loop-এ packet চিরকাল ঘুরতে না পারে তা নিশ্চিত করা।

1988 সালে Van Jacobson বুঝলেন — এই ত্রুটি-বার্তাটাই একটা ফ্রি measurement channel। Router কখনো নিজের পরিচয় announce করে না; কিন্তু তাকে বিরক্ত করলে সে রেগে গিয়ে নিজের address-সহ বার্তা পাঠিয়ে দেয়। কৌশল:

TTL=1 packet পাঠাও  →  hop-1 ফেলে দেয়  →  time exceeded ফেরে
                        (source = hop-1-এর address!)
TTL=2 packet পাঠাও  →  hop-2-তে TTL শূন্য  →  hop-2-র address ফেরে
TTL=3 ...           →  এভাবে চলতে থাকে
...
TTL=k-তে গন্তব্য পৌঁছালে  →  echo reply / port-unreachable ফেরে
                            →  থেমে যাও, পথ সম্পূর্ণ

প্রতিটা TTL-এ সাধারণত ৩টা করে probe পাঠায় — তাই output-এ প্রতি লাইনে তিনটা RTT।

তিনটা mode — কেন একই পথে output আলাদা হয়

Probe packet নিজে কী, তার উপর গন্তব্যে পৌঁছানোর “সিগন্যাল” নির্ভর করে:

ModeProbeশেষ hop চেনা যায় কীভাবেদৃশ্যমানতা
Default (Linux traceroute)UDP, উচ্চ port (33434+)destination-unreachable code 3 (port closed)NAT/firewall-বান্ধব, তবে raw socket লাগে
-IICMP echo requestecho reply (type 0)অনেক firewall echo পথ দেয় — বেশি hop দেখা যায়
-T (TCP mode)TCP SYN (যেমন -p 443)SYN-ACK বা RSTHTTPS-port প্রায় কোথাও বন্ধ করা হয় না

Intermediate hops-এর জন্য তিনটাই একই সূত্রে কাজ করে — time exceeded। পার্থক্য শুধু শেষ মাথায়।

*** লাইন — নিখোঁজ না, নীরব

Output-এ মাঝে মাঝে দেখবেন:

 4  * * *
 5  142.250.226.209 (142.250.226.209)  12.3 ms  11.9 ms  12.1 ms

hop 4 কোনো reply দেয়নি — কিন্তু hop 5 উত্তর দিয়েছে, অর্থাৎ hop-4 দিয়ে traffic যাচ্ছে-ই, সে শুধু time-exceeded বার্তা পাঠাতে অস্বীকার করছে। কারণগুলো:

  • Data-plane ASIC-এ forwarding হয় প্রায় হার্ডওয়্যার গতিতে, আর ICMP generation চলে ধীর CPU-তে — অনেক core router নিজের CPU বাঁচাতে rate-limit বা পুরোপুরি বাদ দেয়
  • Security policy: time-exceeded ফাঁস করানো topology-র তথ্য দেয়
  • TTL-এর চেয়ে ছোট internal hop-count সহ load balancer

মনে রাখবেন: *** মানে নীরবতা, মৃত্যু নয়।

mtr — traceroute-এর continuous রূপ

mtr (My Traceroute) এই একই কৌশল চালায় থেমে না — প্রতি hop-এ শত শত probe ঢেলে live পরিসংখ্যান দেখায়: Loss%, Snt, Avg, Best, Wrst, StDev। একবারের traceroute একটা ছবি; mtr একটা চলচ্চিত্র — কোন hop-এ সমস্যা কখন হয় তা ধরতে এটাই দরকার।

PMTUD — ICMP-র সবচেয়ে গুরুত্বপূর্ণ চাকরি

Path MTU Discovery নিয়মটা সরল: sender প্রথমে DF (Don’t Fragment) bit সেট করে সর্বোচ্চ মাপের packet পাঠায়। পথে কোনো link-এর MTU ছোট হলে router packet-টা ফেলে দিয়ে ফেরত পাঠায় destination unreachable, code 4 — fragmentation needed — আর বার্তার ভেতরে লেখা থাকে ওই link-এর MTU। Sender নিজের MSS কমিয়ে আবার চেষ্টা করে।

এই পুরো যন্ত্রটা ICMP-র উপর দাঁড়িয়ে। এখন কেউ ভাবুক সে “security”-র নামে ICMP পুরোপুরি block করে দিলে: code-4 বার্তা আর আসে না, sender অন্ধভাবে বড় packet-ই পাঠাতে থাকে, সব ফেলে যায় — connection তৈরি হয়, handshake চলে, ছোট packet চলে… কিন্তু বড় bulk transfer আটকে যায় রহস্যময়ভাবে। এটাই কুখ্যাত PMTUD blackhole — ঐতিহাসিক ভাবে এত common যে Linux-এর net.ipv4.tcp_mtu_probing জাতীয় workaround-এর জন্ম দিয়েছে।

উদাহরণ

একটা ping output-কে কঙ্কাল পর্যন্ত খোলা

$ ping -c 3 example.com
PING example.com (93.184.216.34) 56(84) bytes of data.
64 bytes from 93.184.216.34: icmp_seq=1 ttl=56 time=11.4 ms
64 bytes from 93.184.216.34: icmp_seq=2 ttl=56 time=10.9 ms
64 bytes from 93.184.216.34: icmp_seq=3 ttl=56 time=11.2 ms

--- example.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 10.900/11.166/11.400/0.205 ms

লাইন ধরে ধরে:

  • 56(84) bytes — ICMP payload 56 byte, বন্ধনীতে 84 = 20-byte IP header + 8-byte ICMP header + 56 payload
  • icmp_seq=2 — sequence number; একটাও লাফিয়ে গেলে (1, 2, 4) মাঝে একটা reply lost বা দেরিতে এসেছে
  • ttl=56 — reply-টা আসতে 56 router পার হয়নি; যদি জানেন OS-এর default TTL 64 (macOS/Linux), তাহলে reverse-path-এ আনুমানিক 64 − 56 = 8 hop
  • time=11.4 ms — send থেকে recv, এই এক probe-এর RTT
  • 0% packet loss, time 2003ms — ৩টা probe ~২ সেকেন্ডে (1s interval)

একটা traceroute-কে পড়া

$ traceroute example.com
traceroute to example.com (93.184.216.34), 30 hops max, 60 byte packets
 1  192.168.1.1 (192.168.1.1)     1.204 ms  1.101 ms  1.087 ms
 2  100.64.0.1 (100.64.0.1)       8.902 ms  9.114 ms  8.995 ms
 3  ae-3.core1.isp.net (203.0.113.9)   12.40 ms  12.31 ms  12.55 ms
 4  * * *
 5  93.184.216.34 (93.184.216.34) 11.80 ms  11.72 ms  11.95 ms
  • Hop 1: আপনার বাসার router — private address
  • Hop 2: 100.64.x.x — CGNAT/ISP carrier-grade range (RFC 6598)
  • Hop 3: ISP-র core, interface name-সহ (ae-3 = aggregated ethernet)
  • Hop 4: তিন probe-ই নীরব — কিন্তু hop 5 উত্তর দিয়েছে, তাই পথ অক্ষত
  • Hop 5: গন্তব্য নিজেই — default UDP mode-এ এটা আসলে port-unreachable (type 3, code 3) দিয়ে সমাপ্তি জানিয়েছে, traceroute সেটাকেই ”!X” style marker না দিয়ে শেষ লাইন হিসেবে দেখায়

লক্ষ্য করুন hop-3 আর hop-5-এর RTT প্রায় সমান (~12 vs ~11.8) — মাঝের hop-4 নীরব হওয়া সত্ত্বেও পথের latency সেখানে বাড়েনি।

ছবিতে

পুরো ছবি এক নজরে

traceroute-এর প্রথম তিন TTL-step-এর exchange timeline:

Host                Router A              Router B            Destination
  |                     |                     |                     |
  |-- TTL=1 echo req -->|                     |                     |
  |<- time exceeded ----|  (src=A!)           |                     |
  |   ttl=0             |                     |                     |
  |                                           |                     |
  |-- TTL=2 echo req ------------------------>|                     |
  |<- time exceeded ------------------------------------|           |
  |                       ttl=0 at B          |           |
  |                                                       |         |
  |-- TTL=3 echo req ------------------------------------------------>|
  |<- echo reply (type 0) <--------------------------------------------|
  |                                                                   |
  শেষ: "port unreachable"/"reply" = গন্তব্য পৌঁছেছে, থামো
TTL বাড়ানোর প্রতিটা ধাপে এক নতুন router নিজের address ফাঁস করে — প্রতিটা লাইন একটা করে নতুন hop আবিষ্কার।

আর echo request/reply-র নিজের round-trip-এ field-গুলোর ভূমিকা:

pinger                          kernel                 remote host
  |                               |                         |
  | build: type=8, id=X, seq=1,   |                         |
  | checksum, 56B payload, t0     |                         |
  |------------------------------>|-- IP proto=1 ---------->|
  |                               |                         |
  |                               |      kernel ICMP handler|
  |                               |      swap type 8 -> 0,  |
  |                               |      copy id/seq/payload|
  |                               |<------------------------|
  |<-- reply: type=0, id=X,       |                         |
  |    seq=1, same payload        |                         |
  | match(id,seq) -> t1           |                         |
  | RTT = t1 - t0                 |                         |
ping-এর এক পাক — identifier+sequence মিলিয়ে reply তার জোড়া request-এর সাথে bind হয়, RTT মাপা হয় একই clock-এ দুই মুহূর্তের ব্যবধানে।

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

EXPERIMENT

নিজের হাতে size, TTL আর তিন mode-এ traceroute

macOS / Linux· ২০ মিনিট

ধাপ ১ — payload size বদলে PMTU-র গন্ধ নিন:

# default 56-byte payload
ping -c 2 example.com
# বড় payload: -s bytes (IP+ICMP overhead মিলিয়ে মোট জানতে চাইলে)
ping -c 2 -s 1400 example.com
# সীমা ছাড়ানোর চেষ্টা — local MTU 1500 হলে এটা fail করা উচিত
ping -c 2 -s 1473 example.com
# macOS: প্রথম দুইটা flag-এ 'do not fragment'-সহ পাঠায় না;
# Linux-এ DF-সহ সীমা খুঁজতে:
# ping -M do -s 1472 example.com   # 1472+28=1500 → ঠিক MTU-তে ধরা

-s 1473 ব্যর্থ হলে বার্তাটা খেয়াল করুন — এটাই local MTU সীমা (1500 − 28 header = 1472 max payload)।

ধাপ ২ — TTL নিজে হাতে কমান:

ping -c 1 -t 2 example.com    # macOS flag: -t ; Linux: -t/-o ভিন্ন নয়
ping -c 1 -t 1 example.com    # এবার প্রথম hop-ই থামাবে
# প্রত্যাশিত: "Time to live exceeded"-জাতীয় ভুল — এটাই
# traceroute-এর শোষণ করা বার্তা, আপনি এখন নিজেই trigger করলেন

ধাপ ৩ — তিন mode-এ traceroute, পার্থক্য তুলনা করুন:

# default UDP mode (raw socket লাগে — sudo দিন অথবা setuid binary হলে ছাড়াই চলবে)
sudo traceroute -N 1 -q 1 -w 2 example.com
# ICMP mode — echo request হিসেবে probe
sudo traceroute -I -N 1 -q 1 -w 2 example.com
# TCP mode — port 443-এ SYN (HTTPS প্রায় সব জায়গায় খোলা)
sudo traceroute -T -p 443 -N 1 -q 1 -w 2 example.com

(-N 1 -q 1 মানে একবারে ১ probe, প্রতি TTL-এ ১ বার — পরিষ্কার output-এর জন্য; বাস্তব ব্যবহারে default 3-ই রাখুন।)

দেখার বিষয়: কোন mode-এ কয়টা hop উত্তর দিল, কোথায় * এলো? সাধারণত ICMP/TCP mode UDP-র চেয়ে বেশি জায়গায় উত্তর পায়, আর -T -p 443 এমন firewall-ও পার হয় যেখানে echo বন্ধ।

ধাপ ৪ — mtr-এ ৬০ সেকেন্ড বসে থাকুন:

sudo mtr -rw -c 60 example.com   # report mode, 60 probe, শেষে exit

Report-এর প্রতিটা column একবার উপরের hood section-এর ব্যাখ্যার সাথে মিলিয়ে পড়ুন — বিশেষত মাঝের কোনো hop-এ Loss% থাকলে পরের hop-এ সেটা টিকে আছে কি না চেক করুন।

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

ping-এর option-গুলো সরাসরি ICMP header-এর field ম্যানিপুলেট করে, আর traceroute-এর mode-বদল প্রমাণ করে যে hop visibility নির্ভর করে কোন message-এর উপর — firewall কোনটা ছেড়ে দেয় তার উপর।

নিজে বানান

BUILD IT

mini-traceroute — pure-socket TTL-walker

Python · ●●●○○
  1. UDP socket দিয়ে probe পাঠান, setsockopt(IP_TTL, ttl) দিয়ে প্রতিবার TTL এক করে বাড়ান
  2. আলাদা raw ICMP socket (IPPROTO_ICMP) খুলে select() দিয়ে time-exceeded অপেক্ষা করুন
  3. ICMP payload-এর ভেতরের original IP header থেকে বিরক্তকারী router-এর source address বের করুন
  4. echo-reply/port-unreachable পেলে থামুন — পথ সম্পূর্ণ
  5. PermissionError ধরে sudo ছাড়া চালালে ব্যবহারকারীকে ব্যাখ্যা-সহ বিদায় জানান

লক্ষ্য: traceroute-এর মূল কৌশল — TTL বাড়িয়ে বাড়িয়ে প্রতিটা router-কে time-exceeded বলতে বাধ্য করা — নিজের হাতে implement করা, কোনো scapy/library ছাড়া, খাঁটি stdlib দিয়ে।

Privilege caveat: raw ICMP socket তৈরিতে root লাগে। চালাবেন sudo python3 mini_trace.py example.com দিয়ে; sudo ছাড়া চালালে প্রোগ্রামটা নিজেই ব্যাখ্যা করে বন্ধ হবে।

import socket, struct, select, sys, time

DEST_PORT = 33434          # traceroute convention
PROBE_TTL_MAX = 20
TIMEOUT = 2.0

def icmp_socket():
    # SOCK_RAW + IPPROTO_ICMP => শুধু ICMP দেখবে; sudo/root লাগে
    s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
    s.settimeout(TIMEOUT)
    return s

def inner_source(icmp_bytes):
    """time-exceeded-এর payload-এ থাকা original IP header থেকে src IP"""
    orig = icmp_bytes[8:]                    # ICMP header 8 byte পরে original packet
    if len(orig) >= 24:
        ihl = (orig[0] & 0x0F) * 4           # original IP header-এর দৈর্ঘ্য
        if len(orig) >= ihl + 16:
            return socket.inet_ntoa(orig[ihl + 12 : ihl + 16])
    return None

def main(target):
    dst_ip = socket.gethostbyname(target)
    print(f"trace to {target} ({dst_ip}), max {PROBE_TTL_MAX} hops")
    icmp = icmp_socket()
    udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    for ttl in range(1, PROBE_TTL_MAX + 1):
        udp.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, ttl)
        udp.sendto(b"kilo-probe", (dst_ip, DEST_PORT))
        t0 = time.monotonic()

        reached = False
        deadline = t0 + TIMEOUT
        while True:
            remain = deadline - time.monotonic()
            if remain <= 0:
                print(f"{ttl:>2}  *  (timeout)")
                break
            r, _, _ = select.select([icmp], [], [], remain)
            if not r:
                continue
            data, addr = icmp.recvfrom(512)
            # BSD-তে raw socket IP-header-সহ দেয়, Linux-এও প্রায়ই দেয় —
            # version nibble দেখে ICMP-র শুরু বের করি
            off = (data[0] >> 4) == 4 and (data[0] & 0x0F) * 4 or 0
            itype, icode = data[off], data[off + 1]
            rtt = (time.monotonic() - t0) * 1000
            if itype == 11 and icode == 0:
                hop_ip = addr[0] if addr else inner_source(data[off:])
                print(f"{ttl:>2}  {hop_ip}   {rtt:7.2f} ms")
                break
            if itype == 3:                   # destination unreachable family
                print(f"{ttl:>2}  {addr[0]}   {rtt:7.2f} ms  !  (unreachable code={icode})")
                reached = True
                break
            if itype == 0:                   # কেউ echo-reply দিল (কিছু host করে)
                print(f"{ttl:>2}  {addr[0]}   {rtt:7.2f} ms  (echo reply)")
                reached = True
                break
        if reached:
            break

if __name__ == "__main__":
    try:
        main(sys.argv[1] if len(sys.argv) > 1 else "example.com")
    except PermissionError:
        print("raw socket-এর জন্য root দরকার:  sudo python3 mini_trace.py <host>")

প্রত্যাশিত output-এর আকার:

$ sudo python3 mini_trace.py example.com
trace to example.com (93.184.216.34), max 20 hops
 1  192.168.1.1      1.31 ms
 2  100.64.0.1       9.02 ms
 3  203.0.113.9     12.47 ms
 4  *  (timeout)
 5  93.184.216.34   11.88 ms  !  (unreachable code=3)

শেষ লাইনের code=3 মানে destination নিজে port-unreachable দিয়ে বলেছে “আমি এখানেই, এই port-এ কেউ নেই” — ঠিক আসল traceroute-এর default UDP mode যেভাবে শেষ হয়।

নিজে বাড়ান:

  1. প্রতি TTL-এ ৩টা probe পাঠিয়ে min/avg/max দেখান (আসল traceroute-এর মতো)
  2. Reverse-DNS যোগ করুন — socket.gethostbyaddr() দিয়ে hop name
  3. -I mode যোগ করুন: একই ICMP socket-এ type-8 echo পাঠিয়ে reply-র অপেক্ষায়; শেষ hop তখন echo-reply দিয়ে শেষ হবে

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

বাস্তব জগতে এই জিনিসগুলো কোথায়

PMTUD blackhole ঘটানো firewall। Enterprise edge firewall-এ “block all ICMP” policy এখনো দেখা যায় — ফলে VPN-এর ওপারে বড় file transfer আটকে যায়, ওয়েবসাইটের অর্ধেক page লোড হয় (ছোট response), অন্য অর্ধেক হ্যাং। আধুনিক best practice: echo-request বন্ধ করুন যদি ইচ্ছা, কিন্তু type 3 code 4 অবশ্যই ছেড়ে দিন।

Cloud provider-দের default security group। AWS/GCP-র fresh instance-এ ping by-default বন্ধ — প্রথমবার instance তৈরি করে ping fail করলে নতুনরা ভাবে server dead; আসলে শুধু ICMP echo filter হয়ে আছে।

mtr অপস runbook-এ। যেকোনো CDN/cloud provider-এর support ticket- এর প্রথম request প্রায়ই “both directions থেকে mtr পাঠান” — কারণ loss/asymmetry শুধু continuous measurement-এই ধরা পড়ে, one-shot traceroute-এ নয়।

RIPE Atlas আর looking glass। বিশ্বজুড়ে হাজার হাজার volunteer vantage point থেকে ping/traceroute চালানোর network আছে — BGP hijack সন্দেহ হলে একাধিক দেশ থেকে path তুলনা করেই প্রমাণ হয় traffic ভুল দিকে যাচ্ছে কি না।

Submarine cable fault হান্টিং। ২০২৪-এ Red Sea cable cut-এর সময় operator-রা regional traceroute-এর ভিত্তিতেই বলেছিল কোন path-গুলো reroute হয়েছে — hop-by-hop latency jump দেখে fault-এর geographic এলাকা অনুমান করা যায়।

Game/VoIP support টিকিট। “lag হচ্ছে” রিপোর্টের প্রথম diagnostic step: ব্যবহারকারীকে ping -n 60 gateway আর mtr চালাতে বলা — mdev spike দেখে jitter না কি genuine congestion, আলাদা করা যায়।

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

“Ping উত্তর না দিলে host বন্ধ বা নেই।”

ping-এর উত্তর দেয় kernel-এর ICMP handler — সেটা শুধু প্রমাণ করে IP stack জীবিত আর echo-reply দেওয়ার অনুমতি আছে। Host-এর webserver, database, SSH — কিছুই এর সাথে জড়িত না। Firewall echo drop করলে সম্পূর্ণ সুস্থ server-ও ping-এ নীরব; আর ভাঙা webserver সহ একটা machine হয়তো ping-এ সবচেয়ে দ্রুত উত্তর দেয়। Ping হলো liveness signal, service health check নয়।

“Traceroute-এর `***` মানে ওই router নষ্ট, traffic ওই দিয়ে যায় না।”

উল্টো প্রমাণ ওই output-এই আছে: hop 4 তিনবার নীরব হয়েও hop 5 উত্তর দিয়েছে — packet তাহলে hop 4 পার হয়েই গেছে, নইলে hop 5-এ কীভাবে পৌঁছাত? *** মানে শুধু “এই hop time-exceeded পাঠায় না”। Rate-limit, ASIC-vs-CPU architecture, বা policy — কারণ যা-ই হোক, forwarding ওই সম্পর্কিত নয়।

“ICMP শুধু debugging tool — security-র জন্য পুরোটা block করা নিরাপদ।”

এই single rule-ই PMTUD ভাঙে: fragmentation-needed (type 3, code 4) বন্ধ থাকলে বড় packet নীরবে ফেলে যায়, connection তৈরি হয় কিন্তু bulk transfer আটকে যায় — কুখ্যাত blackhole। সঠিক posture: echo request-এর ingress সীমিত করুন, কিন্তু outbound ICMP error flow করুন আর inbound error (বিশেষত code 4) receive করুন। ICMP-র diagnostic ভূমিকা ছোট; transport-সহায়ক ভূমিকাটা বাঁচানো জরুরি।

“Ping-এর time মানে দুই মেশিনের মধ্যে physical distance-এর সময়।”

RTT-তে distance-এর propagation delay মাত্র একটা উপাদান — তার সাথে মিশে আছে serialization delay, per-hop queuing delay, router lookup, rate-limited reply processing, এমনকি আপনার নিজের Wi-Fi airtime। Fiber-এ light প্রতি 1000 km-এ ~5 ms একমুখী — কিন্তু একই 1000 km overloaded link-এ 50 ms দেখাতে পারে। তাই একই দূরত্বের দুই destination- এর RTT ৫ গুণ আলাদা হওয়াটা ব্যতিক্রম নয়।

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

1

ICMP echo request আর echo reply-র type number কোনটা? এবং destination-unreachable-এর কোন code-টা Path MTU Discovery-র জীবনরক্ষক?

স্মরণ

Echo request type 8, echo reply type 0। PMTUD-র জন্য destination-unreachable (type 3) এর code 4 — fragmentation needed — এই বার্তাতেই router নিজের link-এর MTU জানায়, যা দেখে sender MSS কমায়।

2

একটা reply-তে ttl=118 দেখলেন। Sender Windows machine (default TTL 128)। ফেরত-পথে আনুমানিক কত hop? এই অনুমান forward-path-এর hops-এর সমান না-ও হতে পারে কেন?

প্রয়োগ

128 − 118 = 10 hop — ফেরত-পথের আনুমানিক সংখ্যা। Internet-এর routing asymmetric: ফেরত packet ভিন্ন BGP path ধরতে পারে, ভিন্ন router সেট দিয়ে যেতে পারে। তাই এই সংখ্যা forward-path traceroute- এর সাথে না-ও মিলবে — আর এটাই normal।

3

Default UDP-mode traceroute গন্তব্যে পৌঁছে “শেষ হয়েছে” বুঝলে কোন ICMP message দেখে? আর একটা middle-hop নীরব (***) থাকলেও traceroute কেন থেমে যায় না?

যুক্তি

শেষ হয় type 3, code 3 (port unreachable) — উচ্চ port-এ কেউ listen করছে না, destination-এর kernel সেটা জানিয়ে দেয়, traceroute বুঝে নেয় গন্তব্য পৌঁছেছে (কারণ এই বার্তা শুধু destination-ই দিতে পারে — middle-hop TTL-শূন্যে type 11-ই দেয়)। Middle-hop নীরব থাকলেও পরের TTL-এ পরের hop উত্তর দেয় — তাই walk চলতেই থাকে; নীরব hop শুধু একটা ফাঁকা লাইন হয়ে থাকে।

4

mtr report-এ hop 6-এ Loss% = 40, কিন্তু hop 7 ও hop 8-এ Loss% = 0 এবং Avg latency ঠিক আছে। এই 40%-কে real packet loss ধরা যাবে কি?

যুক্তি

না। Real congestion-loss হলে পরের hop-গুলোতেও সেই loss দেখা যেত — packet যেহেতু পরের hop-এ পৌঁছাতেই হয়। শেষ hop-গুলো clean মানে forwarding অক্ষত; hop 6 শুধু time-exceeded reply-তে rate-limit মেরেছে (probe-দের কিছু উত্তর দেয়নি), যা mtr-এ loss-এর মতো দেখায় কিন্তু data-plane-এর সাথে সম্পর্কিত নয়।

5

আপনি একটা company-র edge firewall design করছেন। ICMP-র জন্য একটা সংক্ষিপ্ত, যুক্তিযুক্ত allow/block policy লিখুন — কোনটা ব্লক করবেন, কোনটা আদৌ না, কেন।

ডিজাইন

একটা বাস্তবসম্মত নীতি:

  • Inbound echo request (type 8): untrusted internet-থেকে rate-limit বা ব্লক — reconnaissance সহজ করে না দিতে; internal zone-থেকে allow
  • Outbound echo request/reply: allow — আপনার নিজের diagnosis দরকার
  • Inbound ICMP errors (type 3, 11): allow — না হলে আপনার নিজের client-দের PMTUD ভাঙবে, traceroute অন্ধ হবে
  • Outbound ICMP errors: allow — ভিন্ন পক্ষের সেইম কারণে
  • Rate-limit ICMP generation overall (CPU protection), পুরো ব্লক নয়

মূল সূত্র: echo-তে সতর্কতা, error-তে উদারতা।

6

ping-এ mdev = 0.2 ms এক destination-এ, আরেকটাতে mdev = 18 ms (avg দুটোতেই ~25 ms)। VoIP-র জন্য কোনটা বেশি সমস্যা এবং কেন?

প্রয়োগ

দ্বিতীয়টা। VoIP-র playback buffer ঠিক করে variation (jitter) — avg 25 ms হলেও stable হলে শুনতে ভালো লাগে; কিন্তু 18 ms deviation মানে packet-arrival gap বারবার লাফায় — buffer ছোট হলে late packet drop হবে, বড় হলে কথার delay বাড়বে। এজন্যই mdev আলাদা করে ছাপা হয়: একই average-এর নিচে দুইটা সম্পূর্ণ আলাদা বাস্তবতা।

এরপর কী

এরপর কী

আমরা দেখলাম network নিজের সমস্যা কীভাবে কথায় জানায়। এবার দেখব application-এর data কীভাবে যায় — সবচেয়ে সরল উপায়ে: UDP।

পরের লেসনে:

  • 8-byte header-টা field-by-field খুলব — আজকের checksum আলোচনার ones’-complement গণিতটা সেখানে পুরোদেহি ফিরবে
  • কী কী ছেড়ে দিলে নাম হয় “connectionless” — আর ঠিক সেই ছাড়গুলোর জন্যই DNS, VoIP, game আর QUIC কেন UDP বেছে নেয়
  • Datagram boundary মানে কী — কেন UDP-তে দুই message কখনো একসাথে মিশে না, অথচ TCP-তে মেশে

আজকের mini-traceroute-এ UDP probe পাঠিয়েছিলেন না-কি? পরের লেসনের build-এ সেই UDP-র ভেতরটাই লিখবেন।

আরও পড়ুন

  • TCP/IP Illustrated, Volume 1: The Protocols — ICMP, Ping and Traceroute chapters — W. Richard Stevens · ICMP header anatomy, ping/traceroute mechanics আর বাস্তব capture — এই লেসনের প্রধান ভিত্তি
  • RFC 792 — Internet Control Message Protocol — J. Postel (ISI) · ICMP-র original specification — type ও code-এর authoritative তালিকা
  • Computer Networking: A Top-Down Approach — Network Layer (Control Plane) — Kurose & Ross · ICMP-কে control-plane protocol হিসেবে দেখার কাঠামো আর ICMP-র ভূমিকার সংক্ষিপ্ত আলোচনা