CentOS中resolv.conf的配置实验

通常情况下,在 Linux 中可以用来配置 DNS 地址的文件有两个:

  • 解析配置文件 /etc/resolv.conf,文件中的注释行可以采用 # 或者 ; 开头
  • 网卡 ifcfg 配置文件 /etc/sysconfig/network-scripts/ifcfg-eth*

resolv.conf 的配置参数

通过查看 man手册页,会看到有很多相关的参数,这里只说比较常用的几个

nameserver

这个参数会指定系统使用的 DNS 的 IP 地址,在生产环境中,经常会看到 /etc/resolv.conf 中配置了一个或多个 nameserver 。配置了多个 nameserver 后,系统使用这些 DNS 的顺序并未进行轮询、随机、或者均衡调度,并且系统总是使用第一个 nameserver 对应的地址来进行 DNS 的查询。

1
2
3
4
5
6
7
8
9
[root@bogon ~]# cat /etc/resolv.conf 
nameserver 8.8.8.8
nameserver 9.9.9.9
nameserver 114.114.114.114
nameserver 1.2.4.8
nameserver 180.76.76.76
nameserver 223.5.5.5
[root@bogon ~]#
[root@bogon ~]# dig +short +tries=1 www.redhat.com www.centos.org www.kernel.org

解析的同时,使用 tcpdump 命令分析通信数据,从结果中可以看到,使用 dig 对三个域名的解析只用到了第一个 nameserver 的地址,即 8.8.8.8

1
2
3
4
5
6
7
8
9
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
20:51:38.162534 IP 192.168.127.154.58459 > 8.8.8.8.53: 27136+ [1au] A? www.redhat.com. (43)
20:51:38.165500 IP 8.8.8.8.53 > 192.168.127.154.58459: 27136 4/0/0 CNAME ds-www.redhat.com.edgekey.net., CNAME ds-www.redhat.com.edgekey.net.globalredir.akadns.net., CNAME e3396.ca2.s.tl88.net., A 210.192.117.211 (185)
20:51:38.166018 IP 192.168.127.154.58937 > 8.8.8.8.53: 37326+ [1au] A? www.centos.org. (43)
20:51:38.449824 IP 8.8.8.8.53 > 192.168.127.154.58937: 37326 1/3/4 A 85.12.30.226 (161)
20:51:38.450397 IP 192.168.127.154.47932 > 8.8.8.8.53: 5121+ [1au] A? www.kernel.org. (43)
20:51:38.546600 IP 8.8.8.8.53 > 192.168.127.154.47932: 5121 3/6/1 CNAME git.kernel.org., CNAME hkg.git.kernel.org., A 147.75.42.139 (237)

换成一次解析一个域名

1
2
3
4
[root@bogon ~]# dig +short +tries=1 www.baidu.com
[root@bogon ~]# dig +short +tries=1 www.qq.com
[root@bogon ~]# dig +short +tries=1 www.taobao.com
[root@bogon ~]# dig +short +tries=1 www.amazon.com

结果同上,也是只用到了第一个 nameserver 的地址,即 8.8.8.8

1
2
3
4
5
6
7
8
9
10
11
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
20:54:35.061088 IP 192.168.127.154.54374 > 8.8.8.8.53: 11030+ [1au] A? www.baidu.com. (42)
20:54:35.062881 IP 8.8.8.8.53 > 192.168.127.154.54374: 11030$ 3/0/0 CNAME www.a.shifen.com., A 220.181.112.244, A 220.181.111.188 (93)
20:54:35.071402 IP 192.168.127.154.57419 > 8.8.8.8.53: 31566+ [1au] A? www.qq.com. (39)
20:54:35.073641 IP 8.8.8.8.53 > 192.168.127.154.57419: 31566$ 1/0/0 A 123.151.148.111 (44)
20:54:35.081402 IP 192.168.127.154.37311 > 8.8.8.8.53: 3036+ [1au] A? www.taobao.com. (43)
20:54:35.083099 IP 8.8.8.8.53 > 192.168.127.154.37311: 3036$ 2/0/0 CNAME www.taobao.com.danuoyi.tbcache.com., A 124.238.232.220 (96)
20:54:35.090256 IP 192.168.127.154.34286 > 8.8.8.8.53: 18338+ [1au] A? www.amazon.com. (43)
20:54:35.427330 IP 8.8.8.8.53 > 192.168.127.154.34286: 18338 3/4/1 CNAME www.cdn.amazon.com., CNAME d3ag4hukkh62yn.cloudfront.net., A 13.33.230.194 (258)

如果第一个 nameserver 对应的地址是不可用的 IP ,域名的解析均是从第一个 nameserver 对用的地址进行查询的,系统会按照 nameserver 设定的顺序从上往下进行顺序尝试,当无法获取结果后将尝试使用下一个,并且系统不会记录任何一个 nameserver 的工作状态。

1
2
3
4
5
6
7
8
[root@bogon ~]# cat /etc/resolv.conf 
nameserver 123.45.67.8
nameserver 8.8.8.8
nameserver 9.9.9.9
nameserver 114.114.114.114
nameserver 1.2.4.8
nameserver 180.76.76.76
nameserver 223.5.5.5
1
[root@bogon ~]# dig +short +tries=1 www.redhat.com www.centos.org www.kernel.org

抓包结果

1
2
3
4
5
6
7
8
9
10
11
12
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
21:09:32.043033 IP 124.160.121.68.48453 > 123.45.67.8.53: 3179+ [1au] A? www.redhat.com. (43)
21:09:33.042929 IP 124.160.121.68.37014 > 8.8.8.8.53: 3179+ [1au] A? www.redhat.com. (43)
21:09:33.327958 IP 8.8.8.8.53 > 124.160.121.68.37014: 3179 4/0/1 CNAME ds-www.redhat.com.edgekey.net., CNAME ds-www.redhat.com.edgekey.net.globalredir.akadns.net., CNAME e3396.ca2.s.tl88.net., A 122.224.45.211 (196)
21:09:33.328311 IP 124.160.121.68.54898 > 123.45.67.8.53: 13619+ [1au] A? www.centos.org. (43)
21:09:34.328397 IP 124.160.121.68.43004 > 8.8.8.8.53: 13619+ [1au] A? www.centos.org. (43)
21:09:34.563133 IP 8.8.8.8.53 > 124.160.121.68.43004: 13619 1/0/1 A 85.12.30.226 (59)
21:09:34.563347 IP 124.160.121.68.33925 > 123.45.67.8.53: 13240+ [1au] A? www.kernel.org. (43)
21:09:35.563401 IP 124.160.121.68.36621 > 8.8.8.8.53: 13240+ [1au] A? www.kernel.org. (43)
21:09:35.624542 IP 8.8.8.8.53 > 124.160.121.68.36621: 13240 3/0/1 CNAME git.kernel.org., CNAME hkg.git.kernel.org., A 147.75.42.139 (95)

如果有多个 nameserver 不可用时,对于 digping 命令而言生效的只有前三个,当前三个 nameserver 都不可用时,不会再向其余的 nameserver请求解析。对于 curl 命令来说生效的是全部,依次从上向下轮询,直到找到能有所响应的为止。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@bogon ~]# cat /etc/resolv.conf 
nameserver 123.45.67.8
nameserver 123.45.67.9
nameserver 123.45.67.10
nameserver 123.45.67.11
nameserver 123.45.67.12
nameserver 8.8.8.8
nameserver 9.9.9.9
nameserver 114.114.114.114
nameserver 1.2.4.8
nameserver 180.76.76.76
nameserver 223.5.5.5
[root@bogon ~]#
[root@bogon ~]# dig +short +tries=1 www.redhat.com www.centos.org www.kernel.org
;; connection timed out; no servers could be reached
;; connection timed out; no servers could be reached
;; connection timed out; no servers could be reached

抓包结果

