NetKubeLab EN

DNS — ทำไม "มันคือ DNS" ถึงเป็นคำตอบที่ถูกบ่อยจนกลายเป็นมุก

กลไก ประวัติ และการไล่ปัญหาของ DNS ตั้งแต่ไฟล์ HOSTS.TXT ไฟล์เดียวของทั้งอินเทอร์เน็ต ไปจนถึงเหตุผลที่คนสองคนถามชื่อเดียวกันแล้วได้คำตอบไม่ตรงกัน

ในวงการมีมุกที่เล่ากันจนเบื่อว่า เวลาอะไรพังแล้วหาสาเหตุไม่เจอ ให้เดาไว้ก่อนว่า "มันคือ DNS" มุกนี้อยู่ได้นานเพราะมันถูกบ่อยจนน่าตกใจ

เหตุผลไม่ใช่เพราะ DNS ห่วย ตรงกันข้าม มันเป็นระบบกระจายที่ออกแบบมาดีมาก ทำงานมาสี่สิบปีโดยแทบไม่ต้องแก้แกนกลาง ปัญหาคือมันตั้งใจให้คำตอบไม่สด และตั้งใจให้คนละคนได้คำตอบไม่ตรงกันได้ ซึ่งเป็นสองอย่างที่ทำให้การไล่ปัญหา ยากกว่าที่ควรถ้าไม่เข้าใจว่าทำไมมันถึงถูกออกแบบมาแบบนั้น

หน้านี้เริ่มจากศูนย์ แล้วไล่ลงไปจนถึงระดับที่ใช้ทำงานจริงได้

เว็บนี้มีบทความเรื่อง ping กับ traceroute อยู่แล้ว สามเรื่องนี้ประกอบกันเป็นลำดับ การไล่ปัญหาที่คนทำงานจริงใช้จริง — ชื่อแปลงได้ไหม → ถึงไหม → ไปหยุดตรงไหน และหน้านี้คือข้อแรกซึ่งเป็นข้อที่พังบ่อยที่สุด

ถ้ายังไม่เคยพิมพ์มาก่อน เริ่มตรงนี้

dig netkubelab.com

ถ้าไม่มี dig ใช้ nslookup netkubelab.com แทนได้ทุกระบบ

สิ่งที่ได้

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57362
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; ANSWER SECTION:
netkubelab.com.		300	IN	A	104.21.35.137
netkubelab.com.		300	IN	A	172.67.175.92

อ่านง่าย ๆ คือ ชื่อ netkubelab.com แปลงเป็นเลขได้สองเลข และคำตอบนี้ เก็บไว้ใช้ซ้ำได้อีก 300 วินาที

ตัวเลข 300 นั้นคือ TTL และมันคือหัวใจของทั้งบทความนี้

ก่อนปี 1983 ทั้งอินเทอร์เน็ตมีไฟล์ชื่อเดียว

ก่อนปี 1983 ทุกเครื่องดึงไฟล์ HOSTS.TXT ไฟล์เดียวกันจาก SRI-NIC มาเก็บไว้เอง หลังจากนั้นเปลี่ยนเป็นการมอบอำนาจเป็นชั้นที่ไม่มีใครถือข้อมูลทั้งหมด

สมัย ARPANET การแปลงชื่อเป็นเลขทำด้วยไฟล์ข้อความไฟล์เดียวชื่อ HOSTS.TXT ดูแลโดย Network Information Center ที่ SRI ทุกเครื่องบนเครือข่ายต้องดาวน์โหลด ไฟล์นั้นมาเก็บไว้ในเครื่องตัวเอง อยากให้ชื่อใหม่ใช้ได้ก็ต้องส่งเรื่องไปให้ NIC แก้ไฟล์ แล้วรอให้คนอื่นดาวน์โหลดฉบับใหม่

RFC 1034 ซึ่งเป็นเอกสารที่นิยาม DNS อธิบายไว้เองว่าทำไมวิธีนั้นไปต่อไม่ได้

ปริมาณข้อมูลรวมที่ใช้แจกจ่ายไฟล์ฉบับใหม่ด้วยวิธีนี้ แปรผันตามกำลังสอง ของจำนวนเครื่องในเครือข่าย

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

