以上是開放讓 127.0.0.1 進行動態更新,動態更新有其指令,詳細您可看看 nsupdate man page (man nsupdate),以下僅以最常用的進行說明:
CODE:
#nsupdate [root@eai1 dyndns]# nsupdate > server 127.0.0.1 > zone dyndns.twnic.tw > update delete user1.dyndns.twnic.tw A 211.72.210.249 > update add user1.dyndns.twnic.tw A 211.72.210.251 ttl 'A': not a valid number # 這個例子是錯誤示範,加一筆記錄要有 TTL 值 > update add user1.dyndns.twnic.tw 60 A 211.72.210.251 > show Outgoing update query: ;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 0 ;; flags: ; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0 ;; UPDATE SECTION: user1.dyndns.twnic.tw. 0 NONE A 211.72.210.249 user1.dyndns.twnic.tw. 60 IN A 211.72.210.251
> send > quit
CODE:
server 指向某一台 NameServer 進行 update 操作 zone 修改某個 zone file update delete 進行 update 的 delete 動作,這個指令格式是 update delete FQDN TYPE RDATA,如果有多筆相同的 A 記錄或不同的 MX 記錄要刪除某一筆需將 RDATA 補上, 若沒有 RDATA 則表示這個 FQDN 的這個 TYPE 都要刪除 (TYPE 即是 A,MX,PTR,SOA,NS..等,RDATA 就是 TYPE 後 接的東西,如 A 的 RDATA 是 IP 而 MX 的 RDATA 是 優 先權 FQDN) update add 進行記錄的增加,操作如同 delete, 但是一定要有 TTL 值,且必需明確寫出 RDATA show 這只是操作後要顯示進行了那些 update 指令 send 這個代表要把整個 update 指令送給 server,操作 update 時資料不是馬上送出的,所以 update 可以很多行,最後 nsupdate 看到 send 時,才會將整個所有 update 送出, 而 update 使用 port 53/udp 若送出的資料量 (DNS packet) 大於 512 bytes,則會 truncate 而改使用 53/tcp,這是您 需要注意的地方,而只要您有 send, 則 SOA 記錄的 serial 會自動加1,以期讓 slave 來進行同步,所以過多的 send 可 能造成過多的 traffic
2.1.2 zone file 及日誌檔 如果您進行了 nsupdate 的操作,則原來 directory 所指的目錄將會產生一些日誌檔,這個日誌檔即為 zone_name.jnl (directory 習慣上都設在 /var/named , 您自己必要注意 named 程式要有寫入的權限, chroot 狀況等)
CODE:
# 顯示 dyndns.twnic.tw zone file 內容 [root@eai1 named]# cat /var/named/dyndns.twnic.tw $TTL 86400 ; 1 day @ IN SOA twnic.net.tw. snw.twnic.net.tw. ( 2006073267 ; serial 7200 ; refresh (2 hours) 1800 ; retry (30 minutes) 2419000 ; expire (3 weeks 6 days 23 hours 56 minutes 40 seconds) 300 ; minimum (5 minutes) ) NS ns2.dyndns.twnic.tw. NS eai1.twnic.tw. ns2 A 203.73.24.204 ; 如果別人在查詢時,我們有這個記錄則回應這個記錄的 IP,若沒有這個記錄代表 ; 這個網站沒有上線,所以此時我們可以建立一筆 wildcard 記錄,指向自己的說 ; 明網站,以供 user 識別這個網站沒有上線,而這筆 wildcard 的記錄 TTL 時間 ; 不能太長,以免別的 DNS Cache 了這資料 * 0 A 211.72.210.251
# 目錄裏的東西 [root@eai1 named]# ls -la /var/named/ 總計 128 drwxr-xr-x 2 named named 4096 7月 27 09:25 . drwxr-xr-x 20 root root 4096 3月 13 16:50 .. -rw-r--r-- 1 named named 451 7月 27 09:25 dyndns.twnic.tw -rw-r--r-- 1 named named 104177 7月 27 10:01 dyndns.twnic.tw.jnl -rw-r--r-- 1 named named 195 7月 4 2001 localhost.zone -rw-r--r-- 1 named named 2851 10月 17 2003 named.ca
我們可以看到這個 .jnl 的產生,這個 .jnl 檔是不能隨便刪除,因為它等於是 dyndns.twnic.tw 的補 充資料,而這些補充資料在 DNS reload/restart 時, named 還會在把它讀進來,所以動態更新後的資料, 並不會隨著 dns 重啟後而消失,如果你想讓現在整個 zone 檔出現所有的記錄,那可以 rndc stop 來停止 dns, 此時 named 會把 .jnl資料寫入原來的 zone file,不過這種方式一般來說較不建議,因為我們的 zone file 只要存一個樣版 (template),其他的東西都是臨時性的. 而若你想知道現在整個 zone 的內容,在可 以做 zone transfer 的主機上(如上例為 slave_ip及 127.0.0.1), 以 dig 指令來執行 axfr:
; <<>> DiG 9.3.0 <<>> @127.0.0.1 dyndns.twnic.tw axfr ;; global options: printcmd dyndns.twnic.tw. 86400 IN SOA twnic.net.tw. snw.twnic.net.tw. 2006073528 7200 1800 2419000 300 dyndns.twnic.tw. 86400 IN NS ns2.dyndns.twnic.tw. dyndns.twnic.tw. 86400 IN NS eai1.twnic.tw. *.dyndns.twnic.tw. 0 IN A 211.72.210.251 ns2.dyndns.twnic.tw. 86400 IN A 203.73.24.204 user1.dyndns.twnic.tw. 60 IN A 211.72.210.248 user1.dyndns.twnic.tw. 60 IN MX 10 user1.dyndns.twnic.tw. # 以下略 ...
2.設定 NameServer 僅進行差異化的同步 Master/Slave 要進行 zone file 的同步,而 ddns server 若只有一部是可以不用考慮這些問題的,但是若有兩 部以上的 DNS Server, 就需要考慮到同步的進行方式,若 zone file 的總資料量小,採用什麼同步方式是無所 謂的,但若資料量多,或是經常處在變動狀況,那差異化的同步就會顯得很重要,因為它可以讓所有的 DNS 在短時 間內全部同步完成,BIND 支援 IXFR 後,其預設即是採用 IXFR, 若沒有 IXFR (update) 時,則採用 AXFR,所以不 需要對 IXFR 進行額外設定,但為使大家了解其參數,本處還是舉例來進行說明,好讓大家能夠更了解
if [ -n "$QUERY_STRING" ];then # 取得 QUERY_STRING,以下這個作法是危險的,因為沒有檢查資料的正確性就 eval # 我的用意只在於說明作法 eval `echo "$QUERY_STRING" | sed "s/&/;/g"` # 讀取設定檔,這個路徑您需要自行調整 eval `cat /home/abelyang/dyndns/dyndns.cfg ` sql0="select 1 from USER where USERNAME='$LOGIN' and PASSWD='$PASSWD'" res=`echo $sql0 | $MYSQL ` # 如果 USER 密碼正確, ${#res} 應為2,不對則為 0 if [ ${#res} -lt 1 ];then echo "Login Failure" else # 取得 IP, 需判斷有 Proxy 存在,但是不考慮 Proxy 後是 NAT 情形 IP=${HTTP_X_FORWARDED_FOR:-$REMOTE_ADDR} FQDN="$LOGIN.$DOMAIN" # 刪除上一次的登入 sql1="delete from RR where USERNAME='$LOGIN'" # 預設的動態更新項目為 A/MX sql2="insert into RR(USERNAME,FQDN,TYPE,RDATA) values('$LOGIN','$FQDN','A','$IP')" sql3="insert into RR(USERNAME,FQDN,TYPE,RDATA) values('$LOGIN','$FQDN','MX','10 $FQDN')" echo $sql1 | $MYSQL echo $sql2 | $MYSQL echo $sql3 | $MYSQL echo $LOGIN login success @$IP fi else # 以下只是網頁的部份,我沒有做 DDNS 申請,這個部份我想只要懂網頁的朋友應該都會才是 cat <
EOF
fi
3.4 dyndns-cron.sh 定時產生 nsupdate 這隻程式主要進行讀取 Table RR , 並產生 nsupdate 所需要的指令格式後執行 nsupdate, 程式預設 每15秒執行一次(參數如上 dyndns.cfg 中的 UPD_FREQ 更新頻率),您可以拿掉 while [ 1 ] 的迴圈, 改用 crontab 方式來跑,不過這樣就較不容易控制一分鐘以內的更新頻率了,最後,這個程式會把 SOA 的序號改成更新時間,這個時間是 UTC 的秒數(意即 1970/1/1 至今秒數, date +%s 可得),由 SOA 的 序號就可以知道最後的 update 時間,這個原理和 .com 的verisign 或是 dyndns 中的 dyndns.org/ noip.com 是相同的.
另外,根據 RR_VALID 參數,若 USER 的登錄時間 小於 現在時間-RR_VALID (秒數),則該 Record 視同 離線,所以我們需要進行 delete 動作
CODE:
#!/bin/sh
while [ 1 ] do # 您必需調整路徑,放在 while loop 裏是要讓修改了設定檔即可生效,若不要可放在 while 之外 eval `cat /home/abelyang/dyndns/dyndns.cfg` cat < $CMD_FILE server $DYNDNS_MASTER zone $DOMAIN EOF
# 取得這段時間內有上來更新的 USER,這個部份不檢查 IP 不變動情形 # 主要因為 nsupdate 巳執行很快,而且 named 它自己會檢查重覆更新的東西 echo "select FQDN,TTL,TYPE,RDATA from RR where CREATE_TIME between $last and $now" | $MYSQL| grep -v 'RDATA' | while read FQDN TTL TYPE RDATA RDATA2 do