Historia e paketeve DNS të humbura nga mbështetje e Google Cloud

Nga redaktori i blogut të Google: A keni ndonjëherë kërkuar se si inxhinierët e Zgjidhjeve Teknike të Google Cloud (TSE) trajtojnë kërkesat tuaja për mbështetje? Detyra e inxhinierëve të mbështetjes teknike TSE përfshin identifikimin dhe zgjidhjen e burimeve të problemeve të raportuara nga përdoruesit. Disa nga këto probleme janë mjaft të thjeshta, por ndonjëherë ndodhet një kërkesë që kërkon vëmendjen e disa inxhinierëve. Në këtë artikull, një nga punonjësit e TSE do të na tregojë për një problem shumë të komplikuar nga praktika e tij e fundit — rasti i humbjes së paketave DNS. Gjatë këtij tregimi, do të shohim se si inxhinierët arritën të zgjidhnin situatën dhe çfarë të reja mësuan gjatë përpjekjeve për të zgjidhur gabimin. Shpresojmë që kjo histori jo vetëm t'ju tregojë për një defekt të thellë, por gjithashtu të ofrojë një kuptim të proceseve që ndodhin gjatë paraqitjes së një kërkese në mbështetje të Google Cloud.

Historia e paketeve DNS të humbura nga mbështetje e Google Cloud

Zgjidhja e problemeve është njëkohësisht shkencë dhe art. Çdo gjë fillon me ndërtimin e një hipoteze për shkakun e sjelljes jo standard të sistemit, pas së cilës testi i saj është thelbësor. Megjithatë, para se të formuloni një hipotezë, duhet të përcaktojmë qartë dhe të formulojmë saktësisht problemin. Nëse pyetja është shumë e paqartë, do t'ju duhet të bëni një analizë të thellë; kjo është pikërisht ajo që përbën "artin" e zgjidhjes së problemeve.

Në kushtet e Google Cloud, këto procese komplikohen shumë, pasi Google Cloud përpiqet të garantojë privatësinë e përdoruesve të tij. Për këtë arsye, inxhinierët TSE nuk kanë as qasje për të edituar sistemet tuaja, as mundësi për të shqyrtuar konfiguracionet po aq gjerësisht sa bëjnë përdoruesit. Prandaj, për të kontrolluar ndonjë nga hipotezat tona, ne (inxhinierët) nuk mund të modifikojmë shpejt sistemin.

Disa disa përdorues mendojnë se ne do të rregullojmë gjithçka si në një servis automjetesh, dhe thjesht na dërgojnë id e makinës virtuale, ndërkohë që në të vërtetë procesi zhvillohet në format bisedash: mbledhja e informacionit, formimi dhe konfirmimi (ose hedhja poshtë) e hipotezave, dhe, në fund, zgjidhja e problemit ndërtohet mbi komunikimin me klientin.

Problemi në shqyrtim

Sot përpara nesh është një histori me një fund të mirë. Një nga arsyet e suksesit në zgjidhjen e rastit të propozuar është përshkrimi shumë i detajuar dhe i saktë i problemit. Më poshtë mund të shihni një kopje të parë të tiketës (e redaktuar, për të fshehur informacionin konfidencial):
Historia e paketeve DNS të humbura nga mbështetje e Google Cloud
Në këtë mesazh ka shumë informacion të dobishëm për ne:

  • Është caktuar VM konkrete
  • Është caktuar vetë problemi – DNS nuk funksionon
  • Është caktuar ku shfaqet problemi – VM dhe kontejner
  • Janë caktuar hapat që ka ndjekur përdoruesi për të përcaktuar problemin

Ankimi është regjistruar si «P1: Ndikim Kritike – Shërbimi i Pasishtëm në prodhim», që do të thotë mbikëqyrje të vazhdueshme të situatës 24/7 sipas skemës «Follow the Sun» (në lidhje mund të lexoni më shumë mbi prioritetet e ankesave të përdoruesve), me kalimin e saj nga një ekip mbështetje në tjetrin me çdo ndryshim të zonave kohet. Në thelb, deri në momentin që problemi arriti tek ekipi ynë në Cyrih, ai kishte bërë një rrethim të globit. Në këtë moment, përdoruesi kishte marrë masa për të reduktuar pasojat, por ishte i shqetësuar për një përsëritje të situatës në prodhim, pasi arsyeja kryesore ende nuk ishte zbuluar.

Në momentin që bileta arriti në Cyrih, ne kishim tashmë informacionin e mëposhtëm:

  • Përmbajtja /etc/hosts
  • Përmbajtja /etc/resolv.conf
  • Përfundim iptables-save
  • Të grumbulluara nga ekipi ngrep skedari pcap

