本文将介绍如何使用 DNS (DNSPod) +HTTPDNS 实现 CNAME 展平 (CNAME Flattening)。一直以来,由于 CNAME 记录和任何记录冲突的独有特性,导致一旦在根域使用 CNAME 解析,将导致其他记录无法正常使用,影响 DS (DNSSEC)、MX (邮箱服务)、TXT (SPF、DKIM、DMARC、站长平台验证) 等记录的使用,进而影响依赖这些记录的相关服务(如括号内所示),而 CNAME 展平 (CNAME Flattening) 是解决这个问题的一种方法,但由于 DNSPod 本身不支持 CNAME 展平 (CNAME Flattening),所以本文将介绍如何使用 DNS+HTTPDNS 通过 API 调用的方式实现 CNAME 展平 (CNAME Flattening)。

为确保能精准稳定的获取到 CDN 等厂商提供的 CNAME 记录所对应的解析 IP(调度结果),脚本需要使用 HTTPDNS 服务,HTTPDNS 服务可能产生对应的请求次数费用,具体费用请参考 HTTPDNS 计费说明

前提条件

  • 域名解析托管在 DNSPod 且使用的套餐版本不低于「企业版」
  • 已开通 HTTPDNS 服务

限制说明

  • 本脚本默认仅支持国内 31 个省份的三大运营商线路,其他二级运营商、教育网、中国港澳台、境外等默认调度至上海电信线路兜底,如您需要更加完整的覆盖,可自行修改脚本添加对应的线路,详情可以查看脚本中的注释。

操作步骤

前期准备

添加域名

  1. 登录 HTTPDNS 控制台,在左侧导航栏中,单击域名管理,进入域名管理页面。
    域名管理
  2. 域名管理页面,单击添加主域名,在弹出的对话框中,输入需要添加的域名所属的,单击确定
    添加主域名

    注意:
    此处添加的域名为需要展平的 CNAME 记录所对应的主域名,而不是您自己域名;
    例如,您需要展平的 CNAME 记录为r2wind.cn.cdn.dnsv1.com.cn,则此处添加的域名为dnsv1.com.cn
    再举个例子,您需要展平的 CNAME 记录为r2wind.cn.eo.dnse3.com,则此处添加的域名为dnse3.com

获取Token

  1. 登录 HTTPDNS 控制台,在左侧导航栏中,单击开发配置,进入开发配置页面,点击Token后面的图标获取Token.
    获取Token

导入记录

使用前请您前往DNSPod 控制台导入相应记录,否则本脚本将无法正常运行。

下载记录模板

IPv4 模板:https://dl.r2wind.cn/template/DNSPod-IPv4-Storm.xls
IPv6 模板:https://dl.r2wind.cn/template/DNSPod-IPv6-Storm.xls

说明:
请根据IP类型选择相应模板。
导入前请自行修改模板中的主机记录。(若有需要)
导入前请自行修改模板中的记录值为当前 CDN 节点 IP,否则会影响域名正常访问。(节点 IP 可以通过nslookup查询CDN CNAME地址获取)
若需要导入的记录已在控制台添加过,请删除原有记录后再导入。

导入记录
  1. 登录 DNSPod 控制台,进入批量操作-导入记录页面。
  2. 输入需要导入的域名,上传已经修改好的模板,点击批量导入
    导入记录
  3. 等待导入完成,请注意查看导入结果,若有导入失败的记录,查看原因修正后手动添加记录,不要重复导入。

配置脚本

安装依赖

本脚本提供Go语言版本和Python语言版本,您可根据自己的需求选择相应版本,在此处仅演示 Go 语言版本的相关步骤。

安装Go语言环境
1
2
3
4
5
6
# 安装Go语言环境
wget https://dl.google.com/go/go1.21.3.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.21.3.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
# 设置GOPROXY
export GOPROXY=https://mirrors.cloud.tencent.com/go/
安装其他依赖
1
2
3
4
5
# CentOS/RHEL
yum install cronie
yum install git
# Debian/Ubuntu
apt install cron git

获取脚本

1
2
3
4
# 从GitHub克隆脚本
git clone https://github.com/KincaidYang/CNAMEFlattening.git
# 如您的服务器无法访问GitHub,可使用如下镜像地址
git clone https://kgithub.com/KincaidYang/CNAMEFlattening.git

修改配置

1
2
3
4
# 进入脚本目录
cd CNAMEFlattening/go/DNSPod/Storm
# 修改配置文件
vim config.go

安装文件中的配置项说明完成配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 本脚本调用了腾讯云HTTPDNS服务,可能会产生额外费用,如不想付费请使用Frost版本https://github.com/KincaidYang/CNAMEFlattening/tree/main/DNSPod/Frost
package main

const (
// 请替换成您自己的域名
domain = "r2wind.cn"
// 请替换成您自己的子域名前缀,如果不使用子域名请写 @
subdomain = "ipv4"
// 请替换成您的 CDN或其他服务的 CNAME 服务地址
// 使用前请前往 https://console.cloud.tencent.com/httpdns/domain 将 CDN 服务域名添加到 HTTPDNS
// 仅需添加主域名,如您的 CDN 服务域名为 cdn.r2wind.cn,仅需填写 r2wind.cn 完成添加即可
CDNCNAME = "r2wind.cn.eo.dnse3.com"
// 您的腾讯云HTTPDNS服务的密钥,可前往 https://console.cloud.tencent.com/httpdns/configure 获取
Token = "1********0"
// 您的腾讯云账号的 SecretId 和 SecretKey,可前往 https://console.cloud.tencent.com/cam/capi 获取
SecretId = "AKIDc5Ui**********cFfuz4GUX"
SecretKey = "teMvJS**************8bppa8U"
// 注意,该地址为DNSPod HTTPDNS服务地址,无需更换
DoH = "https://119.29.29.99/d"
// 记录类型,AAAA为IPv6记录,A为IPv4记录,请根据实际需要自行修改
recordType = "A"
// 记录TTL,单位秒,建议不低于60秒
recordTTL = 60
)

编译脚本

1
go build

完成编译后,会在当前目录生成可执行文件Storm,您可将其移动到任意位置。

运行脚本

1
./Storm

运行后您将会看到如下输出
运行脚本

设置定时任务

1
2
3
4
5
# 编辑定时任务
crontab -e
# 添加定时任务
## 每5分钟执行一次
*/5 * * * * /path/to/Storm

说明:
请根据实际情况自行修改定时任务执行频率。
请根据实际情况自行修改脚本路径,/path/to/请替换成您脚本的实际路径。
编辑完成后请保存退出即可。

验证效果

您可以在 DNSPod 控制台查看对应域名的相关记录,若记录值已经更新为 CDN 节点 IP,则说明脚本运行成功。

问题反馈

若您在使用过程中遇到任何问题,欢迎您提交 Issue

脚本示意

脚本示意