Bali, Indonesia
Insights

VM Proxmox Dipulihkan dari Snapshot Lalu DNS SERVFAIL? Cek Jam Sistem Dulu

October 31, 2026
0:00
Kamu baru mengembalikan VM KVM di Proxmox ke snapshot lama. Service di dalamnya hidup lagi, tapi dari dalam VM hampir semua lookup DNS membalas SERVFAIL. Anehnya, domain yang sama resolve normal dari laptop atau dari server lain. Kalau resolver di VM itu melakukan validasi DNSSEC, misalnya Unbound, BIND, atau systemd-resolved dengan DNSSEC aktif, penyebab yang sering terlewat ada di jam sistem guest yang ikut mundur ke waktu snapshot. Record DNS-nya sendiri tidak bermasalah. Artikel ini fokus ke cara membuktikannya lewat CLI, langkah demi langkah, sebelum dan sesudah jam diperbaiki.
Setiap record di zona yang ditandatangani DNSSEC punya pasangan RRSIG, yaitu tanda tangan kriptografis untuk record set tersebut. RRSIG membawa dua cap waktu: inception (mulai berlaku) dan expiration (habis berlaku). Resolver yang memvalidasi akan membandingkan kedua cap waktu itu dengan jam lokalnya sendiri. Ia tidak bertanya ke siapa pun soal jam berapa sekarang. Misalnya guest mengira sekarang masih dua minggu lalu, sesuai waktu snapshot diambil. RRSIG yang baru ditandatangani ulang kemarin akan punya inception di "masa depan" menurut guest, jadi signature itu dianggap belum berlaku. Kebalikannya juga bisa terjadi. Kalau jam guest terlalu maju, signature yang masih sah dianggap sudah kedaluwarsa. Hasilnya sama: validasi gagal, dan resolver yang patuh spesifikasi wajib menolak jawaban itu dan mengembalikan SERVFAIL. Karena banyak zona ditandatangani ulang secara berkala, makin jauh jam mundur, makin banyak domain yang ikut gagal. Itu sebabnya gejalanya terlihat seperti "DNS mati total" padahal yang salah cuma satu angka di guest.
Di Proxmox, snapshot VM bisa diambil dengan atau tanpa state RAM. Bedanya penting di sini. Snapshot tanpa RAM hanya menyimpan disk. Saat rollback, VM boot dari awal, dan kernel guest membaca jam awal dari RTC virtual yang disediakan QEMU. Biasanya RTC ini mengikuti jam host, jadi selama jam host benar, jam guest juga benar sejak boot. Snapshot dengan RAM menyimpan seluruh isi memori, termasuk keadaan kernel. Saat rollback, VM tidak boot ulang. Ia melanjutkan persis dari detik snapshot diambil, dan jam sistem guest ikut melanjutkan dari waktu lama itu. Apakah jam lalu dikoreksi otomatis tergantung versi Proxmox, ada tidaknya QEMU guest agent, dan konfigurasi NTP di guest. Jangan diasumsikan, cek sendiri. Ada dua hal yang sering membuat koreksi lewat NTP berjalan lambat atau tidak jalan sama sekali:
  1. chrony biasanya hanya melakukan step (lompat langsung ke jam yang benar) di awal service berjalan, sesuai directive makestep di konfigurasinya. Setelah itu ia melakukan slew, yaitu mempercepat atau memperlambat jam sedikit demi sedikit. Karena VM di-resume dan bukan di-boot, chrony menganggap dirinya sudah lama berjalan. Selisih besar lalu dikejar dengan slew yang bisa memakan waktu sangat lama.
  2. Server NTP biasanya ditulis sebagai hostname. Untuk menghubunginya, guest harus resolve hostname itu lewat resolver lokal, padahal resolver lokal sedang menolak semua jawaban karena jamnya salah. Hasilnya buntu: jam tidak bisa diperbaiki karena DNS gagal, dan DNS gagal karena jam salah.
Dari sisi support, pola ini sering muncul sebagai "setelah restore, situs jalan tapi kirim email, update plugin, atau panggil API eksternal gagal semua". Pertanyaan pertama yang layak diajukan: snapshot-nya pakai RAM atau tidak.
Urutannya begini. Cek jam host dan guest dalam UTC. Lalu buktikan bahwa masalahnya ada di validasi, bukan di konektivitas. Terakhir, lihat langsung masa berlaku signature-nya. Semua perintah di bawah bersifat read-only.
BASH
# Di host Proxmox: jam host sebagai pembanding
date -u

# Di dalam guest: jam guest dan status sinkronisasi
date -u
timedatectl

# Query biasa ke resolver lokal (validasi aktif)
dig @127.0.0.1 example.com A

# Query yang sama dengan Checking Disabled (+cd): resolver tidak memvalidasi
dig @127.0.0.1 example.com A +cd

# Tampilkan RRSIG untuk melihat inception dan expiration
dig @127.0.0.1 example.com A +dnssec +cd +multiline
Ganti example.com dengan domain yang sedang gagal. Kalau query biasa membalas status: SERVFAIL tetapi query dengan +cd membalas status: NOERROR lengkap dengan jawaban, berarti resolver bisa menjangkau authoritative server dan menerima datanya, lalu menolaknya saat validasi. Konektivitas dan record-nya aman, masalahnya ada di validasi. Opsi +cd di sini dipakai sebagai alat diagnosis saja. Jangan jadikan solusi dengan mematikan validasi, karena itu menghilangkan perlindungan terhadap cache poisoning dan spoofing. Output +dnssec akan menampilkan baris RRSIG. Formatnya kurang lebih seperti ini (contoh format output, nilainya ilustratif):
TEXT
example.com. 300 IN RRSIG A 13 2 300 (
                20261115000000 20261025000000 12345 example.com.
                ...signature... )
