Windows 11
IntelliJ IDEA 2023.2.1
jpcap
获取网络接口列表,以网络接口为单位进行抓包。
创建线程池,每个线程代表一个网络接口和一个分析包的线程,线程池容量就等于网络接口数量+1。
根据用户选中的接口,执行线程池里面的线程进行抓包,将抓到的包存入一个队列。
分析线程对队列里面抓到的包进行逐个处理、分析,目前仅支持分析IP、TCP、UDP三种包。
其中,每次用户点击开始抓包按钮,都会从线程池取出一个用于抓包的线程;但是分析包的线程只有在程序启动的时候创建,这个线程将处理整个程序运行过程中抓到的全部包
布局如图所示,现介绍使用方法:
choose device:
为一个选项框,里面列出了获取到的所有网络接口。
选择一个选项可以对特定接口进行抓包,选择all表示对全部接口进行抓包;选择choose a device表示先暂停不抓包。
选择选项的时候抓包处于暂停状态
start按钮:
点击start后程序会先清除当前抓到的所有包的记录,然后对所选接口进行抓包。
clear按钮:
清除抓包记录
filter:
过滤器,要求输入大写字符串
目前仅支持输入IP、TCP、UDP、SRC+IP地址、DST+IP地址。分别表示只抓某个类型的包和只抓源/目的为指定IP地址的包
输入过滤条件之后要重新选择接口并按start,过滤条件才可生效
抓包展示表格部分:
time stamp:表示时间戳,保留两位小数单位为ms
src ip:表示源IP地址
dst ip:表示目的IP地址
protocol:表示协议类型
length:表示包数据部分的长度
info:表示包的重要信息
IP:TTL、identification、version
TCP:ACK、SEQ、DST_PORT、SRC_PORT
UDP:上层协议、DST_IP、SRC_PORT
public static String selectedOption:表示用户在filter输入的内容,因为设置为全局变量,因此如果在抓包过程中改变这个值也是支持的
public static volatile boolean isRunning:表示程序是否结束,初始为true,在程序退出时执行的关闭逻辑被设为false,目的是保证执行AnalyzePacket()任务的线程安全退出
public static BlockingQueue packetQueue = new LinkedBlockingQueue<>():存包的队列,保证全局且线程安全
window.chooseDevice.addActionListener:监听用户选的网卡是哪个
window.startBtn.addActionListener:监听用户是否点击开始按钮,根据用户选择的网卡从线程池启动线程
window.clearBtn.addActionListener:监听用户是否要清空屏幕
NPCWindow.table.getSelectionModel().addListSelectionListener:根据用户选择的表项(包),来显示包的数据部分的字节和字符串
Runtime.getRuntime().addShutdownHook:启动一个新线程用于执行程序退出的逻辑,使用 shutdown 和 awaitTermination 来优雅地关闭线程池,确保所有线程在程序关闭时正确终止
private void clearTable()
当用户点击clear按钮时清空抓包展示表项
清空packetQueue
private void AnalyzePacket()
用来分析包的函数
将packetQueue里面的包取出来进行分析
private void NetworkPacketCap(NetworkInterface device)
对device这个网络接口进行抓包,将抓到的包放入packetQueue
显示status的信息
class PacketHandler implements PacketReceiver
这是用于抓包、处理包的类,与Main在同一个包内,其作用有:
根据包的类型处理包
将处理包得到的信息显示在图形化界面上
将包里面的二进制流转换为16进制和String
public void receivePacket (Packet packet)
取得filter里面的字段,并根据过滤条件来过滤包
对每个包单独处理,获取包展示表项需要的所有信息并将其加入表的数据集
在控制台打印出包数据部分的16进制和String
public void addToTable(String time, String srcip, String dstip, String pro, String len, String info, String dataByte, String dataStr)
为包展示表格添加一行表项,表项内容即为传入的参数
public String toCharString(byte[] dataByte)
将包的数据部分由二进制字节数组转换为String
public String toHexString(byte[] dataByte)
将包的数据部分由二进制字节数组转换为16进制字符串
public String inferProtocol(int sourcePort, int destinationPort, String str)
根据源端口和目标端口推断包的上层协议
目前仅能知道HTTP、HTTPS、DNS三种
public class NPCWindow extends JFrame
JFrame
是Java Swing库中的一个类,用于创建图形用户界面(GUI)应用程序的顶层窗口。NPCWindow是它的子类
作用:构造、整合图形化界面
public NPCWindow()
显示图形化窗口
public static JTextField getFilterField()
获取filter示例
public void createNewWindow()
规定窗口大小
将窗口的各个部分整合在一起,包括之前图示中的所有部分
用于设置图形化窗口各个部件的类,与NPCWindow在同一个包内
作用:详细设置图形化界面的每个部分
public void setTopPanel(NPCWindow window)
设置顶部面板的样式
创建choose a device选项框并规定它的长度和内容
创建start、clear按钮并规定它的长度
创建filter输入框并规定它的长度
如果选择了对所有的网卡进行抓包,就从线程池为每一个网卡分配一个线程,该线程执行mainObj.NetworkPacketCap(device)函数,表示对该device进行抓包。这个线程的主要作用就是抓包,并且将抓到的包放入线程安全的队列packetQueue
创建分析包的线程,该线程只有在用户启动程序时创建,在程序退出时被回收。这个线程的主要作用就是取出packetQueue里面的包,并将其交给PacketHandler类来分析包。相当于所有抓包线程抓到的包都将由这一个线程来处理。
最核心的就是这段代码:
window .startBtn .addActionListener (new ActionListener () {
@ Override
public void actionPerformed (ActionEvent e ) {
for (NetworkInterface device : devices ) {
if (selectedOption .equals (device .name + " - " + device .description ) || selectedOption .equals ("all" )) {
// 改变这个值使得当前线程可以结束
isCapturing = false ;
if (!selectedOption .equals ("all" )) {
// 等待一段时间,以确保之前的抓包线程能够结束
try {
Thread .sleep (1000 ); // 1秒钟
} catch (InterruptedException ex ) {
ex .printStackTrace ();
// 提交任务给线程池执行
threadPool .submit (() -> mainObj .NetworkPacketCap (device ));
// 创建处理包的线程
threadPool .submit (() -> mainObj .AnalyzePacket ());