1
2
3
4
5
6
7
8
9
10
11
12
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
21:25:18.162523 IP 124.160.121.68.35636 > 123.45.67.8.53: 34369+ [1au] A? www.redhat.com. (43)
21:25:19.162528 IP 124.160.121.68.35529 > 123.45.67.9.53: 34369+ [1au] A? www.redhat.com. (43)
21:25:20.162618 IP 124.160.121.68.44291 > 123.45.67.10.53: 34369+ [1au] A? www.redhat.com. (43)
21:25:25.162806 IP 124.160.121.68.57363 > 123.45.67.8.53: 36309+ [1au] A? www.centos.org. (43)
21:25:26.162892 IP 124.160.121.68.37002 > 123.45.67.9.53: 36309+ [1au] A? www.centos.org. (43)
21:25:27.162974 IP 124.160.121.68.56470 > 123.45.67.10.53: 36309+ [1au] A? www.centos.org. (43)
21:25:32.163160 IP 124.160.121.68.52253 > 123.45.67.8.53: 59858+ [1au] A? www.kernel.org. (43)
21:25:33.163201 IP 124.160.121.68.36526 > 123.45.67.9.53: 59858+ [1au] A? www.kernel.org. (43)
21:25:34.163285 IP 124.160.121.68.42950 > 123.45.67.10.53: 59858+ [1au] A? www.kernel.org. (43)

从上面的结果可以看到,dig 在请求解析每个域名时,都会向前三个 nameserver 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@bogon ~]# cat /etc/resolv.conf
nameserver 123.45.67.1
nameserver 123.45.67.2
nameserver 123.45.67.3
nameserver 123.45.67.4
nameserver 123.45.67.5
nameserver 123.45.67.6
nameserver 123.45.67.7
nameserver 123.45.67.8
nameserver 8.8.8.8
[root@bogon ~]# curl -I www.baidu.com
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Connection: Keep-Alive
Content-Length: 277
Content-Type: text/html
Date: Sat, 12 May 2018 11:44:10 GMT
Etag: "575e1f5c-115"
Last-Modified: Mon, 13 Jun 2016 02:50:04 GMT
Pragma: no-cache
Server: bfe/1.0.8.18

抓包结果

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@bogon ~]# tcpdump -nn -i eth1   udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
19:43:37.708473 IP 124.160.121.68.52347 > 123.45.67.1.53: 57511+ A? www.baidu.com. (31)
19:43:42.709785 IP 124.160.121.68.44730 > 123.45.67.2.53: 57511+ A? www.baidu.com. (31)
19:43:47.397695 IP 124.160.121.68.52848 > 123.45.67.3.53: 57511+ A? www.baidu.com. (31)
19:43:50.531180 IP 124.160.121.68.32775 > 123.45.67.4.53: 57511+ A? www.baidu.com. (31)
19:43:54.282260 IP 124.160.121.68.34249 > 123.45.67.5.53: 57511+ A? www.baidu.com. (31)
19:43:57.415747 IP 124.160.121.68.45492 > 123.45.67.6.53: 57511+ A? www.baidu.com. (31)
19:44:02.417119 IP 124.160.121.68.53927 > 123.45.67.7.53: 57511+ A? www.baidu.com. (31)
19:44:05.862921 IP 124.160.121.68.48605 > 123.45.67.8.53: 57511+ A? www.baidu.com. (31)
19:44:09.933530 IP 124.160.121.68.55600 > 8.8.8.8.53: 57511+ A? www.baidu.com. (31)
19:44:10.038720 IP 8.8.8.8.53 > 124.160.121.68.55600: 57511 3/0/0 CNAME www.a.shifen.com., A 61.135.169.121, A 61.135.169.125 (90)

domain

1
domain <Local domain name>

这个参数用于系统在进行 DNS 查询时,如果请求的域名无法正常解析时自动补充 domain 的参数值。

当请求解析的内容中含有域时,即无论系统请求哪一个主机名时,系统默认都会先加上根域 .,但是如果不包含域,则会将 domain 中设定的域填充进去。这是官方文档中的一段描述:

1
2
3
the domain part is taken to be everything after the first '.'.
Finally, if the hostname does not contain a domain part,
the root domain is assumed.

当请求解析的内容不包含有域时,不管请求的内容是不是合法的,系统都直接填充 domain 参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@bogon ~]# cat /etc/resolv.conf 
domain baidu.com
nameserver 8.8.8.8
nameserver 9.9.9.9
nameserver 114.114.114.114
[root@bogon ~]#
[root@bogon ~]# ping -c 1 www
PING www.a.shifen.com (61.135.169.121) 56(84) bytes of data.
64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=1 ttl=54 time=28.3 ms

--- www.a.shifen.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 28.390/28.390/28.390/0.000 ms

抓包结果

1
2
3
4
5
6
7
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
15:34:53.581383 IP 124.160.121.68.42899 > 8.8.8.8.53: 62551+ A? www.baidu.com. (31)
15:34:53.711318 IP 8.8.8.8.53 > 124.160.121.68.42899: 62551 3/0/0 CNAME www.a.shifen.com., A 61.135.169.121, A 61.135.169.125 (90)
15:34:53.740080 IP 124.160.121.68.45679 > 8.8.8.8.53: 35362+ PTR? 121.169.135.61.in-addr.arpa. (45)
15:34:53.790788 IP 8.8.8.8.53 > 124.160.121.68.45679: 35362 NXDomain 0/1/0 (97)
1
2
[root@bogon ~]# ping -c 1 baidu
ping: baidu: Name or service not known
1
2
3
4
5
6
7
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
15:40:46.521311 IP 124.160.121.68.54008 > 8.8.8.8.53: 51825+ A? baidu.baidu.com. (33)
15:40:46.619891 IP 8.8.8.8.53 > 124.160.121.68.54008: 51825 NXDomain 0/1/0 (76)
15:40:46.619961 IP 124.160.121.68.37288 > 8.8.8.8.53: 59104+ A? baidu. (23)
15:40:46.668562 IP 8.8.8.8.53 > 124.160.121.68.37288: 59104 0/1/0 (93)

请求解析的内容包含有域时,不管请求的内容是不是合法的,系统都会先直接解析而不是直接填充 domain 参数

1
2
3
4
5
[root@bogon ~]# cat /etc/resolv.conf 
domain .org
nameserver 8.8.8.8
nameserver 9.9.9.9
nameserver 114.114.114.114
  • 请求解析的内容包含有域,且该域有对应的 A 记录
1
2
3
4
5
6
7
[root@bogon ~]# ping -c1 baidu.com
PING baidu.com (123.125.115.110) 56(84) bytes of data.
64 bytes from 123.125.115.110 (123.125.115.110): icmp_seq=1 ttl=54 time=33.6 ms

--- baidu.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 33.654/33.654/33.654/0.000 ms
1
2
3
4
5
6
7
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
15:52:51.006971 IP 124.160.121.68.35960 > 8.8.8.8.53: 29630+ A? baidu.com. (27)
15:52:51.054703 IP 8.8.8.8.53 > 124.160.121.68.35960: 29630 2/0/0 A 123.125.115.110, A 220.181.57.216 (59)
15:52:51.088759 IP 124.160.121.68.52785 > 8.8.8.8.53: 12744+ PTR? 110.115.125.123.in-addr.arpa. (46)
15:52:51.134573 IP 8.8.8.8.53 > 124.160.121.68.52785: 12744 NXDomain 0/1/0 (100)
  • 请求解析的内容包含有域,但该域不合法或者没有对应的A记录
1
2
[root@bogon ~]# ping -c1 baidu123.com
ping: baidu123.com: Name or service not known

抓包结果

1
2
3
4
5
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
15:56:01.274770 IP 124.160.121.68.60947 > 8.8.8.8.53: 32132+ A? baidu123.com. (30)
15:56:01.666132 IP 8.8.8.8.53 > 124.160.121.68.60947: 32132 0/1/0 (96)
1
search <Search list for host-name lookup>

指定一组域名(用空格分割),当仅写出主机名时,就开始依次进行这些域名的匹配,如果第一个域名没有匹配到,那么用第二个进行匹配,以此类推,直到匹配完所有列出的域名,给出最终的结果。

