MyDNSアドレス自動更新スクリプト

いやぁこんな簡単なスクリプトを作るために8時間くらいかかってしまった。
だんだんこだわりすぎて一週間くらいかかりっきりになったorz

最初シンプルな構成を目指しすぎたせいで、ドツボにはまった。
一応、GitHubにも登録しといたんで。

新バージョンから構成が変わりました。

なのでここでの説明はちょっと諦めて(実はこっそり編集して対応していた)
以下をご覧ください。

使い方

GitHub - smileygames/mydns-ip-update: MyDNS.JPにipを自動でupdateするシェルスクリプト

MyDNS.JPにipを自動でupdateするシェルスクリプト. Contribute to smileygames/mydns-ip-update development by creating an account on GitHub.

総合版

GitHub - smileygames/dipper: DDNSにipを自動でupdateするシェルスクリプト

DDNSにipを自動でupdateするシェルスクリプト. Contribute to smileygames/dipper development by creating an account on GitHub.

ワンクリックインストール

頑張って、ワンクリックインストールできるようにしました。
正しいやり方かは分かりませんが、とても簡単にインストールできます。

v1.05/mydns-ip-install.sh(GitHub)

bash <( curl -fsSL https://github.com/smileygames/mydns-ip-update/releases/download/v1.05/mydns-ip-install.sh )

上記コマンドでインストールは完了するので、次に初期設定をします。
ちにみにこのコマンドは上書きインストールにも対応しています。

初期設定

コンフィグファイルで必要な設定をします。
ユーザーIDとかパスワードとかドメインとか…

sudo vim /usr/local/etc/mydns-ip-update.conf

サービス実行&自動起動登録(基本サービス)

sudo systemctl enable mydns-ip-update.service --now

動的IP用サービス(オプション・固定IPならなくても大丈夫)

sudo systemctl enable mydns-ip-change.service --now

 

アンインストール用スクリプト

bash <( curl -fsSL https://github.com/smileygames/mydns-ip-update/releases/download/v1.05/mydns-ip-uninstall.sh )

 

設定変更時

コンフィグファイルの内容を変更した際は、
サービスを再起動しないと反映されないので注意です。

sudo systemctl restart mydns-ip-update.service
sudo systemctl restart mydns-ip-change.service

 

マニュアルインストール

直接ダウンロードはこちら

Release mydns-ip-update_v1.05 · smileygames/mydns-ip-update (github.com)

スクリプトファイルとコンフィグファイルはダウンロードできるようにしておきました。
まぁコピペで問題のないサイズのファイルなんですけどね。
Windowsでコピペすると改行コードの違いが面倒な方向けという事で。

mydns-ip-update.conf(設定用ファイル)

基本的にこれしかユーザー側は弄らなくてOK

sudo vim /usr/local/etc/mydns-ip-update.conf
#!/bin/bash
#
# update ddns Config file
#
# MyDNS

# マルチドメインの場合、例のように [ ] の数字をそろえて追加登録してください
# 例はコメントアウトされているので、先頭の # を外してID等を変更して使用してください
MYDNS_ID[0]="mydnsxxxxxx"
MYDNS_PASS[0]="Password1"
MY_DOMAIN[0]="example.com"

#MYDNS_ID[1]="mydnsxxxxx1"
#MYDNS_PASS[1]="Password1"
#MY_DOMAIN[1]="example1.com"

#MYDNS_ID[2]="mydnsxxxxx2"
#MYDNS_PASS[2]="Password2"
#MY_DOMAIN[2]="example2.com"

# IPV4 アドレス default = on
# IPV4_DDNS 動的IPアドレス mydns-ip-change.serviceが無効の場合は動作しない
# (default) IPV4_DDNS = on
IPV4=on
IPV4_DDNS=on

# IPV6 アドレス default = off
# IPV6_DDNS 動的IPアドレス mydns-ip-change.serviceが無効の場合は動作しない
# default = on
IPV6=off
IPV6_DDNS=on

#   s:	秒(seconds)
#   m:	分(minutes)
#   h:	時間(hours)
#   d:	日(days)
# UPDate Timer 6h (default) 
UPDATE_TIME=6h

# DDNS UPDate Timer 1m (default) 
DDNS_TIME=1m

▼ファイル属性の変更

sudo chown root:root /usr/local/etc/mydns-ip-update.conf
sudo chmod 600 /usr/local/etc/mydns-ip-update.conf

 

mydns-ip-update.sh(基本のIP更新スクリプト )
sudo vim /usr/bin/mydns-ip-update.sh
#!/bin/bash
#
# update IP address
#
# MyDNS

# Config File ロード
FILE_DIR="/usr/local/etc/"
source "${FILE_DIR}mydns-ip-update.conf"

mydns_update() {
# ipv4用
    if [ "$IPV4" = on ]; then
        multi_domain_update "https://ipv4.mydns.jp/login.html"
    fi
# ipv6用
    if [ "$IPV6" = on ]; then
        multi_domain_update "https://ipv6.mydns.jp/login.html"
    fi
}

# 引数としてLogin URLをもらう $1=URL
multi_domain_update() {
    for i in ${!MYDNS_ID[@]}; do
        if [[ ${MYDNS_ID[$i]} = "" ]] || [[ ${MYDNS_PASS[$i]} = "" ]]; then
            echo "ERROR : MYDNS_ID[$i] MYDNS_PASS[$i]  <- どちらかに値がないエラー"
            continue
        fi 

        MYDNS_ACCESS="${MYDNS_ID[$i]}:${MYDNS_PASS[$i]} $1"
        timeout 1m curl -sSfu $MYDNS_ACCESS; if [ $? != 0 ]; then echo "ERROR : $MYDNS_ACCESS  <- 通知接続エラー"; fi
        if [ $? != 0 ]; then 
            echo "ERROR : $MYDNS_ACCESS  <- TIME OUT [60sec]"
            exit 1
        fi
    done
}

# 実行スクリプト(タイマー処理)
sleep 3m;mydns_update
while true;do
    sleep $UPDATE_TIME;mydns_update
done

▼ファイル属性の変更

sudo chown root:root /usr/bin/mydns-ip-update.sh
sudo chmod 755 /usr/bin/mydns-ip-update.sh

▼サービスの作成

sudo vim /etc/systemd/system/mydns-ip-update.service
[Unit]
Description=mydns-ip-update

[Service]
Type=simple
ExecStart=/usr/bin/mydns-ip-update.sh

[Install]
WantedBy=network-online.target

▼サービスの登録(自動起動設定および起動)

sudo systemctl daemon-reload
sudo systemctl enable mydns-ip-update.service --now

固定IPの方はこれだけ作成すればいけます。

以下は動的IPの方用です。
まぁ固定IPでも入れておいても問題なく動くように(余計な処理はしない)作りましたが。
その場合は、コンフィグファイルにて
IPV4_DDNS・IPV6_DDNSを「off」にしてくれれば間違いないです。

 

mydns-ip-update.service(動的IP用の更新スクリプト)

このスクリプトはMyDNSへの負荷を減らすためと、自身の負荷を減らす目的があります。
(IPに変更があった場合のみMyDNSへIPを通知するため)

sudo vim /usr/bin/mydns-ip-change.sh
#!/bin/bash
#
# update dynamic IP address
#
# MyDNS

# Config File ロード
FILE_DIR="/usr/local/etc/"
source "${FILE_DIR}mydns-ip-update.conf"

mydns_change() {
# ipv4
    if [ "$IPV4" = on ] && [ "$IPV4_DDNS" = on ]; then
        IP_NEW=$(curl -s ifconfig.io -4)
        if [[ $IP_NEW != "" ]]; then
            multi_domain_change "A" "https://ipv4.mydns.jp/login.html"
        fi
    fi
# ipv6
    if [ "$IPV6" = on ] && [ "$IPV6_DDNS" = on ]; then
        IP_NEW=$(curl -s ifconfig.io -6)
        if [[ $IP_NEW != "" ]]; then
            multi_domain_change "AAAA" "https://ipv6.mydns.jp/login.html"
        fi
    fi
}

# 引数としてレコードとLogin URLをもらう $1=レコード $2=URL
# IP_NEWはコールされる前に入れておくこと
multi_domain_change() {
    for i in ${!MYDNS_ID[@]}; do
        if [[ ${MY_DOMAIN[$i]} = "" ]] || [[ ${MYDNS_ID[$i]} = "" ]] || [[ ${MYDNS_PASS[$i]} = "" ]]; then
            echo "ERROR : MY_DOMAIN[$i] MYDNS_ID[$i] MYDNS_PASS[$i]  <- どれかに値がないエラー"
            continue
        fi 
        IP_OLD=$(dig "${MY_DOMAIN[i]}" $1 +short)
        if [[ $IP_NEW != $IP_OLD ]]; then
            MYDNS_ACCESS="${MYDNS_ID[$i]}:${MYDNS_PASS[$i]} $2"
            timeout 1m curl -sSfu $MYDNS_ACCESS; if [ $? != 0 ]; then echo "ERROR : $MYDNS_ACCESS  <- 通知接続エラー"; fi
            if [ $? != 0 ]; then 
                echo "ERROR : $MYDNS_ACCESS  <- TIME OUT [60sec]"
                exit 1
            fi
        fi
    done
}

# 実行スクリプト(タイマー処理)
while true;do
  sleep $DDNS_TIME;mydns_change
done

▼ファイル属性変更

sudo chown root:root /usr/bin/mydns-ip-change.sh
sudo chmod 755 /usr/bin/mydns-ip-change.sh

▼サービスの作成

sudo vim /etc/systemd/system/mydns-ip-change.service
[Unit]
Description=mydns-ip-change

[Service]
Type=simple
ExecStart=/usr/bin/mydns-ip-change.sh

[Install]
WantedBy=network-online.target

▼サービスの登録(自動起動設定および起動)

sudo systemctl daemon-reload
sudo systemctl enable mydns-ip-change.service --now

簡易デバッグテストはしましたが、バグはありそうな気がしますので、あったら教えてください。

 

雑記

使用しているコマンドも少ないし処理も簡単なので、
ちょっと調べればすぐ処理内容が分かると思います。

結構複雑化してきました、主にマルチドメイン対応とエラー処理対応のせいで。
極力コメントは少なくしています。
ソースコード汚したくないので、
その内、github内のwikiにスクリプト仕様書的なものを作るかもしれません。
キガムイタラ。

ここに来るまでかな~り遠回りしたので、出来としては満足できるものになりました。

初めてのシェルスクリプトだったんですが、
シェルスクリプトにはまったというより、調べるので結構疲れたなぁという感じ。
スクリプト自体は扱いやすかったですね。

最初1つのスクリプトファイルと1つのサービスにまとめることにこだわったせいで、
無駄に時間がかかってしまいましたが。。。(日をまたいだ)
2つの無限ループ処理を1つにまとめるのが難しく
無理やり作ったけど、暴走気味でサービス登録できなかったので没。
watchコマンドだとスマートに実装できたけど
監視用ウィンドウ要らないうえ、サービスに登録できなかったのでこれも没。
諦めて寝て起きたら、今の処理を思いついたのでやっと完成できた。
出来上がってみればものすごく簡単な処理だったというオチ。
(2つのループ処理を別々のサービスで管理することで、簡単に並列化できた)

シンプルにしようとしすぎて、逆に難しくしてしまうパターンでした(´;ω;`)
▲最新版で対応できています。(サービス1つで3つの異なる無限ループ処理)
スクリプトファイルは増えましたけどね。( ´艸`)

現役のプログラマーであれば1時間もかからず完成できたんじゃないでしょうかね?
(テスト・パッケージ化含む)

可能であればパッケージ化したい気もしますが、誰かやってくれませんかね?
wgetでインストールできるようになるだけで説明が簡単になるんですよね~
(インストール用のシェルスクリプトが必要なのかな?)
分かってる人だったら簡単に作れそうな気がするんですが。

▲頑張って作りました!

ちなみに、もっとちゃんと作るんであればtimeout処理を追加したいところです。
ただ、検証が面倒そうなので今回はやめました。
誰か追加してもいいんですよ?

▲timeout処理も最新版では追加済みです。

ソースは自由に弄ってもらっていいので。
もし、これは良いスクリプトだと感謝して使ってもらえるのなら、
このサイトの一番下に寄付できるようになっているので、
気が向いたら、寄付をよろしくお願いします!

だって、かなり頑張ったからねぇ。
自分じゃ使わないのにね。。。

GitHubも初めて使ってみたけども、
もっとリポジトリのトップページを分かりやすくできないものかと、、、
バージョン管理に関しては昔使ったことあるので、
軽く扱うだけでも使い方には困らなかったけど。

参考にしたサイトはたくさんあるんですが、
結局、最終的に全然参考にしていない処理になってしまったので、
割愛させていただきます。
一応ベースはこちらでした。

MyDNS, LinuxでIP通知の自動化。シェルを作ってSystemdのサービスに登録。 | ただ屋ぁのブログ

DDNS(Dinamic DNS)を無料で使えるMyDNSは、定期的にIP通知が必要です。(たった8日通知がないだけでサイトの接続が遮断される。)それをLinuxで自動化する設定を行いま…

ただ、動的IP用の処理がどうしても納得できなくて、そちらは最初から使ってなかったのです。
基本のサービスタイマー処理もちょっとカスタムして最初のころは使っていましたが、
サービスがエラー出すようになったし、結局固定IPに変えたりで、
GoogleのDNSに移行して、つかわなくなった経緯です。

改めて、しっかりスクリプトとsystemdを学んだところ、
自分の使い方が間違っていたことに気づいたりしたんですけどね、
それでもやっぱり動的IP用のスクリプトは間違えている気がしたので、
自分のやり方で1から作った経緯です。
でも、IP取得のコマンドとかはここを参考にしています。 

いまMyDNSのHPを見ていたら、大事なことを忘れていた。
マルチドメインがあったんだ。。。
気が向いたら実装します。。。。。。。。キガムイタラネ。

▲これも頑張って追加しました!

ちなみに、公式のやり方はめちゃくちゃシンプルで

ダイナミックDNS (Dynamic DNS)のMyDNS.JP

STEP.1 実際にMyDNS.JP用のIPアドレス通知スクリプトを作る

 vi /root/mydns.sh
#!/bin/sh
#
# TEST1.MYDNS.JP
/usr/bin/wget -O - 'http(s)://mydns111111:tp5YgZv4@ipv4.mydns.jp/login.html'
/usr/bin/wget -O - 'http(s)://mydns111111:tp5YgZv4@ipv6.mydns.jp/login.html'
#
#
# TEST2.0am.JP
/usr/bin/wget -O - 'http(s)://mydns222222:Ex8ZVkm7@ipv4.mydns.jp/login.html'
/usr/bin/wget -O - 'http(s)://mydns222222:Ex8ZVkm7@ipv6.mydns.jp/login.html'
#
#
# TEST3.0T0.JP
/usr/bin/wget -O - 'http(s)://mydns333333:QC6L2SF8@ipv4.mydns.jp/login.html'
/usr/bin/wget -O - 'http(s)://mydns333333:QC6L2SF8@ipv6.mydns.jp/login.html'

STEP.2 実行属性をつけて、実際に実行してエラーとならないか確認する

chmod 700 /root/mydns.sh
/root/mydns.sh

STEP.3 続いてcronの設定にこの通知用スクリプトを追加

crontab -e
#
# MyDNS.JP への通知...
#
*/3 * * * * /root/mydns.sh 1> /dev/null 2> /dev/null

となります。

これは、3分毎にMyDNSへアドレスを通知する処理ですね。
何が問題かというと、
自身のアドレスが変わろうが変わらなかろうがMyDNSへ3分毎にログインしてアドレスを通知していることと、
wgetコマンドは確かHTTPS非対応だったはず、
それと、RedHat系ではcrontabは非推奨らしいし。

MyDNSのWebサイト重いんだよね。
だから少しでも負荷が減ればいいと思って、このスクリプト作った経緯です。
折角なんでいろいろ詰め込んでしまったけれども。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です