概述
DNS 协议建立在UDP或TCP 协议之上,属于应用层协议,默认使用 53 端口。该协议的作用是将人类可读的域名转换为机器可读的IP地址。默认情况下通过UDP协议进行通讯,但由于广域网中不适合传输过大的UDP数据包,因此规定当报文长度超过了512字节时会转换为TCP 协议进行数据传输。
DNS记录有一个ttl值(time to live),单位是秒,意思是这个记录最大有效期是多少。操作系统缓存DNS记录的时间会参考ttl值,但是不完全等于ttl值,而浏览器缓存的时间跟ttl值无关。
搭建本地DNS服务器
执行如下命令安装bind9。
# apt-get install bind9
安装后,配置文件位于/etc/bind,进入该目录。涉及dns配置的文件为named.conf、named.conf.local、named.conf.options,首先查看named.conf,这文件里主要加载named.conf.options、 named.conf.local,、named.conf.default-zones 文件中的配置。
第一步配置named.conf.local,如下配置域名huasec.cn 和huasec.com。
`zone "huasec.cn"{ `` type master; `` file "/etc/bind/db.huasec.cn";``};`` ``zone "10.17.172.in-addr.arpa"{` `type master;` `file "/etc/bind/db.172.huasec.com";``};`
然后新建db.huasec.cn和db.172.huasec.com两个文件,内容如下:
`/etc/bind# cat db.huasec.cn``$TTL 604800@ IN SOA huasec.cn. admin.huasec.cn. (` `2023082201 ; Serial` `604800 ; Refresh` `86400 ; Retry` `2419200 ; Expire` `604800 ) ; Negative Cache TTL;``@ IN NS huasec.cn.``huasec.cn IN NS 172.17.10.43``www IN A 172.17.10.43``local IN A 172.17.10.43``host IN A 172.17.10.43``@ IN A 172.17.10.43``@ IN AAAA ::1`` ``/etc/bind# cat db.172.huasec.com``$TTL 604800@ IN SOA huasec.com. root.huasec.com. (` `2023082201;Serial` `604800 ;Refresh` `86400 ;Retry` `2419200 ;Expire` `604800) ;Negative Cache TTL;``@ IN NS huasec.com.``52 IN PTR www.huasec.com.``52 IN PTR nsl.huasec.com.`
最后配置一下named.conf.options文件。
`/etc/bind# cat named.conf.options``options { `` directory "/var/cache/bind"; // If there is a firewall between you and nameservers you want // to talk to, you may need to fix the firewall to allow multiple // ports to talk. See http://www.kb.cert.org/vuls/id/800113 // If your ISP provided one or more IP addresses for stable // nameservers, you probably want to use them as forwarders. // Uncomment the following block, and insert the addresses replacing // the all-0's placeholder. `` forwarders { `` 114.114.114.114; `` }; //======================================================================== // If BIND logs error messages about the root key being expired, // you will need to update your keys. See https://www.isc.org/bind-keys //======================================================================== `` dnssec-validation auto; `` auth-nxdomain no; # conform to RFC1035 `` listen-on-v6 { any; }; `` listen-on port 53 {172.17.10.52;}; `` allow-transfer {any; }; `` allow-query{ any; };``};`
配置完成后,执行“systemctl start bind9”启动bind服务。至此本地dns服务器就搭建完成了。
DNS协议解析
使用wireshark捕获查询www.baidu.com的DNS数据包,先来解析下请求包。
Transaction ID: 0x733c,用来对应DNS查询和响应的唯一ID。
Flags段中标志位Response,用于区分查询报文和响应报文,0 表示查询报文,1 表示响应报文。
Flags段中标志位Opcode代表操作码,0:标准查询;1 表示反向查询;2 表示服务器状态请求;3仅限用于响应,代表服务器状态。
Flags段中标志位Recursion desired值为1,说明该查询是递归查询
Questions: 问题区段中的问题记录数。如果查询失败,不会递增问题记录数,因为无法确定查询结果是否正确。
Answer RRs,回答资源记录数
Authority RRs,权威名称服务器计数
Additional RRs,附加资源记录数
Queries: 记录查询内容和类型。当前的查询域名是www.baidu.com、查询记录为A、地址类型是IN(互联网地址)。常见的 Class(地址类型)有以下三种。CH和HS使用范围很局限,已经很少使用了。
`IN(Internet):适用于 Internet 环境。``CH(Chaosnet):适用于 Chaosnet 环境。``HS(Hesiod):适用于 Hesiod 数据库。`
在响应包中可以看到ID也为0x733c。该ID和请求包是一一对应关系。Flags段中标志位Response值为1,说明该包是响应包,Answer RRS值为3,代表Answers中存在3条记录。当查询www.baidu.com的A记录时候,DNS服务器第一次返回www.baidu.com指向的cname结果www.a.shifen.com,接着返回www.a.shifen.com的两个解析IP 110.242.68.4、110.242.68.5。
DNS资源记录类型
A /AAAA记录
A(Address)记录用于将域名映射到一个 IPv4 地址。AAAA(IPv6 Address)记录用于将域名映射到一个 IPv6 地址。每个A / AAAA 记录包含以下信息:
`域名:需要解析的域名。``TTL(Time To Live):DNS 缓存该 A / AAAA记录的时间。``A / AAAA记录类型(Type):A / AAAA。``IPv4 /IPv6地址:指向的 IPv4/ IPv6 地址。`
CNAME记录
CNAME(Canonical Name)记录用于将一个域名映射到另一个域名。CNAME 记录通常用于将某个域名的别名(Alias)指向其真实的主机名(Canonical Name)。每个条CNAME 记录包含以下信息:
`Name:需要解析的域名。``TTL(Time To Live):DNS 缓存该 CNAME 记录的时间。``CNAME 记录类型(Type):CNAME 记录类型通常为 CNAME 类型。``主机名(Canonical Name):指向别名所对应的真实主机名。`
NS记录
NS(Name Server)用于指定负责管理域名的DNS 服务器。每个NS记录包含以下信息:
`域名:该 NS 记录对应的域名。``TTL(Time To Live):DNS 缓存该 NS 记录的时间。``NS 记录类型(Type):NS 记录类型通常为 NS 类型。``域名服务器(Name Server):负责管理该域名的 DNS 服务器的主机名。`
如下baidu.com有5个ns记录。
SOA记录
SOA(Start of Authority)记录用于指定一个域名的控制和管理权。每个域名至少有一个 SOA 记录。SOA 记录包含以下信息:
`域名(Name):该 SOA 记录所属的域名。``主要名称服务器(MNAME):负责管理该域名的主要名称服务器。``管理员电子邮件地址(RNAME):该域名管理员的电子邮件地址,以 @ 替换为 .(点),并且最后有一个句点(.)``序列号(SERIAL):该域名的版本号,每次进行更改时必须递增。``刷新时间(REFRESH):从主要名称服务器获取该域名数据的间隔时间。``重试时间(RETRY):无法访问主要名称服务器时等待再次尝试的间隔时间。``过期时间(EXPIRE):如果无法更新该域名,则视为该域名已过期的时间。``默认TTL(Time To Live):在没有其他 TTL 指定的情况下,使用该域名中的资源记录的默认生存时间。`
例如查询www.baidu.com的soa记录,返回结果如下。MNAME为ns1.a.shifen.com,负责该域名的授权NS记录,RNAME是baidu_dns_master.baidu.com,Refresh Interval 为 5 秒,Retry Interval 为 5 秒,Expire limit 为 2592000 秒(30 天),Minimum TTL 为 3600 秒(1 小时)。
PTR记录
PTR记录用于反向DNS查询,即从ip反查域名。
PTR(Pointer)记录通常被称为反向解析记录(Reverse DNS Record),用户可以通过 IP 地址查找相应的域名。每个 PTR 记录包含以下信息:
`反向解析记录:需要解析的 IP 地址。``TTL(Time To Live):DNS 缓存该 PTR 记录的时间。``PTR 记录类型(Type):PTR 记录类型通常为 PTR 类型。``域名:指向的域名。`
MX记录
MX记录是邮件交换记录,它指向一个邮件服务器,用于电子邮件系统发邮件时根据收信人的地址后缀来定位邮件服务器。
MX(Mail Exchanger)记录用于指定负责接收域名电子邮件的邮件服务器。每个 MX 记录包含以下信息:
`域名:该 MX 记录对应的域名。``TTL(Time To Live):DNS 缓存该 MX 记录的时间。``优先级(Priority):表示当存在多个 MX 记录时,邮件客户端应该选择哪个 MX 记录来发送邮件。数值越小则优先级越高,优先级相同的 MX 记录会轮流接收邮件。``邮件交换器(Mail Exchanger):负责接收该域名电子邮件的邮件服务器的主机名。`
TXT/SPF记录
TXT 记录用于允许域名所有者向域名系统中添加任意文本信息。通常被用于验证域名所有权、提供安全策略指南和其他类型的元数据。包含以下信息:
`域名:该 TXT 记录对应的域名。``TTL(Time To Live):DNS 缓存该 TXT 记录的时间。``TXT 记录类型(Type):TXT 记录类型通常为 TXT 类型。``TXT 记录值:TXT 记录的值是一个包含文本信息的字符串,可以是任何字符或文本。最长的单个 TXT 记录值为255个字节。`
SPF(Sender Policy Framework)记录用于验证其它邮件服务器是否被授权发送特定域名的电子邮件。内容写在DNS的TXT记录里,可以用来防止别人伪造你的邮件地址进行发信。包含以下信息:
`域名:该 SPF 记录对应的域名。``TTL(Time To Live):DNS 缓存该 SPF 记录的时间。``SPF 记录类型(Type):SPF 记录类型通常为 TXT 类型。``SPF 记录值:SPF 记录的值定义哪些 IP 地址或域名可以发送该域名的电子邮件。SPF 记录可以包含多个条目,每个条目之间用空格分隔,例如"v=spf1 include:spf1.baidu.com include:spf2.baidu.com include:spf3.baidu.com include:spf4.baidu.com mx ptr -all"`
应用场景
DNS隧道
项目地址:https://github.com/yarrick/iodine.git
使用方法:
# git clone https://github.com/yarrick/iodine.git# cd iodine # make
执行完后,会在bin目录下生成iodine和iodined两个文件。iodined在服务器端运行,iodine在客户端运行。
(1)执行以下命令启动服务端
`# ./iodined -P 123456 -f -DD 192.168.0.1 huasec.cn`
-P:指定密码
-c:禁止检查所有传入请求的客户端IP地址
-f:在前台运行
-D:指定调试级别。-DD指第二级,D的数量随等级增加
然后服务器端会生成一块dns0的虚拟网卡
(2)执行如下命令连接服务端(需要root权限),如图连接成功
`# ./iodine -f -P 123456 huasec.cn`
客户端也会虚拟出一块网卡。
这时候流量中会产生以"huasec.cn"结尾的随机域名
iodine在连接服务端的时候可以指定一些参数,比如-T 指定dns类型 -O 指定数据编码格式 -r 强制在任何情况下使用DNS隧道,通过配置可以修改流量特征。
下面就分析下使用iodine过程的几个场景产生的pcap。
一、默认参数启动iodine
前三个包是客户端连接认证,请求类型是NULL,如果认证成功,回包中Data的值包含客户端IP、MTU、服务端IP三个值。
第四个包是会话连接包,后续通过dns协议继续通信。连接成功后在服务器端执行curl和ssh命令,由于没有指定-r 参数,通信流量是非标准的DNS数据包。
正常的情况下DNS数据包中问题计数、回答资源记录数、权威名称服务器计数、附加资源记录数这四个字节的值非0即1。默认配置产生的DNS数据包这四个字节的值偏大。
另外Flags中的OpCode标志位值为Unknown。
默认情况下添加-r参数,则请求类型是NULL,避免产生非标准DNS流量包。
二、添加参数启动iodine
接下来指定传输的类型为TXT ,
# ./iodine -f -P 123456 -r -T TXT huasec.cn
首先是域名侧,存在长短字符和不可读字符。
另外由于隧道工具需要规避DNS缓存机制,所以TTL的值为0
当在服务端执行curl 、ssh命令后,流量的内容是加密的。
三、不同资源记录的错误密码返回分析
使用-T参数指定资源类型,当输入错误的密码后,会产生两条流量,一条握手一条认证,从流量侧无法直观找到流量特征。
因此尝试从代码侧入手看看,当使用错误密码的时候,命令行会返回"bad password"关键字。
通过该特征定位到iodined.c 901-903行,这一块的函数名称是handle_null_request,处理资源类型为NULL的函数。
从代码侧可以看到当资源记录为NULL/UNKNOWN的时候,密码错误会返回字符"LANK"。查看流量包中的Data字段亦是如此。