NetKubeLab EN

Network Fundamental ข้ามเครือข่าย

MTU — ตัวเลขที่ไม่มีใครตั้ง แต่ทุกคนต้องเดาให้ถูก

แปดบทบนเว็บนี้พูดถึง MTU แต่ไม่มีบทไหนอธิบายมัน บทนี้วัดขอบด้วยคำสั่งเดียว แล้วแสดงว่าทำไมกลไกที่หามันถึงพังบ่อย

· หมวด 4 · ข้ามเครือข่าย · 8 นาที

คำว่า MTU ปรากฏใน 8 จาก 31 บทบนเว็บนี้ บท Ethernet ส่งคนอ่านไปหาบท ping ส่วนบท ไฟร์วอลล์ บอกว่าการบล็อก ICMP ทำให้ การค้นหา MTU พัง

แต่ยังไม่มีบทไหนบอกว่ามันคืออะไร และทำไมถึงต้องค้นหา บทนี้ตอบทั้งสองข้อ

ถ้ายังไม่เคยดู เริ่มตรงนี้

หาขอบด้วยตัวเอง ใช้เวลาไม่ถึงนาที ตัวเลือก -D คือห้ามแตกแพ็กเก็ต

$ ping -c1 -D -s 1472 8.8.8.8
$ ping -c1 -D -s 1473 8.8.8.8

บนเครื่องที่ใช้เขียนบทนี้ อันแรกผ่าน อันที่สองไม่ผ่าน ขอบอยู่ระหว่างสองบรรทัด นั้นพอดี

ทำไมขอบถึงอยู่ตรงนั้น

ผมไล่ทีละไบต์รอบ ๆ ขอบ

  -s      total on wire   result
  1470             1498   ผ่าน
  1471             1499   ผ่าน
  1472             1500   ผ่าน
  1473             1501   ไม่ผ่าน
  1474             1502   ไม่ผ่าน

ขอบอยู่ที่ 1500 พอดีเป๊ะ ไม่ใช่ 1472 ตัวเลข 1472 คือสิ่งที่เหลือหลังหักหัว ออกแล้ว

  link MTU        1500
  IPv4 header      -20
  ICMP echo        -8
                  ----
  payload         1472

ตัวเลข 1500 มาจากไหน บทความ Ethernet อธิบายไว้แล้วว่ามันเป็นผลของ การตัดสินใจเมื่อปี 1980 และนั่นคือประเด็นทั้งหมดของบทนี้ — ไม่มีใครตั้งเลขนี้ ให้คุณ มันเป็นสมบัติของลิงก์แต่ละเส้น

เครื่องเดียวมีได้หลายค่า

MTU ไม่ใช่ค่าของเครื่อง แต่เป็นค่าของอินเทอร์เฟซ

$ ifconfig | grep mtu

บนเครื่องนี้

  lo0     16384
  en1      1500
  gif0     1280

สามค่าบนเครื่องเดียว และแพ็กเก็ตจะเจอค่าไหนขึ้นกับว่ามันออกทางไหน

Path MTU คือค่าที่น้อยที่สุดตลอดเส้นทาง

RFC 1191 ปี 1990 นิยามไว้ในประโยคเดียว

"This datagram size is referred to as the Path MTU (PMTU), and it is equal to the minimum of the MTUs of each hop in the path."

แพ็กเก็ตเดินผ่านลิงก์ที่มี MTU ต่างกัน ค่าที่ใช้ได้จริงคือค่าที่น้อยที่สุดในเส้นทางนั้น ไม่ใช่ค่าของลิงก์แรก

ค่าที่น้อยที่สุดชนะ ไม่ใช่ค่าเฉลี่ย ไม่ใช่ค่าของลิงก์แรก และผู้ส่งไม่มีทาง รู้ค่านั้นล่วงหน้า เพราะบทความ การเลือกเส้นทาง แสดงไว้แล้วว่าไม่มีใคร รู้เส้นทางทั้งเส้น

RFC 8201 ใช้นิยามเดียวกันสำหรับ IPv6

"This packet size is referred to as the Path MTU, and it is equal to the minimum link MTU of all the links in a path."

