CASE STUDY • DNSSEC • ROOT KSK ROLLOVER

Resolver รุ่นเก่าไม่รู้จัก Root KSK-2024
จากการตรวจพบ จนถึงการแก้ไขอย่างปลอดภัย

บันทึกกรณีจริงของ recursive resolver ที่ใช้ BIND สาย 9.16 หลัง Root KSK rollover วันที่ 11 ตุลาคม 2026 (พ.ศ. 2569)

ข้อมูลระบบจริงถูกปิดบังทั้งหมด: ไม่มีชื่อเครื่อง, IP, ชื่อ view/โดเมนภายใน, บัญชีผู้ใช้ หรือ path ภายใน

1. สรุปสั้น

2. ภูมิหลัง: Root KSK rollover

IANA กำหนดให้ KSK-2024 (38696) เริ่มลงนาม DNSKEY RRset ของ root แทน KSK-2017 (20326) ในวันที่ 11 ตุลาคม 2026 โดย key ใหม่ถูกเผยแพร่ล่วงหน้าตั้งแต่ 11 มกราคม 2025 ผู้ดูแล validating resolver ต้องมั่นใจว่า resolver เชื่อถือ key ใหม่ ไม่ใช่เพียงเห็น key ในคำตอบ

สามอย่างที่มักถูกสับสน
สิ่งที่ต้องแยกความหมายตรวจจากอะไร
Trust anchorkey ที่ resolver เชื่อถือเป็นจุดเริ่มต้นการตรวจrndc secroots - / managed-keys status
Root DNSKEY ใน cacheข้อมูลที่เคยรับมา ใช้ต่อได้จน TTL หมด อาจยังมีลายเซ็นจาก key เดิมRRSIG signer ในคำตอบ + TTL คงเหลือ
การตรวจจริงของ clientผลที่ client เห็นผ่าน resolverAD flag, ผลของโดเมนที่ลายเซ็นผิด, delv

3. วัตถุประสงค์และเป้าหมายของการแก้ไข

วัตถุประสงค์

เกณฑ์สำเร็จ

สิ่งที่ไม่ใช่เป้าหมาย

4. ลำดับเหตุการณ์ (ใช้ลำดับ ไม่ระบุเวลาจริง)

1. ก่อนตรวจresolver ปิด validation ตามนโยบายเดิม
2. ตรวจ clientresolve ได้ แต่ไม่มี AD และโดเมนลายเซ็นผิดไม่ถูกปฏิเสธ
3. เครื่องตรวจติดขัดdelv ใช้ไม่ได้
4. เปิด validationทุก view SERVFAIL
5. ถอยกลับปิด validation เพื่อกู้บริการ
6. วิเคราะห์พบ bootstrap key ไม่มี 38696
7. แก้และตรวจวางแผน รีวิว อนุมัติ สำรอง activate
#สิ่งที่พบการตีความที่ถูกต้อง
1Resolver ตอบ root DNSKEY ที่ลงนามด้วย 38696 แต่ไม่มี AD flag และไม่มี trust anchor ใน runtimeเป็นการปิด validation ตามนโยบาย ไม่ใช่ความเสียหายจาก rollover แต่ก็ไม่ได้รับการป้องกันจาก DNSSEC
2โดเมนทดสอบที่ลายเซ็นผิดยังตอบ NOERRORสอดคล้องกับ validation ถูกปิดหรือถูกข้าม
3Sentinel ของ RFC 8509 ทั้งคู่ตอบปกติใช้ตัดสินไม่ได้ — ต้องใช้หลักฐาน runtime
4delv บนเครื่องตรวจแจ้ง no crypto supportเป็นข้อจำกัดของเครื่องตรวจ ไม่ใช่ความผิดของ resolver (ดูหัวข้อ 5–6)
5หลังเปิด dnssec-validation auto: root DNSKEY และโดเมนปกติ SERVFAIL, +cd ตอบได้, log แจ้ง DNSKEY set for zone '.' could not be verified with current keysปัญหาอยู่ที่การตรวจลายเซ็นของ root ไม่ใช่โดเมนปลายทาง
6ทั้ง view มี trust anchor แค่ 20326 สถานะ initializing และ no trustBIND bootstrap ด้วย key เก่าอย่างเดียว
7Resolver รุ่นใหม่กว่า (BIND 9.18 ล่าสุด) ในสภาพแวดล้อมเดียวกันเชื่อถือ 38696 ทันทีเมื่อเปิด validationเป็นตัวอ้างอิงว่า bootstrap file ที่ถูกต้องควรเป็นอย่างไร

