ทุกคนที่เรียนเครือข่ายต้องท่องเจ็ดชั้น และหลายคนท่องได้จนถึงวันนี้ — Application, Presentation, Session, Transport, Network, Data Link, Physical
ปัญหาคือกองโปรโตคอลที่แบบจำลองนั้นถูกสร้างมาเพื่ออธิบาย ไม่มีใครใช้แล้ว FTAM, VTP, MHS สำหรับชั้นบน TP0 ถึง TP4 สำหรับชั้นขนส่ง CLNP กับ CONP สำหรับชั้นเครือข่าย — ชื่อเหล่านี้อยู่ในตำราทุกเล่ม และไม่อยู่ในเครื่องคุณ สักตัวเดียว
สิ่งที่เครื่องคุณใช้จริงคือ TCP/IP ซึ่งเอกสารกำหนดของมันบอกว่ามี สี่ชั้น
บทความนี้ไม่ได้จะบอกว่าแบบจำลองเจ็ดชั้นไร้ประโยชน์ มันมีประโยชน์มากในฐานะ คำศัพท์ร่วม แต่จะแสดงให้เห็นด้วยไบต์จริงว่า ชั้นไม่ได้แยกจากกันอย่างที่ วาด และตัวมาตรฐานเองก็รู้ตัวเรื่องนี้ตั้งแต่แรก
ถ้ายังไม่เคยดู เริ่มตรงนี้
ชั้นไม่ใช่เรื่องนามธรรม มันคือไบต์ที่วางซ้อนกันอยู่จริง คำสั่งเดียวเห็นได้
$ nc -v example.com 80
การเชื่อมต่อสำเร็จหนึ่งครั้งนี้ผ่านทุกชั้นพร้อมกัน — ชื่อ example.com ถูกแปลงเป็นเลข IP ที่ชั้นแอปพลิเคชัน เลข 80 เป็นพอร์ตของชั้นขนส่ง เลข IP ที่ได้มาเป็นของชั้นเครือข่าย และการ์ดเน็ตเวิร์กใส่ที่อยู่ MAC ให้ที่ชั้นลิงก์
ทั้งหมดนี้จบในคำสั่งเดียวเพราะแต่ละชั้นไม่ต้องรู้ว่าชั้นอื่นทำอะไร — อย่างน้อยก็ตามทฤษฎี
โปรโตคอลไม่ใช่ซอฟต์แวร์
คำว่าโปรโตคอลถูกใช้ปนกับคำว่าโปรแกรมบ่อยมาก แต่มันคนละอย่าง
โปรโตคอลคือข้อตกลงว่าจะวางไบต์อย่างไรและตอบสนองอย่างไร ไม่ใช่โค้ดที่ทำ ตามข้อตกลงนั้น เว็บเซิร์ฟเวอร์คนละยี่ห้อคุยกันได้เพราะทำตามข้อตกลงเดียวกัน ทั้งที่โค้ดข้างในไม่เหมือนกันสักบรรทัด
ข้อตกลงหนึ่งชุดต้องระบุสามอย่างให้ครบ
syntax ไบต์ไหนอยู่ตรงไหน ยาวเท่าไหร่ อ่านอย่างไร
semantics ค่าแต่ละค่าแปลว่าอะไร และใครต้องทำอะไรต่อ
timing ส่งเมื่อไหร่ รอได้นานแค่ไหน ส่งซ้ำตอนไหน
ถ้าขาดข้อใดข้อหนึ่ง สองฝั่งจะคุยกันไม่รู้เรื่องแม้จะอ่านไบต์ออกก็ตาม บทความ DHCP เป็นตัวอย่างที่ชัดของ timing — ตัวเลข T1 กับ T2 ไม่ได้อยู่ในไบต์ไหนเลย แต่เป็นข้อตกลงว่าต้องต่ออายุเมื่อไหร่
การห่อข้อมูล นับเป็นไบต์ได้
เวลาข้อมูลเดินลงจากชั้นบนไปชั้นล่าง แต่ละชั้นเติมส่วนหัวของตัวเองเข้าไป เรียกว่าการห่อข้อมูล ผมประกอบเฟรมจริงขึ้นมาหนึ่งเฟรมเพื่อวัด
bytes size section owner
0-13 14 Ethernet header layer 2
14-33 20 IP header layer 3
34-53 20 TCP header layer 4
54-69 16 payload layer 7
ข้อมูลที่คนต้องการส่งจริงคือ 16 ไบต์ จากทั้งเฟรม 70 ไบต์ — ส่วนหัวสามชั้น กินไป 54 ไบต์ หรือ 77%
นี่คือราคาของการแบ่งชั้น และเป็นเหตุผลที่โพรโทคอลที่ส่งข้อมูลชิ้นเล็ก ๆ ถี่ ๆ เช่นเสียงหรือเกม ถึงเจ็บกว่าที่คนคิด ทุกครั้งที่คุณส่ง 16 ไบต์ คุณจ่ายค่า ส่วนหัวเต็มราคาเสมอ
1994 — มาตรฐานที่บอกเองว่าพิสูจน์ไม่ได้
แบบจำลองเจ็ดชั้นมีตัวตนเป็นเอกสารจริง ชื่อ ISO/IEC 7498-1 ซึ่ง ITU เผยแพร่ ข้อความเดียวกันในชื่อ X.200 และดาวน์โหลดได้ฟรี ต่างจาก 802.1AX ที่ต้องซื้อ
หัวข้อ 6.1.3 ระบุเจ็ดชั้นไว้ตรง ๆ
layer 7 Application
layer 6 Presentation
layer 5 Session
layer 4 Transport
layer 3 Network
layer 2 Data Link
layer 1 Physical
แต่สิ่งที่น่าสนใจกว่ารายชื่อคือหมายเหตุในหัวข้อ 6.2.1 ซึ่งเขียนไว้ก่อนจะ ลิสต์หลักการที่ใช้ตัดสิน
"NOTE - It may be difficult to prove that any particular layering selected is the best possible solution."
มาตรฐานเองบอกว่าอาจพิสูจน์ไม่ได้ว่าการแบ่งแบบนี้ดีที่สุด ประโยคนี้หายไป จากตำราแทบทุกเล่ม เหลือแต่เลขเจ็ดที่ถูกท่องเหมือนกฎธรรมชาติ
หลักการที่ใช้ตัดสินว่าจะขีดเส้นตรงไหน
หัวข้อเดียวกันลิสต์หลักการไว้ ซึ่งอ่านแล้วเห็นว่านี่คืองานวิศวกรรม ไม่ใช่ การค้นพบ ที่สำคัญที่สุดคือสองข้อนี้
"b) Create a boundary at a point where the description of services can be small and the number of interactions across the boundary are minimized."
"k) create for each layer, boundaries with its upper and lower layer only."
ข้อ k คือกฎที่ทุกคนวาดตามในไดอะแกรม — ชั้นหนึ่งคุยกับชั้นที่อยู่ติดกัน เท่านั้น ห้ามข้าม
จำข้อนี้ไว้ให้ดี เพราะอีกสามหัวข้อข้างล่างจะพิสูจน์ว่า TCP ละเมิดมัน
หลักการที่เหลือก็ตรงไปตรงมาแบบเดียวกัน — อย่าแบ่งเยอะจนอธิบายยาก แยกชั้น เมื่องานต่างกันชัดเจน รวมงานที่คล้ายกันไว้ด้วยกัน และขีดเส้นตรงที่เคยพิสูจน์ มาแล้วว่าใช้ได้
1989 — RFC 1122 บอกว่ามีสี่ชั้น
ห้าปีก่อนที่ X.200 ฉบับ 1994 จะออก IETF ตีพิมพ์ RFC 1122 ชื่อ Requirements for Internet Hosts ซึ่งเป็นเอกสารที่บอกว่าเครื่องที่จะต่ออินเทอร์เน็ตได้ ต้องทำอะไรบ้าง และมันนับชั้นไว้แค่สี่
Application HTTP, DNS, SMTP, SSH
Transport TCP, UDP
Internet IP, ICMP, IGMP
Link Ethernet, Wi-Fi, PPP
และมันพูดถึง OSI ตรง ๆ ว่าชั้นบนถูกยุบรวม
"The application layer of the Internet suite essentially combines the functions of the top two layers -- Presentation and Application -- of the OSI reference model."
พร้อมประโยคก่อนหน้าที่บอกว่า "The Internet suite does not further subdivide the application layer"
ชั้นที่หายไป และชั้นที่ไม่รู้จะอยู่ตรงไหน
สังเกตว่า RFC 1122 พูดถึงการยุบชั้น 6 กับ 7 เข้าด้วยกัน แต่ไม่ได้พูดถึง ชั้น 5 เลย เพราะในกองของอินเทอร์เน็ตไม่มีชั้นเซสชันเป็นชั้นแยก งานที่ OSI มอบให้ชั้น 5 กระจายไปอยู่ในแอปพลิเคชันบ้าง ใน TCP บ้าง
และมีของอีกชิ้นที่ RFC 1122 ยอมรับตรง ๆ ว่าจัดชั้นไม่ลง
"ICMP is a control protocol that is considered to be an integral part of IP, although it is architecturally layered upon IP, i.e., it uses IP to carry its data end-to-end just as a transport protocol like TCP or UDP does."
ICMP เป็นส่วนหนึ่งของ IP แต่ก็วางอยู่บน IP พร้อมกัน — จะเรียกว่าชั้น 3 ก็ได้ จะเรียกว่าชั้น 4 ก็ได้ เอกสารเลือกที่จะบอกว่ามันเป็นทั้งสองอย่าง แทนที่จะ บังคับให้เข้าช่อง
ประโยคที่พลิกความเข้าใจของหลายคนอยู่ในย่อหน้าเดียวกัน
"Internet IP was the model for the OSI Connectionless Network Protocol"
CLNP ที่ตำราสอนว่าเป็นโปรโตคอลชั้นเครือข่ายของ OSI ถูกสร้างโดยเอา IP เป็น ต้นแบบ ไม่ใช่กลับกัน
หลักฐานว่าชั้นรั่ว วัดเป็นตัวเลขได้
ถ้าหลักการข้อ k เป็นจริง TCP ควรคำนวณทุกอย่างได้โดยไม่ต้องรู้อะไรเกี่ยวกับ IP เลย ความจริงคือไม่ได้
RFC 9293 อธิบายวิธีคิด checksum ของ TCP ไว้ว่าต้องเอาสิ่งที่เรียกว่า pseudo-header มาคิดด้วย
"The checksum also covers a pseudo-header (Figure 2) conceptually prefixed to the TCP header. ... Including the pseudo-header in the checksum gives the TCP connection protection against misrouted segments."
และประโยคถัดมาคือคำสารภาพ
"This information is carried in IP headers and is transferred across the TCP/network interface in the arguments or results of calls by the TCP implementation on the IP layer."
pseudo-header ของ IPv4 มี 12 ไบต์ และไม่มีไบต์ไหนถูกส่งออกไปจริง มันเป็นแค่ ค่าที่ทั้งสองฝั่งเอามาคำนวณ
4 bytes source IP address มาจากหัว IP
4 bytes destination IP address มาจากหัว IP
1 byte zero
1 byte protocol number มาจากหัว IP
2 bytes TCP length คำนวณเอา ไม่ได้ส่ง
เปลี่ยนเลข IP แล้ว checksum ของ TCP เปลี่ยนตาม
นี่คือการทดลองที่จบเรื่อง ผมสร้างเซกเมนต์ TCP ขึ้นมาหนึ่งชุด ไบต์ทุกตัว เหมือนกันเป๊ะ แล้วคิด checksum โดยเปลี่ยนแค่ที่อยู่ IP ซึ่งเป็นของชั้นล่าง
source destination TCP checksum
192.0.2.10 198.51.100.7 0x7654
192.0.2.10 203.0.113.9 0x6485
203.0.113.9 198.51.100.7 0xfc54
no pseudo-header 0x62b9
บรรทัดสุดท้ายคือค่าที่ได้ถ้าไม่เอา pseudo-header มาคิดเลย ซึ่งจะเป็นค่าเดียว ไม่ว่าส่งไปที่ไหน
สามค่าแรกต่างกัน ทั้งที่ 25 ไบต์ของ TCP ไม่ขยับเลยสักบิต ชั้น 4 คำนวณตัวเอง ไม่ได้ถ้าไม่รู้ค่าของชั้น 3 ซึ่งขัดกับหลักการข้อ k ของ X.200 ตรง ๆ
และนี่ไม่ใช่ความผิดพลาด มันตั้งใจ RFC 9293 บอกเหตุผลไว้แล้วว่าเพื่อ "protection against misrouted segments" — ถ้าแพ็กเก็ตถูกส่งผิดเครื่อง ปลายทางจะคำนวณ checksum ได้ไม่ตรงและทิ้งมัน ประโยชน์นี้ซื้อมาด้วยการยอม ให้ชั้นสองชั้นผูกกัน
ที่อื่นที่รั่วเหมือนกัน
เมื่อรู้ว่ามันรั่วได้ ก็จะเห็นรอยรั่วเต็มไปหมด
NAT ตามที่ บทความ NAT อธิบาย เป็นอุปกรณ์ชั้น 3 ที่ เข้าไปแก้หมายเลขพอร์ตซึ่งเป็นของชั้น 4 และเมื่อแก้แล้วก็ต้องคำนวณ checksum ของ TCP ใหม่ เพราะที่อยู่ IP ที่มันเพิ่งเปลี่ยนอยู่ใน pseudo-header
MTU เป็นสมบัติของสายและการ์ด ซึ่งเป็นชั้นล่างสุด แต่บทความ ping แสดงให้เห็นว่ามันทำให้การจับมือ TLS ล้มเหลวได้ ซึ่งเป็นเรื่องของชั้นบนสุด
TLS ไม่มีเลขชั้นที่ทุกคนเห็นตรงกัน มันไม่ใช่ชั้น 4 เพราะไม่ได้ส่งข้อมูล เอง ไม่ใช่ชั้น 7 เพราะแอปพลิเคชันไม่รู้จักมัน คนจึงเรียกมันว่าชั้น 5 บ้าง 6 บ้าง หรือ "ชั้น 4.5" แบบติดตลก
QUIC ย้ายงานของชั้นขนส่งทั้งหมดขึ้นไปไว้ในโปรแกรมผู้ใช้ แล้วส่งผ่าน UDP ซึ่งอยู่ชั้น 4 เท่ากับว่ามีชั้นขนส่งซ้อนอยู่บนชั้นขนส่ง
RFC 3439 ของ IETF เขียนหัวข้อชื่อ "Layering Considered Harmful" ไว้ตั้งแต่ ปี 2002 และอธิบายว่าทำไม
"the operations of multiplexing and segmentation both hide vital information that lower layers may need to optimize their performance"
"layer N may need layer N-2 information (e.g., lower layer packet sizes)"
"Layer 7 firewall" หมายถึงอะไรกันแน่
เลขชั้นถูกใช้ขายของมากกว่าถูกใช้ตามนิยาม และเมื่อเจอในสเปกสินค้า มันมัก หมายถึงสิ่งนี้
layer 2 switch ตัดสินจากที่อยู่ MAC
layer 3 switch ตัดสินจากที่อยู่ IP
layer 4 balancer ตัดสินจากหมายเลขพอร์ต
layer 7 balancer ตัดสินจากเนื้อหา เช่น path หรือ Host header
layer 7 firewall อ่านเนื้อหาของโพรโทคอลได้ ไม่ใช่แค่ดูพอร์ต
สังเกตว่าไม่มีใครขาย layer 5 หรือ layer 6 อะไรเลย เพราะสองชั้นนั้นไม่มีตัวตน ในกองที่ใช้งานจริง สิ่งที่คนพูดว่า "ชั้น 7" จริง ๆ แล้วหมายถึง "ชั้นบนสุด เท่าที่มี" มากกว่าจะหมายถึงชั้นที่เจ็ดจากล่าง
เมื่อมันโกหก
"อุปกรณ์ทุกตัวมีครบเจ็ดชั้น" ไม่ใช่ สวิตช์ทำแค่ชั้น 1 กับ 2 เราเตอร์ ทำถึงชั้น 3 X.200 เองอธิบายเรื่องนี้ไว้ว่าอุปกรณ์กลางทางเป็น relay ที่ทำงาน เฉพาะชั้นล่าง
"ชั้นบนไม่ต้องรู้เรื่องชั้นล่าง" ตัวเลข checksum ข้างบนพิสูจน์แล้วว่าไม่จริง และ MTU ก็พิสูจน์ในทางกลับกัน
"แบบจำลอง OSI คือวิธีที่อินเทอร์เน็ตทำงาน" ไม่ใช่ มันคือวิธีที่กอง โปรโตคอลอีกกองหนึ่งตั้งใจจะทำงาน กองนั้นแพ้ไปแล้ว เหลือแต่คำศัพท์
"ชั้นมากกว่าคือดีกว่า" RFC 3439 เถียงตรงกันข้าม การเพิ่มชั้นเพิ่มความ ซับซ้อนและซ่อนข้อมูลที่ชั้นล่างต้องใช้
"เลขชั้นในสเปกสินค้าตรงกับ OSI" ตรงบ้างไม่ตรงบ้าง และไม่มีใครนิยามให้ ชัดว่า layer 7 firewall ต้องทำอะไรได้บ้าง
ตัวอย่างจริงจากงานจริง
กรณีที่ 1 — ไล่ปัญหาจากล่างขึ้นบน
สถานการณ์ ผู้ใช้บอกว่าเข้าเว็บไม่ได้ ไม่มีข้อมูลอื่น
คำสั่ง ถามทีละชั้น จากล่างขึ้นบน แต่ละคำสั่งตัดชั้นหนึ่งออกได้
$ ifconfig en0 | grep 'status:' ชั้น 1 สายต่ออยู่ไหม
$ arp -an | grep 192.168.1.1 ชั้น 2 เห็นเกตเวย์ไหม
$ ping -c2 192.168.1.1 ชั้น 3 คุยกับเกตเวย์ได้ไหม
$ nc -vz example.com 443 ชั้น 4 พอร์ตเปิดไหม
$ curl -sI https://example.com ชั้น 7 แอปตอบไหม
อ่านอย่างไร คำสั่งแรกที่ล้มเหลวคือชั้นที่มีปัญหา และไม่ต้องไล่ต่อ เพราะทุกชั้นข้างบนขึ้นกับชั้นนั้น นี่คือคุณค่าที่แท้จริงของแบบจำลอง — มัน ไม่ได้บอกว่าระบบทำงานอย่างไร แต่บอกว่าควรถามคำถามเรียงลำดับไหน
สิ่งที่ยังไม่ได้พิสูจน์ ลำดับนี้ตัดชั้นล่างออกได้ก็จริง แต่บางปัญหา ข้ามชั้น เช่น MTU ที่ทำให้คำสั่งชั้น 3 ผ่านแต่ชั้น 7 ล้ม การไล่จากล่างขึ้นบน จะบอกว่า "ชั้น 7 มีปัญหา" ทั้งที่ต้นเหตุอยู่ชั้น 2
กรณีที่ 2 — checksum ผิดหลังผ่าน NAT
สถานการณ์ หลังเปลี่ยนอุปกรณ์ที่ทำ NAT บางการเชื่อมต่อล้มเหลวแบบสุ่ม
อ่านอย่างไร อุปกรณ์ NAT ต้องทำสองอย่างพร้อมกัน คือเปลี่ยนที่อยู่ IP ใน หัวชั้น 3 และคำนวณ checksum ของชั้น 4 ใหม่ เพราะที่อยู่ที่มันเพิ่งเปลี่ยน อยู่ใน pseudo-header ถ้ามันทำอย่างแรกแล้วลืมอย่างที่สอง ปลายทางจะทิ้ง เซกเมนต์นั้นเงียบ ๆ
จากตารางข้างบน การเปลี่ยนที่อยู่ปลายทางอย่างเดียวทำให้ checksum เปลี่ยนจาก 0x7654 เป็น 0x6485 — อุปกรณ์ที่ไม่คิดใหม่จะส่งค่าเดิมออกไปและปลายทาง คำนวณได้ไม่ตรง
สิ่งที่ยังไม่ได้พิสูจน์ อาการ "ล้มเหลวแบบสุ่ม" เข้าได้กับหลายสาเหตุ ทั้ง MTU ทั้งตารางของ NAT ที่เต็ม การจะยืนยันว่าเป็นเรื่อง checksum ต้อง ดักจับแพ็กเก็ตทั้งสองฝั่งของอุปกรณ์แล้วเทียบ ซึ่งบทความนี้ยังไม่ได้ทำ
กรณีที่ 3 — อธิบายให้คนที่ไม่ได้ทำเครือข่ายเข้าใจ
สถานการณ์ ต้องบอกทีมพัฒนาว่าทำไมเพิ่มแบนด์วิดท์แล้วแอปไม่เร็วขึ้น
อ่านอย่างไร ใช้ชั้นเป็นคำศัพท์ร่วม ไม่ใช่เป็นความจริงทางกายภาพ แบนด์วิดท์เป็นเรื่องของชั้นล่าง ส่วนความหน่วงที่แอปรู้สึกมาจากจำนวนรอบ ไป-กลับที่ชั้นบนต้องทำ การอธิบายว่า "ปัญหาไม่ได้อยู่ชั้นเดียวกับที่คุณเพิ่ม เงินลงไป" ทำให้บทสนทนาไปต่อได้โดยไม่ต้องเถียงเรื่องตัวเลข
สิ่งที่ยังไม่ได้พิสูจน์ นี่คือกรอบการอธิบาย ไม่ใช่การวินิจฉัย ต้องวัด จริงว่าคอขวดอยู่ที่รอบไป-กลับ ที่ซีพียู หรือที่ฐานข้อมูล ก่อนจะสรุป
กรณีที่ 4 — เมื่อสเปกสินค้าบอกว่า "รองรับ Layer 7"
สถานการณ์ ต้องเลือกอุปกรณ์ และสองยี่ห้อเขียนว่ารองรับชั้น 7 เหมือนกัน
อ่านอย่างไร คำนี้ไม่มีนิยามกลาง ต้องถามต่อว่ารองรับอะไรจริง ๆ
อ่าน Host header ได้ไหม
แยกเส้นทางตาม path ได้ไหม
ถอด TLS แล้วอ่านข้างในได้ไหม
รู้จักโพรโทคอลอะไรบ้างนอกจาก HTTP
สี่คำถามนี้ให้คำตอบที่ต่างกันมากระหว่างสินค้าที่เขียนคำเดียวกันบนกล่อง
สิ่งที่ยังไม่ได้พิสูจน์ คำตอบจากเอกสารของผู้ขายไม่เท่ากับพฤติกรรมจริง สิ่งที่พิสูจน์ได้อย่างเดียวคือการทดสอบกับทราฟฟิกของตัวเอง
แผนที่ที่ยังคุ้มค่าจะพก
หลังจากชี้ให้เห็นว่ามันไม่ตรงกับความจริงมาทั้งบทความ ข้อสรุปกลับไม่ใช่ให้ ทิ้งมัน
แบบจำลองยังมีค่าสองอย่าง อย่างแรกคือลำดับการถาม ตามกรณีที่ 1 ซึ่ง ประหยัดเวลาได้จริงเวลามีอะไรพัง อย่างที่สองคือคำศัพท์ร่วม ที่ทำให้คน สองคนคุยกันรู้เรื่องว่ากำลังพูดถึงส่วนไหน
สิ่งที่ควรทิ้งคือความเชื่อว่าเส้นแบ่งนั้นมีอยู่จริงในสายไฟ มันเป็นเส้นที่ คนขีดขึ้น ด้วยเหตุผลทางวิศวกรรมที่เขียนไว้ในเอกสาร พร้อมหมายเหตุกำกับว่า พิสูจน์ไม่ได้ว่าดีที่สุด
อ้างอิง
มาตรฐาน
- ITU-T X.200 ซึ่งเป็น ข้อความเดียวกับ ISO/IEC 7498-1 ปี 1994 — ที่มาของเจ็ดชั้น หลักการขีดเส้น และหมายเหตุที่ยกมาอ้าง โหลดได้ฟรี
- RFC 1122 ตุลาคม 1989 — สี่ชั้นของอินเทอร์เน็ต และคำอธิบายว่าชั้นบนของ OSI ถูกยุบรวมอย่างไร
- RFC 9293 นิยาม pseudo-header และเหตุผลที่ TCP ต้องรู้ค่าจากชั้น IP
- RFC 768 UDP ซึ่งใช้ pseudo-header แบบเดียวกัน
ข้อวิจารณ์