Me këto të dhëna ishim gati për të filluar fazën e 'hetimit' dhe diagnostikimit.

Hapat tanë të parë

Së pari, ne kontrolluam regjistrat dhe statusin e serverit të të dhënave dhe u siguruam që ai punonte siç duhet. Serveri i të dhënave përgjigjet në adresën IP 169.254.169.254 dhe, përveç të tjerave, është përgjegjës për menaxhimin e emrave të domeneve. Ne gjithashtu konfirmuam se firewalli funksiononte siç duhet me VM-në dhe nuk bllokonte paketat.

Ishte një problem i çuditshëm: kontrolli i nmap e hodhi poshtë hipotezën tonë kryesore për humbjen e paketave UDP, kështu që mendërisht nxorrëm disa mundësi dhe mënyra për t'i kontrolluar ato:

  • A po shfaqen paketet përzgjedhshëm? => Kontrolloni rregullat e iptables
  • A nuk është shumë e vogël MTU? => Проверить вывод ip a shfaq
  • A e ndikon problemi vetëm paketat UDP ose edhe TCP? => Kryeni testimin dig +tcp
  • A kthehen paketat e gjeneruara nga dig? => Kryeni testimin tcpdump
  • A punon saktë libdns? => Kryeni testimin strace për të verifikuar transmetimin e paketave në të dy drejtimet

Këtu ne vendosim të telefonojmë përdoruesin për të zgjidhur problemet live.

Gjatë telefonatës, ne arrijmë të verifikojmë disa gjëra:

  • Pas disa kontrolleve, ne përjashtojmë rregullat e iptables nga lista e shkaqeve
  • Ne kontrollojmë ndërfaqet e rrjetit dhe tabelat e rrugës, dhe rishikojmë saktësinë e MTU
  • Ne zbulojmë që dig +tcp google.com (TCP) funksionon siç duhet, por dig google.com (UDP) nuk funksionon
  • Kryesimi i testimit tcpdump deri tani po punon dig, ne zbulojmë që paketat UDP kthehen
  • Ne kryejmë testimin strace dig google.com dhe shohim se dig thërret saktë sendmsg() dhe recvmsg(), megjithatë e dyta ndërpritet nga skadimi

Për fat të keq, përfundon ndërrimi dhe ne jemi të detyruar ta kalojmë problemin në zonën tjetër të kohës. Sidoqoftë, kontakti shkaktoi interes në ekipin tonë, dhe kolegu sugjeron të krijojmë paketën DNS origjinale me modulin python scrapy.

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

Ky kyç është krijimi i një paketi DNS dhe dërgimi i kërkesës tek serveri i metadata-ve.

Përdoruesi ekzekuton kodin, përgjigjja DNS kthehet, dhe aplikacioni e merr atë, duke konfirmuar se nuk ka probleme në nivelin e rrjetit.

Pas një 'rrethimi të botës' tjetër, kërkesa kthehet tek ekipi ynë, dhe unë e përgjithësoj plotësisht, duke menduar se do të ishte më e lehtë për përdoruesin nëse kërkesa nuk do të vazhdonte të qarkullonte.

Ndërkohë, përdoruesi pranon me mirësjellje të ofrojë një fotografi të imazhit të sistemit. Kjo është një lajm shumë i mirë: mundësia për të testuar sistemin vetë e përshpejton ndjeshëm zgjidhjen e problemeve, pasi nuk nevojitet më të kërkoj nga përdoruesi të ekzekutojë komanda, të më dërgojë rezultatet dhe t'i analizoj, unë mund ta bëj gjithçka vetë!

Kolegët fillojnë të më kenë pak zili. Gjatë drekës diskutojmë për incidentin, megjithatë askush nuk ka ide se çfarë po ndodh. Fatmirësisht, vetë përdoruesi ka marrë masa për të zbutur pasojat dhe nuk ka nxitim, kështu që kemi kohë për të analizuar problemin. Dhe që kemi një imazh, mund të realizojmë çdo test që na intereson. Kjo është shkëlqyer!

Kthehemi një hap mbrapa

Një nga pyetjet më të zakonshme në intervistat për pozitën e inxhinierit të sistemit është: "Çfarë ndodh kur ju pingoni www.google.com?» Вопрос шикарный, так как кандидату необходимо описать пусть от оболочки до пользовательского пространства, до ядра системы и далее к сети. Я улыбаюсь: иногда вопросы с интервью оказываются полезны и в реальной жизни…

Unë vendos të aplikoj këtë pyetje të HR-it në problemin aktual. Thjesht, kur përpiqeni të përcaktoni një emër DNS, ndodh e mëposhtme:

  1. Aplikacioni thërret bibliotekën sistemore, për shembull libdns
  2. libdns kontrollon konfigurimin e sistemit se në cilin server DNS duhet të drejtohet (në diagram është 169.254.169.254, serveri i metadonave)
  3. libdns përdor thirrje sistemore për të krijuar një soket UDP (SOKET_DGRAM) dhe për të dërguar paketa UDP me kërkesën DNS në të dy drejtimet
  4. Përmes ndërfaqes sysctl mund të konfigurohet staku UDP në nivelin e bërthamës
  5. Bërthama bashkëpunon me harduerin për të dërguar paketa në rrjet përmes ndërfaqes rrjet
  6. Hipervizori kap të kapë dhe të dërgojë paketën te serveri i metadatave kur ka kontakt me të
  7. Serveri i metadatave me magjinë e tij përcakton emrin DNS dhe në të njëjtën mënyrë kthen përgjigjen

Historia e paketeve DNS të humbura nga mbështetje e Google Cloud
Më kujtojnë se cilat hipoteza kemi shqyrtuar deri tani:

Hipoteza: Bibliotekat janë dëmtuar

  • Testi 1: të kalojmë në sistemin strace, të kontrollojmë se çfarë thirrjesh të sakta sistemore bën dig
  • Rezultati: thirrjet e sakta sistemore janë bërë
  • Testi 2: përmes srapy të kontrollojmë nëse mund të përcaktojmë emrat përveç bibliotekave sistemore
  • Rezultati: mund të përcaktojmë
  • Testi 3: të kalojmë rpm –V në paketën libdns dhe md5sum të skedave të bibliotekës
  • Rezultati: kodi i bibliotekës është plotësisht identik me kodin në sistemin e punës
  • Testi 4: të montojmë imazhin e sistemit të rrënjës së përdoruesit në VM pa këtë sjellje, të kalojmë chroot, të shohim nëse funksionon DNS
  • Rezultati: DNS funksionon siç duhet

Përfundimi nga testet: problemi nuk është te bibliotekat

Hipoteza: Ka një gabim në konfigurimin e DNS

  • Testi 1: të shqyrtojmë tcpdump dhe të vëzhgojmë nëse paketat DNS dërgohen dhe kthehen siç duhet pas aktivizimit të dig
  • Rezultati: paketat dërgohen siç duhet
  • Testi 2: të rikonfirmojmë në server /etc/nsswitch.conf dhe /etc/resolv.conf
  • Rezultati: gjithçka është në rregull

Përfundimi nga testet: problemi nuk është në konfigurimin e DNS

Hipoteza: bërthama e dëmtuar

  • Testi: instaloni një bërthamë të re, kontrolloni nënshkrimin, ri-nisni
  • Rezultati: sjellje e ngjashme

Përfundimi nga testet: bërthama nuk është e dëmtuar

Hipoteza: sjellje e papërshtatshme e rrjetit të përdoruesit (ose ndërfaqes së rrjetit të hipervizorit)

  • Testi 1: kontrolloni cilësimet e firewall-it
  • Rezultati: firewall-i kalon paketat DNS në host dhe në GCP
  • Testi 2: kapni trafikun dhe ndjekni saktësinë e transmetimit dhe kthimit të kërkesave DNS
  • Rezultati: tcpdump konfirmon marrjen e paketave kthimi nga hosti

Përfundimi nga testet: problemi nuk është në rrjet

Hipoteza: serveri i metadatas nuk funksionon

  • Testi 1: kontrolloni logjet e serverit të metadatas për anomalitë
  • Rezultati: nuk ka anomalish në logje
  • Testi 2: kaloni serverin e metadatas përmes dig @8.8.8.8
  • Rezultati: zgjidhja prishet edhe pa përdorur serverin e metadatas

Përfundimi nga testet: problemi nuk është në serverin e metadatas

Përfundimi: ne testuam të gjitha nën-sistemat përveç cilësimeve të mjedisit të ekzekutimit!

Duke u zhytur në cilësimet e mjedisit të ekzekutimit të bërthamës

Për të konfiguruar mjedisin e ekzekutimit të bërthamës mund të përdorni opsionet e komandave (grub) ose ndërfaqen sysctl. Kam hedhur një sy në /etc/sysctl.conf dhe të mendosh, zbulova disa cilësime të personalizuara. Ndjehesha sikur kisha kapur diçka, prandaj e hodha poshtë çdo cilësim që nuk ishte rrjetësor ose jo-tcp, duke mbetur me një grumbull cilësimesh net.core. Pastaj shkova atje ku VM ka lejet e mikpritësit dhe fillova të aplikoj një pas një cilësimet nga VM-ja e prishur, deri sa arrita te fajtorja:

net.core.rmem_default = 2147483647

