www.SAMURAJ-cz.com 

20.04.2024 Marcela Translate to English by Google     VÍTEJTE V MÉM SVĚTĚ

Články

Zjištění MAC adresy zařízení na portu switche pomocí SNMP a PHP

Čtvrtek, 20.03.2008 11:21 | Samuraj - Petr Bouška |
V předchozích dílech jsem popisoval, jak zjistit základní informace o portech na switchi. A jak informace doplnit o zařazení portu do VLANy. V tomto díle se věnuji dalšímu zajímavému rozšíření a to zjištění MAC adresy zařízení, které je připojené do daného portu. To se může hodit v řadě situací, například nám v síti začne komunikovat nějaký počítač a my potřebujeme dohledat, kde se fyzicky nachází. Postup jsem testoval na switchích Cisco Catalyst 2960, 3750, 6500, ale měl by být aplikovatelný i na jiné značky.

Podobně jako určení zařazení portu do VLANy, ani nalezení MAC adresy na portu není úplně jednoduché. Princip práce switche je takový, že si vytváří tabulku přiřazení portu a MAC adresy a podle ní pak posílá data na druhé vrstvě (layer 2 OSI model). Navíc si tyto tabulky udržuje nezávisle pro každou VLANu. Z toho plyne, že my potřebujeme stáhnout ze switche tuto tabulku. Ta se označuje jako CAM tabulka (Content Addressable Memory) nebo jednoduše mac address table.

Obecný postup vypadá takto:

  1. vytvoříme seznam portů se základními údaji
  2. k portům přiřadíme, zda jsou v trunk módu či ne
  3. vytvoříme seznam VLAN
  4. projdeme VLANy a pro každou vytvoříme tabulku MAC adres a portů
  5. projdeme tabulky MAC adres a podle portu doplníme seznam portů o MAC adresu tam, kde port není trunk

Pozn.: V příkladu vycházím z toho, že mám do portu zapojeno pouze koncové zařízení, takže se pro port nalezne maximálně jedna adresa. Nebo že port je trunk, který ho spojuje s jiným switchem, a pak mne MAC adresy nezajímají. Pokud by někde byl připojen switch/hub nebo například IP telefon, do kterého je připojeno PC, tak dostanu pro jeden port více MAC adres a musel bych vytvářet pole.

Vytvoření seznamu portů/interfaců

Tento bod byl vyřešen v článku Informace o portech switche pomocí SNMP a PHP.

Určení trunk portů

Tento bod byl řešen v článku Informace o zařazení portu do VLANy u Cisco Switchů pomocí SNMP a PHP.

Seznam VLAN

Tento bod byl řešen v článku Informace o zařazení portu do VLANy u Cisco Switchů pomocí SNMP a PHP.

Procházení VLAN a načtení CAM tabulek

Pro stažení tabulky MAC adres a portů využijeme MIB soubor BRIDGE-MIB. V něm se nachází .iso.org.dod.internet.mgmt.mib-2.dot1dBridge.dot1dTp.dot1dTpFdbTableOID = 1.3.6.1.2.1.17.4.3 a zajímat nás budou tato OID:

jméno OID popis
dot1dTpFdbAddress .1.3.6.1.2.1.17.4.3.1.1 seznam MAC adres, pro které má switch forward informace
dot1dTpFdbPort .1.3.6.1.2.1.17.4.3.1.2 číslo portu, na kterém byla naučena daná MAC adresa
dot1dTpFdbStatus .1.3.6.1.2.1.17.4.3.1.3 stav záznamu, nás zajímá 3 = learned

Pro přístup k těmto hodnotám se opět využívá hybridní community string (Cisco tuto metodu nazývá community string indexing), protože v MIB existuje pouze jedna instance a my potřebujeme získat hodnoty pro každou VLANu. Za community string doplníme @VLAN, takže například public@30 pro načtení hodnot z VLAN 30. Pokud nepoužijeme toto rozšíření, tak se vrací hodnoty z VLAN 1.

Pomocí snmpwalk projdeme OID pro dot1dTpFdbAddress, tím získáme seznam MAC adres. OID je za svým číslem doplněno několika číselným indexem. Jeden vrácený záznam může vypadat třeba takto:

[17.4.3.1.1.0.11.205.197.114.60] =>  Hex: 00 0B CD C5 72 3C

Stejným způsobem projdeme dot1dTpFdbStatus a určíme, zda tuto MAC adresu počítat.

[17.4.3.1.1.0.11.205.197.114.60] =>  3

A pomocí dot1dTpFdbPort dostaneme patřičná čísla portu.

[17.4.3.1.1.0.11.205.197.114.60] => 54

Tím, že složíme hodnoty se stejným indexem, v tomto případě 0.11.205.197.114.60, tak dostaneme, že na portu 54 je MAC adresa 00:0B:CD:C5:72:3C. My však pracujeme s indexy portů (IfIndex), takže ještě nalezneme přiřazení indexu k číslu portu (toto OID jsme již použili u VLAN).

jméno OID popis
dot1dBasePortIfIndex .1.3.6.1.2.1.17.1.4.1.2 pro číslo portu vrátí index interfacu

Zde je index dán poslední hodnotou a to je naše číslo portu, pro které hledáme ifIndex.

[17.1.4.1.2.54] => 10202

Realizace v PHP

