Najgłupszy błąd w mojej historii
No cóż, od dobrych kilku lat administruję za pieniądze bandą Linuksowych maszynek. Jedna z nich robi za główny router dla osiedlóweczki na kilka tysięcy komputerów. A ostatnio przez kilka tygodni szukałem paskudnego błędu w skryptach, które dla tejże zdziałałem. Błąd był nietypowy, nieuchwytny i znalezienie go było problemem nie tylko dla mnie(link usunięty na życzenie linkowanego)...
Zasada działania ogólnie pojętego oskryptowania routera Linuksowego jest prosta jak konstrukcja cepa:
1) Podnieś dodatkowe adresy IP na interfejsach
2) Ustaw routing
3) Ustaw masakarady
4) Ustaw ograniczenia transferów
Co w praktyce przekłada się na dobre kilka tysięcy linijek dość schematycznego basha. Oczywiście nikt tego ręcznie nie pisze, ale w tym konkretnym przypadku sam schemat też ma z tysiąc linijek. No i oczywiście wkradł mi się tam błąd.
Błąd straszliwy, bo jego debugowanie było dość uciążliwe. Otóż po odpaleniu tych nowych skryptów wszystko działało, zauważalnie z resztą lepiej niż przed odpaleniem, przez około 20 minut. Po tych ~20 minutach, bez żadnego ostrzeżenia, klienci tracili łączność ze światem. Żeby było fajniej, router nie tracił połączenia z żadnym z łącz - można było choćby się na niego zalogować z każdej strony. Ponadto klientom przechodził ruch ICMP (ping, traceroute), jednak IP już nie. Z nasuwających się hipotez: nic się nie zmieniało w żadnych ustawieniach około 20 minuty, nie ulegał również przepełnieniu conntrack.
Kto zgadnie, co udało mi się spieprzyć? ;)
09 stycznia 2009 o 22:01:11
W cronie gdzieś był "konkurencyjny" skrypt?
09 stycznia 2009 o 22:01:53
Był, ale sam w porę wpadłem na to, by go stamtąd wyprosić. To nie to.
09 stycznia 2009 o 22:05:21
Jakaś regułka powodowała zapętlenie pakietu, który zwykle wpadał po 20 minutach?
Albo nie, lepiej: limit transferu ustawiony jeden na całą sieć? Gdy wszyscy razem przepchali np. 10GB, to mieli sieć odciętą?
09 stycznia 2009 o 22:08:27
Znowu nie zgadłeś. Nic się nie zapętlało, a w naszej osiedlóweczce nie ma limitów miesięcznych. Nie łapał ich też system antywirusowy.
09 stycznia 2009 o 22:13:38
Hm, a klienci podłączeni byli przez IP wklepane na sztywno, czy DHCP?
09 stycznia 2009 o 22:15:57
Klienci mają IP z sieci wewnętrznej przydzielane przez DHCP. Ale to działało bez zarzutu.
09 stycznia 2009 o 22:24:27
Jak ktoś zgadnie szybciej niż "kilka tygodni" to dostaje Twoją posadkę? ;-)
09 stycznia 2009 o 22:25:48
Raczej taką samą jak moja. Albo szanse na kilka zleceń przy podobnych okazjach. Albo stwierdzę, że wywnioskował to z moich podpowiedzi.
09 stycznia 2009 o 22:26:35
Ja to za miękki między uszyma jestem, tak tylko pytałem ;-)
09 stycznia 2009 o 22:42:41
jakis timeout po 20 minutach?
09 stycznia 2009 o 22:45:53
No samo to, że po 20 minutach przestawało działać, można nazwać timeoutem... Ale jeśli o to pytasz, to nie, żaden czas w /proc nie był ustawiony na 20 minut. Do tego - to nie było równe 20 minut, a coś między 18 a 25, ze średnią w okolicach 20.
09 stycznia 2009 o 22:59:29
Defaultowy czas połączenia był ustawiony na 20 minut? Tak jest w moim ASUS AP-WiFi solo który potrafi przełączyć kartę Realteka w trym AccessPointa?
09 stycznia 2009 o 23:00:27
Nie wiem co tutaj rozumiesz przez ten defaultowy czas połączenia. Możesz doprecyzować?
09 stycznia 2009 o 23:05:08
Po ~20 minutach aktywował się botnet!
09 stycznia 2009 o 23:05:42
Weź mi proszę nic o botnetach nie pisz...
09 stycznia 2009 o 23:08:21
zablokowana szeroka, dosc wysoka ranga portow? ;)
09 stycznia 2009 o 23:09:04
Nie, tylko Microsoft trio i może z dwa inne porty.
09 stycznia 2009 o 23:09:53
Ograniczenie transferu ścinało łącze?
09 stycznia 2009 o 23:12:08
to nie mam pojecia co, ja kiedyś tak zablokowałem użytkowników windows, ktorych porty zrodlowe po kilkunastu minutach byly strasznie wysokie i akurat wpasowywaly sie w moja regulke. a ja sie dziwilem, ze u mnie na linuksie dziala ;)
09 stycznia 2009 o 23:14:35
Właśnie, to mi przypomina, że miałem sprawdzić, czy Windows da sobie pozajmować wszystkie porty po UPnP.
09 stycznia 2009 o 23:15:32
D4rky: nie. Również ściągnięcie ograniczeń nie pomagało.
urban: nie działało również użytkownikom korzystającym z Linuksa/OSX/*BSD/telefonu/tostera... No, z tych ostatnich to żaden nie zdążył się poskarżyć ;)
09 stycznia 2009 o 23:19:18
@lRem: To nie była kwestia czegoś, co z założenia miało chronić, a przez błędy w realizacji po prostu się sypało? ;]
09 stycznia 2009 o 23:21:19
Nie. Podpowiem szerzej: nie było to nic z okolic firewalla (rozumianego jako wycinanie portów wirusów, ograniczanie spamu, wycinanie kontrolerów botnetów czy inne tego typu dziwactwa).
09 stycznia 2009 o 23:30:11
Jakiś czynnik ludzki miał wpływ? Ponoć to człowiek jest najbardziej zawodny.
09 stycznia 2009 o 23:31:25
Czynnik ludzki w postaci pani Zosi od zamiatania potykającej się o kabel - nie. Czynnik ludzki w postaci błędu piszącego/wdrażającego skrypty - tak.
09 stycznia 2009 o 23:32:50
Może gdzieś jakąś zmienną wykorzystałeś do różnych celów? :>
09 stycznia 2009 o 23:34:05
Nie. Nie była to też żadna literówka (acz dużo czasu spędziłem szukając takowej).
09 stycznia 2009 o 23:35:15
A moze to sie wywalalo jak skrypt konczyl dzialanie?
09 stycznia 2009 o 23:39:27
@lRem: Te okolice 1200s są istotne? :P
09 stycznia 2009 o 23:44:14
D4rky: zależy który skrypt, bo było rozbite na kilka funkcjonalnych... Ale to by było albo 8, albo około 40 sekund.
Zal: tak, ale sam jeszcze nie doszedłem do tego czemu to akurat okolice 1200s są.
Ale powoli zbliżamy się do końca przesłanek, które odkryłem w czasie szukania tego błędu ;)
10 stycznia 2009 o 00:02:52
Co prawda już dano iptables się nie bawiłem, ale moją niepewność wzbudzają alternatywne adresy IP, przynajmniej ja bym je sprawdził w pierwszej kolejności - pamiętam, że kiedyś z nimi miałem spore problemy :-)
10 stycznia 2009 o 00:16:35
Co rozumiesz przez alternatywne? I co byś sprawdził?
10 stycznia 2009 o 00:25:28
Alternatywne adresy IP (tzw. aliasy):
192.168.0.1 - eth0
192.168.1.1 - eth0:1
192.168.2.1 - eth0:2
Z tego co pamiętam, to lubią być problemy przy ustawianiu limitów przepustowości - albo domyślnie wszystko było przepuszczane przez eth0 (chyba htb, albo hfsc nie pozwalało na ustawienie na aliasach, albo dziwnie to obliczało). Możliwe, że błąd konfiguracji był tutaj i na początku wszystko działało, a jak 'żetony' się skończyły, to ruch zamierał. Stąd różny czas, ale oscylujący wokół 20 minut.
Obstawiam, że tutaj coś mogło by być nie tak. Ale to tylko moje domysły, bo ostatnio tą tematyką zajmowałem się dobre 2 lata temu :-)
10 stycznia 2009 o 00:27:38
Nie używamy aliasów, nie ma to związku z HTB (nie używamy HFSC). Ale podpowiem - jesteś na razie najbliżej z wszystkich tutaj i na IRC-u.
10 stycznia 2009 o 00:31:33
trochę to nie uczciwa zgaduj zgadula, ale spróbuję 'strzelić' raz jeszcze. Może to kwestia ustawień stosu tcp/ip na serwerze ?
Jakie były ustawienia tych parametrów ? (wycinek z orginalnego rc.firewall - www.inet.ll.pl):
---------------------
# Limitowanie sesji tcp
/bin/echo "30" > /proc/sys/net/ipv4/tcp_fin_timeout
/bin/echo "2400" > /proc/sys/net/ipv4/tcp_keepalive_time
/bin/echo "0" > /proc/sys/net/ipv4/tcp_window_scaling
/bin/echo "0" > /proc/sys/net/ipv4/tcp_sack
/bin/echo "20480" > /proc/sys/net/ipv4/ip_conntrack_max
/bin/echo "20" > /proc/sys/net/ipv4/ipfrag_time
/bin/echo "1280" > /proc/sys/net/ipv4/tcp_max_syn_backlog
# Tcp timestamps protection
/bin/echo "1" > /proc/sys/net/ipv4/tcp_timestamps
--------------
10 stycznia 2009 o 00:34:31
Powiedz i nie trzymaj nas w niepewności, bo sam jestem ciekaw :)
10 stycznia 2009 o 00:35:08
talen: Poszedłeś w maliny...
10 stycznia 2009 o 00:35:30
iRem: no to idę spać :-)
10 stycznia 2009 o 00:50:42
Zbyt niski typ zmiennej zliczającej transfer? W sensie, że jak się wyczerpały ograniczenia np. Integer'a (nie wiem, jakie tam są typy zmiennych), to kończyło połączenie? Albo z innej beczki - nie wgrałeś wszystkich plików na serwer ;)
10 stycznia 2009 o 01:02:13
Dobra, to rozwiązaniem zagadki jest: punkt 1 załączonego pseudokodu.
Dokładniej: adresy najpierw czyszczę, potem dodaję. Przez błąd rzeczowy jeszcze w bazie danych w ogóle nie dodawałem adresów wykorzystywanych przez klientów. Czyli w wyniku komendy /ip a l/ widziane były tylko te ip, na których odpowiada router. Jednak mimo to, przez ~20 minut Linux pozwala przepychać ruch przez numery IP które nie są już przypisane (ale wcześniej były) do kart. Po tych ~20 minutach wszystkie kilka tysięcy zdjętych ip w tym samym momencie milknie.
Te kilkadziesiąt komentarzy w próbie odgadnięcia przynajmniej mnie trochę pocieszyło. Widać przeanalizowanie wyjścia /ip a l/ nie jest typowym pierwszym pomysłem przy tych objawach :)
Ponadto odpowiadam na jeszcze jedno pytanie spoza bloga: nie wystarczyło zrobić diffa między nowymi a starymi ustawieniami, bo nie miały linijek wspólnych. Działają na różnych ogólnych zasadach, inaczej wykonane jest prawie wszystko.
10 stycznia 2009 o 11:38:18
IRem, założę się, że rozwiązanie przyszło Ci do głowy wtedy, gdy przestałeś o tym myśleć.
10 stycznia 2009 o 11:41:39
Heh, nie do końca. Generalnie to studiuję na dwóch kierunkach i przestać o tym myśleć miałem duuużo okazji w międzyczasie.
Tak przy okazji: ta pierwsza literka mojego nicku to nie jest 'I'...
10 stycznia 2009 o 15:44:29
tak poczytałem doszedłem do końca i mam dylemat:
w tych cudzysłowach na końcu masz
duże "i" czy małe "L"?
10 stycznia 2009 o 17:37:53
"Ale podpowiem - jesteś na razie najbliżej z wszystkich tutaj i na IRC-u."
Że tak offtopowo pozwolę sobie spytać: na jakim kanale? :] (i w jakiej sieci)
10 stycznia 2009 o 17:46:15
Na IRCNecie, ale nie powiem więcej, bo znowu będzie awantura ;)
10 stycznia 2009 o 17:59:25
Jakie znowu? Jaka awantura? ;-)
10 stycznia 2009 o 18:49:09
…i ktoś tam odpowidział? O o.
10 stycznia 2009 o 18:51:16
Na poprawną odpowiedź wpadła jedna osoba - mlp. Prawdopodobnie dlatego, że zamiast wytężać swoją znajomość sieci komputerowych (których zna tyle, na ile ją na studiach zmusili), przeczytała treść zagadki i przeprowadziła logiczną eliminację z użyciem komentarzy...
11 stycznia 2009 o 22:59:32
Miałem kiedyś problem taki sam w skutkach, z tą tylko różnicą, że: 1) było to na FreeBSD 2) routing blokował się nie po 20 minutach, tylko po jakichś 2 tygodniach (i weź tu sobie człowieku zdebugguj coś takiego...).
Problemem była stara wersja ipfilter, tj. nowsza w jądrze, starsza w zainstalowanym oprogramowaniu.