【问题标题】:Java. Getting URL from package爪哇。从包中获取 URL
【发布时间】:2025-12-02 09:35:02
【问题描述】:

我正在制作一个捕获网络流量的应用程序。我需要获取浏览器向用户显示的 URL,我想我可以使用 InetAddress 从我捕获的 IP 中获取域,但它不一样。例如,我从 facebook.com 获得的域是 xx-fbcdn-shv-01-dft4.fbcdn.net,这并不总是相同的。还有其他方法吗?有没有可能?

我正在使用 JNetPCap 库及其页面的示例代码,只是为了了解如何在我的项目中实现它。

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jnetpcap.*;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.packet.PcapPacketHandler;
import org.jnetpcap.protocol.network.Ip4;

/**
 *
 * @author User
 */
public class Sniffer {

static private String device;

public static void main(String[] args) {

    List<PcapIf> alldevs = new ArrayList<>(); // Will be filled with NICs  
    StringBuilder errbuf = new StringBuilder(); // For any error msgs  

    /**
     * *************************************************************************
     * First get a list of devices on this system 
     *************************************************************************
     */
    int r = Pcap.findAllDevs(alldevs, errbuf);
    if (r == Pcap.NOT_OK || alldevs.isEmpty()) {
        System.err.printf("Can't read list of devices, error is %s", errbuf
                .toString());
        return;
    }

    System.out.println("Network devices found:");

    int i = 0;
    for (PcapIf device : alldevs) {
        String description
                = (device.getDescription() != null) ? device.getDescription()
                        : "No description available";
        System.out.printf("#%d: %s [%s]\n", i++, device.getName(), description);

        System.out.println(device.toString());
    }

    PcapIf device = alldevs.get(2);
    /*************************************************************************** 
     * Second we open up the selected device 
     **************************************************************************/
    int snaplen = 64 * 1024;           // Capture all packets, no trucation  
    int flags = Pcap.MODE_PROMISCUOUS; // capture all packets  
    int timeout = 10 * 1000;           // 10 seconds in millis  
    Pcap pcap
            = Pcap.openLive(device.getName(), snaplen, flags, timeout, errbuf);

    if (pcap == null) {
        System.err.printf("Error while opening device for capture: "
                + errbuf.toString());
        return;
    }
    ///*--------------------------------------------------------------------    ------------------------------
    PcapBpfProgram program = new PcapBpfProgram();
    String expression = "port 80";
    int optimize = 0;         // false
    int netmask = 0xFFFFFF00; // 255.255.255.0  

    if (pcap.compile(program, expression, optimize, netmask) != Pcap.OK) {
        System.err.println(pcap.getErr());
        return;
    }

    if (pcap.setFilter(program) != Pcap.OK) {
        System.err.println(pcap.getErr());
        return;
    }
    ///*

    /**
     * *************************************************************************
     * Third we create a packet handler which will receive packets from the
     * libpcap loop. 
     *************************************************************************
     */
    PcapPacketHandler<String> jpacketHandler = (PcapPacket packet, String user) -> {
        System.out.printf("Received packet at %s caplen=%-4d len=%-4d %s\n",
                new Date(packet.getCaptureHeader().timestampInMillis()),
                packet.getCaptureHeader().caplen(), // Length actually captured
                packet.getCaptureHeader().wirelen(), // Original length
                user // User supplied object

        );
Ip4 ip = new Ip4();
//Tcp tcp= new Tcp();

byte[] sIP;

if (packet.hasHeader(ip)) {

try {
    sIP = packet.getHeader(ip).source();
    String sourceIP = org.jnetpcap.packet.format.FormatUtils.ip(sIP);
    String myIp = InetAddress.getLocalHost().getHostAddress();

    if (!myIp.equals(sourceIP)) {
        System.out.println("source= "+sourceIP);

        String domain;
        domain = InetAddress.getByName(sourceIP).getHostName();

        System.out.println("--------------------------"+domain);

    }
    } catch (UnknownHostException ex) {
    Logger.getLogger(Sniffer.class.getName()).log(Level.SEVERE, null, ex);
    }
}    
    };

    /**
     * *************************************************************************
     * Fourth we enter the loop and tell it to capture 10 packets. The loop
     * method does a mapping of pcap.datalink() DLT value to JProtocol ID,
     * which is needed by JScanner. The scanner scans the packet buffer and
     * decodes the headers. The mapping is done automatically, although a
     * variation on the loop method exists that allows the programmer to
     * sepecify exactly which protocol ID to use as the data link type for
     * this pcap interface. 
     *************************************************************************
     */
    pcap.loop(-1, jpacketHandler, "jNetPcap rocks!");

    /**
     * *************************************************************************
     * Last thing to do is close the pcap handle 
     *************************************************************************
     */
    pcap.close();
    }
}

【问题讨论】:

  • 显示使用你试过的代码

标签: java url networking dns ip


【解决方案1】:

你不能。大型网站有多个地址,因此 Facebook.com 解析为多个地址,但这些地址的反向查找不会解析为 Facebook.com。 如果您可以捕获对话,您可以阅读 http 标头,在那里您可以找到您感兴趣的 url。

【讨论】:

  • 非常感谢您的快速回答,我对网络协议了解不多,但您的回答非常有用,我发现我可以从 http 标头获取主机名而不是获取 ip但是我不能对 https 做同样的事情,还有其他方法可以获取 https 主机名吗?
  • https 有效载荷是加密的,所以你真的不能。
【解决方案2】:

我找到了一种方法来读取 tcp 数据包并使用它的目标端口。谢谢你的帮助,没有你的帮助,我找不到解决方案。这是处理程序方法。

static String dominios[] = {"com", "org", "net", "info", "biz", "edu", "gob"};

PcapPacketHandler<String> jpacketHandler = (PcapPacket packet, String user) -> {
    Tcp tcp= new Tcp();
    Http http= new Http();
    if (packet.hasHeader(tcp)) {

            if (tcp.destination() == 443) {
                int payloadstart = tcp.getOffset() + tcp.size();
                JBuffer buffer = new JBuffer(64 * 1024);
                buffer.peer(packet, payloadstart, packet.size() - payloadstart);
                String payload = buffer.toHexdump(packet.size(), false, true, true);

               for (String b : dominios) {
                    if (payload.contains(b)) {
                        procesarTcp(payload, b);
                    }
                }
            }
            else if(packet.hasHeader(http)){    
                System.out.println(http.fieldValue(Http.Request.Host));
            }
        }
    };
    public static void procesarTcp(String payload, String dominio) {

    payload= payload.substring(0,payload.indexOf(dominio)+dominio.length());
    StringTokenizer token= new StringTokenizer(payload,"\n");
    String pagina;
    String aux;
    payload="";
    while(token.hasMoreTokens()){
        aux=token.nextToken();
        payload+=aux.substring(aux.indexOf("    ")+4, aux.length());
    }
    pagina= payload.substring(payload.lastIndexOf("..")+2,payload.length());
System.err.println(pagina);
}

【讨论】: