18143453325 在线咨询 在线咨询
18143453325 在线咨询
所在位置: 首页 > 营销资讯 > 建站知识 > 学习DNS协议

学习DNS协议

时间:2023-02-02 15:40:01 | 来源:建站知识

时间:2023-02-02 15:40:01 来源:建站知识

DNS

DNS是一个查询域名的IP的协议,访问服务器的之前,需要解析域名的地址。因为IP一串数字不好记忆。

DNS协议结构

  1. TransID的作用是标记请求和响应。当结果回来的时候,读取TransID就可以知道这个响应是那个请求的。
  2. Parameter 是标记这个数据是请求,还是响应。是否标准查询,是否截取,是否递归查询,是否接受不认证的响应。一般就是控制请求和响应的行为
  3. Number of Questions 是响应的时候设置,标记多少个Question 段
  4. Number of Answers 是响应的时候设置,标记多少个Anserr段
  5. Number of Authority是响应的时候设置,标记多少个Authority段
  6. Number of Additional是响应的时候设置,标记多少个Additional段
  7. Query Section。请求的时候设置
    1.域名数据
    2.域名类型Type。一般是A(IPv4是A,IPv6是AAA)
    3.Class类型,默认用INET

发送DNS时数据包结构的大小

我们只看左边的Example1,Example2一样

UDP头是8 Byte,整个UDP是39 Byte。所以DNS协议占用31 Byte。
ID占用2Byte,Flags都是占用2Byte。域名的属性Type和Class都是2Byte的大小,而域名的字符内容数据不是固定的。
上面说是Example1的域名数据是15Byte。但是我抓包看实现的时候发现dns-packet库发出域名数据的字符前后都会有1个空数据的字节,也就是2Byte是空数据的。而直接使用dig查询时没有的

为什么会增加1-2个字节呢?是不是因为担心域名计算字节实际大小比计算的结果可能要大,所以估计增加空间,保证成功呢?可是为什么字符串之前也要留空一个数据呢?还是存在其它问题需要这样处理的呢?暂时想不明白

Node的dns-packet

如果是服务器发起DNS查询请求,可以使用dns-packet库

浏览器二进制数据传输

因为浏览器不能使用Node的Buffeer,只能如下组装数据。

TextEncoder是把域名字符串转换为二进制数据

ArrayBuffer和Uint16Array都是字节数组容器

DataView是操作字节数组容器

let utf8Encode = new TextEncoder(); function createDNSPacket(domain) { var domainUint8array = new TextEncoder("utf-8").encode(domain); var domainSize = domainUint8array.byteLength + 2; console.log(domainSize); const headerBuffer = new ArrayBuffer(12); const header = new DataView(headerBuffer); header.setUint16(0, 1) header.setUint16(2, 100) header.setUint16(4, 1) header.setUint16(6, 0) header.setUint16(8, 0) header.setUint16(10, 0) const questionBuffer = new ArrayBuffer(4); const question = new DataView(questionBuffer); question.setUint16(0, 1) question.setUint16(2, 1) var concateBuff = new Uint8Array(domainUint8array.byteLength + headerBuffer.byteLength + questionBuffer.byteLength + 2); concateBuff.set(new Uint8Array(headerBuffer), 0); concateBuff.set(new Uint16Array(1), headerBuffer.byteLength); // 仿dns-packet实现 concateBuff.set(domainUint8array, headerBuffer.byteLength + 1); concateBuff.set(new Uint16Array(1), headerBuffer.byteLength + 2); // 仿dns-packet实现 concateBuff.set(new Uint8Array(questionBuffer), headerBuffer.byteLength + domainUint8array.byteLength + 2); return concateBuff; }

注意的坑

这个查询只能是一个Demo,是基于Chrome的UDP插件Demo来实现的。

Chrome无法直接发出UDP包,必须经过socket连接到服务端后,才能发UDP。

点击下载demo代码,服务的代码在Server文件夹下

参考

http://www.firewall.cx/networking-topics/protocols/domain-name-system-dns/160-protocols-dns-query.html

关键词:协议,学习

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