1
2
3
4
5
6
7
8
9
10
11
12
[root@bogon ~]# cat /etc/resolv.conf
search redhat.com centos.org baidu.com kernel.org
nameserver 8.8.8.8
nameserver 9.9.9.9
nameserver 114.114.114.114
[root@bogon ~]#
[root@bogon ~]# ping -c 1 -W 1 -q pan
PING yiyun.n.shifen.com (111.206.37.70) 56(84) bytes of data.

--- yiyun.n.shifen.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 26.970/26.970/26.970/0.000 ms

抓包结果

1
2
3
4
5
6
7
8
9
10
11
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
21:54:13.539662 IP 124.160.121.68.41382 > 8.8.8.8.53: 51406+ A? pan.redhat.com. (32)
21:54:13.641746 IP 8.8.8.8.53 > 124.160.121.68.41382: 51406 0/1/0 (76)
21:54:13.641866 IP 124.160.121.68.43018 > 8.8.8.8.53: 15888+ A? pan.centos.org. (32)
21:54:13.876920 IP 8.8.8.8.53 > 124.160.121.68.43018: 15888 NXDomain 0/1/0 (83)
21:54:13.876974 IP 124.160.121.68.39758 > 8.8.8.8.53: 2584+ A? pan.baidu.com. (31)
21:54:13.979307 IP 8.8.8.8.53 > 124.160.121.68.39758: 2584 3/0/0 CNAME yiyun.n.shifen.com., A 111.206.37.70, A 153.37.235.66 (92)
21:54:14.006705 IP 124.160.121.68.54116 > 8.8.8.8.53: 20521+ PTR? 70.37.206.111.in-addr.arpa. (44)
21:54:14.055034 IP 8.8.8.8.53 > 124.160.121.68.54116: 20521 NXDomain 0/1/0 (98)
1
2
[root@bogon ~]# ping -c 1 -W 1 -q x1y2z3
ping: x1y2z3: Name or service not known
1
2
3
4
5
6
7
8
9
10
11
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53
21:57:47.079874 IP 124.160.121.68.59551 > 8.8.8.8.53: 14646+ A? x1y2z3.redhat.com. (35)
21:57:47.388342 IP 8.8.8.8.53 > 124.160.121.68.59551: 14646 0/1/0 (79)
21:57:47.388416 IP 124.160.121.68.40022 > 8.8.8.8.53: 10171+ A? x1y2z3.centos.org. (35)
21:57:47.702240 IP 8.8.8.8.53 > 124.160.121.68.40022: 10171 NXDomain 0/1/0 (86)
21:57:47.702297 IP 124.160.121.68.56305 > 8.8.8.8.53: 15347+ A? x1y2z3.baidu.com. (34)
21:57:47.804776 IP 8.8.8.8.53 > 124.160.121.68.56305: 15347 NXDomain 0/1/0 (77)
21:57:47.821951 IP 124.160.121.68.40022 > 8.8.8.8.53: 10171+ A? x1y2z3.kernel.org. (35)
21:57:47.832714 IP 8.8.8.8.53 > 124.160.121.68.40022: 10171 NXDomain 0/1/0 (94)
21:57:47.804841 IP 124.160.121.68.52432 > 8.8.8.8.53: 1360+ A? x1y2z3. (24)
21:57:47.857440 IP 8.8.8.8.53 > 124.160.121.68.52432: 1360 NXDomain 0/1/0 (99)

options

用来设定一些选项,实现不同的功能

timeout

可选选项,系统一次 DNS 解析 timeout 的时间值,单位为秒。系统默认值为 5,最大可以设定的值是 30

1
timeout:n

下面对于 timeout 的实验我们都在 /etc/resolv.conf 中配置无效的 DNS

在查看了 dig 命令的帮助手册之后发现它也有个 timeout 参数 +time=T,在不指定该参数的情况下默认为 5 秒,那么我们 不在 resolv.conf 中配置 timeout 来进行测试看一下:

1
2
3
4
5
6
7
[root@bogon ~]# cat /etc/resolv.conf
nameserver 123.45.67.1
nameserver 123.45.67.2
nameserver 123.45.67.3
[root@bogon ~]#
[root@bogon ~]# dig +tries=5 +time=2 +short www.baidu.com
;; connection timed out; no servers could be reached

抓包结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes

17:00:22.378172 IP 124.160.121.68.39149 > 123.45.67.1.53: 18650+ [1au] A? www.baidu.com. (42)
17:00:23.378136 IP 124.160.121.68.37930 > 123.45.67.2.53: 18650+ [1au] A? www.baidu.com. (42)
17:00:24.378219 IP 124.160.121.68.58526 > 123.45.67.3.53: 18650+ [1au] A? www.baidu.com. (42)

17:00:26.378269 IP 124.160.121.68.39149 > 123.45.67.1.53: 18650+ [1au] A? www.baidu.com. (42)
17:00:27.378355 IP 124.160.121.68.37930 > 123.45.67.2.53: 18650+ [1au] A? www.baidu.com. (42)
17:00:28.378442 IP 124.160.121.68.58526 > 123.45.67.3.53: 18650+ [1au] A? www.baidu.com. (42)

17:00:30.378527 IP 124.160.121.68.39149 > 123.45.67.1.53: 18650+ [1au] A? www.baidu.com. (42)
17:00:31.378614 IP 124.160.121.68.37930 > 123.45.67.2.53: 18650+ [1au] A? www.baidu.com. (42)
17:00:32.378703 IP 124.160.121.68.58526 > 123.45.67.3.53: 18650+ [1au] A? www.baidu.com. (42)

17:00:34.378786 IP 124.160.121.68.39149 > 123.45.67.1.53: 18650+ [1au] A? www.baidu.com. (42)
17:00:35.378870 IP 124.160.121.68.37930 > 123.45.67.2.53: 18650+ [1au] A? www.baidu.com. (42)
17:00:36.378958 IP 124.160.121.68.58526 > 123.45.67.3.53: 18650+ [1au] A? www.baidu.com. (42)

17:00:38.379040 IP 124.160.121.68.39149 > 123.45.67.1.53: 18650+ [1au] A? www.baidu.com. (42)
17:00:39.379122 IP 124.160.121.68.37930 > 123.45.67.2.53: 18650+ [1au] A? www.baidu.com. (42)
17:00:40.379210 IP 124.160.121.68.58526 > 123.45.67.3.53: 18650+ [1au] A? www.baidu.com. (42)

为了便于区分,上述内容人工填充了空行。从上面可以看到

  • dig 向三个 nameserver 分别请求解析,向每个 nameserver 请求解析的时间间隔为 1 秒而不是 2 秒
  • dig 在五次对文件中的 nameserver 轮询,每次轮询之间的时间间隔为 2 秒

如果我们在 /etc/resolv.conf 中配置了 timeout,到底是以 dig 的为准还是以 /etc/resolv.conf 中的为准?

  • dig 的 timeout 大于 resolv.conf 中的 timeout 时
1
2
3
4
5
6
7
8
[root@bogon ~]# cat /etc/resolv.conf
options timeout:3
nameserver 123.45.67.1
nameserver 123.45.67.2
nameserver 123.45.67.3
[root@bogon ~]#
[root@bogon ~]# dig +tries=5 +timeout=4 +short www.baidu.com
;; connection timed out; no servers could be reached

抓包结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
16:06:44.330997 IP 124.160.121.68.60827 > 123.45.67.1.53: 12194+ [1au] A? www.baidu.com. (42)
16:06:45.331000 IP 124.160.121.68.45589 > 123.45.67.2.53: 12194+ [1au] A? www.baidu.com. (42)
16:06:46.331082 IP 124.160.121.68.43181 > 123.45.67.3.53: 12194+ [1au] A? www.baidu.com. (42)

