计算机网络课程设计
说明书
题 目: IP数据包抓获及分析
系 别: 计算机科学与工程学院
专 业: 软件工程
***** ***
学 号: **********
**** ***
题目类型: 理论研究 实验研究 工程设计 工程技术研究 软件开发
2011年 3月 25日
1设计任务………………………………………………………………………………1
1 需求分析…………………………………………………………………………1
1.1功能需求……………………………………………………………………… 1
1.2界面需求 ………………………………………………………………………1
1.3输入输出需求……………………………………………………………………… 1
3 总体设计……………………………………………………………………… 1
3.1设计技术……………………………………………………………………… 1
3.2功能设计 ………………………………………………………………………1
3.3IP数据包结构分析……………………………………………………… 1
4 详细设计…………………………………………………………………… 2
4.1界面设计……………………………………………………………………… 2
4.2详细功能设计 ………………………………………………………………………3
5 设计总结……………………………………………………………………… 9
6 使用说明…………………………………………………………………………… 10
1设计任务
本课程设计的内容是设计一个IP数据包的捕获解析器,将结果显示在输出设备上,并且保存为系统日志。
1 需求分析
2.1功能需求
能够对网络上的数据包进行捕获,分析,显示结果。保存为日志文件。
2.2界面需求
主面板,显示结果输出控制台,操作工具栏,网络端口选择界面
2.3输入输出需求
选择网络端口,打开IE浏览器上网,接收数据,数据包分析结果在输出面板上显示。
3 总体设计
3.1设计技术
使用java来开发本次课程设计,运用Jpcap类库来解决网络数据包的捕获分析问题,JPCAP实际上并非一个真正去实现对数据链路层的控制,而是一个中间件,JPCAP调用wincap/libpcap,而给 JAVA语言提供一个公共的接口,从而实现了平台无关性。
3.2功能设计
首先要检测本机的网络端口,选择网络端口后对其监控,当它接收或者发送数据包的时候进行捕获,对捕获的数据包进行分析,对于IP报文的结构的主要信息输出在显示界面,保存后可以随时用本程序进行查看。
3.3IP数据包结构分析
0 4 8 16 19 24 31
| 版本 | 报头标长 | 服务类型 | 总长度 | ||
| 标识 | 标志 | 片偏移 | |||
| 生存时间 | 协议 | 头校验和 | |||
| 源IP地址 | |||||
| 目的IP地址 | |||||
| 选项 | 填充域 | ||||
| 数据部分 | |||||
报头标长字段为4位,它定义了以4B为一个单位的IP包的报文长度.报头中除了选项字段和填充域字段外,其他各字段是定长的.因此,IP数据包的头长度在20—40B之间,是可变的。
服务类型(TOS)子域和3位优先级子域组成,1位为保留位,该字段结构如图
B7 b6 b5 b4 b3 b2 b1 b0
| 优先级 | D | T | R | C | 0 |
标识字段的长度为16位,用于识别IP数据包的编号.每批数据都要有一个标识值,用于让目的主机判断新来的数据属于哪个分组.
报头中的标志字段如图7-3所示.标志字段共3位,最高位是0.禁止分片标志DF(do not fragment)字段的值若为1,表示不能对数据包分片;若DF值为0,则表明可以分片.分片标志MF( more fragment)的值为1,表示接收到的不是最后一个分片;若MF值为0,表示接收到的是最后一个分片.
片偏移字段共13位,说明分片在整个数据包中的相对位置.片偏移值是以8B为单位来记数的,因此选择的分片长度应该是8B的整数倍.
生存时间(TTL)字段为8位,用来设置数据包在互联网络的传输过程的寿命,通常是用一个数据包可以经过的最多的路由器跳步数来限定的.
协议字段为8位,表示使用此IP数据包的高层协议类型
头校验和字段为16位,用于存放检查报头错误的校验码。检验的范围是整个IP包的报头
4 详细设计
4.1界面设计
显示网卡信息
选择网卡
4.2详细功能设计
获得网卡配置信息
要想从网络中捕获数据包,第一件必须要做的事就是获取本机的网络接口列表。Jpcap提供了方法JpcapCaptor.getDeviceList()完成这个任务,该方法返回一组NetworkInterface对象。
NetworkInterface接口对象包含了对应网络接口的一些信息,例如:名称、描述、IP以及MAC地址以及数据链路层名称和描述。
public NetworkInterface[] getDevices() {
devices = JpcapCaptor.getDeviceList();
return devices;
}
// 获得网卡接口list描述
public void desNetworkInterface() {
sb.append("************************网卡信息****************************************\\n");
sb.append("总共有 " + devices.length + " 个网络设备接口\\n");
for (int i = 0; i < devices.length; i++) {
sb.append("\\n设备接口" + (i + 1) + ":\\n");
sb.append("网络接口名称:" + devices[i].name+"\\n");
// 选中一个网卡接口进行监听
if (!(devices[i].name.contains("GenericDialupAdapter"))) {
device = devices[i];
}
sb.append("网络接口描述:" + devices[i].description+"\\n");
sb.append("数据链路层名称:" + devices[i].datalink_name+"\\n");
sb.append("数据链路层描述:" + devices[i].datalink_description+"\\n");
sb.append("是否是LOOPBACK设备:" + devices[i].loopback+"\\n");
sb.append("MAC地址:");
int flag = 0;
for (byte b : devices[i].mac_address) {
flag++;
if (flag < devices[i].mac_address.length) {
sb.append(Integer.toHexString(b & 0xff) + ":");
} else
sb.append(Integer.toHexString(b & 0xff)+"\\n");
}
}
sb.append("**********************************************************************\\n");
获得一个网卡的接口连接
一旦有了网络接口列表就可以从选定用于捕获数据包的网络接口,可以使用方法JpcapCaptor.openDevice()来打开网络接口。
调用JpcapCaptor.openDevice()方法必须指定下列参数:
名称 目的
NetworkInterderface 要打开的网络接口。
intrface
int snaplen 一次捕获数据包的最大byte数。
boolean prommics 是否采用混乱模式
混乱模式中,可以捕获所有数据包,即便源MAC或目的MAC地址与打开的网络接口的MAC地址不相同。而非混乱模式中只能捕获由宿主机发送和接收的数据包。
int to_ms 捕获的数据包的超时设置(数量级为毫秒)。
//获得一个网卡接口的连接
public void getCap(NetworkInterface nInterface, boolean mixMode,String filter){
try {
jCaptor = JpcapCaptor.openDevice(nInterface, 2048, mixMode, 5000);
} catch (IOException e) {
e.printStackTrace();
}
}
开始捕获数据包
首先定义一个实现PacketReceiver接口的类。PacketReceiver接口中定义了receivePacket()方法,只需实现receivePacket()这个方法。在类定义的时候继承PacketReceiver,然后在类中实现
public void receivePacket(Packet packet) {
packets.add(packet); //捕获包并保存到链表中
analysis(packet);//分析包
}
数据包分析
分析IP数据包
if(packet instanceof IPPacket){ //分析IP
IPPacket iPacket = (IPPacket)packet;
sb.append("---IP版本: "+iPacket.version+" ---\\n");
if(iPacket.version==4){ //分析IPv4协议
sb.append("Type of service:"+iPacket.rsv_tos+"\\n");
sb.append("Priority:"+iPacket.priority+"\\n");
sb.append("Packet Length:"+iPacket.length+"\\n");
sb.append("Identification:"+iPacket.ident+"\\n");
sb.append("Don't Frag? "+iPacket.dont_frag+"\\n");
sb.append("More Frag? "+iPacket.more_frag+"\\n");
sb.append("Frag Offset:"+iPacket.offset+"\\n");
sb.append("Time to Live:"+iPacket.hop_limit+"\\n");
sb.append("Protocol:"+iPacket.protocol+" (TCP = 6; UDP = 17)\\n");
sb.append("Source address:"+iPacket.src_ip.toString()+"\\n");
sb.append("Destination address:"+iPacket.dst_ip.toString()+"\\n");
sb.append("Options:"+iPacket.option+"\\n");
sb.append("------------------\\n");
}
分析以太网帧信息
if(dPacket instanceof EthernetPacket){ //分析以太网帧
EthernetPacket ePacket = (EthernetPacket)dPacket;
sb.append("src_mac:");
int flag1 = 0;
for(byte b:ePacket.src_mac){
flag1++;
if(flag1 }else sb.append(Integer.toHexString(b & 0xff)+"\\n"); } sb.append("dst_mac:"); int flag2 = 0; for(byte b:ePacket.dst_mac){ flag2++; if(flag2 }else sb.append(Integer.toHexString(b & 0xff)+"\\n"); } sb.append("frametype:"+Integer.toHexString(ePacket.frametype & 0xffff)+"\\n"); sb.append("------------------\\n"); }else{ sb.append(dPacket+"\\n"); sb.append("------------------\\n"); } 将数据保存 // 保存捕获包于文件中 public void saveFile(String fileName) { if(jCaptor == null){ JOptionPane.showMessageDialog(null, "No Packet yet! }else{ try { writer = JpcapWriter.openDumpFile(jCaptor, fileName); while (packets.size() != 0) { writer.writePacket(packets.removeFirst()); } writer.close(); } catch (IOException e) { e.printStackTrace(); } } } 这里传送的参数fileName在主窗口的代码中生成: else if(e.getSource()==F_save){ JFileChooser chooser = new JFileChooser(); int returnType = chooser.showSaveDialog(null); if(returnType==JFileChooser.APPROVE_OPTION){ File file = chooser.getSelectedFile(); String fileName = file.getAbsolutePath(); cPacket.saveFile(fileName); } 用线程对端口进行实时监控 public CatchPacket cPacket ; Thread thread = new Thread(cPacket); public void run() { while(true){ try { Thread.sleep(5000); beginCatch(); } catch (InterruptedException e) { e.printStackTrace(); } } } 5 设计总结 本次课程设计用时大概4天左右,主要的时间是在前期对JPCAP的了解,查询了相关的资料,编写简单的测试程序用于测试JPCAP的方法使用,然后还要比较深入的去了解IP报文的格式,知道JPCAP里的用JPCAPTOR来得到包的各项数据,解决了这些基本的操作的技术之后开始做界面设计,由于局限于功能的简单,本次设计的界面也很简单,主要包括一个主要的操作界面,用菜单工具栏开操作。经过这次课程设计以后,我觉得最主要的是更加的了解了IP报文的结构,对JPCAP的使用还是次要,因为它都已经封装好了方法,只需要调用就可以了,另外在对端口的监控的时候也运用了线程的方法,在设计的过程中还涉及到了其他方面的知识,如ARP以及UDP等协议的解析,还有了解到数据包在网络传输中的安全性问题。 6 使用说明 首先运行程序,可以看到菜单栏中有文件和选项2项,文件包括了打开,保存,退出。选项包括了显示本机网卡信息,网络端口选择,开始,停止。先选择网络端口,模式,报文类型 单击GO 然后单击选项中的开始,程序开始对选择的端口检测 可以打开本机的浏览器,浏览一个网站,可以看到程序开始显示捕获数据包的分析结果,单击选项中的停止终止对端口的监控。 文件->保存 输入文件名后就可以保存了,用本程序的打开功能就可以打开保存后的文件下载本文