O autorovi:
Autorem tohoto článku je Petr Macek, kterého můžete kontaktovat na e-mailu petr.macek@kostax.cz.
Ve starších článcích jsem popsal, jak pomocí PHP ze SNMP vyčíst a prezentovat údaje z CDP a LLDP protokolu. Pro kompletní zjištění síťového okolí je možné tyto informace doplnit o údaje ze Spanning Tree protokolu. O STP se zde již psalo v článcích Cisco IOS 9 - Spanning Tree Protocol a Cisco IOS 10 - Rapid Spanning Tree Protocol. Pro správné pochopení doporučuji alespoň první článek přečíst. STP nám neřekne tolik údajů jako LLDP nebo CDP, ale na rozdíl od výše zmiňovaných protokolů je implementován snad ve všech přepínačích s managementem.
STP používá jako ID prvku nejnižší MAC adresu zařízení uloženou v OID 1.3.6.1.2.1.17.1.1.0
. STP MIB opět obsahuje informace o konfiguraci STP protokolu a tabulku se stavem portů. Jediným indexem této tabulky je index portu, který odpovídá indexu portu v IF-MIBu (intrface MIB) v tabulce portů (OID 1.3.6.1.2.1.2.2.1
).
Z celé tabulky je zajímavý sloupec 1.3.6.1.2.1.17.2.15.1.8
. Ten obsahuje buď svou nejnižší MAC adresu, pokud je prvek root bridge nebo MAC adresu protistrany, která vede k root bridge pro síťový segment. Proto jsou zajímavé pouze záznamy, kde je uložena jiná MAC adresa než nejnižší MAC tohoto prvku. Pokud takový záznam najdeme, s pomocí indexu se doptáme na jméno portu přes Bridge MIB a IF-MIB. Lze tedy zjišťovat pouze spoje směrem od konce větví ke kořenu (root bridge přepínači).
Teď tedy PHP kód
$ip = "192.168.1.1"; $community = "public"; // tato funkce pouze vycisti vracenou SNMP hodnotu, // snmp vraci vysledek vcetne typu, napr: INTEGER: 123 function uprav ($value) { $value = trim($value); if (!strncasecmp("STRING:",$value,7)) { $value = substr($value,8); if ($value[0] == "\"" && $value[strlen($value)-1] == "\"") $value = substr($value,1,strlen($value)-2); return ($value); } else if (!strncasecmp("Timeticks:",$value,10)) { // tady je to taky slozitejsi $value = substr($value,11); $pos = strpos ($value, "("); if ($pos === false) // je to obycejne cislo return ($value); else { $pos2 = strpos ($value,")"); return (trim(substr ($value, $pos+1,$pos2-$pos-1))); } } else if (!strncasecmp("INTEGER:",$value,8)) { // tady je to slozitejsi, v status a admin status je napr: down(2) $value = substr($value,9); $pos = strpos ($value, "("); if ($pos === false) // je to obycejne cislo return ($value); else { $pos2 = strpos ($value,")"); return (substr ($value, $pos+1,$pos2-$pos-1)); } } else if (!strncasecmp("IpAddress:",$value,10)) return (substr($value,11)); else if (!strncasecmp("Hex-STRING:",$value,11)) return (substr($value,12)); else if (!strncasecmp("Gauge32:",$value,8)) return (substr($value,9)); else if (!strncasecmp("Counter32:",$value,10)) return (substr($value,11)); else return trim($value); } // zjistuju svoje chassis ID (stp id) $stp_id = snmpget($ip, $community, "SNMPv2-SMI::mib-2.17.1.1.0"); if ($stp_id) { $stp_id = uprav ($stp_id); echo "Chassis ID je $stp_id<br/><br/>\n"; // zjistuju stp okoli $porty = snmprealwalk($ip, $community, "1.3.6.1.2.1.17.2.15.1.8"); foreach ($porty as $key=>$value) { $value = uprav($value); // pro vsechny nalezene porty si zjistim index portu $pos = strrpos ($key,"."); $index = substr ($key,-(strlen($key)-$pos-1)); // je to index z mibu bridge, zeptame se tedy tam $index_mib = uprav (snmpget ($ip, $community, "1.3.6.1.2.1.17.1.4.1.2.$index")); $nazev_portu = uprav (snmpget ($ip], $community, "1.3.6.1.2.1.2.2.1.2.$index_mib")); // z casti vracene hodnoty poskladame MAC adresu $sl = explode (" ", $value); foreach ($sl as $xkey=>$sloupec) { $sloupec = str_pad ($sloupec, 2, "0", STR_PAD_LEFT); $sl[$xkey] = $sloupec; } $mac = $sl[2] . ":" . $sl[3] . ":" . $sl[4] . ":" . $sl[5] . ":" . $sl[6] . ":" . $sl[7]; // pokud se mac nerovna ID switche, nasli jsme port smerujici k root bridge if ($mac != $stp_id) echo "Nalez na portu $nazev_portu, protistrana $mac<br/>\n"; } else echo "Spatne SNMP udaje nebo STP MIB neni implementovan v zarizeni";
Jak jsem zmínil - STP nám nedá tolik informací jako ostatní protokoly, ale pokud tyto informace vyčteme ze všech prvků, výsledkem by měla být celá topologie.
A jakým způsobem mi tyto informace pomohou k sestavení topologie sítě? Switch sice možná ví, kterou cestou se dostane k Root Bridge, ale už nemá nejmenší šanci, jak zjistit ke komu jsem skutečně připojen
Topologii je v tomto pripade mysleno zapojeni switchu, ne vsech zarizeni v siti. Uz jsem zde psal clanky na zjistovani z CDP a LLDP. Pokud je zajem, muzu doplnit jeste o ziskavani udaju z dalsich MIBU (napr. prepinaci tabulka switche) a s tim uz se zjistit i pripojeni koncovych zarizeni
Protokoly CDP a LLDP nejsou implementovany ve vsech HW. Jedina moznost jak generovat sitovou topologii je pomoci snmp protokolu a prohledavani. Tzn. hledani nejkratsi cesty k mac adrese nalezene na nejakem switchi/bridgi. Nebo existuje nejaky jiny exefktivni zpusob prohledavani?
Dá se to i zjednodušit přes OID 1.3.6.1.2.1.17.2.7, které vrací číslo portu vedoucího k root bridge. Když je switch sám root bridge, vrací 0.
Doporučuji vyzkoušet nedi.ch
Zajímavý nástroj - udělá topologi, zobrazí switche a info o jejich portech, dohledá ale i nody s IP a MAC takže lze dohledat i zpětně, kde bylo jaké zařízení připojené k síti.