piątek, stycznia 20, 2012

ARP flux problem solution

Jakieś dwa tygodnie temu miałem pewien pomysł jak zutylizować jeden z serwerów, którym zarządzam docelowo rozszerzając usługę DHCP na trzy podsieci. Tak się składa, że maszyna posiada 4 porty gigabitowe i działa na Linuksie, więc nie powinno być problemów. Wymyśliłem sobie, że podepnę serwer do switcha w następujący sposób:


Położyłem kable, podpiąłem wszystko i zadowolony z siebie odpaliłem terminal. Jakie było moje zdziwienie, kiedy po podnoszeniu eth1 rozpoczęły się anomalie sieciowe. Połączenie lagowało, pingi się gdzieś nagle gubiły itd. Pomyślałem, że może to coś z trasowaniem. Długo pytałem wujka Google co by mogło się dziać, przy okazji ucząc się o takich rzeczach jak dostęp rozłączny i agregacja portów. Z dobry tydzień gryzłem się z tym problemem. Głównie dlatego, że na eksperymenty mogłem sobie pozwolić tylko w godzinach wieczorowych, kiedy serwer nie był obłożony. Dopiero dziś natknąłem się na przyczynę i rozwiązanie problemu. Przyczyna była trywialna w swojej naturze - domyślne ustawienia jądra linuksowego do obsługi ARP. Normalnie sieciowa dyskusja protokołem ARP powinna wyglądać tak:

KomputerA: "Szukam adresu 192.168.2.1 do partyjki warcrafta, który z was to?"
KomputerB: "To ja. Mój adres MAC to 00:11:22:33:44:55."

Domyślnie na zapytanie ARP odpowiedź wysyłana jest na wszystkich interface'ach, a ponieważ w moim wypadku oba interface'y są podłączone do tej samej przełącznicy skutkuje to niezłym bigosem. Dyskusja zmienia się w rozmowę z schizofrenikiem:

KomputerA: "Szukam adresu 192.168.2.1 do partyjki warcrafta, który z was to?"
KomputerB: "Cześć, znajdziesz mnie pod adresem MAC 00:11:22:33:44:55, albo AA:BB:CC:DD:EE:FF. A może to było jednak 00:11:22:33:44:55?"

Rozwiązaniem jest wymuszenie odpowiedzi na zapytania ARP tylko na tej karcie sieciowej na której odebrano zapytanie. Całość sprowadza się do wykonania:

sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.all.arp_announce=2


Aby zmiany były trwałe należy zrobić stosowne wpisy w pliku
/etc/sysctl.conf

net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.all.arp_announce=2