5. ข้อจำกัด

5.1 ข้อจำกัดของเครื่องที่ใช้ตรวจ

5.2 ข้อจำกัดของ resolver เป้าหมาย

5.3 ข้อจำกัดของการทดสอบ

6. Workaround ในการตรวจสอบ

6.1 เครื่องมือ delv: ตรวจ DNSSEC บนฝั่ง client

delv (DNS lookup and validation utility) เป็นเครื่องมือของ ISC BIND สำหรับดึงคำตอบ DNS และตรวจลายเซ็นบนเครื่องที่รันคำสั่ง โดยขอ DNSKEY และ DS เพื่อสร้างห่วงโซ่จาก root ถึงโดเมน ไม่เพียงเชื่อ AD flag ที่ resolver ส่งมา

เครื่องมือทำหน้าที่ข้อจำกัด
dig +dnssecขอ DNSSEC records และแสดงคำตอบ รวมถึง RRSIG, AD และ CDไม่ตรวจลายเซ็นเอง
delvตรวจลายเซ็นและ trust chain ด้วย trust anchor ฝั่ง clientต้องมี crypto support, anchor ที่ถูกต้อง และ resolver ที่ส่งข้อมูลครบ
rndcตรวจ runtime trust anchors และ managed-key state ของ BIND serverต้องมีสิทธิ์บน server; ผลไม่แทนการทดสอบเส้นทาง client

ติดตั้งและตรวจเครื่องมือ

# Ubuntu/Debian: ตัว delv อยู่ในแพ็กเกจ bind9-dnsutils
sudo apt-get install bind9-dnsutils
command -v delv
delv -v

# macOS: ติดตั้ง BIND tools จาก Homebrew ไม่ต้องเปิดบริการ DNS
brew install bind
"$(brew --prefix bind)/bin/delv" -v

# เลือก BIND tools สำหรับ shell ปัจจุบัน โดยไม่แทนที่ binary ของระบบ
export PATH="$(brew --prefix bind)/bin:$PATH"
command -v delv
delv -v

ตรวจแพ็กเกจที่ผู้ผลิตรองรับสำหรับ OS ของคุณก่อนติดตั้ง; การติดตั้งอาจอัปเดต dependencies หากจะบันทึก PATH ลงไฟล์ shell ให้สำรองและตรวจ checksum ก่อนแก้ ไม่ต้องเปิดบริการ named เพียงเพื่อใช้เครื่องมือ client

คำสั่งใช้งาน

# แทน RESOLVER_IP ด้วย resolver จริง และรันจากเครือข่ายที่ ACL อนุญาต
delv @RESOLVER_IP iana.org. A
delv @RESOLVER_IP +rtrace iana.org. A     # แสดง query ที่ใช้ประกอบการตรวจ
delv @RESOLVER_IP +vtrace iana.org. A     # แสดงขั้นตอน validation
delv @RESOLVER_IP +tcp iana.org. A        # ทดสอบ transport TCP
delv @RESOLVER_IP . DNSKEY                # ตรวจ root DNSKEY
delv @RESOLVER_IP dnssec-failed.org. A    # ข้อมูลที่ลายเซ็นผิดควรถูกปฏิเสธ

