zoukankan      html  css  js  c++  java
  • Pcap4J实现抓包器

    前段时间搞抓包程序,打算使用Pcap4J实现,发现除了GitHub,其它资料少之又少,几乎都是不起作用。

    被迫我一直看(日本作者!)英文注解的源码和sample和test,比较费劲+营养很少。因为几乎都是解析本地保存的抓包文件  同  初始化好的包类型对象做比较,没有对真实的网络环境抓包举例。都按指定类型初始化对象不是重点好不好,重点是怎么把抓到的包转换到指定类型!

    说一下我们要使用Pcap4J的原因。

    之前一直是使用jNetPcap的,但是它已经很久不更新代码了,并且在linux上跑不起来。使用时还需要根据操作系统加载不同的jar包。

          Pcap4J和jNetPcap相同之处,都是基于libpcap/winpcap的。于是乎,过滤器规则也是通用的(比较关键)。过滤器写法可以直接去wareshark验证。

    代码使用上,Pcap4J 和 jNetPcap很相似,不同的是,Pcap4J 比jNetPcap 封装的更多些,其实不好,它想让我们写的更少,却不太灵活了。

    Pcap4J 不用分操作系统引用不同的包,支持linux比较好,比较不错。

    更多优点去参考Github,据说Pcap4J既可以抓包,又可以发包,还多支持了SNMP。当然,对linux的良好支持就够打动我了。

    maven 引用的部分

    <dependencies>
        <dependency>
          <groupId>org.pcap4j</groupId>
          <artifactId>pcap4j-core</artifactId>
          <version>1.6.3</version>
        </dependency>
        <dependency>
          <groupId>org.pcap4j</groupId>
          <artifactId>pcap4j-packetfactory-static</artifactId>
          <version>1.6.3</version>
        </dependency> ... </dependencies>

    开始贴代码吧,只是大体轮廓,意思都到了。

     // 获取所有网卡设备
        List<PcapNetworkInterface> alldev = Pcaps.findAllDevs();   // 根据设备名称初始化抓包接口
        PcapNetworkInterface nif = Pcaps.getDevByName(alldev.get(devicenum).getName()); // 抓取包长度
        int snaplen = 64 * 1024; // 超时50ms
        int timeout = 50; // 初始化抓包器
        PcapHandle.Builder phb = new PcapHandle.Builder(nif.getName()).snaplen(snaplen) .promiscuousMode(PromiscuousMode.PROMISCUOUS).timeoutMillis(timeout) .bufferSize(1 * 1024 * 1024); PcapHandle handle = phb.build(); // handle = nif.openLive(snaplen, PromiscuousMode.NONPROMISCUOUS, timeout);
    
        /** 设置TCP过滤规则 */ String filter = "ip and tcp and (dst host 127.0.0.1 and dst port 80)"; // 设置过滤器
        handle.setFilter(filter, BpfCompileMode.OPTIMIZE);

    filter过滤器只是例子,要根据自身需求写过滤器。

    再写个loop,也就是观察者模式(高大上了有木有!),抓到包后就回调。

    这里没写try-catch 也没啥牛逼的逻辑。代码意思就是抓到包后,都调gotPacket方法。

    或者,你也可以实现自己的loop即无限循环处理包,方法是:

    Packet packet = handle.getNextPacket();

    这样实现的结果就是:直接在嗅探线程返回抓到的包,等待对这个包进行处理(阻塞后面的接收)。这其实是个阻塞方法,就是说可以一个接一个抓到包然后处理,而不是说抓到一个包后它不等你,你还处理呢,后面的包都溜了。

    再往下走,其实比较恶心了。困扰了好几天。

    铺垫下,以下处理的都是TCP/IPv4协议包如果有其他更好的实现方式一定要告诉我!

          说下恶心的原因。

    handle 获取到的包,都是原始类型的packet,debug看到的叫unknownPacket类型。而从各种例子,网络,包括作者的test + sample举例,都没发现怎么把未知类型的packet 转换到可以使用的包类型,如TcpPacket,IpV4Packet(对了,这里作者还分了v4 和 v6 两个版本的IP协议),它们都是Packet的子类。

    然后我们逼不得已,对着TCP/IP协议的教材(是一种对网络知识的复习!),搞一套实现方式。

    贴代码了,但愿我写的代码注释能释然你们。

    byte[] rawData = pcapPacket.getRawData();
    // 如果抓包内容长度都小于最小硬件协议长度,则直接返回。
    if (rawData.length < 14) {
        return;
    }
    
    IpV4Packet ipV4Packet = null;
    TcpPacket tcpPacket = null;
    // 由于默认过滤器过滤为IP和TCP协议包,可以直接判断rawData长度。
    // 只判断IpV4协议,通过rawData数据得出IpV4头部长度。header_length标识在rawDta第15字节值,即(刨去前14位Ethernet协议长度)的后4个bit,
    // 则IpV4协议头部长度,最长为4位二进制数最大值15(4bit最大值) * 4 = 60 字节(1字节为8位即rawData数组中的一个数字)
    int ipV4HeaderLength =
        Integer.parseInt(Integer.toHexString(rawData[14]).charAt(1) + "")
            * 4;
    ipV4Packet = IpV4Packet.newPacket(rawData, 14, ipV4HeaderLength);
    
    // tcpOffset 是tcp协议开始的部分,开始于Ethernet协议和IpV4协议头部之后,存在于IpV4协议数据部分里。
    int tcpOffset = 14 + ipV4HeaderLength;
    // 方法解释:rawData数据, 头部的长度(按非数据内容处理),数据的长度(整个长度-非数据内容长度)
    tcpPacket = TcpPacket.newPacket(rawData, tcpOffset, rawData.length - tcpOffset);

    我解释一下,其实上面的代码真没经过太牛逼的检验,但是简单测试N次是符合我们要求的。

    我们是通过分析包内容rawData来转换对象的,用的都是包对象的构造方法。

    首先,截取到的rawData是分层次的(我们只要TCP和IP协议的东西),从头开始依次是:Ethernet协议,IpV4协议,TCP协议。

    再者,每个协议的定义是有规律的,都包含在rawData内容里。这样我们就可以分析。

    水平有限,只能简单解释一下每个协议的分析。

    1位byte = 8bit  即 两个 16进制数。

    Ethernet协议:  长度是14位是比较固定的, 包含:6位目的mac地址 + 6位源mac地址 + 2位协议类型。

    IPv4协议: 头部长度在整个长度第 15位 的第2个 16进制数上。 具体是换算成10进制后*4 的长度,即最长是60位。为什么乘以4,我解释不了,可能4是4bit的意思,默认的规则。头部长度最小是20位,深究的自己查一下吧。

    TCP协议:  IPv4协议的数据部分,就都是TCP协议的内容了,可以直接来用了。

  • 相关阅读:
    运算符
    JS的基本概念和数据类型
    开源基于Canal的开源增量数据订阅&消费中间件
    用AntDeploy如何更新Agent
    AntDeploy发布前端项目到IIS(脱离vs单独使用)
    截图上传录屏gif上传工具推荐
    netcore开发windows普通服务(非Web)并一键发布到服务器
    一键发布部署vs插件[AntDeploy]开源了
    基于python的Elasticsearch索引的建立和数据的上传
    浅谈闭包
  • 原文地址:https://www.cnblogs.com/welhzh/p/6956993.html
Copyright © 2011-2022 走看看