16:06:49.331133 IP 124.160.121.68.60827 > 123.45.67.1.53: 12194+ [1au] A? www.baidu.com. (42)
16:06:50.331220 IP 124.160.121.68.45589 > 123.45.67.2.53: 12194+ [1au] A? www.baidu.com. (42)
16:06:51.331312 IP 124.160.121.68.43181 > 123.45.67.3.53: 12194+ [1au] A? www.baidu.com. (42)

16:06:54.331403 IP 124.160.121.68.60827 > 123.45.67.1.53: 12194+ [1au] A? www.baidu.com. (42)
16:06:55.331488 IP 124.160.121.68.45589 > 123.45.67.2.53: 12194+ [1au] A? www.baidu.com. (42)
16:06:56.331571 IP 124.160.121.68.43181 > 123.45.67.3.53: 12194+ [1au] A? www.baidu.com. (42)

16:06:59.331658 IP 124.160.121.68.60827 > 123.45.67.1.53: 12194+ [1au] A? www.baidu.com. (42)
16:07:00.331747 IP 124.160.121.68.45589 > 123.45.67.2.53: 12194+ [1au] A? www.baidu.com. (42)
16:07:01.331837 IP 124.160.121.68.43181 > 123.45.67.3.53: 12194+ [1au] A? www.baidu.com. (42)

16:07:04.331913 IP 124.160.121.68.60827 > 123.45.67.1.53: 12194+ [1au] A? www.baidu.com. (42)
16:07:05.332004 IP 124.160.121.68.45589 > 123.45.67.2.53: 12194+ [1au] A? www.baidu.com. (42)
16:07:06.332093 IP 124.160.121.68.43181 > 123.45.67.3.53: 12194+ [1au] A? www.baidu.com. (42)

dig 没有指定 timeout 参数则使用默认值 5 秒

1
2
[root@bogon ~]# dig +tries=5 +short www.baidu.com 
;; connection timed out; no servers could be reached

抓包结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes

16:25:06.558406 IP 124.160.121.68.54373 > 123.45.67.1.53: 51295+ [1au] A? www.baidu.com. (42)
16:25:07.558450 IP 124.160.121.68.46082 > 123.45.67.2.53: 51295+ [1au] A? www.baidu.com. (42)
16:25:08.558486 IP 124.160.121.68.47769 > 123.45.67.3.53: 51295+ [1au] A? www.baidu.com. (42)

16:25:11.558564 IP 124.160.121.68.54373 > 123.45.67.1.53: 51295+ [1au] A? www.baidu.com. (42)
16:25:12.558629 IP 124.160.121.68.46082 > 123.45.67.2.53: 51295+ [1au] A? www.baidu.com. (42)
16:25:13.558724 IP 124.160.121.68.47769 > 123.45.67.3.53: 51295+ [1au] A? www.baidu.com. (42)

16:25:16.558808 IP 124.160.121.68.54373 > 123.45.67.1.53: 51295+ [1au] A? www.baidu.com. (42)
16:25:17.558894 IP 124.160.121.68.46082 > 123.45.67.2.53: 51295+ [1au] A? www.baidu.com. (42)
16:25:18.558976 IP 124.160.121.68.47769 > 123.45.67.3.53: 51295+ [1au] A? www.baidu.com. (42)

16:25:21.559058 IP 124.160.121.68.54373 > 123.45.67.1.53: 51295+ [1au] A? www.baidu.com. (42)
16:25:22.559147 IP 124.160.121.68.46082 > 123.45.67.2.53: 51295+ [1au] A? www.baidu.com. (42)
16:25:23.559230 IP 124.160.121.68.47769 > 123.45.67.3.53: 51295+ [1au] A? www.baidu.com. (42)

16:25:26.559320 IP 124.160.121.68.54373 > 123.45.67.1.53: 51295+ [1au] A? www.baidu.com. (42)
16:25:27.559404 IP 124.160.121.68.46082 > 123.45.67.2.53: 51295+ [1au] A? www.baidu.com. (42)
16:25:28.559488 IP 124.160.121.68.47769 > 123.45.67.3.53: 51295+ [1au] A? www.baidu.com. (42)
  • dig 的 timeout 小于 resolv.conf 中的 timeout 时
1
2
3
4
5
6
7
8
[root@bogon ~]# cat /etc/resolv.conf
options timeout:10
nameserver 123.45.67.1
nameserver 123.45.67.2
nameserver 123.45.67.3
[root@bogon ~]#
[root@bogon ~]# dig +tries=3 +time=2 +short www.baidu.com
;; connection timed out; no servers could be reached

抓包结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes

16:31:54.273506 IP 124.160.121.68.49564 > 123.45.67.1.53: 31368+ [1au] A? www.baidu.com. (42)
16:31:55.273448 IP 124.160.121.68.58295 > 123.45.67.2.53: 31368+ [1au] A? www.baidu.com. (42)
16:31:56.273534 IP 124.160.121.68.43357 > 123.45.67.3.53: 31368+ [1au] A? www.baidu.com. (42)

16:32:06.273581 IP 124.160.121.68.49564 > 123.45.67.1.53: 31368+ [1au] A? www.baidu.com. (42)
16:32:07.273668 IP 124.160.121.68.58295 > 123.45.67.2.53: 31368+ [1au] A? www.baidu.com. (42)
16:32:08.273755 IP 124.160.121.68.43357 > 123.45.67.3.53: 31368+ [1au] A? www.baidu.com. (42)

16:32:18.273872 IP 124.160.121.68.49564 > 123.45.67.1.53: 31368+ [1au] A? www.baidu.com. (42)
16:32:19.273953 IP 124.160.121.68.58295 > 123.45.67.2.53: 31368+ [1au] A? www.baidu.com. (42)
16:32:20.274030 IP 124.160.121.68.43357 > 123.45.67.3.53: 31368+ [1au] A? www.baidu.com. (42)

多次测试后发现:

  • 对于 dig 来说,自身的 timeout 和 /etc/resolv.conf 二者的 timeout 都指的是每次轮询完文件 nameserver 的超时时间,而不是每个 nameserver 的超时时间
  • 而对于 ping 来说,自身的 timeout 指的是每个包的超时时间,/etc/resolv.conf 的 timeout 指的是每个 nameserver 的超时时间,不是每次轮询的时间
  • 只要 /etc/resolv.conf 配置了 timeout 就直接忽略 dig 的 timeout ,以 /etc/resolv.conf 中配置的为准;否则就以 dig 设定的(未设定则使用默认值)为准

attempts

可选选项,系统尝试解析的次数,如果未设定则默认值是 2。系统允许最大值是 5,即当系统请求解析失败多少次之后,才会给系统或者程序返回解析失败的结果。对于 dig 命令来说,文件中配置的 attempts 如果是一个小数,则可能会提示语法错误,如果是 0 则不会进行解析。

1
attempts:n

因为 dig 命令也有个尝试次数的参数 +tries=T,默认是请求三次。不管 /etc/resolv.conf 有没有配置 attempts,在使用 dig 的时候都会以 dig 的为准。这里我们要对 /etc/resolv.conf 文件中的配置做实验,就使用 ping 来测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@bogon ~]# cat /etc/resolv.conf
options timeout:3
options attempts:2
nameserver 123.45.67.1
nameserver 123.45.67.2
nameserver 123.45.67.3
[root@bogon ~]#
[root@bogon ~]# time ping -c 3 www.baidu.com
ping: www.baidu.com: Name or service not known

real 0m36.040s
user 0m0.000s
sys 0m0.004s

抓包结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@bogon ~]# tcpdump -nn -i eth0 udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes

17:57:48.821495 IP 124.160.121.68.37237 > 123.45.67.1.53: 62997+ A? www.baidu.com. (31)
17:57:51.824546 IP 124.160.121.68.42482 > 123.45.67.2.53: 62997+ A? www.baidu.com. (31)
17:57:53.826591 IP 124.160.121.68.48320 > 123.45.67.3.53: 62997+ A? www.baidu.com. (31)
17:57:57.830621 IP 124.160.121.68.37237 > 123.45.67.1.53: 62997+ A? www.baidu.com. (31)
17:58:00.833656 IP 124.160.121.68.42482 > 123.45.67.2.53: 62997+ A? www.baidu.com. (31)
17:58:02.835688 IP 124.160.121.68.48320 > 123.45.67.3.53: 62997+ A? www.baidu.com. (31)