กลไกที่ใช้หา — ส่งแล้วรอคนบ่น

RFC 1191 อธิบายวิธีไว้ตรง ๆ

"The basic idea is that a source host initially assumes that the PMTU of a path is the (known) MTU of its first hop, and sends all datagrams on that path with the DF bit set. If any of the datagrams are too large to be forwarded without fragmentation by some router along the path, that router will discard them and return ICMP Destination Unreachable messages with a code meaning 'fragmentation needed and DF set'"

ต้นทางส่งขนาดเต็มพร้อมบิตห้ามแตก เราเตอร์ที่ MTU เล็กกว่าทิ้งแล้วส่ง ICMP กลับมาบอกค่า ต้นทางจึงลดขนาดลง

สรุปเป็นสามขั้น

  1  assume    ใช้ MTU ของลิงก์แรกไปก่อน
  2  send      ส่งพร้อมบิต DF คือห้ามแตก
  3  learn     ถูกทิ้งแล้วมี ICMP กลับมา จึงลดลง

ขั้นที่สามคือจุดอ่อนทั้งหมดของกลไกนี้ มันต้องพึ่งข้อความที่ส่งกลับมา

เมื่อ ICMP ถูกบล็อก — หลุมดำ

บทความ ไฟร์วอลล์ บอกไว้แล้วว่าการ บล็อก ICMP ทั้งหมดทำให้การค้นหา MTU พัง บทนี้อธิบายว่าพังอย่างไร

  1  assume    ใช้ 1500
  2  send      แพ็กเก็ตใหญ่ถูกทิ้งกลางทาง
  3  learn     ICMP ถูกบล็อก ต้นทางไม่ได้ยินอะไรเลย
  4            จึงส่ง 1500 ซ้ำต่อไปเรื่อย ๆ

อาการที่ได้คือแปลกที่สุดแบบหนึ่งในงานเครือข่าย — เชื่อมต่อได้ ping ผ่าน เปิดหน้าเว็บเล็ก ๆ ได้ แต่พอโหลดของใหญ่แล้วค้างไปเฉย ๆ

เพราะแพ็กเก็ตเล็กผ่านได้ ส่วนแพ็กเก็ตใหญ่หายเงียบ

RFC 8201 เตือนเรื่องนี้ไว้สำหรับ IPv6

"Nodes implementing Path MTU Discovery and sending packets larger than the IPv6 minimum link MTU are susceptible to problematic connectivity if ICMPv6 messages are blocked or not transmitted."

ทางออกที่ไม่ต้องพึ่ง ICMP

RFC 4821 ปี 2007 เสนอวิธีที่ทำงานได้แม้ไม่มี ICMP เลย

"In the absence of ICMP messages, the proper MTU is determined by starting with small packets and probing with successively larger packets."

เริ่มจากเล็กแล้วค่อยขยาย แทนที่จะเริ่มจากใหญ่แล้วรอคนบ่น

ความต่างของสองวิธี

  RFC 1191   start big     ต้องมี ICMP กลับมา
  RFC 4821   start small   ไม่ต้องมี ICMP

และเอกสารระบุว่ามันทำงานที่ชั้นบน ไม่ใช่ที่ชั้น IP

"The bulk of the algorithm is implemented above IP, in the transport layer (e.g., TCP) or other 'Packetization Protocol' that is responsible for determining packet boundaries."

นี่คือจุดที่ควรอ่านคู่กับบทความ โปรโตคอลและชั้นของมัน ซึ่งระบุ MTU ไว้เป็นหนึ่งในจุดที่การแบ่งชั้นรั่ว — ชั้นสี่ต้องรู้เรื่องของชั้นสอง

IPv6 ตัดทางเลือกหนึ่งทิ้ง

IPv4 มีทางออกสำรอง คือเราเตอร์แตกแพ็กเก็ตให้ได้ถ้าไม่ได้ตั้งบิต DF

IPv6 ไม่มีทางนั้น เราเตอร์ไม่แตกแพ็กเก็ตให้เลย ตามที่บทความ IPv6 อธิบายไว้ ต้นทางต้องจัดการเอง

ผลคือค่า MTU ต่ำสุดที่รับประกันได้ต่างกัน

  IPv4   576
  IPv6   1280

และเลข 1280 นั่นเองที่โผล่บนเครื่องผมในอินเทอร์เฟซ gif0 ซึ่งเป็นอินเทอร์เฟซ สำหรับอุโมงค์

ทำไมอุโมงค์ถึงเป็นตัวปัญหาเสมอ

ทุกอุโมงค์ห่อแพ็กเก็ตเดิมไว้ในแพ็กเก็ตใหม่ หัวที่เพิ่มมากินที่จาก payload

แพ็กเก็ตเดิมถูกห่อด้วยหัวของอุโมงค์ ทำให้ขนาดที่ใช้ได้จริงลดลงตามขนาดของหัวที่เพิ่มเข้ามา

  outer link MTU      1500
  tunnel overhead      -40   ตัวอย่าง ขึ้นกับชนิดอุโมงค์
                      ----
  inner usable        1460

เครื่องข้างในอุโมงค์ยังคิดว่าตัวเองมี 1500 เพราะไม่มีใครบอก และนั่นคือที่มา ของอาการค้างเวลาใช้ VPN ที่คนเจอกันบ่อย

ตัวเลข 40 ข้างบนเป็นตัวอย่างเท่านั้น ค่าจริงขึ้นกับชนิดของอุโมงค์ และผมยืนยัน ค่าของแต่ละชนิดจากต้นทางไม่ได้ในบทนี้

เมื่อมันโกหก

"MTU คือ 1500 เสมอ" เป็นค่าของอีเทอร์เน็ต ไม่ใช่ของทุกลิงก์ เครื่องที่ผมใช้ เขียนมีสามค่าบนเครื่องเดียว

"ping ผ่านแปลว่าเส้นทางใช้ได้" ping ปกติส่งแพ็กเก็ตเล็ก ซึ่งผ่านได้แม้เส้นทาง จะมีปัญหา MTU ต้องใส่ -D และขนาดใหญ่ถึงจะเจอ

"บล็อก ICMP ทั้งหมดเพื่อความปลอดภัย" ทำให้กลไกที่หา MTU ตาบอด และสร้างอาการ ที่หาสาเหตุยากที่สุดแบบหนึ่ง

"ตั้ง MTU ให้เล็กไว้ก่อน ปลอดภัยกว่า" RFC 1191 เขียนไว้เองว่าการส่งแพ็กเก็ต เล็กกว่าที่เส้นทางรับได้ คือการเปลืองทรัพยากรและได้ throughput ที่แย่กว่าที่ควร

"เราเตอร์แตกแพ็กเก็ตให้อยู่แล้ว" จริงกับ IPv4 ที่ไม่ตั้ง DF เท่านั้น IPv6 ไม่ทำให้เลย

ตัวอย่างจริงจากงานจริง

กรณีที่ 1 — เชื่อมต่อได้ แต่โหลดของใหญ่แล้วค้าง

สถานการณ์ ping ผ่าน เปิดหน้าเว็บเล็กได้ แต่พอโหลดไฟล์หรือหน้าหนัก ๆ แล้วค้าง

คำสั่ง ไล่หาขอบจริงของเส้นทางนั้น

$ ping -c1 -D -s 1472 <ปลายทาง>
$ ping -c1 -D -s 1400 <ปลายทาง>

อ่านอย่างไร ถ้า 1472 ไม่ผ่านแต่ 1400 ผ่าน แปลว่า path MTU เล็กกว่า 1500 และถ้าไม่มี ICMP กลับมาเลย นั่นคือหลุมดำที่อธิบายไว้ข้างบน

สิ่งที่ยังไม่ได้พิสูจน์ การหาขอบด้วย ping บอกค่าของเส้นทางไป-กลับ ณ ตอนนั้น เส้นทางอาจเปลี่ยนได้ และ ping ใช้ ICMP ซึ่งบางที่ปฏิบัติกับมันต่างจาก TCP

กรณีที่ 2 — อาการเกิดเฉพาะกับบางปลายทาง

