Google Bulud texniki dəstəyindən əldən düşmüş DNS paketləri haqqında hekayə

Google Bloq Redaktorundan: Google Cloud Technical Solutions (TSE) mühəndislərinin dəstək sorğularınızı necə idarə etdiklərini heç düşünmüsünüzmü? TSE Texniki Dəstək Mühəndisləri istifadəçi tərəfindən bildirilmiş problemlərin mənbələrinin müəyyən edilməsi və düzəldilməsi üçün məsuliyyət daşıyırlar. Bu problemlərin bəziləri olduqca sadədir, lakin bəzən bir neçə mühəndisin diqqətini eyni anda tələb edən bir biletlə qarşılaşırsınız. Bu yazıda TSE işçilərindən biri bizə son təcrübəsindən çox çətin bir problem haqqında danışacaq - DNS paketlərinin çatışmaması halı. Bu hekayədə mühəndislərin vəziyyəti necə həll edə bildiklərini və səhvi düzəldərkən hansı yeni şeylər öyrəndiklərini görəcəyik. Ümid edirik ki, bu hekayə sizi nəinki köklü bir səhv haqqında məlumatlandırır, həm də sizə Google Cloud ilə dəstək biletinin verilməsinə gedən proseslər haqqında fikir verir.

Google Bulud texniki dəstəyindən əldən düşmüş DNS paketləri haqqında hekayə

Problemlərin aradan qaldırılması həm elm, həm də sənətdir. Hər şey sistemin qeyri-standart davranışının səbəbi haqqında fərziyyə qurmaqla başlayır, bundan sonra onun gücü yoxlanılır. Bununla belə, fərziyyə yaratmazdan əvvəl problemi dəqiq müəyyən etməli və dəqiq şəkildə formalaşdırmalıyıq. Əgər sual çox qeyri-müəyyən səslənirsə, onda hər şeyi diqqətlə təhlil etməli olacaqsınız; Bu, problemlərin həlli "sənətidir".

Google Bulud altında bu cür proseslər eksponent olaraq daha mürəkkəbləşir, çünki Google Bulud istifadəçilərinin məxfiliyini təmin etmək üçün əlindən gələni edir. Bu səbəbdən, TSE mühəndislərinin sistemlərinizi redaktə etmək, nə də istifadəçilər kimi konfiqurasiyaları geniş şəkildə görmək imkanı yoxdur. Buna görə də, fərziyyələrimizdən hər hansı birini yoxlamaq üçün biz (mühəndislər) sistemi tez bir zamanda dəyişdirə bilmərik.

Bəzi istifadəçilər hesab edir ki, biz avtomobil xidmətində mexanika kimi hər şeyi düzəldəcəyik və sadəcə olaraq bizə virtual maşının id-sini göndərəcəyik, halbuki əslində proses danışıq formatında baş verir: məlumat toplamaq, hipotezləri formalaşdırmaq və təsdiqləmək (və ya təkzib etmək), və nəticədə qərar problemləri müştəri ilə ünsiyyətə əsaslanır.

Sözügedən problem

Bu gün yaxşı bir sonu olan bir hekayəmiz var. Təklif olunan işin uğurlu həllinin səbəblərindən biri də problemin çox ətraflı və dəqiq təsviridir. Aşağıda birinci biletin surətini görə bilərsiniz (məxfi məlumatı gizlətmək üçün redaktə olunub):
Google Bulud texniki dəstəyindən əldən düşmüş DNS paketləri haqqında hekayə
Bu mesajda bizim üçün çoxlu faydalı məlumatlar var:

  • Xüsusi VM müəyyən edilmişdir
  • Problemin özü göstərilir - DNS işləmir
  • Problemin özünü göstərdiyi yerdə göstərilir - VM və konteyner
  • İstifadəçinin problemi müəyyən etmək üçün atdığı addımlar göstərilir.

