Historia për paketat DNS të humbura nga mbështetje teknike Google Cloud

Nga redaktori i blogut të Google: A keni pyetur ndonjëherë se si inxhinierët e Zgjidhjeve Teknike të Google Cloud (TSE) trajtojnë kërkesat tuaja për mbështetje teknike? Përgjegjësia e inxhinierëve të mbështetjes teknike TSE përfshin identifikimin dhe zgjidhjen e burimeve të problemit të përmendura nga përdoruesit. Disa nga këto probleme janë mjaft të thjeshta, por ndonjëherë ndodh 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ë kompleks nga praktika e tij e fundit — rastin e paketave DNS që humbasin. Gjatë këtij rrëfimi, ne do të shohim se si inxhinierët arritën të zgjidhnin situatën dhe çfarë të re do të mësojnë gjatë procesit të zgjidhjes së gabimit. Shpresojmë që kjo histori jo vetëm do t'ju tregojë për një bug të thellë, por do të ofrojë gjithashtu një kuptim të proceseve që ndodhin kur dërgoni një kërkesë për mbështetje në Google Cloud.

Historia për paketat DNS të humbura nga mbështetje teknike Google Cloud

Zgjidhja e problemeve është njëkohësisht shkencë dhe art. E gjithë kjo fillon me ndërtimin e një hipoteze mbi shkakun e sjelljes jo të zakonshme të sistemit, e cila më pas kontrollohet për besueshmëri. Megjithatë, para se të formulojmë një hipotezë, duhet të përcaktojmë qartë dhe saktë problemin. Nëse pyetja është shumë e paqartë, do t'ju duhet të analizoni gjithçka; këtu vjen në lojë «arta» e zgjidhjes së problemeve.

Në kushte të Google Cloud, këto procese komplikohet ndjeshëm, pasi Google Cloud bënë çdo përpjekje për të garantuar privatësinë e përdoruesve të tij. Për këtë arsye, inxhinierët TSE nuk kanë akses për të ndryshuar sistemet tuaja, as për të shqyrtuar konfigurimet aq gjerësisht sa bëjnë përdoruesit. Prandaj, për të verifikuar ndonjë nga hipotezat tona, ne (inxhinierët) nuk mund të modifikojmë shpejt sistemin.

Disa përdorues mendojnë se ne do të zgjidhim gjithçka si mekanikët në një servis automatik, dhe thjesht na dërgojnë id-në e makinerisë virtuale, kur në realitet procesi zhvillohet në formatin e një bisede: mbledhja e informacionit, formimi dhe konfirmimi (ose hedhi poshtë) i hipotezave, dhe, në fund, zgjidhja e problemit ndërtohet mbi komunikimin me klientin.

Problemi i shqyrtuar

Sot kemi përpara një histori me një përfundim 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ë biletës (e redaktuar, me qëllim për të fshehur informacionin e konfidencialitetit):
Historia për paketat DNS të humbura nga mbështetje teknike Google Cloud
Në këtë mesazh ka shumë informacione të dobishme për ne:

  • Të dhënë një VM specifike
  • Caktohet problemi — nuk funksionon DNS
  • Tregohet se ku shfaqet problemi — VM dhe kontejner
  • Të dhëna hap pas hapi që përdoruesi mori për të identifikuar problematikën

Kërkesa u regjistrua si "P1: Ndikim Kritike — Shërbimi i Pakuptueshëm në prodhim", që do të thotë mbikëqyrje të vazhdueshme të situatës 24/7 sipas një plani "Ndjekja e Diellit" (në lidhje mund të lexoni më shumë për prioritetet e kërkesave të përdoruesve), me kalimin e saj nga një ekip mbështetjeje teknike në tjetrin me çdo ndryshim të zonave të kohës. Në thelb, deri në momentin kur problemi arriti në ekipin tonë në Cyrih, ai kishte përshkuar globin. Deri në këtë kohë, përdoruesi kishte marrë masa për të ulur pasojat, megjithatë, shqetësohej për përsëritjen e situatës në prodhim, pasi shkaku themelor ende nuk ishte zbuluar.

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

  • Përmbajtja /etc/hosts
  • Përmbajtja /etc/resolv.conf
  • Përfundimi iptables-save
  • Të dhena të mbledhura nga ekipi ngrep skedari pcap

