สร้างสคริปต์ DDNS สำหรับเราเตอร์กับงานทำโฮสต์ใช้เอง

จากครั้งก่อนเรื่อง ทำโฮสต์ใช้เอง ยังขาดเนื้อหาว่า ถ้าอุปกรณ์ของเราเป็นเราเตอร์ เราจะมีวิธีในการอัปเดตข้อมูล DNS อย่างไร

กรณีเราเตอร์จะต่างจากกรณีโมเด็ม คือเราไม่สามารถทราบได้ว่าสายจะหลุดเมื่อใด ดังนั้นเราจึงต้องอาศัยการเช็คไอพีเป็นระยะ โดยอาศัยการทำงานของ crontab

การทำงานในขั้นตอนนี้ของแพกเกจสำเร็จรูปทั่วไป จะใช้การตรวจสอบไอพีไปที่ zoneedit เป็นระยะ เช่นทุก ๆ 5 นาที เป็นต้น แต่เนื่องจากเราเขียนสคริปต์เอาเอง เราจึงสามารถประหยัดแบนด์วิดท์ (แม้เพียงน้อยนิด) ได้ โดยแทนที่จะไปตรวจไอพีเอาจาก zoneedit เราก็ตรวจเอาจากเราเตอร์ของเราแทน

Internet  ->  Router  ->  Server:eth1
            192.168.5.1   192.168.5.3
                                |
                                v
                           Server:eth0  -> Internal Network
                           192.168.1.1      192.168.1.0/24

สมมุติว่า

  • ไอพีเราเตอร์ เป็น 192.168.5.1
  • ชื่อผู้ใช้เราเตอร์ชื่อ ADMIN รหัสผ่านเป็น ADMIN-PASSWORD
  • ไอพีของการ์ดแลน eth1 บนเซิร์ฟเวอร์ เป็น 192.168.5.3
  • ไอพีของการ์ดแลน eth0 บนเซิร์ฟเวอร์ เป็น 192.168.1.1

เราสามารถดูไอพีของเราเตอร์ที่เป็นสายนอกได้จากคำสั่ง wget

ตัวอย่างของผมใช้คำสั่ง

# wget -o /dev/null -O - --http-user="ADMIN" --http-passwd="ADMIN-PASSWORD" \
"http://192.168.5.1/wancfg.cmd?action=view"

จะได้ผลลัพธ์ออกมาเต็มไปหมด แต่ในนั้นจะมีหมายเลขไอพีเราอยู่ด้วย

ต่อไปเราจะกรองข้อมูลที่เราไม่ต้องการทิ้ง ให้เหลือแต่เลขไอพี

ตอนนี้เราใช้เทคนิคคือ แม้ว่าไอพีเราจะเปลี่ยนทุกครั้งที่ต่อสายใหม่ แต่ตัวที่ไม่เปลี่ยนคือตัวเลขสองหลักหน้า ดังนั้นเราจะเอาตัวเลขสองหลักหน้ามาเป็นตัวกรอง

เช่นของผมเป็น 58.9.XXX.XXX เราจะเพิ่มการกรองด้วยคำสั่ง grep 58.9

# wget -o /dev/null -O - --http-user="ADMIN" --http-passwd="ADMIN-PASSWORD" \
"http://192.168.5.1/wancfg.cmd?action=view" \
| grep 58.9

ได้ผลลัพธ์เป็น

      <td>58.9.XXX.XXX</td>

เพิ่มการกรองอีกชั้นนึงให้ตัดแท็ก html:td ทิ้ง คำสั่งกลายเป็น

# wget -o /dev/null -O - --http-user="ADMIN" --http-passwd="ADMIN-PASSWORD" \
"http://192.168.5.1/wancfg.cmd?action=view" \
| grep 58.9 | cut -d ">" -f 2 | cut -d "<" -f 1

ได้แล้ว

58.9.XXX.XXX

ถึงตอนนี้เพื่อให้ใช้งานสะดวก และเป็นการปกปิดชื่อและรหัสผ่าน เราจะทำเป็นสคริปต์ เก็บไว้ที่ /usr/sbin ผมตั้งชื่อว่า d.router-getip

# vi /usr/sbin/d.router-getip
#!/bin/bash
CMD="http://192.168.5.1/wancfg.cmd?action=view"
USER="ADMIN"
PASSWORD="ADMIN-PASSWORD"
FIRSTTWODIGIT="58.9"
IP_ADDR=`wget -o /dev/null -O - --http-user=$USER \
  --http-passwd=$PASSWORD $CMD \
  | grep $FIRSTTWODIGIT | cut -d ">" -f 2 | cut -d "<" -f 1` \
  >> /dev/null
echo $IP_ADDR
# chmod 0700 /usr/sbin/d.router-getip

เวลาเรียกใช้ก็สั่ง d.router-getip ก็จะได้ไอพีของ WAN ออกมา

ต่อไปเราจะสร้างสคริปต์ให้มีการตรวจสอบว่าไอพีตรงกับค่าปัจจุบันหรือไม่ ถ้าตรงก็ไม่ทำอะไร แต่ถ้าไม่ตรงก็จะให้ไปเรียกสคริปต์ให้ไปอัปเดต DDNS และเก็บค่าไอพีใหม่ ผมตั้งชื่อไฟล์ว่า d.router-cron-checkip ซึ่งผมเก็บไว้ที่ /usr/local/bin

