如何从java中的dns数据报中提取网站名称

时间:2019-02-13 21:52:44

标签: java dns udp datagram

我想读取浏览器发出的DNS请求,然后从DNS UDP数据报中提取网站的名称。 我可以捕获数据报,然后使用getData()查找网站的标签,但是我没有得到清晰的数据。

    public static void main(String args[]) throws Exception
  {
     DatagramSocket serverSocket = new DatagramSocket(53);
        byte[] receiveData = new byte[512];
        while(true)
           {
              DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);
              serverSocket.receive(receivePacket);
              byte telegramContent[] = receivePacket.getData();
              String sentence = new String( telegramContent);
              System.out.println("RECEIVED: " + sentence);

我为www.google.com获得的结果

enter image description here

我的问题是如何使网站的全名清晰如www.google.com

1 个答案:

答案 0 :(得分:0)

您将需要阅读RFC1034和1035。DNS协议要比这复杂得多,您将需要更多的代码来解析它。

首先,为什么不使用特定的Java DNS库,该库肯定存在并且既可以生成又可以解析DNS数据包?即使您不想使用它,阅读其源代码也可以帮助您了解解析的过程。

第二,如果您真的想自己使用它,则必须了解DNS数据包的通用格式(具有将问题,权限部分,答案部分,其他部分分开的结构),请参阅本节。有关DNS数据包的结构,请参见4,然后再具体了解其名称,您需要了解“ DNS压缩”,请参阅同一RFC的4.1.4节。

DNS数据包中的名称不会像这样出现。每个标签(两个点之间的字符串)都按长度编码在电线上,然后在某些情况下使用EXCEPT标签,在某些情况下,指针用于指向DNS数据包的另一部分,以免重复相同的标签或标签序列

最后,您将不仅需要尝试获取DNS数据包中的任何字符串。回复可以包含很多其他内容,例如,如果您收到CNAME回复,则会得到两个“字符串”,即两个域名,即记录的所有者和关联的RDATA。您将需要遵循这些CNAME记录(如果您想查找请求的名字),然后解析AAAAA请求的答复。显然,您还需要考虑对所查询的任何名称都会发生的否定答复(NXDOMAIN)。

至于

  

我想阅读浏览器发出的DNS请求

,有一个简单得多的解决方案。

安装递归名称服务器,例如unbound,并确保您的浏览器指向该名称服务器。然后,您将轻松地在名称服务器日志文件中看到所有主机名。

另一个使用最新浏览器版本实现DoH(基于HTTPS的DNS)的解决方案:再次安装一个名为DoH的名称服务器,并将您的浏览器配置为指向它(例如,对于Firefox,请参见https://www.internetsociety.org/blog/2018/12/dns-privacy-support-in-mozilla-firefox/)。