ping ตอบได้แค่ว่าถึงหรือไม่ถึง คำถามถัดไปเสมอคือ "แล้วมันไปตายตรงไหน" และเครื่องมือที่ทุกคนหยิบมาตอบคำถามนั้นคือ traceroute บนลินุกซ์กับแมค หรือ tracert บนวินโดวส์
มันเป็นเครื่องมือที่คนใช้กันทุกวันและอ่านผิดกันมากที่สุด — เห็นดาวแล้วคิดว่าแพ็กเก็ตหาย เห็นฮอปกลางทางช้าแล้วโทษเราเตอร์ตัวนั้น และเชื่อว่ารายชื่อที่มันพิมพ์ออกมาคือเส้นทางที่แพ็กเก็ตของตัวเองเดินไปจริง
ทั้งสามข้อนั้นผิด และหน้านี้จะอธิบายว่าทำไม
ถ้ายังไม่รู้จัก TTL หรือ ICMP มาก่อน อ่าน ping — คำสั่งอายุ 40 ปีที่ยังใช้อยู่ทุกวัน ก่อนจะง่ายขึ้นมาก เพราะ traceroute สร้างอยู่บนกลไกเดียวกัน
ถ้ายังไม่เคยพิมพ์มาก่อน เริ่มตรงนี้
บนลินุกซ์หรือแมค
traceroute 8.8.8.8
บนวินโดวส์
tracert 8.8.8.8
สิ่งที่จะได้ (ฝั่งยูนิกซ์)
traceroute to 8.8.8.8 (8.8.8.8), 64 hops max, 40 byte packets
1 192.168.1.1 (192.168.1.1) 1.234 ms 1.101 ms 1.087 ms
2 10.4.0.1 (10.4.0.1) 8.412 ms 8.339 ms 8.502 ms
3 * * *
4 203.0.113.9 (203.0.113.9) 12.004 ms 11.887 ms 12.113 ms
5 8.8.8.8 (8.8.8.8) 12.331 ms 12.209 ms 12.288 ms
แต่ละบรรทัดคืออุปกรณ์หนึ่งตัวที่อยู่ระหว่างทาง เรียงจากใกล้ตัวคุณไปหาปลายทาง ตัวเลขสามค่าคือเวลาไปกลับของการยิงสามครั้ง และบรรทัดที่ 3 ที่เป็นดาวสามดวง คือฮอปที่ไม่ตอบ — ซึ่งไม่ได้แปลว่ามีอะไรพัง เดี๋ยวจะอธิบาย
ธันวาคม 1988 ที่ Lawrence Berkeley Laboratory
คนเขียนคือ Van Jacobson ชื่อเดียวกับที่อยู่เบื้องหลังอัลกอริทึมควบคุม ความแออัดของ TCP ที่ทำให้อินเทอร์เน็ตไม่ล่มในยุคปลายแปดสิบ ตอนนั้นเขาอยู่ที่ Lawrence Berkeley Laboratory เครื่องมือนี้จึงถูกเรียกกันว่า LBL traceroute
ในหัวไฟล์ซอร์สต้นฉบับมีบรรทัดหนึ่งเขียนว่า
-- Van Jacobson ([email protected]) Tue Dec 20 03:50:13 PST 1988
และมีอีกประโยคที่ตรงไปตรงมาจนน่าจำ
ผมขโมยไอเดียของโปรแกรมนี้มาจาก Steve Deering ตั้งแต่รุ่นแรกที่ปล่อยออกไป ผมเพิ่งรู้ว่าถ้าไปประชุมกลุ่มทำงาน IETF ที่ถูกที่ ผมก็คงขโมยมันมาจาก Guy Almes หรือ Matt Mathis ได้เหมือนกัน
คู่มือของโปรแกรมยังคงประโยคนี้ไว้จนถึงทุกวันนี้ — เปิด man traceroute บนเครื่องที่คุณนั่งอยู่แล้วเลื่อนลงไปหัวข้อ AUTHOR จะเห็นว่า "Implemented by Van Jacobson from a suggestion by Steve Deering"
แนวคิดการออกแบบ — ทำไมมันถูกสร้างมาแบบนี้
หัวข้อนี้คือส่วนที่ทำให้เข้าใจว่าทำไมเอาต์พุตหน้าตาแบบนั้น และทำไมมันถึงโกหกได้ในบางสถานการณ์
1. ไม่สร้างอะไรใหม่เลย ใช้ผลข้างเคียงของสิ่งที่มีอยู่แล้ว
traceroute ไม่ได้ขอความร่วมมือจากเราเตอร์ตัวไหนเลย
มันอาศัยกฎที่เราเตอร์ทุกตัวต้องทำอยู่แล้วสองข้อ — ลด TTL ลงหนึ่งทุกครั้งที่ ส่งต่อ และเมื่อ TTL เหลือศูนย์ให้ทิ้งแพ็กเก็ตแล้วส่ง ICMP Time Exceeded กลับไปบอกต้นทาง กฎสองข้อนี้มีไว้กันแพ็กเก็ตวิ่งวนไม่รู้จบ ไม่ได้มีไว้ให้ใคร สำรวจเส้นทาง
traceroute แค่จงใจตั้ง TTL ให้ต่ำเกินจริง แล้วเก็บคำบ่นที่ได้กลับมา ที่อยู่ของคนบ่นในแต่ละรอบ เรียงต่อกันก็กลายเป็นเส้นทาง
นี่คือเหตุผลที่มันใช้ได้กับเราเตอร์ของใครก็ได้ในโลก รวมถึงเครื่องที่ผลิตขึ้น หลังจากปี 1988 ไปสามสิบปี
2. ทำไมหมายเลขพอร์ตต้องเพิ่มขึ้นทุกครั้ง
ข้อนี้คือหัวใจของการออกแบบ และเป็นคำตอบของคำถามที่ว่า "แล้วมันรู้ได้ยังไงว่าคำบ่นที่ได้กลับมาเป็นของการยิงครั้งไหน"
ปัญหาคือ ข้อความ ICMP แจ้งข้อผิดพลาดพาข้อมูลของแพ็กเก็ตเดิมกลับมาแค่นิดเดียว ตามมาตรฐานมันแนบหัว IP ของแพ็กเก็ตที่ตายมาด้วย บวกกับข้อมูลถัดจากนั้น อีกเพียง 8 ไบต์
แปดไบต์นั้นสำหรับ UDP คือหัว UDP ทั้งหัวพอดี — พอร์ตต้นทาง พอร์ตปลายทาง ความยาว และ checksum ไม่มีที่ว่างเหลือให้ใส่หมายเลขลำดับอะไรเลย
Van Jacobson จึงใช้สิ่งที่มีอยู่แล้วเป็นตัวระบุ นั่นคือ หมายเลขพอร์ตปลายทาง โดยเพิ่มขึ้นทีละหนึ่งก่อนยิงทุกครั้ง คำบ่นที่กลับมาจึงพกหมายเลขพอร์ตนั้น ติดมาด้วยเสมอ และเทียบกลับได้ว่าเป็นของการยิงครั้งไหน
เทียบกับ ping ที่มีฟิลด์ Identifier กับ Sequence Number ให้ใช้ตรง ๆ traceroute ไม่มีอะไรแบบนั้น จึงต้องยืมฟิลด์ที่ออกแบบมาเพื่ออย่างอื่นมาทำหน้าที่นี้
3. ทำไมยิงไปที่พอร์ตสูง ๆ ที่ไม่มีใครฟัง
ค่าเริ่มต้นคือพอร์ต 33434 แล้วไล่ขึ้นไป เหตุผลคือ traceroute ต้องการ ให้ปลายทาง ไม่มีบริการอะไรฟังอยู่ที่พอร์ตนั้น
เมื่อไม่มีใครฟัง ปลายทางจะตอบกลับมาว่า ICMP Port Unreachable ซึ่งเป็นข้อความคนละชนิดกับ Time Exceeded ที่ได้จากเราเตอร์กลางทาง ความต่างนั้นเองคือสัญญาณว่า "ถึงปลายทางแล้ว หยุดได้"
ถ้าเผลอยิงไปโดนพอร์ตที่มีบริการฟังอยู่จริง ปลายทางจะไม่ตอบอะไรเลย และ traceroute จะไล่ TTL ต่อไปจนครบเพดานโดยไม่รู้ว่าถึงแล้ว
ซอร์สต้นฉบับไม่ได้อธิบายว่าทำไมถึงเลือกเลข 33434 โดยเฉพาะ มีเรื่องเล่ากันว่ามาจาก 32768 บวก 666 แต่ไม่มีอยู่ในโค้ดหรือคู่มือ จึงควรถือเป็นเกร็ดที่ยังพิสูจน์ไม่ได้
4. ยิงสามครั้งต่อหนึ่งฮอป
ค่าเริ่มต้นคือสามครั้ง เพราะ UDP ไม่รับประกันการส่งถึง การหายหนึ่งครั้ง จึงเป็นเรื่องปกติที่ไม่ควรทำให้ทั้งบรรทัดกลายเป็นความว่างเปล่า
และการเห็นสามค่าพร้อมกันทำให้เห็นความแปรปรวน ไม่ใช่แค่ค่ากลาง สามค่าที่ห่างกันมากบอกอะไรได้มากกว่าค่าเดียวที่ดูดี
5. รายงานสิ่งที่ได้ ไม่สรุปแทนคุณ
เหมือน ping ทุกประการ traceroute ไม่เคยบอกว่า "เส้นทางมีปัญหาที่ฮอปที่ 7" มันพิมพ์แค่ว่ายิงไปแล้วใครตอบ ใช้เวลาเท่าไหร่ และตรงไหนไม่มีใครตอบ การตีความเป็นงานของคน
ซึ่งเป็นเรื่องดี เพราะอย่างที่จะเห็นข้างล่าง การตีความผิดทำได้ง่ายมาก
มันทำงานอย่างไร
ไล่ตามลำดับคือ
- ยิงแพ็กเก็ตที่ตั้ง TTL เท่ากับ 1 → เราเตอร์ตัวแรกลดเหลือ 0 → ทิ้ง แล้วส่ง Time Exceeded กลับมา → ได้ชื่อฮอปที่ 1
- ยิงใหม่ด้วย TTL เท่ากับ 2 → ตัวแรกลดเหลือ 1 แล้วส่งต่อ ตัวที่สองลดเหลือ 0 → ได้ชื่อฮอปที่ 2
- ทำซ้ำไปเรื่อย ๆ
- จนกระทั่ง TTL มากพอที่จะถึงปลายทาง ซึ่งจะตอบ Port Unreachable แทน Time Exceeded → รู้ว่าจบแล้ว
สังเกตว่าไม่มีแพ็กเก็ตใดเลยที่เดินทางครบเส้นทางแล้วรายงานสิ่งที่มันเห็น แต่ละบรรทัดมาจากคนละแพ็กเก็ต คนละการเดินทาง และคนละช่วงเวลา ข้อนี้คือรากของทุกอย่างที่จะผิดพลาดได้ในหัวข้อถัดไป
ทำไม ICMP แจ้งข้อผิดพลาดพาข้อมูลกลับมาแค่ 8 ไบต์
แปดไบต์นั้นคือทั้งหมดที่ traceroute มีให้ใช้ระบุว่าคำบ่นเป็นของใคร และเป็นเหตุผลว่าทำไมการออกแบบถึงต้องยืมหมายเลขพอร์ตมาทำหน้าที่นั้น
อ่านเอาต์พุตให้ออก
4 203.0.113.9 (203.0.113.9) 12.004 ms 11.887 ms 12.113 ms
| | |
| | +-- เวลาของการยิงสามครั้ง
| +-- ใครตอบ ชื่อและหมายเลข
+-- ค่า TTL ที่ใช้ยิงรอบนั้น ไม่ใช่ "ลำดับที่แน่นอนบนเส้นทาง"
จุดที่คนอ่านผิดบ่อยที่สุดคือคิดว่าเลขหน้าบรรทัดคือลำดับที่ตายตัวของอุปกรณ์ บนเส้นทาง จริง ๆ แล้วมันคือ ค่า TTL ที่ใช้ยิงในรอบนั้น ซึ่งไม่เหมือนกัน เมื่อเส้นทางเปลี่ยนระหว่างการวัด
ดาว คือคำเดียวที่มีสี่ความหมาย
* แปลว่า "ยิงไปแล้วไม่มีอะไรกลับมาในเวลาที่รอ" เท่านั้น สาเหตุมีอย่างน้อยสี่แบบ และสามแบบในนั้นไม่ใช่ปัญหา
- เราเตอร์ตัวนั้นถูกตั้งค่าไม่ให้ส่ง ICMP Time Exceeded ออกมา ซึ่งพบบ่อยมาก ในเครือข่ายผู้ให้บริการ
- เราเตอร์จำกัดอัตราการส่ง ICMP ของตัวเอง เลยส่งบ้างไม่ส่งบ้าง
- คำตอบถูกส่งออกมาจริง แต่หายบนเส้นทางขากลับ
- ไฟร์วอลล์กลางทางทิ้งแพ็กเก็ตขาไป เพราะเป็น UDP ไปพอร์ตแปลก ๆ
กฎการอ่าน ดาวที่โผล่กลางทางแล้วฮอปถัดไปกลับมาตอบปกติ แทบไม่เคยเป็นปัญหา ดาวที่เริ่มจากฮอปหนึ่งแล้วไม่กลับมาอีกเลยจนจบ นั่นต่างหากที่น่าสนใจ
สัญลักษณ์หลังเวลา
ถ้าเห็นตัวอักษรตามหลังตัวเลขเวลา นั่นคือ traceroute บอกว่าได้ ICMP แจ้งข้อผิดพลาดชนิดอื่นกลับมา ไม่ใช่ Time Exceeded ธรรมดา
!H host unreachable ไปถึงเครื่องปลายทางไม่ได้
!N network unreachable ไปถึงเครือข่ายนั้นไม่ได้
!P protocol unreachable ปลายทางไม่รองรับโพรโทคอลนี้
!F fragmentation needed ใหญ่เกินและห้ามแตก พร้อมบอกค่า MTU
!S source route failed
!U !W destination network/host unknown
!I source host is isolated
!A ห้ามติดต่อเครือข่ายนั้นตามนโยบาย
!X !Z ห้ามติดต่อโดยทั่วไป / ห้ามติดต่อโฮสต์นั้นตามนโยบาย
! ค่า TTL ที่ตอบกลับมาเหลือ 1 หรือน้อยกว่า
!A กับ !Z มีความหมายชัดเจนมากในทางปฏิบัติ — แปลว่ามีคนตั้งใจกั้นไว้ ไม่ใช่ของเสีย ส่วน !F เป็นเบาะแสตรงของปัญหา MTU ซึ่งอธิบายไว้ในบทความ ping
สามสายพันธุ์ที่ยิงคนละอย่าง
นี่คือเรื่องที่ทำให้คนสองคนได้ผลไม่เหมือนกันทั้งที่ยิงไปที่เดียวกัน
Linux, macOS, BSD ยิง UDP ไปพอร์ตสูง ค่าเริ่มต้น
Windows tracert ยิง ICMP Echo ค่าเริ่มต้น
traceroute -I ยิง ICMP Echo เหมือน Windows
traceroute -T ยิง TCP SYN ทะลุไฟร์วอลล์ได้ดีที่สุด
traceroute -P proto เลือกเอง เช่น UDP TCP GRE ICMP
ความต่างนี้สำคัญมากเวลามีไฟร์วอลล์อยู่กลางทาง
- ที่ที่บล็อก UDP ไปพอร์ตแปลก ๆ →
tracerouteแบบปกติจะเห็นดาวเต็มไปหมด แต่tracertของวินโดวส์กลับใช้ได้ - ที่ที่บล็อก ICMP ขาเข้า →
tracertตาบอด แต่ UDP อาจผ่าน - ที่ที่ปล่อยเฉพาะ 443 → ใช้
traceroute -T -p 443เท่านั้นที่จะเห็นอะไร
ถ้า traceroute ไม่เห็นอะไรเลย อย่าเพิ่งสรุปว่าเส้นทางขาด ให้เปลี่ยนโพรโทคอล แล้วลองใหม่ก่อน เพราะสิ่งที่คุณพิสูจน์ได้จริงมีแค่ว่าโพรโทคอลนั้นไปไม่ถึง
มีข้อควรรู้จากคู่มือด้วยว่า เมื่อใช้โพรโทคอลอื่นที่ไม่ใช่ UDP ฮอปสุดท้ายมักจะดูเหมือนหาย เพราะปลายทางไม่ได้ส่ง Port Unreachable กลับมา จึงไม่มีสัญญาณบอกว่าถึงแล้ว
เมื่อ traceroute โกหก
1. รายชื่อที่เห็นอาจไม่ใช่เส้นทางของแพ็กเก็ตใดเลย
นี่คือข้อที่ร้ายแรงที่สุดและคนรู้น้อยที่สุด
เครือข่ายสมัยใหม่กระจายโหลดข้ามหลายเส้นทาง โดยตัดสินจากค่าที่คำนวณจากหัว แพ็กเก็ต — ที่อยู่ต้นทาง ปลายทาง โพรโทคอล และหมายเลขพอร์ต
แต่ traceroute แบบดั้งเดิม เปลี่ยนหมายเลขพอร์ตปลายทางทุกครั้งที่ยิง เพราะนั่นคือวิธีเดียวที่มันระบุการยิงแต่ละครั้งได้ ผลคือแต่ละการยิง ถูกจัดให้เดินคนละเส้นทาง
รายชื่อที่พิมพ์ออกมาจึงเป็นการเย็บชิ้นส่วนจากหลายเส้นทางเข้าด้วยกัน เส้นทางนั้นอาจไม่เคยมีแพ็กเก็ตใดเดินจริงเลยแม้แต่ครั้งเดียว
ปัญหานี้ถูกอธิบายเป็นเรื่องเป็นราวในงานวิจัยชื่อ Avoiding traceroute anomalies with Paris traceroute เมื่อปี 2006 และทางแก้คือ Paris traceroute ซึ่งตรึงค่าที่ใช้คำนวณการกระจายโหลดไว้ให้คงที่ แล้วไปใช้ฟิลด์อื่นเป็นตัวระบุแทน
ถ้าเจอเส้นทางที่ดูสลับไปมาไม่คงที่ระหว่างการวัด ให้สงสัยเรื่องนี้ก่อนเสมอ
2. ฮอปกลางทางช้า ไม่ได้แปลว่าเส้นทางช้า
ข้อเดียวกับที่อธิบายไว้ในบทความ ping และมันสำคัญกว่าใน traceroute เพราะที่นี่คุณเห็นตัวเลขของทุกฮอปพร้อมกัน จึงเผลอเปรียบเทียบกันได้ง่าย
การตอบ Time Exceeded เป็นงานของซีพียูในเราเตอร์ ไม่ใช่ของฮาร์ดแวร์ส่งต่อ และเป็นงานที่ถูกจัดลำดับความสำคัญไว้ต่ำที่สุด
ให้อ่านเวลาที่ปลายทางสุดท้าย และเชื่อเฉพาะตัวเลขที่เพิ่มขึ้นแล้วไม่ลดลงอีก ถ้าฮอปที่ 5 ได้ 300 ms แต่ฮอปที่ 6 ถึง 12 ได้ 40 ms แสดงว่าฮอปที่ 5 แค่ตอบช้า ไม่ได้ส่งต่อช้า
3. เห็นแค่ขาไป ไม่เคยเห็นขากลับ
traceroute วัดเวลาไปกลับ แต่แสดงเฉพาะที่อยู่ของขาไป เส้นทางขากลับอาจต่างกันสิ้นเชิงและคุณมองไม่เห็นมันเลย
เวลาที่กระโดดขึ้นระหว่างสองฮอปจึงอาจมาจากขากลับที่เปลี่ยนไป ไม่ใช่จากลิงก์ ระหว่างสองฮอปนั้น การจะเห็นขากลับต้องมีเครื่องมือที่ปลายทางอีกฝั่ง
4. MPLS ทำให้ฮอปหายไปทั้งช่วง
ในเครือข่ายผู้ให้บริการที่ใช้ MPLS แพ็กเก็ตอาจวิ่งผ่านเราเตอร์หลายตัว โดยที่ตัวกลาง ๆ ไม่ลด TTL หรือไม่ตอบกลับมาเลย
ผลคือเห็นสองฮอปที่ดูติดกันแต่เวลาห่างกันมาก ทั้งที่จริงมีอุปกรณ์คั่นอยู่หลายตัว ไม่ใช่ความผิดพลาดของเครื่องมือ แต่เป็นการซ่อนโครงสร้างโดยตั้งใจ
5. ชื่อและ AS ที่แสดงอาจไม่ตรงกับความจริง
ชื่อที่เห็นมาจากการค้น reverse DNS ซึ่งเจ้าของเครือข่ายตั้งเองและมักตั้งค้างไว้ นานหลายปี ชื่อที่บอกว่าอยู่สิงคโปร์อาจเป็นเครื่องที่ย้ายไปโตเกียวแล้ว
ส่วนหมายเลข AS ที่ได้จาก -A คู่มือของโปรแกรมเองเตือนไว้ว่าอาจไม่ตรง เพราะฐานข้อมูลที่ใช้ค้นกับสภาพจริงของอินเทอร์เน็ตไม่ได้ตรงกันเสมอ
ตัวอย่างจริงจากงานจริง
กรณีที่ 1 — ดาวเต็มไปหมด แต่เน็ตใช้ได้ปกติ
$ traceroute api.partner.example
1 192.168.1.1 1.1 ms 1.0 ms 1.1 ms
2 * * *
3 * * *
4 * * *
...
30 * * *
อ่านอย่างไร ยังไม่ได้แปลว่าอะไรเลย ต้องเปลี่ยนโพรโทคอลก่อน
$ traceroute -I api.partner.example
1 192.168.1.1 1.1 ms 1.0 ms 1.1 ms
2 10.4.0.1 8.4 ms 8.3 ms 8.5 ms
3 203.0.113.9 12.0 ms 11.9 ms 12.1 ms
4 api.partner.example 13.2 ms 13.0 ms 13.1 ms
เส้นทางปกติทุกอย่าง สิ่งที่เกิดขึ้นคือมีไฟร์วอลล์ทิ้ง UDP ไปพอร์ตสูง ซึ่งเป็นค่าปกติของไฟร์วอลล์องค์กรจำนวนมาก
สิ่งที่ยังไม่ได้พิสูจน์ เรารู้แค่ว่า ICMP ผ่านและ UDP ไม่ผ่าน ยังไม่รู้ว่าไฟร์วอลล์ตัวไหนทิ้ง และยังไม่ได้พิสูจน์ว่าทราฟฟิกจริงของ แอปพลิเคชัน (ซึ่งน่าจะเป็น TCP 443) ผ่านได้ ต้องยิง -T -p 443 ต่อ
กรณีที่ 2 — ฮอปกลางทางที่ดูแย่แต่ไม่ได้แย่
$ traceroute 8.8.8.8
1 192.168.1.1 1.2 ms 1.1 ms 1.1 ms
2 10.4.0.1 8.4 ms 8.3 ms 8.5 ms
3 203.0.113.1 284.1 ms 291.7 ms 288.3 ms
4 203.0.113.9 12.0 ms 11.9 ms 12.1 ms
5 8.8.8.8 12.3 ms 12.2 ms 12.3 ms
อ่านอย่างไร ฮอปที่ 3 ได้เกือบ 300 ms แต่ฮอปที่ 4 และ 5 ที่อยู่หลังมัน กลับได้ 12 ms ถ้าฮอปที่ 3 หน่วงจริง ทุกอย่างหลังจากนั้นต้องหน่วงตามไปด้วย เพราะต้องวิ่งผ่านมัน
เวลาไม่ได้เพิ่มแล้วคงอยู่ แปลว่าฮอปที่ 3 แค่ตอบช้า ไม่ได้ส่งต่อช้า
สิ่งที่ยังไม่ได้พิสูจน์ ยังเป็นไปได้ที่ฮอปที่ 3 มีปัญหาจริงกับทราฟฟิก บางประเภทที่ traceroute ไม่ได้จำลอง หลักฐานชุดนี้ตัดออกได้แค่ข้อกล่าวหาว่า "หน่วงทุกอย่างที่วิ่งผ่านมัน"
กรณีที่ 3 — เส้นทางที่ไม่มีอยู่จริง
$ traceroute example.net
5 ae-1.r01.bkk.example-isp.net 24.1 ms
ae-3.r02.sin.example-isp.net 41.8 ms
ae-1.r01.bkk.example-isp.net 24.3 ms
6 ae-2.r04.hkg.example-isp.net 58.2 ms 57.9 ms 58.4 ms
อ่านอย่างไร ฮอปที่ 5 ตอบมาจากสองที่อยู่คนละเมือง สลับกันในการยิงสามครั้ง นี่ไม่ใช่ความผิดพลาด แต่คือการกระจายโหลดต่อโฟลว์ทำงานอยู่ และเนื่องจาก traceroute เปลี่ยนพอร์ตปลายทางทุกครั้ง การยิงแต่ละครั้งจึงถูกจัดคนละเส้น
บรรทัดที่ 6 คือกับดัก — มันมาจากเส้นทางไหนใน 5 ก็ไม่รู้ การเอา 5 กับ 6 มาต่อกันเป็นเส้นทางเดียวจึงอาจเป็นเส้นทางที่ไม่มีอยู่จริง
วิธียืนยันคือใช้ Paris traceroute ที่ตรึงค่าการกระจายโหลดไว้
สิ่งที่ยังไม่ได้พิสูจน์ ยังไม่รู้ว่ามีกี่เส้นทางจริง ๆ และเส้นไหนที่ทราฟฟิก ของแอปพลิเคชันจริงใช้อยู่ — ซึ่งจะเป็นเส้นเดียวคงที่ เพราะโฟลว์จริงมีพอร์ตคงที่
กรณีที่ 4 — หาว่าปัญหาอยู่ในองค์กรหรือนอกองค์กร
$ traceroute -T -p 443 app.vendor.example
1 192.168.1.1 1.1 ms 1.0 ms 1.1 ms
2 10.4.0.1 8.4 ms 8.3 ms 8.5 ms
3 10.4.255.1 9.1 ms 9.0 ms 9.2 ms <- ขอบขององค์กร
4 203.0.113.1 12.4 ms 12.2 ms 12.5 ms
5 * * *
6 * * *
7 * * *
อ่านอย่างไร เดินออกจากองค์กรได้ ผ่านเราเตอร์ขอบและถึงผู้ให้บริการแล้ว จึงหยุด ปัญหาไม่ได้อยู่ในองค์กร นี่เป็นข้อมูลที่พอสำหรับการส่งต่อเรื่อง ให้ผู้ให้บริการ พร้อมหมายเลข IP ของฮอปสุดท้ายที่ตอบ
ใช้ -T -p 443 เพราะตรงกับทราฟฟิกจริงที่แอปพลิเคชันใช้ ไม่ใช่ UDP พอร์ตสุ่ม ที่ไม่มีใครสนใจปล่อยผ่าน
สิ่งที่ยังไม่ได้พิสูจน์ ดาวหลังฮอปที่ 4 อาจเป็นแค่การไม่ตอบตามนโยบาย ไม่ใช่การขาด ต้องทดสอบว่าปลายทางเชื่อมต่อได้จริงหรือไม่ด้วยเครื่องมืออื่น ก่อนจะบอกว่าเส้นทางขาด
กรณีที่ 5 — ใช้ mtr แทนเมื่ออาการเป็น ๆ หาย ๆ
traceroute ยิงรอบเดียวแล้วจบ ปัญหาที่เกิดเป็นช่วง ๆ จึงจับไม่ได้
$ mtr -rwc 200 8.8.8.8
HOST Loss% Snt Last Avg Best Wrst StDev
1. 192.168.1.1 0.0% 200 1.1 1.2 1.0 3.2 0.2
2. 10.4.0.1 0.0% 200 8.4 8.5 8.2 12.1 0.4
3. 203.0.113.1 42.0% 200 12.1 12.3 11.8 19.0 0.6
4. 203.0.113.9 0.0% 200 12.0 12.1 11.9 14.2 0.3
5. 8.8.8.8 0.0% 200 12.3 12.4 12.1 15.0 0.3
อ่านอย่างไร ฮอปที่ 3 แสดงการสูญหาย 42% แต่ฮอปที่ 4 และ 5 ที่อยู่หลังมัน สูญหาย 0% ทั้งคู่ ถ้าฮอปที่ 3 ทำแพ็กเก็ตหายจริง ทุกอย่างหลังจากนั้นต้องหายด้วย
นี่คือกฎที่ต้องท่องให้ขึ้นใจ — การสูญหายที่ฮอปกลางทางจะมีความหมาย ก็ต่อเมื่อมันปรากฏที่ฮอปหลังจากนั้นด้วย ถ้าไม่ปรากฏ นั่นคือการจำกัดอัตรา การตอบของเราเตอร์ตัวนั้นเอง
สิ่งที่ยังไม่ได้พิสูจน์ ตัวเลข 0% ที่ปลายทางพิสูจน์ว่า ICMP ผ่านได้ครบ ไม่ได้พิสูจน์ว่าทราฟฟิกของแอปพลิเคชันไม่ถูกทิ้ง
กรณีที่ 6 — เมื่อฮอปแรกไม่ใช่เราเตอร์ที่คุณคิด
$ traceroute 8.8.8.8
1 10.72.0.1 4.2 ms 4.1 ms 4.3 ms
2 100.64.12.1 9.8 ms 9.7 ms 9.9 ms
3 203.0.113.1 14.1 ms 13.9 ms 14.2 ms
อ่านอย่างไร ฮอปที่ 2 อยู่ในช่วง 100.64.0.0/10 ซึ่งเป็นช่วงที่กันไว้ สำหรับ Carrier-Grade NAT ของผู้ให้บริการ ไม่ใช่ที่อยู่ส่วนตัวธรรมดา และไม่ใช่ที่อยู่สาธารณะ
เห็นแบบนี้แปลว่าคุณอยู่หลัง CGNAT ซึ่งอธิบายอาการหลายอย่างที่ตามมา เช่นการเปิดพอร์ตเข้ามาจากภายนอกไม่ได้
สิ่งที่ยังไม่ได้พิสูจน์ ยังไม่รู้ว่ามี NAT กี่ชั้น และไม่ได้พิสูจน์ว่า CGNAT เป็นสาเหตุของอาการที่กำลังไล่หาอยู่
เกร็ด: มีมาตรฐานของ traceroute อยู่ และไม่มีใครใช้
ปี 1993 มี RFC 1393 ที่เสนอวิธี traceroute แบบใหม่ ใช้ IP option กับข้อความ ICMP ชนิดใหม่ ซึ่งจะได้เส้นทางทั้งเส้นด้วยแพ็กเก็ตเพียง n+1 ชิ้น แทนที่จะเป็น 2n ชิ้นแบบวิธีเดิม
มันไม่เคยถูกใช้งานจริงในวงกว้าง
สิ่งที่ชนะคือวิธีของ Van Jacobson ที่ไม่ต้องขอให้ใครทำอะไรใหม่เลย บทเรียนเดียวกับ ping — เครื่องมือที่ทำงานได้กับสิ่งที่มีอยู่แล้ว ชนะเครื่องมือที่ดีกว่าแต่ต้องรอให้โลกทั้งใบอัปเกรดตาม
เมื่อ traceroute ไม่พออีกต่อไป
- mtr — ยิงต่อเนื่องแล้วสรุปสถิติทุกฮอป จับอาการเป็น ๆ หาย ๆ ได้ ถ้าจะเรียนเพิ่มอีกตัวเดียว เลือกตัวนี้
- Paris traceroute — เมื่อสงสัยว่าเจอการกระจายโหลด
- traceroute -T -p 443 — เมื่อ UDP และ ICMP ถูกบล็อก
- BGP looking glass ของผู้ให้บริการ — ดูเส้นทางจากฝั่งเขากลับมาหาเรา ซึ่งเป็นขากลับที่ traceroute ของเราไม่มีวันเห็น
- tcpdump หรือ Wireshark — เมื่อเลิกเดาแล้ว
traceroute เป็นเครื่องมือที่ดีมากสำหรับคำถาม "ไปหยุดตรงไหน" และเป็นเครื่องมือที่แย่มากสำหรับคำถาม "เส้นทางคืออะไร"
ความต่างของสองคำถามนั้นคือสิ่งที่แยกคนที่ใช้มันเป็น ออกจากคนที่พิมพ์มันได้
อ้างอิง
เอกสารมาตรฐาน
- RFC 792 — Internet Control Message Protocol กันยายน 1981 — นิยาม Time Exceeded (type 11), Destination Unreachable (type 3) และข้อกำหนดที่ว่าข้อความแจ้งข้อผิดพลาดพาข้อมูลเดิมกลับมา 8 ไบต์
- RFC 1812 — Requirements for IP Version 4 Routers ข้อกำหนดเรื่องการลด TTL และการส่ง Time Exceeded
- RFC 1393 — Traceroute Using an IP Option มกราคม 1993 — มาตรฐานที่ไม่มีใครใช้
- RFC 1191 — Path MTU Discovery ที่มาของค่า MTU ที่แสดงพร้อมสัญลักษณ์ !F
- RFC 6598 — IANA-Reserved IPv4 Prefix for Shared Address Space ที่มาของช่วง 100.64.0.0/10 ที่ใช้กับ CGNAT
ต้นฉบับและงานวิจัย
- ซอร์สโค้ดต้นฉบับของ Van Jacobson — หัวไฟล์มีคำอธิบายการทำงานและประโยค ที่เขาบอกว่าขโมยไอเดียมาจาก Steve Deering
- Avoiding traceroute anomalies with Paris traceroute Augustin และคณะ, IMC 2006 — อธิบายปัญหาการกระจายโหลดและทางแก้
- paris-traceroute.net
คู่มือ
man tracerouteบนเครื่องที่คุณนั่งอยู่ — หัวข้อ AUTHOR มีที่มาของโปรแกรม และหัวข้อ BUGS มีข้อจำกัดที่ควรอ่านก่อนใช้โพรโทคอลอื่นที่ไม่ใช่ UDPman mtrและtracert /?บนวินโดวส์