Me këto të dhëna, ishim të gatshëm të fillonim fazën e "hetimit" dhe zgjidhjes së problemeve.

Hapat tanë të parë

Së pari, kontrolluam logot dhe statusin e serverit të metadatan dhe u siguruam që ai funksiononte saktë. Serveri i metadatan përgjigjet në adresën IP 169.254.169.254 dhe, përveç të gjitha, është përgjegjës për kontrollin e emrave të domainëve. Ne gjithashtu rikonfirmuam se firewallu po funksiononte siç duhet me VM dhe nuk po bllokonte paketat.

Ishte një problem i çuditshëm: kontrolli me nmap e refuzoi hipotezën tonë kryesore për humbjen e paketave UDP, kështu që ne mënduam disa mundësi të tjera për t'i verifikuar:

  • A përjashtohen paketat? => Kontrolloni rregullat iptables
  • A është shumë e vogël MTU? => Проверить вывод ip a show
  • A përfshin problemi vetëm paketat UDP apo edhe TCP? => Testoni dig +tcp
  • A kthehen paketat e gjeneruara nga dig? => Testoni tcpdump
  • A funksionon saktë libdns? => Testoni strace për të verifikuar kalimin e paketave në të dyja drejtimet

Këtu ne vendosim të telefonojmë përdoruesin për të zgjidhur problemet në mënyrë të drejtpërdrejtë.

Gjatë telefonatës arritëm të verifikojmë disa gjëra:

  • Pas disa kontrollesh, ne përjashtojmë rregullat e iptables nga lista e shkaqeve
  • Ne kontrollojmë ndërfaqet e rrjetit dhe tabelat e routingut, dhe verifikojmë saktësinë e MTU
  • Ne zbulojmë se dig +tcp google.com (TCP) funksionon siç duhet, por dig google.com (UDP) nuk funksionon
  • Duke e kaluar tcpdump po funksionon dig, zbulojmë se paketat UDP kthehen
  • Ne kalojmë strace dig google.com dhe shohim si dig e thërret saktësisht sendmsg() dhe recvmsg(), megjithatë i dyti ndërpritet për shkak të skadimit të kohës

Për fat të keq, përfundon turni dhe ne jemi të detyruar ta dorëzojmë problemin në zonën tjetër të kohës. Megjithatë, kërkesa shkaktoi interes në ekipin tonë, dhe një koleg sugjeroi të krijojmë paketën origjinale DNS 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 fragment krijon paketën DNS dhe dërgon kërkesën në serverin e metadatuave.

Përdoruesi ekzekuton kodin, përgjigja DNS kthehet dhe aplikacioni e merr, duke konfirmuar mungesën e problemit në nivelin e rrjetit.

Pas një "udhëtimi rreth botës", kërkesa kthehet në ekipin tonë, dhe unë e marr plotësisht, duke menduar se do të ishte më e lehtë për përdoruesin nëse kërkesa nuk do të lëvizte më.

Ndërkohë, përdoruesi është me mirësjellje dakord të ofrojë një fotografi të imazhit të sistemit. Këto janë lajme shumë të mira: mundësia për të testuar sistemin vetë e përshpejton ndihmën në zgjidhjen e problemeve, sepse nuk është më e nevojshme të kërkojë nga përdoruesi të ekzekutojë komanda, të më dërgojë rezultatet dhe t'i analizojë ato, unë mund ta bëj gjithçka vetë!

