​在国内,我们常使用的DNS解析托管服务商有DNSPod、阿里云(万网)等。比如以下这个例子

$ dig qidian.com NS
; <<>> DiG 9.11.3-1ubuntu1.15-Ubuntu <<>> qidian.com NS
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3496
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
​
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;qidian.com.                    IN      NS
​
;; ANSWER SECTION:
qidian.com.             86400   IN      NS      ns4.dnsv4.com.
qidian.com.             86400   IN      NS      ns3.dnsv4.com.
​
;; Query time: 226 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Sun Aug 01 19:03:39 CST 2021
;; MSG SIZE  rcvd: 81

可以看出,对于qidian.com来说,如果想获得子域的解析,可以直接向ns*.dnsv4.com发起请求。通过查询可知,以上权威DNS是DNSPod提供的。

同时,我们也常常在一些互联网大厂的DNS中发现这种情形

$ dig qq.com NS
; <<>> DiG 9.11.3-1ubuntu1.15-Ubuntu <<>> qq.com NS
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 425
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
​
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;qq.com.                                IN      NS
​
;; ANSWER SECTION:
qq.com.                 47533   IN      NS      ns3.qq.com.
qq.com.                 47533   IN      NS      ns4.qq.com.
qq.com.                 47533   IN      NS      ns1.qq.com.
qq.com.                 47533   IN      NS      ns2.qq.com.
​
;; Query time: 1 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Sun Aug 01 19:13:00 CST 2021
;; MSG SIZE  rcvd: 107

qq.com的解析需要向ns1.qq.com来查询,然而ns1.qq.com又是qq.com的子域,这貌似形成了一个循环。
这就是本文所谈及的,NS的域与托管的域相同,这种NS一般被称作白标签(White-label) NS,或者称作虚(Vanity) NS。

可能要问了,它有什么好处呢?看起来更专业:)
国内DNS解析托管服务商通常不提供这种服务,下面我们会将如何在亚马逊云科技所提供的Route 53 China创建托管区域并且实施白名单NS做一个记录。

1) 你需要有一个域名,比如我在NameSilo购入了一个域名,sean-aws.xyz,其NS默认设置如下,ns*.dnsowl.com是NameSilo的默认NS

$ dig sean-aws.xyz NS
; <<>> DiG 9.11.3-1ubuntu1.15-Ubuntu <<>> sean-aws.xyz NS
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35777
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
​
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;sean-aws.xyz.                  IN      NS
​
;; ANSWER SECTION:
sean-aws.xyz.           86400   IN      NS      ns3.dnsowl.com.
sean-aws.xyz.           86400   IN      NS      ns1.dnsowl.com.
sean-aws.xyz.           86400   IN      NS      ns2.dnsowl.com.
​
;; Query time: 387 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Sun Aug 01 20:46:35 CST 2021
;; MSG SIZE  rcvd: 105

2) 用以下命令创建可重用委派集(reusable delegation set),顾名思义,它可以在多个托管区域重用。

$ aws route53 create-reusable-delegation-set --caller-reference demo
{
    "Location": "https://route53.amazonaws.com.cn/2013-04-01/delegationset/N0275007Y61U5W4UH13A",
    "DelegationSet": {
        "Id": "/delegationset/N0275007Y61U5W4UH13A",
        "CallerReference": "demo",
        "NameServers": [
            "ns-1747.awsdns-cn-45.net",
            "ns-3578.awsdns-cn-31.cn",
            "ns-intl-3578.awsdns-cn-31.cn",
            "ns-1009.awsdns-cn-63.com",
            "ns-2315.awsdns-cn-16.biz",
            "ns-intl-1009.awsdns-cn-63.com"
        ]
    }
}

3) 记住以上的DelegationSetId,并使用如下命令创建sean-aws.xyz的托管区域,可以看到刚才的可重用委派集在这里直接使用在了托管区域上。

