Kisah Dukungan Awan DNS Tidak Ada dari Google Cloud

Dari Editor Blog Google: Pernahkah Anda bertanya-tanya bagaimana insinyur Google Cloud Technical Solutions (TSE) menangani panggilan dukungan teknis Anda? Tanggung jawab Insinyur Dukungan Teknis TSE adalah untuk mendeteksi dan menyelesaikan sumber masalah yang diidentifikasi oleh pengguna. Beberapa masalah ini cukup sederhana, tetapi kadang-kadang Anda menemukan permintaan yang membutuhkan perhatian dari beberapa insinyur sekaligus. Dalam artikel ini, salah satu karyawan TSE akan memberi tahu kami tentang satu masalah yang sangat rumit dari praktiknya baru-baru ini - kasus paket DNS yang hilang. Dalam perjalanan cerita ini, kita akan melihat bagaimana para insinyur berhasil menyelesaikan situasi, dan hal-hal baru apa yang mereka pelajari selama menghilangkan kesalahan. Kami berharap kisah ini tidak hanya akan memberi tahu Anda tentang bug yang mengakar dalam, tetapi juga memberikan pemahaman tentang proses yang terjadi ketika mengirimkan permintaan untuk mendukung Google Cloud.



Pemecahan masalah adalah ilmu dan seni. Semuanya dimulai dengan membangun hipotesis tentang penyebab perilaku non-standar sistem, setelah itu diuji kekuatannya. Namun, sebelum merumuskan hipotesis, kita harus secara jelas mengidentifikasi dan merumuskan masalah secara akurat. Jika pertanyaannya terdengar terlalu kabur maka Anda harus menganalisis semuanya dengan benar; ini adalah "seni" pemecahan masalah.

Dalam konteks Google Cloud, proses semacam itu kadang-kadang rumit, karena Google Cloud berjuang untuk menjamin privasi penggunanya. Karena itu, insinyur TSE tidak memiliki akses untuk mengedit sistem Anda, atau kemampuan untuk melihat konfigurasi seluas pengguna. Karena itu, untuk menguji hipotesis kami, kami (insinyur) tidak dapat dengan cepat memodifikasi sistem.

Beberapa pengguna percaya bahwa kami akan memperbaiki segala sesuatu seolah-olah mekanisme dalam layanan mobil, dan cukup mengirimkan kepada kami id dari mesin virtual, sedangkan dalam kenyataannya proses berlangsung dalam format percakapan: mengumpulkan informasi, menghasilkan dan mengkonfirmasi (atau menyangkal) hipotesis, dan, pada akhirnya, menyelesaikan masalah dibangun berdasarkan komunikasi dengan klien.

Masalah sedang dipertimbangkan


Hari ini kita punya cerita dengan akhir yang bagus. Salah satu alasan keberhasilan penyelesaian kasus yang diusulkan adalah deskripsi masalah yang sangat terperinci dan akurat. Di bawah ini Anda dapat melihat salinan tiket pertama (diedit, untuk menyembunyikan informasi rahasia):

Pesan ini memiliki banyak informasi berguna bagi kami:
  • VM yang ditentukan
  • Masalahnya ditunjukkan - DNS tidak berfungsi
  • Diindikasikan di mana masalah memanifestasikan dirinya - VM dan wadah
  • Langkah-langkah yang diambil pengguna untuk mengidentifikasi masalah ditunjukkan.

Banding didaftarkan sebagai "P1: Dampak Penting - Layanan Tidak Dapat Digunakan dalam produksi", yang berarti pemantauan terus-menerus terhadap situasi 24/7 menurut skema "Ikuti Matahari" (tautan dapat dibaca secara lebih rinci tentang prioritas panggilan pengguna ), dengan transmisi dari satu tim dukungan teknis ke yang lain di setiap pergeseran zona waktu. Bahkan, pada saat masalahnya mencapai tim kami di Zurich, dia berhasil mengelilingi dunia. Pada saat ini, pengguna mengambil langkah-langkah untuk mengurangi konsekuensi, tetapi takut akan pengulangan situasi pada produksi, karena alasan utama masih belum ditemukan.