ถ้าไม่ระบุ @RESOLVER_IP เครื่องมือจะเลือก resolver จาก configuration ของเครื่องตรวจ จึงต้องระบุ endpoint ให้ชัดเจนเมื่อตรวจระบบเป้าหมาย อย่านำ options ของ dig เช่น +time, +tries หรือ +cd มาใช้กับ delv โดยไม่ตรวจคู่มือรุ่นนั้น

อ่านผลและแยกสาเหตุ

ข้อความความหมายตรวจต่อ
fully validatedClient ตรวจลายเซ็นของคำตอบและ trust chain ผ่านตรวจ signer ของ root และ runtime ของ resolver เพิ่ม เพื่อแยก cache เก่าจากการใช้ key ใหม่
unsigned answerคำตอบไม่ได้อยู่ภายใต้การรับรองด้วย DNSSECตรวจ delegation/DS และนโยบาย ไม่ถือว่าเป็นข้อมูลปลอมหรือ failure อัตโนมัติ
no crypto support / No trusted keys were loadedเครื่องตรวจเริ่ม validation ไม่ได้ตรวจ binary/version และ trust-anchor source ไม่ตีความเป็น outage ของ DNS เป้าหมาย
got insecure response; parent indicates it should be secureClient ไม่ได้รับหลักฐาน DNSSEC ที่จำเป็นสำหรับข้อมูลซึ่งควรตรวจได้หากพบที่ root DNSKEY ให้ตรวจว่า RRSIG DNSKEY ถูกส่งมาหรือไม่ ด้วย dig +tcp +dnssec
broken trust chainClient ตรวจห่วงโซ่ต่อไม่ได้ดู trace ว่าขาดหรือผิดที่ root, DS หรือ DNSKEY; เทียบ query ปกติกับ dig +cd และ resolver ที่ตรวจผ่าน
resolution failed: failureไม่ได้คำตอบที่นำมาตรวจสำเร็จแยก SERVFAIL, ACL, timeout และ known-bogus test ก่อนสรุป root-anchor failure
ขอบเขตของหลักฐาน: delv ใช้ validator library ของ BIND เช่นเดียวกับ named จึงเป็นการตรวจจาก client แยกเครื่อง/แยก trust anchor ไม่ใช่ implementation ต่างผู้ผลิต แม้ resolver ปิด validation ก็อาจส่งข้อมูลครบจน delv ตรวจผ่านได้ จึงต้องใช้ runtime และ valid/bogus controls ประกอบเสมอ

Trust anchor ของ delv แยกจาก managed-key database ของ server และไม่ได้ทำ RFC 5011 maintenance เอง หากต้องใช้ -a ANCHOR_FILE ต้องรับไฟล์จากแหล่งที่เชื่อถือและตรวจรูปแบบให้ตรงรุ่น ห้ามตั้ง anchor จาก DNSKEY ที่เพียงดึงได้โดยยังไม่พิสูจน์ที่มา

Reading delv resultsFlowchart for deciding whether a delv result points at the client tool, the resolver path, an upstream, or a healthy chain.NONONOYESYESYESRun delv@RESOLVER_IPvalidationstarts?answerreturned?fullyvalidated?Confirm on serverrndc secroots: 38696Fix the clientinstall BIND toolsIsolate the causeACL, timeout, dig +cdCompare upstreamsdig +tcp +dnssecLEGENDSTARTACTIONDECISIONTARGET OUTCOME
รูปที่ 2 — ลำดับอ่านผล delv เพื่อแยกปัญหาของเครื่องตรวจ, เส้นทาง resolver และ upstream ก่อนสรุป

6.2 Workaround และขอบเขตการยืนยัน

