定义
DNS(Domain Name System), 是一个位于应用层的协议, 作用是将有意义的, 人类可读的域名如 (www.baidu.com) 转化为机器可读的 IP 地址如 192.168.1.1, 打个比方就是手机中的通讯录, 为无意义的电话号码记上人名. DNS 协议建立在 UDP 或 TCP 协议之上, 默认使用 53 号端口. 客户端默认通过 UDP 协议进行通讯, 但是由于广域网中不适合传输过大的 UDP 数据包, 因此规定当报文长度超过了 512 字节时, 应转换为使用 TCP 协议进行数据传输.
域名
域名可以类比手机通讯录, 但不同在于域名必须是对所有用户来说都是唯一的. 为了达到唯一性的目的, 因特网在命名的时候采用了层次结构的命名方法. 每一个域名 (本文只讨论英文域名) 都是一个标号序列 (labels), 用字母(A-Z,a-z, 大小写等价), 数字(0-9) 和连接符 (-) 组成, 标号序列总长度不能超过 255 个字符, 它由点号分割成一个个的标号(label), 每个标号应该在 63 个字符之内, 每个标号都可以看成一个层次的域名. 级别最低的域名写在左边, 级别最高的域名写在右边.
要注意的是根域其实就是一个., 最开始的时候完整的网址应该是 www.google.com. 这样的形式, 只是后来简化了这样的写法.
分层稍微解释一下:
根域: 全球的根服务器有 13 台;
顶级域: 用来指示某个国家, 地区, 或组织, 如 com -> 商业公司, edu -> 教育机构, net -> 网络公司, gov -> 非军事政府机构; cn -> 代表中国, jp -> 日本, uk -> 英国, hk -> 香港等等.
二级域: 个人或组织在 Internet 使用的注册名称, 如 baidu,google,cctv 等.
三级 / 四级域: 一般没有特定指什么, 按实际情况而变化, 一般表示当前网页提供的服务如 mail -> 邮箱, www -> 一般的浏览服务等.
而要注意, 一个网址中带有的 http:// 或者 https:// 部分并不是域名的一部分, 他们代表的是当前网页使用的协议, DNS 和 http 协议都是位于应用层的协议, 只是作用不一样.
域名服务器
有域名结构还不行, 还需要有一个东西去解析域名, 手机通讯录是由通讯录软件解析的, 域名需要由遍及全世界的域名服务器去解析, 域名服务器实际上就是装有域名系统的主机. 由高向低进行层次划分, 可分为以下几大类:
根域名服务器: 最高层次的域名服务器, 也是最重要的域名服务器, 本地域名服务器如果解析不了域名就会向根域名服务器求助. 全球共有 13 个不同 IP 地址的根域名服务器, 它们的名称用一个英文字母命名, 从 a 一直到 m. 这些服务器由各种组织控制, 并由 ICANN(互联网名称和数字地址分配公司)授权, 由于每分钟都要解析的名称数量多得令人难以置信, 所以实际上每个根服务器都有镜像服务器, 每个根服务器与它的镜像服务器共享同一个 IP 地址, 中国大陆地区内只有 6 组根服务器镜像(F,I(3 台),J,L). 当你对某个根服务器发出请求时, 请求会被路由到该根服务器离你最近的镜像服务器. 所有的根域名服务器都知道所有的顶级域名服务器的域名和地址, 如果向根服务器发出对 "jocent.me" 的请求, 则根服务器是不能在它的记录文件中找到与 "jocent.me" 匹配的记录. 但是它会找到 "me" 的顶级域名记录, 并把负责 "me" 地址的顶级域名服务器的地址发回给请求者.
顶级域名服务器: 负责管理在该顶级域名服务器下注册的二级域名. 当根域名服务器告诉查询者顶级域名服务器地址时, 查询者紧接着就会到顶级域名服务器进行查询. 比如还是查询 "jocent.me", 根域名服务器已经告诉了查询者 "me" 顶级域名服务器的地址,"me" 顶级域名服务器会找到 "jocent.me" 的域名服务器的记录, 域名服务器检查其区域文件, 并发现它有与 "jocent.me" 相关联的区域文件. 在此文件的内部, 有该主机的记录. 此记录说明此主机所在的 IP 地址, 并向请求者返回最终答案.
权限域名服务器: 负责一个区的域名解析工作
本地域名服务器: 当一个主机发出 DNS 查询请求的时候, 这个查询请求首先就是发给本地域名服务器的.
域名解析过程
域名解析总体可分为两大步骤, 第一个步骤是本机向本地域名服务器发出一个 DNS 请求报文, 报文里携带需要查询的域名; 第二个步骤是本地域名服务器向本机回应一个 DNS 响应报文, 里面包含域名对应的 IP 地址.
具体来说, 就是 host 主机先向本地域名服务器发送一个 dns 请求报文, 然后等待结果(这里也叫做递归查询, 即不在意中间过程, 旨在以最终结果); 而本地域名服务器如果无法解析, 就会向上找到根域名服务器, 跟域名服务器又会返回信息告诉本地域名服务器向下去哪个顶级域名服务器查找, 就这样一层层下去之后本地域名服务器就会获得最终的查询结果也就是一个 IP 地址然后返回给主机.(这一过程也叫做迭代查询, 即将自己部分工作做完, 交付给一下个人来办)
报文格式
了解一下报文格式, 我们可以更了解这个协议的传输过程做了些什么.
头部(header)
会话标识(Transaction ID,2bytes)
每个 DNS 报文唯一的 ID 标识, 用以区分是哪个请求的响应.
标志(Flags,2bytes)
标志名 | 含义 |
---|---|
QR(1bit) | 查询 / 响应标志,0 为查询,1 为响应 |
opcode(4bit) | 0 表示标准查询,1 表示反向查询,2 表示服务器状态请求 |
AA(1bit) | 表示授权回答 |
TC(1bit) | 表示可截断的 |
RD(1bit) | 表示期望递归 |
RA(1bit) | 表示可用递归 |
rcode(4bit) | 表示返回码,0 表示没有差错,3 表示名字差错,2 表示服务器错误(Server Failure) |
数量字段(8bytes)
Questions,Answer RRs,Authority RRs,Additional RRs 各自表示后面的四个区域的数目. Questions 表示查询问题区域节的数量, Answers 表示回答区域的数量, Authoritative namesversers 表示授权区域的数量, Additional recoreds 表示附加区域的数量.
正文
1.Queries 区域
1.1 查询名(name)
长度不固定, 最大为 4 字节, 且不使用填充字节, 一般该字段表示的就是需要查询的域名(如果是反向查询, 则为 IP, 反向查询即由 IP 地址反查域名)
格式示例:
1.2 查询类型(Type)
这里列出几种常见的, 想要查看详细的可以点击参考资料中的博客连接阅读.
类型 | 助记符 | 说明 |
---|---|---|
1 | A | 由域名获得 IPv4 地址 |
2 | NS | 查询域名服务器 |
5 | CNAME | 查询规范名称 |
12 | PTR | 把 IP 地址转换成域名 |
28 | AAAA | 由域名获得 IPv6 地址 |
255 | ANY | 对所有记录的请求 |
2. 资源记录 (RR,resource record) 区域
该区域有三个, 但格式都是一样的. 这三个区域分别是: 回答区域, 授权区域和附加区域. 也与头部的 RR 数量对应.
2.1. 域名(2 字节或不定长): 它的格式和 Queries 区域的查询名字字段是一样的. 有一点不同就是, 当报文中域名重复出现的时候, 该字段使用 2 个字节的偏移指针来表示. 比如, 在资源记录中, 域名通常是查询问题部分的域名的重复, 因此用 2 字节的指针来表示, 具体格式是最前面的两个高位是 11, 用于识别指针. 其余的 14 位从 DNS 报文的开始处计数(从 0 开始), 指出该报文中的相应字节数. 一个典型的例子, C00C(1100000000001100,12 正好是头部的长度, 其正好指向 Queries 区域的查询名字字段).
2.2 查询类型: 表明资源纪录的类型, 见 1.2 节的查询类型表格所示
2.3 查询类: 对于 Internet 信息, 总是 IN
2.4 生存时间(TTL): 以秒为单位, 表示的是资源记录的生命周期, 一般用于当地址解析程序取出资源记录后决定保存及使用缓存数据的时间, 它同时也可以表明该资源记录的稳定程度, 极为稳定的信息会被分配一个很大的值(比如 86400, 这是一天的秒数).
2.5. 资源数据: 该字段是一个可变长字段, 表示按照查询段的要求返回的相关资源记录的数据. 可以是 Address(表明查询报文想要的回应是一个 IP 地址)或者 CNAME(表明查询报文想要的回应是一个规范主机名)等.
补充概念
在查阅资料过程中还接触到了大量的相关概念, 也是对 DNS 协议的一个补充. 下面都做一个简单介绍牌, 如果有具体深入的必要会另外写一篇博客来进行详解.
1. DNS 缓存
DNS 缓存指的是使用 DNS 协议返回了正确的网站 IP 后, 设备就会将这个结果缓存起来, 并在一定时间内不销毁它(这里就跟上文提到的 TTL 有关), 这段时间内再次访问相同的域名时, 就不需要往上查询, 而是直接使用缓存好的结果, 从而达到更快解析域名的效果.
对于 PC 机的日常使用中, 应该不少人都试过有些网站无法访问的情况, 就很有可能是本地的 DNS 缓存出了问题(比如缓存仍有效, 但是想要访问的网站 IP 改变了, 利用缓存结果进行域名), 这个时候就需要我们去手动清除缓存, 重新向 DNS 服务器查询 IP.
DNS 缓存不仅仅存在于操作系统中, 实际上使用 DNS 协议的每一部分如浏览器, 应用程序以及 IPS 网络运营商都会对 DNS 进行缓存, 而它们的位置, 控制策略等等也有所不同. 下面举几个例子来了解一下实际情况:
浏览器: 各个浏览器有不同的固定 DNS 缓存时间, 而与 DNS 服务器返回的 TTL 是无关的. 例如 Chrome 的过期时间就是 1 分钟.
操作系统(OS): 会参考 DNS 返回的 TTL 值但是不完全等于它. 但是每个不同的系统也会有所区别, iOS 一般是每 24h 刷新一次, Android 则是 10 分钟刷新一次.
2. DNS 污染
DNS 污染是指一些刻意制造或无意中制造出来的域名服务器数据包, 把域名指往不正确的 IP 地址. 很多时候也像我们主机的 DNS 缓存出了问题一样, 在一个网域中的服务器缓存受到了污染的话, 就会把网域内的计算机导引去错误的网址.
其工作方式是: 由于通常的 DNS 查询没有任何认证机制, 而且 DNS 查询通常基于的 UDP 是无连接不可靠的协议, 因此 DNS 的查询非常容易被篡改, 通过对 UDP 端口 53 上的 DNS 查询进行入侵检测, 一经发现与关键词相匹配的请求则立即伪装成目标域名的解析服务器 (NS,Name Server) 给查询者返回虚假结果. DNS 污染是发生在用户请求的第一步上, 直接从协议上对用户的 DNS 请求进行干扰.
而实际上许多无法访问的如推特, 油管等网站就是通过 dns 污染来阻止访问的. 这也就是为什么修改 hosts 文件可以达到一定的 FQ 效果, 但是这些网站的 ip 地址还是会被定期封杀, 所以实际上修改 hosts 也不是长久之策, 现在 FQ 主要还是通过代理服务器连到境外服务器提供上网服务, hosts 文件下文也会进行细讲, 别的就不多说了.
3. DNS 劫持
实际上 DNS 劫持也很好理解, 通过某种手段劫持了 DNS 服务器后, 使对于某域名的解析全都指向另一个网站的 IP, 从而导致无法访问原网站. 我们小时候上网完成宽带连接之后出现的 "电信互联星空","网通黄页广告" 等就都是 dns 劫持的结果.
DNS 劫持和污染本质上都是错误解析用户发送的域名, 那我们应该如何区分呢? 污染是指 dns 缓存被污染, 而这个缓存结果是一些非 dns 服务器伪装成 dns 服务器向 host 主机发送的; 劫持是 dns 服务器被劫持, 刻意指向错误网址. 污染针对的是域名, 实际上域名解析仍然会去到原本的 dns 服务器去查询, 只不过因为 (从缓存) 先返回了假的结果, 所以显示了错误结果; 劫持针对的是服务器, 根本去不到原本的服务器查询而是完全指向错误的服务器. 但是从结果上来看, 这两个技术手段达到的效果是类似的.
4. hosts 文件
它的工作与 dns 缓存也很类似, 在我们访问某个域名的网站的时候, 我们所使用的操作系统会先从 hosts 文件中寻找对应的 ip 地址 (或者一个远端 dns 服务器地址), 如果存在, 系统就马上打开该网页, 如果没有再一步步进行 dns 解析, 从而提高网页打开的速度. 上文也提到, 正因如此我们可以达到 FQ 效果, 因为 8.8.8.8 就是 google 提供的 dns 服务器地址, 也就是作了一个重定向. 除此以外还可以利用重定向屏蔽某些网站. 如一般 hosts 文件中都会定义 127.0.0.1 是 localhost 也就是本机 ip. 文件格式也十分简单, txt 打开之后也会发现操作系统(如 Windows) 已经写好了注释教用户使用, 这里不再阐述.
5. http 协议
http 协议 (hyper text transfer protocol, 超文本传输协议), 是一个基于 tcp/ip 协议来传输数据的协议, 几乎所有的网站都是使用这个协议进行数据传输. 前文提过它和 dns 都是属于应用层上的协议, http 是通过 URI(uniform resource identifier, 统一资源标识符) 来唯一的表示某个资源, 而 URL(uniform resource locator, 统一资源定位符)则是一种特殊的 URI, 也是现在普遍采用的在互联网上标识资源的方法, 而域名是 URL 中的一部分. 一个完整的 URL 一般按顺序含有以下几个部分:
协议部分: 即 http: https: ftp: 等, 后面的 // 是分隔符;
域名部分;
端口部分: 跟在域名后面并使用分号间隔, 省略的话将采用默认端口 80;
虚拟目录部分: 即第一个 / 和最后一个 / 之间的内容, 与实际电脑的文件目录相似;
文件名部分: 最后一个 / 与? 之间带有文件类型后缀的内容, 省略的话则使用默认的文件名;
参数部分: 从? 开始后面带有等式的内容都是参数部分, 表达式之间用 & 隔开;
锚部分: 用来定位网页中的某个位置.
从平时生活中的使用我们可以知道, 只有协议部分和域名部分是必须的, 其他都可省略, 而端口和文件名部分虽然可省但是也实际存在, 只是直接使用默认值代替了.
由于 http 协议也是十分重要的协议, 后面还会另外写一篇博客讲述.
总结
DNS 协议是现代网络技术应用层中十分重要的技术, 其核心思想就是类似通讯录的功能, 用人类可读的域名去代替机器可读的 IP, 当然里面的技术细节也值得细细琢磨.
参考资料
[1] DNS 协议详解及报文格式分析
[2] DNS 协议 https://www.jianshu.com/p/915de89d070e
[3] DNS 缓存
[4] DNS 污染 & 劫持 https://www.hack520.com/330.html
[5] HTML 协议 https://www.cnblogs.com/ranyonsue/p/5984001.html
DNS 协议
来源: http://www.bubuko.com/infodetail-3459527.html