CoreDNS 是一个开源的域名系统(DNS)服务器,用于将域名解析为 IP 地址以实现网络通信。它是一个用 Go 语言编写的可扩展 DNS 服务器,旨在取代传统的 DNS 服务器并提供更灵活、可配置的解析方案。
安装配置 一个极简的Corefile配置如下
DNS服务默认端口为53。本机测试期间,选择使用 1053 端口。
首先创建名为 Corefile1 的配置文件,内容如下:
启动 coredns 服务:
1 2 3 4 % coredns -conf ./Corefile1 .:1053 CoreDNS-1.11.1 darwin/arm64, go1.21.0,
使用hosts插件 在某个项目中,我要用CoreDNS来 为特定域名指定hosts。这时用到了 hosts 插件。
例如:要实现把 a.example.com 指向 192.168.1.2。
创建名为 Corefile2 的配置文件,内容如下:
1 2 3 4 5 6 7 8 .:1053 { whoami hosts { 192.168.1.2 a.example.com fallthrough } log }
启动 coredns服务:
1 % coredns -conf ./Corefile2
查询一下 a.example.com 对应的IP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 dig @127.0.0.1 -p 1053 a.example.com ; <<>> DiG 9.10.6 <<>> @127.0.0.1 -p 1053 a.example.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64095 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;a.example.com. IN A ;; ANSWER SECTION: a.example.com. 3600 IN A 192.168.1.2 ;; Query time: 3 msec ;; SERVER: 127.0.0.1#1053(127.0.0.1) ;; WHEN: Thu Nov 23 10:58:16 CST 2023 ;; MSG SIZE rcvd: 71
可以看到 a.example.com. 3600 IN A 192.168.1.2
,符合预期。
使用template插件 要用CoreDNS来实现泛域名或具有特定规则的域名指定hosts,需要 template 插件。
例如:要实现把 *.example.com 指向 192.168.1.1。 创建名为 Corefile3 的配置文件,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 .:1053 { whoami hosts { 192.168.1.2 a.example.com fallthrough } template IN A example.com { match .*\.example\.com answer "{{ .Name }} 60 IN A 192.168.1.1" fallthrough } log }
启动 coredns服务:
1 % coredns -conf ./Corefile3
查询一下 a.example.com 对应的IP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 dig @127.0.0.1 -p 1053 b.example.com ; <<>> DiG 9.10.6 <<>> @127.0.0.1 -p 1053 b.example.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49105 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;b.example.com. IN A ;; ANSWER SECTION: b.example.com. 60 IN A 192.168.1.1 ;; Query time: 1 msec ;; SERVER: 127.0.0.1#1053(127.0.0.1) ;; WHEN: Thu Nov 23 11:11:36 CST 2023 ;; MSG SIZE rcvd: 71
可以看到 b.example.com. 60 IN A 192.168.1.1
,符合预期。
同时使用 hosts 和 template 插件 在使用 Corefile3 时,如果查询 a.example.com 的解析,就会发现一个奇怪的现象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 dig @127.0.0.1 -p 1053 a.example.com ; <<>> DiG 9.10.6 <<>> @127.0.0.1 -p 1053 a.example.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28857 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;a.example.com. IN A ;; ANSWER SECTION: a.example.com. 60 IN A 192.168.1.1 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#1053(127.0.0.1) ;; WHEN: Thu Nov 23 11:16:16 CST 2023 ;; MSG SIZE rcvd: 71
从直观看,a.example.com设置了hosts,应该是优先级更高才对,应该返回 192.168.1.2。但实际返回了templeat插件里的结果 192.168.1.1。
那么是不是插件顺序的问题呢?因为template插件在后面,覆盖了hosts插件的结果呢?实验一下。
创建 Corefile4,颠倒一下template和hosts的位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 .:1053 { whoami template IN A example.com { match .*\.example\.com answer "{{ .Name }} 60 IN A 192.168.1.1" fallthrough } hosts { 192.168.1.2 a.example.com fallthrough } log }
重新启动coredns
1 coredns -conf ./Corefile4
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 dig @127.0.0.1 -p 1053 a.example.com ; <<>> DiG 9.10.6 <<>> @127.0.0.1 -p 1053 a.example.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4163 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;a.example.com. IN A ;; ANSWER SECTION: a.example.com. 60 IN A 192.168.1.1 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#1053(127.0.0.1) ;; WHEN: Thu Nov 23 11:21:59 CST 2023 ;; MSG SIZE rcvd: 71
发现结果没有变化。
这是因为:template和hosts插件同时使用时,template的优先级更高,执行的顺序是先执行hosts 插件,后执行template 插件。源码:plugin.cfg
注意注释:
1 2 3 4 5 6 7 8 # Directives are registered in the order they should be executed. # # Ordering is VERY important. Every plugin will feel the effects of all other # plugin below (after) them during a request, but they must not care what plugin # above them are doing. 指令按照它们应该执行的顺序进行注册。 顺序非常重要。在一个请求期间,每个插件都会感受到所有其它在它们之后(下方)的插件的影响,但是它们不必关心在上面的插件正在做什么。
翻译一下就是:hosts插件不能关注到template插件所做的变更,但template插件能够改变hosts插件所做的改变。
如何解决 第1种方法是改变coredns插件的顺序,这个需要自己更改代码并编译coredns,一般不建议。
第2种方法是新起一个端口来提供服务。 创建 Corefile5 ,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 .:1053 { whoami hosts { 192.168.1.2 a.example.com fallthrough } forward . 127.0.0.1:2053 log } .:2053 { whoami template IN A example.com { match .*\.example\.com answer "{{ .Name }} 60 IN A 192.168.1.1" fallthrough } log }
启动coredns
1 2 3 4 5 coredns -conf ./Corefile5 .:1053 .:2053 CoreDNS-1.11.1 darwin/arm64, go1.21.0,
测试一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 dig @127.0.0.1 -p 1053 a.example.com ; <<>> DiG 9.10.6 <<>> @127.0.0.1 -p 1053 a.example.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60952 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;a.example.com. IN A ;; ANSWER SECTION: a.example.com. 3600 IN A 192.168.1.2 ;; Query time: 3 msec ;; SERVER: 127.0.0.1#1053(127.0.0.1) ;; WHEN: Thu Nov 23 11:51:35 CST 2023 ;; MSG SIZE rcvd: 71
发现解析地址已经变为 a.example.com. 3600 IN A 192.168.1.2
,符合预期了。
这种方法的弊端是要多发起一次请求,性能有所下降。
有没有其它更好的方法?有的,使用file插件。
使用 file 插件 fiel 插件允许使用一个 zone 文件来解析泛域名和指定域名。
首先创建 example.db 的配置文件:
1 2 3 4 5 6 7 8 9 10 11 $TTL 3600 $ORIGIN example.com. @ IN SOA ns.example.com. contact.example.com. ( 2023112301 ; serial 1d ; refresh 2h ; retry 4w ; expire 1h ; nxdomain ttl ) a.example.com. IN A 192.168.1.2 *.example.com. IN A 192.168.1.1
创建 Corefile6,内容如下:
1 2 3 4 5 .:1053 { whoami file ./example.db log }
启动coredns
1 coredns -conf ./Corefile6
然后查一下 a.example.com 和 b.example.com 的解析:
1 2 3 4 5 6 7 8 9 10 11 dig @127.0.0.1 -p 1053 a.example.com ...... ;; ANSWER SECTION: a.example.com. 3600 IN A 192.168.1.2 ...... dig @127.0.0.1 -p 1053 b.example.com ...... ;; ANSWER SECTION: b.example.com. 3600 IN A 192.168.1.1
可以看到是符合预期的。