SNMP(简单网络管理协议)详解
一、簡介
SNMP(簡單網絡管理協議):?專門用于在 IP 網絡管理網絡節點(服務器、工作站、路由器、交換機及HUBS等)的一種標準協議,它是一種應用層協議。?SNMP 使網絡管理員能夠管理網絡效能,發現并解決網絡問題以及規劃網絡增長。通過 SNMP 接收隨機消息(及事件報告)網絡管理系統獲知網絡出現問題。
SNMP的前身是簡單網關監控協議(SGMP),用來對通信線路進行管理。隨后,人們對SGMP進行了很大的修改,特別是加入了符合Internet定義的SMI和MIB,改進后的協議就是著名的SNMP。
- 管理信息結構SMI(Structure ofManagement Information)定義了SNMP框架所用信息的組織和標識,為MIB定義管理對象及使用管理對象提供模板。
- 管理信息庫MIB(,Management Information Base)定義了可以通過SNMP進行訪問的管理對象的集合,一種樹狀數據庫,MIB管理的對象,就是樹的端節點。
- 對象識別符OID(Object Identifier)定義了端節點的唯一位置和唯一名字,其命名規則就是父節點的名字作為子節點名字的前綴。?
二、架構原理
?一個SNMP管理的網絡由下列三個關鍵組件組成:
- 網絡管理系統(NMS,Network-management systems)NMS運行應用程序,監控被管理的設備。網絡管理系統提供網絡管理需要的大量運算和記憶資源。
- 被管理的設備(managed device)被管理的設備是一個網絡節點,它包含一個SNMP agent。被管理的設備通過管理信息庫(MIB)收集并存儲管理信息,并且讓網絡管理系統通過agent讀取這些信息。
- 代理者(agent)agent是一種存在于被管理的設備中的網絡管理軟件模塊。agent控制本地機器的管理信息,以和SNMP兼容的格式傳送這項信息。
主代理是一個在可運行的SNMP網絡組件上運作的軟件,可回應從管理站發出的SNMP要求。它的角色類似C/S術語中的服務器。主代理依賴子代理提供有關特定功能的管理信息。
子代理是一個在可運行的SNMP網絡組件上運作的軟件,運行在特定子系統的特定管理信息庫(MIB,Management Information Base)中定義的信息和管理功能。子代理的一些能力有:搜集主代理的信息、配置主代理的參數、回應管理者的要求、產生警告或陷阱trap
主代理和子代理的角色可以合并,在這種情況下我們可以簡單的稱之為代理(agent)。
?SNMP定義了五種Manager與Agent之間的通訊形式。
前三項都是屬于Manager向Agent發出的訊息,后兩項則屬于Agent向Manager發出的訊息
Trap:當設備發生了各種事件之后,產生的MIB信息由SNMP代理主動向NMS發送,是不需要NMS請求的,NMS收到之后不需要向SNMP代理發送確認消息,SNMP發出去的Trap是根本不知道NMS是否收到,自己發送完畢之后,這些MIB信息會馬上刪除,不會駐留內存里面。
informs:informs和Trap恰好相反、設備發生事件后,這些信息并不會主動向NMS通告,除非NMS發送requst來查詢,然后才會發出去,但是發出去的informs之后會保留在內存里面,當NMS收到informs之后必須向SNMP代理發送確認消息,如果不發送確認消息,SNMP代理會重復多次發送informs(informs具有可靠性)
通過NMS來更改設備上的配置,查詢設備信息,發送的數據包為Get,更改設備的配置為Set
三、現存版本
- SNMPV1:該版本基于簡單網關監視協議發展而來的,于1988年發布,安全性差,錯誤狀態較少。典型的,SNMP為代理使用UDP端口161,為管理站使用UDP端口162。客戶端的認證使用明碼傳送。
- SNMPV2:SNMP v2c(基于社區的SNMP第二版)定義于RFC 1901–RFC 1908,SNMP v2u(基于用戶的SNMP第二版)定義于RFC 1909–RFC 1910。由于高復雜度,產生了商業化的變種,稱為SNMP v2*,而且它的機制最后被SNMP第三版的兩個安全性框架之一采用。
- SNMPV3:Internet工程工作小組(IETF)把在RFC3411-RFC3418(STD0062)中定義的SNMP第三版作為2004年的標準版本,以替代SNMPV1正式成為標準協議,SNMP第三版提供三項重要的服務:認證、隱私和訪問控制。
四、技術優點
SNMP是管理進程(NMS)和代理進程(Agent)之間的通信協議。它規定了在網絡環境中對設備進行監視和管理的標準化管理框架、通信的公共語言、相應的安全和訪問控制機制。網絡管理員使用SNMP功能可以查詢設備信息、修改設備的參數值、監控設備狀態、自動發現網絡故障、生成報告等。
SNMP具有以下技術優點:
五、snmp4j代碼示例
先看一下SNMP協議要傳輸的內容:SNMP的5種協議數據單元_協議分析網
接下來就是用SNMP4J協議的jar包來完成各個功能:http://www.snmp4j.org/html/download.html
SNMP4J把開發包分為了兩個,一個SNMP4J.jar主要負責get,trap,set,一個是SNMP4J-Agent.jar主要負責作為一個網元被管理。
5.1、開發一個Agent
?需要用到兩個配置文件bc和cfg文件,可以在這里下載:http://download.csdn.net/detail/three_man/7477991
import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.snmp4j.agent.BaseAgent; import org.snmp4j.agent.CommandProcessor; import org.snmp4j.agent.DuplicateRegistrationException; import org.snmp4j.agent.io.ImportModes; import org.snmp4j.agent.mo.DefaultMOTable; import org.snmp4j.agent.mo.MOTableRow; import org.snmp4j.agent.mo.snmp.RowStatus; import org.snmp4j.agent.mo.snmp.SnmpCommunityMIB; import org.snmp4j.agent.mo.snmp.SnmpNotificationMIB; import org.snmp4j.agent.mo.snmp.SnmpTargetMIB; import org.snmp4j.agent.mo.snmp.StorageType; import org.snmp4j.agent.mo.snmp.VacmMIB; import org.snmp4j.agent.security.MutableVACM; import org.snmp4j.mp.MPv3; import org.snmp4j.security.SecurityLevel; import org.snmp4j.security.SecurityModel; import org.snmp4j.security.USM; import org.snmp4j.smi.Integer32; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.Variable; public class MyAgent extends BaseAgent { private List<DefaultMOTable> moTables = new ArrayList<DefaultMOTable>(); private String community; protected MyAgent(File bootCounterFile, File configFile, List<DefaultMOTable> moTables, String community) { super(bootCounterFile, configFile, new CommandProcessor(new OctetString(MPv3.createLocalEngineID()))); this.moTables = moTables; this.community = community; } @Override protected void registerManagedObjects() { try { for (DefaultMOTable table : moTables) { server.register(table, null); } } catch (DuplicateRegistrationException e) { e.printStackTrace(); } } public void startUp(){ try { this.init(); } catch (IOException e) { e.printStackTrace(); } this.loadConfig(ImportModes.REPLACE_CREATE); this.addShutdownHook(); this.getServer().addContext(new OctetString(community)); this.finishInit(); this.run(); this.sendColdStartNotification(); } /** * to set community */ @Override protected void addCommunities(SnmpCommunityMIB communityMIB) { Variable[] com2sec = new Variable[] { new OctetString(community), // community name new OctetString("cpublic"), // security name getAgent().getContextEngineID(), // local engine ID new OctetString(community), // default context name new OctetString(), // transport tag new Integer32(StorageType.nonVolatile), // storage type new Integer32(RowStatus.active) // row status }; MOTableRow row = communityMIB.getSnmpCommunityEntry().createRow( new OctetString("public2public").toSubIndex(true), com2sec); communityMIB.getSnmpCommunityEntry().addRow(row); } }- ?主要的代碼是需要繼承BaseAgent
- 需要設置community
- 需要注冊Table,這個注冊中的內容將是供給get和walk的內容。
- 可以從MIB直接構建Agent,可能需要的包為:mibble-mibs是能夠獨MIB結構。這個也提供個下載地址吧: http://download.csdn.net/detail/three_man/7478061
5.2、Trap Receiver
import java.io.IOException; import java.util.logging.Logger; import org.snmp4j.MessageDispatcherImpl; import org.snmp4j.Snmp; import org.snmp4j.TransportMapping; import org.snmp4j.mp.MPv2c; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.UdpAddress; import org.snmp4j.transport.DefaultUdpTransportMapping; import org.snmp4j.util.MultiThreadedMessageDispatcher; import org.snmp4j.util.ThreadPool; import com.prince.snmp.tool.Command; import com.prince.snmp.tool.util.Configure; import com.prince.snmp.tool.util.Const; /** * 構建一個多線程的Trap Receiver * @author wangzijian * */ public class SnmpReceiver implements Command{ private final Logger log = Logger.getLogger(SnmpReceiver.class.getName()); @Override public void startUp() throws IOException { log.info("Snmp Trap Receiver Start"); log.info("listened on " + Configure.getInstance().getUdpTrapIpPort()); ThreadPool pool = ThreadPool.create(Const.THREAD_POOL_NAME, Const.AGENT_THREAD_NUM); MultiThreadedMessageDispatcher dispatcher = new MultiThreadedMessageDispatcher(pool, new MessageDispatcherImpl()); Address listenAddress = GenericAddress.parse(Configure.getInstance().getUdpTrapIpPort()); TransportMapping transport = new DefaultUdpTransportMapping((UdpAddress) listenAddress); // 構建SNMP,并且使其開始監聽 Snmp snmp = new Snmp(dispatcher, transport); snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c()); snmp.listen(); snmp.addCommandResponder(new CommandResponderImpl()); } } package com.prince.snmp.tool.receiver; import java.util.List; import java.util.logging.Logger; import org.snmp4j.CommandResponder; import org.snmp4j.CommandResponderEvent; import org.snmp4j.PDU; import org.snmp4j.smi.OID; import org.snmp4j.smi.VariableBinding; public class CommandResponderImpl implements CommandResponder { private final Logger log = Logger.getLogger(CommandResponderImpl.class.getName()); @Override public void processPdu(CommandResponderEvent event) { PDU pdu = event.getPDU(); if(PDU.TRAP == pdu.getType()){ operate(pdu); }else{ log.info("pdu method is:" + pdu.getType() + " not a trap"); } } private void operate(PDU pdu) { List<VariableBinding> bindings = pdu.getBindingList(new OID(".1")); for (VariableBinding binding : bindings) { System.out.println(binding.getOid() + "====" + binding.getVariable().toString()); } } }- ?需要一個多線程的服務器MultiThreadedMessageDispatcher
- 還需要一個處理類?CommandResponderImpl ?snmp.addCommandResponder
- 在處理類中能夠得到PDU,這個類不只可以作為Receiver還能夠開發為Agent,但是需要自己來寫很多邏輯,還有可能用到文件或者內存數據庫
5.3、send trap
package com.prince.snmp.tool.trap; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Vector; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.TransportMapping; import org.snmp4j.event.ResponseEvent; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.UdpAddress; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; import com.prince.snmp.tool.Command; import com.prince.snmp.tool.trap.dataGenerator.ITrapGenerator; import com.prince.snmp.tool.util.Configure; public class TrapSender implements Command{ private Snmp snmp; private Address targetAddress; private ITrapGenerator generator; public TrapSender(ITrapGenerator generator) { this.generator = generator; targetAddress = GenericAddress.parse(Configure.getInstance().getUdpTrapIpPort()); TransportMapping<UdpAddress> transport = null; try { transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); } catch (IOException e) { e.printStackTrace(); } } public void sendTrap(){ CommunityTarget target = new CommunityTarget(); target.setAddress(targetAddress); target.setRetries(Configure.getInstance().getRetries()); target.setTimeout(Configure.getInstance().getTimeOut()); target.setCommunity(new OctetString(Configure.getInstance().getCommunity())); target.setVersion(Configure.getInstance().getSnmpVersion()); List<TrapData> datas = generator.generateTrapData(); try { for (TrapData trapData : datas) { sendPdu(trapData, target); } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private void sendPdu(TrapData trapData, CommunityTarget target) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, IOException { PDU pdu = MoToPdu.moToPdu(trapData); ResponseEvent respEvnt = snmp.send(pdu, target); // 解析Response if (respEvnt != null && respEvnt.getResponse() != null) { Vector<VariableBinding> recVBs = (Vector<VariableBinding>) respEvnt.getResponse().getVariableBindings(); for (int i = 0; i < recVBs.size(); i++) { VariableBinding recVB = recVBs.elementAt(i); System.out.println(recVB.getOid() + " : " + recVB.getVariable()); } } } }- ? trap主要注意必須設置兩個VariableBingding
? ? ? ? ? ? ? ? pdu.add(new VariableBinding(SnmpConstants.sysUpTime, new TimeTicks(trap.getSysUpTime())));
? ? ? ? ? ? ? ? pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, new OID(trap.getTrapOid())))
5.4、get
private static void simpleGet() throws IOException { TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping(); Snmp snmp = new Snmp(transport); transport.listen(); CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString("CONV")); Address targetAddress = GenericAddress.parse("udp:10.141.43.237/161"); target.setAddress(targetAddress); target.setRetries(3); target.setTimeout(3000); target.setVersion(SnmpConstants.version2c); PDU pdu = new PDU(); pdu.add(new VariableBinding(new OID(".1.3.6.1.4.1.7569.1.2.1.23.3.1"))); pdu.setType(PDU.GETBULK); pdu.setMaxRepetitions(20); pdu.setNonRepeaters(0); ResponseEvent respEvnt = snmp.send(pdu, target); if (respEvnt != null && respEvnt.getResponse() != null) { Vector<VariableBinding> recVBs = (Vector<VariableBinding>) respEvnt.getResponse().getVariableBindings(); for (int i = 0; i < recVBs.size(); i++) { VariableBinding recVB = recVBs.elementAt(i); System.out.println(recVB.getOid() + " : " + recVB.getVariable()); } } }- ?get相對于比較簡單,資料也比較多。主要是設定pdu.setType(PDU.GETBULK);
- 利用getnext和一些判斷可以實現walk.
- http://blog .sina.com.cn/s/blog_6cb15f8f0100yx4p.html 這個哥們兒寫得非常好
具體的代碼沒有寫,因為下一篇會共享一個小的工具,可以以配置文件為基礎來構建Receiver,發送Trap,構建Agent等。
六、附錄
具體參考:阿里云登錄 - 歡迎登錄阿里云,安全穩定的云計算服務平臺
簡單網絡管理協議SNMP(史上最全)_奇妙之二進制的博客-CSDN博客_snmp是什么協議
總結
以上是生活随笔為你收集整理的SNMP(简单网络管理协议)详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: asp毕业设计—— 基于asp+acce
- 下一篇: Trapcode Particular