Setelah original TTL, angka pertama adalah expiration dan angka kedua adalah inception. Formatnya YYYYMMDDHHmmSS dalam UTC. Pada contoh di atas, signature berlaku dari 25 Oktober 2026 sampai 15 November 2026. Bandingkan dengan hasil date -u di guest. Kalau jam guest lebih awal dari inception, atau lebih lambat dari expiration, kamu sudah menemukan penyebabnya. Jam host dipakai sebagai acuan bahwa yang benar memang host, bukan guest. Urutan expiration lalu inception ini sering terbalik dibaca, jadi pastikan lagi sebelum menarik kesimpulan.
Log resolver biasanya sudah menyebut alasannya dengan cukup jelas. Lokasinya tergantung distro dan cara instalasi. Di sistem dengan systemd, journalctl -u unbound atau journalctl -u named (di Debian dan Ubuntu kadang bind9) adalah tempat pertama untuk dilihat. Unbound secara default cukup pendiam soal alasan validasi gagal. Directive val-log-level: 2 di unbound.conf membuatnya mencatat alasan per query yang gagal, misalnya pesan seperti signature before inception date atau signature expired. BIND biasanya mencatat sesuatu seperti signature is in the future atau signature has expired. Teks persisnya bisa berbeda antarversi, jadi cari kata kunci inception, expired, atau future. Untuk systemd-resolved, resolvectl query example.com biasanya menampilkan alasan kegagalan DNSSEC langsung di output-nya. Kalau log menyebut signature belum berlaku, jam guest kemungkinan mundur. Kalau menyebut expired padahal domain itu valid dari luar, jam guest kemungkinan terlalu maju. Kalau keduanya tidak muncul dan yang terlihat justru masalah DS atau DNSKEY, berarti penyebabnya lain. Itu topik berbeda, misalnya seperti yang dibahas di artikel tentang RRSIG yang benar-benar kedaluwarsa setelah zona dipindah ke BIND.
Catatan sebelum memperbaiki: memaksa jam melompat bisa berdampak ke aplikasi yang sensitif terhadap waktu, misalnya cron yang tiba-tiba menjalankan job tertinggal, timestamp log yang terlihat loncat, atau sesi dan token yang mendadak dianggap kedaluwarsa. Untuk VM produksi, lakukan saat kamu siap memantau efeknya. Langkah ini tidak menghapus data, tapi lompatan waktunya sendiri tidak bisa dibatalkan.
BASH
# Jika guest memakai chrony: lihat offset, lalu paksa step sekali
chronyc tracking
chronyc sources -v
sudo chronyc makestep

# Jika guest memakai systemd-timesyncd
timedatectl timesync-status
sudo systemctl restart systemd-timesyncd

# Setelah jam benar: buang cache jawaban bogus
sudo unbound-control flush_bogus   # Unbound
sudo rndc flush                    # BIND

# Ulangi query tanpa +cd, harus kembali NOERROR
dig @127.0.0.1 example.com A
Perhatikan baris System time di chronyc tracking, yang menunjukkan seberapa jauh jam sistem dari jam referensi. Kalau chronyc sources kosong atau semua source tidak terjangkau, kemungkinan besar kamu sedang kena masalah buntu tadi: hostname server NTP tidak bisa di-resolve. Jalan keluarnya, sementara arahkan guest ke resolver lain yang tidak bergantung pada jam guest. Bisa juga menyetel jam secara manual mendekati jam host lewat timedatectl set-time, tapi perintah ini hanya bisa dipakai kalau NTP dinonaktifkan dulu. Setelah itu biarkan NTP mengambil alih lagi. Pembersihan cache perlu dilakukan karena resolver bisa menyimpan hasil validasi gagal untuk sementara waktu. Tanpa flush, query tetap SERVFAIL beberapa saat meskipun jam sudah benar, dan ini sering bikin orang mengira perbaikannya tidak berhasil. Perintah unbound-control hanya bekerja kalau remote-control Unbound aktif. Kalau tidak, restart service resolver juga mengosongkan cache. Terakhir, pastikan sinkronisasi memang aktif dan bukan cuma kebetulan benar. Di output timedatectl, baris System clock synchronized harus yes dan NTP service harus active. Untuk chrony, cek apakah konfigurasinya punya directive makestep dan bagaimana batasnya. Isi default-nya berbeda per distro, dan itu menentukan apakah selisih besar setelah resume akan di-step atau hanya di-slew pelan-pelan. Jadi, kalau VM habis di-rollback lalu DNS di dalamnya mendadak SERVFAIL, mulai dari dua perintah paling murah: date -u di host dan guest, lalu dig dengan dan tanpa +cd. Kalau +cd berhasil dan jam guest berada di luar rentang inception sampai expiration di RRSIG, perbaiki jamnya, flush cache bogus, dan pastikan NTP benar-benar tersinkron. Untuk ke depannya, biasakan cek jam setiap kali melakukan rollback snapshot yang menyertakan RAM.