通过SNMP查询交换机的MAC表以及核心交换机的ARP表,实现查询对应关系
通过SNMP查询交换机的MAC表以及核心交换机的ARP表,实现查询对应关系,这样就可以实现后面我们要的功能了,无论是查询IP的MAC,接在什么交换机的什么口,还是去匹配机房里异常的进入设备,后面可以加上集成MSSQL数据库,在表里加上每个MAC的所有历史记录,比如什么时候接入交换机,什么时候换到另外的交换机的哪个口。
下载并引用
SnmpSharpNet.dll
https://download.csdn.net/download/chscomfaner/12094545
先打开交换机的SNMP,打开方法:
#snmp-server community public ro #配置本路由器的只读字串为public
#snmp-server community public rw #配置本路由器的读写字串为public
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="community" value="public"/>
<add key="sw" value="192.168.10.200"/>
<add key="router" value="192.168.10.1"/>
</appSettings>
</configuration>
Programs.cs
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading;
namespace SNMP_SW
{
class Program
{
static object locker=new object();
static List<SW> allSW=new List<SW>();
static List<Router> allRouter = new List<Router>();
static void Main(string[] args)
{
//扫描交换机
string[] sws = ConfigurationManager.AppSettings["sw"].Split(',');
Console.WriteLine("共有{0}个交换机需要扫描", sws.Length);
//Console.WriteLine("--------------------------------------------------------------------");
foreach (string sw in sws)
{
if (string.IsNullOrEmpty(sw))
continue;
ParameterizedThreadStart pst = new ParameterizedThreadStart(scanSw);
Thread thread = new Thread(pst);
thread.Name = sw + "扫描交换机线程";
thread.Start(sw);
}
//扫描核心
string[] routers = ConfigurationManager.AppSettings["router"].Split(',');
Console.WriteLine("共有{0}个核心需要扫描", routers.Length);
foreach (string rou in routers)
{
if (string.IsNullOrEmpty(rou))
continue;
ParameterizedThreadStart pst = new ParameterizedThreadStart(scanRouter);
Thread thread = new Thread(pst);
thread.Name = rou + "扫描核心线程";
thread.Start(rou);
}
Console.WriteLine("--------------------------------------------------------------------");
Console.ReadLine();
}
static void scanRouter(object host)
{
Console.WriteLine("启动线程:" + Thread.CurrentThread.Name);
Dictionary<string, string> arpTable = new Dictionary<string, string>();
Dictionary<string, string> dicArp = SimpleSnmp.getWalkValue(host.ToString(), SimpleSnmp.OID.arp);
foreach (var item in dicArp)
{
string[] dip = item.Key.Split('.');
string ip = string.Format("{0}.{1}.{2}.{3}", dip[dip.Length - 4], dip[dip.Length - 3], dip[dip.Length - 2], dip[dip.Length - 1]);
string mac = item.Value.Replace(" ", ":").ToUpper();
arpTable.Add(mac, ip);
}
Console.WriteLine("核心的ARP表");
Console.WriteLine("--------------------------------------------------------------------");
foreach (var item in arpTable)
{
Console.WriteLine("{0}-{1}", item.Key, item.Value);
}
Router rou = new Router(host.ToString(), arpTable);
string json = Utils.toJson(arpTable);
Utils.save(host.ToString() + "_ArpTable.txt", json);
lock (locker)
{
allRouter.Add(rou);
}
}
static void scanSw(object host)
{
Console.WriteLine("启动线程:" + Thread.CurrentThread.Name);
List<string> vlan = new List<string>();
Dictionary<string, Dictionary<string, string>> macTable = new Dictionary<string, Dictionary<string, string>>();
//Dictionary<string, string> dicPort = SimpleSnmp.getWalkValue(host.ToString(), SimpleSnmp.OID.port); //获取所有的端口
//if (dicPort == null)
//{
// Console.WriteLine(Thread.CurrentThread.Name+"端口请求失败");
// return;
//}
//else
//{
// //Console.WriteLine(Thread.CurrentThread.Name + "端口请求成功");
//}
//foreach (var item in dicPort)
//{
// if (item.Value.Contains("Vl"))
// {
// vlan.Add(item.Value.Replace("Vl",""));
// }
// Console.WriteLine("{0}:{1}:{2}", host, item.Key, item.Value);
//}
Dictionary<string, string> dicVlan = SimpleSnmp.getWalkValue(host.ToString(), SimpleSnmp.OID.vtp); //获取所有VLAN
if (dicVlan == null)
{
Console.WriteLine(Thread.CurrentThread.Name + "VLAN请求失败");
return;
}
else
{
//Console.WriteLine(Thread.CurrentThread.Name + "VLAN请求成功");
}
foreach (var item in dicVlan)
{
if (!vlan.Contains(item.Value.Replace("vlan", "")))
{
vlan.Add(item.Value.Replace("vlan", ""));
}
//Console.WriteLine("{0}:{1}:{2}", host, item.Key, item.Value);
}
//Console.WriteLine("获取到了如下所有的VLAN:");
foreach (var item in vlan)
{
Dictionary<string, string> mac = SimpleSnmp.getWalkValue(host.ToString(), SimpleSnmp.OID.mac,item);
Dictionary<string, string> mac_port = SimpleSnmp.getWalkValue(host.ToString(), SimpleSnmp.OID.mac_port, item);
Dictionary<string, string> mac_link_port = new Dictionary<string, string>();
foreach (var i in mac)
{
foreach (var j in mac_port)
{
string t1 = j.Key.Substring(SimpleSnmp.OID.mac_port.Length - 1);
string t2 = i.Key.Substring(SimpleSnmp.OID.mac_port.Length - 1);
if (t1==t2) //找端口号
{
mac_link_port.Add(i.Value, j.Value);
//Console.WriteLine("{0}:vlan{1}:{2}:{3}", host, item, i.Value, j.Value);
break;
}
}
}
if(mac_link_port.Count>0)
macTable.Add(item, mac_link_port);
}
foreach (var item in macTable)
{
Console.WriteLine("--------------------------------------------------------------------");
Console.WriteLine("SW{0}:VLAN{1}",host.ToString(),item.Key);
foreach (var mp in item.Value)
{
Console.WriteLine("MAC:{0}--PORT:{1}", mp.Key, mp.Value);
}
}
SW sw = new SW(host.ToString(), macTable);
string json = Utils.toJson(macTable);
Utils.save(host.ToString() + "_MacTable.txt", json);
lock (locker)
{
allSW.Add(sw);
}
}
}
class SW
{
string ip;
Dictionary<string, Dictionary<string, string>> macTable;
public SW(string ip, Dictionary<string, Dictionary<string, string>> macTable)
{
this.ip = ip;
this.macTable = macTable;
}
}
class Router
{
string ip;
Dictionary<string, string> arpTable;
public Router(string ip, Dictionary<string, string> arpTable)
{
this.ip = ip;
this.arpTable = arpTable;
}
}
}
SimpleSnmp.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Net;
using SnmpSharpNet;
using System.Configuration;
namespace SNMP_SW
{
class SimpleSnmp
{
public static string communityString = ConfigurationManager.AppSettings["community"];
public struct OID {
public static string mac = ".1.3.6.1.2.1.17.4.3.1.1";
public static string mac_port = ".1.3.6.1.2.1.17.4.3.1.2";
public static string arp = ".1.3.6.1.2.1.4.22.1.2";
public static string port = ".1.3.6.1.2.1.31.1.1.1.1";
public static string vtp = ".1.3.6.1.2.1.47.1.2.1.1.2";
}
public SimpleSnmp()
{
//
//TODO: 在此处添加构造函数逻辑
//
}
#region 通过oid字符数组获得相应的值
public static Dictionary<string, string> getOIDValue(string host, string[] oid)
{
//返回变量
Dictionary<string, string> dic = new Dictionary<string, string>();
// SNMP community name
OctetString community = new OctetString(communityString);
// Define agent parameters class
AgentParameters param = new AgentParameters(community);
// Set SNMP version to 1 (or 2)
param.Version = SnmpVersion.Ver1;
//param.Version = SnmpVersion.Ver2;
// Construct the agent address object
// IpAddress class is easy to use here because
// it will try to resolve constructor parameter if it doesn't
// parse to an IP address
IpAddress agent = new IpAddress(host);
// Construct target
UdpTarget target = new UdpTarget((IPAddress)agent, 161, 2000, 1);
// Pdu class used for all requests
Pdu pdu = new Pdu(PduType.Get);
foreach (string singleoid in oid)
{
pdu.VbList.Add(singleoid);
}
// Make SNMP request
SnmpV1Packet result = (SnmpV1Packet)target.Request(pdu, param);
// If result is null then agent didn't reply or we couldn't parse the reply.
if (result != null)
{
// ErrorStatus other then 0 is an error returned by
// the Agent - see SnmpConstants for error definitions
if (result.Pdu.ErrorStatus == 0)
{
for (int i = 0; i < result.Pdu.VbList.Count; i++)
{
dic.Add(result.Pdu.VbList[i].Oid.ToString(), result.Pdu.VbList[i].Value.ToString());
}
// Reply variables are returned in the same order as they were added
// to the VbList
}
}
target.Close();
return dic;
}
#endregion
#region 通过snmpwalk返回oid根下面的所有值
public static Dictionary<string, string> getWalkValue(string host, string irootOid,string vlan = null )
{
Dictionary<string, string> dic = new Dictionary<string, string>();
// SNMP community name
OctetString community;
if(vlan==null)
community = new OctetString(communityString);
else
community = new OctetString(communityString+"@"+vlan);
// Define agent parameters class
AgentParameters param = new AgentParameters(community);
// Set SNMP version to 2 (GET-BULK only works with SNMP ver 2 and 3)
param.Version = SnmpVersion.Ver2;
// Construct the agent address object
// IpAddress class is easy to use here because
// it will try to resolve constructor parameter if it doesn't
// parse to an IP address
IpAddress agent = new IpAddress(host);
// Construct target
UdpTarget target = new UdpTarget((IPAddress)agent, 161, 2000, 1);
// Define Oid that is the root of the MIB
// tree you wish to retrieve
Oid rootOid = new Oid(irootOid); // ifDescr
// This Oid represents last Oid returned by
// the SNMP agent
Oid lastOid = (Oid)rootOid.Clone();
// Pdu class used for all requests
Pdu pdu = new Pdu(PduType.GetBulk);
// In this example, set NonRepeaters value to 0
pdu.NonRepeaters = 0;
// MaxRepetitions tells the agent how many Oid/Value pairs to return
// in the response.
pdu.MaxRepetitions = 200;
// Loop through results
while (lastOid != null)
{
// When Pdu class is first constructed, RequestId is set to 0
// and during encoding id will be set to the random value
// for subsequent requests, id will be set to a value that
// needs to be incremented to have unique request ids for each
// packet
if (pdu.RequestId != 0)
{
pdu.RequestId += 1;
}
// Clear Oids from the Pdu class.
pdu.VbList.Clear();
// Initialize request PDU with the last retrieved Oid
pdu.VbList.Add(lastOid);
// Make SNMP request
SnmpV2Packet result;
try
{
result = (SnmpV2Packet)target.Request(pdu, param);
}
catch
{
return null;
}
// You should catch exceptions in the Request if using in real application.
// If result is null then agent didn't reply or we couldn't parse the reply.
if (result != null)
{
// ErrorStatus other then 0 is an error returned by
// the Agent - see SnmpConstants for error definitions
if (result.Pdu.ErrorStatus == 0)
{
// Walk through returned variable bindings
foreach (Vb v in result.Pdu.VbList)
{
// Check that retrieved Oid is "child" of the root OID
if (rootOid.IsRootOf(v.Oid))
{
dic.Add(v.Oid.ToString(), v.Value.ToString());
}
else
{
// we have reached the end of the requested
// MIB tree. Set lastOid to null and exit loop
lastOid = null;
break;
}
}
//lastOid = null; //取完就结束吧!
}
}
}
target.Close();
return dic;
}
#endregion
}
}
Utils.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;
using System.IO;
namespace SNMP_SW
{
class Utils
{
public static string toJson(object obj)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize(obj);
return json;
}
public static bool save(string filename, string json)
{
try
{
StreamWriter sw = new StreamWriter(filename, false);
sw.Write(json);
sw.Close();
return true;
}
catch (Exception)
{
return false;
}
}
}
}
效果: