Isang kwento tungkol sa mga nawawalang DNS packet mula sa teknikal na suporta ng Google Cloud

Mula sa Google Blog Editor: Naisip mo na ba kung paano pinangangasiwaan ng mga inhinyero ng Google Cloud Technical Solutions (TSE) ang iyong mga kahilingan sa suporta? Ang TSE Technical Support Engineer ay may pananagutan sa pagtukoy at pagwawasto sa mga pinagmumulan ng mga problema na iniulat ng user. Ang ilan sa mga problemang ito ay medyo simple, ngunit kung minsan ay nakatagpo ka ng isang tiket na nangangailangan ng atensyon ng ilang mga inhinyero nang sabay-sabay. Sa artikulong ito, sasabihin sa amin ng isa sa mga empleyado ng TSE ang tungkol sa isang napakahirap na problema mula sa kanyang kamakailang pagsasanay - kaso ng nawawalang mga DNS packet. Sa kwentong ito, makikita natin kung paano nalutas ng mga inhinyero ang sitwasyon, at kung anong mga bagong bagay ang kanilang natutunan habang inaayos ang error. Inaasahan namin na ang kuwentong ito ay hindi lamang nagtuturo sa iyo tungkol sa isang malalim na bug, ngunit nagbibigay din sa iyo ng insight sa mga proseso na napupunta sa pag-file ng ticket ng suporta sa Google Cloud.

Isang kwento tungkol sa mga nawawalang DNS packet mula sa teknikal na suporta ng Google Cloud

Ang pag-troubleshoot ay parehong agham at isang sining. Nagsisimula ang lahat sa pagbuo ng isang hypothesis tungkol sa dahilan para sa hindi pamantayang pag-uugali ng system, pagkatapos nito ay nasubok para sa lakas. Gayunpaman, bago tayo bumalangkas ng hypothesis, kailangan nating malinaw na tukuyin at tiyak na bumalangkas ng problema. Kung ang tanong ay masyadong malabo, pagkatapos ay kailangan mong pag-aralan nang mabuti ang lahat; Ito ang "sining" ng pag-troubleshoot.

Sa ilalim ng Google Cloud, ang mga naturang proseso ay nagiging mas kumplikado, habang sinusubukan ng Google Cloud ang lahat upang magarantiya ang privacy ng mga user nito. Dahil dito, ang mga inhinyero ng TSE ay walang access upang i-edit ang iyong mga system, o ang kakayahang tingnan ang mga configuration nang kasing lawak ng ginagawa ng mga user. Samakatuwid, upang subukan ang alinman sa aming mga hypotheses, hindi namin (mga inhinyero) mabilis na mabago ang system.

Naniniwala ang ilang user na aayusin namin ang lahat tulad ng mga mekaniko sa isang serbisyo ng kotse, at ipapadala lang sa amin ang id ng isang virtual machine, samantalang sa katotohanan ang proseso ay nagaganap sa format ng pakikipag-usap: pagkolekta ng impormasyon, pagbuo at pagkumpirma (o pagpapabulaanan) ng mga hypotheses, at, sa huli, ang mga problema sa pagpapasya ay batay sa komunikasyon sa kliyente.

Problema na pinag-uusapan

Ngayon ay mayroon tayong kwento na may magandang wakas. Ang isa sa mga dahilan para sa matagumpay na paglutas ng iminungkahing kaso ay isang napaka-detalyado at tumpak na paglalarawan ng problema. Sa ibaba makikita mo ang isang kopya ng unang tiket (na-edit upang itago ang kumpidensyal na impormasyon):
Isang kwento tungkol sa mga nawawalang DNS packet mula sa teknikal na suporta ng Google Cloud
Ang mensaheng ito ay naglalaman ng maraming kapaki-pakinabang na impormasyon para sa amin:

  • Tinukoy ang partikular na VM
  • Ang problema mismo ay ipinahiwatig - DNS ay hindi gumagana
  • Ito ay ipinahiwatig kung saan ang problema ay nagpapakita mismo - VM at lalagyan
  • Ang mga hakbang na ginawa ng user upang matukoy ang problema ay ipinahiwatig.

Ang kahilingan ay nakarehistro bilang "P1: Kritikal na Epekto - Serbisyong Hindi Magagamit sa produksyon", na nangangahulugang patuloy na pagsubaybay sa sitwasyon 24/7 ayon sa "Follow the Sun" scheme (maaari kang magbasa nang higit pa tungkol sa mga priyoridad ng mga kahilingan ng user), kasama ang paglipat nito mula sa isang technical support team patungo sa isa pa sa bawat time zone shift. Sa katunayan, nang dumating ang problema sa aming koponan sa Zurich, umikot na ito sa mundo. Sa oras na ito, ang gumagamit ay gumawa ng mga hakbang sa pagpapagaan, ngunit natatakot na maulit ang sitwasyon sa produksyon, dahil hindi pa natutuklasan ang ugat.

Sa oras na makarating ang tiket sa Zurich, mayroon na kaming sumusunod na impormasyon sa kamay:

  • Nilalaman /etc/hosts
  • Nilalaman /etc/resolv.conf
  • Pagbubuhos iptables-save
  • Pinagsama-sama ng pangkat ngrep pcap file

Gamit ang data na ito, handa kaming simulan ang yugto ng "pagsisiyasat" at pag-troubleshoot.

Ang aming mga unang hakbang

Una sa lahat, sinuri namin ang mga log at status ng metadata server at tiniyak na ito ay gumagana nang tama. Ang metadata server ay tumutugon sa IP address na 169.254.169.254 at, bukod sa iba pang mga bagay, ay may pananagutan sa pagkontrol sa mga domain name. Sinuri din namin na ang firewall ay gumagana nang tama sa VM at hindi hinaharangan ang mga packet.

Ito ay isang uri ng kakaibang problema: pinabulaanan ng nmap check ang aming pangunahing hypothesis tungkol sa pagkawala ng mga UDP packet, kaya naisip namin ang ilang higit pang mga opsyon at paraan upang suriin ang mga ito:

  • Pinili bang ibinaba ang mga packet? => Suriin ang mga panuntunan ng iptables
  • Hindi ba ito masyadong maliit? MTU? => Suriin ang output ip a show
  • Ang problema ba ay nakakaapekto lamang sa mga UDP packet o TCP din? => Itaboy dig +tcp
  • Ibinalik ba ang dig generated packets? => Itaboy tcpdump
  • Gumagana ba nang tama ang libdns? => Itaboy strace upang suriin ang pagpapadala ng mga packet sa parehong direksyon

Dito kami nagpasya na tawagan ang user upang i-troubleshoot ang mga problema nang live.

Sa panahon ng tawag, nasusuri namin ang ilang bagay:

  • Pagkatapos ng ilang pagsusuri, ibinubukod namin ang mga panuntunan ng iptables mula sa listahan ng mga dahilan
  • Sinusuri namin ang mga interface ng network at mga talahanayan ng pagruruta, at i-double-check kung tama ang MTU
  • Natutuklasan namin iyon dig +tcp google.com (TCP) ay gumagana ayon sa nararapat, ngunit dig google.com (UDP) ay hindi gumagana
  • Nagtaboy tcpdump ito ay gumagana pa rin dig, nalaman namin na ang mga UDP packet ay ibinabalik
  • Nag drive kami palayo strace dig google.com at nakikita natin kung paano tama ang tawag ni dig sendmsg() ΠΈ recvms(), gayunpaman ang pangalawa ay naantala ng isang timeout

Sa kasamaang palad, dumating ang pagtatapos ng shift at napipilitan kaming iangat ang problema sa susunod na time zone. Ang kahilingan, gayunpaman, ay pumukaw ng interes sa aming team, at ang isang kasamahan ay nagmumungkahi ng paglikha ng paunang DNS package gamit ang scrapy Python module.

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

Lumilikha ang fragment na ito ng DNS packet at ipinapadala ang kahilingan sa metadata server.

