无法在 pcap4j 中读取 TcpPacket

Cannot read TcpPacket in pcap4j

我正在尝试使用 pcap4j 从环回地址获取 TcpPackets。我可以成功读取数据包,但无法将它们转换为 TcpPackets:

public class Main {
    public static void main(String[] args) throws Exception {
        PcapNetworkInterface device = null;
        try {
            PcapNetworkInterface nic = new NifSelector().selectNetworkInterface();
            System.out.println(nic);
            PcapHandle handle = nic.openLive(65536, PcapNetworkInterface.PromiscuousMode.PROMISCUOUS, 10000);
            handle.setFilter(
                    "tcp port 8080",
                    BpfProgram.BpfCompileMode.OPTIMIZE
            );

            while (handle.isOpen()) {
                Packet packet = handle.getNextPacketEx();
                if (packet != null) {

                    TcpPacket tcpPacket = packet.get(TcpPacket.class);
                    System.out.println(tcpPacket);

//                    EthernetPacket ethernetPacket = EthernetPacket.newPacket(packet.getRawData(), 0, packet.length());
//
//                    Dot1qVlanTagPacket dot1qVlanTagPacket = Dot1qVlanTagPacket.newPacket(ethernetPacket.getRawData(), 0, ethernetPacket.length());
//
//                    IpV4Packet ipV4Packet = IpV4Packet.newPacket(dot1qVlanTagPacket.getRawData(), 0, dot1qVlanTagPacket.length());
//
//                    TcpPacket tcpPacket1 = TcpPacket.newPacket(ipV4Packet.getRawData(), 0, ipV4Packet.length());
//                    System.out.println(tcpPacket1);
                }
            }

        } catch (Exception e) {
            System.out.println(e.getClass() + " " + e.getMessage());
        }
    }
}

注意事项:

我正在使用 getNextPacketEx,因此我可以从 packet factory 中获益

我在 pom.xml 中的依赖项看起来像

<dependencies>
    <dependency>
        <groupId>org.pcap4j</groupId>
        <artifactId>pcap4j-core</artifactId>
        <version>1.8.2</version>
    </dependency>
    <dependency>
        <groupId>org.pcap4j</groupId>
        <artifactId>pcap4j-packetfactory-propertiesbased</artifactId>
        <version>1.8.2</version>
    </dependency>
</dependencies>

我还尝试过手动解包(请参阅注释代码)。在我得到一个包含碎片数据的 IpV4Packet 之前,它一直有效。

当我尝试构建 TcpPacket.newPacket... 我收到错误消息:

class org.pcap4j.packet.IllegalRawDataException The data offset must be equal or more than 5, but it is: 0

我想做的是读取 tcp 数据包,重新组装它们,然后读取我想要嗅探的 http 内容。有人可以帮忙吗?

更新: 这是 ipv4 数据包的完整转储,用于在端口 8080 中的本地主机上进行简单的 Http 获取:

name: [\Device\NPF_Loopback] description: [Adapter for loopback traffic capture] loopBack: [true]] up: [true]] running: [true]] local: [true]
[IPv4 Header (32 bytes)]
  Version: 1 (unknown)
  IHL: 8 (32 [bytes])
  TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
  Total length: 0 [bytes]
  Identification: 24591
  Flags: (Reserved, Don't Fragment, More Fragment) = (true, true, true)
  Fragment offset: 5741 (45928 [bytes])
  TTL: 0
  Protocol: 32 (MERIT-INP)
  Header checksum: 0x0680
  Source address: /0.0.0.0
  Destination address: /0.0.0.0
  Option: [option-type: 0 (End of Option List)]
  Padding: 0x00 00 00 00 00 00 01 00 00 00 00
[Fragmented data (44 bytes)]
  Hex stream: 00 00 00 00 00 00 00 00 00 00 00 01 c3 df 1f 90 16 42 e3 94 00 00 00 00 80 02 ff ff 97 b8 00 00 02 04 ff c3 01 03 03 08 01 01 04 02

[IPv4 Header (32 bytes)]
  Version: 1 (unknown)
  IHL: 8 (32 [bytes])
  TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
  Total length: 0 [bytes]
  Identification: 24590
  Flags: (Reserved, Don't Fragment, More Fragment) = (true, true, false)
  Fragment offset: 4790 (38320 [bytes])
  TTL: 0
  Protocol: 32 (MERIT-INP)
  Header checksum: 0x0680
  Source address: /0.0.0.0
  Destination address: /0.0.0.0
  Option: [option-type: 0 (End of Option List)]
  Padding: 0x00 00 00 00 00 00 01 00 00 00 00
[Fragmented data (44 bytes)]
  Hex stream: 00 00 00 00 00 00 00 00 00 00 00 01 1f 90 c3 df 1c b1 79 d7 16 42 e3 95 80 12 ff ff 01 1f 00 00 02 04 ff c3 01 03 03 08 01 01 04 02

[IPv4 Header (32 bytes)]
  Version: 1 (unknown)
  IHL: 8 (32 [bytes])
  TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
  Total length: 0 [bytes]
  Identification: 24591
  Flags: (Reserved, Don't Fragment, More Fragment) = (true, true, true)
  Fragment offset: 5741 (45928 [bytes])
  TTL: 0
  Protocol: 20 (HMP)
  Header checksum: 0x0680
  Source address: /0.0.0.0
  Destination address: /0.0.0.0
  Option: [option-type: 0 (End of Option List)]
  Padding: 0x00 00 00 00 00 00 01 00 00 00 00
[Fragmented data (32 bytes)]
  Hex stream: 00 00 00 00 00 00 00 00 00 00 00 01 c3 df 1f 90 16 42 e3 95 1c b1 79 d8 50 10 27 f6 14 0c 00 00

[IPv4 Header (32 bytes)]
  Version: 1 (unknown)
  IHL: 8 (32 [bytes])
  TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
  Total length: 0 [bytes]
  Identification: 24591
  Flags: (Reserved, Don't Fragment, More Fragment) = (true, true, true)
  Fragment offset: 5741 (45928 [bytes])
  TTL: 0
  Protocol: 106 (QNX)
  Header checksum: 0x0680
  Source address: /0.0.0.0
  Destination address: /0.0.0.0
  Option: [option-type: 0 (End of Option List)]
  Padding: 0x00 00 00 00 00 00 01 00 00 00 00
[Fragmented data (118 bytes)]
  Hex stream: 00 00 00 00 00 00 00 00 00 00 00 01 c3 df 1f 90 16 42 e3 95 1c b1 79 d8 50 18 27 f6 c3 af 00 00 47 45 54 20 2f 67 72 65 65 74 69 6e 67 20 48 54 54 50 2f 31 2e 31 0d 0a 48 6f 73 74 3a 20 6c 6f 63 61 6c 68 6f 73 74 3a 38 30 38 30 0d 0a 55 73 65 72 2d 41 67 65 6e 74 3a 20 63 75 72 6c 2f 37 2e 35 35 2e 31 0d 0a 41 63 63 65 70 74 3a 20 2a 2f 2a 0d 0a 0d 0a

[IPv4 Header (32 bytes)]
  Version: 1 (unknown)
  IHL: 8 (32 [bytes])
  TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
  Total length: 0 [bytes]
  Identification: 24590
  Flags: (Reserved, Don't Fragment, More Fragment) = (true, true, false)
  Fragment offset: 4790 (38320 [bytes])
  TTL: 0
  Protocol: 20 (HMP)
  Header checksum: 0x0680
  Source address: /0.0.0.0
  Destination address: /0.0.0.0
  Option: [option-type: 0 (End of Option List)]
  Padding: 0x00 00 00 00 00 00 01 00 00 00 00
[Fragmented data (32 bytes)]
  Hex stream: 00 00 00 00 00 00 00 00 00 00 00 01 1f 90 c3 df 1c b1 79 d8 16 42 e3 eb 50 10 27 f6 13 b6 00 00

[IPv4 Header (32 bytes)]
  Version: 1 (unknown)
  IHL: 8 (32 [bytes])
  TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
  Total length: 0 [bytes]
  Identification: 24590
  Flags: (Reserved, Don't Fragment, More Fragment) = (true, true, false)
  Fragment offset: 4790 (38320 [bytes])
  TTL: 0
  Protocol: 175 (unknown)
  Header checksum: 0x0680
  Source address: /0.0.0.0
  Destination address: /0.0.0.0
  Option: [option-type: 0 (End of Option List)]
  Padding: 0x00 00 00 00 00 00 01 00 00 00 00
[Fragmented data (187 bytes)]
  Hex stream: 00 00 00 00 00 00 00 00 00 00 00 01 1f 90 c3 df 1c b1 79 d8 16 42 e3 eb 50 18 27 f6 5e cc 00 00 48 54 54 50 2f 31 2e 31 20 32 30 30 20 0d 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 61 70 70 6c 69 63 61 74 69 6f 6e 2f 6a 73 6f 6e 0d 0a 54 72 61 6e 73 66 65 72 2d 45 6e 63 6f 64 69 6e 67 3a 20 63 68 75 6e 6b 65 64 0d 0a 44 61 74 65 3a 20 57 65 64 2c 20 32 38 20 4f 63 74 20 32 30 32 30 20 31 30 3a 31 32 3a 35 33 20 47 4d 54 0d 0a 0d 0a 32 33 0d 0a 7b 22 69 64 22 3a 36 36 2c 22 63 6f 6e 74 65 6e 74 22 3a 22 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 22 7d 0d 0a

[IPv4 Header (32 bytes)]
  Version: 1 (unknown)
  IHL: 8 (32 [bytes])
  TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
  Total length: 0 [bytes]
  Identification: 24591
  Flags: (Reserved, Don't Fragment, More Fragment) = (true, true, true)
  Fragment offset: 5741 (45928 [bytes])
  TTL: 0
  Protocol: 20 (HMP)
  Header checksum: 0x0680
  Source address: /0.0.0.0
  Destination address: /0.0.0.0
  Option: [option-type: 0 (End of Option List)]
  Padding: 0x00 00 00 00 00 00 01 00 00 00 00
[Fragmented data (32 bytes)]
  Hex stream: 00 00 00 00 00 00 00 00 00 00 00 01 c3 df 1f 90 16 42 e3 eb 1c b1 7a 73 50 10 27 f5 13 1c 00 00

[IPv4 Header (32 bytes)]
  Version: 1 (unknown)
  IHL: 8 (32 [bytes])
  TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
  Total length: 0 [bytes]
  Identification: 24590
  Flags: (Reserved, Don't Fragment, More Fragment) = (true, true, false)
  Fragment offset: 4790 (38320 [bytes])
  TTL: 0
  Protocol: 25 (Leaf-1)
  Header checksum: 0x0680
  Source address: /0.0.0.0
  Destination address: /0.0.0.0
  Option: [option-type: 0 (End of Option List)]
  Padding: 0x00 00 00 00 00 00 01 00 00 00 00
[Fragmented data (37 bytes)]
  Hex stream: 00 00 00 00 00 00 00 00 00 00 00 01 1f 90 c3 df 1c b1 7a 73 16 42 e3 eb 50 18 27 f6 ce f3 00 00 30 0d 0a 0d 0a

[IPv4 Header (32 bytes)]
  Version: 1 (unknown)
  IHL: 8 (32 [bytes])
  TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
  Total length: 0 [bytes]
  Identification: 24591
  Flags: (Reserved, Don't Fragment, More Fragment) = (true, true, true)
  Fragment offset: 5741 (45928 [bytes])
  TTL: 0
  Protocol: 20 (HMP)
  Header checksum: 0x0680
  Source address: /0.0.0.0
  Destination address: /0.0.0.0
  Option: [option-type: 0 (End of Option List)]
  Padding: 0x00 00 00 00 00 00 01 00 00 00 00
[Fragmented data (32 bytes)]
  Hex stream: 00 00 00 00 00 00 00 00 00 00 00 01 c3 df 1f 90 16 42 e3 eb 1c b1 7a 78 50 10 27 f5 13 17 00 00

[IPv4 Header (32 bytes)]
  Version: 1 (unknown)
  IHL: 8 (32 [bytes])
  TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
  Total length: 0 [bytes]
  Identification: 24591
  Flags: (Reserved, Don't Fragment, More Fragment) = (true, true, true)
  Fragment offset: 5741 (45928 [bytes])
  TTL: 0
  Protocol: 20 (HMP)
  Header checksum: 0x0680
  Source address: /0.0.0.0
  Destination address: /0.0.0.0
  Option: [option-type: 0 (End of Option List)]
  Padding: 0x00 00 00 00 00 00 01 00 00 00 00
[Fragmented data (32 bytes)]
  Hex stream: 00 00 00 00 00 00 00 00 00 00 00 01 c3 df 1f 90 16 42 e3 eb 1c b1 7a 78 50 11 27 f5 13 16 00 00

[IPv4 Header (32 bytes)]
  Version: 1 (unknown)
  IHL: 8 (32 [bytes])
  TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
  Total length: 0 [bytes]
  Identification: 24590
  Flags: (Reserved, Don't Fragment, More Fragment) = (true, true, false)
  Fragment offset: 4790 (38320 [bytes])
  TTL: 0
  Protocol: 20 (HMP)
  Header checksum: 0x0680
  Source address: /0.0.0.0
  Destination address: /0.0.0.0
  Option: [option-type: 0 (End of Option List)]
  Padding: 0x00 00 00 00 00 00 01 00 00 00 00
[Fragmented data (32 bytes)]
  Hex stream: 00 00 00 00 00 00 00 00 00 00 00 01 1f 90 c3 df 1c b1 7a 78 16 42 e3 ec 50 10 27 f6 13 15 00 00

[IPv4 Header (32 bytes)]
  Version: 1 (unknown)
  IHL: 8 (32 [bytes])
  TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
  Total length: 0 [bytes]
  Identification: 24590
  Flags: (Reserved, Don't Fragment, More Fragment) = (true, true, false)
  Fragment offset: 4790 (38320 [bytes])
  TTL: 0
  Protocol: 20 (HMP)
  Header checksum: 0x0680
  Source address: /0.0.0.0
  Destination address: /0.0.0.0
  Option: [option-type: 0 (End of Option List)]
  Padding: 0x00 00 00 00 00 00 01 00 00 00 00
[Fragmented data (32 bytes)]
  Hex stream: 00 00 00 00 00 00 00 00 00 00 00 01 1f 90 c3 df 1c b1 7a 78 16 42 e3 ec 50 11 27 f6 13 14 00 00

[IPv4 Header (32 bytes)]
  Version: 1 (unknown)
  IHL: 8 (32 [bytes])
  TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
  Total length: 0 [bytes]
  Identification: 24591
  Flags: (Reserved, Don't Fragment, More Fragment) = (true, true, true)
  Fragment offset: 5741 (45928 [bytes])
  TTL: 0
  Protocol: 20 (HMP)
  Header checksum: 0x0680
  Source address: /0.0.0.0
  Destination address: /0.0.0.0
  Option: [option-type: 0 (End of Option List)]
  Padding: 0x00 00 00 00 00 00 01 00 00 00 00
[Fragmented data (32 bytes)]
  Hex stream: 00 00 00 00 00 00 00 00 00 00 00 01 c3 df 1f 90 16 42 e3 ec 1c b1 7a 79 50 10 27 f5 13 15 00 00

pcap4j 存储库包含一个如何处理碎片包的示例:
https://github.com/kaitoy/pcap4j/blob/v1/pcap4j-sample/src/main/java/org/pcap4j/sample/DefragmentEcho.java

基本上你需要根据 header.identification

对 IpV4Packets 进行分组
Packet packet = handle.getNextPacketEx();
Short id = packet.get(IpV4Packet.class).getHeader().getIdentification();

一旦你有了所有的碎片,你就可以重新组装整个有效载荷:

//list of fragments with the same id
List<IpV4Packet> list; 
final IpV4Packet defragmentedIpV4Packet = IpV4Helper.defragment(list);

编辑(响应添加的pcap转储文件)

我注意到(在您在评论下方链接的 output.pcap 文件中)您正在使用 IPv6。我试过使用该文件作为数据包的来源,即

PcapHandle handle = Pcaps.openOffline("output.pcap"); 

并且这些数据包没有完全解析。原因是 Protocol family 没有被识别。

IPv6 协议族的正确值是特定于平台的,除非您指定自定义值,否则 pcap4j 使用此代码为各个平台获取默认值:Pcap4jPropertiesLoader.

由于您捕获的数据包中使用的值 24 未列在默认值中,您需要自定义配置。

一种方法是通过 System.properties:

//associate value 24 with the IPv6 protocol family
System.setProperty("org.pcap4j.af.inet6", "24");
//set the class which should parse the packets for that family
System.setProperty("org.pcap4j.packet.Packet.classFor.org.pcap4j.packet.namednumber.ProtocolFamily.24", "org.pcap4j.packet.IpV6Packet");

之后,解析通过:

Packet packet = handle.getNextPacketEx();
TcpPacket tcpPacket = packet.get(TcpPacket.class)

应该可以正常工作。