SuperAdminka z licencją na strejsowanie

- Megi, chodź już! - banda wygłodniałych programistów przebierała nogami w boksach, czekając na sygnał, by rozpocząć szaleńczą gonitwę do cukierni Jagódka oferującej najlepsze w okolicy... kebaby wołowe.
- Idu, idu, jeszcze tylko zerknę na pocztę - w końcu nie sprawdzałam jej przez ostatnie 68 sekund.

From: SuperProgramista@DuzyPortal
To: SuperAdminka@MegiTeam
Subject: pilne! pilne! awaria!!1 pilne!11jeden

- Nie idu, to chyba pilne.

I must go! My planet needs me!

Otworzyłam maila...

Nasza strona strasznie wolno działa, nic w kodzie nie zmienialiśmy, pomocy!

Weszłam na stronę - faktycznie demonem prędkości to ona dziś nie jest. Na codzień w konfiguracji Nginx-Varnish-Django-Memcached, mimo dużego ruchu, daje radę.

From: SuperAdminka@MegiTeam
To: SuperProgramista@DuzyPortal
Subject: Re: pilne! pilne! awaria!!1 pilne!11jeden

> Nasza strona strasznie wolno działa, nic w kodzie nie zmienialiśmy, pomocy!

Panie SuperProgramisto, już sprawdzamy! 

Poklikałam chwilę po stronie, żeby zorientować się w sytuacji. Ciekawiło mnie czy problem dotyczy strony głównej czy wszystkich podstron, żądań do plików statycznych również czy tylko do treści dynamicznych oraz jaki pojawia się błąd:
- 502 (brak połączenia z backendem - w tym przypadku Varnishem)
- 503 zwracany przez Varnisha 
- czy może 504 (timeout połączenia z Varnishem).

W zależności od kodu błędu problem może być na innym poziomie - zawsze to jakiś punkt zaczepienia. Dostałam 503ką między oczy, static serwowany bezpośrednio przez Nginxa śmigał czyli coś się dzieje w okolicy Varnisha i Django.

Zalogowałam się na dedyka klienta i uruchomiłam top -cS. Pierwsze kilka procesów na liście to procesy Gunicorna (serwera aplikacji dla Django) jadące po CPU ile fabryka dała. Ok, to zawęża krąg podejrzanych, tylko jak dowiedzieć się co właśnie dzieje się w aplikacji?

Jest takie narzędzie, które z miejsca daje +10 do lansu w grupie Anonimowych Adminów, dzięki któremu debugowanie problemu to jak gra na "czitach" a klienci myślą, że wiesz wszystko. Narzędzie o którym wspominają stare manuale a sekretu obsługi strzegą tybetańscy brodaci hakerzy.

Spotkałam takiego hakera na swojej drodze. 2005 rok, Kraków. Był słoneczny maj a ja byłam jeszcze piękną i młodą ale Jeszcze-Nie-SuperAdminką. Ach, te romantyczne wieczory spędzone na wspólnym kompilowaniu kernela...

Ekhem... no więc wtedy nauczyłam się używać strace'a i dostałam licencję na strejsowanie.

No to niech strace. Wklepałam w konsolę

strace -s 10000 -ff -tt -o /root/strace -p PID1 -p PID2 -p PID3 -p PID4 -p PIDn

i podpięłam się do procesów Gunicorna. Dzięki temu mogę zobaczyć wywołania systemowe jakie wykonuje proces i tym samym podejrzeć, co właściwie robi (gdzie się łączy, jakie dane otrzymuje od serwera WWW, bazy danych, ile zajmuje mu komunikacja z innymi serwisami itp.). Polecenie wydawane setki razy wpisałam machinalnie, nie zastanawiając się nad tym, że

  • -s 10000 - oznacza, że każdy string (parametr albo zwracana wartość) może mieć maksymalnie 10000 znaków
  • -ff - każe śledzić również procesy potomne a nie tylko proces do którego się podpinam
  • -tt to data w przystępnym formacie (zamiast timestampa)
  • w -o podaję ścieżkę do pliku do którego będą logowane dane

PIDy procesów sprawdziłam poleceniem ps aux. Ponieważ procesów Gunicorna jest kilka a nie wiem który z nich obsłuży problematyczne wejścia na stronę, musiałam podpiąć się do wszystkich. Poklikałam chwilę po stronie, aby upewnić się, że nadal muli i będę mieć to w logach i ubiłam strace'a. Sprawdziłam co się zalogowało - ok. 100 MB w kilka minut. Auć! Teraz trzeba to ręcznie (ocznie?) przeglądnąć.

less /root/strace

Nie wiem właściwie czego szukam, ale będę wiedzieć, że to to, jak to znajdę.

page down

page down

page down

page down

page down

page down

page down

page down

page down

yyy

page up

To nie powinno TAK wyglądać:

Mówiłam już, że na strace można zobaczyć jakie dane proces otrzymuje? Zobaczyłam żądanie POST, formularz rejestracji nowego konta a te krzaczki to hasło użytkownika. Bingo! Skojarzyłam to, co widzę z niedawno wykrytym błędem w Django

http://niebezpiecznik.pl/post/dlugie-haslo-nie-zawsze-jest-dobre/

Klient na swoim koncie ma samodzielnie instalowane Django więc aktualizacja jest na jego głowie. Ja ze swojej strony na szybko mogę na poziomie serwera WWW wyciąć żądania POST wysyłane pod URLa rejestracji i logowania. Co też, nie chwaląc się, uczyniłam:

location /profil/register {
    if ($request_method = POST ) {
        return 405;
    }

}

location /profil/zaloguj {
    if ($request_method = POST ) {
        return 405;
    }

}

Dumna i blada napisałam do klienta.

From: SuperAdminka@MegiTeam
To: SuperProgramista@DuzyPortal
Subject: Re: pilne! pilne! awaria!!1 pilne!11jeden

DuzyPortal stał się celem ataku wykorzystującego błąd opisany tutaj

http://niebezpiecznik.pl/post/dlugie-haslo-nie-zawsze-jest-dobre/

Trzeba zaktualizować Django a na razie zablokowałam żądania POST.

Ponieważ klient jest SuperProgramistą nie tylko z nazwy to natychmiast dokonał aktualizacji i mogłam odblokować rejestrację i logowanie na stronie.

A później żyliśmy długo i szczęśliwie...

THE END

PS A po drugiej stronie to wyglądało tak:

devopsreactions.tumblr.com

18 listopada 2013



blog comments powered by Disqus