17:58:06.839767 IP 124.160.121.68.54390 > 123.45.67.1.53: 47323+ A? www.baidu.com. (31)
17:58:09.842821 IP 124.160.121.68.60543 > 123.45.67.2.53: 47323+ A? www.baidu.com. (31)
17:58:11.844871 IP 124.160.121.68.51676 > 123.45.67.3.53: 47323+ A? www.baidu.com. (31)
17:58:15.848917 IP 124.160.121.68.54390 > 123.45.67.1.53: 47323+ A? www.baidu.com. (31)
17:58:18.851953 IP 124.160.121.68.60543 > 123.45.67.2.53: 47323+ A? www.baidu.com. (31)
17:58:20.853984 IP 124.160.121.68.51676 > 123.45.67.3.53: 47323+ A? www.baidu.com. (31)

上面的抓包结果看上去有些费解。我们先算一下时间,已知 /etc/resolv.conf 中的 timeout 对于 ping 来说指的是每个 nameserver 的超时时间,我们设置了 3 个无效的 DNS ,超时时间为 3 ,因此尝试(轮询)一次的时间为 3 x 3 =9 , 两次尝试应该是 18 s 才对,为什么看到的却是 36 呢?这是因为 ping 在进行一次解析的时候会做两个不同的记录的询问请求,一个是 A 记录,另一个是 PTR 记录。当然 PTR 记录是得到 A 记录之后再做的,如果没有得到 A 记录就会再请求一次 A 记录。

我们不妨设置两个 DNS,第一个无效,第二个设为有效的来看看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@bogon ~]# cat /etc/resolv.conf
options timeout:3
options attempts:2
nameserver 123.45.67.1
nameserver 8.8.8.8
[root@bogon ~]#
[root@bogon ~]# time ping -c 3 www.baidu.com
PING www.a.shifen.com (61.135.169.125) 56(84) bytes of data.
64 bytes from 61.135.169.125 (61.135.169.125): icmp_seq=1 ttl=54 time=28.4 ms
64 bytes from 61.135.169.125 (61.135.169.125): icmp_seq=2 ttl=54 time=28.3 ms
64 bytes from 61.135.169.125 (61.135.169.125): icmp_seq=3 ttl=54 time=28.3 ms

--- www.a.shifen.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 4084ms
rtt min/avg/max/mdev = 28.356/28.378/28.405/0.195 ms

real 0m7.215s
user 0m0.002s
sys 0m0.004s

抓包结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@bogon ~]# tcpdump -nn -i eth0   icmp or udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
18:11:43.480899 IP 124.160.121.68.60040 > 123.45.67.1.53: 29894+ A? www.baidu.com. (31)
18:11:46.483955 IP 124.160.121.68.57979 > 8.8.8.8.53: 29894+ A? www.baidu.com. (31)
18:11:46.579031 IP 8.8.8.8.53 > 124.160.121.68.57979: 29894 3/0/0 CNAME www.a.shifen.com., A 61.135.169.125, A 61.135.169.121 (90)
18:11:46.579360 IP 124.160.121.68 > 61.135.169.125: ICMP echo request, id 14864, seq 1, length 64
18:11:46.607733 IP 61.135.169.125 > 124.160.121.68: ICMP echo reply, id 14864, seq 1, length 64
18:11:46.607865 IP 124.160.121.68.36510 > 123.45.67.1.53: 16127+ PTR? 125.169.135.61.in-addr.arpa. (45)
18:11:49.610912 IP 124.160.121.68.53473 > 8.8.8.8.53: 16127+ PTR? 125.169.135.61.in-addr.arpa. (45)
18:11:49.660012 IP 8.8.8.8.53 > 124.160.121.68.53473: 16127 NXDomain 0/1/0 (97)
18:11:49.662472 IP 124.160.121.68 > 61.135.169.125: ICMP echo request, id 14864, seq 2, length 64
18:11:49.690812 IP 61.135.169.125 > 124.160.121.68: ICMP echo reply, id 14864, seq 2, length 64
18:11:50.663851 IP 124.160.121.68 > 61.135.169.125: ICMP echo request, id 14864, seq 3, length 64
18:11:50.692213 IP 61.135.169.125 > 124.160.121.68: ICMP echo reply, id 14864, seq 3, length 64

分析:

1
18:11:43.480899 IP 124.160.121.68.60040 > 123.45.67.1.53: 29894+ A? www.baidu.com. (31)

向第一个 DNS 开始第一次尝试,做第一件事:询问 A 记录

1
18:11:46.483955 IP 124.160.121.68.57979 > 8.8.8.8.53: 29894+ A? www.baidu.com. (31)

第一个 DNS 无效,在等待超时时间 options timeout:3 也就是 3 秒之后,向第二个 DNS 第一次尝试,做第一件事:询问 A 记录

1
2
3
18:11:46.579031 IP 8.8.8.8.53 > 124.160.121.68.57979: 29894 3/0/0 CNAME www.a.shifen.com., A 61.135.169.125, A 61.135.169.121 (90)
18:11:46.579360 IP 124.160.121.68 > 61.135.169.125: ICMP echo request, id 14864, seq 1, length 64
18:11:46.607733 IP 61.135.169.125 > 124.160.121.68: ICMP echo reply, id 14864, seq 1, length 64

第二个 DNS 有效,并返回了 A 记录 ,立刻发送了一个 ICMP 包并且得到了响应

1
18:11:46.607865 IP 124.160.121.68.36510 > 123.45.67.1.53: 16127+ PTR? 125.169.135.61.in-addr.arpa. (45)

得到百度的响应之后并没有继续发送剩余的 ICMP 报文,而是又向第一个 DNS 请求了 PTR 记录的解析,注意这里并不是进行了第二次尝试,而是在做第一次尝试中的第二件事情:询问 PTR 记录

1
2
18:11:49.610912 IP 124.160.121.68.53473 > 8.8.8.8.53: 16127+ PTR? 125.169.135.61.in-addr.arpa. (45)
18:11:49.660012 IP 8.8.8.8.53 > 124.160.121.68.53473: 16127 NXDomain 0/1/0 (97)

第一个 DNS 无效,在等待超时时间 options timeout:3 也就是 3 秒之后,向第二个DNS 请求做第一次尝试中的第二件事情:询问 PTR 记录

1
2
3
4
18:11:49.662472 IP 124.160.121.68 > 61.135.169.125: ICMP echo request, id 14864, seq 2, length 64
18:11:49.690812 IP 61.135.169.125 > 124.160.121.68: ICMP echo reply, id 14864, seq 2, length 64
18:11:50.663851 IP 124.160.121.68 > 61.135.169.125: ICMP echo request, id 14864, seq 3, length 64
18:11:50.692213 IP 61.135.169.125 > 124.160.121.68: ICMP echo reply, id 14864, seq 3, length 64

发送剩余的两个 ICMP 报文

我们再算一下时间:

两个 DNS ,每个 DNS 都进行了一次尝试,做了两个不同的事情(询问A记录,再询问 PTR 记录),第一个 DNS 尝试一次的过程中超时两次时间是 6 秒,第二个 DNS 未超时,总共加起来是 7 秒左右

那么有没有可能是 PTR 记录是 ping 进行了第二次错误解析尝试呢(一次错误等待时长为 3 s,所以 attemps 设置为2,等待时长是 3s * 2 = 6s,正好与 time ping 的执行结果相吻合)

为了更有说服力,我们把尝试次数改为一次,前两个 DNS 设置为无效,第三个 DNS 有效,再做一次实验

1
2
3
4
5
6
[root@bogon ~]# cat /etc/resolv.conf
options timeout:3
options attempts:1
nameserver 123.45.67.1
nameserver 123.45.67.2
nameserver 8.8.8.8

