你必须知道的DNS那些事
文章目录
DNS
(Domain Name System) 域名系统
基本概念
域名系统 (DNS) 将人类可读的域名 (例如,www.baidu.com) 转换为机器可读的 IP 地址。
DNS
属于应用层协议。把 域名/主机名字
转换为IP地址。
域名
域名是文本字符串到Ip地址的的映射。
域名采用层次树状结构方法命名。每一个域名都由标号序列组成,各标号直接用点隔开。例如 news.baidu.com
级别最低的域名写在最左边,而级别最高的顶级域名则写在最右边。
每一个标号不超过63个字符(中文需要转换成Punycode),不区分大小写。多标号组成的完整域名总共不超过255个字符。
顶级域名 TLD (Top Level Domain)
- 通用顶级域名 gTLD
- 国家/地区顶级域名 nTLD
- 基础结构域名 (infrastructure domain) 这种顶级域名只有一个,即 arpa, 用于反向域名解析
用域名树来表示域名系统较清楚。实际上是一个倒过来的树,在最上面的是根,但没有对应的名字。根下面一级的节点,就是最高一级的顶级域名。顶级域名可往下划分子域,即二级域名。再往下划分就是三级域名、四级域名等等。
域名由ICANN (Internet Corporation for Assigned Names and Numbers)互联网名称与数字地址分配机构管理。但是具体的管理工作由域名注册管理机构管理(顶级域名)。
域名注册管理机构将域名注册的商业销售委托给注册商。用户通过注册商购买域名后,注册商必须通知域名注册管理机构并支付费用。
.COM的顶级域域名注册管理机构是VeriSign, Inc.
域名服务器
域名系统是通过域名服务器实现的。
互联网上的DNS服务器是按照层级结构管理的, 分区管理。
域名服务器分类
根域名服务器 (root name server)
根域名服务器是最高层次的域名服务器。根域名服务器记录着顶级域名服务器的域名和 IP 地址。
目前根域名服务器由13组构成,为了方便人们记忆,使用从 a.rootservers.net到m.rootservers.net的域名表示。这13组根域名服务器只使用13个不同的IP地址(IPv4/IPv6)。
Root Servers | IPv4 | IPv6 | OPERATOR |
---|---|---|---|
a.root-servers.net | 198.41.0.4 | 2001:503:ba3e::2:30 | Verisign, Inc. |
b.root-servers.net | 199.9.14.201 | 2001:500:200::b | University of Southern California, Information Sciences Institute |
c.root-servers.net | 192.33.4.12 | 2001:500:2::c | Cogent Communications |
d.root-servers.net | 199.7.91.13 | 2001:500:2d::d | University of Maryland |
e.root-servers.net | 192.203.230.10 | 2001:500:a8::e | NASA (Ames Research Center) |
f.root-servers.net | 192.5.5.241 | 2001:500:2f::f | nternet Systems Consortium, Inc. |
g.root-servers.net | 192.112.36.4 | 2001:500:12::d0d | US Department of Defense (NIC) |
h.root-servers.net | 198.97.190.53 | 2001:500:1::53 | US Army (Research Lab) |
i.root-servers.net | 192.36.148.17 | 2001:7fe::53 | Netnod |
j.root-servers.net | 192.58.128.30 | 2001:503:c27::2:30 | Verisign, Inc. |
k.root-servers.net | 193.0.14.129 | 2001:7fd::1 | RIPE NCC |
l.root-servers.net | 199.7.83.42 | 2001:500:9f::42 | ICANN |
m.root-servers.net | 202.12.27.33 | 2001:dc3::35 | WIDE Project |
根域名服务器有很多镜像服务器。在中国大陆北京、上海、广州、杭州等城市都有镜像服务器。
根域名服务器采用任播(anycast)技术,当 DNS客户向某个根域名服务器的IP地址发出查询报文时,互联网上的路由器就能找到离这个DNS客户最近的一个根域名服务器。这样做不仅加快了DNS的查询过程,也更加合理地利用了互联网的资源。
顶级域名服务器
负责管理在该顶级域名服务器注册的所有二级域名。当收到DNS查询请求时,给出相应的应答。
权威域名服务器(Authoritative DNS server)
权威域名服务器是实际持有并负责DNS资源记录的服务器。是位于DNS查找链底部的服务器,根据所查询的资源记录进行IP地址响应。
|
|
域名服务器解析原理
查询方式
递归查询(Recursive Query)
如果主机所询问的本地域名服务器不知道被查询域名的 IP 地址,那么本地域名服务器就以 DNS 客户的身份,向其他根域名服务器继续发出查询请求报文(即替该主机继续查询),而不是让该主机自己进行下一步的查询。递归查询返回的查询结果或者是所要查询的IP地址,或者是报错,表示无法查询到所需的 IP 地址。
迭代查询(Iterative Query)
向域名服务器查询时,不是替本地域名服务器进行后续的查询,而是告知了后续的域名查询服务器。本地域名服务器向根域名服务器的查询通常是采用迭代查询。
我们以在浏览器中访问网址为例。(下面内容来源于cloudflare)
DNS查询步骤
- 用户在 Web 浏览器中输入 “example.com”,查询传输到 Internet 中,并被DNS递归解析器接收(一般由用户的互联网服务提供商 (ISP) 进行管理)。
- 接着,解析器查询 DNS 根域名服务器(.)。
- 然后,根服务器使用存储其域信息的顶级域(TLD)DNS 服务器(例如 .com)的地址响应该解析器。在搜索 example.com 时,我们的请求指向 .com TLD。
- 然后,解析器向 .com TLD 发出请求。
- TLD 服务器随后使用该域的域名服务器 example.com 的 IP 地址进行响应。
- 最后,递归解析器将查询发送到域的域名服务器。
- example.com 的 IP 地址而后从域名服务器返回解析器。
- 然后 DNS 解析器使用最初请求的域的 IP 地址响应 Web 浏览器。
DNS 查找的这 8 个步骤返回 example.com 的 IP 地址后,浏览器便能发出对该网页的请求:
- 浏览器向该 IP 地址发出 HTTP 请求。
- 位于该 IP 的服务器返回将在浏览器中呈现的网页(第 10 步)。
DNS 记录
DNS 记录是位于权威DNS服务器中的指令,提供一个域的相关信息,包括哪些 IP 地址与该域关联,以及如何处理对该域的请求。所有 DNS 记录都有一个 “TTL”,其代表生存时间,指示DNS服务器多久刷新一次该记录。
常用DNS记录
类型 | 介绍 |
---|---|
A | IPv4 地址 |
AAAA | IPv6 地址 |
CNAME | 将域名指向另一个域名地址,与其保持相同解析 |
MX | 用于邮件服务器 |
NS | 域名服务器 |
SRV | 用于标识某台服务器使用了某个服务 |
PTR | 用于根据IP地址查询域名 |
实现
DNS协议
前12字节属于Header头。
标识字段(ID/Transaction ID)
标识字段(ID/Transaction ID) 2字节,客户端设置并由服务器返回结果。客户端通过它来确定响应与查询是否匹配。
标志字段(Flags)
标志字段(Flags) 2字节,如下字段组成:
字段 | 长度(bit) | 含义 |
---|---|---|
QR | 1 | 0表示查询报文,1表示响应报文 |
Opcode | 4 | 0(标准查询),其他值为 1(反向查询)和2(服务器状态请求) |
AA | 1 | 授权(权威)回答 |
TC | 1 | 可截断的 ( truncated ) |
RD | 1 | 期望递归 (Recursion Desired) |
RA | 1 | 可用递归 (Recursion Available ) |
Z | 3 | Reserved for future use |
Rcode | 4 | The result code of an answer; 0: No error 1: Format error |
问题数(QDCOUNT)
资源记录数(ANCOUNTT)
授权资源记录数(NSCOUNT)
额外资源记录数(ARCOUNT)
DNS报文中最后的三个字段,回答字段、授权字段和附加信息字段,均采用一种称为资源记录RR(Resource Record)的相同格式。
常用命令
ping
、host
、nslookup
、dig
flags
- qr 消息响应
- aa 权威
- rd 递归
- ra 远程服务器支持递归
dig @域名服务器 域名
dig +[no]recurse 关闭递归查询(递归默认是打开的)
dig +vc 发送基于tcp的查询 ( +[no]tcp )
dig -x ip地址 反向查询
dig +trace 域名
dig +short 域名
|
|
|
|
C 语言
linux glibc库
|
|
gethostbyname()
函数因只支持IPv4地址已不建议使用,已被getaddrinfo()
函数取代。
具体详细信息可参考getaddrinfo
Java 语言
InetAddress.getAllByName(“hostname”)
|
|
其底层代码是通过native InetAddress[] lookupAllHostAddr(String hostname)
方法实现。翻看openJDK源码,此方法调用了系统glibc库的getaddrinfo
方法 (Inet4AddressImpl.c或者Inet6AddressImpl.c)。
Java的地址解析默认带缓存功能。在Java 8中是通过使用 Cache
类实例 addressCache
(存储解析成功结果)和 negativeCache
(存储解析失败结果)对结果进行缓存,每次查询时优先查询缓存。
缓存时间我们可以通过:
networkaddress.cache.ttl
、sun.net.inetaddr.ttl
控制解析成功缓存时间 (两参数效果相同),在不开启安全管理器的情况下,默认时间为 30秒。
如果值为 0
时,不使用缓存;值为 -1
时则缓存永久有效。
networkaddress.cache.negative.ttl
、 sun.net.inetaddr.negative.ttl
控制解析失败缓存时间 (两参数效果相同),默认时间为10秒。
sun.net.inetaddr.ttl
和sun.net.inetaddr.negative.ttl
不建议使用
如果开启了 SecurityManager,优先从 ${java.home}/jre/lib/security/java.security 中读取参数,
networkaddress.cache.ttl
值为 -1,永久缓存。
可通过
-Djava.security.manager
启用安全管理器,然而java 17 中移除了 Security Manager
Java默认使用系统的配置策略解析, 我们在程序中可以通过JNDI DNS服务指定自定义DNS服务器
sun.net.spi.nameservice.provider.<n>=<default|dns,sun|...>
sun.net.spi.nameservice.nameservers=<server1_ipaddr,server2_ipaddr ...>
使用Google DNS
|
|
JNDI DNS service 在Java 9 中被移除,使用
jdk.net.hosts.file
替代。
Java 18
Java 18 中实现了 Internet-Address Resolution SPI
。
实现 InetAddressResolver
接口 和 InetAddressResolverProvider
抽象类并在 resources 文件夹下添加 META-INF/services/java.net.spi.InetAddressResolverProvider
文件,在文件内配置我们实现的
InetAddressResolverProvider
全限定类。
其他框架
Okhttp
提供了Dns
接口,方便我们实现自定义DNS解析器
Netty
Linux 系统实现
查看glibc版本
|
|
/etc/nsswitch.conf
Name Service Switch configuration file
用来配置不同的来源的查询顺序。
hosts: files dns myhostname
/etc/hosts
在DNS出现之前,用于维护主机名和IP地址之间的映射关系
/etc/resolv.conf
域名解析器配置文件
参数 | 描述 | 示例 |
---|---|---|
nameserver | 用于配置DNS服务器 | 8.8.8.8 |
search | 用户配置主机名搜索列表 | example.com company.net |
sortlist | IP/子网掩码对 | 130.155.160.0/255.255.240.0 130.155.0.0 |
options | 控制参数 |
nameserver
nameserver
用于DNS服务器的配置,支持IPv4 和 IPv6。最多支持3个(参考/resolv/bits/types/res_state.h
中 MAXNS宏)。按照配置顺序请求DNS服务器,请求超时则使用下一个,直至尝试完所有DNS服务器,
然后再根据配置的重试次数进行重试。
search
当查询不完全限定域名时会使用到此参数
sortlist
options
timeout
解析器请求超时时间,单位为秒,默认为 5,最大值为30。
attempts
重试次数,默认值为2。最大值为3。
rotate
轮训名称服务器,而非一直使用第一个。
single-request
(since glibc 2.10) glibc从2.9版本开始支持并发执行IPv4和IPv6 请求。此选项禁用并发请求,使glibc顺序执行IPv6和IPv4请求。
single-request-reopen
(since glibc 2.9)
对IPv4和IPv6使用相同的套接字会因为某些原因可能会导致第二个请求发生丢包现象。设置此参数如果第二个请求没有被正确处理时,关闭此连接并打开一个新的连接。
ndots
: n
如果域名参数中 “.” 的数量大于等于设置的数值,那么解析器就会在使用搜索列表之前,先查找这个域名。
容器化
Docker
Docker 启动容器时,会从宿主机上复制 /etc/resolv.conf
文件,并删掉其中无法连接到的DNS服务器。
/etc/hosts
只记录容器自身的地址和名称
/etc/hostname
容器的主机名
启动一个容器,在容器中使用 mount 命令可以看到这三个文件挂载信息
|
|
|
|
K8s
|
|
Pod 的 DNS 策略
- Default
- ClusterFirst
- ClusterFirstWithHostNet
- None