บทความ IP กับ ซับเน็ต อธิบายว่าเลขที่อยู่ คืออะไรและแบ่งกันอย่างไร แต่ไม่เคยตอบว่าเครื่องได้เลขนั้นมาจากไหน
คำตอบในบ้านและในออฟฟิศเกือบทั้งหมดคือ DHCP และหน้านี้คือเรื่องของมัน
ปัญหาที่มันแก้ฟังดูเป็นไปไม่ได้ตั้งแต่ต้น เครื่องที่ยังไม่มีเลขที่อยู่จะส่ง ข้อความออกไปขอได้อย่างไร ในเมื่อทุกแพ็กเก็ตต้องมีที่อยู่ต้นทาง
จะขอเลขที่อยู่ ต้องมีเลขที่อยู่ก่อน
คำถามนี้เก่ากว่า DHCP RFC 951 ซึ่งเป็นมาตรฐานของ BOOTP เมื่อเดือนกันยายน 1985 เขียนไว้ตรง ๆ ว่า
How can the server send an IP datagram to the client, if the client doesnt know its own IP address (yet)?
ทั้งโพรโทคอลนี้คือคำตอบของประโยคเดียวนั้น
คำตอบคือใช้ที่อยู่ที่ไม่ต้องรู้จักใครเลยทั้งสองทาง ขาไปใช้ 0.0.0.0 เป็น ต้นทาง ซึ่งแปลว่ายังไม่มีที่อยู่ และ 255.255.255.255 เป็นปลายทาง ซึ่งแปลว่า ทุกเครื่องบนสายนี้
ขากลับใช้ broadcast เหมือนกัน เพราะเซิร์ฟเวอร์ยังส่งตรงหาเครื่องที่ยังไม่มี ที่อยู่ไม่ได้
การพึ่ง broadcast ทั้งสองทางคือรากของข้อจำกัดทุกข้อที่เหลือในหน้านี้ ทั้งเรื่อง ที่มันข้ามเราเตอร์เองไม่ได้ และเรื่องที่ใครก็ตอบแทนได้
ถ้ายังไม่เคยดู เริ่มตรงนี้
เครื่อง Mac เก็บแพ็กเก็ต DHCP ใบล่าสุดที่ได้รับไว้ และเปิดดูได้ทั้งใบ
$ ipconfig getpacket en0
op = BOOTREPLY
htype = 1
hlen = 6
hops = 0
xid = 0x3f7a12c4
secs = 0
flags = 0x0
ciaddr = 192.0.2.31
yiaddr = 192.0.2.31
siaddr = 0.0.0.0
giaddr = 0.0.0.0
chaddr = 00:00:5e:00:53:11
sname =
file =
options:
dhcp_message_type (uint8): ACK 0x5
server_identifier (ip): 192.0.2.1
lease_time (uint32): 0x15180
subnet_mask (ip): 255.255.255.0
router (ip_mult): {192.0.2.1}
domain_name_server (ip_mult): {192.0.2.1}
end (none):
นี่คือทั้งบทความในหน้าจอเดียว ทุกชื่อฟิลด์ในนั้นจะได้อธิบายทีละอัน
สามอย่างที่ควรสังเกตไว้ก่อน siaddr กับ giaddr เป็นศูนย์ทั้งคู่ sname กับ file ว่างเปล่า และ lease_time เป็นเลขฐานสิบหกที่แปลงแล้วได้ตัวเลขกลม ๆ
DORA — สี่ข้อความ และทำไมไม่ใช่สอง
ชื่อเล่นของลำดับนี้คือ DORA ตามอักษรแรกของทั้งสี่
1 DISCOVER เครื่องตะโกนถามว่ามีใครแจกเลขบ้าง
2 OFFER เซิร์ฟเวอร์เสนอเลขมาให้ แต่ยังไม่จอง
3 REQUEST เครื่องบอกว่าเอาของใคร
4 ACK เซิร์ฟเวอร์ยืนยันและจองจริง
คำถามที่ควรถามคือทำไมไม่สองข้อความ ถามแล้วตอบก็น่าจะจบ
คำตอบคือเซิร์ฟเวอร์อาจมีมากกว่าหนึ่งตัว และทั้งหมดได้ยิน DISCOVER ใบเดียวกัน เพราะมันเป็น broadcast ถ้าแต่ละตัวจองเลขให้ทันทีที่ตอบ เลขจะถูกจองซ้ำซ้อนโดยที่ เครื่องใช้จริงแค่อันเดียว
ขั้น REQUEST จึงมีไว้ประกาศว่าเลือกใคร และ RFC 2131 บังคับว่าข้อความนี้ "MUST include the 'server identifier' option to indicate which server it has selected"
ทำไม REQUEST ยังต้อง broadcast
จุดนี้คนมองข้ามบ่อยที่สุด ในเมื่อเครื่องรู้แล้วว่าจะเอาของใคร ทำไมไม่ส่งตรงไป
เพราะ เซิร์ฟเวอร์ที่ไม่ถูกเลือกก็ต้องรู้ด้วย ว่าเลขที่ตัวเองเสนอไปนั้นไม่ได้ ถูกใช้ จะได้ปล่อยคืนพูล ถ้า REQUEST ส่งตรงไปหาตัวที่ถูกเลือกตัวเดียว ตัวอื่น จะค้างเลขไว้จนกว่าจะหมดเวลาเอง
การ broadcast จึงไม่ใช่ความไม่ประณีต แต่เป็นวิธีบอกทุกคนพร้อมกันด้วยข้อความเดียว
รูปร่างของข้อความ
off field octets meaning
0 op 1 1 = request, 2 = reply
1 htype 1 hardware type, 1 = ethernet
2 hlen 1 hardware address length, 6
3 hops 1 relay agents increment this
4 xid 4 transaction id, chosen by the client
8 secs 2 seconds since the client started
10 flags 2 one bit asks for a broadcast reply
12 ciaddr 4 the client's own address, if it has one
16 yiaddr 4 the address being handed out
20 siaddr 4 next server, for booting
24 giaddr 4 relay agent address
28 chaddr 16 client hardware address
44 sname 64 server host name
108 file 128 boot file name
236 cookie 4 99.130.83.99
240 options var
236 ไบต์ที่สืบทอดมาจากปี 1985
sname 64 ไบต์กับ file 128 ไบต์รวมกันเป็น 192 จาก 236 ไบต์ คือ 81% ของหัว ทั้งใบ และบนเครื่องที่เอาแพ็กเก็ตมาดูข้างบน ทั้งคู่ว่างเปล่า
สองฟิลด์นั้นมาจากงานดั้งเดิมของ BOOTP ซึ่งไม่ใช่การแจกเลขที่อยู่ แต่คือการบูต เครื่องที่ไม่มีดิสก์ RFC 951 บอกว่ามันมีไว้ให้เครื่องรู้ "the address of a server host, and the name of a file to be loaded into memory and executed"
เครื่องที่ไม่มีดิสก์แทบไม่เหลือแล้ว แต่ไบต์ยังอยู่ครบ เพราะการเอาออกแปลว่า ต้องเปลี่ยนโครงข้อความ ซึ่งจะทำให้อุปกรณ์เก่าทุกตัวในโลกใช้ไม่ได้ทันที
นี่คือตัวอย่างที่ชัดที่สุดของสิ่งที่เกิดกับโพรโทคอลที่สำเร็จ ราคาของการเข้ากันได้ ย้อนหลังจ่ายเป็นไบต์ทุกใบ ตลอดไป
magic cookie คือรอยต่อ
DHCP ไม่ได้ออกแบบใหม่ มันสร้างทับ BOOTP และตัวที่แยกสองอย่างออกจากกันคือเลขสี่ ไบต์ที่ต่อท้าย 236 ไบต์นั้น
RFC 2132 นิยามไว้ว่า "The value of the magic cookie is the 4 octet dotted decimal 99.130.83.99 (or hexadecimal number 63.82.53.63) in network byte order"
เจอเลขชุดนี้แปลว่าที่ตามมาคือ options แบบ DHCP ไม่เจอก็เป็น BOOTP ธรรมดา สี่ไบต์นั้นคือทั้งหมดที่แยกโพรโทคอลสองตัวออกจากกัน
options เป็น TLV
RFC 2132 อธิบายโครงไว้ว่า "All options begin with a tag octet, which uniquely identifies the option ... All other options are variable-length with a length octet following the tag octet"
คือ tag หนึ่งไบต์ length หนึ่งไบต์ แล้วค่ายาวตามที่ length บอก ยกเว้นสองอันที่มี แค่ tag คือ pad กับ end
โครงแบบนี้คือเหตุผลที่ DHCP ยังไม่ตาย เพิ่มความสามารถใหม่ได้ด้วยการจอง หมายเลข tag ใหม่ ตัวที่ไม่รู้จักข้ามไปได้เพราะรู้ความยาว โครงข้อความไม่ต้องเปลี่ยน
หมายเลขที่เจอบ่อย
1 subnet mask
3 router
6 domain name server
12 host name
50 requested ip address
51 ip address lease time
53 dhcp message type
54 server identifier
55 parameter request list
58 renewal time T1
59 rebinding time T2
82 relay agent information
255 end
option 53 คือตัวที่บอกว่าข้อความนี้เป็นอะไรในลำดับ DORA ซึ่งน่าสนใจตรงที่ ชนิดของข้อความไม่ได้อยู่ในหัวหลัก แต่อยู่ใน options เพราะหัวหลักเป็นของ BOOTP ซึ่งไม่มีแนวคิดเรื่องชนิดข้อความ
1 DISCOVER 5 ACK
2 OFFER 6 NAK
3 REQUEST 7 RELEASE
4 DECLINE 8 INFORM
และ option 55 คือรายการที่เครื่องขอ ไม่ใช่รายการที่เซิร์ฟเวอร์ให้ เครื่อง บอกไปว่าอยากรู้อะไรบ้าง เซิร์ฟเวอร์พยายามตอบให้ครบเท่าที่มี
ทำไมต้องสองพอร์ต
DHCP ใช้พอร์ต 67 สำหรับเซิร์ฟเวอร์ และ 68 สำหรับเครื่องลูก RFC 2131 เขียนไว้ว่า "DHCP messages from a client to a server are sent to the 'DHCP server' port (67), and DHCP messages from a server to a client are sent to the 'DHCP client' port (68)"
คำถามคือทำไมไม่ให้เครื่องลูกใช้พอร์ตชั่วคราวแบบทุกโปรแกรมอื่น
เพราะคำตอบเป็น broadcast ถ้าเครื่องลูกใช้พอร์ตสุ่ม เซิร์ฟเวอร์จะไม่รู้ว่าจะ ส่ง broadcast ไปที่พอร์ตไหน และเครื่องอื่นทุกเครื่องบนสายก็จะได้รับมันด้วย
RFC 951 อธิบายเหตุผลเดิมไว้อีกชั้นว่าการใช้สองพอร์ตช่วยเลี่ยงการปลุกเดมอนของ เซิร์ฟเวอร์ตัวอื่นขึ้นมาโดยไม่จำเป็นเวลามีการ broadcast คำตอบ
นี่คือผลพวงโดยตรงของการที่โพรโทคอลนี้ต้องทำงานตอนที่ยังไม่มีที่อยู่ ทุกอย่าง ที่ต้องเจรจากันไว้ล่วงหน้าไม่ได้ ต้องตรึงเป็นค่าคงที่
สัญญาเช่า และเวลาสองจุดที่ต้องรู้
เลขที่ได้มาไม่ใช่ของถาวร มันมีอายุ และค่าที่เครื่องนี้ได้มาคือ 0x15180
lease 0x15180 = 86400 s = 24 h
T1 0.5 x 86400 = 43200 s = 12 h
T2 0.875 x 86400 = 75600 s = 21 h
T1 ต่อตรง T2 ตะโกน
RFC 2131 กำหนดค่าตั้งต้นของทั้งสองไว้ตรง ๆ ว่า "T1 defaults to (0.5 duration_of_lease). T2 defaults to (0.875 duration_of_lease)"
ถึง T1 เครื่องส่ง REQUEST ตรงไปที่เซิร์ฟเวอร์เดิม เพราะยังจำได้ว่าใครเป็นคน ให้มา จาก option 54 ที่แนบมากับ ACK ขั้นนี้ไม่ต้อง broadcast เพราะตอนนี้เครื่อง มีที่อยู่แล้ว
ถึง T2 แล้วยังไม่มีใครตอบ เครื่องเปลี่ยนเป็น broadcast เพราะการเงียบแปลว่า เซิร์ฟเวอร์เดิมอาจตายไปแล้ว จึงต้องถามใครก็ได้ที่ยังอยู่
การมีสองจุดแทนที่จะเป็นจุดเดียวคือการเผื่อเวลาไว้ ระหว่าง T1 กับ T2 มีเวลา เก้าชั่วโมงให้ลองใหม่ซ้ำ ๆ ก่อนที่จะยอมแพ้กับเซิร์ฟเวอร์เดิม และระหว่าง T2 กับ วันหมดอายุยังเหลืออีกสามชั่วโมงให้หาเจ้าใหม่
ถ้าหมดอายุแล้วยังไม่ได้ ACK RFC บอกว่าเครื่อง "MUST immediately stop any other network processing" คือต้องหยุดใช้เลขนั้นทันที ไม่ใช่ใช้ต่อไปเรื่อย ๆ
ข้าม subnet ได้อย่างไร ทั้งที่เป็น broadcast
broadcast ไม่ข้ามเราเตอร์ ซึ่งเป็นข้อที่บทความ Spanning Tree กับ VLAN พูดถึงจากมุมของ การจำกัดขอบเขต แต่ตรงนี้มันกลายเป็นปัญหา เพราะแปลว่าต้องมีเซิร์ฟเวอร์ DHCP ทุกซับเน็ต
ทางแก้คือให้เราเตอร์ทำหน้าที่คนกลาง RFC 2131 นิยามว่า "A BOOTP relay agent or relay agent is an Internet host or router that passes DHCP messages between DHCP clients and DHCP servers" และบอกผลไว้ว่ามัน "eliminates the necessity of having a DHCP server on each physical network segment"
กลไกทั้งหมดอยู่ในฟิลด์ giaddr เราเตอร์เขียนที่อยู่ของตัวเองบนซับเน็ตของ เครื่องลูกลงไป แล้วส่งต่อแบบ unicast ไปยังเซิร์ฟเวอร์
ฟิลด์เดียวนั้นทำสองหน้าที่พร้อมกัน
หน้าที่แรก บอกว่าจะหยิบเลขจากพูลไหน เพราะที่อยู่ของเราเตอร์บอกว่าเครื่องลูก อยู่ซับเน็ตอะไร
หน้าที่สอง บอกว่าจะส่งคำตอบกลับไปที่ไหน RFC เขียนว่าถ้า giaddr ไม่เป็นศูนย์ เซิร์ฟเวอร์จะส่งคำตอบไปที่พอร์ตเซิร์ฟเวอร์ของ relay ตัวที่อยู่ใน giaddr นั้น
บนเครื่องที่ดูแพ็กเก็ตข้างบน giaddr = 0.0.0.0 ซึ่งพิสูจน์ว่าไม่มี relay คั่นกลาง เซิร์ฟเวอร์อยู่บนสายเดียวกัน
option 82 — สิ่งที่ relay แอบเติมเข้าไป
RFC 3046 ปี 2001 เพิ่ม option 82 ให้ relay แนบข้อมูลว่าคำขอนี้มาจากพอร์ตไหนหรือ สายไหน
ประโยชน์คือเซิร์ฟเวอร์ตัดสินใจได้ละเอียดขึ้น RFC เขียนว่า "Servers recognizing the Relay Agent Information option may use the information to implement IP address or other parameter assignment policies"
และสมมติฐานด้านความปลอดภัยของมันน่าสนใจกว่าตัวกลไก RFC ระบุว่ามันตั้งอยู่บน ความสัมพันธ์ที่เชื่อใจกันระหว่าง relay กับเซิร์ฟเวอร์ โดยถือว่าเครื่องลูกเป็น ฝ่ายที่เชื่อไม่ได้ ซึ่งเป็นการยอมรับตรง ๆ ว่าโพรโทคอลนี้ไม่มีทางเชื่อสิ่งที่ เครื่องลูกบอกมาได้เลย
เมื่อไม่มีใครตอบ — 169.254
ถ้าไม่มีเซิร์ฟเวอร์ตอบเลย เครื่องไม่ได้ยอมแพ้เฉย ๆ RFC 3927 ปี 2005 กำหนดทาง ออกไว้ให้
ช่วงที่สงวนไว้คือ 169.254/16 และเครื่องเลือกเลขในนั้นมาใช้เอง แล้วตรวจว่าไม่ซ้ำ กับใครบนสาย
169.254.0.0 - 169.254.0.255 สงวนไว้
169.254.1.0 - 169.254.254.255 ใช้ได้จริง
169.254.255.0 - 169.254.255.255 สงวนไว้
RFC ระบุว่า "The first 256 and last 256 addresses in the 169.254/16 prefix are reserved for future use and MUST NOT be selected" เหลือใช้จริง 65,024 เลข
สิ่งที่ต้องเข้าใจคือเลขพวกนี้คุยกันได้เฉพาะบนสายเดียวกัน ไม่มีเกตเวย์ ไม่มี DNS ออกเน็ตไม่ได้ การเห็นเลข 169.254 บนเครื่องจึงไม่ใช่การตั้งค่าอะไร มันคือข้อความแจ้งข้อผิดพลาดที่หน้าตาเหมือนที่อยู่
ใครก็ตั้งเซิร์ฟเวอร์ได้
DHCP ไม่มีการยืนยันตัวตนใด ๆ ทั้งสิ้น ไม่มีลายเซ็น ไม่มีรหัส ใครส่ง OFFER ได้ก็เป็นเซิร์ฟเวอร์ได้
และเครื่องลูกรับใบที่มาถึงก่อน ซึ่งเครื่องผู้โจมตีที่อยู่บนสายเดียวกันมักตอบได้ เร็วกว่าเซิร์ฟเวอร์จริงที่ต้องผ่านสวิตช์หลายตัว
ผลที่ได้ร้ายกว่าที่คิด เพราะสิ่งที่ DHCP แจกไม่ได้มีแค่เลขที่อยู่ มันแจก เกตเวย์ กับ DNS ด้วย
- ตั้งเกตเวย์เป็นเครื่องตัวเอง ทราฟฟิกทั้งหมดวิ่งผ่าน
- ตั้ง DNS เป็นเครื่องตัวเอง ทุกชื่อที่ผู้ใช้พิมพ์ตอบเองได้
สังเกตว่าทั้งสองอย่างทำได้โดยไม่ต้องแตะเครื่องเป้าหมายเลย และเหยื่อไม่มีทางรู้ เพราะทุกอย่างดูปกติทุกประการ
ทางแก้ไม่ได้อยู่ในโพรโทคอล ต้องไปทำที่สวิตช์ ด้วยการทำเครื่องหมายว่าพอร์ตไหน มีสิทธิ์ส่งข้อความแบบเซิร์ฟเวอร์ได้บ้าง แล้วทิ้งของที่มาจากพอร์ตอื่น
ฝั่ง IPv6
DHCPv4 255.255.255.255 67 68
DHCPv6 ff02::1:2 547 546
ที่อยู่ปลายทางเปลี่ยนเพราะบทความ IPv6 อธิบายไว้แล้วว่า IPv6 ไม่มี broadcast เลย จึงต้องใช้กลุ่ม multicast แทน และกลุ่มนั้นชื่อ All_DHCP_Relay_Agents_and_Servers
RFC 8415 ปี 2018 ระบุพอร์ตไว้ว่า "Clients listen for DHCP messages on UDP port 546. Servers and relay agents listen for DHCP messages on UDP port 547"
ความต่างที่ใหญ่กว่านั้นคือ IPv6 มีทางเลือกอื่น บทความ IPv6 อธิบาย SLAAC ไว้ แล้วว่าเครื่องหาที่อยู่เองได้โดยไม่ต้องมีเซิร์ฟเวอร์ ส่วน RFC 8415 ระบุว่า DHCPv6 "can operate either in place of or in addition to stateless address autoconfiguration"
ทำแทนก็ได้ ทำเสริมก็ได้ ซึ่งเป็นสิ่งที่ฝั่ง IPv4 ไม่เคยมี ที่นั่นมีแค่ DHCP หรือตั้งเลขเองด้วยมือ
เมื่อมันโกหก
"ได้ IP แล้วแปลว่าเน็ตใช้ได้" ไม่ใช่ DHCP แจกสี่อย่างแยกกันคือเลขที่อยู่ ซับเน็ตมาสก์ เกตเวย์ และ DNS ขาดอย่างใดอย่างหนึ่งก็พังคนละแบบ ไม่มีเกตเวย์ ก็ออกนอกซับเน็ตไม่ได้ ไม่มี DNS ก็ใช้ชื่อไม่ได้แต่ใช้เลขได้
"เลขที่ได้จะเป็นเลขเดิมเสมอ" ไม่มีอะไรรับประกัน เซิร์ฟเวอร์มักจะให้เลขเดิม ถ้ายังว่างอยู่ แต่นั่นเป็นนโยบายของแต่ละตัว ไม่ใช่ข้อกำหนดในมาตรฐาน
"ตั้ง IP เองแล้วไม่ต้องยุ่งกับ DHCP" ตั้งเองได้ แต่ต้องเลือกเลขที่อยู่นอกพูล ที่เซิร์ฟเวอร์แจก มิฉะนั้นวันหนึ่งจะมีเครื่องอื่นได้เลขเดียวกันไป
"lease นานไว้ก่อนดีกว่า" ไม่เสมอไป lease ยาวแปลว่าเลขที่เครื่องเลิกใช้แล้ว ยังถูกจองอยู่นาน ซึ่งเป็นปัญหาในที่ที่คนเข้าออกเยอะอย่างร้านกาแฟ ส่วน lease สั้น แปลว่าต่ออายุบ่อยและเซิร์ฟเวอร์ทำงานหนักขึ้น
"DHCP อยู่ที่เราเตอร์เสมอ" ในบ้านใช่ ในองค์กรมักไม่ใช่ เราเตอร์ทำหน้าที่แค่ relay ส่วนเซิร์ฟเวอร์จริงอยู่ที่อื่น ซึ่งเป็นเหตุผลที่ฟิลด์ giaddr มีอยู่
ตัวอย่างจริงจากงานจริง
กรณีที่ 1 — เครื่องได้เลขขึ้นต้นด้วย 169.254
เสียบสายแล้วเครื่องขึ้นว่าต่อแล้ว แต่ออกเน็ตไม่ได้ และเลขที่อยู่หน้าตาแปลก
อ่านอย่างไร เลขขึ้นต้น 169.254 คือคำตอบทั้งหมด ไม่มีเซิร์ฟเวอร์ DHCP ตัวไหนตอบเลย เครื่องจึงตั้งเลขให้ตัวเองตาม RFC 3927
$ ipconfig getpacket en0
ipconfig: getpacket: no packet
ไม่มีแพ็กเก็ตให้ดูเลย ซึ่งยืนยันว่าไม่เคยได้รับ ACK
จากตรงนี้แยกได้เป็นสองทาง ถ้าเครื่องอื่นบนสายเดียวกันได้เลขปกติ ปัญหาอยู่ที่ พอร์ตหรือสายของเครื่องนี้ ถ้าทุกเครื่องเป็นเหมือนกัน ปัญหาอยู่ที่เซิร์ฟเวอร์ หรือที่ relay บนเราเตอร์
สิ่งที่ยังไม่ได้พิสูจน์ เรารู้ว่าไม่มีใครตอบ แต่ยังไม่รู้ว่าคำขอออกไปถึงไหน ให้ดักดูทราฟฟิกที่พอร์ตนั้นว่ามี DISCOVER ออกไปจริงหรือไม่ก่อนไปโทษเซิร์ฟเวอร์
กรณีที่ 2 — ได้เลขมา แต่เป็นเลขของเครือข่ายอื่น
เครื่องได้เลขที่อยู่ปกติ แต่เป็นช่วงที่ไม่ควรได้ และออกเน็ตไม่ได้
อ่านอย่างไร เปิดแพ็กเก็ตดูว่าใครเป็นคนให้
$ ipconfig getpacket en0 | grep -E 'server_identifier|router|yiaddr'
yiaddr = 198.51.100.44
server_identifier (ip): 198.51.100.9
router (ip_mult): {198.51.100.9}
server_identifier คือคำตอบ มันบอกว่าใครเป็นคนตอบ ถ้าเลขนั้นไม่ใช่ เซิร์ฟเวอร์ที่ควรจะเป็น แปลว่ามีตัวอื่นตอบแทน
สองสาเหตุที่พบบ่อย หนึ่งคือมีคนเสียบเราเตอร์บ้านเข้ามาในเครือข่าย ซึ่งเปิด DHCP มาจากโรงงานเสมอ สองคือพอร์ตถูกตั้ง VLAN ผิด ทำให้เครื่องไปได้ยิน เซิร์ฟเวอร์ของเครือข่ายอื่น
สังเกตว่า router ชี้ไปที่เดียวกับ server_identifier ซึ่งเป็นลายเซ็นของ เราเตอร์บ้านที่ทำทุกอย่างเองในตัวเดียว
สิ่งที่ยังไม่ได้พิสูจน์ เรารู้ว่าใครตอบ แต่ยังไม่รู้ว่ามันเสียบอยู่พอร์ตไหน ให้ตามหาจาก MAC ของมันในตาราง MAC ของสวิตช์
กรณีที่ 3 — เครื่องใหม่ขอเลขไม่ได้ ทั้งที่เครื่องเก่าใช้ได้ปกติ
เครื่องที่เคยได้เลขแล้วยังใช้ได้ แต่เครื่องที่เพิ่งมาใหม่ไม่ได้เลย และเกิดตอน คนเยอะ
อ่านอย่างไร อาการที่แยกเครื่องเก่ากับเครื่องใหม่ออกจากกันแบบนี้คือลายเซ็นของ พูลหมด ไม่ใช่ของเซิร์ฟเวอร์ล่ม เพราะเครื่องเก่าแค่ต่ออายุเลขเดิมซึ่งยังจองอยู่
คำนวณเพดานได้ตรง ๆ จากขนาดซับเน็ต ซับเน็ต /24 มีเลขใช้ได้ 254 เลข หักที่ตั้ง ตายตัวไว้แล้วเหลือเท่าไรคือเพดานจริง
และ lease time คือตัวคูณที่คนลืม ที่ที่คนเข้าออกเร็วอย่างร้านกาแฟหรือห้อง ประชุม lease 24 ชั่วโมงแปลว่าเลขของคนที่เดินออกไปแล้วยังถูกจองไว้อีกเกือบวัน
ทางแก้มีสองทางที่ต้องเลือก ขยายซับเน็ตให้ใหญ่ขึ้น หรือลด lease ให้สั้นลงจนคืนเลข ได้ทันกับอัตราคนเข้าออก
สิ่งที่ยังไม่ได้พิสูจน์ เราคำนวณว่าพูลน่าจะหมด แต่ยังไม่ได้ดูของจริง ให้เปิดดูตารางการจองบนเซิร์ฟเวอร์ว่าจองไปกี่รายการและกี่รายการที่ยังใช้อยู่จริง
กรณีที่ 4 — อยากรู้ว่าเลขที่ใช้อยู่ตอนนี้มาจากไหน
ไม่มีอาการผิดปกติ แต่ต้องยืนยันว่าเครื่องได้ค่าอะไรมาบ้างและจากใคร
อ่านอย่างไร เปิดแพ็กเก็ตล่าสุดดูทั้งใบ
$ ipconfig getpacket en0 | grep -A9 options
options:
dhcp_message_type (uint8): ACK 0x5
server_identifier (ip): 192.0.2.1
lease_time (uint32): 0x15180
subnet_mask (ip): 255.255.255.0
router (ip_mult): {192.0.2.1}
domain_name_server (ip_mult): {192.0.2.1}
end (none):
เจ็ดบรรทัดนี้บอกทุกอย่าง ใครเป็นคนให้ ให้มานานเท่าไร และให้อะไรมาบ้าง
เทคนิคที่ใช้ได้ตลอดคือแปลง lease_time เอง 0x15180 เป็นเลขฐานสิบได้ 86400 ซึ่งคือ 24 ชั่วโมงพอดี จากตรงนั้นคำนวณ T1 กับ T2 ต่อได้ทันทีด้วย 0.5 กับ 0.875
สิ่งที่ยังไม่ได้พิสูจน์ แพ็กเก็ตนี้คือใบล่าสุดที่ได้รับ ไม่ได้บอกว่าตอนนี้ ยังเหลือเวลาอีกเท่าไร ต้องดูว่าได้รับมาเมื่อไรแล้วหักออกจาก lease เอง
อ้างอิง
มาตรฐานหลัก
- RFC 2131 — Dynamic Host Configuration Protocol R. Droms, มีนาคม 1997 Standards Track แทนที่ RFC 1541 ที่มาของโครงข้อความ ลำดับ DORA พอร์ต 67 กับ 68 ค่าตั้งต้นของ T1 กับ T2 และนิยามของ relay agent
- RFC 2132 — DHCP Options and BOOTP Vendor Extensions S. Alexander และ R. Droms, มีนาคม 1997 ที่มาของ magic cookie โครง TLV หมายเลข option ทั้งหมด และค่าของ message type แปดค่า
- RFC 951 — Bootstrap Protocol Bill Croft และ John Gilmore, กันยายน 1985 ต้นกำเนิดของโครงข้อความทั้งใบ คำถามเรื่องไก่กับไข่ และเหตุผลของการใช้สองพอร์ต
ส่วนขยาย
- RFC 3046 — DHCP Relay Agent Information Option M. Patrick, มกราคม 2001 option 82 และสมมติฐานว่าเครื่องลูกเป็นฝ่ายที่เชื่อไม่ได้
- RFC 3927 — Dynamic Configuration of IPv4 Link-Local Addresses Cheshire, Aboba และ Guttman, พฤษภาคม 2005 ที่มาของ 169.254/16 และช่วงที่ สงวนไว้หัวท้ายอย่างละ 256 เลข
- RFC 8415 — DHCP for IPv6 พฤศจิกายน 2018 แทนที่เจ็ดฉบับ พอร์ต 546 กับ 547 กลุ่ม ff02::1:2 และ ความสัมพันธ์กับ SLAAC
ของจริงบนเครื่อง
ipconfig getpacket en0บน macOS แสดงแพ็กเก็ต DHCP ใบล่าสุดทั้งใบ ทั้งฟิลด์ ของ BOOTP และ options ที่ได้รับมา- ค่า
lease_timeที่เป็น0x15180แปลงได้ 86400 วินาที ซึ่งเป็นที่มาของ ตัวเลข 12 กับ 21 ชั่วโมงในรูป
อ่านต่อในชุดนี้