本地模拟CNAME解析
众所周知,我们可以通过修改本地 hosts 文件来定义一个域名的指向,这个过程我们可以简单的理解为在本机创建了一个优先级很高的 DNS A 记录,实现了某种程度上的域名劫持, 利用这种特性我们可以实现诸如广告屏蔽、本地测试、别名等需求,但 hosts 机制仅仅能定义域名与 IP 对应关系, 并不能模拟其他的 Record 类型, 比如 CNAME 记录。
前言
由于近期某个应用在某些地区的连通性较差,于是考虑临时对其使用 CDN, 在上线之前,我们需要测试并调整 CDN 回源、缓存策略等各项配置,由于不是新上线的域名,这个域名是有用户在使用的,所以我们不能简单粗暴的将 DNS 记录直接切到 CDN 的 CNAME 域名, 因此我们只能考虑在本地搭建一个 DNS 服务,用于模拟 CNAME。
安装 DNS 服务
本机为 macOS,使用 homebrew 来安装 dnsmasq 搭建 DNS 服务器, 其他系统配置文件路径会有所不同。1
2
3
4
5# 安装 dnsmasq
brew install dnsmasq
# 备份默认配置文件
cp /opt/homebrew/etc/dnsmasq.conf /opt/homebrew/etc/dnsmasq.conf.bak
默认的 dnsmasq 配置文件很长,不过大多数配置都注释掉了,可以根据注释来配置我们需要的,这里仅配置一下我们需要关注的地方:
vim /opt/homebrew/etc/dnsmasq.conf
:1
2
3
4
5
6
7
8
9
10
11
12
13# 定义一下上游的 DNS 服务地址
resolv-file=/Users/alliot/dns.conf
# 按照 resolv-file 中列出的顺序查询上游 DNS 服务器
strict-order
user=root
listen-address=127.0.0.1
# 从指定的文件读取额外的主机名映射,也就是 hosts
addn-hosts=/etc/banner_add_hosts
# 创建一条CNAME记录,www.iots.vip会CNAME到alliot.blog.net,多条记录可以在配置文件中写多条配置
cname=www.iots.vip,alliot.blog.net
创建一下 dns.conf 指定上游的 DNS:vim /Users/alliot/dns.conf
1
2nameserver 114.114.114.114
nameserver 223.5.5.5
之后重启服务:1
2这里由于我们上面启动dnsmasq的用户是root,所以必须加sudo
sudo brew services restart dnsmasq
配置本机DNS
假设我们 macOS 当前使用的 Wi-Fi 网络,我们可以直接使用命令行配置 Wi-Fi 网卡的 DNS 服务器:1
2
3
4
5
6
7# 获取当前的 DNS 配置
networksetup -getdnsservers Wi-Fi
# 修改DNS为127.0.0.1,即我们的dnsmasq服务
networksetup -setdnsservers Wi-Fi 127.0.0.1
networksetup -getdnsservers Wi-Fi
当然你也可以通过界面来配置:
依次点击 “系统偏好设置 > 网络 > 高级 > DNS”,选中 “DNS” 配置,删除现有的公共 DNS,填入 127.0.0.1
保存即可。
至此我们便可以完成了在本地模拟 CNAME 解析了,当我们访问 www.iots.vip
时,便 CNAME 到了 alliot.blog.net
。
验证
我们可以使用 dig
来指定 DNS 服务器来验证一下:1
2
3
4
5
6
7
8
9先使用114的DNS解析来看一下现网的DNS记录:
dig +short www.iots.vip @114.114.114.114
这里会返回我们现网的DNS记录
再使用本地我们的dnsmasq来解析一下:
dig +short www.iots.vip @127.0.0.1
再直接使用当前系统配置的DNS服务看看是否生效:
dig +short www.iots.vip
结语
原理是 DNS 的工作方式是分层的,就像一个有许多层次的目录或者电话簿。
我们这里将本机 DNS 指定为了我们启动的 dnsmasq, dnsmasq 指定了 114.114.114.114 为上游 DNS, 那么当我们访问一个网站时,DNS 解析路径就为 hosts -> dnsmasq -> 114DNS.www.iots.vip
在 dnsmasq 时找到了一个 CNAME 记录,便不会再往 114DNS 去查询,达到了自定义 CNAME 记录的目的。