$ aws route53 create-hosted-zone --name sean-aws.xyz --caller-reference demo --delegation-set-id N0275007Y61U5W4UH13A
{
    "Location": "https://route53.amazonaws.com.cn/2013-04-01/hostedzone/Z03262292RQU5PFGGMFYG",
    "HostedZone": {
        "Id": "/hostedzone/Z03262292RQU5PFGGMFYG",
        "Name": "sean-aws.xyz.",
        "CallerReference": "demo",
        "Config": {
            "PrivateZone": false
        },
        "ResourceRecordSetCount": 2
    },
    "ChangeInfo": {
        "Id": "/change/C02191583TQILEZY84OCK",
        "Status": "PENDING",
        "SubmittedAt": "2021-08-01T11:57:11.006000+00:00"
    },
    "DelegationSet": {
        "Id": "/delegationset/N0275007Y61U5W4UH13A",
        "CallerReference": "demo",
        "NameServers": [
            "ns-1747.awsdns-cn-45.net",
            "ns-3578.awsdns-cn-31.cn",
            "ns-intl-3578.awsdns-cn-31.cn",
            "ns-1009.awsdns-cn-63.com",
            "ns-2315.awsdns-cn-16.biz",
            "ns-intl-1009.awsdns-cn-63.com"
        ]
    }
}

4) 获取NS的IP地址,可以通过如下方式获得

$ dig ns-1747.awsdns-cn-45.net +short
52.82.182.211

重复这个动作,我们可以得到如下表格,

​NS IP
ns-1747.awsdns-cn-45.net 52.82.182.211
ns-3578.awsdns-cn-31.cn 54.222.37.250
ns-intl-3578.awsdns-cn-31.cn 52.46.181.250
ns-1009.awsdns-cn-63.com 52.82.179.241
ns-2315.awsdns-cn-16.biz 54.222.33.11
ns-intl-1009.awsdns-cn-63.com 52.46.187.241

这里需要注意的是,Route 53 China和Global不同,Global采用了Anycast并且每个NS都有IPv6,而China没有Anycast同时NS也没有提供IPv6,对以上内容分析,我们可以得出,Route 53 China给的六个IP,2个是北京区域,2个是宁夏区域,还有两个则是AWS Global。
5) 根据第四步获得的IP,我们可以在托管区域内创建以下记录,假设目标用户主要在国内,我们以北京做为ns1,宁夏做为ns2,国际做为ns3

​A IP
ns1.sean-aws.xyz 54.222.37.250
54.222.33.11
ns2.sean-aws.xyz 52.82.182.211
52.82.179.241
ns3.sean-aws.xyz 52.46.181.250
52.46.187.241

A记录,采用NS典型TTL 172800 (2天),可以得到以下json文件,命名为ns-records.json。

{
    "Comment": "add ns records",
    "Changes": [
        {
            "Action": "CREATE",
            "ResourceRecordSet": {
                "Name": "ns1.sean-aws.xyz",
                "Type": "A",
                "TTL": 172800,
                "ResourceRecords": [
                    {
                        "Value": "54.222.37.250"
                    },
                    {
                        "Value": "54.222.33.11"
                    }
                ]
            }
        },
        {
            "Action": "CREATE",
            "ResourceRecordSet": {
                "Name": "ns2.sean-aws.xyz",
                "Type": "A",
                "TTL": 172800,
                "ResourceRecords": [
                    {
                        "Value": "52.82.182.211"
                    },
                    {
                        "Value": "52.82.179.241"
                    }
                ]
            }
        },
        {
            "Action": "CREATE",
            "ResourceRecordSet": {
                "Name": "ns3.sean-aws.xyz",
                "Type": "A",
                "TTL": 172800,
                "ResourceRecords": [
                    {
                        "Value": "52.46.181.250"
                    },
                    {
                        "Value": "52.46.187.241"
                    }
                ]
            }
        }
    ]
}

然后我们可以添加这些记录

$ aws route53 change-resource-record-sets --hosted-zone-id Z03262292RQU5PFGGMFYG --change-batch file://ns-records.json
{
    "ChangeInfo": {
        "Id": "/change/C021041031NI8B2MHPTA6",
        "Status": "PENDING",
        "SubmittedAt": "2021-08-01T13:15:08.099000+00:00",
        "Comment": "add ns records"
    }
}

这里可以看到状态是Pending,我们可以通过Id确认下这个操作是否已经传播到了所有的Route 53服务器上

$ aws route53 get-change --id /change/C021041031NI8B2MHPTA6
{
    "ChangeInfo": {
        "Id": "/change/C021041031NI8B2MHPTA6",
        "Status": "INSYNC",
        "SubmittedAt": "2021-08-01T13:15:08.099000+00:00",
        "Comment": "add ns records"
    }
}