Pada saat tiket mencapai Zurich, kami sudah memiliki informasi berikut:
  • Kandungan /etc/hosts
  • Kandungan /etc/resolv.conf
  • Kesimpulan iptables-save
  • File ngreppcap dikompilasi oleh perintah

Dengan data ini, kami siap untuk memulai tahap "investigasi" dan pemecahan masalah.

Langkah pertama kami


Pertama-tama, kami memeriksa log dan status server metadata dan memastikan bahwa itu berfungsi dengan benar. Server metadata merespons dengan alamat IP 169.254.169.254 dan, antara lain, bertanggung jawab untuk mengendalikan nama domain. Kami juga memeriksa ulang bahwa firewall berfungsi dengan baik dengan VM dan tidak memblokir paket.

Itu adalah masalah aneh: tes nmap membantah hipotesis utama kami tentang hilangnya paket UDP, jadi kami secara mental menyimpulkan beberapa opsi dan cara untuk memeriksanya:
  • Apakah paket hilang secara selektif? => Periksa aturan iptables
  • Apakah MTU terlalu kecil ? => Periksa outputip a show
  • Apakah masalahnya hanya mempengaruhi paket UDP atau TCP? => Mengemudidig +tcp
  • Apakah paket penggalian yang dihasilkan dikembalikan? => Mengemuditcpdump
  • Apakah libdns berfungsi dengan benar? => Mengusir straceuntuk memverifikasi transfer paket di kedua arah

Di sini kami memutuskan untuk menelepon pengguna untuk memecahkan masalah secara langsung.

Selama panggilan, kami berhasil memverifikasi beberapa hal:
  • Setelah beberapa pemeriksaan, kami mengecualikan aturan iptables dari daftar alasan.
  • Kami memeriksa antarmuka jaringan dan tabel perutean, dan memeriksa ulang MTU
  • Kami menemukan bahwa dig +tcp google.com(TCP) berfungsi sebagaimana mestinya, tetapi dig google.com(UDP) tidak berfungsi
  • Setelah tcpdumpdijalankan saat berfungsi dig, kami menemukan bahwa paket UDP sedang dikembalikan
  • Kami menjalankan strace dig google.comdan melihat bagaimana menggali panggilan dengan benar sendmsg()dan recvms(), bagaimanapun, yang kedua terganggu oleh batas waktu

Sayangnya, perubahan akan segera berakhir dan kami terpaksa memindahkan masalah ke zona waktu berikutnya. Seruan tersebut, bagaimanapun, membangkitkan minat pada tim kami, dan seorang kolega menyarankan untuk membuat paket sumber DNS dengan modul Python yang tidak sopan.
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, yang menegaskan tidak adanya masalah di tingkat jaringan.

Setelah "perjalanan keliling dunia" berikutnya, banding kembali ke tim kami, dan saya sepenuhnya menerjemahkannya ke diri saya sendiri, percaya bahwa itu akan lebih nyaman bagi pengguna jika banding berhenti berputar dari satu tempat ke tempat lain.

Sementara itu, pengguna setuju untuk memberikan snapshot dari gambar sistem. Ini adalah berita yang sangat bagus: kemampuan untuk menguji sistem Anda sendiri secara signifikan mempercepat pemecahan masalah, karena Anda tidak perlu lagi meminta pengguna untuk menjalankan perintah, mengirim saya hasil dan menganalisisnya, saya bisa melakukan semuanya sendiri!

Rekan kerja mulai sedikit iri padaku. Saat makan siang, kami membahas banding, tetapi tidak ada yang tahu apa yang sedang terjadi. Untungnya, pengguna itu sendiri telah mengambil langkah-langkah mitigasi dan tidak terburu-buru, jadi kami punya waktu untuk menyiapkan masalah. Dan karena kita memiliki gambar, kita dapat melakukan tes apa pun yang menarik bagi kita. Baik!

Kembali satu langkah


Salah satu pertanyaan paling populer dalam wawancara untuk seorang insinyur sistem adalah: "Apa yang terjadi ketika Anda melakukan ping www.google.com ?" Pertanyaannya adalah mewah, karena kandidat perlu dijelaskan dari shell ke ruang pengguna, ke inti sistem dan lebih jauh ke jaringan. Saya tersenyum: kadang-kadang pertanyaan wawancara juga berguna dalam kehidupan nyata ...

