ツイート
シェア
LINEで送る
B! はてぶでブックマーク
Pocketでブックマーク
RSSフィード

MyDNS, LinuxでIP通知の自動化。シェルを作ってSystemdのサービスに登録。

domain image

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ファイルを作成します。

mydns.service
[Unit]
Description=mydns notify ip

[Service]
Type=simple
ExecStart=/etc/mydns/notify-ip.sh user:password

simpleはデフォルト値(メインプロセスとして起動)です。そのままでいいでしょう。

ExcecStartにコマンドを書いてもいいですがシェルにしました。シェルのほうが自由に書けるので。

シェルの内容です。

notify-ip.sh
#!/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と同じところに)

notify-ip-change.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通知ではこれを使います。

mydns-short.service
[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ファイルを作成します。

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)

mydns-short.timer
[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
前の投稿
Webサイト攻撃にあったログを見る。eval()を使うPHPファイルは狙われている。

コメント

  1. いなか より:

    大変有益な情報をありがとうございます。

    一点質問なのですが、notify-ip-change.shの8行目では現在のIPをmydnsから取得しておりますが、
    これだと自機の現在のIPを取得していることにはならないのではないかと思います。

    また16行目のCMD="${FILE_DIR}notify-ip.sh"はCMD="${FILE_DIR}notify-ip.sh user:password"にする必要が
    あるのではないかと思います。

コメントを残す

*