可以看到状态已经变成了INSYNC

6) 更新SOA和NS记录

我们先看看原来的SOA和NS记录是什么

$ aws route53 list-resource-record-sets --hosted-zone-id Z03262292RQU5PFGGMFYG
{
    "ResourceRecordSets": [
        {
            "Name": "sean-aws.xyz.",
            "Type": "NS",
            "TTL": 172800,
            "ResourceRecords": [
                {
                    "Value": "ns-1747.awsdns-cn-45.net."
                },
                {
                    "Value": "ns-3578.awsdns-cn-31.cn."
                },
                {
                    "Value": "ns-intl-3578.awsdns-cn-31.cn."
                },
                {
                    "Value": "ns-1009.awsdns-cn-63.com."
                },
                {
                    "Value": "ns-2315.awsdns-cn-16.biz."
                },
                {
                    "Value": "ns-intl-1009.awsdns-cn-63.com."
                }
            ]
        },
        {
            "Name": "sean-aws.xyz.",
            "Type": "SOA",
            "TTL": 900,
            "ResourceRecords": [
                {
                    "Value": "ns-1747.awsdns-cn-45.net. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400"
                }
            ]
        }
    ]
}

这是我们便可以把NS记录替换为我们创建的三个NS,同时将SOA最前面的域名替换为第一个NS,可以构建如下json,命名为ns-n-soa.json

{
    "Comment": "update NS and SOA records",
    "Changes": [
        {
            "Action": "UPSERT",
            "ResourceRecordSet": {
                "Name": "sean-aws.xyz.",
                "Type": "NS",
                "TTL": 172800,
                "ResourceRecords": [
                    {
                        "Value": "ns1.sean-aws.xyz."
                    },
                    {
                        "Value": "ns2.sean-aws.xyz."
                    },
                    {
                        "Value": "ns3.sean-aws.xyz."
                    }
                ]
            }
        },
        {
            "Action": "UPSERT",
            "ResourceRecordSet": {
                "Name": "sean-aws.xyz.",
                "Type": "SOA",
                "TTL": 900,
                "ResourceRecords": [
                    {
                        "Value": "ns1.sean-aws.xyz. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400"
                    }
                ]
            }
        }
    ]
}

然后应用这个json

$ aws route53 change-resource-record-sets --hosted-zone-id Z03262292RQU5PFGGMFYG --change-batch file://ns-n-soa.json
{
    "ChangeInfo": {
        "Id": "/change/C08509841RLAAP1ULRO0N",
        "Status": "PENDING",
        "SubmittedAt": "2021-08-01T13:26:18.509000+00:00",
        "Comment": "update NS and SOA records"
    }
}

7) 经过已经上步骤,Route 53侧的配置就已经结束了。我们需要将NS配置到域名上,这通常在域名注册商更改,对于一般的NS(类似于起点那种,使用非自己域的NS),我们直接在注册商更新NS记录即可,但是对于白标签NS,我们还需要在注册商做NS和IP的绑定,即胶水记录(glue records)。

对于NameSilo,首先我们更新NS,点击View/Manage Registered NameServers

将记录都添加到NameSilo

然后再更新NameSilo,NS的更新需要更长的时间才能传播到更多的服务器上,最终如下

等待一些时间,我们也可以使用dig来验证一下。

$ dig sean-aws.xyz NS @8.8.8.8 +tcp
; <<>> DiG 9.11.3-1ubuntu1.15-Ubuntu <<>> sean-aws.xyz NS @8.8.8.8 +tcp
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55451
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;sean-aws.xyz.                  IN      NS

;; ANSWER SECTION:
sean-aws.xyz.           21599   IN      NS      ns1.sean-aws.xyz.
sean-aws.xyz.           21599   IN      NS      ns2.sean-aws.xyz.
sean-aws.xyz.           21599   IN      NS      ns3.sean-aws.xyz.

;; Query time: 148 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Aug 01 21:51:47 CST 2021
;; MSG SIZE  rcvd: 95

DNS解析服务是网站的基础设施,我们建议在一开始就完成搭建,如果是从其他服务商迁移到Route 53还好,若是已经存在Route 53托管区域了,又想使用白标签NS,则流程上就变得更加复杂了,而且还存在解析中断的风险。

参考资料:https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/white-label-name-servers.html