前言廢話
自從第一次使用過 Amazon Cloudfront 後,就發現他的 DNS 是使用 GeoDNS,與一般如 Cloudflare Anycast 的不同,這種 GeoDNS 會依照用戶的地理位置來響應不同的 IP 位址。
我個人認為這個東西的用途非常廣泛,舉例遊戲來說,可以針對不同國家、ASN 的用戶,將其指向不同節點或是代理伺服器,進而增加網路品質。
不過市面上可以用到的 GeoDNS 幾乎都是付費方案,就算想體驗玩玩也不符合效益。因此,就讓我找到了 Github 上的 這個 項目。
成本
這篇文章介紹的工具,你在哪邊都能架,但不代表完全沒有成本。自架意味者你需要擔心要不要租伺服器、自動擴充、負載平衡、會不會被攻擊、備份及自行維護等等問題。此篇高度建議你對 DNS 已經有一定知識的人再來玩玩,初心者請繞道。
準備環境
更新系統。
sudo apt-get -y update
操作過程中,我們需要 wget、git、vim。
sudo apt-get install wget git vim
由於他是使用 golang 寫的,我們必須要先準備 golang,你可以參考以下又或是 官方最新版本的教學。
sudo wget https://go.dev/dl/go1.20.5.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.20.5.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
go version
安裝 GeoDNS
由於我喜歡放在 /var
,所以我們在該目錄開始操作。
cd /var
接著操作 git 取得檔案並 build。
git clone https://github.com/abh/geodns.git
cd geodns
go build
取得 GeoIP 資料
既然我們是使用 GeoDNS,我們當然也要每個 IP 位址的 國家、城市、ASN 囉!
這個 GeoDNS 使用 MaxMind 的 IP 資料庫,取得方式你可以到 這裡 查看,這裡就不多贅述。
檔案應為 .mmdb
的副檔名,請將下載完的資料放到 /usr/local/share/GeoIP/
,資料夾若不存在請自行建立。
如果你對他完全沒概念,你對這些可能真的還沒有基礎,請繞道。
編輯 DNS 紀錄
到 /var/geodns/dns
底下,我們先處理 geodns.conf.sample
這個檔案,基本上內容不用改動,直接將他重新命名為 geodns.conf
即可。
sudo mv geodns.conf.sample geodns.conf
接著,我們需要建立一個檔案,檔名取決於你的網域名稱,假設說你想使用 geo.example.com
這個域名,則建立 geo.example.com.json
檔案。
sudo vim geo.example.com.json
內容大概如下:
{
"serial": 3,
"ttl": 10,
"targeting": "country continent @ regiongroup region ip asn",
"data": {
"": {
"ns": {"geo.example.com": null}
},
"test": {
"a": [["1.1.1.1"]]
},
"test.tw": {"a": [["2.2.2.2"]]},
"test.as3462": {"a": [["3.3.3.3"]]},
"test.europe": {"a": [["4.4.4.4"]]},
"test.[192.168.0.1]": {"a": [["5.5.5.5"]]}
}
}
上述的文件基本上意思是:
test.geo.example.com
的預設回應 IP 為 1.1.1.1
。
當來源的國家為 tw
,則回應 2.2.2.2
。
當來源的 ASN 是 as3462
,則回應 3.3.3.3
。
當來源的地區為 europe
(歐洲地區),則回應 4.4.4.4
。
當來源的 IP 為 192.168.0.1
,則回應 5.5.5.5
。
這是一些基本的使用,詳細設定你可以到 Github 上了解。
建立服務
接著,我們將他打包成一個服務,我們在 /lib/systemd/system
建立 geodns.service
檔案。
sudo vim /lib/systemd/system/geodns.service
內容如下:
[Unit]
Description=GeoDNS
After=multi-user.target
[Service]
Type=simple
WorkingDirectory=/var/geodns
ExecStart=/var/geodns/geodns -port 53
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
存檔後退出,輸入以下指令讓服務生效。
sudo systemctl daemon-reload
現在你可以使用以下命令來控制這個服務。
sudo systemctl start geodns.service #啟動服務
sudo systemctl restart geodns.service #重新啟動服務
sudo systemctl stop geodns.service #停止服務
sudo systemctl enable geodns.service #開機自動執行此服務
sudo systemctl disable geodns.service #開機不執行此服務
後續步驟
你需要將你的網域使用 NS
紀錄指向這台主機,來解析網域。
一樣,我在這裡不多介紹,因為他是對 DNS 維護非常基本的操作。
接著可以透過 ping.sx 測試你的結果囉!
結語
這就是一個簡易的 GeoDNS 架設。說真的,作為 Nameserver 主機,你需要注意非常多事情,例如最好支援 IPv6。
GeoDNS 非常仰賴 EDNS 或是 ECS 這些東西,所以用戶使用的公共 DNS 也必須要支援,才能使其正確解析。像是 8.8.8.8
就能解析的非常好,而不支援 EDNS 的 1.1.1.1
則解析的非常糟糕。