Sorğu "P1: Kritik təsir - İstehsalda istifadə edilə bilməz xidmət" kimi qeydə alınıb, bu da "Günəşi izləyin" sxeminə uyğun olaraq 24/7 vəziyyətin daimi monitorinqi deməkdir (bu barədə ətraflı oxuya bilərsiniz). istifadəçi sorğularının prioritetləri), hər saat qurşağı dəyişikliyi ilə bir texniki dəstək qrupundan digərinə ötürülməsi ilə. Əslində, problem Sürixdəki komandamıza çatanda artıq dünyanı dövrə vurmuşdu. Bu vaxta qədər istifadəçi yumşaldıcı tədbirlər görmüşdü, lakin əsas səbəb hələ aşkar edilmədiyi üçün istehsalda vəziyyətin təkrarlanmasından qorxurdu.

Bilet Sürixə çatanda artıq əlimizdə aşağıdakı məlumatlar var idi:

  • Məzmun /etc/hosts
  • Məzmun /etc/resolv.conf
  • Buraxılış iptables-save
  • Komanda tərəfindən yığılmışdır ngrep pcap faylı

Bu məlumatlarla biz “araşdırma” və problemlərin aradan qaldırılması mərhələsinə başlamağa hazır idik.

İlk addımlarımız

İlk növbədə, biz metadata serverinin loglarını və statusunu yoxladıq və onun düzgün işlədiyinə əmin olduq. Metaməlumat serveri 169.254.169.254 IP ünvanına cavab verir və digər şeylərlə yanaşı, domen adlarına nəzarət etmək üçün məsuliyyət daşıyır. Biz həmçinin təhlükəsizlik duvarının VM ilə düzgün işləməsini və paketləri bloklamadığını iki dəfə yoxladıq.

Bu, bir növ qəribə problem idi: nmap yoxlaması UDP paketlərinin itirilməsi ilə bağlı əsas fərziyyəmizi təkzib etdi, buna görə də biz zehni olaraq daha bir neçə variant və onları yoxlamaq üçün yollar tapdıq:

  • Paketlər seçici şəkildə atılır? => iptables qaydalarını yoxlayın
  • Çox kiçik deyil? MTU? => Çıxışı yoxlayın ip a show
  • Problem yalnız UDP paketlərinə və ya TCP-yə də təsir edirmi? => Sürün dig +tcp
  • Qazılmış paketlər qaytarılırmı? => Sürün tcpdump
  • Libdns düzgün işləyirmi? => Sürün strace paketlərin hər iki istiqamətdə ötürülməsini yoxlamaq

Burada problemləri canlı olaraq həll etmək üçün istifadəçiyə zəng etmək qərarına gəlirik.

Zəng zamanı biz bir neçə şeyi yoxlaya bilərik:

  • Bir neçə yoxlamadan sonra biz iptables qaydalarını səbəblər siyahısından çıxarırıq
  • Şəbəkə interfeyslərini və marşrutlaşdırma cədvəllərini yoxlayırıq və MTU-nun düzgünlüyünü iki dəfə yoxlayırıq
  • Biz bunu kəşf edirik dig +tcp google.com (TCP) lazım olduğu kimi işləyir, lakin dig google.com (UDP) işləmir
  • Uzaqlaşaraq tcpdump hələ də işləyir dig, biz UDP paketlərinin geri qaytarıldığını görürük
  • Biz uzaqlaşırıq strace dig google.com və biz qazmağı necə düzgün çağırdığını görürük sendmsg() и recvms(), lakin ikincisi fasilə ilə kəsilir

Təəssüf ki, növbənin sonu gəlir və biz problemi növbəti saat qurşağına çatdırmaq məcburiyyətindəyik. Bununla belə, sorğu komandamızda maraq oyatdı və bir həmkarımız pis Python modulundan istifadə edərək ilkin DNS paketini yaratmağı təklif edir.

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

Bu fraqment DNS paketi yaradır və sorğunu metadata serverinə göndərir.