เอกสารเดียวกันยังบอกอีกข้อที่สำคัญไม่แพ้กัน — เครือข่ายเปลี่ยนไปจากเครื่อง ขนาดใหญ่ที่คนใช้ร่วมกัน มาเป็นเครือข่ายของเวิร์กสเตชันในองค์กร องค์กรเหล่านั้น ดูแลชื่อของตัวเองอยู่แล้ว แต่ต้องรอ NIC แก้ไฟล์กลางให้ก่อนชื่อถึงจะใช้ได้จริง

Paul Mockapetris ออกแบบระบบใหม่ในปี 1983 เผยแพร่เป็น RFC 882 กับ RFC 883 ต่อมาถูกเขียนใหม่เป็น RFC 1034 และ RFC 1035 ในเดือนพฤศจิกายน 1987 ซึ่งยังเป็นเอกสารฐานของ DNS จนถึงวันนี้

น่าสังเกตว่าปี 1983 เป็นปีเดียวกับที่ Mike Muuss เขียน ping — ปีที่ TCP/IP บนอินเทอร์เน็ตอายุยังไม่ถึงหนึ่งปี และเป็นปีที่เครื่องมือพื้นฐานหลายอย่าง ที่เรายังใช้อยู่ทุกวันนี้ถือกำเนิด

แนวคิดการออกแบบ — ทำไมมันถูกสร้างมาแบบนี้

ping กับ traceroute ชนะเพราะไม่ขอให้ใครทำอะไรใหม่ DNS เป็นเรื่องตรงข้าม มันคือระบบที่ออกแบบขึ้นใหม่ทั้งหมดโดยตั้งใจ และนั่นทำให้บทเรียนของมันคนละบท

1. ไม่มีใครถือข้อมูลทั้งหมด

แทนที่จะมีไฟล์กลาง DNS แบ่งชื่อเป็นชั้น ๆ แล้วมอบอำนาจดูแลลงไปทีละชั้น root รู้แค่ว่าใครดูแล .com ส่วน .com รู้แค่ว่าใครดูแล netkubelab.com และคนที่ดูแล netkubelab.com เท่านั้นที่รู้คำตอบจริง

ผลที่ตามมาสำคัญกว่าที่ดู — การแก้ชื่อในโดเมนของคุณไม่ต้องขออนุญาตใคร และไม่ต้องแจ้งใคร องค์กรดูแลชื่อของตัวเองได้เต็มที่ ซึ่งเป็นข้อที่ HOSTS.TXT ทำไม่ได้เลย

2. แคชคือสิ่งที่ทำให้มันขยายได้ ไม่ใช่ของแถม

ถ้าทุกคำถามต้องเดินจาก root ทุกครั้ง เซิร์ฟเวอร์ root จะรับไม่ไหวตั้งแต่ปีแรก

DNS จึงให้ทุกคำตอบพกอายุติดตัวมาด้วย ใครที่ได้คำตอบไปเก็บไว้ใช้ซ้ำได้ จนกว่าจะหมดอายุ คำถามส่วนใหญ่บนโลกจึงจบที่แคชใกล้ตัว ไม่เคยไปถึง root เลย

แคชไม่ใช่การเพิ่มประสิทธิภาพที่ใส่ทีหลัง แต่เป็นสิ่งที่ทำให้ระบบนี้เป็นไปได้ ตั้งแต่แรก และราคาที่จ่ายคือคำตอบที่ได้อาจไม่ใช่ของล่าสุด ซึ่งเป็นการแลก ที่ผู้ออกแบบรู้ตัวและยอมรับ

3. ให้เจ้าของข้อมูลเป็นคนกำหนดว่ายอมให้เก่าได้แค่ไหน

TTL คือกลไกที่ทำให้การแลกข้างบนควบคุมได้ เจ้าของระเบียนเป็นคนตั้งเอง ว่าคำตอบนี้เก็บไว้ได้กี่วินาที

  • ตั้งสูง เช่นหนึ่งวัน — ภาระของระบบต่ำ แต่แก้อะไรแล้วกว่าจะมีผลใช้เวลานาน
  • ตั้งต่ำ เช่นห้านาที — แก้แล้วมีผลเร็ว แต่คำถามวิ่งไปถึงเซิร์ฟเวอร์จริงบ่อยขึ้น