Pinapatakbo ng user ang code, ibinalik ang tugon ng DNS, at natatanggap ito ng application, na nagpapatunay na walang problema sa antas ng network.

Pagkatapos ng isa pang "round-the-world trip," babalik ang kahilingan sa aming team, at ganap kong inililipat ito sa aking sarili, sa pag-aakalang magiging mas maginhawa para sa user kung ang kahilingan ay hihinto sa pag-ikot sa bawat lugar.

Pansamantala, sumasang-ayon ang user na magbigay ng snapshot ng imahe ng system. Ito ay napakagandang balita: ang kakayahang subukan ang system mismo ay ginagawang mas mabilis ang pag-troubleshoot, dahil hindi ko na kailangang hilingin sa gumagamit na magpatakbo ng mga utos, ipadala sa akin ang mga resulta at suriin ang mga ito, magagawa ko ang lahat sa aking sarili!

Medyo naiingit na sa akin ang mga kasamahan ko. Sa paglipas ng tanghalian, tinatalakay namin ang conversion, ngunit walang sinuman ang may ideya kung ano ang nangyayari. Sa kabutihang palad, ang gumagamit mismo ay gumawa na ng mga hakbang upang pagaanin ang mga kahihinatnan at hindi nagmamadali, kaya mayroon kaming oras upang i-dissect ang problema. At dahil mayroon kaming imahe, maaari kaming magpatakbo ng anumang mga pagsubok na interesado sa amin. Malaki!

Paatras ng isang hakbang

Isa sa mga pinakasikat na tanong sa panayam para sa mga posisyon ng system engineer ay: β€œAno ang mangyayari kapag nag-ping ka www.google.com? Ang tanong ay mahusay, dahil ang kandidato ay kailangang ilarawan ang lahat mula sa shell hanggang sa espasyo ng gumagamit, sa kernel ng system at pagkatapos ay sa network. Napangiti ako: minsan ang mga tanong sa panayam ay nagiging kapaki-pakinabang sa totoong buhay...

Nagpasya akong ilapat itong HR na tanong sa isang kasalukuyang problema. Sa halos pagsasalita, kapag sinubukan mong tukuyin ang isang pangalan ng DNS, ang mga sumusunod ay mangyayari:

  1. Ang application ay tumatawag sa isang library ng system tulad ng libdns
  2. Sinusuri ng libdns ang configuration ng system kung saan dapat itong kontakin ang DNS server (sa diagram ito ay 169.254.169.254, metadata server)
  3. Gumagamit ang libdns ng mga system call para gumawa ng UDP socket (SOKET_DGRAM) at magpadala ng mga UDP packet na may DNS query sa parehong direksyon
  4. Sa pamamagitan ng interface ng sysctl maaari mong i-configure ang UDP stack sa antas ng kernel
  5. Nakikipag-ugnayan ang kernel sa hardware upang magpadala ng mga packet sa network sa pamamagitan ng network interface
  6. Ang hypervisor ay nakakakuha at nagpapadala ng packet sa metadata server sa pakikipag-ugnay dito
  7. Ang metadata server, sa pamamagitan ng magic nito, ay tumutukoy sa pangalan ng DNS at nagbabalik ng tugon gamit ang parehong paraan

Isang kwento tungkol sa mga nawawalang DNS packet mula sa teknikal na suporta ng Google Cloud
Hayaan mong ipaalala ko sa iyo kung anong mga hypotheses ang napag-isipan na natin:

Hypothesis: Sirang mga aklatan

  • Pagsubok 1: patakbuhin ang strace sa system, suriin na ang dig ay tumatawag sa tamang mga tawag sa system
  • Resulta: Tinatawag ang mga tamang tawag sa system
  • Pagsubok 2: gamit ang srapy upang suriin kung matutukoy namin ang mga pangalan na lumalampas sa mga library ng system
  • Resulta: kaya natin
  • Pagsubok 3: magpatakbo ng rpm –V sa libdns package at md5sum library file
  • Resulta: ang code ng library ay ganap na magkapareho sa code sa gumaganang operating system
  • Pagsubok 4: i-mount ang imahe ng root system ng user sa isang VM nang walang ganitong pag-uugali, patakbuhin ang chroot, tingnan kung gumagana ang DNS
  • Resulta: Gumagana nang tama ang DNS

Konklusyon batay sa mga pagsubok: ang problema ay wala sa mga aklatan

Hypothesis: May error sa mga setting ng DNS

  • Pagsubok 1: suriin ang tcpdump at tingnan kung naipadala at naibalik nang tama ang mga DNS packet pagkatapos tumakbo ng dig
  • Resulta: ang mga packet ay naipadala nang tama
  • Pagsubok 2: i-double check sa server /etc/nsswitch.conf ΠΈ /etc/resolv.conf
  • Resulta: lahat ay tama

Konklusyon batay sa mga pagsubok: ang problema ay wala sa configuration ng DNS

Hypothesis: nasira ang core

  • Pagsubok: mag-install ng bagong kernel, suriin ang lagda, i-restart
  • Resulta: katulad na pag-uugali

Konklusyon batay sa mga pagsubok: hindi nasira ang kernel

Hypothesis: maling pag-uugali ng user network (o hypervisor network interface)

  • Pagsubok 1: Suriin ang iyong mga setting ng firewall
  • Resulta: ipinapasa ng firewall ang mga DNS packet sa parehong host at GCP
  • Pagsubok 2: harangin ang trapiko at subaybayan ang kawastuhan ng pagpapadala at pagbabalik ng mga kahilingan sa DNS
  • Resulta: Kinukumpirma ng tcpdump na nakatanggap ang host ng mga return packet

Konklusyon batay sa mga pagsubok: wala sa network ang problema

Hypothesis: hindi gumagana ang metadata server

  • Pagsubok 1: suriin ang mga log ng server ng metadata para sa mga anomalya
  • Resulta: walang mga anomalya sa mga log
  • Pagsubok 2: I-bypass ang metadata server sa pamamagitan ng dig @8.8.8.8
  • Resulta: Nasira ang resolution kahit na hindi gumagamit ng metadata server

Konklusyon batay sa mga pagsubok: ang problema ay wala sa metadata server

Ang bottom line: sinubukan namin ang lahat ng mga subsystem maliban mga setting ng runtime!

Sumisid sa Mga Setting ng Kernel Runtime

Para i-configure ang kernel execution environment, maaari mong gamitin ang command line options (grub) o ang interface ng sysctl. Tumingin ako sa loob /etc/sysctl.conf at isipin mo na lang, may natuklasan akong ilang custom na setting. Pakiramdam ko ay may nahawakan ako, itinapon ko ang lahat ng setting na hindi network o hindi tcp, na natitira sa mga setting ng bundok net.core. Pagkatapos ay pumunta ako sa kung saan ang mga pahintulot ng host ay nasa VM at nagsimulang ilapat ang mga setting nang paisa-isa, isa-isa, kasama ang sirang VM, hanggang sa nakita ko ang salarin:

net.core.rmem_default = 2147483647

Narito ito, isang configuration ng DNS-breaking! Natagpuan ko ang sandata ng pagpatay. Ngunit bakit ito nangyayari? Kailangan ko pa ng motibo.

Ang pangunahing laki ng DNS packet buffer ay na-configure sa pamamagitan ng net.core.rmem_default. Ang isang karaniwang halaga ay nasa isang lugar sa paligid ng 200KiB, ngunit kung ang iyong server ay tumatanggap ng maraming DNS packet, maaaring gusto mong dagdagan ang laki ng buffer. Kung puno na ang buffer kapag may dumating na bagong packet, halimbawa dahil hindi ito pinoproseso ng application nang mabilis, magsisimula kang mawalan ng mga packet. Tamang pinalaki ng aming kliyente ang laki ng buffer dahil natatakot siyang mawala ang data, dahil gumagamit siya ng application para sa pagkolekta ng mga sukatan sa pamamagitan ng mga DNS packet. Ang halagang itinakda niya ay ang pinakamataas na posible: 231-1 (kung nakatakda sa 231, ang kernel ay magbabalik ng "INVALID ARGUMENT").

