狠狠撸

狠狠撸Share a Scribd company logo
DNS - DNS 协议及应用介绍
              Jeff.Rao

     chenlin.rao@renren-inc.com

              人人网

           May 25, 2012
什么是 DNS

? 网络的原始时代
? We are the cowboys over the WWW(wild wild west)~ BUT
? 采用 IP 地址访问——真滴记不住啊有木有 ??!!
? 在 NIC 的 hosts.txt 里记录主机名与 IP 地址的映射关系
? NIC 互联网信息中心,不是网络适配器 ~~
? 几天 NIC 更新一次,大家去下载—— 12306 抢票的感觉有木有 !!
? "We will encourage you to develop the three great virtues of a
  programmer: laziness, impatience, and hubris." -- LarryWall
? 大家都想要自己独立的够酷的名字空间
? DNS(Domain Name System) 诞生了
DNS 设计
? 能够指明网络地址、路由等信息
? 分布式存储 ( 数据正确性,失败时使用缓存
  数据 )
? 数据格式支持多协议传输
  (FTP/EMAIL/SSH/RSYNC/SQL...)
? 支持多协议访问 (TCP/UDP)
DNS 组成
?   域名空间和资源记录
?   域名空间是一个树状结构
?   资源记录是和名字相关的数据
?   名字服务器
?   服务器端程序,用来保留域名空间和资源记录
?   一般只保存域名空间的一个子集,作为这个子集的权威。
?   一个子集内的信息又算一个区 (zone)
?   其他信息通过其他名字服务器查询
?   解析器
?   客户端程序,可以访问至少一个名字服务器,接收返回的
    结果或者转向其他名字服务器查询
域名空间

?   树状结构的每个结点都对应一个资源集 ( 可能为空 )
?   每个结点的标记为 0-63 字节
?   0 字节标记为根记录 (.)
?   标记对大小写不敏感
?   结点的域名由从结点到根的标记连接组成
?   每个域名的结点最多不超过 127 个
?   一般实现中域名长度不超过 255 字节
DNS 查询过程
? 递归查询
? 要点:“请对方辩友正面回答!”
? 客户端请求必须得到一个 yes or no 的响应——
  NXDOMAIN 或 NOERROR
? 一般情况下,电脑客户端都会使用递归查询
? 迭代查询
? 要点:“今人不见古时月,今月曾经照古人”
? 服务器端 ( 今人 ) 返回一个可能知道该域名 ( 古
  月 ) 解析结果的名字服务器 ( 古人 ) ,然后客户端
  重新去那台查询
DNS 查询过程
?   举例:
?   电脑发出“可递归” (RFC1034 中定义的 "recursive") 查询的请求到自己配置的 LDNS
    服务器上
