当前位置: 首页 > 工具软件 > rawip4j > 使用案例 >

pcap4j 实现java 抓包及DNS解析

赵雅懿
2023-12-01

目前java实现解析pcap格式的三方库很多,如jnetpcapjpcappcap4j,但是jnetpcap和jpcap已经很久没有更新了,而且jnetpcap的跨平台表现不是很好,在Linux系统上在很多问题,我这边是获取不到网卡信息(root方式启动)。
综合考虑下来决定采用pcap4j,pcap4j 目前支持DNS、SNMP,以及传输层TCP、UDP,网络层的ARP、ICMP等协议,但是暂不支持Http协议解析,作者在issue中提到2.0版本会添加http支持。

环境准备

Mac/Linux/UNIX 需要安装libpcap,windows环境需要安装winpcap
Centos

yum install libpcap-devel

Ubuntu

apt-get install libpcap-dev

Mac

brew install libpcap

添加依赖

Gradle

compile 'org.pcap4j:pcap4j-core:1.+'
compile 'org.pcap4j:pcap4j-packetfactory-static:1.+'

Maven

<dependency>
  <groupId>org.pcap4j</groupId>
  <artifactId>pcap4j-core</artifactId>
  <version>[1.0, 2.0)</version>
</dependency>
<dependency>
  <groupId>org.pcap4j</groupId>
  <artifactId>pcap4j-packetfactory-static</artifactId>
  <version>[1.0, 2.0)</version>
</dependency>

代码实现

本部分不详细说明各个代码的实现逻辑,具体请查看代码注释吧。

获取抓包设备
可以根据设备名称、设备IP地址进行选择本地的网络设备,具体的代码如下:

  /**
     * 根据IP获取指定网卡设备
     * @param localHost 网卡IP
     * 
     * @return 指定的设备对象
     */
    public static PcapNetworkInterface getCaptureNetworkInterface(String localHost) {
        List<PcapNetworkInterface> allDevs;
        try {
            // 获取全部的网卡设备列表,Windows如果获取不到网卡信息,输入:net start npf  启动网卡服务
            allDevs = Pcaps.findAllDevs();

            for (PcapNetworkInterface networkInterface : allDevs) {
                List<PcapAddress> addresses = networkInterface.getAddresses();
                for (PcapAddress pcapAddress : addresses) {
                    // 获取网卡IP地址
                    String ip = pcapAddress.getAddress().getHostAddress();
                    if (ip != null && ip.contains(localHost)) {
                        // 返回指定的设备对象
                        return networkInterface;
                    }

                }
            }
        } catch (PcapNativeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

核心抓包代码

  /**
     *在线抓包以及保存至本地
     * 
     * @return
     * @throws InterruptedException
     */
    private boolean captureAndDumpLive() throws InterruptedException {
        //将回环地址替换成自己网卡地址( ipconfig 查看)
        PcapNetworkInterface nif = PcapNIfManager.getCaptureNetworkInterface("127.0.0.1");
        if (nif == null) {
            return false;
        }

        try {
            // 抓包
            pcapHandle = nif.openLive(SNAPLEN, PromiscuousMode.PROMISCUOUS, TIMEOUT);
            // 打开抓包数据写入文件
            dumper = pcapHandle.dumpOpen(DUMP_FILE);
            // 循环处理 -1 为持续抓包,直至中断退出,可以设定为正整数(抓包个数),
            pcapHandle.loop(-1, new CoreCaptureListener());
            //   也可以采用如下方式,进行循环抓包,
            /*
            while (true) {
                Packet packet = pcapHandle.getNextPacket();
                if (packet == null) {
                    continue;
                } else {
                    if (condition) {
                        break;
                    }
                }
            }*/

        } catch (PcapNativeException e) {
            e.printStackTrace();
            return false;
        } catch (NotOpenException e) {
            e.printStackTrace();
            return false;
        }
        return true;

    }

抓包处理

 class CoreCaptureListener implements PacketListener {

        /* (non-Javadoc)
         * @see org.pcap4j.core.PacketListener#gotPacket(org.pcap4j.packet.Packet)
         */
        @Override
        public void gotPacket(Packet packet) {
            // 解析DNS 数据信息
            if (packet.contains(DnsPacket.class)) {
                DnsHeader dnsHeader = packet.get(DnsPacket.class).getHeader();
                if (dnsHeader.isResponse()) {
                    dnsHeader.getAnswers().get(0).getName();
                } else {
                    dnsHeader.getQuestions();
                    // DNS 记录类型
                    dnsHeader.getQuestions().get(0).getQType();
                }
            }
            try {
                dumper.dump(packet);
            } catch (NotOpenException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

    }

结语

只是简单介绍了下pcap4j的基本应用,详细的说明还请去github上查看或者查看在线doc
本文demo下载地址

 类似资料: