2017-09-07 15 views
0

SNMP 에이전트를 작성하고 관리 객체를 등록했습니다 (MIB OID 값 작성/설정). SNMPv2c를 사용하여이 값을 검색하면 값이 올바르게 반환됩니다. ResponseEvent.getResponse의 PDU 유형이 GET이고 변수 바인딩이 데이터 OID 등을 올바르게 예상합니다. SNMPv3 및 사용자 인증을 사용하여이 값을 검색하면 값이 올바르게 반환되지 않습니다. ResponseEvent.getResponse의 PDU에는 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 통신을 설정하기 위해 하나 또는 두 개의 요청 /보고 교환이 이루어집니다.

첫 번째 메시지는 관리자가 에이전트의 엔진 ID (키 로컬 리 제이션에 필요한/etc)를 검색 할 수있게 해주는 보고서로 보통 usmStatUnknownEngineIDs이며 초기 요청에 적절한 엔진 ID를 지정하지 않으면 발생합니다. 두 번째/기타는 auth/noPriv 또는 auth/priv 수준 보안을 사용하는 경우 발생하며 usmStatsNotInTimeWindows입니다. 요청이 에이전트 값의 적절한 범위 내에서 엔진 부팅/엔진 시간 값을 지정하지 않은 경우 전송됩니다. 이 값은 시간 제한에서 벗어난 요청이 더 이상 유효하지 않게하여 메시지 재생 공격을 방지하며 일반적으로 보고서 PDU를 통해 에이전트에서 메시지를 수신 할 때까지 관리자가 알지 못합니다.

관리자가 적절한 엔진 ID, 부팅 및 시간을 갖고 필요한 경우 엔진 ID에 현지화 된 키가있는 경우 정상 요청/응답 교환이 예상대로 진행될 수 있습니다. 일부 SNMP API는이 교환을 처리하여 사용자가 요청을 보내고 교환 후에 최종 결과를 얻습니다. SNMP4j는 그렇지 않은 것으로 보이며이 보고서 중 하나 인 경우 직접 처리해야 할 수도 있습니다.

이러한 보고서 중 하나가 아닌 경우 구성이 일치하지 않을 가능성이 높습니다.