İstifadəçi kodu işlədir, DNS cavabı qaytarılır və proqram şəbəkə səviyyəsində problem olmadığını təsdiq edərək onu alır.

Başqa bir “dünya gəzintisi”ndən sonra sorğu komandamıza qayıdır və mən sorğunun yerdən yerə fırlanmasını dayandırarsa istifadəçi üçün daha rahat olacağını düşünərək onu tamamilə özümə köçürürəm.

Bu vaxt istifadəçi sistem şəklinin şəklini təqdim etməyə razıdır. Bu çox yaxşı xəbərdir: sistemi özüm sınamaq imkanı problemlərin aradan qaldırılmasını xeyli sürətləndirir, çünki mən artıq istifadəçidən əmrləri yerinə yetirməyi, nəticələri mənə göndərməyi və təhlil etməyi tələb etməli deyiləm, hər şeyi özüm edə bilərəm!

Həmkarlarım mənə bir az paxıllıq etməyə başlayırlar. Nahar zamanı biz konversiyanı müzakirə edirik, lakin heç kim nə baş verdiyini bilmir. Xoşbəxtlikdən, istifadəçinin özü artıq nəticələri azaltmaq üçün tədbirlər görüb və tələsmir, buna görə də problemi araşdırmağa vaxtımız var. Və bir imicimiz olduğundan, bizi maraqlandıran istənilən testləri keçirə bilərik. Əla!

Geri addım atmaq

Sistem mühəndisi vəzifələri üçün ən populyar müsahibə suallarından biri belədir: “Pinq etdiyiniz zaman nə baş verir www.google.com? Sual əladır, çünki namizəd qabıqdan tutmuş istifadəçi sahəsinə, sistem nüvəsinə və sonra şəbəkəyə qədər hər şeyi təsvir etməlidir. Gülürəm: bəzən müsahibə sualları real həyatda faydalı olur...

Bu HR sualını cari problemə tətbiq etmək qərarına gəldim. Kobud desək, DNS adını təyin etməyə çalışdığınız zaman aşağıdakılar baş verir:

  1. Tətbiq libdns kimi sistem kitabxanasını çağırır
  2. libdns, hansı DNS serveri ilə əlaqə saxlamalı olduğu sistem konfiqurasiyasını yoxlayır (diaqramda bu, 169.254.169.254, metadata serveridir)
  3. libdns UDP yuvası (SOKET_DGRAM) yaratmaq və hər iki istiqamətdə DNS sorğusu ilə UDP paketlərini göndərmək üçün sistem zənglərindən istifadə edir.
  4. Sysctl interfeysi vasitəsilə siz UDP yığınını kernel səviyyəsində konfiqurasiya edə bilərsiniz
  5. Kernel şəbəkə interfeysi vasitəsilə paketləri şəbəkə üzərindən ötürmək üçün aparatla qarşılıqlı əlaqədə olur
  6. Hipervisor paketi tutaraq metadata serverinə ötürür
  7. Metaməlumat serveri öz sehri ilə DNS adını müəyyən edir və eyni metoddan istifadə edərək cavab qaytarır

Google Bulud texniki dəstəyindən əldən düşmüş DNS paketləri haqqında hekayə
Artıq hansı fərziyyələri nəzərdən keçirdiyimizi sizə xatırlatmağa icazə verin:

Hipotez: Sınıq kitabxanalar

  • Test 1: sistemdə strace-i işə salın, qazmanın düzgün sistem zənglərini çağırdığını yoxlayın
  • Nəticə: Düzgün sistem zəngləri çağırılır
  • Test 2: sistem kitabxanalarından yan keçən adları təyin edə bildiyimizi yoxlamaq üçün srapy istifadə edin
  • Nəticə: bacarırıq
  • Test 3: libdns paketi və md5sum kitabxana fayllarında rpm –V işləyin
  • Nəticə: kitabxana kodu işləyən əməliyyat sistemindəki kodla tamamilə eynidir
  • Test 4: istifadəçinin kök sistemi şəklini bu davranış olmadan VM-ə quraşdırın, chroot-u işə salın, DNS-in işlədiyinə baxın
  • Nəticə: DNS düzgün işləyir

