Split Tracking, v0.12 pl Pomysł śledzenia splitów to pamiętanie kanałów tak długo, jak długo istnieją na każdym serwerze, przy założeniu, że kanały istnieją także na serwerach odsplitowanych. To nam pozwoli na uniemożliwienie hackowania opów przez splitowanie serwera. Załóżmy, że sieć jest tylko 2.11 (serwerów przed 2.11 i tak nie jesteśmy w stanie śledzić na split, zwłaszcza chodzi o maski). Wszystkie kanały by miały dodatkową listę serwerów (albo po prostu liczby (tj. SID-y skonwertowane base36) lub wskaźniki do dokładnych pozycji w liście lub tabeli wszystkich znanych serwerowi SID-ów (w takiej tabeli można trzymać dodatkowe informacji, np. kiedy ostatnio splitował), które zaginęły w splicie, a które posiadały jakichkolwiek klientów na tym kanale. Przykład 1: A --- B #ab: a1, a2, b1, b2 / \ / \ #a: a1, a2 a1 a2 b1 b2 #b: b1, b2 Następuje split. Sytuacja na serwerze A: i. serwera A widzi, że serwer B zniknął, użytkownicy b1 i b2 zniknęli; serwer musi popatrzeć się na kanały, na których siedzieli ci użytkownicy i zaznaczyć je jako odsplitowane ii. w tym przypadku kanały #ab i #b zostaną oznaczone jako odsplitowane iii. to także oznacza, że /cycle ani /join na te kanały nie będzie miał efektu tworzenia kanału, tj. nie zostanie przyznany op; losowy reop (+r) nie może działać, choć z reopem pasujących do +R nie powinno być problemu iv. kanały oznaczone jako odsplitowane, kiedy staną się puste (albo w trakcie splitu, albo gdy ostatni klient wyjdzie) będą zablokowane (żaden użytkownik nie będzie mógł wejść), a wszystkie ich tryby usunięte[1] v. użytkownicy mogą tworzyć nowe kanały (które nie istniały przed splitem) i normalnie otrzymywać opa [1] Możemy albo trzymać wszystkie tryby i pozwolić wszystkim, którzy mogą, wejść na kanał, bez opa, oczywiście (zużywa trochę pamięci i po netjoin z powrotem odsyła istniejące tryby, co może być uznane za złe) LUB możemy nie trzymać trybów w ogóle, co wymaga zablokowania kanału, żeby abuserzy nie mogli wejść i po zakończeniu splitu nie móc podejrzeć kto siedzi na kanale (ani jaki jest klucz). Co lepsze? Na razie wybieramy blokowanie pustego kanału. Sytuacja na serwerze B: jak wyżej, tylko kanał oznaczone jako odsplitowane to #ab i #a. Koniec splitu. (Oczywiście EOBACK, nie po prostu SERVER.) Sytuacja na serwerze A: i. musimy przejrzeć wszystkie kanały i usunąć serwer B z listy odsplitowanych serwerów dla każdego kanału ii. jeśli taka lista dla kanału zostaje pusta, wracamy do normalności, w przeciwnym przypadku kanał jest ciągle odsplitowany (w nieskończoność, jeśli serwer nie wróci) Przykład 2: A --- B --- C #ab: a1, a2, b1, b2, c1 / \ / \ / \ #a: a1, a2 a1 a2 b1 b2 c1 c2 #b: b1, b2, c2 Split między B i C. Przegląd sytuacji: Kanały #b i #ab zostają oznaczone jako odsplitowane na serwerach A, B i C. Kanał #a zostaje pusty, zablokowany i oznaczony jako odsplitowany na serwerze C. Kolejny split, między A i B. Sytuacja: I. Serwer A i. #a nie jest oznaczony jako odsplitowany ii. #b pusty, zablokowany, odsplitowany z B, C iii. #ab odsplitowany z B, C II. Serwer B i. #a pusty, zablokowany, odsplitowany z A ii. #b odsplitowany z C iii. #ab odsplitowany z A, C II. Serwer C i. #a pusty, zablokowany, odsplitowany z A ii. #b odsplitowany z B iii. #ab odsplitowany z A, B Koniec splitu między B i C. Jako że C widzi wracające B (ale nie A), usuwa znak splitu z B ze wszystkich kanałów. Analogicznie robi B. Sytuacja: I. Serwer A i. #a nie odsplitowany ii. #b pusty, zablokowany, odsplitowany z B, C iii. #ab odsplitowany z B, C II. Serwer B i. #a pusty, zablokowany, odsplitowany z A ii. #b nie odsplitowany iii. #ab odsplitowany z A II. Serwer C i. #a pusty, zablokowany, odsplitowany z A ii. #b nie odsplitowany iii. #ab odsplitowany z A Użytkownicy na B i C nie mogą wejść na #a (ERR_UNAVAILRESOURCE), ale bez problemów mogą /cycle #b i normalnie używać (oprócz losowego +r) kanał #ab -- chyba że wyjdą z niego wszyscy (wtedy sytuacja będzie taka, jak na #a). Użytkownicy na A mogą bez ograniczeń używać kanału #a, a nie mogą wejść na #b oraz mogą używać #ab tak jak klienci na B i C. Problem 1. Nowe (lub restartowane) serwery. O ile serwery takie mogą wpuszczać klientów przed dołączeniem do sieci, to nie wolno im wpuszczać klientów na żadne kanały (no, z wyjątkiem lokalnych i !kanałów). Musimy wysłać im obecny stan sieci, tj. wszystkie kanały razem z ich listami splitów. Do tego potrzeba nowej komendy, powiedzmy SRVSPLIT (lepsza jakaś nazwa? SJOIN? SMISS? SPLIT?) Tylko serwery bezpośrednio podłączone powinny wysyłać taką listę w trakcie burstu. Serwery otrzymujące powinny taką listę rozpropagować do innych serwerów podłączonych do nich (najpierw usuwając z listy ich własny SID). Przykład 3: A --- B #ab: a1, a2, b1, b2 / \ / \ #a: a1, a2 a1 a2 b1 b2 #b: b1, b2 Split między A i B. Po chwili do A podłącza się server C. A --- C #ab: a1, a2 / \ #a: a1, a2 a1 a2 #b: Serwer A musi wysłać do serwera C takie informacje: :A NJOIN #ab: a1, a2 :A SRVSPLIT #ab: B :A NJOIN #a: a1, a2 :A SRVSPLIT #b: B Teraz i A, i C wiedzą, że kanały #ab i #b są odsplitowane z B. Na #ab mogą normalnie działać (możliwy kierunek ataku: DoS-em odsplitować serwer, wpuścić klony, zaopować, poczekać na netjoin, walczyć większą ilością klonów), chyba że, oczywiście, zostawią pusty kanał. Kanał #a zaś jest do dowolnego użycia. Problem 2. Zamknięte serwery. Takie muszą wysłać (nową) komendę DIE, która powie reszcie sieci, że ten serwer i jego klienci już nie wrócą, więc nie trzeba o nich pamiętać. Jeśli serwer zniknie z sieci bez poprawnego DIE, potrzebna będzie interwencja operatora (dostawienie serwera i wyjście z DIE), w przeciwnym wypadku kanały, które miały użytkowników na tym serwerze, zostaną na zawsze odsplitowane z nim oraz, jeśli opustoszeją, całkowicie zamknięte. Problem 3. Dwa zrestartowane serwery. A --- B --- C #ab: a1, a2, b1, b2, c1 / \ / \ / \ #a: a1, a2 a1 a2 b1 b2 c1 c2 #b: b1, b2, c2 Serwery B i C splitują. A #ab: a1, a2 / \ #a: a1, a2 a1 a2 #b: Problem 3a. Normalnie. Serwery ślą komendę DIE, reszta sieci wie, że ich klienci nie wrócą. Kanał #b znika, kanały #ab i #a są do dowolnego użycia. Problem 3b. Nieprawidłowo. Serwerom nie udało się wysłać komendy DIE. Reszta sieci myśli, że ich klienci wrócą. Kanały #a działa bez przeszkód, kanał #ab jest w splicie z B i C, a kanał #b jest pusty i zamknięty, w splicie z B i C. Serwery B i C wracają i łączą się najpierw między sobą. B --- C Mamy problem. EOBACK zostały otrzymane, ale nie mają stanu sieci, żadnych kanałów. Powinniśmy uważać, że to dalej jest split i nie wpuszczać klientów na żadne kanały. (Hm, może znowu MIN_SERV_SPLIT?) W innym przypadku wszystkie kanały są w niebezpieczeństwie. Problem 3a. kont. A --- B --- C #ab: a1, a2 / \ #a: a1, a2 a1 a2 Serwer A wysyła wszystkie swoje kanały i SRVSPLIT. Klienci na B i C mogą korzystać z sieci. (Zważ też, że kanał #b zniknął.) Problem 3b. cont. A --- B --- C #ab: a1, a2 / \ #a: a1, a2 a1 a2 #b: Serwer A wysyła wszystkie swoje kanały i SRVSPLIT, tj.: #ab B, C #b B, C To prowadzi do 3a, gdyż serwery B i C usuwają z listy splitów już widoczne serwery B i C. Kanał #b robi się pusty, ale nie zablokowany, w związku z czym znika. Klienci na B i C mogą korzystać z irc normalnie. Problem N. O jakich scenariuszach nie pomyślałem? ------------- Notka 1. ZA PRZECIW utrzymywanie pozwala użytkownikom na wprowadza do sieci stare tryby; trybów korzystanie z kanału, a zużywa ciut więcej pamięci; nawet reop, jeśli pasują wymaga trzymania trybów na zawsze, do +R nawet jeśli użytkownicy sobie pójdą; pozwala ustawić więcej niż MAXBAN trybów :> blokowanie odporne na abuserów, po nieprzyjazne dla użytkowników kanału prostu nikt nie może wejść (kanału nie można w ogóle używać, na kanał; jeśli opustoszeje); używa nieco mniej pamięci; nie wprowadza do sieci starych trybów;