首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用pcap4j库实现类似ping的功能

如何使用pcap4j库实现类似ping的功能
EN

Stack Overflow用户
提问于 2016-11-16 10:24:40
回答 2查看 1K关注 0票数 0

我想实现基本的网络检查功能,以测试所提供的网址是否响应(例如。ping www.google.com).It必须提供操作信息,例如,指示请求的服务不可用或无法到达主机。我能够使用icmp4j库实现它。但是我想使用pcap4j库来实现同样的目标。我想把网址放在文本框中,然后点击连接按钮,这将调用pcap4j api来检查主机是否响应。

EN

回答 2

Stack Overflow用户

发布于 2016-11-19 21:55:06

您可以使用IcmpV4EchoPacketIcmpV4CommonPacketIpV4PacketEthernetPacket的构建器在以太网数据包上创建Echo (ping),并通过PcapHandle.sendPacket()发送它们。请参阅pcap4j样例项目中的org.pcap4j.sample.SendFragmentedEcho

您需要实现ARP来将IP地址解析为pcap4j示例项目中的org.pcap4j.sample.SendArpRequest等MAC地址。

您还需要实现一个功能,以便从给定的IP地址找到下一个跳(默认网关)。Pcap4J不提供支持此实现的API。(Java不提供API来获取路由表.)

你最好用java.net.InetAddress#isReachable()代替。

票数 0
EN

Stack Overflow用户

发布于 2022-02-04 11:54:28

我花了一年多的时间才弄明白这一点,因为我想用pcap4j制作一个traceroute,下面是我所做的:

  1. 获取您的IPv4地址和Mac地址,这可以通过查询PcapNetworkInterface轻松实现。
  2. 获取目标IP地址,如果您有一个DNS名称,您需要事先解决它。
  3. 获取目标Mac地址。
    1. 目标位于同一个子网中:发送一个ARP请求来解析mac (或者,mac广播也可能运行得很好)。
    2. 目标位于不同的子网中:您需要获得网关服务器的mac,这并不容易。假设您有其他网络流量,您可以侦听传入的数据包并获取源mac,其中源IP地址来自不同的子网,这很可能是网关服务器的mac地址。

  4. 创建IcmpV4EchoPacket并发送
  5. 侦听传入的ICMP通信量,您将得到以下三种中的一种:
    1. IcmpV4EchoReplyPacket,它可能是对您的请求的回答(请检查标识符和序列号以确保)
    2. 如果无法用指定的时间到达目标,则为IcmpV4TimeExceededPacket
    3. 没有,路由器和被点击的目标可以自由地忽略和不响应你的要求。

需要填写的变量:

代码语言:javascript
复制
short IDENTIFIER; // identifer may be any 16 bit interger
short SEQUENCE; // sequence may be any 16 bit integer
byte TTL; // time to live (1-255)
Inet4Address IP_TARGET; // ip address of your ping target
Inet4Address IP_ORIGIN; // your own ip address
MacAddress MAC_TARGET; // target or gateway mac address
MacAddress MAC_SOURCE; // your own mac address
PcapNetworkInterface PCAP4J_NETWORK_INTERFACE; // network interface used to execute the ping

如何制作ICMP回波请求包(作为IcmpV4CommonPacket of IpV4Packet of EthernetPacket的有效负载):

