使用Jcap捕获数据包

 使用JPcap可以发包,使用JnetPcap可以接收和过滤包。现在项目中遇到的问题总结如下。

1.  环境搭建

如果是在Window下则必须在path路径下存在JnetPcap.dll和Jpcap.dll文件,如果是在linux环境下,可以将JnetPcap.so和JnetPcap.so存放到/usr/lib目录下即可,但是最好的解决方案是讲将两个so文件存放到项目目录下,然后使用

System.load(System.getProperty(“user.dir”)+/so文件相对路径)。

2.  无法打开网卡,或者是存在主备网卡的问题(bond网卡)

解决方案:直接使用网卡名称打开网卡   

  Pcap pcap=Pcap.openLive("eth0",64*1024,Pcap.MODE_NON_PROMISCUOUS,new StringBuilder()); 
 //Pcap pcap=Pcap.openLive(网卡名称,包大小,网卡模式,错误信息);           

说明:网卡名称一般为eth0等

           包大小一般为64*1024

           网卡模式一般为Pcap.MODE_NON_PROMISCUOUS混合模式

           错误信息其中存放的是当网卡打开失败后返回的系统信息,一般为StringBuilder

3.  如何循环捕包

通过上面得到的Pcap网卡对象就可以循环捕包了,大致程序逻辑如下:

      由于会一台机器上可能会有多个网卡,所以抓包前应先进行网卡的绑定

  Pcap pcap=Pcap.openLive("eth0",64*1024,Pcap.MODE_NON_PROMISCUOUS,new StringBuilder()); 
PcapBpfProgram  filter = new PcapBpfProgram(); 
String       expression=”   ”;
int  r=pcap.compile(filter ,  expression , 0,  0);
if(r==Pcap.OK){
       Pcap.setFilter(filter);
}
PcapPacketHandler<Object>    handler=newPcapPacketHandler<Object>(){
        @Override
          public   void nextPcaket( PcapPacket  oriPcaket,Object  arg1){
                   //oriPcaket为在网卡上根据filter捕获的包
                //具体的业务逻辑在这里添加
    }
}
pcap.loo(-1,handler,”可以随便起个名字”);//第一个参数指示接收的包数,如果为-1则表示一直接收,10则表示收取10个包后就不再收包了。

特别说明:

扫描二维码关注公众号,回复: 2496691 查看本文章

1.     表达式expression的重要性,因为同一时刻网卡有可能会收到大量的包,如果不加上过滤器那么程序的处理能力肯定是达不到的。

2.     过滤表达式示例:

String  expression=”ip   and  udp src port  12345 and dst port  54321  and eth  src  not 11:22:33:44:55:66”;

该表达式过滤使用了IP和UDP协议,并且源端口为12345,目的端口为54321,并且源mac地址不为11:22:33:44:55:66,只有满足上述所有条件,才会被到。

4.  包结构

 

内容

长度

eth头

源mac,目的mac

14字节

ip头

源IP,目的IP

20字节

udp头

源端口,目的端口

8字节

负载

数据

不定

1. 得到mac

EtherNet   ethe=newEtherNet();
PcapPcaket  pcaket;
if(pcaket.hasHeader(ethe)){
    String   srcMac= FormatUtils.mac(ethe.source());
    String   dstMac= FormatUtils.mac(ethe.destination());
}

2. 得到ip

Ip4    ip   =new Ip4();
byte  srcIp=new byte[4];
byte  dstIp=new byte[4];
PcapPcaket  pcaket;
If(pcaket.hasHeader(ip)){
    srcIp =ip.source();
dstIp=ip. Destination();
}

3. 得到端口

Udp udp=new Udp();
PcapPcaket  pcaket;
If(pcaket.hasHeader(usp)){
    int  srcPort=udp.source();
    int  dstPort=udp.destination();
}

猜你喜欢

转载自blog.csdn.net/callmev6/article/details/80989058