Následující kód obsahuje pouze funkci pro získání MAC adres a navazuje na kód v předchozích dílech.

// načte všechny hodnoty pod OID a vrátí je jako pole, index – poslední číslo OID 
function getInterPart2(&$interfaces, $ip, $comm, $oid) {
	$array = snmprealwalk($ip, $comm, $oid);
	foreach($array as $key => $val) {
		$index = ereg_replace('.*\.([0-9]+)$', "\\1", $key);
		$val = format_snmp_string($val);
		$interfaces[$index] = $val;
	}
}
// načte všechny hodnoty pod OID a vrátí je jako pole, index – složený z několika posledních čísel OID 
function getInterPart3(&$interfaces, $ip, $comm, $oid) {
	$array = snmprealwalk($ip, $comm, $oid);
	$oidl = strlen($oid) - 12;
	foreach($array as $key => $val) {
		$index = substr($key, $oidl);
		$val = format_snmp_string($val);
		$interfaces[$index] = $val;
	}
}
// pole portů doplní o MAC adresu
function getMACs(&$interfaces, $ip, $comm) {
	$vlans = array();
	getInterPart($vlans, $ip, $comm, ".1.3.6.1.4.1.9.9.46.1.3.1.1.18", "Index");      // VLAN ifIndex 
	getInterPart($vlans, $ip, $comm, ".1.3.6.1.4.1.9.9.46.1.3.1.1.3", "Type");        // VLAN type, 1 - OK 
	foreach($vlans as $vlan_id => $vlan) 
		if($vlan["Type"] == 1) {
			$macs = array();
			getInterPart3($macs, $ip, $comm."@".$vlan_id, ".1.3.6.1.2.1.17.4.3.1.1");   // seznam MAC adres pro danou VLAN
			$bridge = array(); 
			getInterPart3($bridge, $ip, $comm."@".$vlan_id, ".1.3.6.1.2.1.17.4.3.1.2"); // urceni, kteremu bridge portu MAC adresa patri
			$ifI = array();
			getInterPart2($ifI, $ip, $comm."@".$vlan_id, ".1.3.6.1.2.1.17.1.4.1.2");    // k bridge portu urci jeho interface index
			foreach($macs as $id => $mac) {          // projdeme seznam MAC adres
				$ifIndex = $ifI[$bridge[$id]];       // ifIndex dostaneme z indexu záznamu, převedený na číslo portu a pak na ifIndex
				if($interfaces[$ifIndex]["Trunk"] == 2) $interfaces[$ifIndex]["MAC"] = $mac;
				else $interfaces[$ifIndex]["MAC"] = "";
			}
		}
}
zobrazeno: 26984krát | Komentáře [5]

Autor:

Související články:

SNMP

Protokol SNMP (Simple Network Management Protocol) je velice užitečný pro správu počítačové sítě.

Pokud se chcete vyjádřit k tomuto článku, využijte komentáře níže.

Komentáře

  1. [1] neco

    Mam prosbu.

    Jak mam zjistit fyzickou topologii?

    Resp chci detekovat i spoje mezi switchi, ktere spannig tree algoritmus "blokuje".

    S tim ze je i zakazan(neni podporovan) CDP.

    Moc dik za odpověďl

    Sobota, 08.11.2008 14:44 | odpovědět
  2. [2] maka

    great post ;)

    my Czech is not that good so excuse me if you have pointed this out, but just to clarify - the numerical indexes after dot1dTpFdbAddress in the example are actually the decimal equivalents of the 6 hex tuples of the mac address ;)

    Pátek, 22.03.2013 20:08 | odpovědět
  3. [3] jimmy

    ve funkci getMACs je imho chybka, alespon u me to takhle nefungovalo. Konkretne se jedna o radek

    $ifI[$bridge[$id]]; // ifIndex dostaneme z indexu záznamu, převedený na číslo portu a pak na ifIndex

    ve kterem je predano $id, ale toto $id se musi v jednom cisle OID lisit. Da se to vyresit nasledovne:

    $ifI[$bridge[str_replace(".1.17.4.3.1.1", ".1.17.4.3.1.2", $id]];

    Úterý, 20.08.2013 12:49 | odpovědět
  4. [4] jimmy

    odpověď na [3]jimmy: jeste opravene TYPO

    $ifI[$bridge[str_replace(\".1.17.4.3.1.1\", \".1.17.4.3.1.2\", $id)]];

    Úterý, 20.08.2013 12:50 | odpovědět
  5. [5] Samuraj

    odpověď na [3]jimmy: Je to už hodně dlouho, co jsem se tomu věnoval, než bych si to osvěžil, tak by to zabralo moc času. Ale tak, jak je to v příkladu, to mám i v aplikaci, kterou stále používám, a vše funguje korektně.

    Úterý, 27.08.2013 08:36 | odpovědět
Přidat komentář

Vložit tag: strong em link

Vložit smajlík: :-) ;-) :-( :-O

Nápověda:
  • maximální délka komentáře je 2000 znaků
  • HTML tagy nejsou povoleny (budou odstraněny), použít se mohou pouze speciální tagy (jsou uvedeny nad vstupním polem)
  • nový řádek (ENTER) ukončí odstavec a začne nový
  • pokud odpovídáte na jiný komentář, vložte na začátek odstavce (řádku) číslo komentáře v hranatých závorkách