代码语言:javascript
复制
    public Packet buildPacket() {
        IcmpV4EchoPacket.Builder icmpV4Echo = new IcmpV4EchoPacket.Builder()
                .identifier(IDENTIFIER) // optional, default zero
                .sequenceNumber(SEQUENCE); // optional, default zero
        IcmpV4CommonPacket.Builder icmpV4Common = new IcmpV4CommonPacket.Builder()
                .type(IcmpV4Type.ECHO) // type is echo
                .code(IcmpV4Code.NO_CODE) // echo request doesn't need this
                .payloadBuilder(icmpV4Echo)
                .correctChecksumAtBuild(true);
        IpV4Packet.Builder ipv4Builder = new IpV4Packet.Builder()
                .correctChecksumAtBuild(true)
                .correctLengthAtBuild(true)
                .dstAddr(IP_TARGET) // IPv4 Address where tp send the request
                .payloadBuilder(icmpV4Common)
                .protocol(IpNumber.ICMPV4) // payload is ICMPV4
                .srcAddr(IP_ORIGIN) // Your own IPv4 Address
                .tos(IpV4Rfc1349Tos.newInstance((byte) 0))
                .ttl(TTL) // time to live (1-255)
                .version(IpVersion.IPV4); // IP Version is IPv4
        EthernetPacket.Builder etherBuilder = new EthernetPacket.Builder()
                .dstAddr(MAC_TARGET) // the targets mac address
                .srcAddr(MAC_SOURCE) // your own mac address
                .type(EtherType.IPV4) // payload protocl is IPv4
                .payloadBuilder(ipv4Builder)
                .paddingAtBuild(true);
        return etherBuilder.build(); // build your packet
    }

ICMP回声应答或超时的侦听器:

代码语言:javascript
复制
    public PacketListener buildListener() {
        return new PacketListener() {
            @Override
            public void gotPacket(Packet packet) {
                if (!(packet instanceof EthernetPacket))
                    return;
                EthernetPacket ethernetPacket = (EthernetPacket) packet;
                packet = ethernetPacket.getPayload();
                if (!(packet instanceof IpV4Packet))
                    return;
                IpV4Packet ipV4Packet = (IpV4Packet) packet;
                IpV4Header ipV4Header = ipV4Packet.getHeader();
                packet = ipV4Packet.getPayload();
                if (!(packet instanceof IcmpV4CommonPacket))
                    return;
                IcmpV4CommonPacket icmpPacket = (IcmpV4CommonPacket) packet;
                packet = icmpPacket.getPayload();
                // successful reply just measure time and done
                if (packet instanceof IcmpV4EchoReplyPacket) {
                    IcmpV4EchoReplyPacket icmpV4EchoReplyPacket = (IcmpV4EchoReplyPacket) packet;
                    IcmpV4EchoReplyHeader icmpV4EchoReplyHeader = icmpV4EchoReplyPacket.getHeader();
                    if (icmpV4EchoReplyHeader.getIdentifier() != identifier)
                        return;
                    if (icmpV4EchoReplyHeader.getSequenceNumber() != sequence)
                        return;
                    // here you got an echo reply
                    System.out.println(packet);
                    return;
                }
                // try handle time to live exceeded messages
                if (packet instanceof IcmpV4TimeExceededPacket) {
                    packet = packet.getPayload(); // original IPv4
                    if (!(packet instanceof IpV4Packet))
                        return;
                    packet = packet.getPayload(); // original ICMP common
                    if (!(packet instanceof IcmpV4CommonPacket))
                        return;
                    packet = packet.getPayload(); // original ICMP echo
                    if (!(packet instanceof IcmpV4EchoPacket))
                        return;
                    IcmpV4EchoHeader icmpV4EchoHeader = ((IcmpV4EchoPacket)packet).getHeader();
                    if (icmpV4EchoHeader.getIdentifier() != IDENTIFIER)
                        return;
                    if(icmpV4EchoHeader.getSequenceNumber() != SEQUENCE)
                        return;
                    // HERE you got an answer, that the time to live has been used up
                    System.out.println(packet);
                    return;
                }
            };
        }

把它结合起来:

代码语言:javascript
复制
    public static void main(String[] args) throws IOException, PcapNativeException, NotOpenException, InterruptedException {
        try (PcapHandle handle = PCAP4J_NETWORK_INTERFACE.openLive(1024, PromiscuousMode.PROMISCUOUS, 1000)) {
            // set filter to only get incoming ICMP traffic
            handle.setFilter("icmp and dst host " + Pcaps.toBpfString(IP_ORIGIN), BpfCompileMode.OPTIMIZE);
            // send ARP request
            Packet p = buildPacket();
            handle.sendPacket(p);
            // wait (forever) for ARP answer
            PacketListener listener = buildListener();
            handle.loop(-1, listener);
        }
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40629657

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档