ฉันเจาะ ::1 ได้! (วิธีการเขียนและแอดเดรส IPv6 ที่ควรรู้)

by e.p.
8 February 2011 - 16:33

ในขณะที่ IPv6 กำลังเข้ามาเราน่าจะเรียนรู้เรื่องเล็กๆ น้อยๆ ของ IPv6 กันเสียหน่อย ไม่อย่างนั้นอาจจะมีคนทำเสื้อมาล้อเลียนเราได้ว่า "I hacked ::1"

เริ่มต้นด้วยการเขียนแอดเดรส IPv6 แบบเต็มๆ นั้นเราแบ่งเลข IPv6 ซึ่งมี 128 บิตออกเป็น 8 ชุด ชุดละ 16 บิต แล้วเขียนแต่ละชุดในรูปของเลขฐาน 16 คั่นแต่ละชุดจากกันด้วยเครื่องหมายโคลอน เช่น

0010000000000001 0000110110111000 0000000000000010 0000000000000011 0000000000000100 0000000000000101 0000000000000110 0000000000000111

เราจะเขียนได้เป็น
2001:db8:2:3:4:5:6:7

แต่ถ้าเลขฐาน 16 ที่มีค่าเป็น 0 อยู่ติดกันหลายชุดเราจะสามารถเขียนย่อด้วยโคลอนคู่ติดกันได้ เช่น

0010000000000001 0000110110111000 0000000000000010 0000000000000000 0000000000000000 0000000000000000 0000000000000110 0000000000000111

จะเขียนเป็น
2001:db8:2::6:7

เนื่องจากการเขียนนั้นทำได้หลายรูปแบบทำให้สับสนยุ่งยาก จึงได้มี RFC5952: A Recommendation for IPv6 Address Text Representation ที่เป็นการแนะนำการเขียนแอดเดรสของ IPv6 เอาไว้ดังนี้ (RFC ที่ยกมาแต่ละตัวตอนนี้มีสถานะต่างๆ กัน ไม่มีตัวไหนเป็น "มาตรฐาน" นะครับ ยังเปลี่ยนไปเปลี่ยนมาตลอด มองว่าเป็นคำแนะนำสำหรับเวลานี้ก็แล้วกัน)

  • ตัดเลข 0 ที่นำหน้าเลขฐาน 16 แต่ละชุดทิ้งทั้งหมด เช่น เราจะไม่เขียน "0db8" แต่จะต้องเขียน "db8" และเราจะไม่เขียน "0000" แต่จะต้องเขียน "0"
  • การใช้ "::"
    • ใช้ "::" ได้เพียงตำแหน่งเดียวเท่านั้น
    • ต้องเลือกตำแหน่งที่ทำให้ย่อได้มากที่สุด (นั่นหมายถึงเลือกตำแหน่งที่เลขฐาน 16 แต่ละชุดเป็น 0 ติดกันมากที่สุดเท่าที่จะทำได้) ถ้ามีหลายตำแหน่งที่สามารถย่อได้ยาวเท่ากัน ให้เลือกตำแหน่งทางซ้ายเสมอ เช่น 2001:db8:0:0:1:0:0:1 จะต้องย่อเป็น 2001:db8::1:0:0:1 เท่านั้น
    • ห้ามใช้ "::" เพื่อย่อเลข 0 เพียงตัวเดียว เช่นห้ามเขียน 2001:db8::1:1:1:1:1 เพราะ :: นั้นแทน :0: ซึ่งเป็น 0 เพียงตัวเดียว
  • ในส่วนเลขฐาน 16 ตัวอักษร 'a' 'b' 'c' 'd' 'e' 'f' ต้องใช้ตัวเล็ก (lowercase) เท่านั้น

ที่ผ่านมานั้นเป็นการเขียนแอดเดรส IPv6 ธรรมดา ในกรณีของแอดเดรส IPv6 พิเศษเช่น

  • IPv4-Mapped IPv6 address เลข IPv4 ที่เขียนในรูป IPv6 ซึ่งหลายคนคงเคยเห็นกันแล้วเวลาสั่ง netstat -n -a ในเครื่อง Linux ที่เปิด IPv6 ไว้แล้ว
  • ISATAP การทำท่อระหว่างเครื่องที่เป็น dual-stack ด้วยกันวิ่งผ่านบนเครือข่าย IPv4 แบบอัตโนมัติ
  • IPv4-translatable address ใช้ในการแปลง IPv6/IPv4 เพื่อทำท่อเชื่อม