Testlərə əsaslanan nəticə: problem kitabxanalarda deyil

Hipoteza: DNS parametrlərində xəta var

  • Test 1: tcpdump-u yoxlayın və qazma əməliyyatından sonra DNS paketlərinin göndərilib düzgün şəkildə qaytarılıb-dönmədiyini yoxlayın
  • Nəticə: paketlər düzgün ötürülür
  • Test 2: serveri iki dəfə yoxlayın /etc/nsswitch.conf и /etc/resolv.conf
  • Nəticə: hər şey düzgündür

Testlərə əsaslanan nəticə: problem DNS konfiqurasiyası ilə bağlı deyil

Hipotez: nüvə zədələnmişdir

  • Test: yeni nüvəni quraşdırın, imzanı yoxlayın, yenidən başladın
  • Nəticə: oxşar davranış

Testlərə əsaslanan nəticə: nüvəsi zədələnmir

Hipotez: istifadəçi şəbəkəsinin səhv davranışı (və ya hipervizor şəbəkə interfeysi)

  • Test 1: Firewall parametrlərinizi yoxlayın
  • Nəticə: firewall həm hostda, həm də GCP-də DNS paketlərini keçir
  • Test 2: trafiki kəsin və DNS sorğularının ötürülməsi və qaytarılmasının düzgünlüyünə nəzarət edin
  • Nəticə: tcpdump hostun qaytarma paketləri aldığını təsdiqləyir

Testlərə əsaslanan nəticə: problem şəbəkədə deyil

Hipotez: metadata serveri işləmir

  • Test 1: metadata server qeydlərində anomaliyaları yoxlayın
  • Nəticə: qeydlərdə heç bir anomaliya yoxdur
  • Test 2: metadata serverindən keçin dig @8.8.8.8
  • Nəticə: Metadata serverindən istifadə etmədən belə qətnamə pozulur

Testlərə əsaslanan nəticə: problem metadata serverində deyil

Alt line: istisna olmaqla, bütün alt sistemləri sınaqdan keçirdik iş vaxtı parametrləri!

Kernel Runtime Parametrlərinə daxil olmaq

Kernel icra mühitini konfiqurasiya etmək üçün siz komanda xətti seçimlərindən (grub) və ya sysctl interfeysindən istifadə edə bilərsiniz. içəri baxdım /etc/sysctl.conf və sadəcə düşünün, mən bir neçə fərdi parametr kəşf etdim. Özümü bir şeyə yapışmış kimi hiss edərək, dağ parametrləri ilə qalan bütün qeyri-şəbəkə və ya qeyri-tcp parametrlərini ləğv etdim. net.core. Sonra mən VM-də host icazələrinin olduğu yerə getdim və günahkarı tapana qədər pozulmuş VM ilə parametrləri bir-bir tətbiq etməyə başladım:

net.core.rmem_default = 2147483647

Budur, DNS-i pozan konfiqurasiya! Mən qətl silahını tapdım. Bəs bu niyə baş verir? Mənə hələ də motiv lazım idi.

Əsas DNS paket bufer ölçüsü vasitəsilə konfiqurasiya edilir net.core.rmem_default. Tipik bir dəyər təxminən 200KiB-dir, lakin serveriniz çoxlu DNS paketləri qəbul edərsə, bufer ölçüsünü artırmaq istəyə bilərsiniz. Əgər yeni paket gələndə bufer doludursa, məsələn, proqram onu ​​kifayət qədər sürətlə emal etmirsə, siz paketləri itirməyə başlayacaqsınız. Müştərimiz məlumatların itirilməsindən qorxduğu üçün bufer ölçüsünü düzgün artırdı, çünki o, DNS paketləri vasitəsilə ölçüləri toplamaq üçün proqramdan istifadə edirdi. Onun təyin etdiyi dəyər mümkün olan maksimum idi: 231-1 (əgər 231-ə təyin olunarsa, nüvə “YANLIŞ ARQUMENT” qaytaracaq).