Kolegët fillojnë të më kenë pak zili. Gjatë drekës diskutojmë për kërkesën, por askush nuk ka ide se çfarë po ndodh. Për fat, vetë përdoruesi tashmë ka marrë masa për të lehtësuar pasojat dhe nuk po nxiton, kështu që kemi kohë të analizojmë problemin. Dhe pasi kemi një imazh, mund të kryejmë çdo test që na intereson. Shkëlqyeshëm!

Duke u kthyer një hap mbrapa

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

Vendosa ta përdor këtë pyetje HR për problemin aktual. Në thelb, kur përpiqeni të përcaktoni emrin DNS, ndodhin këto:

  1. Aplikacioni thërret bibliotekën sistemore, për shembull libdns
  2. libdns kontrollon konfigurimin e sistemit se cili server DNS duhet të përdoret (në diagram është 169.254.169.254, serveri i metadatas)
  3. libdns përdor thirrjet 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ë dyja drejtimet
  4. Përmes ndërfaqes sysctl mund të konfigurohet stoku UDP në nivelin e bërthamës
  5. Bërthama ndërvepron me harduerin për të dërguar paketa në rrjet përmes ndërfaqes rrugore
  6. Hipervizori kap dhe transmeton paketën te serveri i metadatas gjatë kontaktit me të
  7. Serveri i metadatas me magjinë e tij përcakton emrin DNS dhe në të njëjtën mënyrë kthen përgjigjen

Historia për paketat DNS të humbura nga mbështetje teknike Google Cloud
Të kujtojmë se cilat hipoteza kemi shqyrtuar deri tani:

Hipoteza: Bibliotekat janë të prishura

  • Testi 1: ekzekuto në sistem strace, kontrollo nëse dig thërrit thirrjet sistemore të sakta
  • Rezultati: thirrjet sistemore të sakta thirren
  • Testi 2: përmes srapy kontrollo nëse mund të përcaktojmë emrat duke anashkaluar bibliotekat sistemore
  • Rezultati: mundemi
  • Testi 3: ekzekuto rpm –V në paketën libdns dhe md5sum skedarët e bibliotekës
  • Rezultati: kodi i bibliotekës është plotësisht identik me kodin në sistemin operativ funksional
  • Testi 4: të monosh imazhin e sistemit rrënor të përdoruesit në VM pa këtë sjellje, ekzekuto chroot, shiko nëse DNS funksionon
  • Rezultati: DNS funksionon siç duhet

Përfundimi bazuar në testet: problemi nuk është në biblioteka

Hipoteza: Ka një gabim në konfigurimin e DNS

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

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

Hipoteza: bërthama është e dëmtuar

  • Testi: instalo një bërthamë të re, kontrollo nënshkrimin, ripërtri
  • Rezultati: sjellje analogjike

Përfundimi bazuar në 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: kontrollo konfigurimin e fireuallit
  • Rezultati: fireualli lejon paketat DNS si në host ashtu edhe në GCP
  • Testi 2: kap trafik dhe ndiq regjistrimin e saktë të dërgimit dhe kthimit të kërkesave DNS
  • Rezultati: tcpdump konfirmon marrjen e paketave kthyes nga hosti

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

Hipoteza: serveri i metadatas nuk funksionon

  • Testi 1: kontrollo logjet e serverit të metadatas për anomalitë
  • Rezultati: në logje nuk ka anomali
  • Test 2: go around the metadata server through dig @8.8.8.8
  • Result: resolution fails even without using the metadata server

Përfundimi bazuar në testet: the problem is not with the metadata server

Përfundimi: we tested all subsystems except runtime settings!

Diving into the core runtime settings

To configure the core runtime, you can use command line options (grub) or the sysctl interface. I looked into /etc/sysctl.conf and just think, I found several custom settings. Feeling like I grasped something, I discarded all non-network or non-tcp settings, ending up with a handful of settings net.core. Then I turned to where the VM permissions are located and began applying settings one after another from the broken VM until I found the culprit:

