原理
既然说起 DNS 和其污染问题,就不得不先看看 DNS 系统是如何工作的,这个自从上个世纪80出现的方便大家连接主机的系统的确是有问题。从 Wikipedia 上偷张图先。
DNS 解析流程图
图中可以看到我们的 ISP 的 DNS 服务器在图中叫做 DNS Recurser,在解析一个域名的时候,总共经过了以下的步骤,图是以 www.wikipedia.org 作为示范的:
- 向 root 服务器获取该 gTLD 的管辖服务器,图中为 org 结尾的域名
- root 服务器返回 org 的管辖服务器
- 向 org 的管辖服务器查询,谁来负责解析 wikipedia.org 这个域名的
- org 的管辖服务器返回解析 wikipedia.org 的服务器 IP 地址
- 向 wikipedia.org 的解析服务器发出查询,解析 www.wikipedia.org 的 IP 地址
- 拿到最终要的 IP 地址
共6个步骤。那么如果在最后一次查询的时候,有人假冒了 wikipedia.org 的解析服务器,则可以在中间进行欺骗攻击,致使用户最后得到的 IP 地址不是真实的地址。如图所示,
解析请求被劫持
更详细的关于 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 来试验下
$ 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 出来这些服务器的地址吧,随便找一个好了
$ 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,继续
$ 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 的记录保存。
$ 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 看看结果如何
$ dig # 这里的结果完全一样,我们继续选择 e 的那组 $ dig e.root-servers.net # 嗯,这里也一样,继续 $ dig -t ns @192.203.230.10 com. # 没有什么新奇的,继续…
以上几条结果都是一样的返回
$ 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 的服务器,既然都做到这里了,就继续下去吧,继续从里面随便抓一个出来
$ 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 包出去,看看返回什么结果。
$ 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 看看结果如何吧
$ 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