?   LDNS 检查自己的权威认证区——一般是没有的
?   LDNS 检查自己的非权威缓存信息
?   有,返回结果,完毕
?   没有,向其他 NS 查询
?   配置了 forwarder 的话,只向 forwarder 的 NS 发请求,这个请求依然是“可递归”
?   否则向根 DNS 发出“迭代” (RFC1034 中的大多数情况下仅仅把它叫 "non-
    recursive" ,偶尔叫 iterative) 请求
?   全世界只有 13 个根 DNS ,所以根是不会响应递归请求的
?   根 DNS 返回顶级域 (.com..net..org. 等等 )DNS 的 IP 给 LDNS
?   LDNS 向顶级域权威 DNS 发出“迭代”请求
?   顶级域权威 DNS 返回对应一级域的权威 DNS 的 IP
?   LDNS 向一级域权威 DNS 发出“迭代”请求
?   一级域权威 DNS 查找到对应主机名的资源记录,返回结果
?   LDNS 将结果返回给电脑,结束本次“递归”查询
DNS 查询过程
DNS 查询结构体


? 前面讲的是 RFC1034 《 DOMAIN NAMES -
  DOMAIN CONCEPTS AND FACILITIES 》里关
  于 DNS 的概念阐述。

? 然后说一下 RFC1035 《 DOMAIN NAMES -
  IMPLEMENTATION AND SPECIFICATION 》里
  对于 DNS 的实现阐述。

? ftp://ftp.rfc-editor.org/in-notes/rfc1035.txt
UDP 报文的结构
? 一、报头
?                        1 1 1 1 1 1
?     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |              ID                |
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |             QDCOUNT                  |
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |             ANCOUNT                  |
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |             NSCOUNT                  |
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |             ARCOUNT                  |
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   这张图大家都用,汗 ~ 顶上一个数字表示这列是 1bit ,后面 10-15bit 分成两行写了,
    ……
UDP 报文的结构
?   ID :占 2bytes ,客户端生成,服务器端返回时靠这个对应客户端的请求
?   QR(Question Response) :占 1bit , 0 代表查询, 1 代表响应
?   Opcode :占 4bits , 0 代表标准查询, 1 代表反向查询, 2 代表服务器状态
    查询, 3-15 没啥用,过去还有个完全查询已经废弃了
?   AA(Authoritative Answer) :占 1bit , 1 代表权威响应, 0 代表非权威响应
?   TC(TrunCation) :占 1bit ,是否截断报文—— UDP 一个报文只有 512bytes
?   RD(Recursion Desired) :占 1bit ,客户端生成,服务器端沿袭, 1 代表启用
    递归查询
?   RA(Recursion Available) :占 1bit ,服务器端生成, 1 代表服务器支持递归
    查询
?   这里我们看到实际没有对于迭代的设置,所以 RFC 中更多的把迭代叫成非递
    归
?   Z :占 3bits ,保留字段,设 0
?   RCODE :占 4bits ,服务器端生成的响应返回码。 0: 正常, 1: 格式错
    误, 2:DNS 错误, 3: 域名不存在, 4: 查询类型不支持, 5: 拒绝查询
?   QDCOUNT :占 2bytes ,查询记录的个数
?   ANCOUNT :占 2bytes ,回复记录的个数
?   NSCOUNT :占 2bytes ,权威记录的个数
?   ARCOUNT :占 2bytes ,额外记录的个数
UDP 报文的结构
? 二、查询
?                        1 1 1 1 1 1
?     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |                               |
?   /              QNAME                   /
?   /                               /
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |              QTYPE                 |
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |              QCLASS                  |
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
UDP 报文的结构
? QNAME :一般就是查询的域名了。被编码成 labels 序列
  ,每个 label 包括: 1byte 表示后续字符串长度 + 字符串。
  最后一个 label 以 0 长度 + 空字符串表示域名结束
?     QNAME 可能是奇数个 btyes ,不需要填充完整
?        使用 label 的原因是为了压缩报文,因为可能
  一个域名查询多个 TYPE ,所以后面的重复 label 可以用
  指针代替
?          在目前的 DNS 实现中,对一个报文发送多个
  查询的情况,要求 QNAME 必须一致,否则递归查询碰上
  两个不同 QNAME 权威 NS 不一致的情况就完蛋鸟 ~
? QTYPE :查询类型
? QCLASS :查询协议
UDP 报文的结构
? 三、响应
?                        1 1 1 1 1 1
?     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |                               |
?   /                               /
?   /              NAME                   /
?   |                               |
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |              TYPE                 |
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |              CLASS                  |
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |              TTL                |
?   |                               |
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
?   |            RDLENGTH                    |
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
?   /              RDATA                   /
?   /                               /
?   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
UDP 报文的结构
? RDLENGTH :占 2bytes ,表示 RDATA 的长度
? RDATA :响应记录,长度与格式不定。比如最常见的话
  ,如果 TYPE==A , CLASS==IN ,那么 RDATA 就是占
  位 4bytes 的 ARPA 网络地址
? http://www.iana.org/assignments/dns-parameters
? 四、权威
? 五、附加
? 这两个格式和响应一样,不赘述

? 对于附加 (Additional) 资源记录,在 EDNS 和 DNSSEC
  中会用来存放 OPT 记录数据,分别用来支持超过 512 字
  节的 UDF 包和确认是否支持 DNSSEC 。
资源记录 (Resource Record)
? 常见 RR(TYPE) :
? SOA(Start Of Authority)
?   放在 zone 的最开始,有且仅有一个。用来描述负责这个 zone 的名字服务器,版本信
    息等。举例 BIND 配置说明 :

?   @   IN   SOA     renren.com. root.renren.com. (
?                  2012051401      ; Serial
?                  3600        ; Refresh
?                  300        ; Retry
?                  3600000       ; Expire
?                  3600 )      ; Minimum
?   @ 代表整个 zone
?   renren.com. 代表本机主机名
?   root.renren.com. 代表本机管理员邮箱 root@renren.com
?   serial 代表 zone 版本,每次变动都应该自增,方便从服务器校验同步
?   refresh 代表从服务器同步间隔——现在一般采用主服务器 notify 的方式
?   expire 废弃时间——超过这个时间从依然连不上主,就自杀……
?   minimum 代表 zone 内记录的默认 TTL ,非权威 DNS 做缓存时不能超过这个时间
资源记录 (Resource Record)
? 常见记录 RR(TYPE) :
? A(Address)
? 主机名对应的 IPv4 地址
? AAAA 代表的就是 IPv6 地址,因为 IPv6 是 128 位, 4 倍于 IPv4 的
  32 位,所以写 4 个 A
? CNAME(Canonical NAME)
?   别名
?   DNAME ,在 RFC2672 中定义, bind9 里已经实现,类似 CNAME 。但 CNAME 之后
    对应的是具体主机,而 DNAME 用处是别名掉整个域
? TXT
?   返回文本信息,可能用来描述这个记录
?   但其实有 HINFO 专门做主机信息描述资源记录
? MX(Mail Exchanger)
?   邮件服务器主机,比 A 记录多一个优先级定义,数值越低越优先
资源记录 (Resource Record)
? MX(Mail Exchanger)
?   邮件服务器主机,比 A 记录多一个优先级定义,数值越低越优先
? NS(Name Server)
?   本 zone 的权威名字服务器
? PTR(Pointer Record)
?   主要用来实现反向解析
?   小提示:互联网上, 60% 的 DNS 查询是反向解析,正向只有 40%
?          邮件传输等协议都依赖反解, nslookup 默认也有反解,可见附 1 脚本
    测试
? TSIG(Transaction Signature)
?   签名加密动态更新记录
资源记录 (Resource Record)
?   协议类 RR(class):
?   IN(internet)
?   CS(csnet)
?   HS(hesiod)
?   CH(chaos)
?   虽然都没见过,不过还是要修正前面 A 记
    录的说明, 32 位 IP 地址只是 IN 情况下
    的;如果是 CH ,应该是 16 位八进制
    Chaos 地址域名
资源记录 (Resource Record)
? 查询类 RR(QTYPE):
? AXFR(Authoritative Zone Transfer)
?      请求传输整个 zone 的资源
? IXFR(Increamental Zone Transfer)
?     AXFR 的改进版,根据 serial 数值传输变更了的资源
? MAILA
?      废弃了,现在都是用 MX
? *
?      请求所有记录
? http://en.wikipedia.org/wiki/PTR_record
DNS 应用
? DNS 负载均衡
? 因为 A 记录可以返回多个,所以在 LVS 没有诞生的中古时代,人们
  是使用 DNS 做负载均衡的

? 问题:没有健康检查,没有权重设置,没有哈希分布,没有……

? 动态 DNS
? 上面这些其实都不是问题。通过自定义函数返回不同的 IP 即
  可。 DNS 做负载均衡真正的问题是:

? TTL 时间内没办法改变客户端访问路由!
? 所以最后动态 DNS 的应用场合就变成了 CDN 系统全局调度器。
CDN 系统内的 Dynamtic DNS
?   要点:根据 ip 地址段对应的 view ,返回不同的 IP 地址
?   常见应用: Bind9 、 TinyDNS 、 WINMyDNS
?   运维难点:收集足够准确的 IP 段信息
?          F5 的 GTM 首选算法是 RTT ,但是我们注
    意到: DNS 首选协议是 UDP 的,只有在 package 大于
    512 字节和 zone transfer 的时候采用 TCP 。 UDP 木有
    RTT 的概念 ~

? 所以我们就知道了 GTM 是被动 RTT 的了。
? GTM 工作原理: NS 返回一台 GTM 的 ip 给
  LDNS , LDNS 请求到该 ip ; GTM 在就近路由表中查
  询,没有的话,联系全网其他 GTM 共同对 LDNS 发起
  TCP 请求计算 RTT ,汇总 RTT 结果更新路由表返回最近
  结果。
CDN 系统内的 Dynamtic DNS
?   小设想:一般情况下,我们都说 DDNS 上收到的 localDNS 的 IP ,真的么?
?          上面的协议实现部分,我们其实并没有看到 DNS 报文里有哪存放 ip 的,也
    就是说: ip 还是 TCP/IP 层的事情。
?           实际根据的是迭代查询的原理!
?           那么我们如果在上海搭建一个 'recursion yes;' 的 bind ,然后在北京的 dns
    上配置 forwarder 到上海,最终权威 NS 建连的 IP 是上海!

?   好吧,正过来想一想:如果每个客户端上都自带一个支持迭代查询的 dnsproxy ,那么
    ip 收集也就方便了。
?         小提示:对于动态返回 ip ,可见附 2 脚本
偏门武器谱
? 一本正经说这么多,最后来几个有趣的 DNS 应用:

?   反垃圾邮件白名单
?   dig TXT 21cn.com
?   天天背单词之英汉字典
?   echo "function j() { dig $1.jianbing.org txt +short | perl
    -pe's/(d{1,3})/chr $1/eg; s/"//g' }" >> ~/.bashrc