我们假设 PTR 记录是 ping 进行了第二次错误解析尝试,而文件 /etc/resolv.conf 中我们只允许尝试一次,那么根据假设,等待的时间应该是 第一个 DNS 超时时间 3s 加上 第二个 DNS 超时时间 3s,总共为 6s,是不是这样呢?

1
2
3
4
5
6
7
8
9
10
11
[root@bogon ~]# time ping -c 1 www.baidu.com
PING www.a.shifen.com (61.135.169.121) 56(84) bytes of data.
64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=1 ttl=54 time=27.9 ms

--- www.a.shifen.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 27.960/27.960/27.960/0.000 ms

real 0m10.189s
user 0m0.004s
sys 0m0.002s

抓包结果

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@bogon ~]# tcpdump -nn -i eth0   icmp or udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
18:50:27.858495 IP 124.160.121.68.56337 > 123.45.67.1.53: 51295+ A? www.baidu.com. (31)
18:50:30.861543 IP 124.160.121.68.35679 > 123.45.67.2.53: 51295+ A? www.baidu.com. (31)
18:50:32.863588 IP 124.160.121.68.48112 > 8.8.8.8.53: 51295+ A? www.baidu.com. (31)
18:50:32.962175 IP 8.8.8.8.53 > 124.160.121.68.48112: 51295 3/0/0 CNAME www.a.shifen.com., A 61.135.169.121, A 61.135.169.125 (90)
18:50:32.962437 IP 124.160.121.68 > 61.135.169.121: ICMP echo request, id 15252, seq 1, length 64
18:50:32.990376 IP 61.135.169.121 > 124.160.121.68: ICMP echo reply, id 15252, seq 1, length 64
18:50:32.990478 IP 124.160.121.68.42683 > 123.45.67.1.53: 23619+ PTR? 121.169.135.61.in-addr.arpa. (45)
18:50:35.993528 IP 124.160.121.68.34443 > 123.45.67.2.53: 23619+ PTR? 121.169.135.61.in-addr.arpa. (45)
18:50:37.995573 IP 124.160.121.68.48473 > 8.8.8.8.53: 23619+ PTR? 121.169.135.61.in-addr.arpa. (45)
18:50:38.042414 IP 8.8.8.8.53 > 124.160.121.68.48473: 23619 NXDomain 0/1/0 (97)

从上述结果可以看到,ping 再做一次尝试的过程中存在了两种不同记录的查询,A 记录和 PTR 记录,因此 PTR 记录是 ping 进行了第二次错误解析尝试 的假设不成立。因此对于 ping 来说一次尝试的超时时间应该是 (PTR的超时时间 + A 记录的超时时间) * 无法解析的 nameserver 的个数6 x 2 =12

如果是下面的配置,使用 ping 的话超时时间就应该是 一次尝试:6 x 3 =18,两次尝试 36s,第一个实验中令人费解的时间此时已经有了来路

1
2
3
4
5
6
[root@bogon ~]# cat /etc/resolv.conf
options timeout:3
options attempts:2
nameserver 123.45.67.1
nameserver 123.45.67.2
nameserver 123.45.67.3

rotate

为了避免 DNS 查询每次都从第一个 nameserver 开始,来均衡各个 nameserver 的压力。如果第一个 nameserver 失效时,使用这个选项就可以提高解析的效率。另外 rotate 可能会优先使用可用的 DNS。要注意很多云主机上都有自己分配好的 DNS ,如果此时用了 rotate 将会在一定程度上影响效率,因为对于云主机来说,自家的 DNS 肯定比公共的响应要快。

我们取消options rotate 参数。这样既保证了 aws 上使用自己的快速 DNS,也保证了在他自己平台上一旦DNS 失效,咱们全部的 AWS 业务可以使用 公共 DNS 进行解析。
参数如下:

options timeout:1
options attempts:2
options single-request-reopen

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@bogon ~]# cat /etc/resolv.conf
options rotate
nameserver 123.45.67.1
nameserver 123.45.67.2
nameserver 8.8.8.8
[root@bogon ~]#
[root@bogon ~]# time ping www.baidu.com -c 5 -q
PING www.a.shifen.com (61.135.169.121) 56(84) bytes of data.

--- www.a.shifen.com ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4000ms
rtt min/avg/max/mdev = 27.947/28.093/28.183/0.169 ms

real 0m9.137s
user 0m0.001s
sys 0m0.004s

抓包结果

1
2
3
4
5
6
7
8
[root@bogon ~]# tcpdump -nn -i eth0   udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
20:23:05.883477 IP 124.160.121.68.51976 > 123.45.67.2.53: 29551+ A? www.baidu.com. (31)
20:23:10.888528 IP 124.160.121.68.39697 > 8.8.8.8.53: 29551+ A? www.baidu.com. (31)
20:23:10.988607 IP 8.8.8.8.53 > 124.160.121.68.39697: 29551 3/0/0 CNAME www.a.shifen.com., A 61.135.169.121, A 61.135.169.125 (90)
20:23:11.017108 IP 124.160.121.68.55712 > 8.8.8.8.53: 48423+ PTR? 121.169.135.61.in-addr.arpa. (45)
20:23:11.067780 IP 8.8.8.8.53 > 124.160.121.68.55712: 48423 NXDomain 0/1/0 (97)

single-request-reopen

1
options single-request-reopen

自从 CentOS6 之后,准确的说是 glibc >= 2.9 之后,Linux 系统 DNS 解析器(resolver)会使用相同的 socket 去请求 A(for IPv4) & AAAA(for IPv6) 记录解析。比如在存在防火墙等机制的网络环境中,同样源目的 ip,同样源目的 port,同样的第4层协议的连接,会被防火墙看成是同一个会话,因此会存在返回包被丢弃现象,过程如下:

默认的 DNS 解析过程是这样的:

  • 主机从一个随机的源端口(图中为 12345 ),请求 DNS 的 A 记录
  • 主机从同一个源端口,请求 DNS 的 AAAA 记录
  • 主机先收到 DNS 返回的 AAAA 记录(也可能先收到 A 记录)
  • 防火墙(可能是其他硬件设备,官方给出的描述是: Some hardware )认为本次交互通信已经完成,关闭连接
  • 剩下的 DNS 服务器返回的 A 记录响应包被防火墙丢弃

如果我们启用参数 single-request-reopen (默认未启用),一旦出现同一个 socket 发送的两次请求处理,解析端发送第一次请求后会关闭 socket,并在发送第二次请求前打开新的 socket 对 DNS server 端进行发送解析请求

生产环境中发现在阿里云的主机上可能会出现上述问题,因此如果主机使用了 IPv6 建议启用该参数。

edns0

1
options edns0

EDNS0:Extension Mechanisms for DNS Version 0,是 DNS 在 rfc1035 基础上对 DNS 协议的扩展。

修改原来的 DNS 协议,让其可以传输超过 512 字节的报文限制,但是必须客户端和服务端同时支持 edns0 才能使用该协议。glibc 2.6 及以上可以支持。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@bogon ~]# dig @8.8.8.8 www.baidu.com

; <<>> DiG 9.9.4-RedHat-9.9.4-50.el7_3.1 <<>> @8.8.8.8 www.baidu.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28203
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;www.baidu.com. IN A

;; ANSWER SECTION:
www.baidu.com. 1049 IN CNAME www.a.shifen.com.
www.a.shifen.com. 299 IN A 61.135.169.121
www.a.shifen.com. 299 IN A 61.135.169.125

;; Query time: 95 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sat May 12 20:46:23 CST 2018
;; MSG SIZE rcvd: 101

总结和建议

当第一个 nameser 解析超过指定的超时后会向第二个 nameserver 请求解析,此时第一个 nameserversocket 已经关闭,于是不存在这种情况:虽然第一个 nameserver 已经超时了,系统在向第二个 nameserver 请求解析时,就会有可能这时第一个 nameserver 将解析结果返回给系统了

