2017-09-07 448 views
0

我寫了一個SNMP代理並註冊了一個託管對象(創建/設置了一個MIB OID的值)。 當我使用SNMPv2c檢索該值時,該值被正確返回 - 來自ResponseEvent.getResponse的PDU具有類型= GET,並且變量綁定具有預期數據 - 正確的OID等。 當我使用SNMPv3和用戶認證檢索此值時,值沒有被正確地返回 - 來自ResponseEvent.getResponse的PDU具有type = REPORT,並且變量綁定具有與請求中不同的OID - 從我迄今爲止讀取的內容來看,這表示配置/認證錯誤。 下面是用於客戶端&代理的示例代碼(片段) - 請你能告訴我如何創建代理&客戶端 - 我哪裏出錯了?使用SNMP4j(org.snmp4j)v3和用戶身份驗證時,代理程序未返回正確的OID值?

// TestSNMPAgent: 
public class TestSNMPAgent { 

    private OID sysDescr = new OID("1.3.6.1.2.1.1.1.0"); 
    ... 
    public static void main(String[] args) throws IOException { 
     TestSNMPAgent agent = new TestSNMPAgent(); 
     agent.init("0.0.0.0/4071"); 

    private void init(String agentIp) throws IOException { 

     agent = new SNMPAgent(agentIp); 

     agent.start(); 

     agent.unregisterManagedObject(agent.getSnmpv2MIB()); 

     agent.registerManagedObject(new MOScalar(oid, 
      MOAccessImpl.ACCESS_READ_WRITE, 
      getVariable(value),sysDescr, 
      "1"))); 
     ... 
    } 

} 

// SNMPAgent: 
public class SNMPAgent extends BaseAgent { 
... 
    @Override 
    protected void addUsmUser(USM arg0) { 
     UsmUser user = new UsmUser(new OctetString("SHADES"), 
     AuthSHA.ID, 
     new OctetString("SHADESAuthPassword"), 
     PrivDES.ID, 
     new OctetString("SHADESPrivPassword")); 
    } 

    @Override 
    protected void addViews(VacmMIB vacm) { 
     vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, 
        new OctetString("SHADES"), 
        new OctetString("v3group"), 
        StorageType.nonVolatile); 

     vacm.addAccess(new OctetString("v3group"), new OctetString(), 
        SecurityModel.SECURITY_MODEL_USM, 
        SecurityLevel.NOAUTH_NOPRIV, VacmMIB.vacmExactMatch, 
        new OctetString("fullReadView"), 
        new OctetString("fullWriteView"), 
        new OctetString("fullNotifyView"), 
        StorageType.nonVolatile); 
    } 

    public void registerManagedObject(ManagedObject mo) { 
     try { 
      server.register(mo, null); 
     } catch (DuplicateRegistrationException ex) { 
     throw new RuntimeException(ex); 
    } 
} 

// TestSNMPMgr 
public class TestSNMPMgr { 

    public static void main(String[] args) throws IOException { 

     TestSNMPMgr client = new TestSNMPMgr(); 
     client.init(); 
    } 

    public void init() { 
     SNMPMgr client = new SNMPMgr(); 
     client.start(); 
     // Get back Value which is set 
     String value = client.getAsString(new OID("1.3.6.1.2.1.1.1.0")); 
    } 
} 

// SNMPMgr 
public class SNMPMgr { 

    Snmp snmp = null; 
    Address address = null; 

    public SNMPMgr() 
    { 
     address = "1.3.6.1.2.1.1.1.0"; 
    } 

    /** 
    * Start the Snmp session. If you forget the listen() method you will not 
    * get any answers because the communication is asynchronous 
    * and the listen() method listens for answers. 
    * @throws IOException 
    */ 
    public void start() throws IOException { 
     address = GenericAddress.parse("udp:127.0.0.1/4701"); 
     TransportMapping transport = new DefaultUdpTransportMapping(); 
     snmp = new Snmp(transport); 
     USM usm = new USM(SecurityProtocols.getInstance(), 
         new OctetString(MPv3.createLocalEngineID()), 0); 
     SecurityModels.getInstance().addSecurityModel(usm); 
     transport.listen(); 
    } 

    public void end() { 
     try { 
      snmp.close(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 


    /** 
    * Method which takes a single OID and returns the response from the agent as a String. 
    * @param oid 
    * @return 
    * @throws IOException 
    */ 
    public String getAsString(OID oid) throws IOException { 
     ResponseEvent event = get(new OID[] { oid }); 
     return event.getResponse().get(0).getVariable().toString(); 
    } 


    public ResponseEvent get(OID oids[]) throws IOException { 
     PDU pdu = new ScopedPDU(); 
     for (OID oid : oids) { 
      pdu.add(new VariableBinding(oid)); 
     } 

     pdu.setType(PDU.GET); 

     // add user to the USM 
     snmp.getUSM().addUser(new OctetString("SHADES"), 
       new UsmUser(new OctetString("SHADES"), 
       AuthSHA.ID, 
       new OctetString("SHADESAuthPassword"), 
       PrivDES.ID, 
       new OctetString("SHADESPrivPassword"))); 


     // send the PDU 
     ResponseEvent event = snmp.send(pdu, getTarget(), null); 

     if(event != null) { 
      return event; 
     } 
     throw new RuntimeException("GET timed out"); 
    } 

    /** 
    * This method returns a Target, which contains information about 
    * where the data should be fetched and how. 
    * @return 
    */ 
    private UserTarget getTarget() { 
     UserTarget target = new UserTarget(); 
     target.setAddress(address); 
     target.setRetries(1); 
     target.setTimeout(5000); 
     target.setVersion(SnmpConstants.version3); 
     target.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV); 
     target.setSecurityName(new OctetString("SHADES")); 
     return target; 
    } 

} 

回答

0

報告PDU中的OID應告訴您發生了什麼。在典型情況下,將會有一個或兩個(或兩個)請求/報告交換來建立管理者和代理之間的初始SNMPv3通信(或者分別是非權威和權威的引擎)。

第一個通常是usmStatUnknownEngineIDs報告,它允許管理員發現代理的引擎ID(用於密鑰本地化/等),並且如果您沒有在初始請求中指定正確的引擎ID,就會發生。如果使用auth/noPrivauth/priv級別安全性,並且這是usmStatsNotInTimeWindows,則會發生第二次/其他事件,如果請求未在代理值的適當範圍內指定引擎啓動/引擎時間值,則會發送該次數。這些值通過使請求不再有效時防止消息重播攻擊,並且管理器通常不知道它們是什麼,直到它通過報告PDU從代理接收它們。

在管理器具有適當的引擎ID,引導和時間並且具有引擎ID的本地化密鑰(如有必要)之後,正常請求/響應交換可按預期進行。有些SNMP API將爲您處理此交換,因此您只需發送請求並在交換後獲得最終結果。看起來SNMP4j沒有,如果它是其中一個報告,您可能必須自己處理它。

如果它不是這些報告中的一個,那麼您的配置可能不匹配。

相關問題