net.core.rmem_default = 2147483647

Here it is, the DNS configuration break! I found the weapon of crime. But why is this happening? I still needed a motive.

The basic buffer size for DNS packets is set through net.core.rmem_default. The typical value ranges somewhere around 200KiB, however, if your server receives many DNS packets, you may increase the buffer size. If at the moment a new packet arrives, the buffer is full, for instance, because the application does not process it quickly enough, you will start to lose packets. Our client rightly increased the buffer size as they feared data loss since they were using an application for metric collection through DNS packets. The value they set was the maximum possible: 231-1 (if you set 231, the kernel returns 'INVALID ARGUMENT').

Suddenly I realized why nmap and scapy worked correctly: they used raw sockets! Raw sockets differ from regular ones: they bypass iptables, and they are not buffered!

But why does a 'too large buffer' cause problems? It clearly does not work as intended.

At this point, I could reproduce the problem on several kernels and many distributions. The problem was already manifesting on kernel 3.x and now was also showing on kernel 5.x.

Indeed, when executing

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

DNS stopped working.

Fillova kam kërkoja vlerat funksionale përmes një algoritmi të thjeshtë të kërkimit binar dhe zbulova se sistemi funksiononte me 2147481343, megjithatë ky numër për mua ishte një grup i paqartë numrash. I propozova klientit të provonte këtë numër, dhe ai u përgjigj se sistemi funksionoi me google.com, por ende jepte gabim me domainet e tjera, kështu që vazhdova hetimin tim.

Kam instaluar dropwatch, një mjet që do të kishte qenë e mençur ta përdorja më parë: ai tregon se ku konkretisht në bërthamë arrin pakoja. Problemi doli të ishte funksioni udp_queue_rcv_skb. Kam shkarkuar burimet e bërthamës dhe kam shtuar disa funksione printk për të ndjekur se ku konkretisht arrin pakoja. Shpejt zbulova kushtin e nevojshëm nëse, dhe për një kohë thjesht shikoja në të, pasi pikërisht atëherë gjithçka përfundimisht filloi të përputhej në një imazh të plotë: 231-1, një numër pa kuptim, një domain që nuk funksiononte... Problemi ishte në një copë kodi në __udp_enqueue_schedule_skb:

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

Kujdes:

  • rmem ka tipin int
  • size ka tipin u16 (int i dhjetëbitësh jo i nënshkruar) dhe ruan madhësinë e paketës
  • sk->sk_rcybuf ka tipin int dhe ruan madhësinë e tamponit që sipas përkufizimit është e barabartë me vlerën në net.core.rmem_default

Kur sk_rcvbuf afrohet me 231, grumbullimi i madhësisë së paketës mund të çojë në tejkalim të numrave të plotë. Dhe për shkak se është int, vlera e tij bëhet negative, kështu që kushti bëhet i vërtetë kur duhet të jetë i gabuar (më shumë rreth kësaj mund të mësoni nga linkun).

Gabimi rregullohet në mënyrë triviale: duke e transformuar në unsigned int. Kam zbatuar rregullimin dhe kam rinisur sistemin, pas së cilës DNS filloi të funksiononte sërish.

Shija e fitores

Kam kaluar zbulimet e mia te klienti dhe kam dërguar LKML patch-in e bërthamës. Jam i kënaqur: çdo copëz enigme u bashkua në një tërësi, mund të shpjegoj saktësisht pse kemi vërejtur atë që kemi vërejtur, dhe më e rëndësishmja, arritëm të gjejmë zgjidhjen e problemit përmes punës së përbashkët!

Duhet pranuar se rasti doli të ishte i rrallë, dhe fatmirësisht nga përdoruesit na vijnë rrallë kërkesa kaq komplekse.

Historia për paketat DNS të humbura nga mbështetje teknike Google Cloud


Burimi: habr.com

Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS 🔥 Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS | ProHoster