MyDNSアドレス自動更新スクリプト
いやぁこんな簡単なスクリプトを作るために8時間くらいかかってしまった。
だんだんこだわりすぎて一週間くらいかかりっきりになったorz
最初シンプルな構成を目指しすぎたせいで、ドツボにはまった。
一応、GitHubにも登録しといたんで。
目次 / Contents
新バージョンから構成が変わりました。
なのでここでの説明はちょっと諦めて(実はこっそり編集して対応していた)
以下をご覧ください。
使い方
総合版
ワンクリックインストール
頑張って、ワンクリックインストールできるようにしました。
正しいやり方かは分かりませんが、とても簡単にインストールできます。
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も初めて使ってみたけども、
もっとリポジトリのトップページを分かりやすくできないものかと、、、
バージョン管理に関しては昔使ったことあるので、
軽く扱うだけでも使い方には困らなかったけど。
参考にしたサイトはたくさんあるんですが、
結局、最終的に全然参考にしていない処理になってしまったので、
割愛させていただきます。
一応ベースはこちらでした。
ただ、動的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サイト重いんだよね。
だから少しでも負荷が減ればいいと思って、このスクリプト作った経緯です。
折角なんでいろいろ詰め込んでしまったけれども。