我想读取浏览器发出的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上的结果
我的问题是如何获得网站的全名,如www.google.com
您将需要阅读RFC1034和1035. DNS协议远比这复杂,您将需要更多的代码来解析它。
首先,为什么不使用肯定存在且可以生成和解析DNS数据包的特定Java DNS库?即使您不想使用它,阅读其来源也可以帮助您了解解析的发生方式。
其次,如果你真的想自己,你必须要了解DNS数据包的通用格式(结构分离问题,权限部分,答案部分,附加部分),请参阅第4节的DNS数据包结构,然后对于名称,您需要了解“DNS压缩”,请参阅相同RFC的4.1.4节。
DNS数据包中的名称不会显示如下。每个标签(两个点之间的字符串)在线上编码其长度,然后标签EXCEPT在某些情况下,指针用于指向DNS数据包的另一部分内部,以便永远不会重复相同的标签或标签序列。
最后,您不仅需要尝试获取DNS数据包中的任何字符串。回复可以包含很多其他内容,例如,如果您获得CNAME
回复,您将获得两个“字符串”,即两个域名,记录的所有者和相关的RDATA。您将需要遵循这些CNAME
记录(如果您想找出所请求的名字),然后解析A
和AAAA
请求的回复。您显然还需要考虑对所查询的任何名称可能发生的否定回复(NXDOMAIN
)。
至于
我想阅读浏览器发出的DNS请求
,有一个更容易的解决方案。
安装递归名称服务器,如unbound
,并确保您的浏览器指向它。然后,您将轻松查看名称服务器日志文件中的所有主机名。
最近浏览器版本实现DoH(基于HTTPS的DNS)的另一种解决方案:再次安装名称服务器,说出DoH并配置浏览器指向它(例如,参见https://www.internetsociety.org/blog/2018/12/dns-privacy-support-in-mozilla-firefox/ for Firefox)。