Google Cloud texnik yordamidan DNS paketlarini etishmayotgani haqidagi hikoya

Google Blog muharriridan: Google Cloud Technical Solutions (TSE) muhandislari sizning qo'llab-quvvatlash so'rovlaringizni qanday hal qilishlari haqida hech o'ylab ko'rganmisiz? TSE Texnik qo'llab-quvvatlash muhandislari foydalanuvchi tomonidan bildirilgan muammolar manbalarini aniqlash va tuzatish uchun javobgardir. Ushbu muammolardan ba'zilari juda oddiy, lekin ba'zida siz bir vaqtning o'zida bir nechta muhandislarning e'tiborini talab qiladigan chiptaga duch kelasiz. Ushbu maqolada TSE xodimlaridan biri o'zining so'nggi amaliyotidagi juda qiyin muammo haqida gapirib beradi - DNS paketlarining yo'qolishi holati. Ushbu hikoyada biz muhandislar vaziyatni qanday hal qilishga muvaffaq bo'lganini va xatoni tuzatishda qanday yangi narsalarni o'rganganini ko'rib chiqamiz. Umid qilamizki, bu hikoya sizni nafaqat chuqur xato haqida ma'lumot beradi, balki sizga Google Cloud bilan qo'llab-quvvatlash chiptasini topshirish jarayonlari haqida ham ma'lumot beradi.

Google Cloud texnik yordamidan DNS paketlarini etishmayotgani haqidagi hikoya

Muammolarni bartaraf etish ham fan, ham san'atdir. Bularning barchasi tizimning nostandart xatti-harakatlarining sababi haqida gipotezani yaratishdan boshlanadi, shundan so'ng u kuch uchun sinovdan o'tkaziladi. Biroq, gipotezani shakllantirishdan oldin, biz muammoni aniq belgilashimiz va aniq shakllantirishimiz kerak. Agar savol juda noaniq bo'lsa, unda siz hamma narsani diqqat bilan tahlil qilishingiz kerak bo'ladi; Bu muammolarni bartaraf etishning "san'ati".

Google Cloud ostida bunday jarayonlar eksponent ravishda murakkablashadi, chunki Google Cloud o'z foydalanuvchilarining maxfiyligini kafolatlash uchun qo'lidan kelganicha harakat qiladi. Shu sababli, TSE muhandislari tizimlaringizni tahrirlash va konfiguratsiyalarni foydalanuvchilar kabi kengroq ko'rish imkoniyatiga ega emaslar. Shuning uchun, har qanday farazimizni sinab ko'rish uchun biz (muhandislar) tizimni tezda o'zgartira olmaymiz.

Ba'zi foydalanuvchilar avtoservisdagi mexanika kabi hamma narsani tuzatamiz va shunchaki virtual mashina identifikatorini yuboramiz, deb ishonishadi, aslida esa bu jarayon suhbat formatida amalga oshiriladi: ma'lumot to'plash, gipotezalarni shakllantirish va tasdiqlash (yoki rad etish), va oxir-oqibat, qaror qabul qilish muammolari mijoz bilan muloqotga asoslanadi.

Savoldagi muammo