ข้อจำกัดวิธีเลี่ยงยืนยันได้ยังยืนยันไม่ได้
delv ของ macOS ไม่มี cryptoติดตั้ง BIND tools จาก Homebrew (ไม่เปิดบริการ named) และเรียกด้วย path เต็ม แล้วค่อยปรับ PATH ภายหลังพร้อมสำรองไฟล์ shellตรวจลายเซ็นตั้งแต่ root ถึงโดเมนเอง (fully validated)ไม่รับรองว่า resolver เองตรวจผ่าน
AD flag อาจเชื่อไม่ได้อย่างเดียวใช้โดเมนที่ลายเซ็นผิดเป็น control เทียบกับ +cd และเทียบกับ resolver สาธารณะที่ validateแยก validation failure ออกจาก outageไม่ระบุสาเหตุภายในเอง
Sentinel ไม่ชี้ชัดใช้ anchor ที่ใช้งานจริงจากคำสั่งฝั่งเซิร์ฟเวอร์ ควบคู่กับ logสถานะ trusted / initializingการรับ key ใหม่หลัง cache หมด
Resolver ส่ง root DNSKEY ไม่มี RRSIGใช้ dig +tcp +dnssec เทียบหลาย upstream และอ่าน trace จาก delv +rtraceระบุว่าข้อมูลขาดตรงจุดใดไม่สรุปว่าเกิดจากค่าปิด validation
View ที่ไม่มี client ทดสอบใช้ dig -b <SECONDARY_IP> บนเซิร์ฟเวอร์เพื่อเลือก viewตรวจหลักฐาน runtime ของ view นั้นไม่ถือเป็น client E2E หาก ACL ไม่อนุญาต recursion
ผลตรวจก่อนหน้าอาจผ่านเพราะ cacheอ่าน TTL คงเหลือ และไม่ flush cache เพียงเพื่อให้ผลดีเวลาที่ cache จะหมดอายุโดยประมาณไม่ยืนยัน post-cache-turnover จนกว่าจะตรวจซ้ำ
# ตรวจจาก client (RESOLVER_IP คือ resolver ที่ต้องการทดสอบ)
dig @RESOLVER_IP . DNSKEY +dnssec +tcp
dig @RESOLVER_IP isc.org A +dnssec
dig @RESOLVER_IP dnssec-failed.org A +dnssec        # คาด SERVFAIL ถ้า validation ทำงาน
dig @RESOLVER_IP dnssec-failed.org A +dnssec +cd    # คาด NOERROR (ข้ามการตรวจเพื่อเทียบ)
delv @RESOLVER_IP +rtrace iana.org. A              # ต้องเป็น "fully validated"

# ตรวจบนเซิร์ฟเวอร์ BIND ที่มีสิทธิ์ (ทุก view ที่ให้บริการ)
sudo rndc secroots -          # ต้องมี ./RSASHA256/38696 ; managed
sudo rndc managed-keys status
อ่านข้อความของ delv เสมอ ไม่ใช้ exit code อย่างเดียว เพราะ delv อาจคืน exit 0 แม้รายงาน resolution failed

7. สาเหตุราก

  1. BIND 9.16 อ่าน bootstrap root key จาก /etc/bind/bind.keys เมื่อเปิด dnssec-validation auto
  2. ไม่พบไฟล์ log จึงแจ้ง unable to open ... using built-in keys และ BIND ใช้ key ที่ฝังในโปรแกรมซึ่งมีเฉพาะ 20326
  3. Root zone ลงนาม DNSKEY RRset ด้วย 38696 แล้ว จึงตรวจด้วย key ที่มีอยู่ไม่ผ่าน ระบบจึงถือว่า trust chain พัง
  4. เพราะ managed-key zone ของแต่ละ view ว่างเปล่า BIND จึงไม่เริ่ม RFC 5011 hold-down และอยู่ในสถานะ initializing
Trust-anchor bootstrap on BIND 9.16Flowchart showing how named picks its root trust anchor and why a missing bind.keys file ends in SERVFAIL.YESNOnamed startsdnssec-validation autobind.keysreadable?Load bind.keysinitial-ds 38696 + 20326Validation works38696 managedUse built-in key20326 only (KSK-2017)Root signed by 38696KSK-2024 DNSKEY RRsetSERVFAIL everywhereDNSKEY cannot be verifiedLEGENDSTART / ENDSTEPDECISIONFAILURE
รูปที่ 1 — ทำไมเปิด validation แล้วทุกอย่าง SERVFAIL: ไม่มีไฟล์ bind.keys BIND จึงใช้ key ที่ฝังมา (20326) แต่ root ลงนามด้วย 38696
ข้อสรุปที่ต้องระวัง: การปิด validation เป็น workaround ที่ทำให้บริการกลับมา แต่ไม่ใช่การแก้ เพราะผู้ใช้สูญเสียการป้องกันจาก DNSSEC โดยไม่รู้ตัว

