…生活與工作…個人的生活雜記….
Container Station

自動更新非固定制ipv6 DNS

本網站一直都有使用ipv6,也一直嚐試利用ipv6提供網頁服務,但是也不知道是HINET小氣還是技術瓶頸,說好的一顆沙子都有IPV6位置的固定IPV6服務一直沒有普及。

雖然之前嘗試使用HINET所提供的IPv6 reverse proxy服務,但是因為https的認證無法通過而取消。

這次利用QNAP架設BIND伺服器,並使用nsupdate功能建立可以自動更新ipv6位置的DNS服務。

需要的軟體可以利用QNAP的Container Station建立。這次使用LXC的Ubuntu 18.04 LTS。

Container Station建立與環境設定請參考相關的QNAP Q&A

Container Station
Container Station

安裝軟體

軟體使用BIND,目前都是BIND9了,至於細項版本的話,因為只服務一台機器就不用挑剔了。

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install bind9 -y

安裝好之後先確認一下BIND有沒有順利啟動並且監聽PORT 53

netstat -anl |grep 53

tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:953           0.0.0.0:*               LISTEN
tcp6       0      0 :::53                   :::*                    LISTEN
tcp6       0      0 ::1:953                 :::*                    LISTEN
udp        0      0 127.0.0.1:53            0.0.0.0:*
udp        0      0 127.0.0.53:53           0.0.0.0:*
udp6       0      0 :::53                   :::*

重新啟動服務的方式

sudo service bind9 restart

