前言
作业要求是写一个类似于wireshark的流量捕捉器,要求有gui界面,能监听到相关流量
这是逆天的老师布置的作业,感觉我们什么都会,java,py都没学过。真就硬着让我写。。还好有gpt能帮我
监听
使用监听库
监听指定的网卡,有两种的思路。首先可以使用python封装的pyshark和java封装的pcap4j这些包去监听流量。以下是一个用py写的简单的流量抓捕
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import pyshark
def packet_handler(pkt): print("start listening:") print(f"Source IP: {pkt.ip.src}, Destination IP: {pkt.ip.dst}") if hasattr(pkt, 'tcp'): print(f"Protocol: TCP, Source Port: {pkt.tcp.srcport}, Destination Port: {pkt.tcp.dstport}") elif hasattr(pkt, 'udp'): print(f"Protocol: UDP, Source Port: {pkt.udp.srcport}, Destination Port: {pkt.udp.dstport}") print(f"Packet Length: {pkt.length}")
shark = pyshark.LiveCapture(interface='eth0') shark.apply_on_packets(packet_handler)
|
这里就可以进行简单的流量捕捉了
已经能监听到了。
tcpdump
需要有这个软件,同时在root环境下进行监听
tcpdump可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用的信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| -a 将网络地址和广播地址转变成名字 -c 在收到指定的包的数目后,tcpdump就会停止; -d 将匹配信息包的代码以人们能够理解的汇编格式给出;以可阅读的格式输出。 -dd 将匹配信息包的代码以c语言程序段的格式给出; -ddd 将匹配信息包的代码以十进制的形式给出; -e 在输出行打印出数据链路层的头部信息; -f 将外部的Internet地址以数字的形式打印出来; -l 使标准输出变为缓冲行形式; -n 直接显示IP地址,不显示名称; -nn 端口名称显示为数字形式,不显示名称; -t 在输出的每一行不打印时间戳; -v 输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息; -vv 输出详细的报文信息; -F 从指定的文件中读取表达式,忽略其它的表达式; -i 指定监听的网络接口; -r 从指定的文件中读取包(这些包一般通过-w选项产生); -w 直接将包写入文件中,并不分析和打印出来; -T 将监听到的包直接解释为指定的类型的报文,常见的类型有rpc (远程过程调用)和snmp(简单 网络管理协议;)
|
界面
老师要求写一个GUI 的界面,方便操作
直接想到了java 的swing库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| setTitle("Packet Sniffer"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(800, 600); selectedProtocols = new ArrayList<>(); JPanel controlPanel = new JPanel(new FlowLayout()); outputTextArea = new JTextArea(30, 60); outputTextArea.setEditable(false); JScrollPane scrollPane = new JScrollPane(outputTextArea); JButton startButton = new JButton("Start"); startButton.addActionListener(e -> startCapture()); JButton stopButton = new JButton("Stop"); stopButton.addActionListener(e -> stopCapture()); controlPanel.add(startButton); controlPanel.add(stopButton); add(controlPanel, BorderLayout.NORTH); add(scrollPane, BorderLayout.CENTER);
|
这样就能搞出来一个简单的界面了
过滤器
要求能选择自己需要监听的流量,这里我选用的是tcpdump的命令,相对的简单
tcpdump提供了直接可以监听对应流量的方法,也就是直接加上想要的流量包
如
直接添加内容完成对应的界面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public Main() { setTitle("Packet Sniffer"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(800, 600);
selectedProtocols = new ArrayList<>();
JPanel controlPanel = new JPanel(new FlowLayout()); outputTextArea = new JTextArea(30, 60); outputTextArea.setEditable(false); JScrollPane scrollPane = new JScrollPane(outputTextArea);
JButton startButton = new JButton("Start"); startButton.addActionListener(e -> startCapture());
JButton stopButton = new JButton("Stop"); stopButton.addActionListener(e -> stopCapture());
JCheckBox tcpCheckBox = new JCheckBox("TCP"); JCheckBox udpCheckBox = new JCheckBox("UDP"); JCheckBox icmpCheckBox = new JCheckBox("ICMP");
portField = new JTextField(10);
tcpCheckBox.addActionListener(e -> handleProtocolSelection("tcp", tcpCheckBox.isSelected())); udpCheckBox.addActionListener(e -> handleProtocolSelection("udp", udpCheckBox.isSelected())); icmpCheckBox.addActionListener(e -> handleProtocolSelection("icmp", icmpCheckBox.isSelected()));
controlPanel.add(startButton); controlPanel.add(stopButton); controlPanel.add(tcpCheckBox); controlPanel.add(udpCheckBox); controlPanel.add(icmpCheckBox); controlPanel.add(new JLabel("Port:")); controlPanel.add(portField);
add(controlPanel, BorderLayout.NORTH); add(scrollPane, BorderLayout.CENTER); }
|
输出流量信息
使用ProcessBuilder去执行本地命令,然会使用BufferedReader把命令执行的结果读取出来
1 2 3 4 5 6 7
| ProcessBuilder builder = new ProcessBuilder(command); builder.redirectErrorStream(true); process = builder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); new Thread(() -> { String line;}
|
本来直接想Runtime.getRuntime().exec(command);去执行的,但是我的idea一直提示我说已经不用这个函数了。。。
将获取到的东西输出。add到输出框里面就好了
1 2
| outputTextArea.append(line + "\n"); outputTextArea.append("数据包原始流量:"+line+"\n");
|
切记正则下再出来不然巨丑
现在已经基本完成要求
运行结果
对的正则写不出
傻逼老师屁事好多
就接下来写入文件然后读取、
写入文件
1 2 3 4 5 6 7
| private void writeToFile(String fileName, String content) { try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName,true))) { writer.write(content+"\n"); } catch (IOException e) { e.printStackTrace(); } }
|
判断数据包时间戳是不是同一个时间,来判断是不是一个数据包的内容,然后写入数据就好了
文本超链接
写一个事件监听器,监听到点击文字就直接可以打开对应文件
1 2 3 4 5 6 7 8
| if (text.contains("点击这里查看流量包")) { String linkPrefix = "点击这里查看流量包=》<"; String linkSuffix = ">"; int startIndex = text.indexOf(linkPrefix) + linkPrefix.length(); int endIndex = text.indexOf(linkSuffix); String filename = text.substring(startIndex, endIndex); open.open_pcap(filename); }
|
文件打开
创建一个新的窗口然后直接打开文件就好了
1 2 3 4 5
| try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { String line; while ((line = reader.readLine()) != null) { textArea.append(line + "\n"); }}
|
项目结果
项目源码
作业结束了发,不给超