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ć? ;)

Komentarze

  • Jajcuś (2009-01-09 22:01:11):

    W cronie gdzieś był "konkurencyjny" skrypt?

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-09 22:01:53):

    Był, ale sam w porę wpadłem na to, by go stamtąd wyprosić. To nie to.

  • Jajcuś (2009-01-09 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ą?

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-09 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.

  • DeeTah (2009-01-09 22:13:38):

    Hm, a klienci podłączeni byli przez IP wklepane na sztywno, czy DHCP?

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-09 22:15:57):

    Klienci mają IP z sieci wewnętrznej przydzielane przez DHCP. Ale to działało bez zarzutu.

  • Bartosz "BTM" Szczec (2009-01-09 22:24:27):

    Jak ktoś zgadnie szybciej niż "kilka tygodni" to dostaje Twoją posadkę? ;-)

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-09 22:25:48):

    Raczej taką samą jak moja. Albo szanse na kilka zleceń przy podobnych okazjach. Albo stwierdzę, że wywnioskował to z moich podpowiedzi.

  • Bartosz "BTM" Szczec (2009-01-09 22:26:35):

    Ja to za miękki między uszyma jestem, tak tylko pytałem ;-)

  • D4rky (2009-01-09 22:42:41):

    jakis timeout po 20 minutach?

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-09 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.

  • anonim (2009-01-09 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?

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-09 23:00:27):

    Nie wiem co tutaj rozumiesz przez ten defaultowy czas połączenia. Możesz doprecyzować?

  • Michał Górny (2009-01-09 23:05:08):

    Po ~20 minutach aktywował się botnet!

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-09 23:05:42):

    Weź mi proszę nic o botnetach nie pisz…

  • urban (2009-01-09 23:08:21):

    zablokowana szeroka, dosc wysoka ranga portow? ;)

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-09 23:09:04):

    Nie, tylko Microsoft trio i może z dwa inne porty.

  • D4rky (2009-01-09 23:09:53):

    Ograniczenie transferu ścinało łącze?

  • urban (2009-01-09 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 ;)

  • Michał Górny (2009-01-09 23:14:35):

    Właśnie, to mi przypomina, że miałem sprawdzić, czy Windows da sobie pozajmować wszystkie porty po UPnP.

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-09 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ć ;)

  • Zal (2009-01-09 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? ;]

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-09 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).

  • mateyko (2009-01-09 23:30:11):

    Jakiś czynnik ludzki miał wpływ? Ponoć to człowiek jest najbardziej zawodny.

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-09 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.

  • Bartosz "BTM" Szczec (2009-01-09 23:32:50):

    Może gdzieś jakąś zmienną wykorzystałeś do różnych celów? :>

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-09 23:34:05):

    Nie. Nie była to też żadna literówka (acz dużo czasu spędziłem szukając takowej).

  • D4rky (2009-01-09 23:35:15):

    A moze to sie wywalalo jak skrypt konczyl dzialanie?

  • Zal (2009-01-09 23:39:27):

    @lRem: Te okolice 1200s są istotne? :P

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-09 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 ;)

  • talen (2009-01-10 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 :-)

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-10 00:16:35):

    Co rozumiesz przez alternatywne? I co byś sprawdził?

  • talen (2009-01-10 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 :-)

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-10 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.

  • talen (2009-01-10 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
    ————–

  • alchemyx (2009-01-10 00:34:31):

    Powiedz i nie trzymaj nas w niepewności, bo sam jestem ciekaw :)

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-10 00:35:08):

    talen: Poszedłeś w maliny…

  • talen (2009-01-10 00:35:30):

    iRem: no to idę spać :-)

  • marsjaninzmarsa (2009-01-10 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 ;)

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-10 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.

  • Scout (2009-01-10 11:38:18):

    IRem, założę się, że rozwiązanie przyszło Ci do głowy wtedy, gdy przestałeś o tym myśleć.

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-10 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’…

  • wikiyu (2009-01-10 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"?

  • BeteNoire (2009-01-10 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)

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-10 17:46:15):

    Na IRCNecie, ale nie powiem więcej, bo znowu będzie awantura ;)

  • BeteNoire (2009-01-10 17:59:25):

    Jakie znowu? Jaka awantura? ;-)

  • Michał Górny (2009-01-10 18:49:09):

    …i ktoś tam odpowidział? O o.

  • Remigiusz ‘lRem’ Modrzejewski (2009-01-10 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…

  • Void (2009-01-11 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.