MyDNS.JPのIP更新通知

技術ネタ

7年ぶりの更新w

自宅サーバーを運用してきていろいろ環境も変わったので、まだつらつらと書いていきたいなと思います。

さて、自宅サーバーを運用する際に、ダイナミックDNSを利用して独自ドメイン運用というケースが多いと思います。

我が家も無料のダイナミックDNSで有名なMyDNS.JPという素晴らしいサービスを長年利用しております。無料のサブドメインが取得できるだけでなく、独自ドメインの管理までできてしまう優れものです。

ダイナミックDNSの仕組み上、プロバイダから割り当てられたグローバルIPをMyDNSさんに通知しないといけないのですが、毎回手動でIP通知するのは非常に面倒。。というかIP変わるタイミングは不規則なので無理ですねw

なのでサーバーでシェルスクリプトを使って自動実行しちゃいましょう

#!/bin/bash

#############################
# SETTINGS
#############################
ROOT_FOLDER="$1"
DATA_FOLDER=$ROOT_FOLDER/data
IP_FILE="$DATA_FOLDER/current-ip"
# CSV format [ MasterID,password,IPV6flag[true|false] ]
CREDENTIAL_PATH="$ROOT_FOLDER/config/mydns-credential.csv"
MIN_NOTIFICATION_DAYS=3
ERROR_COUNT=0

get_current_ip() {
    echo `curl -s -4 ifconfig.io`
}

get_current_ipv6() {
    echo `curl -s -6 ifconfig.io`
}

new_ip_file() {
    echo "$1,`date '+%Y%m%d'`" > $IP_FILE
}

check_update() {
    if [ ! -e $IP_FILE ]; then
        echo "$IP_FILE Not Found."
        return 1
    fi

    local before_ip=`cat $IP_FILE | cut -d ',' -f1`
    local notification_date=`cat $IP_FILE | cut -d ',' -f2`
    local passed_date=`date "+%Y%m%d" -d "$2 days ago"`

    if [ $notification_date -le $passed_date ]; then
        echo "Notification date is Passed."
        return 1

    elif [ "$before_ip" != "$1" ]; then
        echo "Global IP is changed."
        return 1
    fi

    return 0
}

update_ipv4() {
    curl -s -o /dev/null -u $1:$2 https://ipv4.mydns.jp/login.html

    if [ $? -eq 0 ]; then
        echo "success. ${FUNCNAME[0]} $1"
    else
        echo "error. ${FUNCNAME[0]} $1 $2"
        return 1
    fi

    return 0
}

update_ipv6() {
    curl -s -o /dev/null -u $1:$2 https://ipv6.mydns.jp/login.html

    if [ $? -eq 0 ]; then
        echo "success. ${FUNCNAME[0]} $1"
    else
        echo "error. ${FUNCNAME[0]} $1 $2"
        return 1
    fi

    return 0
}

error() {
    ERROR_COUNT=$((++ERROR_COUNT))
}

#############################
# MAIN
#############################

# CheckCredentialFile
if [ ! -f $CREDENTIAL_PATH ]; then
    echo "${CREDENTIAL_PATH} Not Found."
    exit 1
fi

# CreateDataFolder
if [ ! -d $DATA_FOLDER ]; then
    mkdir -p $DATA_FOLDER
fi

# CheckUpdate
CURRENT_IP=`get_current_ip`
check_update $CURRENT_IP $MIN_NOTIFICATION_DAYS
if [ $? -eq 0 ]; then
    echo "Not update."
    exit 2
fi

while IFS=, read id pass ipv6
do
    if [ -n $id ] && [ -n $pass ]; then
        update_ipv4 $id $pass || error

        if [ -n $ipv6 ] && "${ipv6}"; then
            update_ipv6 $id $pass || error
        fi
    fi
done < $CREDENTIAL_PATH

if [ $ERROR_COUNT -eq 0 ]; then
    new_ip_file ${CURRENT_IP}
else
    echo "found error."
    exit 1
fi

exit 0

うちではこんな感じのスクリプトでCronやJenkins等使って定期実行してます。IPアドレスが変わっていない場合は、通知をしないようにしているので1分間隔とかでもたぶん大丈夫です。

あまり頻繁にMyDNSさんに通知をすると負荷をかけてしまうのでIPアドレスが変わってなければ通知しない実装にしました。なお、1週間以上通知しないとドメイン情報が生成されなくなるのでドメインにアクセスできなくなります。そのまま1か月以上放置すると削除されてしまうそうなので、気を付けましょう。

ちなみに筆者は最初、IPアドレスが変更なければ通知しないという機能だけで実装してしまい、うっかり1週間以上通知してなくて、MyDNSさんからお知らせメールで気づくという失態を犯してますw

MIN_NOTIFICATION_DAYS=3と定義しているのが最小の通知期間となっていて、最後に通知した日から3日目に再度同じIPでも通知するという作りになってます。まぁ通信がコケてしまうこともあるかと思うので、1週間のうちに2回チャンスがあるという感じですね。

if [ $? -eq 0 ]; then
    echo "Not update."
    exit 2
fi

あとこのexit 2としているところですが、IPアドレスが前回と変わっていない場合でも正常終了するので通知したときだけSNSに通知するというようなことをするために正常終了とは違うコードを返しています。

# CSV format [ MasterID,password,IPV6flag[true|false] ]
CREDENTIAL_PATH="$ROOT_FOLDER/config/mydns-credential.csv"

あとは上記のCSVファイルを用意して所定のパスに置いておけば準備OK。複数IDに対応しているので独自ドメインを別MasterIDで管理している場合はCSVに行を追加していけばOKです。(子IDもたぶんいけると思います。ためしてないですがw)IPV6対応も入れてますが、当方の環境ではIPV6対応していないので未検証です。

作っているうちにあれもこれもと実装してたら100行以上のスクリプトになってしまいましたが、我が家ではこのスクリプトを使って二つのドメインを運用しています。

今のところトラブルはないので、MyDNSを利用していて手動で何とかしている方wとかいたら使ってみてください。※ご利用の際はノンサポートでお願いします<(_ _)>

※ 2021/07/03 エラー処理を追記

コメント

タイトルとURLをコピーしました