很重要,因為熟悉度與重啟次數會有相關(笑

如果出現錯誤或是BIND沒有反應的查詢方式

sudo tail -50 /var/log/syslog

syslog是最好用的,有沒有錯誤一看就知道,至於其他的方式像是 sudo service bind9 status 或是 named-checkzone 則是看看就好。

建立nsupdate需要的密鑰

HOST後面的名稱是為了辨別,取名不是很重要。加密的方式有很多種可以選擇,像DH (Diffie Hellman)、HMAC-MD5、HMAC-SHA1、HMAC-SHA224、HMAC-SHA256、HMAC-SHA384或HMAC-SHA512。

我這邊是使用HMAC-SHA512,長度為512bits。

cd /etc/bind
sudo dnssec-keygen -a HMAC-SHA512 -b 512 -n HOST est.idv.tw.

完成後在路徑下建立2個檔案,其中的private檔是我們需要的。

Kest.idv.tw.+165+54877.key
Kest.idv.tw.+165+54877.private

sudo cat Kest.idv.tw.+165+54877.private

Private-key-format: v1.3
Algorithm: 165 (HMAC_SHA512)
Key: b3twery534546hgwe4g43wg54y46u7jhghtrshdf54dyw2a3rtes-05oylperw34534ertertertewrtyb2r057A==
Bits: AAA=
Created: 20201221022842
Publish: 20201221022842
Activate: 20201221022842

其中的 Algorithm 跟 Key 先記錄下來,並貼在 named.conf.default-zones 裡面。

sudo vi /etc/bind/named.conf.default-zones

// prime the server with knowledge of the root servers
...中略...
key "est.idv.tw." {
        algorithm hmac-sha512;    <--- Algorithm填這邊
        secret "b3twery534546hgwe4g43wg54y46u7jhghtrshdf54dyw2a3rtes-05oylperw34534ertertertewrtyb2r057A==";  <--- Key填這邊
};
...中略...
//這邊是你的正解檔位置
zone "est.idv.tw" {
        type master;
        file "/etc/bind/est.idv.tw.fwd";
        allow-query { ANY; };	     <--- 允許誰更新
        update-policy {
                grant est.idv.tw. name est.idv.tw. AAAA;    <--- 只允許AAAA更新
        };
};

...後略...
//這邊就是你的反解檔,但是不需要去動他。

建立好之後可以先restart一次看看有沒有錯誤,通常的錯誤是 “;” 或是 “.” 忘記打。另外就是 update-policy 跟 allow-update 是不能一起使用的。

nsupdate 使用

nsupdate依附在dnsutils 內,所以必須安裝dnsutils在web server(如果是跟BIND安裝在同一SERVER就不用執行這步驟)。

sudo apt-get -y install dnsutils

用法:

nsupdate [-dv] [-y keyname:secret | -k keyfile] [-t timeout] [-u udptimeout] [-r udpretries] [filename]

參數 -d 是debug模式。

參數 -v 是使用TCP方式更新,這樣在更新失敗時會一直重複嚐試直到成功。如果使用UDP則會有下列參數 -t 逾時 、-u 重試間格、-r 重試次數 可使用。

參數 -y 是key值,以 : 來做為分隔,使用法必須依照 加密方式 : key名稱: 密鑰 的方式填入。不建議使用 –y 選項,因為共享密鑰作為命令行參數以明文形式提供,可以在 ps(1)的輸出中或用戶 shell 維護的歷史文件中看到。

參數 -k 則是從文件 keyfile 讀取密鑰,其名稱格式為 K{name}.+165.+{random}.private。由於歷史原因,還必須存在文件 K{name}.+165.+{ random}.key。

先手動更新試試看:

nsupdate -v -k  Kest.idv.tw.+165+54877.private
update del est.idv.tw. AAAA
update add est.idv.tw. 60 AAAA 2001:b011:7c05:14ee::1002
send

正常執行不會出現訊息,若是出現

; TSIG error with server: tsig indicates error
update failed: NOTAUTH(BADKEY)
named[58]: client @0x7fe2d412c640 122.116.254.160#29079: request has invalid signature: TSIG hmac-sha512: tsig verify failure (BADKEY)

是密鑰錯誤,可能是打到空白或是加密方式搞錯,可以從syslog看到詳細錯誤訊息。

如果是出現

update failed: REFUSED
named[1363]: client @0x7f8fe4101460 122.116.254.160#38651/key est.idv.tw: updating zone 'est.idv.tw/IN': update failed: rejected by secure update (REFUSED)

查一下是不是 “.” 忘記了。

如果是出現

update failed: SERVFAIL

則必須先看一下syslog,有可能是權限問題造成。只須把目錄更新為775就可以了。等jnl檔建立後即可改回原來的權限。

 named[1395]: client @0x7f4b2810fa80 122.116.254.160#2783/key est.idv.tw: updating zone 'est.idv.tw/IN': deleting rrset at 'est.idv.tw' AAAA
named[1395]: /etc/bind/est.idv.tw.fwd.jnl: create: permission denied
named[1395]: client @0x7f4b2810fa80 122.116.254.160#2783/key est.idv.tw: updating zone 'est.idv.tw/IN': error: journal open failed: unexpected error

確定手動方式可以正常更新之後就可以使用自動執行了

Shell Script

sudo vi ipv6ddns.sh

#!/usr/bin/env bash

#安裝路徑
INSTALLPATH="檔案路徑"

# NS名稱
HOST="xx.yy.zz."

#nsupdate用參數
KEYPATH="Kxyz+165+random.private檔名"

# DNS SERVER IP 有裝BIND那台
DNSSERVER="1.2.3.4"

#取得現在IPv6位置
IP=`dig -6 TXT +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'"' '{ print $2}'`

#記錄在DNS伺服器上的位置
PRIIP=`dig +short @168.95.192.1 $HOST AAAA`

if [ "$IP" != "$PRIIP" ];
then
        echo "server $DNSSERVER" > $INSTALLPATH/nsupdate_update
        echo "update delete $HOST AAAA" >> $INSTALLPATH/nsupdate_update
        echo "update add $HOST 60 AAAA $IP" >> $INSTALLPATH/nsupdate_update
        echo "send" >> $INSTALLPATH/nsupdate_update
        echo "answer" >> $INSTALLPATH/nsupdate_update
        echo "IP已變更,更新AAAA紀錄..."
        nsupdate -v -k ${KEYPATH} $INSTALLPATH/nsupdate_update > /var/log/nsupdate.log 2>&1
else
        echo "無需更新..."
fi

然後將ipv6ddns.sh、private檔、key檔放在同一目錄,並確定權限。

sudo chmod 744 ipv6ddns.sh
sudo chmod 600 *.key
sudo chmod 600 *.private

執行訊息會存在/var/log/nsupdate.log

確定沒問題後就可以使用cron定期執行。

*/5 * * * * root   PATH/ipv6ddns.sh >/dev/null 2>&1

可以用http://ipv6-test.com/validate.php檢查是不是設定正確。

別忘了要到你的Domain服務商那邊將託管與DNS主機設定好。

DNS主機設定
DNS主機設定