Saya memutuskan untuk menerapkan pertanyaan eychar ini untuk masalah saat ini. Secara kasar, ketika Anda mencoba menentukan nama DNS, hal berikut terjadi:
  1. Aplikasi memanggil pustaka sistem, misalnya libdns
  2. libdns memeriksa konfigurasi sistem yang harus digunakan server DNS (dalam diagram adalah 169.254.169.254, server metadata)
  3. libdns menggunakan panggilan sistem untuk membuat soket UDP (SOKET_DGRAM) dan mengirim paket UDP dengan permintaan DNS di kedua arah
  4. Dengan menggunakan antarmuka sysctl, Anda dapat mengkonfigurasi tumpukan UDP tingkat kernel
  5. Kernel berinteraksi dengan perangkat keras untuk mengirimkan paket melalui jaringan melalui antarmuka jaringan
  6. Hypervisor menangkap dan meneruskan paket ke server metadata ketika kontak dengannya
  7. Server metadata menentukan nama DNS dengan sihirnya dan mengembalikan jawabannya dengan cara yang sama


Biarkan saya mengingatkan Anda hipotesis mana yang sudah berhasil kita pertimbangkan:

Hipotesis: Perpustakaan yang rusak
  • Tes 1: jalankan strace di sistem, periksa penggalian yang menyebabkan panggilan sistem yang benar
  • Hasil: panggilan sistem yang benar dipanggil
  • Tes 2: melalui srapy untuk memeriksa apakah kita dapat menentukan nama yang melewati pustaka sistem
  • Hasil: kita bisa
  • Tes 3: jalankan rpm –V pada paket libdns dan file library md5sum
  • Hasil: kode perpustakaan benar-benar identik dengan kode di sistem operasi yang berfungsi
  • Uji 4: pasang gambar sistem root pengguna di VM tanpa perilaku ini, jalankan chroot, lihat apakah DNS berfungsi
  • Hasil: 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 dikirim dan dikembalikan dengan benar setelah menjalankan penggalian
  • Hasil: paket dikirimkan dengan benar
  • Tes 2: periksa kembali di server /etc/nsswitch.confdan/etc/resolv.conf
  • Hasil: semuanya benar

Kesimpulan Berbasis Tes: Masalahnya Tidak Ada dalam Hipotesis Konfigurasi DNS

: Kernel Rusak
  • Uji: pasang kernel baru, verifikasi tandatangan, restart
  • Hasil: perilaku serupa

Kesimpulan berdasarkan tes: kernel tidak rusak

Hipotesis: perilaku yang salah dari jaringan pengguna (atau antarmuka jaringan hypervisor)
  • Tes 1: periksa pengaturan firewall
  • Hasil: firewall melewati paket DNS pada host dan GCP
  • Tes 2: mencegat lalu lintas dan melacak kebenaran transfer dan pengembalian permintaan DNS
  • Hasil: tcpdump mengakui penerimaan paket kembali oleh tuan rumah

Kesimpulan Berbasis Tes: Masalahnya adalah Offline


  • Tes 1: periksa log server metadata untuk mencari anomali
  • Hasil: tidak ada anomali di log
  • Tes 2: memotong server metadata melalui dig @8.8.8.8
  • Hasil: izin dilanggar bahkan tanpa menggunakan server metadata

Kesimpulan berbasis pengujian: masalahnya bukan pada server metadata

Intinya: kami menguji semua subsistem kecuali pengaturan runtime!

Menyelam ke pengaturan kernel runtime


Untuk mengkonfigurasi runtime kernel, Anda dapat menggunakan opsi baris perintah (grub) atau antarmuka sysctl. Saya melihat ke dalam /etc/sysctl.confdan berpikir saja, saya menemukan beberapa pengaturan khusus. Merasa seperti telah meraih sesuatu, saya mengabaikan semua pengaturan non-jaringan atau non-tcp, yang tersisa dari pengaturan gunung net.core. Kemudian saya beralih ke tempat di mana VM memiliki izin host dan mulai menerapkan satu demi satu, pengaturan satu demi satu dengan VM yang rusak, sampai saya mencapai penjahat:
net.core.rmem_default = 2147483647