ไม่มีค่าที่ถูกสำหรับทุกกรณี มันคือปุ่มปรับที่เจ้าของข้อมูลต้องเลือกเอง ตามว่าอะไรสำคัญกว่ากันในตอนนั้น

4. คำตอบว่า "ไม่มี" ก็ต้องแคชด้วย

ข้อที่คนมองข้าม ถ้าแคชเฉพาะคำตอบที่มีอยู่จริง ชื่อที่พิมพ์ผิดจะทำให้เกิด คำถามวิ่งไปถึงเซิร์ฟเวอร์จริงทุกครั้งไม่รู้จบ

DNS จึงกำหนดให้แคชคำตอบว่า "ไม่มี" ได้ด้วย โดยอายุของมันมาจากค่าสุดท้าย ในระเบียน SOA ของโซนนั้น ของ netkubelab.com คือ 1800 วินาที

netkubelab.com.  1800  IN  SOA  kyle.ns.cloudflare.com.
        dns.cloudflare.com. 2413456799 10000 2400 604800 1800
                                                        ^^^^
                                  อายุของคำตอบว่า "ไม่มี"

นี่คือเหตุผลที่บางครั้งสร้างชื่อใหม่แล้วยังใช้ไม่ได้ทันที ทั้งที่เพิ่งสร้าง — มีคนเคยถามชื่อนั้นก่อนที่คุณจะสร้าง และคำตอบว่า "ไม่มี" ยังไม่หมดอายุ

มันทำงานอย่างไร

resolver เดินถามทีละชั้น จาก root ไป .com ไปยังเซิร์ฟเวอร์ที่ดูแลโดเมนนั้น แต่ละชั้นไม่รู้คำตอบสุดท้าย รู้แค่ว่าต้องไปถามใครต่อ

ภาพนี้ไม่ได้วาดขึ้นลอย ๆ มันคือผลจริงของการรัน dig +trace netkubelab.com จากเครื่องที่เขียนบทความนี้

;; Received 239 bytes from 1.1.1.1#53(1.1.1.1)
com.  172800  IN  NS  a.gtld-servers.net.   (และอีก 12 ชื่อ)
;; Received 839 bytes from 202.12.27.33#53(m.root-servers.net)
netkubelab.com.  172800  IN  NS  kyle.ns.cloudflare.com.
netkubelab.com.  172800  IN  NS  opal.ns.cloudflare.com.
;; Received 359 bytes from 192.48.79.30#53(j.gtld-servers.net)
netkubelab.com.  300  IN  A  104.21.35.137
;; Received 75 bytes from 2606:4700:58::a29f:2c6f#53(kyle.ns...)

อ่านจากบนลงล่างคือ ถาม root ตัวหนึ่งได้รายชื่อเซิร์ฟเวอร์ของ .com กลับมา ถาม .com ตัวหนึ่งได้รายชื่อเซิร์ฟเวอร์ของโดเมนนี้ แล้วค่อยถามตัวจริง จึงได้เลข IP

ไม่มีชั้นไหนรู้คำตอบสุดท้าย ทุกชั้นรู้แค่ว่าต้องไปถามใครต่อ

ใครเป็นคนเดิน

เครื่องคุณถามคำถามเดียวแล้วรอคำตอบสุดท้าย ส่วน resolver เป็นคนเดินถามทีละชั้นเอง

เครื่องของคุณไม่ได้เดินเอง มันส่งคำถามเดียวไปให้ resolver แล้วรอคำตอบ สุดท้าย นี่คือสิ่งที่ธง rd (recursion desired) ในคำถามหมายถึง และธง ra (recursion available) ในคำตอบแปลว่าอีกฝั่งยอมเดินให้

