面试小抄本之网络协议篇

    DNS 基本概念

    • 域名 ( Domain Name ) 是一串点号分割的名字,不区分大小写;完全域名 ( Fully Qualified Domain Name, FQDN ) 包含所有的域名级别,能够完全定位在 DNS 树状图下的位置。
    • DNS ( Domain Name System ) 即负责域名和 IP 地址映射的分布式数据库。早期主机名和 IP 地址的映射保存在 NIC 的 hosts 文件中,该方案随着互联网规模的膨胀而变得压力巨大;DNS 的分布式结构缓解了单一主机的瓶颈。
    • 域名服务器 ( Domain Name Server ) 存储并管理所辖区域的域名数据库,负责接收来自地址解析器 ( Resolver ) 的请求并返回响应,按照请求的类型、进行递归与非递归查询。

    1. 根域名服务器

    DNS 中最高级别的域名服务器(即 .) 负责返回顶级域名的权威域名服务器的地址。全球众多的根服务器被编号为A~M共13个编号,借助任播 ( Anycast ) 技术,编号相同的根服务器使用同一个 IP,全球都具备这些 IP 的镜像站点。关于根域的详细信息可以查看:http://www.iana.org/domains/root/

    13个根域服务器是指逻辑上(相同 IP 地址)、而非物理上13台服务器。至于13怎么来的,原因是13组响应 ( 32 bytes IPv4 Address ) 是一个 512-Bytes UDP 包能容纳的数目

    根域的运营主体(如 ICANN)可以中止镜像服务器的路由,比如国内因为发生 DNS 污染而被中断路由的事件。

    2. 顶级域名

    • 一般顶层域名 ( Generic TLDs, gTLD ) 如 .com, .gov, 包括一些新启用的域名如 .me
    • 国家码顶层域名 ( Country code TLDs, ccTLD ) 如 .cn

    各层 DNS 能够授权管理自己辖下的主机名或子域名,比如 .com 记录 example.com 的信息;每层 DNS 只能管理直接下级域中的主机。

    层级结构带来的好处:

    • 域名修改时,只需知会直接上一级域名服务器即可
    • DNS 的分布式解析架构,也可以平衡流量压力

    3. DNS 解析流程

    当浏览器输入网址 wyh.life

    1. DNS 客户端(如 Chrome 浏览器)解析某个域名时,会自动补全 FQDN,并查询客户端DNS缓存;Chrome DNS 缓存 TTL 是1分钟

    2. 当客户端 DNS 缓存不存在时,查询操作系统 DNS 缓存;如果仍不存在,尝试读取本地 hosts 文件

    3. 发送查询请求至 Local DNS,Local DNS 一般是由 ISP 分配。查询方式为递归解析,即 Local DNS 作为客户端持续向其它 DNS 服务器进行查询,直至解析成功或失败

       $ cat /etc/resolv.conf
       nameserver 8.8.8.8
      
    4. Local DNS 首先检查自己是否能够给出权威应答,即是否是为该 DNS Zone 的管理者

    5. 如果是非权威服务器时,则首先查询请求域名是否存在于缓存,如果有则直接返回;否则从 DNS 保存的根域 Zone File 中读取根服务器地址,并发起请求

       ; <<>> DiG 9.9.5-3ubuntu0.8-Ubuntu <<>> wyh.life +trace
       ;; global options: +cmd
       .           9095    IN  NS  a.root-servers.net.
       .           9095    IN  NS  b.root-servers.net.
       .           9095    IN  NS  c.root-servers.net.
       ...
       .           9095    IN  NS  m.root-servers.net.
       ;; Received 397 bytes from 8.8.8.8#53(8.8.8.8) in 5125 ms
      
    6. 根服务器返回 .life 域的权威 DNS 服务器(即 NS 记录)

       life.           172800  IN  NS  demand.gamma.aridns.net.au.
       life.           172800  IN  NS  demand.delta.aridns.net.au.
       life.           172800  IN  NS  demand.beta.aridns.net.au.
       life.           172800  IN  NS  demand.alpha.aridns.net.au.
       ;; Received 576 bytes from 192.228.79.201#53(b.root-servers.net) in 114 ms
      

      NS records identify an authoritative name server for a domain (more correctly, a DNS zone). They tell a DNS query where to look for authoritative detail about a domain (zone).

    7. 请求得到 wyh.life. 的权威 DNS 服务器

       wyh.life.       86400   IN  NS  f1g1ns2.dnspod.net.
       wyh.life.       86400   IN  NS  f1g1ns1.dnspod.net.
       ;; Received 684 bytes from 37.209.196.7#53(demand.gamma.aridns.net.au) in 634 ms
      
    8. 请求得到A记录,地址解析完成

       wyh.life.       86400   IN  A   192.30.252.154
       wyh.life.       86400   IN  A   192.30.252.153
       wyh.life.       86400   IN  NS  f1g1ns1.dnspod.net.
       wyh.life.       86400   IN  NS  f1g1ns2.dnspod.net.
       ;; Received 133 bytes from 182.140.167.188#53(f1g1ns2.dnspod.net) in 286 ms
      

    注:如果得到的不是A地址,而是别名记录(CNAME,即将某个别名指向A记录),查询中止、并重新发起对别名的查询请求。

    参考资料:How does dig +trace actually work?

    注:DNS 负载均衡

    • 循环 DNS ( Round-robin DNS) 单个域名、多个 IP 列表循环应对 DNS 查询,缺点是客户端一旦解析成功会使用缓存的解析记录,继而绕过了 DNS 服务器负载均衡。

    4. 域名区域 ( DNS Zone )

    DNS 数据库中针对每个域 ( Domain ) 的记录,称为一个域名区域 ( Zone )

    关于区域和域的划分,参考文章:关于DNS的杂七杂八

    每个区域通常包含:

    • 名称服务器记录 ( Name Server, NS ) 表明有哪些 DNS 服务器负责解析
    • 起始授权机构 ( Start of Authority, SOA ) 表明哪个 DNS 服务器是主服务器
    • 主机记录 ( A / AAAA ) 将主机名映射到 IPv4 / IPv6 地址

    (以下摘自:关于DNS的杂七杂八

    例如,服务器A是 a.com 的权威域名服务器,它将 test.a.com 子域授权给服务器B. 服务器A上有如下记录:

    test.a.com. IN  NS  B.test.a.com.
    B.test.com. IN  A   1.2.3.4
    

    B.test.a.com. 是服务器B的 FQDN,下边一条A记录称为 glue 记录,这样 test.com 域外的服务器能够通过 glue 记录找到服务器B.

    服务器B作为区域 test.a.com 的权威域名服务器,包含一条 SOA 记录和一条 NS 记录。


    DNS 攻击

    DNS 污染

    由于通常的 DNS 查询没有任何认证机制,且 DNS 查询主要基于无连接不可靠的 UDP,因此 DNS 查询非常容易被篡改。攻击者伪装成目标域名的解析服务器(NS)给查询者返回虚假结果,查询者只接受最先返回的格式正确结果,因此得到错误的 DNS 解析结果。

    此外各级 DNS 服务器为了减少重复查询,会缓存 DNS 解析结果,一旦 DNS 查询被污染、后继查询请求都会被污染。

    DNS 劫持

    即 DNS 服务器返回非正确的查询结果,常见于 ISP 恶意劫持,比如 jQuery 等类库的 CDN 请求被调包为包含恶意或广告代码的返回文件。CDN 本质上也是一种 DNS 劫持(良性劫持)。

    参考阅读:Google DNS劫持背后的技术分析

    DNS 安全事件

    1. 暴风影音导致断网

    1. 由于游戏私服互斗,DNSPod 遭受了 DDoS 攻击
    2. 由于流量压力,电信 IDC 在路由上封禁了 DNSPod 的IP地址,导致 DNSPod 的域名解析服务不可用
    3. 暴风影音自启的后台程序每15s左右与服务器通信,当解析不到地址会不断重试;而该域名解析服务由 DNSPod 提供
    4. 全国各地千万级别的电信暴风用户不断进行 DNS 查询,形成了对 DNS 递归查询服务器的 DDoS 攻击。UDP 传输是没有流控功能的,导致部分地区电信出口链路出现拥塞
    5. 网通因为有 DNS 绑架(解析不出来会返回网通广告页地址,而非返回 DNS SERVFAIL),所以网通线路基本没受影响

    2. 百度域名劫持

    社工攻击,黑客冒充管理员请求域名注册代理服务商 Register.com 修改了 baidu.com 的管理员邮箱,进而重置了管理员帐号、并修改了 baidu.com 的域名指向

    DNS 安全策略

    • 采用 UDP 随机端口,避免 DNS 缓存攻击
    • 对于少数重要网站采用IP静态映射,不使用缓存或向上一级进行迭代查询,减少 DNS 欺骗攻击
    • 限制查询,以避免泄漏内部的网络拓扑结构:在一个信任网域下,将 DNS 资料列出是没有问题的(即正常的主从服务器的 Zone Transfer),需要避免的是从外界进行任意查询。参考:DNS域传送信息泄露

    相关实验

    dig 介绍

    工具可用 dig, host, nslookup.

    dig (domain information groper) is a flexible tool for interrogating DNS name servers. It performs DNS lookups and displays the answers that are returned from the name server(s) that were queried.

    A typical invocation of dig looks like: dig @server name type

    使用 dig 查看一条记录(RR, Resource Record)输出格式:

    [Domain]    [TTL]   IN  [RR Type]   [[RR Data]]
    

    参考:http://anouar.adlani.com/2011/12/useful-dig-command-to-troubleshot-your-domains.html

    实验:查询 IP

    $ dig wyh.life
    ;; ANSWER SECTION:
    wyh.life.           85276   IN  CNAME   pages.coding.me.
    pages.coding.me.    246     IN  A       23.91.98.188
    
    # Test on VPS
    $ dig wyh.life
    ;; ANSWER SECTION:
    wyh.life.       96  IN  A   192.30.252.153
    wyh.life.       96  IN  A   192.30.252.154
    

    对于国外线路,A记录指向了 Github Pages 的 DNS Zone ( 192.30.252.* ),详见 https://help.github.com/articles/setting-up-an-apex-domain/,国内线路则 CNAME 到 Coding Pages.

    Github Pages / Coding Pages 主机上托管了无数站点,而对于这些站点的请求是通过 HTTP 头部的 Host 字段来识别的

    $ curl --header "host: wyh.life" 192.30.252.153
    $ curl --header "host: wyh.life" pages.coding.me
    

    实验:查询 CNAME, NS

    $ dig +short wyh.life cname
    pages.coding.me.
    
    # Test on VPS
    $ dig wyh.life ns
    f1g1ns1.dnspod.net.
    f1g1ns2.dnspod.net.
    

    实验:指定 DNS Server 查询

    $ dig wyh.life @8.8.8.8 +short
    192.30.252.153
    192.30.252.154
    
    $ dig wyh.life @114.114.114.114 +short
    pages.coding.me.
    23.91.98.188
    

    实验:查询 SOA

    $ dig wyh.life soa +multiline
    ;; ANSWER SECTION:
    wyh.life.      600 IN SOA f1g1ns1.dnspod.net. freednsadmin.dnspod.com. (
                            1460108051 ; serial
                            3600       ; refresh (1 hour)
                            180        ; retry (3 minutes)
                            1209600    ; expire (2 weeks)
                            180        ; minimum (3 minutes)
                            )
    
    • f1g1ns1.dnspod.net.: SOA 主机地址
    • freednsadmin.dnspod.com.: 标识联系邮件,即 freednsadmin@dnspod.com
    • 1460108051; serial: 标识域名信息变化的序列号,每次域名变化时该项数值增大
    • 3600; refresh: 标识备用 DNS 服务器查询主服务器中序列号是否增加(即域文件变化)的间隔时间
    • 180; retry: 标识备用 DNS 服务器无法连接主服务器时重试间隔时间
    • 1209600; expire: 标识备用 DNS 服务器无法连接主服务器时,可以在多长时间内认为缓存有效
    • 180; minimum: 标识缓存 DNS 服务器可以缓存记录多长时间

    实验:查询 MX

    $ dig mx gmail.com
    ;; ANSWER SECTION:
    gmail.com.      3263 IN MX 10 alt1.gmail-smtp-in.l.google.com.
    gmail.com.      3263 IN MX 30 alt3.gmail-smtp-in.l.google.com.
    gmail.com.      3263 IN MX 5 gmail-smtp-in.l.google.com.
    gmail.com.      3263 IN MX 20 alt2.gmail-smtp-in.l.google.com.
    gmail.com.      3263 IN MX 40 alt4.gmail-smtp-in.l.google.com.
    
    # Or try
    $ nslookup -query=mx gmail.com
    

    MX 应答的格式:

    [Domain]    [TTL]   IN MX [Preference] [Exchange]
    

    Preference 标识优先级(0~65535,越小优先级越高),Exchange 为主机域名。

    The domain names that a Sender-SMTP sends in MAIL and RCPT commands MUST have been “canonicalized”, i.e., they must be fully-qualified principal names or domain literals, not nicknames or domain abbreviations. A canonicalized name either identifies a host directly or is an MX names; it cannot be a CNAME

    • 某条 MX 记录的 Exchange 不可访问(比如被 Block)、可能导致邮件发送失败,原因可能在于邮件发送服务没有遵循 RFC 定义的 MX 重试规则。
    • 一些海外邮件代收服务,也是通过添加 MX 记录来实现的。

    实验:查询 IP 对应的主机名

    $ dig -x 114.114.114.114 +short
    public1.114dns.com.
    

    实验:查询顶级域名的 NS

    $ dig NS life. +short
    demand.alpha.aridns.net.au.
    demand.beta.aridns.net.au.
    demand.delta.aridns.net.au.
    demand.gamma.aridns.net.au.
    

    可以从 ICANN 官方 Wiki 查看顶级域名(TLD)详细信息,如 http://icannwiki.com/.life

    $ dig NS com. +short | sort
    a.gtld-servers.net.
    b.gtld-servers.net.
    c.gtld-servers.net.
    d.gtld-servers.net.
    e.gtld-servers.net.
    f.gtld-servers.net.
    g.gtld-servers.net.
    h.gtld-servers.net.
    i.gtld-servers.net.
    j.gtld-servers.net.
    k.gtld-servers.net.
    l.gtld-servers.net.
    m.gtld-servers.net.
    

    测试根域 / com域 的权威解析服务,可以尝试如下脚本(参考自 http://blog.fenghe.org/archives/1839#more-1839

    for i in a b c d e f g h i j k l m; do
        echo $i.root-servers.net
        dig wyh.life @$i.root-servers.net | grep 'Query time'
        # echo @$i.gtld-servers.net
        # dig wyh.life @$i.gtld-servers.net | grep 'Query time'
        echo
    done
    

    对于不常访问的域名,各地的递归服务器里没有缓存,会向上查询。而上一级的权威NS(如com/net域)、以及根DNS都大规模访问失败,从而导致域名解析超时,或无法解析。

    摘自:http://blog.fenghe.org/archives/927,原文有更精彩的内容

    通过 Chrome 查看 DNS 解析情况

    • Chrome 访问 chrome://net-internals#dns 查看 DNS 记录
    • Chrome 访问 chrome://histograms/DNS.ResolveSuccess 查看 DNS 解析的耗时分布统计

    左侧第一栏数字为解析耗时(毫秒),从直方图可以看出解析耗时的分布,比如 ~50% 的 DNS 解析在 50ms 内完成,90% 是在 150ms 内。

    参考:https://plus.google.com/+IlyaGrigorik/posts/WhpTG92ta3f