กรณี zoneedit
# vi /usr/local/bin/d.router-cron-checkip
#!/bin/bash
OLD_IP=`cat /root/router-ip`
CUR_IP=`/usr/sbin/d.router-getip`
if [ $OLD_IP != $CUR_IP ]; then
    echo $CUR_IP > /root/router-ip
    /usr/sbin/d.router-update-zoneedit
fi
# chmod 755 /usr/local/bin/d.router-cron-checkip

สร้างไฟล์อัปเดตเอาไว้ที่ /usr/sbin

# vi /usr/sbin/d.router-update-zoneedit
#!/bin/bash
# SCRIPT FOR ROUTER TO UPDATE DNS RECORD AT zoneedit.com

updatezoneedit() {
    USER=$1
    PASSWORD=$2
    IP_ADDR=$3
    DOMAIN=$4
    HOST=$5
    # NEW wget 48-10-8 USED WHEN dynamic.zoneedit.com IS DOWN
    wget -O - --http-user=$USER --http-passwd=$PASSWORD \
"http://www.zoneedit.com/auth/dynamic.html?host=$DOMAIN&type=A&dnsto=$IP_ADDR"
}

USER="MYUSERNAME"
PASSWD="MYPASSWORD"
DOMAIN1="example.com"
HOST1="www.example.com"
IP_ADDR=`/usr/sbin/d.router-getip`
updatezoneedit $USER $PASSWD $IP_ADDR $DOMAIN1 $HOST1

เสร็จสำหรับ zoneedit

กรณีeverydns
# vi /usr/local/bin/d.router-cron-checkip
#!/bin/bash
OLD_IP=`cat /root/router-ip`
CUR_IP=`/usr/sbin/d.router-getip`
if [ $OLD_IP != $CUR_IP ]; then
    echo $CUR_IP > /root/router-ip
    /usr/sbin/d.router-update-everydns
fi
# chmod 755 /usr/local/bin/d.router-cron-checkip

สร้างไฟล์อัปเดตเอาไว้ที่ /usr/sbin

# vi /usr/sbin/d.router-update-everydns
#!/bin/bash
# SCRIPT FOR ROUTER TO UPDATE DNS RECORD AT everydns.net

updateeverydns() {
    USER=$1
    PASSWORD=$2
    IP_ADDR=$3
    DOMAIN=$4
    HOST=$5
    eDNS.pl -u $USER -p $PASSWORD -ip $IP_ADDR -d $DOMAIN
    eDNS.pl -u $USER -p $PASSWORD -ip $IP_ADDR -d $HOST
}

USER="MYUSERNAME"
PASSWD="MYPASSWORD"
DOMAIN1="example.com"
HOST1="www.example.com"
IP_ADDR=`/usr/sbin/d.router-getip`
updateeverydns $USER $PASSWD $IP_ADDR $DOMAIN1 $HOST1

เสร็จสำหรับ everydns

งานต่อไปคือการตั้งให้ crontab ตรวจสอบค่าไอพีทุก 5 นาที

# crontab -e
...
#CHECK ROUTER IP ADDRESS EVERY 5 MIN
0/5 0-23    * * *   /usr/local/bin/d.router-cron-checkip
...

เสร็จแล้วครับ

เกร็ด

จากตัวอย่าง ผมละเลยที่จะกล่าวถึงการทำตาราง nat เพราะความรู้ไม่พอที่จะอธิบาย จึงขอลงวิธีการไว้ตอนท้ายเพื่อให้สามารถศึกษาต่อได้เองดังนี้ครับ

  • การฟอร์เวิร์ดไอพี
    # vi /etc/sysctl.conf
    
    ...
    net.ipv4.ip_forward = 1
    ...
    
    # echo 1 > /proc/sys/net/ipv4/ip_forward
    
  • การเพิ่มเกตเวย์ไปที่เราเตอร์
    # route add default gw 192.168.5.1
    
  • การทำตาราง nat ด้วย iptables
    # WAN_INT=eth1
    # iptables -t nat -D POSTROUTING -o $WAN_INT -j MASQUERADE > /dev/null
    # iptables -t nat -A POSTROUTING -o $WAN_INT -j MASQUERADE
    
  • อย่าลืมตั้งค่า NAT ให้เราเตอร์ชี้ DMZ host มาที่ eth1 ของเซิร์ฟเวอร์ด้วย ซึ่งในที่นี้คือ 192.168.5.3
  • คำสั่งในการดูเลขไอพี ตามตัวอย่างเป็น http://192.168.5.1/wancfg.cmd?action=view แต่เวลาใช้งานจริงต้องดูว่าเราเตอร์เราใช้คำสั่งเดียวกันนี้หรือไม่ ส่วนใหญ่ดูจาก Status Bar ด้านล่างของเบราว์เซอร์ เวลาที่เราเอาเมาส์ไปชี้ตรงลิงก์
Creative Commons License ลิขสิทธิ์ของบทความเป็นของเจ้าของบทความแต่ละชิ้น
ผลงานนี้ ใช้สัญญาอนุญาตของครีเอทีฟคอมมอนส์แบบ แสดงที่มา-อนุญาตแบบเดียวกัน 3.0 ที่ยังไม่ได้ปรับแก้