Ini dia, konfigurasi pemecah DNS! Saya menemukan alat kejahatan. Tetapi mengapa ini terjadi? Saya masih membutuhkan motif.

Pengaturan ukuran dasar buffer paket DNS terjadi net.core.rmem_default. Nilai tipikal bervariasi di suatu tempat dalam 200KiB, namun jika server Anda menerima banyak paket DNS, Anda dapat meningkatkan ukuran buffer. Jika buffer penuh saat paket baru tiba, misalnya, karena aplikasi tidak memprosesnya dengan cukup cepat, maka Anda akan mulai kehilangan paket. Klien kami meningkatkan ukuran buffer dengan benar karena ia takut kehilangan data, karena ia menggunakan aplikasi untuk mengumpulkan metrik melalui paket DNS. Nilai yang dia tetapkan adalah maksimum yang dimungkinkan: 2 31 -1 (jika Anda menetapkan 2 31 , 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 berfungsi memotong iptables, dan tidak ada buffer!

Tetapi mengapa "buffer terlalu besar" menyebabkan masalah? Jelas tidak berfungsi sebagaimana dimaksud.

Pada titik ini, saya dapat mereproduksi masalah pada banyak core dan beberapa distribusi. Masalahnya telah memanifestasikan dirinya dalam kernel 3.x dan sekarang juga memanifestasikan dirinya dalam kernel 5.x.

Memang saat startup
sysctl -w net.core.rmem_default=$((2**31-1))

DNS telah berhenti bekerja.

Saya mulai mencari nilai-nilai yang bekerja melalui algoritma pencarian biner sederhana dan menemukan bahwa sistem bekerja dengan 2147481343, namun angka ini adalah seperangkat angka yang tidak berarti bagi saya. Saya mengundang klien untuk mencoba nomor ini, dan dia menjawab bahwa sistem bekerja dengan google.com, tetapi masih memberikan kesalahan dengan domain lain, jadi saya melanjutkan penyelidikan.

Saya memasang dropwatch , alat yang seharusnya saya gunakan sebelumnya: ini menunjukkan di mana tepatnya paket masuk ke kernel. Fungsi itu bersalah udp_queue_rcv_skb. Saya mengunduh sumber kernel dan menambahkan beberapa fungsi printk untuk melacak di mana paket mendapatkan secara khusus. Saya segera menemukan kondisi yang tepatif, dan untuk sementara waktu hanya menatapnya, karena pada saat itulah semuanya akhirnya datang bersama dalam satu gambar: 2 31 -1, angka yang tidak berarti, domain yang tidak digunakan ... Itu adalah sepotong kode di __udp_enqueue_schedule_skb:
if (rmem > (size + sk->sk_rcvbuf))
		goto uncharge_drop;

catatan:
  • rmem memiliki tipe int
  • size adalah tipe u16 (unsigned sixteen bit int) dan menyimpan ukuran paket
  • sk->sk_rcybuf adalah tipe int dan menyimpan ukuran buffer, yang menurut definisi sama dengan nilai dalam net.core.rmem_default

Saat sk_rcvbufmendekati 2 31 , menjumlahkan ukuran paket dapat menyebabkan overflow integer . Dan karena itu adalah int, nilainya menjadi negatif, sehingga kondisinya menjadi benar ketika harus salah (lebih lanjut tentang ini dapat ditemukan dengan referensi ).

Kesalahan diperbaiki dengan cara sepele: dengan casting ke unsigned int. Saya menerapkan tambalan dan memulai kembali sistem, setelah itu DNS mulai bekerja kembali.

Rasa kemenangan


Saya meneruskan temuan saya ke klien dan mengirim patch kernel LKML . Saya puas: setiap bagian puzzle menyatu menjadi satu, saya dapat menjelaskan dengan tepat mengapa kami mengamati apa yang kami amati, dan yang paling penting, kami dapat menemukan solusi untuk masalah tersebut dengan bekerja bersama!

Patut diakui bahwa kasus ini ternyata jarang, dan untungnya, panggilan kompleks seperti itu jarang diterima dari pengguna dari kami.





All Articles