คนที่เหนื่อยคือ resolver ซึ่งเดินถามทีละชั้นด้วยตัวเอง แล้วเก็บทุกชั้น ที่ผ่านไว้ในแคชของมัน ครั้งต่อไปที่มีคนถามชื่ออื่นใน .com มันไม่ต้องไปถาม root ใหม่แล้ว เพราะข้อมูลของ .com ยังไม่หมดอายุ

ในข้อความมีอะไรอยู่บ้าง

หัวข้อความบอกจำนวนระเบียนในสี่ส่วน คือ QUESTION ANSWER AUTHORITY และ ADDITIONAL พร้อมธงที่บอกลักษณะของคำตอบ

ข้อความ DNS ทั้งคำถามและคำตอบใช้โครงเดียวกัน คือส่วนหัวแล้วตามด้วยสี่ส่วน และส่วนหัวจะบอกว่าแต่ละส่วนมีกี่ระเบียน

ธงที่ควรรู้จัก

  qr   นี่คือคำตอบ ไม่ใช่คำถาม
  rd   ผู้ถามขอให้เดินให้ (recursion desired)
  ra   ผู้ตอบยอมเดินให้ (recursion available)
  aa   คำตอบนี้มาจากเซิร์ฟเวอร์ที่มีสิทธิ์ตอบโดยตรง ไม่ใช่จากแคช
  ad   ข้อมูลผ่านการตรวจสอบ DNSSEC แล้ว
  tc   คำตอบใหญ่เกิน ถูกตัด ให้ถามใหม่ด้วย TCP

ธง aa มีประโยชน์มากตอนไล่ปัญหา เพราะมันแยกได้ทันทีว่าคำตอบที่เห็นมาจาก ตัวจริงหรือมาจากแคชของใครสักคนระหว่างทาง

ส่วน tc เป็นที่มาของความเข้าใจผิดที่ว่า DNS ใช้แค่ UDP — จริง ๆ แล้ว มันใช้ทั้ง UDP และ TCP บนพอร์ต 53 คำตอบที่ใหญ่เกินจะถูกตัดแล้วบอกให้ถามใหม่ ผ่าน TCP ทุกวันนี้ EDNS ช่วยขยายเพดานของ UDP ให้ใหญ่ขึ้น ค่าที่เห็นบ่อยคือ 1232 ไบต์

ไฟร์วอลล์ที่เปิดแค่ UDP 53 แต่ปิด TCP 53 จึงทำให้เกิดอาการแปลก ๆ คือชื่อส่วนใหญ่ใช้ได้ แต่บางชื่อที่มีระเบียนเยอะกลับใช้ไม่ได้

TTL — และคำเดียวกันที่หมายถึงคนละอย่าง

TTL ใน IP นับจำนวนเราเตอร์ที่ผ่านได้อีก ส่วน TTL ใน DNS นับวินาทีที่เก็บคำตอบไว้ได้อีก คนละหน่วยและคนละงาน

ถ้าอ่านบทความ ping กับ traceroute มาแล้วจะเคยเจอคำว่า TTL ในความหมาย "ผ่านเราเตอร์ได้อีกกี่ตัว" — TTL ใน DNS ไม่เกี่ยวอะไรกับอันนั้นเลย มันแค่ชื่อซ้ำกัน

  • TTL ใน IP นับ จำนวนเราเตอร์ ลดลงหนึ่งทุกครั้งที่ถูกส่งต่อ
  • TTL ใน DNS นับ วินาที ลดลงตามเวลาที่ผ่านไป

เจอคำนี้ที่ไหนให้ดูก่อนเสมอว่ากำลังพูดถึงหัว IP หรือระเบียน DNS

แคชคือเหตุผลที่คนสองคนเห็นไม่เหมือนกัน

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

ลองรัน dig ชื่อเดิมสองครั้งห่างกันสักพัก จะเห็นตัวเลข TTL ลดลง

$ dig +noall +answer google.com A
google.com.		280	IN	A	142.250.204.206

   ... รอสักครู่ ...

$ dig +noall +answer google.com A
google.com.		253	IN	A	142.250.204.206

280 แล้ว 253 ไม่ใช่ความผิดพลาด นั่นคือเวลาที่เหลือของคำตอบที่อยู่ในแคช ของ resolver ไม่ใช่ค่าที่เจ้าของโดเมนตั้งไว้