文件 /etc/resolv.conf 中参数的有效性,准确的说应该视系统命令或应用程序而定的。例如:

  • 对于 pingdig 来说他们会最多轮询三个 nameserver ,但是 curl 则是轮询所有的 nameserver
  • attempts 为小数时, nslookupdig 会提示该文件语法错误
  • attmepts 为 0 时,对于 ping 来说则不会进行 DNS 解析请求,但对于 dignslookup 来说依然发送 DNS 解析请求
  • 一旦设定 timeout 参数值,系统会直接忽略掉 dig 自身的 timeout

为了避免单个 DNS 不可用时导致解析瘫痪,最好配置两个或多个 nameserver,一般最好配置三个,适当调整 timeoutattempts 提高解析效率。

配置示例

1
2
3
4
5
6
7
options timeout:1
options attempts:2
options rotate
options single-request-reopen
nameserver 8.8.8.8
nameserver 9.9.9.9
nameserver 114.114.114.114

什么会修改 resolv.conf

在维护的主机数量较多的时候,系统中 DNS 的配置我们应该做到统一化,随意修改或更新会造成管理混乱。比如统一只靠人为干预的方式来修改 /etc/resolv.conf ,并将其他可能会更新该文件的服务或配置禁用掉。因此我们需要找到可能会更新 /etc/resolv.conf 的来源:

  • 用户:这个不必多说了,有权限的用户都可以配置该文件
  • 服务或程序

网卡配置文件中的 DNS

网卡配置参考文档

在 Redhat 官方文档中可以找到相关说明

1
DNS{1,2}=address

where address is a name server address to be placed in /etc/resolv.conf provided that the PEERDNS directive is not set to no.

1
PEERDNS=<answer>

where <answer> is one of the following:

  • yes — Modify /etc/resolv.conf if the DNS directive is set. If using DHCP, then yes is the default.
  • no — Do not modify /etc/resolv.conf.

To configure an interface to use particular DNS servers, add the following lines to the ifcfg file:

1
2
3
PEERDNS=no
DNS1=ip-address
DNS2=ip-address

where ip-address is the address of a DNS server. This will cause the network service to update /etc/resolv.conf with the specified DNS servers specified. Only one DNS server address is necessary, the other is optional.

By default, NetworkManager calls the DHCP client, dhclient, when a profile has been set to obtain addresses automatically by setting BOOTPROTO to dhcp in an interface configuration file. If DHCP is required, an instance of dhclient is started for every Internet protocol, IPv4 and IPv6, on an interface. If NetworkManager is not running, or is not managing an interface, then the legacy network service will call instances of dhclient as required.

Important

In order to apply the configuration, you need to enter the nmcli c reload command.

PEERDNS=yes :如果网卡配置文件中设置了 DNS 就会修改 /etc/resolv.conf。在网卡配置文件中如果启动方式配置了 DHCP 之后,PEERDNS 默认为 yes

我们分 DHCP 和 静态方式 来测试

DHCP方式

单独配置 PEERDNS

我们先人为给系统配置公共的DNS,并且网卡配置自动获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@bogon ~]# cat /etc/resolv.conf 
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="dhcp"
ONBOOT="yes"

[root@bogon ~]# ifdown eth0;ifup eth0
Device 'eth0' successfully disconnected.
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)

[root@bogon ~]# cat /etc/resolv.conf
# Generated by NetworkManager
search localdomain
nameserver 192.168.127.2
nameserver 114.114.114.114

启动方式配置了 DHCP 之后我们知道 PEERDNS 默认为 yes,当重启了网卡之后,发现/etc/resolv.conf 确实被修改了,我们再加一条配置:PEERDNS=no 来看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@bogon ~]# cat /etc/resolv.conf 
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="dhcp"
PEERDNS="no"
ONBOOT="yes"

[root@bogon ~]# ifdown eth0;ifup eth0
Device 'eth0' successfully disconnected.
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/3)

[root@bogon ~]# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 114.114.114.114

此时发现虽然配置了 PEERDNS=no ,当重启了网卡之后/etc/resolv.conf 还是被修改了,但是少了一个 DNS 并且两次实验后文件中都会有个注释:# Generated by NetworkManager,查看进程后发现系统运行了一个服务 NetworkManager 为了排除其因素我们将此服务停止再次测试

1
systemctl stop NetworkManager

先不配置 PEERDNS 选项,即默认PEERDNS=yes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@bogon ~]# systemctl stop NetworkManager

[root@bogon ~]# cat /etc/resolv.conf
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="dhcp"
ONBOOT="yes"

[root@bogon ~]# ifdown eth0;ifup eth0
Determining IP information for eth0... done.

[root@bogon ~]# cat /etc/resolv.conf
; generated by /usr/sbin/dhclient-script
search localdomain
nameserver 192.168.127.2

配置 PEERDNS 选项,即PEERDNS=no

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@bogon ~]# cat /etc/resolv.conf
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="dhcp"
PEERDNS="no"
ONBOOT="yes"

[root@bogon ~]# ifdown eth0;ifup eth0
Determining IP information for eth0... done.

[root@bogon ~]# cat /etc/resolv.conf
nameserver 8.8.8.8

结论:

  • PEERDNS=yes 的情况下,会生成一个 nameserver 192.168.127.2 的配置,会更改 /etc/resolv.conf
  • PEERDNS=no 的情况下,不会生成一个 nameserver 192.168.127.2 的配置,不会更改 /etc/resolv.conf

那么在 PEERDNS=yes 的情况下生成的 nameserver 192.168.127.2 到底是哪的呢?在查看了 DHCP 服务器的配置后发现获得的这个地址是 DHCP 服务器分配给客户端的 DNS 地址

PEERDNS & DNS{1,2}=address

为了排除掉 NetworkManager 的因素我们将此服务停止

PEERDNS=yes & DNS{1,2}=address

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@bogon ~]# cat /etc/resolv.conf 
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="dhcp"
PEERDNS="yes"
DNS1="219.141.136.10"
DNS2="219.141.140.10"
ONBOOT="yes"

[root@bogon ~]# ifdown eth0;ifup eth0
Determining IP information for eth0... done.

[root@bogon ~]# cat /etc/resolv.conf
; generated by /usr/sbin/dhclient-script
search localdomain
nameserver 219.141.136.10
nameserver 219.141.140.10

PEERDNS=no & DNS{1,2}=address

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@bogon ~]# cat /etc/resolv.conf
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="dhcp"
PEERDNS="no"
DNS1="219.141.136.10"
DNS2="219.141.140.10"
ONBOOT="yes"

[root@bogon ~]# ifdown eth0;ifup eth0
Determining IP information for eth0... done.

[root@bogon ~]# cat /etc/resolv.conf
nameserver 8.8.8.8

静态指定方式

单独配置 PEERDNS

PEERDNS=yes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[[root@bogon ~]# cat /etc/resolv.conf 
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="static"
PEERDNS="yes"
ONBOOT="yes"
IPADDR=192.168.127.154
NETMASK=255.255.255.0
GATEWAY=192.168.127.2

[root@bogon ~]# ifdown eth0;ifup eth0

[root@bogon ~]# cat /etc/resolv.conf
nameserver 8.8.8.8

PEERDNS=no

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@bogon ~]# cat /etc/resolv.conf 
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="static"
PEERDNS="no"
ONBOOT="yes"
IPADDR=192.168.127.154
NETMASK=255.255.255.0
GATEWAY=192.168.127.2

[root@bogon ~]# ifdown eth0;ifup eth0

[root@bogon ~]# cat /etc/resolv.conf
nameserver 8.8.8.8

PEERDNS & DNS{1,2}=address

PEERDNS=yes & DNS{1,2}=address

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@bogon ~]# cat /etc/resolv.conf
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="static"
PEERDNS="yes"
ONBOOT="yes"
IPADDR=192.168.127.154
NETMASK=255.255.255.0
GATEWAY=192.168.127.2
DNS1="219.141.136.10"
DNS2="219.141.140.10"