Bugun bizda oxiri yaxshi bo'lgan hikoya bor. Taklif etilayotgan ishning muvaffaqiyatli hal etilishining sabablaridan biri bu muammoning juda batafsil va aniq tavsifidir. Quyida siz birinchi chipta nusxasini ko'rishingiz mumkin (maxfiy ma'lumotlarni yashirish uchun tahrirlangan):
Google Cloud texnik yordamidan DNS paketlarini etishmayotgani haqidagi hikoya
Ushbu xabar biz uchun juda ko'p foydali ma'lumotlarni o'z ichiga oladi:

  • Maxsus VM ko'rsatilgan
  • Muammoning o'zi ko'rsatilgan - DNS ishlamaydi
  • Muammoning qaerda namoyon bo'lishi ko'rsatiladi - VM va konteyner
  • Muammoni aniqlash uchun foydalanuvchi qilgan qadamlar ko'rsatilgan.

So'rov "P1: Kritik ta'sir - ishlab chiqarishda foydalanish mumkin bo'lmagan xizmat" sifatida ro'yxatga olingan, bu "Quyoshga ergashish" sxemasiga muvofiq vaziyatni 24/7 doimiy monitoringini anglatadi (bu haqida batafsil ma'lumot olishingiz mumkin). foydalanuvchi so'rovlarining ustuvorliklari), har bir vaqt zonasi o'zgarishi bilan bir texnik yordam guruhidan boshqasiga o'tkazilishi bilan. Darhaqiqat, muammo Syurixdagi jamoamizga yetib borganida, u allaqachon butun dunyoni aylanib ulgurgan edi. Bu vaqtga kelib, foydalanuvchi yumshatish choralarini ko'rdi, ammo ishlab chiqarishdagi vaziyatning takrorlanishidan qo'rqdi, chunki asosiy sabab hali aniqlanmagan.

Chipta Tsyurixga yetganida, bizda quyidagi ma'lumotlar bor edi:

  • Tarkib /etc/hosts
  • Tarkib /etc/resolv.conf
  • xulosa iptables-save
  • Jamoa tomonidan yig'ilgan ngrep pcap fayli

Ushbu ma'lumotlar bilan biz "tergov" va muammolarni bartaraf etish bosqichini boshlashga tayyor edik.

Bizning birinchi qadamlarimiz

Avvalo, biz metadata serverining jurnallari va holatini tekshirdik va uning to'g'ri ishlashiga ishonch hosil qildik. Metama'lumotlar serveri 169.254.169.254 IP manziliga javob beradi va boshqa narsalar qatori domen nomlarini boshqarish uchun javobgardir. Shuningdek, xavfsizlik devori VM bilan to'g'ri ishlashini va paketlarni bloklamasligini ikki marta tekshirdik.

Bu qandaydir g'alati muammo edi: nmap tekshiruvi UDP paketlarini yo'qotish haqidagi asosiy gipotezamizni rad etdi, shuning uchun biz aqlan yana bir nechta variant va ularni tekshirish usullarini o'ylab topdik:

  • Paketlar tanlab tashlanadimi? => iptables qoidalarini tekshiring
  • Juda kichik emasmi? MTU? => Chiqishni tekshiring ip a show
  • Muammo faqat UDP paketlari yoki TCP ga ham ta'sir qiladimi? => Haydab keting dig +tcp
  • Qazilgan paketlar qaytariladimi? => Haydab keting tcpdump
  • Libdns to'g'ri ishlayaptimi? => Haydab keting strace har ikki yo'nalishda paketlarning uzatilishini tekshirish

Bu erda muammolarni jonli ravishda bartaraf etish uchun foydalanuvchini chaqirishga qaror qildik.

Qo'ng'iroq paytida biz bir nechta narsalarni tekshirishimiz mumkin:

  • Bir nechta tekshiruvlardan so'ng biz sabablar ro'yxatidan iptables qoidalarini istisno qilamiz
  • Biz tarmoq interfeyslari va marshrutlash jadvallarini tekshiramiz va MTU to'g'riligini ikki marta tekshiramiz
  • Biz buni kashf qilamiz dig +tcp google.com (TCP) kerak bo'lganidek ishlaydi, lekin dig google.com (UDP) ishlamaydi
  • Haydab ketgan tcpdump u hali ham ishlamoqda dig, biz UDP paketlari qaytarilayotganligini aniqlaymiz
  • Biz haydab ketamiz strace dig google.com va biz qazishni qanday qilib to'g'ri chaqirishini ko'ramiz sendmsg() и recvms(), ammo ikkinchisi vaqt tugashi bilan to'xtatiladi

Afsuski, smenaning oxiri keladi va biz muammoni keyingi vaqt zonasiga o'tkazishga majburmiz. Biroq, so'rov bizning jamoamizda qiziqish uyg'otdi va hamkasbimiz yirtqich Python moduli yordamida dastlabki DNS paketini yaratishni taklif qilmoqda.

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())

Ushbu fragment DNS paketini yaratadi va so'rovni metadata serveriga yuboradi.

