最近是被这个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. python之函数用法__getitem__()

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python之函数用法__getitem__() #http://www.cnblogs.com/hongf ...

  2. php 5.3新特性

    1.命名空间 解决了类,函数和常量名冲突的问题 2.静态绑定 继承时父类可以直接调用子类重写父类的方法 class A { public static function who() { echo __ ...

  3. 架构-LAMP特级学习(网站服务器监控)

    1.服务监控(SNMP配合CACTI监控) Apache Web服务监控 MySQL数据库监控 磁盘空间监控 2.流量监控(SNMP配合MRTG监控) 网站流量监控 3.使用SNMP可以获取被监控服务 ...

  4. Block编程注意的问题

    一,前言   block 是在 iOS 4 中引入的新特性,它和 C++ 11 中的 lamba 表达式概念相似,有时候也被称为闭包.经过一段时间的使用,我发现要用对用好 block 还是有不少需要注 ...

  5. 【LeetCode】136. Single Number (4 solutions)

    Single Number Given an array of integers, every element appears twice except for one. Find that sing ...

  6. Chrome浏览器桌面通知提示设置

    版本 24.0.1312.56 m     老版本23.* 桌面通知,也可以由用户在Chrome浏览器中自定义:板手 -> 选项  -> 高级选项 –> 通知 (管理例外情况…).

  7. Android 小技巧-- TextView与EditText 同步显示

    方法一.利用View.OnKeyListener"同步"显示 EditText  myEdit = (EditText)findViewById(R.id.myEdit); Tex ...

  8. python os库学习笔记

    os.getcwd(): 获取当前目录 os.name: 获取当前使用的操作系统 eg: print os.name os.remove(): 删除指定文件 eg: os.remove('test.t ...

  9. IIS下浏览指定文件(如:web.config)

    具体步骤如下: 1.快捷键:Ctrl + R 2.输入:%windir%\System32\inetsrv\config\applicationHost.config 3.注销:fileExtensi ...

  10. Android vcard使用示例,生成vcf文件

     Android vcard使用示例,生成vcf文件 我们备份手机联系人时,导出到SD卡时,会在SD卡中生成一个vcf文件,用于保存联系人姓名,手机号码. vCard 规范容许公开交换个人数据交换 ( ...