Bigla kong napagtanto kung bakit gumagana nang tama ang nmap at scapy: gumagamit sila ng mga hilaw na socket! Ang mga raw socket ay iba sa mga regular na socket: nilalampasan nila ang mga iptable, at hindi sila na-buffer!

Ngunit bakit nagdudulot ng mga problema ang "masyadong malaki ang buffer"? Malinaw na hindi ito gumagana ayon sa nilalayon.

Sa puntong ito maaari kong kopyahin ang problema sa maraming mga kernel at maramihang mga distribusyon. Ang problema ay lumitaw na sa 3.x kernel at ngayon ito ay lumitaw din sa 5.x kernel.

Sa katunayan, sa pagsisimula

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

Huminto sa paggana ang DNS.

Nagsimula akong maghanap ng mga gumaganang halaga sa pamamagitan ng isang simpleng binary search algorithm at nalaman kong gumagana ang system sa 2147481343, ngunit ang numerong ito ay isang walang kahulugan na hanay ng mga numero para sa akin. Iminungkahi ko sa kliyente na subukan ang numerong ito, at sumagot siya na gumagana ang system sa google.com, ngunit nagbigay pa rin ng error sa ibang mga domain, kaya ipinagpatuloy ko ang aking pagsisiyasat.

na-install ko na dropwatch, isang tool na dapat ay ginamit nang mas maaga: ito ay nagpapakita nang eksakto kung saan sa kernel napupunta ang isang packet. Ang salarin ay ang function udp_queue_rcv_skb. Nag-download ako ng mga mapagkukunan ng kernel at nagdagdag ng ilan function printk upang subaybayan kung saan eksaktong nagtatapos ang packet. Mabilis akong nakahanap ng tamang kondisyon if, at tinitigan lang ito nang ilang sandali, dahil sa wakas ay nagkasama-sama ang lahat sa isang buong larawan: 231-1, isang walang kabuluhang numero, isang hindi gumaganang domain... Ito ay isang piraso ng code sa __udp_enqueue_schedule_skb:

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

Mangyaring tandaan:

  • rmem ay uri ng int
  • size ay nasa uri na u16 (unsigned sixteen-bit int) at iniimbak ang laki ng packet
  • sk->sk_rcybuf ay may uri na int at iniimbak ang laki ng buffer na, ayon sa kahulugan, ay katumbas ng halaga sa net.core.rmem_default

Kapag sk_rcvbuf ay lumalapit sa 231, ang pagbubuod ng laki ng packet ay maaaring magresulta sa integer overflow. At dahil ito ay isang int, nagiging negatibo ang halaga nito, kaya nagiging totoo ang kundisyon kapag ito ay dapat na mali (maaari kang magbasa nang higit pa tungkol dito sa link).

Ang error ay maaaring itama sa isang maliit na paraan: sa pamamagitan ng pag-cast unsigned int. Inilapat ko ang pag-aayos at na-restart ang system at gumana muli ang DNS.

Sarap ng tagumpay

Ipinasa ko ang aking mga natuklasan sa kliyente at ipinadala LKML kernel patch. Natutuwa ako: magkatugma ang bawat piraso ng puzzle, maipaliwanag ko nang eksakto kung bakit namin naobserbahan ang aming naobserbahan, at higit sa lahat, nakahanap kami ng solusyon sa problema salamat sa aming pagtutulungan ng magkakasama!

Ito ay nagkakahalaga ng pagkilala na ang kaso ay naging bihira, at sa kabutihang palad ay bihira kaming makatanggap ng mga ganoong kumplikadong kahilingan mula sa mga user.

Isang kwento tungkol sa mga nawawalang DNS packet mula sa teknikal na suporta ng Google Cloud


Pinagmulan: www.habr.com

Magdagdag ng komento