最近是被这个snmp的trap给坑了,其实回想起来主要是对这个不了解。特别是对snmp协议研究不够深入,

真的不想看这些协议东西,只想大概知道。结果在开发snmp trap时候被坑了,下面列下自己踩到的坑:

1、snmp的trap的中文问题

本来在自己的机器上运行挺好,但是测试说发现乱码,内心直呼不可能吧,结果还真是,原来的代码如下:

if (val_type.equals("OCTET STRING")){
//字符串类型转码,防止里面有中文内容
strValue = new String(((OctetString)recVB.getVariable()).getValue(), charsetCode);
} else {
strValue = new String (recVB.getVariable().toString());
}

charsetCode 为配置的消息编码类型, 这里说明下java的String都是Unicode编码的,

说明下:

如果想获得这个字符串的byte[] 可以通过类似:String.getBytes("UTF-8")来获得。

如果这样String.getBytes(); 就会依赖于JVM的字符集编码,WINDOWS下一般为GBK。

(要想改变JVM缺省字符集编码, 启动JVM时用选项-Dfile.encodeing=UTF-8)

注意千万不要在程序里面设置没有用的如下设置:

System.getProperties().setProperty("file.encoding", "GBK");

这样来解决默认编码的问题是不可行的!!!不可行的!!!不可行的!!!

getBytes() ---->StringCoding.encode()-->  String csn = Charset.defaultCharset().name();

/**
* Returns the default charset of this Java virtual machine.
*
* <p> The default charset is determined during virtual-machine startup and
* typically depends upon the locale and charset of the underlying
* operating system.
*
* @return A charset object for the default charset
*
* @since 1.5
*/
public static Charset defaultCharset() {
if (defaultCharset == null) {
synchronized (Charset.class) {
String csn = AccessController.doPrivileged(
new GetPropertyAction("file.encoding"));
Charset cs = lookup(csn);
if (cs != null)
defaultCharset = cs;
else
defaultCharset = forName("UTF-8");
}
}
return defaultCharset;
}

看到了吧,这个是个静态的方法,只要第一次运行defaultCharset 这个不为空了之后,后面就和file.encoding无关了,所以你基本上你无法保证

你在第一次调用之前设置,比如java其他类库会不会已经调用了getBytes(),只要一旦调用编码就固定了。

这个问题导致我在客户端测试的时候,配置的编码和实际发送的编码不一致,后来自己知道可以通过-Dfile.encodeing=UTF-8选项运行了。

有个简单的办法,可以把getBytes的内容打印出来就可以大概知道汉字是什么编码的:

System.out.println("bytes:"+Arrays.toString(strTmp.getBytes()));

GBK都是2个字节的,而UTF-8一般是2个或三个字节表示一个汉字。

2、配置文件里面项目大小写

flume的配置文件,在读取的时候是区分大小写的,所以这个不要写错了,或者在程序中忽视,自己竟然被坑到了,下次对配置还是忽略大小写的好。

3、Trap 的V3 版本会丢弃包问题

开发同事在测试中,说V3的Trap消息运行一会会丢包,严格来说不是丢包,是说运行一段时间后,V1、V2版本的消息正常接收,SNMP Trap的V3

版本的消息无法接收到,真坑,看了下Snmp4J,找不到在哪里把日志启动起来,╮(╯▽╰)╭,在初始化的地方用:

org.snmp4j.log.LogFactory.setLogFactory(new ConsoleLogFactory()); 来进行初始化下,结果在不接受V3的Trap包的时候,会打印出来:

1.3.6.1.6.3.15.1.1.2.0=0这条莫名其妙的记录,有记录就好,然后我顺着这条线索查下去,了解的SNMP的时间窗口,这个对应的含义是:

IdNotInTimeWindow 后来继续查SNMP4J的源码,发现在USM中有这样一段相关代码:

        if (securityLevel >= 2) {
if (statusInfo != null) {
int authParamsPos = usmSecurityParameters.getAuthParametersPosition()
+ usmSecurityParameters.getSecurityParametersPosition(); boolean authentic = auth.isAuthentic(user.getAuthenticationKey(), message, 0, message.length,
new ByteArrayWindow(message, authParamsPos, 12)); if (!(authentic)) {
if (logger.isDebugEnabled()) {
logger.debug("RFC3414 §3.2.6 Wrong digest -> authentication failure: "
+ usmSecurityParameters.getAuthenticationParameters().toHexString());
} CounterEvent event = new CounterEvent(this, SnmpConstants.usmStatsWrongDigests); fireIncrementCounter(event);
statusInfo.setSecurityLevel(new Integer32(1));
statusInfo.setErrorIndication(new VariableBinding(event.getOid(), event.getCurrentValue())); return 1408;
}
usmSecurityStateReference.setAuthenticationKey(user.getAuthenticationKey());
usmSecurityStateReference.setPrivacyKey(user.getPrivacyKey());
usmSecurityStateReference.setAuthenticationProtocol(auth);
usmSecurityStateReference.setPrivacyProtocol(priv); int status = this.timeTable.checkTime(
new UsmTimeEntry(securityEngineID, usmSecurityParameters.getAuthoritativeEngineBoots(),
usmSecurityParameters.getAuthoritativeEngineTime())); switch (status) {
case 1411:
logger.debug("RFC3414 §3.2.7.a Not in time window; engineID='" + securityEngineID
+ "', engineBoots=" + usmSecurityParameters.getAuthoritativeEngineBoots()
+ ", engineTime=" + usmSecurityParameters.getAuthoritativeEngineTime()); CounterEvent event = new CounterEvent(this, SnmpConstants.usmStatsNotInTimeWindows); fireIncrementCounter(event);
statusInfo.setSecurityLevel(new Integer32(2));
statusInfo.setErrorIndication(new VariableBinding(event.getOid(), event.getCurrentValue())); return status;
case 1410:
if (logger.isDebugEnabled()) {
logger.debug("RFC3414 §3.2.7.b - Unkown engine ID: " + securityEngineID);
} CounterEvent event = new CounterEvent(this, SnmpConstants.usmStatsNotInTimeWindows); fireIncrementCounter(event);
statusInfo.setSecurityLevel(new Integer32(2));
statusInfo.setErrorIndication(new VariableBinding(event.getOid(), event.getCurrentValue())); return status;
} }

重点在于:  int status = this.timeTable.checkTime(

new UsmTimeEntry(securityEngineID, usmSecurityParameters.getAuthoritativeEngineBoots(),  usmSecurityParameters.getAuthoritativeEngineTime())); 

通过这句话检查是否在时间窗口内,如果不在时间窗口内直接就抛出去。

这句话又调用了其他的方法,来让我们看下:在UsmTimeTable.java里面

public synchronized int checkTime(UsmTimeEntry entry) {
int now = (int) (System.currentTimeMillis() / 1000L);
if (this.localTime.getEngineID().equals(entry.getEngineID())) {
if ((this.localTime.getEngineBoots() == 2147483647)
|| (this.localTime.getEngineBoots() != entry.getEngineBoots())
|| (Math.abs(now + this.localTime.getTimeDiff() - entry.getLatestReceivedTime()) > 150)) {
if (logger.isDebugEnabled()) {
logger.debug(
"CheckTime: received message outside time window (authorative):"
+ ((this.localTime.getEngineBoots() != entry.getEngineBoots())
? "engineBoots differ"
: new StringBuffer().append("")
.append(Math.abs(now + this.localTime.getTimeDiff()
- entry.getLatestReceivedTime()))
.append(" > 150").toString()));
} return 1411;
} if (logger.isDebugEnabled()) {
logger.debug("CheckTime: time ok (authorative)");
}
return 0;
}

这个函数就是检查时间窗函数,注意了,getEngineBoots获取的是引擎运行次数,在第一次收到消息后,每秒增加一次,getEngineID标示引擎ID,好像一个用户一个引擎。

然后判断下这个时间:getLastestReceivedTime()注意这个时间是Snmp的Report消息的时候汇报时间,如果从开始收到第一条消息到150s内还没有汇报,则认为是不在时间窗口的丢弃掉。

尝试通过:  snmpListener.getUSM().getTimeTable().getEntry(new OctetString(securityName)).setLatestReceivedTime(((int) (System.currentTimeMillis() / 1000L))); 这个方法来设置下,结果还一样,可能还有更好办法。

不过既然是协议的要求,这种防止攻击的机制,那么就暂时保留吧。

 

关于Snmp的Trap代码开发之坑的更多相关文章

  1. 微信小程序中途加入云开发之坑

    一开始未使用云开发的小程序项目,之后想使用云开发能力时,要先删除对应在开发者工具中的项目(先压缩备份源码!),再用开发者工具重新创建,很多时候都需要用这种方式进行处理

  2. 插件开发之360 DroidPlugin源码分析(五)Service预注册占坑

    请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52264977 在了解系统的activity,service,broa ...

  3. 插件开发之360 DroidPlugin源码分析(四)Activity预注册占坑

    请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52258434 在了解系统的activity,service,broa ...

  4. UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

    前面[UWP开发之Mvvmlight实践五:SuspensionManager中断挂起以及复原处理]章节已经提到过Template10,为了认识MvvmLight的区别特做了此实例. 原代码地址:ht ...

  5. Android NDK开发之C调用Java及原生代码断点调试(二)

    上一篇中,我们主要学习了Java调用本地方法,并列举了两大特殊实例来例证我们的论据,还没学习的伙伴必须先去阅读下,本次的学习是直接在上一篇的基础上进行了.点击:Android NDK开发之从Java与 ...

  6. Android安全开发之ZIP文件目录遍历

    1.ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在“../”的字符串,攻击者可以利用多个“../”在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原有的文件.如果被覆盖掉的文件是动态链接s ...

  7. Cocos2d-x 3.x游戏开发之旅

    Cocos2d-x 3.x游戏开发之旅 钟迪龙 著   ISBN 978-7-121-24276-2 2014年10月出版 定价:79.00元 516页 16开 内容提要 <Cocos2d-x ...

  8. Linux内核驱动开发之KGDB原理介绍及kgdboe方式配置

    接博文<Linux内核驱动开发之KGDB单步调试内核(kgdboc方式)>.上篇博文中,仅简单介绍使用串口的Kgbd的流程(kgdboc方式),本文将重点介绍KGDB调试Linux内核的原 ...

  9. 李洪强iOS开发之RunLoop的原理和核心机制

    李洪强iOS开发之RunLoop的原理和核心机制 搞iOS之后一直没有深入研究过RunLoop,非常的惭愧.刚好前一阵子负责性能优化项目,需要利用RunLoop做性能优化和性能检测,趁着这个机会深入研 ...

随机推荐

  1. winform网络编程之TcpClient类,TcpListener类和UdpClient类

    TcpClient类和TcpListener类 (1)TcpClient的用途: 用于在同步阻止模式下通过网络来链接.发送和接受流数据,在此情况下,必须有侦听此连接的请求,而侦听的任务就交给TcpLi ...

  2. plsql 存储过程 测试

      plsql 存储过程 测试 CreationTime--2018年8月14日09点54分 Author:Marydon 1.找到要运行的存储过程-->选中-->右键-->测试 2 ...

  3. KnockoutJS + My97DatePicker b

    如何将Knockoutjs和其他脚本库结合使用?这里给出一个Knockoutjs与my97datepicker配合使用的例子,例子中使用了ko的自定义绑定功能: ko.bindingHandlers. ...

  4. 通过jdbc使用PreparedStatement,提升性能,防止sql注入

    为什么要使用PreparedStatement? 一.通过PreparedStatement提升性能 Statement主要用于执行静态SQL语句,即内容固定不变的SQL语句.Statement每执行 ...

  5. 坦克大战-C语言-详注版

    代码地址如下:http://www.demodashi.com/demo/14259.html 坦克大战-C语言-详注版 概述 本文详述了C语言版坦克大战游戏的原理以及实现方法,对游戏代码进行了详细的 ...

  6. 微信小程序横版日历,tab栏

    代码地址如下:http://www.demodashi.com/demo/14243.html 一.前期准备工作 软件环境:微信开发者工具 官方下载地址:https://mp.weixin.qq.co ...

  7. ELK日志分析平台搭建全过程

    一.使用背景 当生产环境有很多服务器.很多业务模块的日志需要每时每刻查看时 二.环境 系统:centos 6.5 JDK:1.8 Elasticsearch-5.0.0 Logstash-5.0.0 ...

  8. 让MyEclipse支持mac的Retina屏解决字体模糊的问题

    最近在使用MyEclipse时最让我头疼的问题就是MyEclipse并不能很好的支持苹果的Retina屏幕,看着字体会非常模糊,那叫一个心酸,真白瞎了这块好屏幕.(不知道最新的版本有没有支持,反正我的 ...

  9. 一些很经典的JavaScript的问题

    1.作用域 (function() { var a = b = 5; })(); console.log(b); 输出:5 陷阱是,在函数表达式中有两个赋值,但a是用关键字var 来声明的,这意味着a ...

  10. Linux查看GPU信息和使用情况

    Linux查看显卡信息: lspci | grep -i vga 使用nvidia GPU可以: lspci | grep -i nvidia [root@gpu-server-002 ~]# lsp ...