Foydalanuvchi kodni ishga tushiradi, DNS javobi qaytariladi va dastur uni qabul qilib, tarmoq darajasida muammo yo'qligini tasdiqlaydi.

Yana bir "dunyo bo'ylab sayohat" dan so'ng, so'rov jamoamizga qaytadi va men so'rov joydan ikkinchi joyga aylanib qolsa, foydalanuvchi uchun qulayroq bo'ladi deb o'ylab, uni butunlay o'zimga o'tkazaman.

Shu bilan birga, foydalanuvchi tizim tasvirining oniy rasmini taqdim etishga rozi bo'ladi. Bu juda yaxshi yangilik: tizimni o'zim sinab ko'rish qobiliyati muammolarni bartaraf etishni ancha tezlashtiradi, chunki men endi foydalanuvchidan buyruqlarni bajarishni, natijalarni yuborishni va ularni tahlil qilishni so'rashim shart emas, men hamma narsani o'zim qila olaman!

Hamkasblarim menga biroz havas qila boshlashdi. Tushlik paytida biz konvertatsiyani muhokama qilamiz, lekin hech kim nima bo'layotganini bilmaydi. Yaxshiyamki, foydalanuvchining o'zi allaqachon oqibatlarni yumshatish uchun choralar ko'rgan va shoshilmayapti, shuning uchun muammoni tahlil qilishga vaqtimiz bor. Va bizda tasvir borligi sababli, bizni qiziqtirgan har qanday testlarni o'tkazishimiz mumkin. Ajoyib!

Orqaga qadam tashlash

Tizim muhandisi lavozimlari uchun eng mashhur intervyu savollaridan biri: “Ping qilganingizda nima bo'ladi www.google.com? Savol ajoyib, chunki nomzod qobiqdan tortib foydalanuvchi maydonigacha, tizim yadrosi va keyin tarmoqqa qadar hamma narsani tasvirlashi kerak. Men tabassum qilaman: ba'zida intervyu savollari haqiqiy hayotda foydali bo'ladi ...

Men ushbu HR savolini hozirgi muammoga qo'llashga qaror qildim. Qo'pol qilib aytganda, DNS nomini aniqlashga harakat qilganingizda, quyidagilar sodir bo'ladi:

  1. Ilova libdns kabi tizim kutubxonasini chaqiradi
  2. libdns qaysi DNS-server bilan bog'lanishi kerak bo'lgan tizim konfiguratsiyasini tekshiradi (diagrammada bu 169.254.169.254, metama'lumotlar serveri)
  3. libdns UDP soketini (SOKET_DGRAM) yaratish va har ikki yo'nalishda DNS so'rovi bilan UDP paketlarini yuborish uchun tizim chaqiruvlaridan foydalanadi.
  4. Sysctl interfeysi orqali siz yadro darajasida UDP stekini sozlashingiz mumkin
  5. Yadro tarmoq interfeysi orqali paketlarni tarmoq orqali uzatish uchun apparat bilan o'zaro ta'sir qiladi
  6. Gipervisor paketni ushlaydi va u bilan aloqa qilganda metadata serveriga uzatadi
  7. Meta-ma'lumotlar serveri o'zining sehri bilan DNS nomini aniqlaydi va xuddi shu usul yordamida javob qaytaradi

Google Cloud texnik yordamidan DNS paketlarini etishmayotgani haqidagi hikoya
Sizga qanday gipotezalarni ko'rib chiqqanimizni eslatib o'taman:

Gipoteza: Buzilgan kutubxonalar

  • Sinov 1: tizimda strace-ni ishga tushiring, dig to'g'ri tizim chaqiruvlarini chaqirishini tekshiring
  • Natija: To'g'ri tizim qo'ng'iroqlari chaqiriladi
  • Sinov 2: tizim kutubxonalarini chetlab o'tgan nomlarni aniqlashimiz mumkinmi yoki yo'qligini tekshirish uchun srapy-dan foydalanish
  • Natija: biz qila olamiz
  • Sinov 3: libdns paketi va md5sum kutubxonasi fayllarida rpm –V ni ishga tushiring
  • Natija: kutubxona kodi ishlaydigan operatsion tizimdagi kod bilan mutlaqo bir xil
  • Sinov 4: foydalanuvchining ildiz tizimi tasvirini bunday xatti-harakatlarsiz VM ga o'rnating, chroot-ni ishga tushiring, DNS ishlayotganligini tekshiring
  • Natija: DNS to'g'ri ishlaydi

Sinovlar asosida xulosa: muammo kutubxonalarda emas

Gipoteza: DNS sozlamalarida xatolik bor

  • 1-sinov: tcpdump-ni tekshiring va qazishni bajarganingizdan so'ng DNS paketlari to'g'ri yuborilganligini va qaytarilganligini tekshiring
  • Natija: paketlar to'g'ri uzatildi
  • Sinov 2: serverni ikki marta tekshiring /etc/nsswitch.conf и /etc/resolv.conf
  • Natija: hamma narsa to'g'ri

Sinovlar asosida xulosa: muammo DNS konfiguratsiyasida emas

Gipoteza: yadro shikastlangan

  • Sinov: yangi yadro o'rnating, imzoni tekshiring, qayta ishga tushiring
  • Natija: shunga o'xshash xatti-harakatlar

Sinovlar asosida xulosa: yadro buzilmaydi

Gipoteza: foydalanuvchi tarmog'ining noto'g'ri xatti-harakati (yoki gipervisor tarmoq interfeysi)

  • Sinov 1: xavfsizlik devori sozlamalarini tekshiring
  • Natija: xavfsizlik devori DNS paketlarini xost va GCP da uzatadi
  • Sinov 2: trafikni ushlab turing va DNS so'rovlarini uzatish va qaytarishning to'g'riligini nazorat qiling
  • Natija: tcpdump xost qaytaruvchi paketlarni olganligini tasdiqlaydi

Sinovlar asosida xulosa: muammo tarmoqda emas

Gipoteza: metadata serveri ishlamayapti

  • Sinov 1: metadata server jurnallarida anomaliyalarni tekshiring
  • Natija: jurnallarda hech qanday anomaliya yo'q
  • Sinov 2: metama'lumotlar serverini chetlab o'ting dig @8.8.8.8
  • Natija: Metadata serveridan foydalanmasdan ham ruxsat buziladi

Sinovlar asosida xulosa: muammo metadata serverida emas

Bottom layn: tashqari barcha quyi tizimlarni sinab ko'rdik ish vaqti sozlamalari!

Yadroning ishlash vaqti sozlamalariga kirish

Yadro ijro muhitini sozlash uchun siz buyruq qatori parametrlaridan (grub) yoki sysctl interfeysidan foydalanishingiz mumkin. Men ichkariga qaradim /etc/sysctl.conf va o'ylab ko'ring, men bir nechta maxsus sozlamalarni topdim. O'zimni biror narsaga qo'l urgandek his qilib, tog 'sozlamalarida qolgan tarmoqdan tashqari yoki tcp bo'lmagan barcha sozlamalarni o'chirib tashladim. net.core. Keyin men VM-da xost ruxsatlari joylashgan joyga bordim va aybdorni topgunimcha, sozlamalarni birin-ketin, buzilgan VM bilan qo'llashni boshladim:

net.core.rmem_default = 2147483647

Mana, DNS-buzuvchi konfiguratsiya! Men qotillik qurolini topdim. Lekin nima uchun bu sodir bo'lmoqda? Menga hali ham motiv kerak edi.

Asosiy DNS paketi bufer hajmi orqali sozlangan net.core.rmem_default. Odatdagi qiymat 200KiB atrofida bo'ladi, lekin agar sizning serveringiz juda ko'p DNS paketlarini qabul qilsa, bufer hajmini oshirishni xohlashingiz mumkin. Agar yangi paket kelganda bufer to'lgan bo'lsa, masalan, dastur uni etarlicha tez qayta ishlamasa, siz paketlarni yo'qotishni boshlaysiz. Bizning mijozimiz bufer hajmini to'g'ri oshirdi, chunki u ma'lumotlar yo'qolishidan qo'rqdi, chunki u DNS paketlari orqali o'lchovlarni yig'ish uchun dastur ishlatgan. U o'rnatgan qiymat mumkin bo'lgan maksimal qiymat edi: 231-1 (agar 231 ga o'rnatilgan bo'lsa, yadro "YANGI ARGUMENT" ni qaytaradi).

To'satdan men nmap va scapy nima uchun to'g'ri ishlaganini tushundim: ular xom rozetkalardan foydalanishgan! Xom rozetkalar oddiy rozetkalardan farq qiladi: ular iptablesni chetlab o'tadi va ular buferlanmaydi!

Lekin nima uchun "bufer juda katta" muammolarni keltirib chiqaradi? Bu mo'ljallangandek ishlamasligi aniq.

Shu nuqtada men muammoni bir nechta yadro va bir nechta tarqatishda takrorlashim mumkin edi. Muammo allaqachon 3.x yadrosida paydo bo'lgan va endi u 5.x yadrosida ham paydo bo'ldi.

Darhaqiqat, ishga tushirilganda

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

DNS ishlamay qoldi.

Men oddiy ikkilik qidiruv algoritmi orqali ishchi qiymatlarni qidira boshladim va tizim 2147481343 bilan ishlaganligini aniqladim, ammo bu raqam men uchun ma'nosiz raqamlar to'plami edi. Men mijozga ushbu raqamni sinab ko'rishni taklif qildim va u tizim google.com bilan ishlaganini aytdi, lekin shunga qaramay, boshqa domenlarda xatolik yuz berdi, shuning uchun men tergovni davom ettirdim.

Men o'rnatdim tomchi soat, avvalroq ishlatilishi kerak bo'lgan vosita: u paket yadroning qayerda tugashini aniq ko'rsatadi. Aybdor funktsiya edi udp_queue_rcv_skb. Men yadro manbalarini yuklab oldim va bir nechtasini qo'shdim vazifalari printk paket qayerda tugashini kuzatish uchun. Men tezda kerakli holatni topdim if, va shunchaki unga bir muddat tikilib turdi, chunki o‘shanda hamma narsa nihoyat bir butun rasmga birlashdi: 231-1, ma’nosiz raqam, ishlamaydigan domen... Bu kod bo‘lagi edi. __udp_enqueue_schedule_skb:

if (rmem > (size + sk->sk_rcvbuf))
		goto uncharge_drop;

Shuni yodda tuting:

  • rmem int turiga kiradi
  • size u16 (imzosiz o'n olti bitli int) turiga ega va paket hajmini saqlaydi
  • sk->sk_rcybuf int turiga kiradi va ta'rifi bo'yicha in qiymatiga teng bo'lgan bufer hajmini saqlaydi net.core.rmem_default

qachon sk_rcvbuf 231 ga yaqinlashadi, paket hajmini yig'ish natijaga olib kelishi mumkin butun sonning to'lib ketishi. Va bu int bo'lgani uchun uning qiymati manfiy bo'ladi, shuning uchun shart noto'g'ri bo'lishi kerak bo'lganda to'g'ri bo'ladi (bu haqida ko'proq o'qishingiz mumkin. aloqa).

Xato arzimas tarzda tuzatilishi mumkin: kasting orqali unsigned int. Men tuzatishni qo'lladim va tizimni qayta ishga tushirdim va DNS yana ishladi.

G'alabaning ta'mi

Men topilmalarimni mijozga yubordim va yubordim LKML yadro patchi. Men mamnunman: jumboqning har bir qismi bir-biriga mos keladi, men nima uchun kuzatganimizni aniq tushuntira olaman va eng muhimi, jamoaviy ishimiz tufayli muammoga yechim topa oldik!

Shuni tan olish kerakki, bu holat kamdan-kam hollarda bo'lib chiqdi va xayriyatki, biz foydalanuvchilardan bunday murakkab so'rovlarni kamdan-kam qabul qilamiz.

Google Cloud texnik yordamidan DNS paketlarini etishmayotgani haqidagi hikoya


Manba: www.habr.com

a Izoh qo'shish