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

Pcap4j仅检测到主机设备地址,无法识别局域网其他设备求助

解决Pcap4j ARP嗅探器仅显示本地主机地址的问题

你现在的代码其实还没真正启动ARP数据包的捕获流程——它只是帮你选好了网卡,然后打印了该网卡自身的链路层地址,这就是为什么你只能看到自己主机的信息。要捕获局域网内其他设备的ARP包,我们需要完善代码,添加数据包捕获、过滤和解析的核心逻辑。

问题根源分析

你的当前代码只完成了网卡选择和本地地址的打印,缺少三个关键步骤:

  • 没有打开网卡进入数据包捕获模式
  • 没有设置ARP专属的数据包过滤器
  • 没有监听并解析捕获到的ARP数据包

完整解决方案代码

下面是修正后的代码,它会主动捕获局域网内的ARP请求/响应包,并提取出其他设备的MAC和IP地址:

package arpsniffer;

import java.io.IOException;
import org.pcap4j.core.*;
import org.pcap4j.packet.ArpPacket;
import org.pcap4j.packet.Packet;
import org.pcap4j.util.LinkLayerAddress;
import org.pcap4j.util.NifSelector;
import org.pcap4j.util.MacAddress;
import org.pcap4j.util.Inet4Address;

public class ArpSniffer {
    private static final int SNAPLEN = 65536; // 捕获数据包的最大长度
    private static final int TIMEOUT = 10; // 捕获超时时间(毫秒)
    private static final String ARP_FILTER = "arp"; // BPF过滤器,仅捕获ARP类型数据包

    public static void main(String[] args) {
        PcapNetworkInterface nif;
        try {
            // 选择要监听的目标网卡
            nif = new NifSelector().selectNetworkInterface();
            if (nif == null) {
                System.out.println("未选择网卡,程序退出");
                return;
            }

            // 打印选中网卡的本地信息
            System.out.println("正在监听网卡: " + nif.getName());
            for(LinkLayerAddress addr : nif.getLinkLayerAddresses()){
                System.out.println("本地链路层地址: " + addr.toString());
            }

            // 打开网卡并启用混杂模式(捕获所有经过的数据包)
            PcapHandle handle = nif.openLive(SNAPLEN, PcapNetworkInterface.PromiscuousMode.PROMISCUOUS, TIMEOUT);
            
            // 设置ARP数据包过滤器,减少无效数据包处理
            handle.setFilter(ARP_FILTER, BpfCompileMode.OPTIMIZE);
            System.out.println("已启用ARP过滤器,开始捕获数据包...");

            // 定义数据包处理器,解析ARP包内容
            PacketListener listener = packet -> {
                ArpPacket arpPacket = packet.get(ArpPacket.class);
                if (arpPacket == null) {
                    return;
                }

                ArpPacket.ArpHeader header = arpPacket.getHeader();
                // 提取ARP包中的源MAC和IP地址
                MacAddress srcMac = header.getSrcHardwareAddr();
                Inet4Address srcIp = header.getSrcProtocolAddr();

                // 排除本地地址,避免重复打印自己的设备信息
                if (!srcMac.equals(nif.getLinkLayerAddresses().get(0).getAddress())) {
                    System.out.printf("检测到设备 -> MAC: %s, IP: %s%n", srcMac, srcIp);
                }
            };

            // 启动无限捕获循环(按Ctrl+C可中断)
            handle.loop(-1, listener);

        } catch (IOException e) {
            System.err.println("IO错误: " + e.getMessage());
            e.printStackTrace();
        } catch (PcapNativeException e) {
            System.err.println("Pcap本地库错误: " + e.getMessage());
            e.printStackTrace();
        } catch (NotOpenException e) {
            System.err.println("网卡未打开: " + e.getMessage());
            e.printStackTrace();
        } catch (InterruptedException e) {
            System.err.println("捕获被中断");
            Thread.currentThread().interrupt();
        }
    }
}

关键改进点说明

  1. 启用混杂模式:在打开网卡时设置PromiscuousMode.PROMISCUOUS,让网卡可以捕获所有经过的数据包,而不只是发给自己的。
  2. BPF过滤器:使用arp过滤器,只处理ARP类型的数据包,减少不必要的资源消耗。
  3. ARP数据包解析:通过ArpPacket类解析捕获到的数据包,提取出其他设备的MAC和IP地址。
  4. 排除本地地址:添加判断逻辑,避免重复打印自己主机的地址信息。

额外注意事项

  • 运行权限:务必以管理员身份运行程序,Windows环境下捕获数据包需要管理员权限。
  • 网卡选择:确认选择的是连接局域网的物理网卡,而非虚拟网卡(如VPN、虚拟机网卡)。
  • 触发ARP流量:如果暂时看不到其他设备,可以手动触发ARP请求(比如在另一台设备上ping网关),这样就能捕获到对应的ARP数据包了。

内容的提问来源于stack exchange,提问作者Fabio Slßr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:25:55