ความสนุกของการพาร์สที่อยู่ IP
(blog.dave.tf)-
บทความที่สรุปสิ่งที่ได้เรียนรู้ระหว่างการสร้างพาร์เซอร์ IPv4+v6 แบบรวดเร็วให้อ่านง่าย
-
รูปแบบมาตรฐาน (Canonical)
→ v4 : 192.168.0.1 , Dotted Quad ของไบต์ 1 ไบต์แต่ละตัว
→ v6 : 1:2:3:4:5:6:7:8 , Colon-Hex ของไบต์ 2 ไบต์แต่ละตัว
[IPv6]
- เพราะมักมี 0 อยู่ตรงกลางจำนวนมาก จึงใช้
::เพื่อตัด 0 ออกตั้งแต่ 1 กลุ่มขึ้นไป
→ 1:2::3:4 = 1:2:0:0:0:0:3:4
- 32 บิตสุดท้ายสามารถเขียนด้วยรูปแบบ Dotted Quad ของ v4 ได้
→ 1:2:3:4:5:6:77.77.88.88 = 1:2:3:4:5:6:4d4d:5858
→ fe80::1.2.3.4 = fe80:0:0:0:0:0:102:304
- มีกรณีที่
::อยู่ต้นหรือท้าย ทำให้ซับซ้อนขึ้นอีกเล็กน้อย
→ ::1 = 0:0:0:0:0:0:0:1
→ 1:: = 1:0:0:0:0:0:0:0
→ :: = 0:0:0:0:0:0:0:0
- ทุกฟิลด์ของ IPv6 Colon-Hex เป็นเลขฐาน 16 ยาว 4 หลัก และตัด 0 ด้านหน้าออกได้
→ :: = 0000:0000:0000:0000:0000:0000:0000:0000
[IPv4]
- จุดที่น่าสนใจคือ ก่อนที่การเขียน Dotted Quad สำหรับ 32 บิตท้ายใน IPv6 จะถูกทำให้เป็นทางการ ก็ไม่เคยมีการทำให้เป็นมาตรฐานในเอกสารใดเลย
→ ดังนั้นมาตรฐานโดยพฤตินัย (de-facto) ในวงการจึงมักเป็นคำถามว่า “4.2BSD ตีความได้ไหม?” และ “เมื่อ OS อื่นคัดลอก 4.2BSD มา พวกเขาคงอะไรไว้บ้าง”
- แต่ 4.2BSD ค่อนข้างแปลก (whacky)
→ 192.168.140.255 = 3232271615 เหมือนกัน
→ กล่าวคือ ถ้าเข้า http://3232271615 ใน Chrome ก็จะโหลด http://192.168.140.255 เพราะมันเป็นตัวเลข 4 ไบต์!
→ แบบเลขฐาน 8 อย่าง http://0300.0250.0214.0377 ก็ใช้ได้
→ ถ้าอย่างนั้นแบบเลขฐาน 16 อย่าง https://0xc0.0xa8.0x8c.0xff ก็แน่นอนว่าเป็นที่อยู่เดียวกันทั้งหมด
- CIDR (Classless Inter-Domain Routing) ก็มีผลกับที่อยู่ IP เช่นกัน
→ รูปแบบคลาส C อย่าง 192.168.140.255 ถ้าเขียนเป็นคลาส B จะเป็น http://192.168.36095 และถ้าเขียนเป็นคลาส A จะเป็น http://192.11046143
→ นี่จึงเป็นเหตุผลว่าทำไม ping 127.1 จึงเท่ากับ 127.0.0.1 ได้ ไม่ใช่การตัด 0 ซ้ำแบบ IPv6 แต่หมายถึงโฮสต์ตัวที่ 1 ของเครือข่ายคลาส A หมายเลข 127 หรือก็คือตัวเลข 24 บิตค่า 1
- จะมี 0 นำหน้าได้กี่ตัวในตัวเลขของแต่ละ Quad?
→ 001.002.003.004 ? 0000000001.0000000002.0000000003.000000004 ?
→ (Chrome รองรับ http://0000000001.0000000002.0000000003.000000004 ด้วย)
→ แล้วตอนนี้ควรอ่านตัวเลขเหล่านี้เป็นเลขฐาน 8 หรือเลขฐาน 16? : การติดตั้งใช้งานสมัยใหม่เลิกใช้ฐาน 8/16 ไปแล้ว และจัดการ 0 นำหน้าเป็นเลขฐาน 10
- ปัญหาเรื่อง 0 นำหน้านี้ส่งผลถึง IPv6 ด้วย
→ 000001::00001.00002.00003.00004 = 1::1.2.3.4, or 1::102:304
→ พาร์เซอร์สมัยใหม่ส่วนใหญ่ใช้ไลบรารี “parse integer” กันอยู่แล้ว จึงมักยอมรับ 0 นำหน้าจำนวนมากทั้งหมด
สรุปคือ ถ้าจะพาร์สที่อยู่ IP ให้ครอบคลุมทั้งหมด ก็ต้องคำนึงถึงเรื่องชวนปวดหัวพวกนี้ทั้งหมด แต่...
พาร์เซอร์ของผู้เขียนรองรับประมาณนี้
-
รองรับรูปแบบ v4 แบบดั้งเดิมที่เป็นจำนวนเต็มคั่นด้วยจุด และยอมให้มี 0 นำหน้าได้ไม่จำกัด
-
ไม่รองรับรูปแบบคลาส A/B และเลขฐาน 8/16
-
ไม่รองรับการเขียนทุกอย่างด้วยตัวเลข
unit32เพียงตัวเดียว -
สำหรับ IPv6 รองรับทั้งรูปแบบ colon-hex มาตรฐาน, รูปแบบย่อ
::, และการต่อ IPv4 เข้าที่ 32 บิตสุดท้าย (โดย IPv4 นี้ใช้กฎด้านบน) แต่ละฟิลด์มี 0 นำหน้าได้ไม่จำกัด
- ตอนแรกผู้เขียนใส่วิธีต่อที่อยู่ IPv4 ไว้ท้ายสุดเพื่อช่วยย้ายจาก IPv4 ไป IPv6 ได้ง่ายขึ้น แต่ในความเป็นจริงแทบไม่ค่อยพบเห็น จึงแม้จะรองรับอยู่ แต่ก็คิดว่าไม่ได้มีประโยชน์นัก
2 ความคิดเห็น
โอ้ น่าสนุกดีนะ! เห็นเทคนิคหลายอย่างที่เหมาะกับการบิดแพลงตอนโจมตีอยู่เยอะเลย!
รู้สึกว่าแค่จะเขียนรูปแบบที่อยู่ IP ถ้าต้องใช้กฎที่ซับซ้อนขนาดนี้ มันก็เป็นการสิ้นเปลืองทรัพยากรคอมพิวเตอร์โดยใช่เหตุหรือเปล่านะ ^^;;