You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Pcap4j库发送TCP SYN包时出现NullPointerException问题

使用Pcap4j构建TCP SYN包时触发NullPointerException(提示builder.srcAddr/dstAddr为null)

问题详情

尝试使用Pcap4j库发送TCP SYN数据包,执行ipv4Builder.build();时触发NullPointerException。调试确认sourceIp与destIp均不为空,但错误日志提示builder.srcAddr: null builder.dstAddr: null。

相关代码

import org.pcap4j.core.*;
import org.pcap4j.packet.*;
import org.pcap4j.packet.namednumber.TcpPort;
import org.pcap4j.util.MacAddress;
import org.pcap4j.packet.namednumber.EtherType;
import org.pcap4j.packet.namednumber.IpNumber;
import org.pcap4j.packet.namednumber.IpVersion;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.Collections;
import java.util.List;

public class SYN {

    public static void send() {
        String targetIp = "8.8.8.8";
        int targetPort = 80;

        try {
            List<PcapNetworkInterface> allDevs = Pcaps.findAllDevs();
            Collections.shuffle(allDevs);
            PcapNetworkInterface nif = null;
            Inet4Address sourceIp = null;
            
            for (PcapNetworkInterface dev : allDevs) {
                System.out.println("Interface: " + dev.getName() + " (" + dev.getDescription() + ")");
                
                for (PcapAddress pcapAddress : dev.getAddresses()) {
                    InetAddress addr = pcapAddress.getAddress();
                    if (addr instanceof Inet4Address) {
                        System.out.println("Found IPv4 Address: " + addr.getHostAddress());
                        if (nif == null) {
                            nif = dev;
                            sourceIp = (Inet4Address) addr;
                            break;
                        }
                    }
                }
                if (nif != null) {
                    break;
                }
            }

            if (nif == null || sourceIp == null) {
                System.out.println("No suitable network interface found.");
                return;
            }
            
            System.out.println("Selected Interface: " + nif.getName());
            System.out.println("Source IP: " + sourceIp.getHostAddress());

            PcapHandle handle = nif.openLive(65536, PcapNetworkInterface.PromiscuousMode.PROMISCUOUS, 10);

            TcpPacket.Builder tcpBuilder = new TcpPacket.Builder();
            tcpBuilder
                    .srcPort(TcpPort.getInstance((short) 80))
                    .dstPort(TcpPort.getInstance((short) targetPort))
                    .sequenceNumber(100)
                    .acknowledgmentNumber(0)
                    .dataOffset((byte) 5)
                    .syn(true)
                    .window((short) 65535)
                    .correctChecksumAtBuild(true)
                    .correctLengthAtBuild(true);

            Inet4Address destIp = (Inet4Address) InetAddress.getByName(targetIp);

            IpV4Packet.Builder ipv4Builder = new IpV4Packet.Builder();
            ipv4Builder
                    .version(IpVersion.IPV4)
                    .tos(IpV4Rfc791Tos.newInstance((byte) 0))
                    .ttl((byte) 64)
                    .protocol(IpNumber.TCP)
                    .srcAddr(sourceIp)
                    .dstAddr(destIp)
                    .payloadBuilder(tcpBuilder)
                    .correctChecksumAtBuild(true)
                    .correctLengthAtBuild(true);
            
            System.out.println(sourceIp == null);
            System.out.println(destIp == null);
            Packet p1 = ipv4Builder.build(); // 触发错误的行

            handle.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

错误信息

false // sourceIp is not null
false // destIp is not null
java.lang.NullPointerException: builder.srcAddr: null builder.dstAddr: null
    at org.pcap4j.packet.TcpPacket.<init>(TcpPacket.java:100)
    at org.pcap4j.packet.TcpPacket.<init>(TcpPacket.java:33)
    at org.pcap4j.packet.TcpPacket$Builder.build(TcpPacket.java:432)
    at org.pcap4j.packet.TcpPacket$Builder.build(TcpPacket.java:169)
    at org.pcap4j.packet.IpV4Packet.<init>(IpV4Packet.java:121)
    at org.pcap4j.packet.IpV4Packet.<init>(IpV4Packet.java:32)
    at org.pcap4j.packet.IpV4Packet$Builder.build(IpV4Packet.java:370)

解决方案

错误的核心原因是:TCP校验和的计算依赖IP层的源地址和目的地址,但TcpPacket.Builder未获取到这些信息。当开启correctChecksumAtBuild(true)时,Pcap4j需要这些地址来生成正确的TCP校验和,而IPv4 Builder不会自动将IP地址传递给下层的TCP Builder,必须手动设置。

修改代码,在构建TcpPacket.Builder后添加一行,设置外层IPv4地址:

tcpBuilder.outerIpv4Address(sourceIp, destIp);

修改后的关键代码片段

TcpPacket.Builder tcpBuilder = new TcpPacket.Builder();
tcpBuilder
        .srcPort(TcpPort.getInstance((short) 80))
        .dstPort(TcpPort.getInstance((short) targetPort))
        .sequenceNumber(100)
        .acknowledgmentNumber(0)
        .dataOffset((byte) 5)
        .syn(true)
        .window((short) 65535)
        .correctChecksumAtBuild(true)
        .correctLengthAtBuild(true)
        .outerIpv4Address(sourceIp, destIp); // 新增这一行,传递IP地址给TCP Builder

说明

outerIpv4Address方法会将IP层的源和目的地址传递给TCP Builder,这样TCP包在计算校验和时就能获取到所需的地址信息,避免NullPointerException。

内容的提问来源于stack exchange,提问作者Metalowy Robot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 16:24:51