Search code examples
pcap4j

Cannot read TcpPacket in pcap4j


I am trying to use pcap4j to get TcpPackets from loopback address. I can read packets successfully but I cannot convert them to 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());
        }
    }
}

Things to note:

I am using getNextPacketEx so I can benefit from packet factory

My dependencies in pom.xml looks like

<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>

What I have also tried is to unwrap manually the packets ( see the commented code ). That works successfully until I get an IpV4Packet which contains fragmented data.

When I try to construct the TcpPacket.newPacket... I am receiving the error:

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

What I would like to do is read tcp packets, reassemble them and then read my http content that I want to sniff. Can anyone help?

UPDATE: This is a full dump of ipv4 packets for a simple Http get on localhost in port 8080:

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

Solution

  • The pcap4j repository contains an example of how to deal with fragmented packets:
    https://github.com/kaitoy/pcap4j/blob/v1/pcap4j-sample/src/main/java/org/pcap4j/sample/DefragmentEcho.java

    Basically you need to group the IpV4Packets based on their header.identification

    Packet packet = handle.getNextPacketEx();
    Short id = packet.get(IpV4Packet.class).getHeader().getIdentification();
    

    and once you have all the fragments, you can reassemble the whole payload:

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

    Edit (in response to the added pcap dump file)

    I've noticed (in the output.pcap file that you've linked below in the comment) that you are using IPv6. I've tried using that file as a source of the packets, i.e.

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

    and those packets were not fully parsed. The reason for that was that the Protocol family was not recognized.

    The correct value of IPv6 protocol family is platform specific and unless you specify a custom value, pcap4j uses this code to obtain a default value for respective platforms: Pcap4jPropertiesLoader.

    Since the value 24 used in your captured packets is not listed among the default values, you need custom configuration.

    One way to do that is via 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");
    

    After that, parsing via:

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

    should work normally.