ข้อนี้มีผลจริงในการทำงานสองอย่าง

หนึ่ง อยากรู้ค่า TTL จริงที่เจ้าของตั้งไว้ ต้องถาม authoritative ตรง ๆ ไม่ใช่ถามผ่าน resolver

สอง ก่อนย้ายเซิร์ฟเวอร์ ให้ลด TTL ลงล่วงหน้าอย่างน้อยหนึ่งรอบของ TTL เดิม ถ้าเดิมตั้งไว้ 86400 ต้องลดล่วงหน้าอย่างน้อยหนึ่งวันเต็ม แล้วค่อยแก้ระเบียน ไม่งั้นจะมีคนเห็นของเก่าต่อไปอีกเป็นวัน โดยที่คุณทำอะไรไม่ได้เลย

และไม่มีทางบังคับให้แคชของคนอื่นทิ้งคำตอบเก่า ล้างแคชของเครื่องตัวเองได้ ล้างของ resolver ที่ตัวเองดูแลได้ แต่ resolver ของผู้ให้บริการรายอื่น กับของผู้ใช้ปลายทางทั่วโลก อยู่นอกเหนือการควบคุมทั้งหมด

NOERROR ที่ไม่ได้แปลว่ามีคำตอบ

ตรงนี้เป็นจุดที่คนอ่านผิดกันมาก มีสามสถานะที่ต้องแยกให้ออก

  NOERROR + ANSWER มากกว่า 0     มีคำตอบ ใช้ได้เลย
  NOERROR + ANSWER 0 + มี SOA    ชื่อนี้มีอยู่ แต่ไม่มีระเบียนชนิดที่ถาม
  NXDOMAIN                       ไม่มีชื่อนี้อยู่จริงเลย

กรณีกลางเรียกว่า NODATA เช่นถาม MX ของโดเมนที่ไม่ได้ตั้งค่าอีเมลไว้ ชื่อมีอยู่ ระเบียนชนิดนั้นไม่มี

และมีเรื่องที่ต้องระวังเพิ่ม — ผู้ให้บริการบางรายไม่ตอบ NXDOMAIN ลองถามชื่อที่ไม่มีอยู่จริงใต้โดเมนนี้ดู

$ dig no-such-name-xyz789.netkubelab.com A
;; ->>HEADER<<- opcode: QUERY, status: NOERROR
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
netkubelab.com.  1800  IN  SOA  kyle.ns.cloudflare.com. ...

ได้ NOERROR ไม่ใช่ NXDOMAIN ทั้งที่ชื่อนั้นไม่มีอยู่จริง

บทเรียนคืออย่าเขียนสคริปต์ที่ตัดสินจาก NXDOMAIN อย่างเดียว เพราะพฤติกรรม ตรงนี้ต่างกันตามผู้ให้บริการ ให้ดูที่ ANSWER ว่าเป็นศูนย์หรือไม่จะแม่นกว่า

เมื่อ DNS โกหก

1. คำตอบที่ได้อาจเก่ากว่าความจริงเสมอ

ข้อนี้ไม่ใช่บั๊ก แต่เป็นการออกแบบ ทุกคำตอบที่ไม่ได้มาจาก authoritative โดยตรงคือคำตอบที่เคยจริง ณ ตอนที่มันถูกเก็บ

เวลาแก้ระเบียนแล้วมีคนบอกว่าเห็นของเก่า อย่าเพิ่งคิดว่าแก้ไม่สำเร็จ ให้ถาม authoritative ตรง ๆ ก่อน ถ้าตรงนั้นถูกแล้วแปลว่างานของคุณเสร็จแล้ว ที่เหลือคือรอ TTL

2. ชื่อเดียวกันอาจได้คำตอบไม่เท่ากันโดยตั้งใจ

มีอย่างน้อยสามกลไกที่ทำให้เกิดเรื่องนี้

  • anycast — เลขเดียวประกาศจากหลายที่ทั่วโลก เช่นเลขที่ netkubelab.com ชี้ไป คนละคนจึงคุยกับคนละเครื่อง
  • GeoDNS — เซิร์ฟเวอร์ตอบคนละคำตอบตามตำแหน่งของผู้ถาม
  • split-horizon — คนในองค์กรถามได้เลขภายใน คนนอกถามได้เลขภายนอก