Ja, ky është konfigurimi që prish DNS-in! Gjeta armën e krimit. Por pse ndodh kjo? Më duhej ende një motiv.

Cilësimi i madhësisë bazë të njësive DNS bëhet nëpërmjet net.core.rmem_default. Vlera tipike shkon diku rreth 200KiB, por nëse serveri juaj merr shumë njësitë DNS, mund të rritni madhësinë e njësisë. Nëse në momentin e marrjes së një njësie të re, e gjithë njësia është e mbushur, për shembull, sepse aplikacioni nuk e proceson mjaft shpjet, atëherë do të filloni të humbni paketa. Klienti ynë e rriti saktësisht madhësinë e njësisë sepse kishte frikë se do të humbiste të dhëna, pasi përdorte një aplikacion për mbledhjen e metrikave përmes njësive DNS. Vlera që ai vendosi ishte maksimumi i mundshëm: 231-1 (nëse vendosni 231, bërthama do të kthejë "ARGUMENT I PABESUESHËM").

Papritëm papritur se pse nmap dhe scapy funksiononin siç duhej: ato përdornin soket të gjallë! Soket të gjallë janë ndryshe nga ata normalë: ata punojnë përtej iptables dhe nuk buferohen!

Por pse ‘buferi shumë i madh’ shkakton probleme? Ai duket se nuk funksionon siç duhej.

Në këtë pikë, unë mund të riprodhoja problemin në disa bërthama dhe shumë distribucione. Problemi kishte shfaqur tashmë në bërthamën 3.x dhe tani shfaqej gjithashtu në bërthamën 5.x.

Në të vërtetë, kur ekzekutova

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

DNS ndaloi së funksionuari.

Nisa të kërkoja vlera funksionale përmes një algoritmi të thjeshtë të kërkimit binar dhe zbulova se me 2147481343 sistemi funksiononte, megjithatë ky numër ishte për mua një grup numrash pa kuptim. I propozuam klientit ta provonte këtë numër dhe ai u përgjigj se sistemi pati sukses me google.com, por ende jepte gabim me domain të tjerë, prandaj vazhdova hetimin tim.

Instalova dropwatch, një mjet që do e doja të kisha përdorur më parë: ai tregon se ku saktësisht në bërthamë arrin paketi. Faji doli të ishte funksioni udp_queue_rcv_skb. E shkarkova kodin burimor të bërthamës dhe shtova disa funksione printk për të ndjekur se ku përfundon konkretisht paketa. I kisha zbuluar shpejt kushtin e duhur nëse, dhe për një kohë të shkurtër thjesht e shikoja atë, sepse pikërisht atëherë gjithçka përfundimisht u bashkua në një tabllo të plotë: 231-1, një numër pa kuptim, një domen që nuk funksionon… Problemi ishte në një pjesë kodi në __udp_enqueue_schedule_skb:

nëse (rmem > (size + sk->sk_rcvbuf))
		shko te uncharge_drop;

Vini re:

  • rmem ka tip int
  • size ka tip u16 (një int i gjashtëmbëdhjetë bitësh të pandashëm) dhe ruan madhësinë e paketës
  • sk->sk_rcybuf ka tip int dhe ruan madhësinë e bufere që sipas definicionit është e barabartë me vlerën në net.core.rmem_default

Kur sk_rcvbuf duke iu afruar 231, përllogaritja e madhësisë së paketës mund të çojë në tepricë të numrit të plotë. Dhe meqenëse është int, vlera e tij bëhet negative, kështu që kushti bëhet i vërtetë kur duhet të jetë i gabuar (mund të mësoni më shumë për këtë në lidhjes).

Gabimi korrigjohet në mënyrë triviale: përmes konvertimit në unsigned int. E aplikoha korrigjimin dhe ripërtheva sistemin, pas së cilës DNS rifilloi të funksionojë.

Shija e fitores

I dërgova gjetjet e mia klientit dhe dërgova LKML patch kernel. Jam i kënaqur: çdo copë nga enigmat përputhet në një tërësi, mund të shpjegoj saktësisht pse panë atë që panë, dhe ajo që është më e rëndësishmja, arritëm të gjenim zgjidhjen për problemin falë punës së bashku!

Duhet pranuar se rasti ishte i rrallë dhe, fatmirësisht, nuk kemi marrë shpesh kërkesa të tilla kaq komplekse nga përdoruesit.

Historia e paketeve DNS të humbura nga mbështetje e Google Cloud


Burimi: habr.com

Bli një hosting të besueshëm për faqet me mbrojtje DDoS, VPS VDS serverë 🔥 Bli një hosting të besueshëm për faqet me mbrojtje DDoS, VPS VDS serverë | ProHoster