สถานการณ์ เครื่องเดียวกัน บางเว็บใช้ได้ บางเว็บค้าง

อ่านอย่างไร Path MTU เป็นค่าของ เส้นทาง ไม่ใช่ของเครื่อง ตามนิยามใน RFC 1191 ปลายทางคนละที่ผ่านลิงก์คนละชุด จึงมีค่าคนละค่า การที่บางปลายทางใช้ได้ จึงไม่ได้แปลว่าเครื่องเราไม่มีปัญหา

สิ่งที่ยังไม่ได้พิสูจน์ อาการเฉพาะบางปลายทางเกิดจากสาเหตุอื่นได้ด้วย เช่น ปลายทางนั้นเองมีปัญหา ต้องลองจากเครื่องอื่นในวงเดียวกันเทียบ

กรณีที่ 3 — ตั้งค่าอุโมงค์แล้วช้าลงมาก

สถานการณ์ เปิด VPN แล้วบางอย่างใช้ไม่ได้ หรือช้าผิดปกติ

อ่านอย่างไร ตรวจ MTU ของอินเทอร์เฟซอุโมงค์เทียบกับของลิงก์จริง

$ ifconfig | grep -B4 mtu

ถ้าอินเทอร์เฟซอุโมงค์ยังตั้งไว้ 1500 เท่าลิงก์จริง แปลว่ายังไม่ได้หักหัวของ อุโมงค์ออก

สิ่งที่ยังไม่ได้พิสูจน์ การลด MTU ของอุโมงค์แก้อาการได้ในหลายกรณี แต่ค่าที่ ควรตั้งขึ้นกับชนิดอุโมงค์ ซึ่งบทนี้ไม่ได้ยืนยันตัวเลขของแต่ละชนิด

สิ่งที่ตัวเลขนี้สอน

MTU เป็นตัวอย่างที่ชัดที่สุดของค่าที่ไม่มีใครเป็นเจ้าของ ต้นทางไม่ได้ตั้ง ปลายทางไม่ได้ตั้ง และเราเตอร์กลางทางแต่ละตัวก็รู้แค่ค่าของลิงก์ตัวเอง

ค่าที่ใช้ได้จริงจึงต้องถูก ค้นหา ไม่ใช่ถูกอ่าน และกลไกที่ใช้ค้นหาก็ต้องพึ่ง ข้อความที่คนอื่นส่งกลับมา ซึ่งอาจไม่มา

เป็นรูปแบบเดียวกับที่ทั้งซีรีส์เจอมาตลอด ระบบทำงานได้เพราะมีคนยอมบอก และ พังเงียบ ๆ เมื่อไม่มีใครบอก

อ้างอิง

เอกสารมาตรฐาน

  • RFC 1191 พฤศจิกายน 1990 Path MTU Discovery — นิยาม PMTU และกลไก DF bit ที่ยกมาอ้าง
  • RFC 8201 กรกฎาคม 2017 Path MTU Discovery for IP version 6 — นิยามเดียวกันสำหรับ IPv6 และคำเตือน เรื่อง ICMPv6 ที่ถูกบล็อก
  • RFC 4821 มีนาคม 2007 Packetization Layer Path MTU Discovery — วิธีที่ทำงานได้โดยไม่ต้องมี ICMP

วัดจากเครื่องที่ใช้เขียน

  • ping -D ไล่ขนาดทีละไบต์ ได้ขอบที่ 1500 ไบต์บนสายพอดี
  • ifconfig แสดง MTU สามค่าบนเครื่องเดียว คือ 16384, 1500 และ 1280

คำนวณเอง

  • ตารางหักหัว IPv4 20 ไบต์ และหัว ICMP 8 ไบต์ ออกจาก 1500

สิ่งที่ยืนยันจากต้นทางไม่ได้

  • ขนาดหัวของอุโมงค์แต่ละชนิด บทนี้ใช้ 40 ไบต์เป็นตัวอย่างประกอบเท่านั้น

วัดจากเครื่องจริงคำนวณเอง

อ่านหน้านี้เป็นภาษาอังกฤษ