?   source !$
?   j apple
?   翻墙
?   http://code.kryo.se/iodine/
?   http://blog.codingnow.com/2011/06/dns_tunnel.html
?   #!/human/mouth
?   use active;
?   use ME;
?   use Topic qw/DNS/;

?   my $topic = Topic::DNS->new( slide => 'Spork');
?   my $me = ME->bind([ qw/mouth ears/ ]);
?   while( $me->say($topic) or my $ears = $me->listen() ) {
?      kill STOP => $me->say($topic);
?      my $question = <$ears>;
?      say " 这个问题问得好! ";
?      say $ears $topic->answer($question);
?      kill CONT => $me->say($topic);
?   };
?   say " 真的木问题鸟 ";
?   $topic->close();
?   __END__
附1
?   use 5.014;
?   use Net::DNS::Nameserver;
?   my $ns = new Net::DNS::Nameserver( LocalPort => 5353,
?                           ReplyHandler => &reply_handler,
?                           Verbose     => 1
?                         );
?   $ns->main_loop;
?   sub reply_handler {
?     my ($qname, $qclass, $qtype, $peerhost, $query, $conn) = @_;
?     my ($rcode, @ans, @auth, @add);
?     $query->print;
?     if ($qtype eq "A" && $qname =~ m/foobar.com$/ ) {
?           my ($ttl, $rdata) = (3600, "10.1.2.3");
?           my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
?           push @ans, $rr;
?           $rcode = "NOERROR";
?     }else{
?           $rcode = "NXDOMAIN";
?     }
?     return ($rcode, @ans, @auth, @add, { aa => 1 });
?   }
附2
?   use 5.014;
?   use Net::IP::Match::Regexp qw/create_iprange_regexp match_ip/;
?   use Stanford::DNS;
?   use Stanford::DNSserver;
?   my $hostmaster = 'admin.renren-inc.com';
?   my $hostname = '127.0.0.1';
?   my $soa        = rr_SOA($hostname, $hostmaster, time(), 3600, 1800, 86400, 0);
?   my $ns         = Stanford::DNSserver->new( listen_on => [ $hostname ],
?                                  debug => 1,
?                       logfunc => sub { say },
?                       daemon => 'no',);
?   my $host       = 'chenlin.rao.som.renren-inc.com';
?   my $regexp = create_iprange_regexp({ '127.0.0.1/32' => 'localhost', '10.0.0.0/8 =>
    'ethernet',});
