ProHoster > blog > administrasi > Kisah tentang paket DNS yang hilang dari dukungan teknis Google Cloud
Kisah tentang paket DNS yang hilang dari dukungan teknis Google Cloud
Dari Editor Blog Google: Pernahkah Anda bertanya-tanya bagaimana teknisi Solusi Teknis Google Cloud (TSE) menangani permintaan dukungan Anda? Insinyur Dukungan Teknis TSE bertanggung jawab untuk mengidentifikasi dan memperbaiki sumber masalah yang dilaporkan pengguna. Beberapa masalah ini cukup sederhana, namun terkadang Anda menemukan tiket yang memerlukan perhatian beberapa teknisi sekaligus. Dalam artikel ini, salah satu karyawan TSE akan memberi tahu kita tentang satu masalah yang sangat rumit dari praktiknya baru-baru ini - kasus paket DNS hilang. Dalam cerita ini, kita akan melihat bagaimana para insinyur berhasil menyelesaikan situasi tersebut, dan hal-hal baru apa yang mereka pelajari saat memperbaiki kesalahan tersebut. Kami berharap cerita ini tidak hanya mendidik Anda tentang bug yang mengakar, namun juga memberi Anda wawasan tentang proses yang diperlukan untuk mengajukan tiket dukungan ke Google Cloud.
Pemecahan masalah adalah ilmu dan seni. Semuanya dimulai dengan membangun hipotesis tentang alasan perilaku sistem yang tidak standar, setelah itu diuji kekuatannya. Namun, sebelum kita merumuskan hipotesis, kita harus mendefinisikan dengan jelas dan merumuskan masalahnya secara tepat. Jika pertanyaannya terdengar terlalu kabur, Anda harus menganalisis semuanya dengan cermat; Ini adalah “seni” pemecahan masalah.
Di bawah Google Cloud, proses tersebut menjadi jauh lebih kompleks karena Google Cloud berupaya semaksimal mungkin untuk menjamin privasi penggunanya. Oleh karena itu, teknisi TSE tidak memiliki akses untuk mengedit sistem Anda, atau kemampuan untuk melihat konfigurasi seluas yang dimiliki pengguna. Oleh karena itu, untuk menguji hipotesis kami, kami (insinyur) tidak dapat dengan cepat memodifikasi sistem.
Beberapa pengguna percaya bahwa kami akan memperbaiki semuanya seperti mekanik di layanan mobil, dan cukup mengirimkan kami id mesin virtual, sedangkan pada kenyataannya proses tersebut berlangsung dalam format percakapan: mengumpulkan informasi, membentuk dan mengkonfirmasi (atau menyangkal) hipotesis, dan, pada akhirnya, pengambilan keputusan masalah didasarkan pada komunikasi dengan klien.
Masalah yang dimaksud
Hari ini kita memiliki cerita dengan akhir yang bagus. Salah satu alasan keberhasilan penyelesaian kasus yang diajukan adalah uraian masalahnya yang sangat rinci dan akurat. Di bawah ini Anda dapat melihat salinan tiket pertama (diedit untuk menyembunyikan informasi rahasia):
Pesan ini berisi banyak informasi berguna bagi kami:
VM tertentu ditentukan
Masalahnya sendiri ditunjukkan - DNS tidak berfungsi
Ini ditunjukkan di mana masalah muncul - VM dan container
Langkah-langkah yang diambil pengguna untuk mengidentifikasi masalah ditunjukkan.
Permintaan tersebut terdaftar sebagai “P1: Dampak Kritis - Layanan Tidak Dapat Digunakan dalam Produksi”, yang berarti pemantauan situasi secara terus-menerus 24/7 sesuai dengan skema “Ikuti Matahari” (Anda dapat membaca lebih lanjut tentang prioritas permintaan pengguna), dengan perpindahannya dari satu tim dukungan teknis ke tim lainnya dengan setiap pergeseran zona waktu. Faktanya, saat masalah ini sampai ke tim kami di Zurich, masalah tersebut sudah menyebar ke seluruh dunia. Pada saat ini, pengguna telah mengambil langkah-langkah mitigasi, namun takut akan terulangnya situasi di produksi, karena akar permasalahannya belum ditemukan.
Pada saat tiket sampai di Zurich, kami sudah memiliki informasi berikut:
Konten /etc/hosts
Konten /etc/resolv.conf
Keluaran iptables-save
Dikumpulkan oleh tim ngrep file pcap
Dengan data ini, kami siap memulai tahap “investigasi” dan pemecahan masalah.
Langkah pertama kami
Pertama-tama, kami memeriksa log dan status server metadata dan memastikannya berfungsi dengan benar. Server metadata merespons alamat IP 169.254.169.254 dan, antara lain, bertanggung jawab untuk mengendalikan nama domain. Kami juga memeriksa ulang apakah firewall berfungsi dengan benar dengan VM dan tidak memblokir paket.
Itu adalah masalah yang aneh: pemeriksaan nmap menyangkal hipotesis utama kami tentang hilangnya paket UDP, jadi kami secara mental memikirkan beberapa opsi dan cara lagi untuk memeriksanya:
Apakah paket dijatuhkan secara selektif? => Periksa aturan iptables
Bukankah itu terlalu kecil? MTU? => Periksa keluaran ip a show
Apakah masalahnya hanya mempengaruhi paket UDP atau TCP juga? => Berkendara pergi dig +tcp
Apakah paket yang dihasilkan dig dikembalikan? => Berkendara pergi tcpdump
Apakah libdns berfungsi dengan benar? => Berkendara pergi strace untuk memeriksa transmisi paket di kedua arah
Di sini kami memutuskan untuk memanggil pengguna untuk memecahkan masalah secara langsung.
Selama panggilan kami dapat memeriksa beberapa hal:
Setelah beberapa kali pemeriksaan, kami mengecualikan aturan iptables dari daftar alasan
Kami memeriksa antarmuka jaringan dan tabel perutean, dan memeriksa ulang apakah MTU sudah benar
Kami menemukan itu dig +tcp google.com (TCP) berfungsi sebagaimana mestinya, tapi dig google.com (UDP) tidak berfungsi
Setelah diusir tcpdump saat bekerja dig, kami menemukan bahwa paket UDP dikembalikan
Kami pergi strace dig google.com dan kita melihat bagaimana dig memanggil dengan benar sendmsg() и recvms(), namun yang kedua diinterupsi oleh batas waktu
Sayangnya, akhir peralihan telah tiba dan kami terpaksa meneruskan masalah ke zona waktu berikutnya. Namun, permintaan tersebut membangkitkan minat tim kami, dan seorang rekan menyarankan untuk membuat paket DNS awal menggunakan modul Python yang kasar.
from scapy.all import *
answer = sr1(IP(dst="169.254.169.254")/UDP(dport=53)/DNS(rd=1,qd=DNSQR(qname="google.com")),verbose=0)
print ("169.254.169.254", answer[DNS].summary())
Fragmen ini membuat paket DNS dan mengirimkan permintaan ke server metadata.
Pengguna menjalankan kode, respons DNS dikembalikan, dan aplikasi menerimanya, mengonfirmasi bahwa tidak ada masalah di tingkat jaringan.
Setelah “perjalanan keliling dunia” lainnya, permintaan tersebut kembali ke tim kami, dan saya sepenuhnya mentransfernya ke diri saya sendiri, berpikir bahwa akan lebih nyaman bagi pengguna jika permintaan tersebut berhenti berputar-putar dari satu tempat ke tempat lain.
Sementara itu, pengguna dengan hormat setuju untuk memberikan cuplikan gambar sistem. Ini adalah kabar baik: kemampuan untuk menguji sistem sendiri membuat pemecahan masalah menjadi lebih cepat, karena saya tidak lagi harus meminta pengguna untuk menjalankan perintah, mengirimkan saya hasilnya dan menganalisisnya, saya dapat melakukan semuanya sendiri!
Rekan-rekan saya mulai sedikit iri kepada saya. Saat makan siang kami mendiskusikan konversi tersebut, namun tidak ada yang tahu apa yang sedang terjadi. Untungnya, pengguna sendiri telah mengambil tindakan untuk mengurangi konsekuensinya dan tidak terburu-buru, jadi kami punya waktu untuk membedah masalahnya. Dan karena kami memiliki gambar, kami dapat menjalankan tes apa pun yang kami minati. Besar!
Mengambil langkah mundur
Salah satu pertanyaan wawancara paling populer untuk posisi insinyur sistem adalah: “Apa yang terjadi ketika Anda melakukan ping www.google.com? Pertanyaannya bagus, karena kandidat perlu menjelaskan semuanya mulai dari shell hingga ruang pengguna, hingga kernel sistem, dan kemudian ke jaringan. Saya tersenyum: terkadang pertanyaan wawancara ternyata berguna dalam kehidupan nyata...
Saya memutuskan untuk menerapkan pertanyaan HR ini pada masalah saat ini. Secara kasar, saat Anda mencoba menentukan nama DNS, hal berikut akan terjadi:
Aplikasi memanggil perpustakaan sistem seperti libdns
libdns memeriksa konfigurasi sistem ke server DNS mana yang harus dihubungi (dalam diagram ini adalah 169.254.169.254, server metadata)
libdns menggunakan panggilan sistem untuk membuat soket UDP (SOKET_DGRAM) dan mengirim paket UDP dengan permintaan DNS di kedua arah
Melalui antarmuka sysctl Anda dapat mengkonfigurasi tumpukan UDP di tingkat kernel
Kernel berinteraksi dengan perangkat keras untuk mengirimkan paket melalui jaringan melalui antarmuka jaringan
Hypervisor menangkap dan mengirimkan paket ke server metadata setelah kontak dengannya
Server metadata, secara ajaib, menentukan nama DNS dan mengembalikan respons menggunakan metode yang sama
Izinkan saya mengingatkan Anda hipotesis apa yang telah kami pertimbangkan:
Hipotesis: Perpustakaan rusak
Tes 1: jalankan strace di sistem, periksa apakah dig memanggil panggilan sistem yang benar
Hasil: Panggilan sistem yang benar dipanggil
Tes 2: menggunakan srapy untuk memeriksa apakah kita dapat menentukan nama dengan melewati perpustakaan sistem
Hasilnya: kita bisa
Tes 3: jalankan rpm –V pada paket libdns dan file perpustakaan md5sum
Hasilnya: kode perpustakaan benar-benar identik dengan kode di sistem operasi yang berfungsi
Tes 4: pasang image sistem root pengguna pada VM tanpa perilaku ini, jalankan chroot, lihat apakah DNS berfungsi
Hasilnya: DNS berfungsi dengan benar
Kesimpulan berdasarkan tes: masalahnya bukan di perpustakaan
Hipotesis: Ada kesalahan dalam pengaturan DNS
Tes 1: periksa tcpdump dan lihat apakah paket DNS terkirim dan dikembalikan dengan benar setelah menjalankan dig
Hasilnya: paket dikirimkan dengan benar
Tes 2: periksa kembali pada server /etc/nsswitch.conf и /etc/resolv.conf
Hasilnya: semuanya benar
Kesimpulan berdasarkan tes: masalahnya bukan pada konfigurasi DNS
Hipotesis: inti rusak
Tes: instal kernel baru, periksa tanda tangan, mulai ulang
Hasil: perilaku serupa
Kesimpulan berdasarkan tes: kernelnya tidak rusak
Hipotesis: perilaku jaringan pengguna (atau antarmuka jaringan hypervisor) yang salah
Tes 1: Periksa pengaturan firewall Anda
Hasilnya: firewall meneruskan paket DNS di host dan GCP
Tes 2: mencegat lalu lintas dan memantau kebenaran transmisi dan pengembalian permintaan DNS
Hasil: tcpdump mengonfirmasi bahwa host telah menerima paket pengembalian
Kesimpulan berdasarkan tes: masalahnya bukan di jaringan
Hipotesis: server metadata tidak berfungsi
Tes 1: periksa log server metadata untuk mencari anomali
Hasilnya: tidak ada anomali di log
Tes 2: Lewati server metadata melalui dig @8.8.8.8
Hasil: Resolusi rusak bahkan tanpa menggunakan server metadata
Kesimpulan berdasarkan tes: masalahnya bukan pada server metadata
Intinya: kami menguji semua subsistem kecuali pengaturan waktu proses!
Menyelami Pengaturan Waktu Proses Kernel
Untuk mengkonfigurasi lingkungan eksekusi kernel, Anda dapat menggunakan opsi baris perintah (grub) atau antarmuka sysctl. Saya melihat ke dalam /etc/sysctl.conf dan coba bayangkan, saya menemukan beberapa pengaturan khusus. Merasa seolah-olah saya telah meraih sesuatu, saya membuang semua pengaturan non-jaringan atau non-tcp, tetap menggunakan pengaturan gunung net.core. Lalu saya pergi ke tempat izin host berada di VM dan mulai menerapkan pengaturan satu per satu, satu demi satu, dengan VM yang rusak, hingga saya menemukan pelakunya:
net.core.rmem_default = 2147483647
Ini dia, konfigurasi pemecah DNS! Saya menemukan senjata pembunuh. Tapi mengapa ini terjadi? Saya masih membutuhkan motif.
Ukuran buffer paket DNS dasar dikonfigurasi melalui net.core.rmem_default. Nilai tipikalnya adalah sekitar 200KiB, namun jika server Anda menerima banyak paket DNS, Anda mungkin ingin menambah ukuran buffer. Jika buffer penuh saat paket baru tiba, misalnya karena aplikasi tidak memprosesnya dengan cukup cepat, Anda akan mulai kehilangan paket. Klien kami meningkatkan ukuran buffer dengan benar karena dia takut kehilangan data, karena dia menggunakan aplikasi untuk mengumpulkan metrik melalui paket DNS. Nilai yang dia tetapkan adalah nilai maksimum yang mungkin: 231-1 (jika diatur ke 231, kernel akan mengembalikan “INVALID ARGUMENT”).
Tiba-tiba saya menyadari mengapa nmap dan scapy bekerja dengan benar: mereka menggunakan soket mentah! Soket mentah berbeda dari soket biasa: soket ini melewati iptables, dan tidak di-buffer!
Namun mengapa "buffer terlalu besar" menimbulkan masalah? Ini jelas tidak berfungsi sebagaimana mestinya.
Pada titik ini saya dapat mereproduksi masalah pada banyak kernel dan beberapa distribusi. Masalah sudah muncul di kernel 3.x dan sekarang muncul juga di kernel 5.x.
Memang, saat startup
sysctl -w net.core.rmem_default=$((2**31-1))
DNS berhenti bekerja.
Saya mulai mencari nilai kerja melalui algoritma pencarian biner sederhana dan menemukan bahwa sistem bekerja dengan 2147481343, tetapi bagi saya angka ini adalah kumpulan angka yang tidak ada artinya. Saya menyarankan klien untuk mencoba nomor ini, dan dia menjawab bahwa sistem berfungsi dengan google.com, tetapi masih memberikan kesalahan pada domain lain, jadi saya melanjutkan penyelidikan.
Saya telah menginstal jam tangan jatuh, alat yang seharusnya digunakan sebelumnya: alat ini menunjukkan dengan tepat di mana di dalam kernel sebuah paket berakhir. Pelakunya adalah fungsinya udp_queue_rcv_skb. Saya mengunduh sumber kernel dan menambahkan beberapa fungsiprintk untuk melacak di mana tepatnya paket itu berakhir. Saya segera menemukan kondisi yang tepat if, dan hanya menatapnya selama beberapa waktu, karena pada saat itulah semuanya akhirnya menyatu menjadi satu gambaran utuh: 231-1, angka yang tidak berarti, domain yang tidak berfungsi... Itu adalah sepotong kode di __udp_enqueue_schedule_skb:
if (rmem > (size + sk->sk_rcvbuf))
goto uncharge_drop;
Harap dicatat:
rmem bertipe int
size bertipe u16 (unsigned int enam belas bit) dan menyimpan ukuran paket
sk->sk_rcybuf bertipe int dan menyimpan ukuran buffer yang, menurut definisi, sama dengan nilai in net.core.rmem_default
Ketika sk_rcvbuf mendekati 231, menjumlahkan ukuran paket dapat menghasilkan luapan bilangan bulat. Dan karena ini adalah int, nilainya menjadi negatif, sehingga kondisinya menjadi benar padahal seharusnya salah (Anda dapat membaca selengkapnya di link).
Kesalahan dapat diperbaiki dengan cara yang sepele: dengan casting unsigned int. Saya menerapkan perbaikan dan memulai ulang sistem dan DNS berfungsi kembali.
Rasa kemenangan
Saya meneruskan temuan saya ke klien dan mengirimkannya LKML tambalan kernel. Saya senang: setiap bagian dari teka-teki cocok satu sama lain, saya dapat menjelaskan dengan tepat mengapa kami mengamati apa yang kami amati, dan yang paling penting, kami dapat menemukan solusi untuk masalah tersebut berkat kerja tim kami!
Perlu diketahui bahwa kasus ini ternyata jarang terjadi, dan untungnya kami jarang menerima permintaan rumit seperti itu dari pengguna.