[root@bogon ~]# ifdown eth0;ifup eth0

[root@bogon ~]# cat /etc/resolv.conf
nameserver 219.141.136.10
nameserver 219.141.140.10

PEERDNS=no & DNS{1,2}=address

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@bogon ~]# cat /etc/resolv.conf 
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE="eth0"
BOOTPROTO="static"
PEERDNS="no"
ONBOOT="yes"
IPADDR=192.168.127.154
NETMASK=255.255.255.0
GATEWAY=192.168.127.2
DNS1="219.141.136.10"
DNS2="219.141.140.10"

[root@bogon ~]# ifdown eth0;ifup eth0

[root@bogon ~]# cat /etc/resolv.conf
nameserver 8.8.8.8

总结

BOOTPROTO="dhcp" 的情况:

  • PEERDNS=yes:网卡配置文件中配置了 DNS{1,2}=address ,直接将 address 更新到 /etc/resolv.conf,不会去从 DHCP 服务器获取 DNS,如果没有配置 DNS{1,2}=address 就会尝试从 DHCP 服务器获得 DNS 并更新到 /etc/resolv.conf
  • PEERDNS=no :无论网卡配置文件中是否配置 DNS{1,2}=address,都不会更改 /etc/resolv.conf,也不会去从 DHCP 服务器获取 DNS

BOOTPROTO="static"的情况:

  • PEERDNS=yes:网卡配置文件中配置了 DNS{1,2}=address ,直接将 address 更新到 /etc/resolv.conf,不会去从 DHCP 服务器获取 DNS,如果没有配置 DNS{1,2}=address 则不更改 /etc/resolv.conf

  • PEERDNS=no :无论网卡配置文件中是否配置 DNS{1,2}=address,都不会更改 /etc/resolv.conf,也不会去从 DHCP 服务器获取 DNS

NetworkManager 中的 DNS

NetworkManager 是用于便携式计算机和其他可移动计算机的理想解决方案。提供了完善而直观的用户界面,可使用户轻松地切换其网络环境。也就是说 NetworkManager 更适用于桌面环境的 PC 电脑,服务器上一般都是命令行界面,我们完全可以不需要使用 NetworkManager ,而且 NetworkManager 服务和 network 服务有可能会起冲突,因此我们可以将此服务禁掉。

我们先假设由于某种依赖关系的原因必须启用 NetworkManager 服务,测试看看它是否会更改系统的 DNS 。

为了排除其他因素,我们在网卡配置文件中删除 DNS{1,2}=address 相关的配置,并添加 PEERDNS=no ,然后启用 NetworkManager 服务

1
systemctl start NetworkManager

BOOTPROTO="dhcp"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@bogon ~]# cat /etc/resolv.conf
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="dhcp"
PEERDNS="no"
ONBOOT="yes"

[root@bogon ~]# ifdown eth0;ifup eth0
Device 'eth0' successfully disconnected.
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/10)

[root@bogon ~]# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 114.114.114.114

BOOTPROTO="static"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@bogon ~]# cat /etc/resolv.conf 
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="static"
PEERDNS="no"
ONBOOT="yes"
IPADDR=192.168.127.154
NETMASK=255.255.255.0
GATEWAY=192.168.127.2

[root@bogon ~]# ifdown eth0;ifup eth0
Device 'eth0' successfully disconnected.
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/3)

[root@bogon ~]# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 114.114.114.114

BOOTPROTO="dhcp" + DNS{1,2}=address

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@bogon ~]# cat /etc/resolv.conf
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="dhcp"
PEERDNS="no"
ONBOOT="yes"
DNS1="219.141.136.10"
DNS2="219.141.140.10"


[root@bogon ~]# ifdown eth0;ifup eth0
Device 'eth0' successfully disconnected.
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/11)

[root@bogon ~]# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 219.141.136.10
nameserver 219.141.140.10
nameserver 114.114.114.114

BOOTPROTO="static" + DNS{1,2}=address

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@bogon ~]# cat /etc/resolv.conf
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="static"
PEERDNS="no"
ONBOOT="yes"
DNS1="219.141.136.10"
DNS2="219.141.140.10"
IPADDR=192.168.127.154
NETMASK=255.255.255.0
GATEWAY=192.168.127.2

[root@bogon ~]# ifdown eth0;ifup eth0
Device 'eth0' successfully disconnected.
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/12)

[root@bogon ~]# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 219.141.136.10
nameserver 219.141.140.10
nameserver 114.114.114.114

通过测试发现,默认情况下 NetworkManager 服务运行起来,如果改了网络配置就会更新系统的 /etc/resolv.conf,如果我们的目的只是修改一下 IP 地址,重启完网卡后却更新了系统的 DNS ,这显然不符合我们的预期。那么有没有什么办法可以避免这种问题发生呢?

查看了 NetworkManager 的服务配置文件 /etc/NetworkManager/NetworkManager.conf 之后,给出了 See "man 5 NetworkManager.conf" for details. 的提示,通过查看 man 手册发现了与 DNS 相关的配置:

1
2
3
4
5
6
dns
Set the DNS (resolv.conf) processing mode. If the key is unspecified, default is used, unless /etc/resolv.conf is a symlink to /run/systemd/resolve/resolv.conf, /lib/systemd/resolv.conf or /usr/lib/systemd/resolv.conf. In that case, systemd-resolved is chosen automatically.

default: NetworkManager will update /etc/resolv.conf to reflect the nameservers provided by currently active connections.

none: NetworkManager will not modify resolv.conf. This implies rc-manager unmanaged

那么我们将处理模式改为 none 并重启 NetworkManager 服务再次进行测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[root@bogon ~]# cat /etc/NetworkManager/NetworkManager.conf
# Configuration file for NetworkManager.
#
# See "man 5 NetworkManager.conf" for details.
#
# The directory /etc/NetworkManager/conf.d/ can contain additional configuration
# snippets. Those snippets override the settings from this main file.
#
# The files within conf.d/ directory are read in asciibetical order.
#
# If two files define the same key, the one that is read afterwards will overwrite
# the previous one.

[main]
plugins=ifcfg-rh
dns=none

[logging]
#level=DEBUG
#domains=ALL

[root@bogon ~]# cat /etc/resolv.conf
options rotate
nameserver 8.8.8.8

[root@bogon ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="static"
PEERDNS="no"
ONBOOT="yes"
DNS1="219.141.136.10"
DNS2="219.141.140.10"
IPADDR=192.168.127.154
NETMASK=255.255.255.0
GATEWAY=192.168.127.2

[root@bogon ~]# systemctl restart NetworkManager

[root@bogon ~]# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 219.141.136.10
nameserver 219.141.140.10
nameserver 114.114.114.114

修改了模式之后重启服务仍然会修改系统 DNS,是配置的参数没生效吗?我们将系统的 DNS 改回去再试一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@bogon ~]# cat /etc/resolv.conf          
options rotate
nameserver 8.8.8.8

[root@bogon ~]# systemctl restart NetworkManager

[root@bogon ~]# cat /etc/resolv.conf
options rotate
nameserver 8.8.8.8

[root@bogon ~]# ifdown eth0;ifup eth0
Device 'eth0' successfully disconnected.
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/3)

[root@bogon ~]# cat /etc/resolv.conf
options rotate
nameserver 8.8.8.8

这说明配置的参数可以阻止 NetworkManager 服务修改 /etc/resolv.conf

DNS配置优化

为了避免其他来源覆盖本机的 /etc/resoolv.conf,可以从以下几处来进行优化:

  • 网卡配置文件中删除 DNS{1,2}=address 相关的配置,并添加 PEERDNS=no
  • 网卡配置文件中添加 NM_CONTROLLED=no 来避免 network.serviceNetworkManager.service 冲突
  • 修改 NetworkManager 的处理模式,在 /etc/NetworkManager/NetworkManager.conf 中添加 dns=none
  • 如果没有必要的话,则停止 NetworkManager.service ,并禁止开机自启动
有钱任性,请我吃包辣条
0%