DDNS(Dinamic DNS)を無料で使えるMyDNSは、定期的にIP通知が必要です。
(たった8日通知がないだけでサイトの接続が遮断される。)
それをLinuxで自動化する設定を行います。かんたんなシェルを作りsystemdのサービスに登録し、同じくsystemdのタイマーを使います。
MyDNSは無料で使えるDNSサーバーのサービスです。
クラウド・レンタルサーバのDNSサービスは、サブドメインを使うには有料オプションになることがあるのに対して、MyDNSはサブドメインすら無料で使えます。
テスト用や開発用の暫定的なドメインを作ったりするのに便利です。しかし弱点があって、一定期間DNSサーバーにIPアドレスの通知をしないと使えなくなります。
DNSの有効期限は1週間。
1週間以上IP通知がないとエラーサイトに誘導される。
1ヶ月以上IP通知がないとすべてのデータ削除。
(アカウントは有効)
MyDNSのIP通知の自動化は必須です。
systemdのタイマーを使う
Linuxのcronを使ってもいいですがsystemdのタイマーを使います。
RedHat・Debian系の両方(CentOS, Ubuntu)で使い方は同じだし、どうやら最近はcronを使わなくなっているようです。
さっそく、タイマーの設定を始めましょう。今回作成するファイルの構成です。
/etc
├ mydns
│ ├ notify-ip.sh
│ └ notify-ip-change.sh
│
└ systemd
└ system
├ mydns.service
├ mydns.timer
├ mydns-short.service
└ mydns-short.timer
*.timer : サービスを実行するsystemdタイマー
*.service : タイマーが実行するsystemdサービス
*.sh : サービスが実行するシェル
タイマーとサービス・シェルの関係
systemd.timer ┬ mydns.timer
│ └ mydns.service
│ └ notify-ip.sh
│
└ mydns-short.timer
└ mydns-short.service
└ notify-ip-change.sh
エラーサイト誘導、アカウント停止を阻止するタイマー。
IP変更を監視して通知するタイマー。
の二つを作ります。まずは、systemdのサービスを作成します。
systemdのサービス作成
タイマーもsystemctlで扱うサービスのひとつ。
/etc/systemd/systemにmydns.serviceファイルを作成します。
[Unit]
Description=mydns notify ip
[Service]
Type=simple
ExecStart=/etc/mydns/notify-ip.sh user:password
simpleはデフォルト値(メインプロセスとして起動)です。そのままでいいでしょう。
ExcecStartにコマンドを書いてもいいですがシェルにしました。シェルのほうが自由に書けるので。
シェルの内容です。
#!/bin/sh
if [ $# != 1 ]; then
echo "usage: notify-ip.sh user:password"
exit -1;
fi
curl -s -u $1 https://ipv4.mydns.jp/login.html
# curl -s -u $1 https://ipv6.mydns.jp/login.html
IP通知はIPv4, IPv6があります。併用するときは2回通知しないといけないので2つ用意しました。
(IPv6を使わないときはコメント化)
シェルのパラメータ(user:password)はIP通知サイトのBasic認証ユーザー・パスワードです。
curlコマンドは、ブラウザでMyDNSのIP通知画面を表示してBasic認証でログインするのと同じです。
notify-ip.shを作成したらアクセス権限に実行権を追加しましょう。
chmod +x modify-ip.sh
/etc/mydnsは勝手に作ったディレクトリ。systemdのサービスが実行できるなら/home/****/にあってもいい。
動的IP用のシェル
notify-ip.shは単純なMyDNSへのIP通知シェルで、通知のサイクルを短くするときは負荷が大きいです。
たとえば動的IPでは、IPが変わった瞬間にすばやく通知したいので、通知タイマーのサイクルが短くなります。1日1回ではキツイでしょう。
(最終的にはDNSキャッシュに依存するが...)
30秒に1回、MyDNSの通知ログインは非現実的です。そこでショートサイクル用のシェルを新たに作ります。(notify-ip.shと同じところに)
#!/bin/sh
if [ $# != 1 ]; then
echo "usage: notify-ip-change.sh domain_name"
exit -1
fi
IP_CURRENT=$(dig $1 +short)
if [ $? != 0 ]; then
IP_CURRENT=$(curl inet-ip.info)
fi
FILE_DIR="/etc/mydns/"
FILE_OLD="${FILE_DIR}old"
CMD="${FILE_DIR}notify-ip.sh"
if [ -f $FILE_OLD ]; then
IP_OLD=$(cat $FILE_OLD)
if [ $IP_CURRENT != $IP_OLD ]; then
eval $CMD
fi
else
eval $CMD
fi
eval "echo $IP_CURRENT > $FILE_OLD"
chmod +x modify-ip-change.sh
ドメイン名からグローバルIPを取得し、前回のグローバルIPと比較してIPが変わったときだけ通知します。
(シェルの最後に取得したグローバルIPをoldとして保存。)
ショートサイクルのIP通知ではこれを使います。
[Unit]
Description=mydns notify ip short cycle
[Service]
Type=simple
ExecStart=/etc/mydns/notify-ip-change.sh sample.com
(パラメータのsample.comは通知するIPのドメイン)
mydns-short.serviceも/etc/systemd/systemに置きます。
グローバルIP取得にはdigコマンドか、なければhttpの取得サービスを使います。
digコマンドのほうが処理は速いです。digコマンドをインストールしましょう。
systemdのタイマー作成
次に、作成したMyDNS・IP通知サービスを実行するタイマーを設定します。
mydns.serviceと同じところにmydns.timerファイルを作成します。
[Unit]
Description=mydns notify ip
[Timer]
OnCalendar=*-*-* 6:00:00
Unit=mydns.service
[Install]
WantedBy=timers.target
OnClendarはサービス実行のスケジュールです。毎日6:00に実行します。
MyDNSの通知は、1週間以内に1回あればスケジュールは自由ですが、IPアドレスが変わらないとき、24時間以上の間隔がなければログに残りません。
1日以上、1週間以内に1回の通知
固定IPならこれでいいと思います。
WantedBy=timers.targetは絶対に必要です。これがないとsystemdのタイマーに登録されません。
動的IPのタイマー
動的IPのとき、最低1日1回の通知では心許(こころもと)ありません。
(最悪、サイトのIPが変わったのに1日中何もしないことになる。)
インターバル1分のタイマーを新たに設定します。使うサービスは動的IP用のシェルです。(notify-ip-change.sh)
[Unit]
Description=mydns notify ip short cycle
[Timer]
OnBootSec=10s
OnActiveSec=10s
OnUnitActiveSec=1min
Unit=mydns-short.service
[Install]
WantedBy=timers.target
OnBootSec | マシンが起動してから指定時間後に実行 |
OnActiveSec | タイマーが有効になってから指定時間後に実行 |
OnUnitActiveSec | 前に実行した時間から指定時間後に実行 |
『〇〇毎に実行』するなら、On***Secを使ったほうが良いです。インターバルの指定はOnUnitActiveSecですが、これは前の実行時間が基準になるので最低1回は実行されてないといけません。
そこで、OnBootSec, OnActiveSecもいっしょに設定します。これで最低1回は必ずサービスが実行されます。
単位は秒ですが、時分、年月日、週なども設定できます。
mydns-short.timerは、IPアドレスに変化がないとき通知をしません。
(IPが変わらないなら永遠に通知しない。)
なので、mydns.timerと併用します。
mydns-ip-short.shを改造してタイマーをひとつに統合してもいいです。
(『最低1日1回は通知する』処理を入れる。)
ボクは『最低1日1回は通知する』処理を統合するのがめんどうで、それを独立させてタイマー化しました。
サイクルを短くすればいいってもんでもない
通知のサイクルを短くすればいいというものでもありません。DNSの反映は最終的にDNSキャッシュで決まるからです。
DNSはキャッシュを使っており、世界中のDNSサーバーはキャッシュをお互いに同期することでドメインとIPアドレスを紐付けています。
DNSキャッシュの反映までには1~3日かかるとも言われます。10秒ごとに通知をしたところで大した意味はありません。
また光インターネットでは、
ルーターの電源を落とす。
ルーターの設定変更・再起動。
停電。
しないかぎり、IPアドレスは変わりません。
(その他、プロバイダの保守・メンテなど。)
またいまのDHCPは、なるべく同じIPを割り当てようとする機能もあるので『ほぼ固定IP』といっていいです。
そのあたりを考えてサイクルを設定しましょう。
タイマーの起動
systemdのサービス・タイマーの設定ファイルを反映させます。
systemctl daemon-reload
mydns.timerを起動します。ついでに、OS起動時にタイマーを起動する(enable)ようにしましょう。
systemctl enable mydns.timer
systemctl start mydns.timer
systemctl enable mydns-short.timer
systemctl start mydns-short.timer
mydns.serviceを起動しないことに注意。
サービスを起動するとシェルを実行して終わりです。タイマー起動になりません。
さいごに、systemdのタイマーリストに加わっているか確認します。
systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
火 2020-01-28 06:00:00 JST 10h left n/a n/a mydns.timer mydns.service
火 2020-01-28 09:22:58 JST 13h left 月 2020-01-27 09:22:58 JST 10h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.
2 timers listed.
Pass --all to see loaded but inactive timers, too.
ちなみに、systemdのタイマーから外すときはsytemctlでstopするだけでいいです。
systemctl stop mydns.timer
systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
火 2020-01-28 09:22:58 JST 12h left 月 2020-01-27 09:22:58 JST 11h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.
1 timers listed.
Pass --all to see loaded but inactive timers, too.
永続的に停止するときは、OS起動時の設定も変えときましょう。
systemctl disable mydns.timer
大変有益な情報をありがとうございます。
一点質問なのですが、notify-ip-change.shの8行目では現在のIPをmydnsから取得しておりますが、
これだと自機の現在のIPを取得していることにはならないのではないかと思います。
また16行目のCMD="${FILE_DIR}notify-ip.sh"はCMD="${FILE_DIR}notify-ip.sh user:password"にする必要が
あるのではないかと思います。