ทั้งสามอย่างทำให้ประโยคว่า "ผมถามแล้วได้เลขนี้" ไม่ใช่หลักฐานว่าคนอื่น จะได้เลขเดียวกัน ตอนไล่ปัญหาต้องถามจากที่เดียวกับที่ผู้ใช้อยู่

3. ชื่อที่คุณพิมพ์อาจไม่ใช่ชื่อที่ถูกถามจริง

ถ้าชื่อที่พิมพ์ไม่มีจุดปิดท้าย ระบบอาจเติม search domain ต่อท้ายให้ก่อน พิมพ์ intranet แล้วเครื่องอาจไปถาม intranet.corp.example.com จริง ๆ

นี่คือที่มาของอาการที่เครื่องหนึ่งเปิดได้อีกเครื่องเปิดไม่ได้ ทั้งที่พิมพ์ เหมือนกันเป๊ะ เพราะสองเครื่องนั้นมี search domain ไม่เหมือนกัน

4. เครื่องอาจไม่ได้ถาม resolver ที่คุณคิด

บนแมค ไฟล์ /etc/resolv.conf ไม่ถูกใช้ ตัวไฟล์เขียนบอกไว้เองว่า ไม่ได้ถูกอ่านสำหรับการแปลงชื่อ ค่าจริงต้องดูด้วย

$ scutil --dns | grep nameserver
  nameserver[0] : 1.1.1.1
  nameserver[1] : 8.8.8.8

บนลินุกซ์สมัยใหม่ที่ใช้ systemd-resolved ไฟล์นั้นมักชี้ไปที่ 127.0.0.53 ซึ่งเป็นตัวกลางในเครื่องอีกที ต้องใช้ resolvectl status ดูของจริง

และ dig ไม่ได้เดินเส้นทางเดียวกับแอปพลิเคชัน dig คุยกับเซิร์ฟเวอร์ ที่ระบุตรง ๆ ส่วนแอปพลิเคชันเรียกผ่านไลบรารีของระบบซึ่งอาจมี mDNS, ไฟล์ /etc/hosts, หรือแคชของระบบคั่นอยู่ dig ได้ผลดีไม่ได้แปลว่า แอปพลิเคชันจะได้ผลเดียวกัน

5. DNS ที่เข้ารหัสทำให้การไล่ปัญหาแบบเดิมตาบอด

DNS ธรรมดาบนพอร์ต 53 ใครอยู่บนเส้นทางก็อ่านได้ ส่วน DoT และ DoH ถูกเข้ารหัสจึงมองไม่เห็นว่าถามชื่ออะไร

สมัยก่อนสงสัยเรื่อง DNS ก็เปิด tcpdump ดูพอร์ต 53 แล้วเห็นทุกอย่าง

ทุกวันนี้เบราว์เซอร์จำนวนมากใช้ DoH ซึ่งส่ง DNS ไปในทราฟฟิก HTTPS พอร์ต 443 และระบบปฏิบัติการหลายตัวรองรับ DoT บนพอร์ต 853 ทั้งสองแบบเข้ารหัส

ผลคือ เครื่องอาจแปลงชื่อผ่านเส้นทางที่ไม่ใช่ resolver ขององค์กรเลย และคุณจะมองไม่เห็นจาก tcpdump ว่ามันถามอะไร ถ้าไล่ปัญหาแล้วตัวเลขไม่สมเหตุผล ให้ตรวจก่อนว่าเบราว์เซอร์เปิด DoH อยู่หรือเปล่า

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

กรณีที่ 1 — แยกให้ออกว่าเป็น DNS หรือไม่ใช่ ใน 10 วินาที

ผู้ใช้แจ้งว่าเปิดเว็บหนึ่งไม่ได้

$ ping app.example.com
ping: cannot resolve app.example.com: Unknown host

$ ping 203.0.113.20
64 bytes from 203.0.113.20: icmp_seq=0 ttl=54 time=12.1 ms

