all-in-one 3 (dynamic ip script)
ทำเรื่อง dynamic dns client
สมมุติว่าได้สมัครเป็นสมาชิก ddns client ไว้ที่ www.zoneedit.com และ www.everydns.net ไว้เรียบร้อยแล้ว การนี้เราจะใช้ทั้งคู่ในการเป็น name server ให้เรา กันเหนียวไว้ เวลาอันไหนตาย อีกอันจะได้ทำหน้าที่แทน
(อย่าลืมใส่ค่า name server ให้เป็นทั้งคู่ ตอนจดทะเบียนโดเมนด้วย)
จากประวัติพบว่า zoneedit เสถียรและอัปเดตเร็วกว่า เราจึงให้ขึ้นเป็น primary
งานที่ต้องทำคือ
- สคริปต์ดูเลขไอพีจากเราเตอร์ หรืออาจให้เริ่มการทำงานเราเตอร์ใหม่
- สคริปต์ cron ที่จะตรวจไอพีมาเก็บไว้เป็นระยะ ทุก 5 นาที ถ้าไม่เท่าเก่าจึงสั่งอัปเดต แบบอัปเดตทุกโซน
- สคริปต์ cron ที่จะตรวจไอพีซ้ำ จาก dns ภายนอก ทุกครึ่งชั่วโมง ถ้าไอพีไม่ตรงค่อยสั่งอัปเดต เฉพาะโซนที่ไม่ตรง
- สคริปต์อัปเดต แบบมีอาร์กิวเมนต์ต่อท้ายว่าจะให้อัปเดตทั้งหมด หรือเฉพาะราย
เตรียมไดเรกทอรีก่อน
# mkdir -p /sys1/sysb/etc/ddns # ln -sf /sys1/sysb/etc/ddns /etc
สคริปต์ดูเลขไอพีจากเราเตอร์
ตั้งชื่อว่า d.router-getip เอาไว้ใน /usr/local/sbin
โดยถ้ามีอาร์กิวเมนต์ต่อท้ายว่า "RESET" จะสั่งให้เราเตอร์เริ่มการทำงานใหม่ สำหรับใช้ในกรณีที่เราเตอร์ฝั่งเราหรือฝั่งไอเอสพีเกิดอาการแฮงก์ (ต้องปรับสคริปต์ตามเราเตอร์ที่ใช้นะครับ)
# vi /usr/local/sbin/d.router-getip
#!/bin/bash
USER="ROUTER_ADMIN"
PASSWORD="ROUTER_PASSWORD"
IPAB="58.9" #OUR FIRST 2 DIGIT OF IP NUMBER
ROUTERNAME="192.168.5.1"
if [ "$1" == "RESET" ]; then
ADDRESS="http://$ROUTERNAME/rebootinfo.cgi"
wget -o /dev/null -O - \
--http-user="$USER" \
--http-passwd="$PASSWORD" \
"$ADDRESS"
echo "RESET ROUTER"
else
ADDRESS="http://$ROUTERNAME/wancfg.cmd?action=view"
IP_ADDR=`wget -o /dev/null -O - \
--http-user="$USER" \
--http-passwd="$PASSWORD" \
"$ADDRESS" \
| grep $IPAB \
| cut -d ">" -f 2 \
| cut -d "<" -f 1`
echo $IP_ADDR
fi
กำหนดสิทธิ์ให้ root ดูได้เท่านั้น เพราะมีรหัสผ่านอยู่ในสคริปต์
# chmod 700 /usr/local/sbin/d.router-getip
สคริปต์ cron ที่จะตรวจไอพีมาเก็บไว้เป็นระยะ ทุก 5 นาที
ตั้งชื่อว่า d.router-cron-checkip เอาไว้ใน /usr/local/sbin
การทำงานคือ ถ้าอ่านค่าไอพีจากเราเตอร์ไม่ได้ (อาจเกิดจากเราเตอร์ของเราหรือของไอเอสพีแฮงก์) จะสั่งรีเซ็ตเราเตอร์ใหม่
# vi /usr/local/bin/d.router-cron-checkip
#!/bin/bash
DATA="/etc/ddns/router-ip"
OLD_IP=`cat $DATA`
CUR_IP=`/usr/local/sbin/d.router-getip`
#SOLVE ROUTER (OR ISP?) IS HUNG
if [ ! $CUR_IP ]; then
/usr/local/sbin/d.router-getip RESET
fi
#TEST BETWEEN SAVED-IP AND NEW-READ-IP
if [ "$OLD_IP" != "$CUR_IP" ]; then
echo $CUR_IP > $DATA #SAVE NEW IP
/usr/local/sbin/d.router-reconnect
fiกำหนดสิทธิ์ให้รันได้
# chmod 700 /usr/local/bin/d.router-cron-checkip
ตั้ง cron ทุก 5 นาที (ถ้าคุณภาพสายไม่ดี อาจตั้งค่าให้บ่อยขึ้นก็ได้ครับ)
# crontab -e
... #CHECK ROUTER IP ADDRESS EVERY 5 MIN */5 * * * * /usr/local/bin/d.router-cron-checkip ...
ในครั้งแรก ที่ยังไม่มีไฟล์ router-ip ต้องสร้างก่อน เพียงครั้งเดียว
# d.router-getip > /etc/ddns/router-ip
สคริปต์ cron ที่จะตรวจไอพีซ้ำ จาก dns ภายนอก ทุกครึ่งชั่วโมง
สร้างไฟล์ข้อมูลโดเมนเอาไว้ที่ /etc/ddns (เลียนแบบการวางไฟล์จาก apache2)
โดยเราจะเขียนไฟล์คอนฟิกเอาไว้ใน /etc/ddns/ddns-available และเมื่อเสร็จแล้วก็โยงลิงก์เข้าไปที่ /etc/ddns/ddns-enabled
(วิธีนี้ทำให้ปรับแต่งไฟล์ง่าย อันไหนที่ทดสอบแล้วว่ายังไม่เรียบร้อย ก็แค่ลบลิงก์ไป)
สคริปต์จะเข้าไปอ่านไฟล์คอนฟิกจากในไดเรกทอรี /etc/ddns/ddns-enabled
# mkdir -p /etc/ddns/{ddns-available,ddns-enabled}
สมมุติว่าเราจดทะเบียนไว้ที่ zoneedit.com และ everydns.net ไว้ 2 โดเมน
คือ example.com และ example.org
ตัวอย่างไฟล์คอนฟิก จะเป็นดังนี้
# vi /etc/ddns/ddns-available/zoneedit
#ZONEEDIT DATA USER="ZONEEDIT-USER" PASSWORD="ZONEEDIT-PASSWORD" #UPDATE_DOMAIN="DOMAIN:NAME-SERVER, ... " #NO SPACE IN FIELD UPDATE_DOMAIN=" example.com:ns13.zoneedit.com example.org:ns2.zoneedit.com"
# vi /etc/ddns/ddns-available/everydns
#EVERYDNS DATA USER="EVERYDNS-USER" PASSWORD="EVERYDNS-PASSWORD" #UPDATE_DOMAIN="DOMAIN:NAME-SERVER, ... " #NO SPACE IN FIELD UPDATE_DOMAIN=" example.com:ns2.everydns.net example.org:ns2.everydns.net"
ต้องระวัง พยายามอย่าพิมพ์ผิด เพราะข้อมูลในนี้คือตัวแปรในสคริปต์โดยตรง ไม่มีการตรวจสอบความถูกต้องจากสคริปต์อีกแล้ว
โยงลิงก์ เพื่อเปิดใช้งาน
# ln -sf /etc/ddns/ddns-available/* /etc/ddns/ddns-enabled
ต่อไปสร้างสคริปต์ชื่อ d.router-cron-checkddns เอาไว้ที่ /usr/local/sbin เพื่อตรวจสอบไอพีของเราจากผู้ให้บริการ
# vi /usr/local/sbin/d.router-cron-checkddns
#!/bin/bash
#CRON SCRIPT FOR TEST IP FROM PROVIDER.
#KNOWN PROVIDER:
# zoneedit.com
# everydns.net
#
#PUT PROVIDERS DATA FILE IN /etc/ddns/ddns-available.
#MAKE LINK TO /etc/ddns/ddns-enabled TO ENABLE.
#DEFAULT DIRECTORY CONTAIN DDNS PROVIDERS DATA
DIR="/etc/ddns/ddns-enabled"
#GLOBAL VAR
CUR_IP=`/usr/local/sbin/d.router-getip`
UPDATE_SCRIPT="/usr/local/sbin/d.router-updatezone"
for PROVIDER in `ls -1 $DIR`; do
#GET VARIABLE: $USER,$PASSWORD,$UPDATE_DOMAIN
. $DIR/$PROVIDER
for i in $UPDATE_DOMAIN; do
DOMAIN=`echo $i | cut -d: -f1`
NAME_SERVER=`echo $i | cut -d: -f2`
TEST_IP=`nslookup $DOMAIN $NAME_SERVER | grep -v "#" | grep Address | cut -d\ -f2`
if [ "$TEST_IP" != "$CUR_IP" ]; then
$UPDATE_SCRIPT $PROVIDER
fi
done
done
ทำให้รันได้
# chmod 700 /usr/local/sbin/d.router-cron-checkddns
ตั้ง cron ทุก 30 นาที
# crontab -e
... #CHECK DOMAIN IP ADDRESS EVERY 30 MIN */30 * * * * /usr/local/sbin/d.router-cron-checkddns ...
สคริปต์อัปเดต
เป็นการสั่งอัปเดต โดยนำค่าจากข้อมูลในไฟล์คอนฟิกข้างบน คือใน /etc/ddns/ddns-enabled มาอัปเดต ชื่อไฟล์คือค่าอาร์กิวเมนต์ของสคริปต์ ยกเว้นถ้าใส่ -a จะหมายถึง all คืออัปเดตทุก ๆ ผู้ให้บริการ
การทำงานของสคริปต์จะแบ่งเป็น 2 จังหวะ คือในครั้งแรกจะอัปเดตรวดเดียวกับทุกโดเมน เมื่อเสร็จเรียบร้อยแล้วจะย้อนกลับมาตรวจสอบอีกครั้งนึงว่า ในแต่ละโดเมนรายงานค่าไอพีถูกต้องหรือไม่ ถ้าไม่ถูกก็จะเว้นไป 5 วินาที แล้วเชื่อมต่อใหม่เป็นจำนวน 10 รอบการทำงาน
สร้างสคริปต์ชื่อ d.router-updatezone เอาไว้ที่ /usr/local/sbin ในการอัปเดตเมื่อไอพีเปลี่ยน
# vi /usr/local/sbin/d.router-updatezone
#!/bin/bash
#SCRIPT FOR UPDATE DNS RECORD.
#KNOWN PROVIDER:
# zoneedit.com
# everydns.net
#
#PUT PROVIDERS DATA FILE IN /etc/ddns/ddns-available.
#MAKE LINK TO /etc/ddns/ddns-enabled TO ENABLE.
#DATA FILE FORMAT:
# USER="user"
# PASSWORD="password"
# UPDATE_DOMAIN="
# example.com:ns1.zoneedit.com
# example.com:ns2.zoneedit.com"
if [ ! $1 ]; then
PROG=`basename $0`
echo "Usage: $PROG [-a=all | ddns_provider_file]"
exit
fi
#DEFAULT DIRECTORY CONTAIN DDNS PROVIDERS DATA
DIR="/etc/ddns/ddns-enabled"
if [ "$1" == "-a" ]; then
DDNS_ENABLED=`ls -1 $DIR`
else
DDNS_ENABLED=$1
fi
#GLOBAL VAR
IP_ADDR=`/usr/local/sbin/d.router-getip`
#FIRST FAST UPDATE
fastupdate() {
ADDRESS=$1
DOMAIN=$2
USER=$3
PASSWORD=$4
echo "$DOMAIN fast update ..."
wget -O - --http-user=$USER --http-passwd=$PASSWORD "$ADDRESS"
}
#SECOND RECHECK & UPDATE
recheck() {
ADDRESS=$1
DOMAIN=$2
NAME_SERVER=$3
USER=$4
PASSWORD=$5
echo "$DOMAIN recheck with $NAME_SERVER ..."
TEST_IP=`nslookup $DOMAIN $NAME_SERVER | grep -v "#" | grep Address | cut -d \ -f 2`
echo "REAL_IP=$IP_ADDR , TEST_IP=$TEST_IP"
I=0
LOOP=10
while [ $I -lt $LOOP ] && [ "$IP_ADDR" != "$TEST_IP" ] ; do
wget -O - --http-user=$USER --http-passwd=$PASSWORD $ADDRESS
sleep 5
echo "ROUND=$I , NAME_SERVER=$NAME_SERVER , REAL_IP=$IP_ADDR , TEST_IP=$TEST_IP"
TEST_IP=`nslookup $DOMAIN $NAME_SERVER | grep -v "#" | grep Address | cut -d \ -f 2`
I=$[$I+1]
done
}
#BEGIN MAIN
#1.FAST UPDATE
for PROVIDER in $DDNS_ENABLED; do
#GET VARIRABLE $USER,$PASSWORD,$UPDATE_DOMAIN
. $DIR/$PROVIDER
for i in $UPDATE_DOMAIN; do
DOMAIN=`echo $i | cut -d: -f1`
case $PROVIDER in
zoneedit)
ADDRESS="http://dynamic.zoneedit.com/auth/dynamic.html?host=$DOMAIN"
;;
everydns)
ADDRESS="http://dyn.everydns.net/index.php?ver=0.1&domain=$DOMAIN"
;;
esac
fastupdate $ADDRESS $DOMAIN $USER $PASSWORD
done
done
#WAIT 30 SECONDS BEFORE RECHECK
sleep 30
#2.RECHECK
for PROVIDER in $DDNS_ENABLED; do
#GET VARIABLE $USER,$PASSWORD,$UPDATE_DOMAIN
. $DIR/$PROVIDER
for i in $UPDATE_DOMAIN; do
DOMAIN=`echo $i | cut -d: -f1`
NAME_SERVER=`echo $i | cut -d: -f2`
case $PROVIDER in
zoneedit)
# NEW wget , USED WHEN dynamic.zoneedit.com IS DOWN OR THIS MACHINE STAY BEHIND FIREWALL
ADDRESS="http://www.zoneedit.com/auth/dynamic.html?host=$DOMAIN&type=A&dnsto=$IP_ADDR"
;;
everydns)
# WITH IP, SUITABLE FOR MACHINE BEHIND FIREWALL
ADDRESS="http://dyn.everydns.net/index.php?ver=0.1&ip=$IP_ADDR&domain=$DOMAIN"
;;
esac
recheck $ADDRESS $DOMAIN $NAME_SERVER $USER $PASSWORD
done
done
กำหนดสิทธิ์ให้รันได้
# chmod 700 /usr/local/sbin/d.router-updatezone
สคริปต์รวมในการบันทึกไอพีใหม่และสั่งอัปเดต
สคริปต์นี้แทบไม่มีอะไร เพียงแต่ไปเรียกใช้สคริปต์อัปเดตข้างบน เพียงแต่ใส่พารามิเตอร์เป็น -a (อัปเดตทุกผู้ให้บริการ) เท่านั้น
แต่ว่าต้องสร้างสคริปต์นี้ไว้ เพราะเราจะต้องเชื่อมโยงกับการอัปเดต bind9 ที่จะติดตั้งต่อไป
ตั้งชื่อว่า d.router-reconnect เอาไว้ใน /usr/local/sbin
# vi /usr/local/sbin/d.router-reconnect
#!/bin/bash #UPDATE ALL ENABLED ZONE #KILL OLD PROCESS killall d.router-updatezone #UPDATE ALL ZONE /usr/local/sbin/d.router-updatezone -a #-------ADDITIONAL BIND9 SCRIPT:------------------
เสร็จแล้ว













Post new comment