?   my $iplist = { $host => { ethernet => '10.10.10.10', localhost => '12.7.0.10'}, };
?   $ns->add_static( $host, T_SOA, $soa );
?   $ns->add_static( $host, T_NS, rr_NS($hostmaster) );
?   $ns->add_dynamic( $host => &dyn_req );
?   $ns->answer_queries();
附2续
?   sub dyn_req {
?      my ($domain,$residual,$qtype,$qclass,$dm,$from) = @_;
?      my $ttl = 3600;
?      if ( $qtype == T_A ) {
?          my $ip = dyn_match($domain, $from);
?          $dm->{'answer'} .= dns_answer(QPTR, T_A, C_IN, $ttl, rr_A($ip));
?          $dm->{'ancount'} += 1;
?          return 1;
?      };
?      if ( $qtype == T_TXT ) {
?            if ( $domain =~ m/^(w+.w+).som.(renren-inc.com)/ ) {
?                $dm->{'answer'} .= dns_answer(QPTR, T_TXT, C_IN, $ttl, rr_TXT("Email
    address: $1@$2"));
?              $dm->{'ancount'} += 1;
?          };
?      };
?      if ( ! $dm->{ancount} ) {
?          $dm->{rcode} = NXDOMAIN;
?      };
?   };
附 2 再续
?   sub dyn_match {
?      my ( $domain, $from ) = @_;
?      my $area = match_ip($from, $regexp);
?      return ($1<<24)|($2<<16)|($3<<8)|$4 if $iplist->{"$host"}->{"$area"} =~ m/
    (d{1,3}).(d{1,3}).(d{1,3}).(d{1,3})/;
?   };

More Related Content

顿狈厂协议与应用介绍

  • 1. DNS - DNS 协议及应用介绍 Jeff.Rao chenlin.rao@renren-inc.com 人人网 May 25, 2012
  • 2. 什么是 DNS ? 网络的原始时代 ? We are the cowboys over the WWW(wild wild west)~ BUT ? 采用 IP 地址访问——真滴记不住啊有木有 ??!! ? 在 NIC 的 hosts.txt 里记录主机名与 IP 地址的映射关系 ? NIC 互联网信息中心,不是网络适配器 ~~ ? 几天 NIC 更新一次,大家去下载—— 12306 抢票的感觉有木有 !! ? "We will encourage you to develop the three great virtues of a programmer: laziness, impatience, and hubris." -- LarryWall ? 大家都想要自己独立的够酷的名字空间 ? DNS(Domain Name System) 诞生了
  • 3. DNS 设计 ? 能够指明网络地址、路由等信息 ? 分布式存储 ( 数据正确性,失败时使用缓存 数据 ) ? 数据格式支持多协议传输 (FTP/EMAIL/SSH/RSYNC/SQL...) ? 支持多协议访问 (TCP/UDP)
  • 4. DNS 组成 ? 域名空间和资源记录 ? 域名空间是一个树状结构 ? 资源记录是和名字相关的数据 ? 名字服务器 ? 服务器端程序,用来保留域名空间和资源记录 ? 一般只保存域名空间的一个子集,作为这个子集的权威。 ? 一个子集内的信息又算一个区 (zone) ? 其他信息通过其他名字服务器查询 ? 解析器 ? 客户端程序,可以访问至少一个名字服务器,接收返回的 结果或者转向其他名字服务器查询
  • 5. 域名空间 ? 树状结构的每个结点都对应一个资源集 ( 可能为空 ) ? 每个结点的标记为 0-63 字节 ? 0 字节标记为根记录 (.) ? 标记对大小写不敏感 ? 结点的域名由从结点到根的标记连接组成 ? 每个域名的结点最多不超过 127 个 ? 一般实现中域名长度不超过 255 字节
  • 6. DNS 查询过程 ? 递归查询 ? 要点:“请对方辩友正面回答!” ? 客户端请求必须得到一个 yes or no 的响应—— NXDOMAIN 或 NOERROR ? 一般情况下,电脑客户端都会使用递归查询 ? 迭代查询 ? 要点:“今人不见古时月,今月曾经照古人” ? 服务器端 ( 今人 ) 返回一个可能知道该域名 ( 古 月 ) 解析结果的名字服务器 ( 古人 ) ,然后客户端 重新去那台查询
  • 7. DNS 查询过程 ? 举例: ? 电脑发出“可递归” (RFC1034 中定义的 "recursive") 查询的请求到自己配置的 LDNS 服务器上 ? LDNS 检查自己的权威认证区——一般是没有的 ? LDNS 检查自己的非权威缓存信息 ? 有,返回结果,完毕 ? 没有,向其他 NS 查询 ? 配置了 forwarder 的话,只向 forwarder 的 NS 发请求,这个请求依然是“可递归” ? 否则向根 DNS 发出“迭代” (RFC1034 中的大多数情况下仅仅把它叫 "non- recursive" ,偶尔叫 iterative) 请求 ? 全世界只有 13 个根 DNS ,所以根是不会响应递归请求的 ? 根 DNS 返回顶级域 (.com..net..org. 等等 )DNS 的 IP 给 LDNS ? LDNS 向顶级域权威 DNS 发出“迭代”请求 ? 顶级域权威 DNS 返回对应一级域的权威 DNS 的 IP ? LDNS 向一级域权威 DNS 发出“迭代”请求 ? 一级域权威 DNS 查找到对应主机名的资源记录,返回结果 ? LDNS 将结果返回给电脑,结束本次“递归”查询
  • 9. DNS 查询结构体 ? 前面讲的是 RFC1034 《 DOMAIN NAMES - DOMAIN CONCEPTS AND FACILITIES 》里关 于 DNS 的概念阐述。 ? 然后说一下 RFC1035 《 DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION 》里 对于 DNS 的实现阐述。 ? ftp://ftp.rfc-editor.org/in-notes/rfc1035.txt
  • 10. UDP 报文的结构 ? 一、报头 ? 1 1 1 1 1 1 ? 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? | ID | ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? |QR| Opcode |AA|TC|RD|RA| Z | RCODE | ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? | QDCOUNT | ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? | ANCOUNT | ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? | NSCOUNT | ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? | ARCOUNT | ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? 这张图大家都用,汗 ~ 顶上一个数字表示这列是 1bit ,后面 10-15bit 分成两行写了, ……
  • 11. UDP 报文的结构 ? ID :占 2bytes ,客户端生成,服务器端返回时靠这个对应客户端的请求 ? QR(Question Response) :占 1bit , 0 代表查询, 1 代表响应 ? Opcode :占 4bits , 0 代表标准查询, 1 代表反向查询, 2 代表服务器状态 查询, 3-15 没啥用,过去还有个完全查询已经废弃了 ? AA(Authoritative Answer) :占 1bit , 1 代表权威响应, 0 代表非权威响应 ? TC(TrunCation) :占 1bit ,是否截断报文—— UDP 一个报文只有 512bytes ? RD(Recursion Desired) :占 1bit ,客户端生成,服务器端沿袭, 1 代表启用 递归查询 ? RA(Recursion Available) :占 1bit ,服务器端生成, 1 代表服务器支持递归 查询 ? 这里我们看到实际没有对于迭代的设置,所以 RFC 中更多的把迭代叫成非递 归 ? Z :占 3bits ,保留字段,设 0 ? RCODE :占 4bits ,服务器端生成的响应返回码。 0: 正常, 1: 格式错 误, 2:DNS 错误, 3: 域名不存在, 4: 查询类型不支持, 5: 拒绝查询 ? QDCOUNT :占 2bytes ,查询记录的个数 ? ANCOUNT :占 2bytes ,回复记录的个数 ? NSCOUNT :占 2bytes ,权威记录的个数 ? ARCOUNT :占 2bytes ,额外记录的个数
  • 12. UDP 报文的结构 ? 二、查询 ? 1 1 1 1 1 1 ? 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? | | ? / QNAME / ? / / ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? | QTYPE | ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? | QCLASS | ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  • 13. UDP 报文的结构 ? QNAME :一般就是查询的域名了。被编码成 labels 序列 ,每个 label 包括: 1byte 表示后续字符串长度 + 字符串。 最后一个 label 以 0 长度 + 空字符串表示域名结束 ? QNAME 可能是奇数个 btyes ,不需要填充完整 ? 使用 label 的原因是为了压缩报文,因为可能 一个域名查询多个 TYPE ,所以后面的重复 label 可以用 指针代替 ? 在目前的 DNS 实现中,对一个报文发送多个 查询的情况,要求 QNAME 必须一致,否则递归查询碰上 两个不同 QNAME 权威 NS 不一致的情况就完蛋鸟 ~ ? QTYPE :查询类型 ? QCLASS :查询协议
  • 14. UDP 报文的结构 ? 三、响应 ? 1 1 1 1 1 1 ? 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? | | ? / / ? / NAME / ? | | ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? | TYPE | ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? | CLASS | ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? | TTL | ? | | ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ? | RDLENGTH | ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| ? / RDATA / ? / / ? +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  • 15. UDP 报文的结构 ? RDLENGTH :占 2bytes ,表示 RDATA 的长度 ? RDATA :响应记录,长度与格式不定。比如最常见的话 ,如果 TYPE==A , CLASS==IN ,那么 RDATA 就是占 位 4bytes 的 ARPA 网络地址 ? http://www.iana.org/assignments/dns-parameters ? 四、权威 ? 五、附加 ? 这两个格式和响应一样,不赘述 ? 对于附加 (Additional) 资源记录,在 EDNS 和 DNSSEC 中会用来存放 OPT 记录数据,分别用来支持超过 512 字 节的 UDF 包和确认是否支持 DNSSEC 。
  • 16. 资源记录 (Resource Record) ? 常见 RR(TYPE) : ? SOA(Start Of Authority) ? 放在 zone 的最开始,有且仅有一个。用来描述负责这个 zone 的名字服务器,版本信 息等。举例 BIND 配置说明 : ? @ IN SOA renren.com. root.renren.com. ( ? 2012051401 ; Serial ? 3600 ; Refresh ? 300 ; Retry ? 3600000 ; Expire ? 3600 ) ; Minimum ? @ 代表整个 zone ? renren.com. 代表本机主机名 ? root.renren.com. 代表本机管理员邮箱 root@renren.com ? serial 代表 zone 版本,每次变动都应该自增,方便从服务器校验同步 ? refresh 代表从服务器同步间隔——现在一般采用主服务器 notify 的方式 ? expire 废弃时间——超过这个时间从依然连不上主,就自杀…… ? minimum 代表 zone 内记录的默认 TTL ,非权威 DNS 做缓存时不能超过这个时间
  • 17. 资源记录 (Resource Record) ? 常见记录 RR(TYPE) : ? A(Address) ? 主机名对应的 IPv4 地址 ? AAAA 代表的就是 IPv6 地址,因为 IPv6 是 128 位, 4 倍于 IPv4 的 32 位,所以写 4 个 A ? CNAME(Canonical NAME) ? 别名 ? DNAME ,在 RFC2672 中定义, bind9 里已经实现,类似 CNAME 。但 CNAME 之后 对应的是具体主机,而 DNAME 用处是别名掉整个域 ? TXT ? 返回文本信息,可能用来描述这个记录 ? 但其实有 HINFO 专门做主机信息描述资源记录 ? MX(Mail Exchanger) ? 邮件服务器主机,比 A 记录多一个优先级定义,数值越低越优先
  • 18. 资源记录 (Resource Record) ? MX(Mail Exchanger) ? 邮件服务器主机,比 A 记录多一个优先级定义,数值越低越优先 ? NS(Name Server) ? 本 zone 的权威名字服务器 ? PTR(Pointer Record) ? 主要用来实现反向解析 ? 小提示:互联网上, 60% 的 DNS 查询是反向解析,正向只有 40% ? 邮件传输等协议都依赖反解, nslookup 默认也有反解,可见附 1 脚本 测试 ? TSIG(Transaction Signature) ? 签名加密动态更新记录
  • 19. 资源记录 (Resource Record) ? 协议类 RR(class): ? IN(internet) ? CS(csnet) ? HS(hesiod) ? CH(chaos) ? 虽然都没见过,不过还是要修正前面 A 记 录的说明, 32 位 IP 地址只是 IN 情况下 的;如果是 CH ,应该是 16 位八进制 Chaos 地址域名
  • 20. 资源记录 (Resource Record) ? 查询类 RR(QTYPE): ? AXFR(Authoritative Zone Transfer) ? 请求传输整个 zone 的资源 ? IXFR(Increamental Zone Transfer) ? AXFR 的改进版,根据 serial 数值传输变更了的资源 ? MAILA ? 废弃了,现在都是用 MX ? * ? 请求所有记录 ? http://en.wikipedia.org/wiki/PTR_record
  • 21. DNS 应用 ? DNS 负载均衡 ? 因为 A 记录可以返回多个,所以在 LVS 没有诞生的中古时代,人们 是使用 DNS 做负载均衡的 ? 问题:没有健康检查,没有权重设置,没有哈希分布,没有…… ? 动态 DNS ? 上面这些其实都不是问题。通过自定义函数返回不同的 IP 即 可。 DNS 做负载均衡真正的问题是: ? TTL 时间内没办法改变客户端访问路由! ? 所以最后动态 DNS 的应用场合就变成了 CDN 系统全局调度器。
  • 22. CDN 系统内的 Dynamtic DNS ? 要点:根据 ip 地址段对应的 view ,返回不同的 IP 地址 ? 常见应用: Bind9 、 TinyDNS 、 WINMyDNS ? 运维难点:收集足够准确的 IP 段信息 ?        F5 的 GTM 首选算法是 RTT ,但是我们注 意到: DNS 首选协议是 UDP 的,只有在 package 大于 512 字节和 zone transfer 的时候采用 TCP 。 UDP 木有 RTT 的概念 ~ ? 所以我们就知道了 GTM 是被动 RTT 的了。 ? GTM 工作原理: NS 返回一台 GTM 的 ip 给 LDNS , LDNS 请求到该 ip ; GTM 在就近路由表中查 询,没有的话,联系全网其他 GTM 共同对 LDNS 发起 TCP 请求计算 RTT ,汇总 RTT 结果更新路由表返回最近 结果。
  • 23. CDN 系统内的 Dynamtic DNS ? 小设想:一般情况下,我们都说 DDNS 上收到的 localDNS 的 IP ,真的么? ? 上面的协议实现部分,我们其实并没有看到 DNS 报文里有哪存放 ip 的,也 就是说: ip 还是 TCP/IP 层的事情。 ? 实际根据的是迭代查询的原理! ? 那么我们如果在上海搭建一个 'recursion yes;' 的 bind ,然后在北京的 dns 上配置 forwarder 到上海,最终权威 NS 建连的 IP 是上海! ? 好吧,正过来想一想:如果每个客户端上都自带一个支持迭代查询的 dnsproxy ,那么 ip 收集也就方便了。 ? 小提示:对于动态返回 ip ,可见附 2 脚本
  • 24. 偏门武器谱 ? 一本正经说这么多,最后来几个有趣的 DNS 应用: ? 反垃圾邮件白名单 ? dig TXT 21cn.com ? 天天背单词之英汉字典 ? echo "function j() { dig $1.jianbing.org txt +short | perl -pe's/(d{1,3})/chr $1/eg; s/"//g' }" >> ~/.bashrc ? source !$ ? j apple ? 翻墙 ? http://code.kryo.se/iodine/ ? http://blog.codingnow.com/2011/06/dns_tunnel.html
  • 25. ? #!/human/mouth ? use active; ? use ME; ? use Topic qw/DNS/; ? my $topic = Topic::DNS->new( slide => 'Spork'); ? my $me = ME->bind([ qw/mouth ears/ ]); ? while( $me->say($topic) or my $ears = $me->listen() ) { ? kill STOP => $me->say($topic); ? my $question = <$ears>; ? say " 这个问题问得好! "; ? say $ears $topic->answer($question); ? kill CONT => $me->say($topic); ? }; ? say " 真的木问题鸟 "; ? $topic->close(); ? __END__
  • 26. 附1 ? use 5.014; ? use Net::DNS::Nameserver; ? my $ns = new Net::DNS::Nameserver( LocalPort => 5353, ? ReplyHandler => &reply_handler, ? Verbose => 1 ? ); ? $ns->main_loop; ? sub reply_handler { ? my ($qname, $qclass, $qtype, $peerhost, $query, $conn) = @_; ? my ($rcode, @ans, @auth, @add); ? $query->print; ? if ($qtype eq "A" && $qname =~ m/foobar.com$/ ) { ? my ($ttl, $rdata) = (3600, "10.1.2.3"); ? my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); ? push @ans, $rr; ? $rcode = "NOERROR"; ? }else{ ? $rcode = "NXDOMAIN"; ? } ? return ($rcode, @ans, @auth, @add, { aa => 1 }); ? }
  • 27. 附2 ? use 5.014; ? use Net::IP::Match::Regexp qw/create_iprange_regexp match_ip/; ? use Stanford::DNS; ? use Stanford::DNSserver; ? my $hostmaster = 'admin.renren-inc.com'; ? my $hostname = '127.0.0.1'; ? my $soa = rr_SOA($hostname, $hostmaster, time(), 3600, 1800, 86400, 0); ? my $ns = Stanford::DNSserver->new( listen_on => [ $hostname ], ? debug => 1, ? logfunc => sub { say }, ? daemon => 'no',); ? my $host = 'chenlin.rao.som.renren-inc.com'; ? my $regexp = create_iprange_regexp({ '127.0.0.1/32' => 'localhost', '10.0.0.0/8 => 'ethernet',}); ? my $iplist = { $host => { ethernet => '10.10.10.10', localhost => '12.7.0.10'}, }; ? $ns->add_static( $host, T_SOA, $soa ); ? $ns->add_static( $host, T_NS, rr_NS($hostmaster) ); ? $ns->add_dynamic( $host => &dyn_req ); ? $ns->answer_queries();
  • 28. 附2续 ? sub dyn_req { ? my ($domain,$residual,$qtype,$qclass,$dm,$from) = @_; ? my $ttl = 3600; ? if ( $qtype == T_A ) { ? my $ip = dyn_match($domain, $from); ? $dm->{'answer'} .= dns_answer(QPTR, T_A, C_IN, $ttl, rr_A($ip)); ? $dm->{'ancount'} += 1; ? return 1; ? }; ? if ( $qtype == T_TXT ) { ? if ( $domain =~ m/^(w+.w+).som.(renren-inc.com)/ ) { ? $dm->{'answer'} .= dns_answer(QPTR, T_TXT, C_IN, $ttl, rr_TXT("Email address: $1@$2")); ? $dm->{'ancount'} += 1; ? }; ? }; ? if ( ! $dm->{ancount} ) { ? $dm->{rcode} = NXDOMAIN; ? }; ? };
  • 29. 附 2 再续 ? sub dyn_match { ? my ( $domain, $from ) = @_; ? my $area = match_ip($from, $regexp); ? return ($1<<24)|($2<<16)|($3<<8)|$4 if $iplist->{"$host"}->{"$area"} =~ m/ (d{1,3}).(d{1,3}).(d{1,3}).(d{1,3})/; ? };