用 dig 命令辨别 DNS 是否被污染

来源: https://kyle.ai/blog/6340.html

原理

既然说起 DNS 和其污染问题,就不得不先看看 DNS 系统是如何工作的,这个自从上个世纪80出现的方便大家连接主机的系统的确是有问题。从 Wikipedia 上偷张图先。
563px-An_example_of_theoretical_DNS_recursion.svg_
DNS 解析流程图
图中可以看到我们的 ISP 的 DNS 服务器在图中叫做 DNS Recurser,在解析一个域名的时候,总共经过了以下的步骤,图是以 www.wikipedia.org 作为示范的:
  1. 向 root 服务器获取该 gTLD 的管辖服务器,图中为 org 结尾的域名
  2. root 服务器返回 org 的管辖服务器
  3. 向 org 的管辖服务器查询,谁来负责解析 wikipedia.org 这个域名的
  4. org 的管辖服务器返回解析 wikipedia.org 的服务器 IP 地址
  5. 向 wikipedia.org 的解析服务器发出查询,解析 www.wikipedia.org 的 IP 地址
  6. 拿到最终要的 IP 地址
共6个步骤。那么如果在最后一次查询的时候,有人假冒了 wikipedia.org 的解析服务器,则可以在中间进行欺骗攻击,致使用户最后得到的 IP 地址不是真实的地址。如图所示,
563px-An_example_of_theoretical_DNS_recursion.svg_1
解析请求被劫持
更详细的关于 DNS 的内容,可以自行参考 rfc1035(http://tools.ietf.org/html/rfc1035)。

手工模拟

以上是大致的解析原理,我们手工一步一步来模拟解析的每个步骤吧。这里我用的环境是北京联通 ADSL + Mac OS X 10.7 『Lion』 + 某国家 VPN 一条。工具用到了 dig 和 tcpdump 来完成,Windows 下默认木有俩工具似乎,大家自行寻找吧,或者找一个 GNU/Linux 发行版装上,个人推荐 Ubuntu,有 red hat 情节的,就 Fedora 好了。首先用联通的 ADSL 来试验下
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
$ dig //直接获取根服务器的地址
; <<>> DiG 9.8.3-P1 <<>>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59858
;; flags: qr rd ra; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 3
;; QUESTION SECTION:
;.              IN  NS
;; ANSWER SECTION:
.           205043  IN  NS  e.root-servers.net.
.           205043  IN  NS  h.root-servers.net.
.           205043  IN  NS  l.root-servers.net.
.           205043  IN  NS  i.root-servers.net.
.           205043  IN  NS  a.root-servers.net.
.           205043  IN  NS  d.root-servers.net.
.           205043  IN  NS  c.root-servers.net.
.           205043  IN  NS  b.root-servers.net.
.           205043  IN  NS  j.root-servers.net.
.           205043  IN  NS  k.root-servers.net.
.           205043  IN  NS  g.root-servers.net.
.           205043  IN  NS  m.root-servers.net.
.           205043  IN  NS  f.root-servers.net.
;; ADDITIONAL SECTION:
k.root-servers.net. 604222  IN  AAAA    2001:7fd::1
m.root-servers.net. 602881  IN  A   202.12.27.33
f.root-servers.net. 604218  IN  AAAA    2001:500:2f::f
;; Query time: 11 msec
;; SERVER: 202.96.134.133#53(202.96.134.133)
;; WHEN: Wed Sep 27 15:56:19 2017
;; MSG SIZE  rcvd: 300
这里我们可以看到,全球的域名根服务器共有从 a 到 m,共 13 组服务器。继续去 dig 出来这些服务器的地址吧,随便找一个好了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ dig e.root-servers.net
; <<>> DiG 9.8.3-P1 <<>> e.root-servers.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25194
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;e.root-servers.net.        IN  A
;; ANSWER SECTION:
e.root-servers.net. 84796   IN  A   192.203.230.10
;; Query time: 4 msec
;; SERVER: 202.96.134.133#53(202.96.134.133)
;; WHEN: Wed Sep 27 15:56:51 2017
;; MSG SIZE  rcvd: 52
这里我们抓到了其中一组的 DNS 根服务器 e.root-servers.net 的地址为 192.203.230.10,继续
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
44
45
46
47
48
49
$ dig -t ns @192.203.230.10 com.
; <<>> DiG 9.8.3-P1 <<>> -t ns @192.203.230.10 com.
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 691
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 13, ADDITIONAL: 15
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;com.               IN  NS
;; AUTHORITY SECTION:
com.            172800  IN  NS  a.gtld-servers.net.
com.            172800  IN  NS  b.gtld-servers.net.
com.            172800  IN  NS  c.gtld-servers.net.
com.            172800  IN  NS  d.gtld-servers.net.
com.            172800  IN  NS  e.gtld-servers.net.
com.            172800  IN  NS  f.gtld-servers.net.
com.            172800  IN  NS  g.gtld-servers.net.
com.            172800  IN  NS  h.gtld-servers.net.
com.            172800  IN  NS  i.gtld-servers.net.
com.            172800  IN  NS  j.gtld-servers.net.
com.            172800  IN  NS  k.gtld-servers.net.
com.            172800  IN  NS  l.gtld-servers.net.
com.            172800  IN  NS  m.gtld-servers.net.
;; ADDITIONAL SECTION:
a.gtld-servers.net. 172800  IN  A   192.5.6.30
b.gtld-servers.net. 172800  IN  A   192.33.14.30
c.gtld-servers.net. 172800  IN  A   192.26.92.30
d.gtld-servers.net. 172800  IN  A   192.31.80.30
e.gtld-servers.net. 172800  IN  A   192.12.94.30
f.gtld-servers.net. 172800  IN  A   192.35.51.30
g.gtld-servers.net. 172800  IN  A   192.42.93.30
h.gtld-servers.net. 172800  IN  A   192.54.112.30
i.gtld-servers.net. 172800  IN  A   192.43.172.30
j.gtld-servers.net. 172800  IN  A   192.48.79.30
k.gtld-servers.net. 172800  IN  A   192.52.178.30
l.gtld-servers.net. 172800  IN  A   192.41.162.30
m.gtld-servers.net. 172800  IN  A   192.55.83.30
a.gtld-servers.net. 172800  IN  AAAA    2001:503:a83e::2:30
b.gtld-servers.net. 172800  IN  AAAA    2001:503:231d::2:30
;; Query time: 349 msec
;; SERVER: 192.203.230.10#53(192.203.230.10)
;; WHEN: Wed Sep 27 15:57:39 2017
;; MSG SIZE  rcvd: 509
上面共有从 a 到 m,一样是 13 组服务器在所有的 com. 的 gTLD 的记录保存。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ dig -t ns @192.5.6.30 twitter.com
; <<>> DiG 9.8.3-P1 <<>> -t ns @192.5.6.30 twitter.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21761
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;twitter.com.           IN  NS
;; ANSWER SECTION:
twitter.com.        240 IN  A   78.16.49.15
;; Query time: 13 msec
;; SERVER: 192.5.6.30#53(192.5.6.30)
;; WHEN: Wed Sep 27 15:58:18 2017
;; MSG SIZE  rcvd: 45
这里看到问题了么?本来应该返回 twitter.com 的具体的解析服务器,为什么直接返回了一个 A 记录?而且还是这么诡异的一个地址?查询以下这个 IP 的归属地,是『新西兰 奥克兰Telstraclear公司』,应该是胡乱编出来的地址了。至此再测试下去意义也就不大了,具体原因等会儿分析。换上 VPN 看看结果如何
1
2
3
4
5
6
7
8
9
10
11
12
13
$ dig
# 这里的结果完全一样,我们继续选择 e 的那组
$ dig e.root-servers.net
# 嗯,这里也一样,继续
$ dig -t ns @192.203.230.10 com.
# 没有什么新奇的,继续…
以上几条结果都是一样的返回
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
$ dig -t ns @192.5.6.30 twitter.com
; <<>> DiG 9.8.3-P1 <<>> -t ns @192.5.6.30 twitter.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56292
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 6
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;twitter.com.           IN  NS
;; AUTHORITY SECTION:
twitter.com.        172800  IN  NS  ns3.p34.dynect.net.
twitter.com.        172800  IN  NS  ns4.p34.dynect.net.
twitter.com.        172800  IN  NS  r01-01.ns.twtrdns.net.
twitter.com.        172800  IN  NS  r01-02.ns.twtrdns.net.
twitter.com.        172800  IN  NS  d01-01.ns.twtrdns.net.
twitter.com.        172800  IN  NS  d01-02.ns.twtrdns.net.
;; ADDITIONAL SECTION:
ns3.p34.dynect.net. 172800  IN  A   208.78.71.34
ns4.p34.dynect.net. 172800  IN  A   204.13.251.34
r01-01.ns.twtrdns.net.  172800  IN  A   205.251.195.113
r01-02.ns.twtrdns.net.  172800  IN  A   205.251.197.74
d01-01.ns.twtrdns.net.  172800  IN  A   208.78.70.34
d01-02.ns.twtrdns.net.  172800  IN  A   204.13.250.34
;; Query time: 171 msec
;; SERVER: 192.5.6.30#53(192.5.6.30)
;; WHEN: Wed Sep 27 16:00:31 2017
;; MSG SIZE  rcvd: 270
到这里的结果就和刚才不一样了,可以看到,192.5.6.30 这个服务器正常返回了应该负责解析 twitter.com 的真实 ns 的服务器,既然都做到这里了,就继续下去吧,继续从里面随便抓一个出来
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
44
45
46
47
48
$ dig @208.78.71.34 twitter.com any
;; Truncated, retrying in TCP mode.
; <<>> DiG 9.8.3-P1 <<>> @208.78.71.34 twitter.com any
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16674
;; flags: qr aa rd; QUERY: 1, ANSWER: 28, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;twitter.com.           IN  ANY
;; ANSWER SECTION:
twitter.com.        293 IN  SOA ns1.p26.dynect.net. zone-admin.dyndns.com. 2007137844 3600 600 604800 60
twitter.com.        13999   IN  NS  ns2.p34.dynect.net.
twitter.com.        13999   IN  NS  r01-02.ns.twtrdns.net.
twitter.com.        13999   IN  NS  r01-01.ns.twtrdns.net.
twitter.com.        13999   IN  NS  d01-02.ns.twtrdns.net.
twitter.com.        13999   IN  NS  d01-01.ns.twtrdns.net.
twitter.com.        13999   IN  NS  ns3.p34.dynect.net.
twitter.com.        13999   IN  NS  ns1.p34.dynect.net.
twitter.com.        13999   IN  NS  ns4.p34.dynect.net.
twitter.com.        79  IN  A   199.59.148.10
twitter.com.        79  IN  A   199.16.156.6
twitter.com.        79  IN  A   199.59.150.7
twitter.com.        79  IN  A   199.16.156.102
twitter.com.        79  IN  A   199.16.156.38
twitter.com.        79  IN  A   199.16.156.70
twitter.com.        79  IN  A   199.59.149.198
twitter.com.        79  IN  A   199.16.156.198
twitter.com.        79  IN  A   199.59.149.230
twitter.com.        79  IN  A   199.59.148.82
twitter.com.        79  IN  A   199.16.156.230
twitter.com.        79  IN  A   199.59.150.39
twitter.com.        300 IN  TXT "v=spf1 ip4:199.16.156.0/22 ip4:199.59.148.0/22 ip4:8.25.194.0/23 ip4:8.25.196.0/23 ip4:204.92.114.203 ip4:204.92.114.204/31 ip4:23.21.83.90 include:_spf.google.com include:_thirdparty.twitter.com -all"
twitter.com.        300 IN  TXT "google-site-verification=h6dJIv0HXjLOkGAotLAWEzvoi9SxqP4vjpx98vrCvvQ"
twitter.com.        600 IN  MX  10 aspmx.l.google.com.
twitter.com.        600 IN  MX  20 alt2.aspmx.l.google.com.
twitter.com.        600 IN  MX  30 ASPMX3.GOOGLEMAIL.COM.
twitter.com.        600 IN  MX  20 alt1.aspmx.l.google.com.
twitter.com.        600 IN  MX  30 ASPMX2.GOOGLEMAIL.COM.
;; Query time: 21 msec
;; SERVER: 208.78.71.34#53(208.78.71.34)
;; WHEN: Wed Sep 27 16:01:08 2017
;; MSG SIZE  rcvd: 891
我们可以发现挂上 VPN 之后的解析流程才是正确无误的过程,但是为什么不挂上就不能正确解析?自然是 DNS 服务器被污染了。并且拦截的方式似乎也很弱智,发现 UDP 53 口的包带有 twitter.com 字样,直接返回一个随即、胡编出来的 IP 地址,也不管人家到底是不是直接要去查 twitter.com 的 A 记录。为了证明这种猜想,继续做一些试验吧。不如发一个错误的 DNS 包出去,看看返回什么结果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ dig @202.204.49.251 twitter.com -t ns --->> 查询的服务器是 202.204.48.251
; <<>> DiG 9.8.3-P1 <<>> @202.204.49.251 twitter.com -t ns
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28290
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;twitter.com.           IN  NS
;; ANSWER SECTION:
twitter.com.        64  IN  A   243.185.187.39
;; Query time: 24 msec
;; SERVER: 202.204.49.251#53(202.204.49.251)
;; WHEN: Wed Sep 27 16:02:43 2017
;; MSG SIZE  rcvd: 45
这里的服务器是 iBeiKe 在教育网内的服务器,对于外网没有开除了 80 的任何口,而且也没有 53 的 UDP 开着,果然,够弱智!

tcpdump 抓包

tcpdump 这个东西虽然叫做 tcpdump,但是 UDP 抓起来也没有问题,随便抓抓 DNS 的解析包,不需要什么重型武器,这种轻量级别就很好用了。环境和上面一样,我用的无线网络,所以在 Mac OS X 的接口就是 en1 了。不上 VPN 看看结果如何吧
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
$ sudo tcpdump -i en1 -vvv udp
16:05:10.189549 IP (tos 0x0, ttl 64, id 51997, offset 0, flags [none], proto UDP (17), length 57)
    192.168.0.86.61289 > a.gtld-servers.net.domain: [udp sum ok] 4731+ NS? twitter.com. (29)
16:05:10.190103 IP (tos 0x0, ttl 255, id 51444, offset 0, flags [none], proto UDP (17), length 69)
    192.168.0.86.53167 > ns.szptt.net.cn.domain: [udp sum ok] 14187+ PTR? 30.6.5.192.in-addr.arpa. (41)
16:05:10.200364 IP (tos 0x0, ttl 45, id 59500, offset 0, flags [DF], proto UDP (17), length 73)
# 假的结果返回
    a.gtld-servers.net.domain > 192.168.0.86.61289: [udp sum ok] 4731 q: NS? twitter.com. 1/0/0 twitter.com. [1m38s] A 59.24.3.173 (45)
16:05:10.201166 IP (tos 0x0, ttl 197, id 55906, offset 0, flags [none], proto UDP (17), length 84)
    a.gtld-servers.net.domain > 192.168.0.86.61289: [udp sum ok] 4731* q: NS? twitter.com. 1/0/0 twitter.com. [1m] A 59.24.3.174 (56)
16:05:10.258033 IP (tos 0x0, ttl 51, id 56581, offset 0, flags [none], proto UDP (17), length 298)
# 正确的返回
    a.gtld-servers.net.domain > 192.168.0.86.61289: [udp sum ok] 4731- q: NS? twitter.com. 0/6/6 ns: twitter.com. [2d] NS ns3.p34.dynect.net., twitter.com. [2d] NS ns4.p34.dynect.net., twitter.com. [2d] NS r01-01.ns.twtrdns.net., twitter.com. [2d] NS r01-02.ns.twtrdns.net., twitter.com. [2d] NS d01-01.ns.twtrdns.net., twitter.com. [2d] NS d01-02.ns.twtrdns.net. ar: ns3.p34.dynect.net. [2d] A 208.78.71.34, ns4.p34.dynect.net. [2d] A 204.13.251.34, r01-01.ns.twtrdns.net. [2d] A 205.251.195.113, r01-02.ns.twtrdns.net. [2d] A 205.251.197.74, d01-01.ns.twtrdns.net. [2d] A 208.78.70.34, d01-02.ns.twtrdns.net. [2d] A 204.13.250.34 (270)
16:05:10.429786 IP (tos 0x0, ttl 51, id 0, offset 0, flags [none], proto UDP (17), length 73)
    a.gtld-servers.net.domain > 192.168.0.86.61289: [udp sum ok] 4731 q: NS? twitter.com. 1/0/0 twitter.com. [3m29s] A 78.16.49.15 (45)
16:05:10.718695 IP (tos 0x0, ttl 59, id 0, offset 0, flags [DF], proto UDP (17), length 101)
    ns.szptt.net.cn.domain > 192.168.0.86.53167: [udp sum ok] 14187 q: PTR? 30.6.5.192.in-addr.arpa. 1/0/0 30.6.5.192.in-addr.arpa. [1d] PTR a.gtld-servers.net. (73)
16:05:11.124993 IP (tos 0x0, ttl 4, id 27621, offset 0, flags [none], proto UDP (17), length 157)
    192.168.0.119.63409 > 239.255.255.250.ssdp: [udp sum ok] UDP, length 129
16:05:11.125357 IP (tos 0x0, ttl 1, id 29662, offset 0, flags [none], proto UDP (17), length 304)
    192.168.0.149.50587 > 239.255.255.250.ssdp: [udp sum ok] UDP, length 276
16:05:11.227349 IP (tos 0x0, ttl 4, id 27623, offset 0, flags [none], proto UDP (17), length 157)
    192.168.0.119.63409 > 239.255.255.250.ssdp: [udp sum ok] UDP, length 129
唔,有人抢在正确的包之前跑来了。你为什么这么积极呢?为什么呢…

转自:https://2.botu.me/post/2763.html
发表评论