8. ทางเลือกที่พิจารณา

ทางเลือกผลเหตุผล
อัปเดต dns-root-data อย่างเดียวไม่พออัปเดตไฟล์รูปแบบ zone-record ที่ BIND ไม่อ่าน ไม่แตะไฟล์ bind.keys
อัปเกรด BIND ภายใน distribution รุ่นเก่าไม่แก้รุ่นที่มีให้ (9.18.30) ยังไม่มี 38696; ตรวจจากไฟล์ .deb จริงเทียบ SHA-256 กับ index
ติดตั้งแพ็กเกจของ release อื่นหรือ build จาก sourceไม่แนะนำไม่มีเส้นทางรับ security update และเสี่ยง dependency
วาง bind.keys ที่มี initial-ds 38696 แล้วเปิด validationเลือกขอบเขตเล็ก ตรวจสอบที่มาได้ และ rollback ง่าย
อัปเกรด OS หรือย้ายไปเครื่องใหม่โครงการแยกจำเป็นเรื่องอายุซอฟต์แวร์ แต่กระทบกว้าง ต้องมี snapshot และแผนทดสอบ

9. ขั้นตอน change (แบบทั่วไป)

ใช้เป็นแนวทางเท่านั้น ปรับ path และคำสั่งตามผลิตภัณฑ์/เวอร์ชัน ผ่านการอนุมัติและกำหนดช่วงเวลา change ก่อนลงมือ
Resolver change pipelineFlowchart of the staged change: plan, backup, stage, approval gate, activate, verify every view, then observe or roll back.YESNOStudy and planread-only, reviewedBack upSHA-256 verifiedStageedit on disk, no reloadApproval gateexplicit, before activateActivaterndc reconfig38696 inall views?Sync and observemanaged-keys sync, 24 hRoll backrestore config, verifyLEGENDSTEPDECISIONAPPROVAL GATE
รูปที่ 3 — ลำดับ change: วางแผน สำรอง stage ขออนุมัติ activate ตรวจทุก view แล้วสังเกตต่อหรือ rollback

9.1 พิสูจน์ข้อมูล trust anchor ก่อนใช้

  1. ดาวน์โหลด root-anchors.xml, root-anchors.p7s และ icannbundle.pem จาก IANA
  2. ตรวจลายเซ็น: openssl cms -verify -binary -inform DER -in root-anchors.p7s -content root-anchors.xml -CAfile icannbundle.pem -purpose any -out /dev/null
  3. เทียบ DS digest ของ 38696 ใน XML (SHA-256: 683D2D0ACB8C9B712A1948B27F741219298D0A450D612C483AF444A4C0FB2B16) กับ initial-ds ในไฟล์ที่จะวาง
  4. คำนวณ DS จาก root DNSKEY สดด้วย dnssec-dsfromkey -2 เพื่อยืนยันว่าตรงกับ IANA
  5. ให้ named-checkconf ของรุ่นปลายทางอ่านไฟล์ได้

9.2 ตรวจก่อนเริ่ม (หยุดถ้าข้อใดไม่ผ่าน)

9.3 สำรองพร้อมตรวจ checksum