อ่านอย่างไร เลข IP ถึงได้ ชื่อแปลงไม่ได้ ปัญหาอยู่ที่การแปลงชื่อล้วน ๆ ไม่ต้องไปยุ่งกับเส้นทางหรือไฟร์วอลล์เลย

นี่คือการทดสอบแรกที่ควรทำเสมอ และเป็นเหตุผลที่บทความนี้ควรอ่านคู่กับ ping

สิ่งที่ยังไม่ได้พิสูจน์ ยังไม่รู้ว่าพังตรงไหนของ DNS — resolver ไม่ตอบ ระเบียนถูกลบ หรือถูกกรอง ต้องไล่ต่อด้วย dig

กรณีที่ 2 — แก้ระเบียนแล้วบางคนเห็นบางคนไม่เห็น

$ dig +short @kyle.ns.cloudflare.com netkubelab.com A
104.21.35.137

$ dig +short @8.8.8.8 netkubelab.com A
203.0.113.99

อ่านอย่างไร ถาม authoritative ตรง ๆ ได้เลขใหม่ ถามผ่าน resolver สาธารณะ ยังได้เลขเก่า แปลว่าการแก้สำเร็จแล้ว สิ่งที่เหลือคือแคชที่ยังไม่หมดอายุ

ดูว่าต้องรออีกนานแค่ไหนด้วยการอ่าน TTL จากฝั่ง resolver

$ dig @8.8.8.8 +noall +answer netkubelab.com A
netkubelab.com.		214	IN	A	203.0.113.99

เหลืออีก 214 วินาที ไม่มีอะไรต้องทำนอกจากรอ

สิ่งที่ยังไม่ได้พิสูจน์ ยังไม่ได้พิสูจน์ว่าทุก resolver บนโลกจะหมดอายุ พร้อมกัน แต่ละตัวเริ่มนับคนละเวลา และบางตัวไม่เคารพ TTL อย่างเคร่งครัด

กรณีที่ 3 — ชื่อที่ยังใช้ไม่ได้ทั้งที่เพิ่งสร้าง

$ dig +noall +answer new.netkubelab.com A
(ว่าง)

$ dig +short @kyle.ns.cloudflare.com new.netkubelab.com A
104.21.35.137

อ่านอย่างไร ตัวจริงมีระเบียนแล้ว แต่ resolver ยังตอบว่าไม่มี นี่คือ negative caching ทำงานอยู่ — มีคนเคยถามชื่อนี้ก่อนที่มันจะถูกสร้าง และคำตอบว่า "ไม่มี" ยังไม่หมดอายุตามค่าสุดท้ายในระเบียน SOA

บทเรียนสำหรับงานจริง — อย่าทดสอบชื่อก่อนสร้างมัน การรีบไปลองก่อน ทำให้ต้องรอนานกว่าเดิม

สิ่งที่ยังไม่ได้พิสูจน์ ยังไม่รู้ว่าต้องรอนานแค่ไหนสำหรับ resolver แต่ละตัว เพราะแต่ละตัวเริ่มนับคนละเวลากัน

กรณีที่ 4 — คำตอบมาจากตัวจริงหรือจากแคช

$ dig @kyle.ns.cloudflare.com netkubelab.com A | grep flags
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, ...

$ dig @1.1.1.1 netkubelab.com A | grep flags
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, ...

อ่านอย่างไร ชุดแรกมีธง aa แปลว่าคำตอบมาจากเซิร์ฟเวอร์ที่มีสิทธิ์ ตอบโดยตรง เป็นข้อมูลสด ชุดที่สองไม่มี aa แต่มี ra แปลว่ามาจาก resolver ที่เดินให้ และอาจมาจากแคช

ธงตัวเดียวนี้ตัดคำถามว่า "ข้อมูลที่เห็นสดหรือเปล่า" ได้ทันที

สิ่งที่ยังไม่ได้พิสูจน์ aa บอกว่ามาจากผู้มีสิทธิ์ตอบ ไม่ได้บอกว่า ข้อมูลนั้นถูกต้องตามที่เจ้าของตั้งใจ ถ้าตั้งค่าผิดตั้งแต่ต้น aa ก็ยืนยันความผิดนั้นให้อย่างมั่นใจ