Birdən mən nmap və scapy-nin niyə düzgün işlədiyini başa düşdüm: onlar xam rozetkalardan istifadə edirdilər! Raw rozetkalar adi rozetkalardan fərqlidir: onlar iptables-dən yan keçir və onlar buferlənmir!

Bəs niyə "bufer çox böyük" problemlər yaradır? Aydındır ki, nəzərdə tutulduğu kimi işləmir.

Bu nöqtədə problemi çoxlu nüvələrdə və çoxlu paylamalarda təkrarlaya bildim. Problem artıq 3.x kernelində yaranıb və indi 5.x kernelində də yaranıb.

Həqiqətən, işə salındıqda

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

DNS işləməyi dayandırdı.

Sadə ikili axtarış alqoritmi vasitəsilə iş dəyərlərini axtarmağa başladım və sistemin 2147481343 ilə işlədiyini tapdım, lakin bu nömrə mənim üçün mənasız rəqəmlər toplusu idi. Müştəriyə bu nömrəni sınamağı təklif etdim və o cavab verdi ki, sistem google.com ilə işləyir, lakin yenə də digər domenlərdə xəta verir, ona görə də araşdırmamı davam etdirdim.

quraşdırmışam dropwatch, əvvəllər istifadə edilməli olan bir alət: o, paketin nüvənin harada bitdiyini dəqiq göstərir. Günahkar funksiya idi udp_queue_rcv_skb. Mən nüvə mənbələrini yüklədim və bir neçəsini əlavə etdim funksiyaları printk paketin tam olaraq harada bitdiyini izləmək üçün. Mən tez uyğun vəziyyəti tapdım if, və sadəcə olaraq bir müddət ona baxdı, çünki o zaman hər şey nəhayət bütöv bir mənzərədə birləşdi: 231-1, mənasız bir rəqəm, işləməyən bir domen... Bu, bir kod parçası idi. __udp_enqueue_schedule_skb:

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

Qeyd:

  • rmem int tiplidir
  • size u16 tiplidir (imzasız on altı bitlik int) və paket ölçüsünü saxlayır
  • sk->sk_rcybuf int tiplidir və tərifinə görə in dəyərinə bərabər olan bufer ölçüsünü saxlayır net.core.rmem_default

Zaman sk_rcvbuf 231-ə yaxınlaşır, paket ölçüsünü cəmləmək nəticələnə bilər tam daşması. Və bu int olduğundan onun dəyəri mənfi olur, ona görə də şərt yalan olduqda doğru olur (bu barədə ətraflı oxuya bilərsiniz: əlaqə).

Səhv mənasız bir şəkildə düzəldilə bilər: tökmə ilə unsigned int. Düzəlişi tətbiq etdim və sistemi yenidən başladım və DNS yenidən işlədi.

Qələbə zövqü

Tapıntılarımı müştəriyə çatdırdım və göndərdim LKML kernel patch. Mən məmnunam: tapmacanın hər bir parçası bir-birinə uyğun gəlir, müşahidə etdiyimizi niyə müşahidə etdiyimizi dəqiq izah edə bilərəm və ən əsası komanda işimiz sayəsində problemin həllini tapa bildik!

Bu işin nadir hallarda baş verdiyini etiraf etmək lazımdır və xoşbəxtlikdən istifadəçilərdən belə mürəkkəb sorğuları nadir hallarda alırıq.

Google Bulud texniki dəstəyindən əldən düşmüş DNS paketləri haqqında hekayə


Mənbə: www.habr.com

Добавить комментарий