B=<BACKUP_DIR>   # โฟลเดอร์สิทธิ์ root เท่านั้น
sudo cp -a /etc/bind/named.conf /etc/bind/named.conf.options "$B/"
sudo cp -a <MANAGED_KEYS_DIR>/*.mkeys* "$B/"
sudo sh -c "cd $B && sha256sum * > SHA256SUMS && sha256sum -c SHA256SUMS"
sudo rndc secroots - | sudo tee "$B/secroots-before.txt" >/dev/null

9.4 ดำเนินการ

  1. วางไฟล์ bind.keys ที่มี initial-key ของ 20326 และ initial-ds ของ 38696 ตามสิทธิ์ที่ BIND อ่านได้
  2. เปลี่ยนเฉพาะ dnssec-validation no; เป็น dnssec-validation auto; แล้วตรวจ named-checkconf
  3. Activate ด้วย rndc reconfig (ไม่ restart ในรอบนี้)
  4. ตรวจ log ต้องเห็นการอ่าน bind.keys และ DNSKEY ID 38696 is now trusted ในทุก view
  5. รัน rndc managed-keys sync เพื่อบันทึก state ลงดิสก์ แล้วตรวจว่า keyzone ของทุก view มี 38696

9.5 Rollback

เงื่อนไข: เห็น could not be verified with current keys หลัง activate, โดเมนปกติหรือโดเมนภายในสำคัญ SERVFAIL, หรือ 38696 ไม่ managed ในบาง view

  1. คืน named.conf.options จาก backup ที่ตรวจ checksum แล้ว ตรวจ syntax และ rndc reconfig
  2. ตรวจ hash ของไฟล์ที่คืน, runtime และ valid queries ซ้ำ ไม่ถือว่า script สำเร็จเพียงเพราะ exit 0
  3. ไม่ลบ bind.keys และไม่ restore หรือ reset managed state ในขั้นนี้
Rollback นี้กลับไปสถานะ “resolve ได้แต่ไม่ validate” จึงต้องขออนุมัติชัดเจนทุกครั้ง และบันทึกเหตุผลเพราะลดการป้องกันของผู้ใช้

10. ผลที่ได้ และระดับของหลักฐาน

ระดับการตรวจสถานะรายละเอียด
Runtime anchor ฝั่งเซิร์ฟเวอร์ผ่านทุก view แสดง 20326 และ 38696 เป็น managed; log ระบุ 38696 trusted
Client ใน view ที่ทดสอบได้ผ่านroot และโดเมนปกติ NOERROR + AD; โดเมนผิด SERVFAIL; +cd ตอบได้; sentinel คู่ถูกต้อง; delv fully validated
Baseline ข้อมูล authoritativeไม่เปลี่ยนผล SOA ก่อน/หลัง change ตรงกันทุกรายการที่ตรวจ
State บนดิสก์ผ่านkeyzone ของทุก view มี 38696 หลัง sync
Client E2E ของ view ที่เหลือจำกัดยืนยัน anchor ได้ แต่ยังไม่มี client ที่ได้รับอนุญาต recursion จึงไม่รายงานว่าทดสอบครบ
หลัง restartยังไม่ทำรอช่วงเวลา change ที่อนุมัติ
สังเกตต่อเนื่อง ≥ 24 ชั่วโมงยังไม่ครบรวมการตรวจหลัง root DNSKEY cache เดิมหมดอายุ

แยกรายงานระหว่าง static check, การทดสอบ runtime จริง และการ rollback ไม่รวมกัน: การ rollback ถูกเตรียมและตรวจ syntax แล้ว แต่ ไม่ได้ถูกใช้และยังไม่ได้ทดสอบกับ production

11. สิ่งที่ยังเปิดอยู่

12. บทเรียนและ checklist สำหรับผู้ดูแลอื่น

13. อ้างอิงสาธารณะ

  1. IANA — Trust Anchors and Rollovers
  2. IANA root-anchors.xml และ ลายเซ็น
  3. ISC BIND — คู่มือ delv และ options
  4. RFC 5011 — Automated Updates of DNSSEC Trust Anchors
  5. RFC 8509 — Root Key Trust Anchor Sentinel
  6. ISC — Software Support Policy and Version Numbering
  7. dnstest.dev — KSK-2024 readiness test