好久没学计网的知识了,这里摸一下snmp协议。
snmp协议
SNMP 是专门设计用于在 IP 网络管理网络节点(服务器、工作站、路由器、交换机及HUBS等)的一种标准协议,它是一种应用层协议。 SNMP 使网络管理员能够管理网络效能,发现并解决网络问题以及规划网络增长。通过 SNMP 接收随机消息(及事件报告)网络管理系统获知网络出现问题。
snmp技术特点
(1)基于TCP/IP互联网的标准协议,传输层协议一般用UDP
(2)自动化网络管理。网络管理员可以利用SNMP平台在网络上的节点检索信息、修改信息、发现故障、完成故障诊断、进行容量规划和生成报告
(3)屏蔽不同设备的物理差异,实现对不同厂商产品的自动化管理。SNMP只提供最基本得功能集,使得管理任务与被管理设备的物理特征和实际网络类型相对独立,从而实现对不同厂商设备的管理
(4)简单的请求-应答方式和主动通告方式相结合,并有超时和重传机制
(5)报文种类少,报文格式简单,方便解析,易于实现
(6)SNMPv3版本提供了认证和加密安全机制,以及基于用户和视图的访问控制功能,增强了安全性
snmp网络架构
snmp中的OID
MIB是以树状结构进行存储的,树的节点表示被管理对象,它可以用从根开始的一条路径唯一地识别,这条路径就称为OID。
安装snmp协议
在windows上开启snmp服务,流程如下:
设置--->更新与安全--->开发者选项--->打开开发者模式
设置--->应用与功能--->添加功能--->添加简单网络管理协议(SNMP)
打开服务程序--->开启snmp服务(安装完成之后可能会自动开启)
以管理员模式运行powershell,在命令行中输入以下命令查看服务是否正常。
可以看到状态是Installed表示snmp服务是正常的。
使用java实现snmp包的发送
在实现代码之前需要用到SNMP4J.jar包,需要下载导入到Externel Libraries。
或使用maven构建项目,在pom.xml中添加依赖
<dependencies>
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j</artifactId>
<version>2.8.2</version>
</dependency>
<dependencies>
这里单纯给出转发snmp数据包的代码
public void Set(String type)
{
try{
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
target = new CommunityTarget();
target.setCommunity(new OctetString("public"));
if(v==1)
{
target.setVersion(SnmpConstants.version1);
}
if(v==2)
{
target.setVersion(SnmpConstants.version2);
}
ip=ipAddress.getText();
String port=Port.getText();
target.setAddress(new UdpAddress(ip+"/"+port));
target.setRetries(1);
target.setTimeout(1000);
long l=System.currentTimeMillis();
int iii=0;
snmp.listen();
PDU request = new PDU();
String OID=Oid.getText();
if(type.equals("Get"))
{
request.setType(PDU.GET);
request.add(new VariableBinding(new OID(OID)));
}
if(type.equals("GetNext"))
{
request.setType(PDU.GETNEXT);
request.add(new VariableBinding(new OID(OID)));
}
System.out.println("发送的UDP:" + request);
PDU response = null;
ResponseEvent responseEvent = snmp.send(request, target);
iii=1;
long ll=System.currentTimeMillis()-l;
System.out.println("所用时间<=>:"+ll+" "+iii);
response = responseEvent.getResponse();
ll=System.currentTimeMillis()-l;
if(response!=null){
if(response.getErrorStatus()==response.noError){
String pause=responseEvent.getResponse().getVariableBindings().toString();
String getvalue=pause.substring( pause.indexOf("= ")+2,pause.indexOf(']'));
String oid=pause.substring(pause.indexOf("VBS[")+2,pause.indexOf("=")-1);
System.out.println(oid+"::");
System.out.println(response);
if(type.equals("Get"))
{
responseText.setText("");
responseText.append(change(getvalue));
}
if(type.equals("GetNext"))
{
Oid.setText(oid);
responseText.setText("");
responseText.append(change(getvalue));
}
}
}
iii=0;
}
catch(Exception e){e.printStackTrace();}
}
使用Swing实现GUI界面
jpcap的部署:https://github.com/jovigb/jpcap-x64
git下载该项目后,在bin目录下,有对应的jar包,在使用之前需要将jpcap.dll放在jre的bin目录下。
swing为实现GUI提供了方便的操作,我们要使用Swing来实现对snmp的发包操作,同时提供可视化的界面来实现接收用户数据的操作。
下面给出设计swing的框架,这里只说明ip地址和port的传入方法。
public class snmptest extends JFrame
{
private static final long serialVersionUID = 1L;
private JPanel jContentPane = null;
private JLabel jLabel = null;
private JLabel jLabel1 = null;
private JTextField ipAddress = null;
private JTextField Port = null;
private CommunityTarget target=new CommunityTarget();
private static String ip="192.168.56.1";
private int v;
public snmptest()
{
super();
initialize();
}
private void initialize()
{
this.setSize(428, 374);
this.setContentPane(getJContentPane());
this.setTitle("Send_Receive");
}
private JPanel getJContentPane()
{
if (jContentPane == null) {
jLabel1 = new JLabel();
jLabel1.setBounds(new Rectangle(0, 20, 107, 30));
jLabel1.setText("本地IP:");
jLabel = new JLabel();
jLabel.setBounds(new Rectangle(200, 20, 107, 30));
jLabel.setText("Port:");
jContentPane = new JPanel();
jContentPane.setLayout(null);
jContentPane.add(jLabel, null);
jContentPane.add(getIpAddress(), null);
jContentPane.add(jLabel1, null);
jContentPane.add(getport(), null);
}
return jContentPane;
}
private JTextField getIpAddress()
{
if (ipAddress == null) {
ipAddress = new JTextField();
ipAddress.setBounds(new Rectangle(40, 20, 100, 20));
try{
InetAddress address=InetAddress.getLocalHost();
String IP_name=address.getHostAddress();
ipAddress.setText(IP_name);
}
catch(UnknownHostException e){ }
}
return ipAddress;
}
private JTextField getport()
{
if (Port == null) {
Port = new JTextField();
Port.setBounds(new Rectangle(240, 20, 100, 20));
Port.setText("161");
}
return Port;
}
完成这个程序之后,就可以使用wireshark进行snmp数据包的抓取了。
这里由于技术原因,设置目标为本地ip地址,发送方也为本地ip地址。使用loopback网卡获取本地环回地址的数据包。
查看ip数据包的详细信息
使用jpcap实现数据包的抓取
Jpcap并非一个真正去实现对数据链路层的控制,而是一个中间件,JPCAP调用winpcap/libpcap,给 JAVA语言提供一个公共的接口,从而实现了平台无关性。
最常用的类
JpcapCaptor:该类提供了一系列静态方法实现一些基本的功能。该类一个实例代表建立了一个与指定设备的链接,可以通过该类的实例来控制设备,例如设定网卡模式、设定过滤关键字等等。
其他的类有IPPacket,UDPPacket等有关于TCP/IP协议族中的相关类,这些类帮助可以完成各种报文分析操作。
下面贴出实现抓包的代码来说明API的调用方法。
public void capture()
{
Packet pa;
try
{
NetworkInterface[] NI=JpcapCaptor.getDeviceList();
JpcapCaptor jpcap1= JpcapCaptor.openDevice(NI[2], 1000, true,50);
for(int i=0;i<200;i++)
{
begin=getBeginValue();
if(begin)
{
pa=jpcap1.getPacket();
if (pa instanceof IPPacket)
{
IPPacket ip=(IPPacket)pa;
jta.append(ip.src_ip+"\t\t"+ip.dst_ip+"\t\t"+ip.protocol+"\t"+ip.version);
jta.append("\r\n");
if(ip.protocol==17)
{
UDPPacket udp=(UDPPacket)pa;
if(udp.src_port==161||udp.dst_port==162)
{
Analy(udp);
}
}
}
}
else
break;
}
}
catch (Exception e)
{
e.printStackTrace();
这里运行程序,可以看到这里抓取的是我电脑上WLAN网卡的数据包
查看运行结果
以上就是整个项目的重要部分了,虽然程序并不完善,但是也完成了很多功能。详细程序可以在下载处进行下载。
|