由一道题目引发的DNS学习笔记

0x00 起因

前几天的全国高校网络信息安全管理运维挑战赛DNS101,从上午查资料到结束,虽然最终做出来了,但却不解其原理,遂
开启了对DNS的学习历程。


0x01 DNS是什么

DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。 摘自百度百科

百科的解释非常直接,但对于我这种小白来说太过宽泛,看了之后有了个大致的了解,却也说不清到底是个啥,我还学要了解更多。万一别人问起来至少要吹牛逼吹得高大上一些嘛


0x02 为什么会有DNS

网络通讯大部分都是基于TCP/IP协议,而此协议则是基于IP地址,所以计算机在网络上进行通讯时只能识别如1.2.3.4之类的IP地址而不能识别域名。由于IP地址不方便记忆,于是需要DNS将输入的域名“翻译”成相对应的IP地址,正确访问对应的网页。


0x03 需要知道的一些术语

域名(Domain Name)

这大概是我们接触到的DNS最常用方式,也就是我们通常所说的网址如baidu.com,google.com等。

顶级域名(Top-Level Domain)

又称一级域名,分为三类:一是国家和地区顶级域名(country code top-level domains,简称ccTLDs),如cnjp等;二是国际顶级域名(generic top-level domains,简称gTLDs),如表示工商企业的com,表示网络提供商的net,表示非盈利组织的org等。三是新顶级域名(New gTLD)如通用的xyz、代表“红色”的red、代表“人”的men等一千多种。

全称域名(FullyQualified Domain Name)

又称完全合格域名,是指主机名加上全称路径,全路径中列出了序列中所有域成员。可以从逻辑上准确地表示出主机在域名树中的位置,也可以说全称域名是主机名的一种完全表示形式。如www.baidu.com,www.google.com等。

IP地址(IP Address)

IP地址用于以数字(IPv4)或字母数字(IPv6)的形式唯一地在网络上寻址。
一个IPv4地址是由四个数字和三个将数字分开的冒号所构成如127.0.0.1。随着全世界越来越多的设备和人员上线,对IPv4地址有限且需求达到顶峰,于是IPv6应运而生。IPv6遵循与IPv4相似的原则:允许设备在其所在的网络上被唯一引用,但是寻址语法包含字母、数字、字符以增加可用地址的数量,如fe80::45a8:3bcd:fb46:82b%36

Zone文件(Zonefile)

Zonefile是一个包含单个域的不同记录的文本文件,文件中每一行都包含特定域的名称以及与其关联的值和类型。
如在google.com的zonefile中可能存在一行用于解析www并通过A记录映射到173.194.34.68(谷歌的ip)。

记录(Records)

DNS的记录是域和相关数据之间的独立映射。

  • A记录:又称IP指向,用户可以在此设置子域名并指向到自己的目标主机地址上,从而实现通过域名找到服务器。

指向的目标主机地址类型只能使用IP地址

  • PTR记录指针记录,是A记录逆向记录,用于将IP地址解析为域名。

  • AAAA记录:IPv6下的A记录PTR记录,可将一个域名解析到IPv6地址上,也可以将子域名解析到IPv6地址上。

  • CNAME记录:又称别名指向,用户可以为主机设置一个别名。如设置fish.o0O.com指向一个主机www.google.com那么以后就能用fish.o0O.com来代替访问www.google.com了。

CNAME的目标主机地址只能使用主机名,不能使用IP地址;主机名前不能有任何其他前缀,如http://等是不被允许的;A记录优先于CNAME记录,即如果一个主机地址同时存在A记录CNAME记录,则CNAME记录不生效。

  • MX记录邮箱交换记录,用于将以改域名为结尾的电子邮件指向对应的邮件服务器以进行处理。如用户所用的邮件十以域名fish.com结尾的,则需要在Zonefile中添加一条MX记录来处理所有以@fish.com结尾的邮件。

MX记录可以使用主机名或IP地址MX记录可以通过设置优先级实现主辅服务器设置,“优先级”中的数字越小表示级别越高。也可以使用相同优先级达到负载均衡的目的;若在“主机名”中填入子域名则此MX记录只对该子域名生效。

  • NS记录域名服务器记录,用来表明由哪台服务器对该域名进行解析。如用户希望由1.2.3.4来解析fish.o0O.com,则需要设置fish.o0O.com的NS记录

“优先级”中的数字越小表示级别越高;“IP地址/主机名”中既可以填写IP地址,也可以填写像cat.o0O.com这样的主机地址,但必须保证该主机地址有效。如将fish.o0O.com的NS记录指向到cat.o0O.com,在设置NS记录的同时还需要设置cat.o0O.com的指向,否则NS记录将无法正常解析;NS记录优先于A记录,即如果一个主机地址同时存在NS记录A记录,则A记录不生效。这里的NS记录只对子域名生效。

  • SOA记录起始授权机构记录NS记录说明了有多台服务器在进行解析,而SOA记录则说明了在众多NS记录中主要服务器的记录

NS记录SOA记录是任何一个DNS的Zonefile中都不可或缺的两条记录

  • SRV记录服务器资源记录,是在RFC2052中新定义的记录,很多老版本的DNS并不支持此记录SRV记录说明了一个服务器能够提供什么样的服务,域内的计算机需要依赖DNS中的SRV记录来定位域控制器。

  • TXT记录:为某条记录设置说明,起注释的作用。

此处只列举了一部分记录,实际上还存在DNS还存在很多类型的记录

An Example of Zonefile

$TTL     86400;      // specified in seconds, but could be 24h or 1d
$ORIGIN  example.com

@ 1D IN SOA ns1.example.com. hostmaster.example.com. (
            123456 ; // serial
                  3H     ;   // refresh
            15     ; // retry
            1w     ; // example
            3h     ; // minimum
            )

      IN NS ns1.example.com
      IN NS ns2.example.com // Good practice to specify multiple nameservers for fault-tolerance
      IN NS ns1.foo.com     // Using external nameservers for fault-tolerance is even better
      IN NS ns1.bar.com     // And multiple external nameservers is better still!

      IN MX 10 mail.example.com // Here, 10 is the highest priority mail server, so is the first to be used
      IN MX 20 mail.foo.com     // If the highest priority mail server is unavailable, fall back to this one

ns1   IN A     1.2.3.4
ns1   IN AAAA  1234:5678:a1234::12 // A and AAAA records can co-exist happily. Useful for supporting early IPv6 adopters.
ns2   IN A     5.6.7.8
ns2   IN A     1234:5678:a1234::89
mail  IN A     1.3.5.7
www   IN A     2.4.6.8
sip   IN CNAME www.example.com.
ftp   IN CNAME www.example.com.
mail  IN TXT   "v=spf1 a -all"

_sip._tcp.example.com. IN SRV 0 5 5060 sip.example.com.

0x04 DNS如何工作

根服务器(Root Servers)

DNS树的顶端是13个(从a到m)由ICANN(Internet Corporation for Assigned Names and Numbers)控制的独立的根服务器。目的是处理那些级别较低的域名服务器不能充分处理的与顶级域名相关的信息请求。根服务器不会对自己无法处理的域名保存任何记录,只会不停地对请求做出响应,并把域名解析到最优的域名服务器去进行进一步处理。

如我们对www.google.com的请求直接进入根服务器根服务器将解析www.google.com记录,但无法找到它的地址,根服务器会将这个域名的com部分匹配,并将这个信息传递回来源处。

TLD服务器

接着上一步,一旦对www.google.com的请求得到回复,根服务器就会代替域名服务器接受来自发送请求的计算机的询问:www.google.com的地址在哪里。TLD服务器将尝试在其记录中找到www.google.com的信息,但只能回复关于google.com的详细信息。在这一阶段,计算机会知道这个服务器以com解析,且至少能够将地址映射到某一个IP地址

域级域名服务器(Domain-level Nameservers)

到了这个阶段,对www.google.com的请求已经被回复了两次:第一次由根服务器不处理任何记录但知道是需要归于com处理;再一次由TLD服务器处理com并且知道google在哪里。即使如此,我们仍还有一个www未处理,为此,该请求将传给google.com的服务器进行解析。google的服务器将在其记录中正确查找到www.google.com,并使用其对应的IP地址进行响应。

至此,我们完成了一个完整的访问请求,看似步骤复杂,实际上DNS查询在短短几秒之内就会完成。


0x05主机特定的DNS配置(Host-specific DNS Configuration)

也就是我们常说的hosts文件,我一直以来有个疑问为什么装破解版软件时需要改hosts文件,为什么改了hosts文件之后就能够访问谷歌网站,hosts文件到底是何方神圣?这一节将从Unix系统的方面说一说主机特定的DNS配置,Linux系统和Windows系统类似。

/etc/hosts

/etc/hosts具有充当本地替代DNS的作用,若用户想要在特定的计算机上覆盖DNS中的记录而又不想影响其他用户使用该记录,则可使用/etc/hosts来覆盖DNS,或者将其作为DNS的备份:若在/etc/hosts中的基础结构中指定了关键型的hosts,则即使在持有用户域名的域名服务器中缺少Zonefile时也能够正常解析。
但是/etc/hosts远远不能DNS的替代品:DNS具有更加丰富的记录类型,而/etc/hosts只能相当于众多记录中的A记录
/etc/hosts大概是长这个样纸滴:

127.0.0.1 localhost 
255.255.255.255 broadcasthost 
:: 1 localhost 
fe80 :: 1% lo0 localhost

192.168.2.2 sql01 
192.168.2.3 sql02 
192.168.1.10 fish bubble o0O

该文件的前四行是系统自带的,并在启动时生效。前两行分别将localhost127.0.0.1之间和broadcasthost255.255.255.255之间建立映射,后面两行其实是在IPv6下第一行的等价物。在第四行之后,我们可以指定一个名称并将其映射到一个IP地址。如第五行,我们将sql01映射到192.168.2.2,这意味着在具有这个/etc/hosts的主机上我们可以访问sql01并以192.168.2.2作为响应,第六行同理。而第七行却是一个奇怪的例子,一个IP地址对应了3个域名,当以这种方式引用时(对于每个IP地址使用多个以空格分隔的名称),则可以使用任意指定的域名访问该IP地址,即使用fishbubbleo0O都是访问192.168.1.10的有效方式。


0x06 缓存(Caching)

为降低硬件成本、减轻网络压力,并加快对常见域名的响应速度,很多客户机都会缓存DNS记录。在ZonefileSOA记录中会指定一个expiry,该值将决定Zonefile维持改状态的时间,在此段时间内再起发起相同的请求就回直接利用缓存解析而不用再向根服务器发起解析请求。


0x07 生存时间(TTLs)

既然提到了缓存那就不得不提TTL,TTL能使个别记录强制到期,从而绕过SOA记录中的expiry。如o0O.com已经转移到了一个新的网络主机,为确保服务正常运行,可通过减少www和*在o0O.comZonefile中的TTL来实现切换。具有合适的高TTL和适当的缓存,计算机响应请求的时间以及缓存更新记录的时间都将大大缩短。

解析域名时会最先检查本地的hosts文件中是否存在该域名的映射关系,若有则直接调用该IP地址映射,完成解析。若无,则查找本地DNS解析器缓存中有无该域名的映射关系,若有也直接返回完成解析,若无再遵循上文中所说的进入正常的域名解析流程。


0x08 这次比赛的DNS101

查询DNS的工具有很多,在这里就说一下比赛做题的时候遇到的dig工具吧。

dig是Unix平台自带的可以用来查看特定域名服务器记录工具,我用到的基本用法为:

dig + 域名 + 记录类型//若不指定记录类型则默认为A记录
  • 比赛中直接挖TXT记录就会发现有一条flag-id-[...].flag.src.edu-info.edu.cn记录

    以TXT类型进行dig

  • 而如果以ANY的类型来挖,则会尝试所有类型的记录,可以发现在存在一条NSEC记录解析到n.flag.src.edu-info.edu.cn并且这个域名存在TXT记录RRSIG记录NSEC记录

    以ANY类型进行dig

  • 继续向下挖掘,发现NSEC记录中又出现了新的域名,并且也存在TXT记录RRSIG记录NSEC记录

    对得到的新域名进行dig

现在学了DNS以上相关知识后,可以判断这道题的DNS服务器那边的是在Zonefile中以NSEC记录的方式形成了一个链表将这些域名链接起来,*.flag.src.edu-info.edu.cn型的域名都有个TXT记录提示最终的域名为flag-id-[...].flag.src.edu-info.edu.cn这个形式的。当时手动dig完全不知道原理,就知道输完了之后会得到一个新域名又继续dig,感觉灰常神奇,为什么有这么多挖不完的域名。也理解了那些大网站如何实现域名第一个.前面有那么多种名称。然后最后吐槽一句,python库是真的神奇,当初啥都不知道的时候只有靠切片来维持生活,dig到一半输出格式不同了还切不动,然后参考浙大表哥们WriteUp中的脚本后。。。一万只草泥马奔腾而过

  • 附上我的脚本以及结果:
from tqdm import tqdm
import os
import re
rerr = re.compile('NSEC.+flag.src.edu-info.edu.cn')

def execCmd(cmd):  
    r = os.popen(cmd)  
    text = r.read()  
    r.close()  
    return text  

payload = 'dig any what.is.my.flag.src.edu-info.edu.cn'
for i in range(1,10000):
    a = execCmd(payload)
    rerrrrr = rerr.search(a)
    payload=rerrrrr.group(0).replace('NSEC','').lstrip()
    print payload
    payload='dig any '+payload
失败
  • 附上浙大大表哥们的脚本及结果:
import dns.resolver
url="what.is.my.flag.src.edu-info.edu.cn"
while True:
    emm = dns.resolver.query(url,"NSEC")
    url=list(emm)[0].next.to_text()
    print(url)
成功
  • 然后再将得到的flag-id-ztfrneclyudrfq3e6endq5.zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzz.flag.src.edu-info.edu.cn拿去dig得到了flag
    flag

菜鸡拙见,望路过大佬们指正。


0x09 参考资料

DNS 101
常用域名记录解释
DNS原理及其解析过程
域名配置Zone文件

推荐阅读更多精彩内容

  • DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能...
    一直在努力hard阅读 2,948评论 4 18
  • 1. 概述 在网络环境中一般用户只需要在浏览器中输入url如www.sunny.com就可以到对应服务器获取相应的...
    ghbsunny阅读 1,366评论 0 6
  • 目录: 一些基本概念主机名DNS名称解析DNS 解析的后端存储名称解析总结 大规模域名解析的体系架构DNS 解析需...
    C86guli阅读 8,185评论 3 33
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 103,800评论 13 125
  • 「交错轨迹转眼即去,正如我爱你」 粗心字句,不经意掠过的余光,你无意间出现,恰恰好戳中我心头最软处。恍惚时间在脑海...
    喵记几阅读 61评论 0 0