กรณีที่ 5 — NS ที่พ่อกับลูกบอกไม่ตรงกัน

$ dig +short netkubelab.com NS
kyle.ns.cloudflare.com.
opal.ns.cloudflare.com.

$ dig +noall +answer netkubelab.com NS
netkubelab.com.		86400	IN	NS	kyle.ns.cloudflare.com.

จาก dig +trace ชั้น .com บอกว่า
netkubelab.com.	       172800	IN	NS	kyle.ns.cloudflare.com.

อ่านอย่างไร รายชื่อเซิร์ฟเวอร์ตรงกัน แต่ TTL ไม่ตรง — ฝั่ง .com บอก 172800 ส่วนตัวโซนเองบอก 86400

อันนี้ปกติ ไม่ใช่ปัญหา เพราะเป็นระเบียนคนละชุดที่คนละฝ่ายดูแล ฝั่งผู้จดทะเบียนตั้งค่าหนึ่ง เจ้าของโซนตั้งอีกค่าหนึ่ง

แต่ถ้ารายชื่อไม่ตรงกันเมื่อไหร่ นั่นคือปัญหาจริง และเป็นสาเหตุของอาการ ที่หายากมาก คือบางคำถามได้คำตอบ บางคำถามไม่ได้ ขึ้นกับว่า resolver สุ่มไปถามเซิร์ฟเวอร์ตัวไหน

สิ่งที่ยังไม่ได้พิสูจน์ ตรงกันตอนนี้ไม่ได้แปลว่าตรงกันตลอด ควรตรวจซ้ำหลังทุกครั้งที่เปลี่ยนผู้ให้บริการ DNS

กรณีที่ 6 — เมื่อ dig ได้ผลแต่แอปพลิเคชันไม่ได้

$ dig +short internal.corp.example
10.20.30.40

$ curl https://internal.corp.example/
curl: (6) Could not resolve host: internal.corp.example

อ่านอย่างไร dig ยิงตรงไปที่ resolver ส่วน curl เรียกผ่านไลบรารี ของระบบซึ่งเดินคนละเส้นทาง อาจไปเจอ /etc/hosts, แคชของระบบ, หรือ resolver คนละตัวก่อน

ตรวจต่อด้วยสามอย่าง — ดู /etc/hosts, ดู resolver จริงด้วย scutil --dns หรือ resolvectl status, และดูว่ามี search domain มาต่อท้ายหรือเปล่า

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

เมื่อ dig ไม่พออีกต่อไป

  • dig +trace — เดินตามการมอบอำนาจทีละชั้น ใช้เมื่อสงสัยว่าปัญหาอยู่ เหนือโซนของเราขึ้นไป
  • dig @เซิร์ฟเวอร์ — ถามตัวจริงโดยไม่ผ่านแคช เป็นคำสั่งที่ใช้บ่อยที่สุด ในการไล่ปัญหา
  • resolvectl status หรือ scutil --dns — ดูว่าเครื่องใช้ resolver อะไรจริง
  • dnsviz.net — ตรวจ DNSSEC เป็นภาพ เมื่อสงสัยว่าลายเซ็นมีปัญหา
  • tcpdump port 53 — ดูของจริงบนสาย แต่ระวังว่า DoH กับ DoT จะไม่ปรากฏตรงนั้น

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

ราคาที่จ่ายคือทุกครั้งที่มีอะไรพังแบบอธิบายไม่ได้ ต้องเดาไว้ก่อนเสมอว่า อาจมีคำตอบเก่าค้างอยู่ที่ไหนสักแห่ง — ซึ่งก็คือที่มาของมุกนั้นนั่นเอง

อ้างอิง

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

คู่มือ

  • man dig และ man resolver บนเครื่องที่คุณนั่งอยู่
  • resolvectl status บนลินุกซ์ที่ใช้ systemd และ scutil --dns บนแมค ซึ่งเป็นที่เดียวที่บอกได้จริงว่าเครื่องใช้ resolver อะไร

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

← กลับไปหน้าความรู้พื้นฐาน