這陣子在研究自行建設 Postfix Mail Server,發現要架設一個 Mail Server 沒有想像中的容易,除了需要透過 DNS 記錄設定網域的 A 記錄、 MX 記錄之外,另外需要 DNS 設定 SPF, DKIM, DMARC 等安全性設定。

在設定的過程中很快的遇到了瓶頸,一般的網域服務諸如 HiDomain、GoDaddy 等平台都有代管 DNS 記錄的上限,像我使用的 HiDomain 就有最多設定 20 筆記錄的上限,因為在不同專案已經註冊了許多子網域,這次要架設一個 Mail Server 時我很快就碰到了 DNS 記錄的代管上限,後來決定使用在 Kubernetes (k8s) 中經常使用的輕量 DNS Server CoreDNS 來自建 DNS Server。


關於 CoreDNS

CoreDNS 是雲原生運算基金會 (Cloud Native Computing Foundation, 簡稱 CNCF)的一項專案,並於 2019 年畢業。

CoreDNS 主要使用 Go 語言實做,所以可以安裝於不同平台並且相當輕量不會佔用太多系統的資源,同時在設定上非常簡單,透過使用 corefile ,可以很簡單的引入各種 plugin,很大程度地減少設定上的複雜度,接下來就實際進入安裝與使用的介紹。


安裝 CoreDNS

官網上提供了三種安裝方式, BinariesSourceDocker

Binaries 是已經預先編譯好的可執行檔,可以透過官方的連結去下載使用。

Source 則是下載最新版本的 CoreDNS 原始碼自行編譯成可執行檔。

最後一種安裝方式是透過官方在 DockerHub 上所提供的 Docker image 去安裝與建置 CoreDNS,也是我選擇的安裝方式。

1
docker pull coredns/coredns

▲使用上面指令可以下載最新版本的 docker image

實務上為了後續維運上的方便,我通常在使用 docker image 時會指定特定版本號,避免後續因為意料外的版本更新造成服務異常。

1
docker pull coredns/coredns:1.9.3

▲加上版本號標籤指定使用特定版本的 docker image

下載完 Docker image 後,可以嘗試啟動 Docker container:

1
docker run --it --rm -p 53:53/udp coredns/coredns:1.9.3

啟動後,我們可以使用下列指令測試服務是否正常

1
dig @127.0.0.1 a whoami.example.org

如果可以看到如下的回覆代表 DNS Server 已成功安裝:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
; <<>> DiG 9.10.3-P4-Ubuntu <<>> @127.0.0.1 a whoami.example.org
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 56921
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;whoami.example.org.  IN A
;; AUTHORITY SECTION:
example.org.  2340 IN SOA ns.icann.org. noc.dns.icann.org. 2022072112 7200 3600 1209600 3600
;; Query time: 5 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Aug 15 11:39:36 CST 2022
;; MSG SIZE  rcvd: 123

使用 Corefile 設定 DNS 紀錄

回到最原本的需求,我是要建立一個 DNS Server 來管理自己網域的相關 DNS 紀錄,那接下來我就示範如何透過 Corefile 來設定自己網域的相關 DNS 紀錄。

CoreDNS 有許多外掛模組可以用,那我這邊用到的是 file 這個 plugin,讓 CoreDNS 可以讀取我們設定好的 zone file。

Corefile:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
.:53 {
     forward . 8.8.8.8 9.9.9.9
     log
     errors
}
example.org:53 {
     file /cfg/example.org
     log
     errors
}

CoreDNS 使用 greedy match policy 來選擇最為匹配的 DNS 設定,上方的 Corefile 中我們可以看到兩個區塊,一個是 .:53,表示 wildcard 的域名 query,下面的是 example.org:53 ,表示跟 example.org 相關的域名請求會跑到這個區塊。

以下說明相關設定:

  • file /cfg/example.org 這行指令是說透過 file 這個外掛模組去讀取 /cfg/example.org 這個 zone file 設定檔。
  • log 是指儲存 DNS query log。
  • errors 是指儲存 error log。

完成 Corefile 設定後,我們就可以開始著手來管理自己域名的 DNS 紀錄啦,可以在設定檔目錄裡面新增一個 example.org (實際設定可依照您自己註冊的域名去做替換)

example.org:

1
2
3
4
5
example.org.         IN  SOA   dns.example.org. admin.example.org. 2022081321 7200 3600 1209600 3600
example.org.         IN  A     10.0.0.1
dns.example.org.     IN  A     10.0.0.1
mail.example.org.    IN  A     10.0.0.1
example.org.         IN  MX    10 mail.example.org

設定檔案目錄結構:

1
2
3
/home/<your_username>/coredns
  ├── Corefile
  └── example.org

在完成設定檔後,重新啟動 CoreDNS Docker container:

1
2
3
4
5
docker run -itd --rm --name=dns1 \
  -v /home/<your_username>/coredns:/cfg \
  -p 53:53/udp \
  -p 53:53/tcp \
  coredns/coredns:1.9.3 -conf /cfg/Corefile

然後使用 dig 指令測試您的 DNS Server

1
dig @127.0.0.1 A mail.example.org

壓力測試

安裝完 DNS Server 之後,使用 dnsperf 這項工具來壓力測試一下,在我所租用的 1 cpu、2G ram 的小型主機上可以得到大約 6,000 qps 的處理效能,看起來挺棒的:

測試命令:

1
$ dnsperf -s 127.0.0.1 -d queryfile -l 30 -c 20 -Q 10000

結果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
DNS Performance Testing Tool
Version 2.9.0
[Status] Command line: dnsperf -s 127.0.0.1 -d queryfile -l 30 -c 20 -Q 10000
[Status] Sending queries (to 127.0.0.1:53)
[Status] Started at: Mon Aug 15 12:46:47 2022
[Status] Stopping after 30.000000 seconds
[Status] Testing complete (time limit)
Statistics:
Queries sent:         187027
  Queries completed:    187027 (100.00%)
  Queries lost:         0 (0.00%)
Response codes:       NOERROR 187027 (100.00%)
  Average packet size:  request 38, response 74
  Run time (s):         30.018232
  Queries per second:   6230.446883
Average Latency (s):  0.015878 (min 0.000180, max 0.217620)
  Latency StdDev (s):   0.010163

域名代管平台設定

在完成並測試自建 DNS Sever 後,我們就可以將域名代管平台的 DNS 主機設定為我們自建的 DNS Server,以 HiDomain 為例,登入後我們可以點選 “我的網域” 進入網域資訊頁面,然後點選 “更新DNS主機”,將我們自建的 DNS Server 的 IPv4 及 IPv6 位址 (如果有的話) 輸入頁面後按下儲存即可。

以上就完成了一個簡單的 DNS Sever !