ไอพีเหล่านี้มีความพิเศษตรงที่ได้ฝังเอาหมายเลข IPv4 เอาไว้ในส่วนนัยสำคัญต่ำ (ขวามือสุด) ของ IPv6 ซึ่งสามารถที่จะเขียนในรูปแบบพิเศษที่ผสมกันระหว่างเลขฐาน 16 ที่คั่นด้วยโคลอนกับเลขฐานสิบที่คั่นด้วยจุด โดยมีข้อกำหนดว่าแนะนำให้เขียนในรูปแบบพิเศษนี้เมื่อสามารถแบ่งแยกชี้ชัดได้ว่าไอพีนี้มี IPv4 แอดเดรสฝังอยู่โดยดูจาก "พรีฟิก (prefix: ส่วนต้นทางซ้ายมือของแอดเดรส)" ที่รู้กันดีเท่านั้น เช่นพรีฟิกที่กำหนดใน RFC4291 และ RFC2765 แต่ถ้ามีวิธีการอื่นที่ทำให้รู้ได้ว่าพรีฟิกนั้นมี IPv4 ฝังอยู่ก็อาจจะเขียนแบบผสมด้วยก็ได้

ตัวอย่าง IPv6 ที่เขียนในรูปแบบนี้เช่น ::ffff:10.0.0.1 (เป็น IPv4-Mapped IPv6 address)

ส่วนในการเขียน IPv6 ร่วมกับหมายเลขพอร์ทนั้นสามารถทำได้หลายวิธีเช่นเดียวกับ IPv4 เช่น

  • [2001:db8::1]:80 ควรใช้ อย่างที่เขียนใน RFC3986
  • 2001:db8::1:80 ไม่แนะนำเพราะมีความกำกวม
  • 2001:db8::1.80
  • 2001:db8::1 port 80
  • 2001:db8::1p80
  • 2001:db8::1#80

ตอนนี้เราพอจะรู้แล้วว่ารูปแบบการเขียน IPv6 นั้นเป็นอย่างไร แล้วมี "แอดเดรส/พรีฟิก" อะไรที่เราควรรู้ไว้บ้าง?

  • 2000::/3 Global Unicast ก็คือ IPv6 ที่มองเห็นทั้งโลก

    • 2001::/32 เอาไว้ใช้กับอุโมงแบบ Teredo
    • 2001:db8::/32 เอาไว้ใช้ในการทำเอกสาร เช่นใช้ในการยกตัวอย่าง (RFC3849)
    • 2002::/16 ใช้กับอุโมงแบบ 6to4
  • 3ffe:831f::/32 อุโมงแบบ Teredo เก่าเช่นที่ Windows เคยใช้ (ยังมีหลงเหลือให้เห็นอยู่)
  • fe80::/10 Link Local Unicast ไว้สำหรับติดต่อกันภายใน link เดียวกัน (เทียบแล้วจะใกล้เคียงกับภายใน subnet เดียวกัน)
  • ff00::/8 Multicast ส่งไปที่ผู้รับหลายๆ เครื่อง
    • ff02::1 All Node Address ทุกเครื่องใน subnet
    • ff02::2 All Routers Address ทุก router ใน subnet
  • ::/128 (ศูนย์หมด) Unspecified แทนไอพีที่ยังไม่ระบุ ตัวอย่างคือถ้าสั่ง netstat -a ดูพอร์ทที่เปิดรับ IPv6 จากเครื่องไหนก็ได้เอาไว้จะเจอไอพีนี้

และอันสุดท้าย

  • ::1/128 Loopback

รู้แบบนี้แล้วก็อย่าไปบอกใครเขาล่ะว่าได้ "hacked ::1" มา

ที่มา

Blognone Jobs Premium