GoogleDomainsのDDNSをWindowsServerのコマンドプロンプトで自動更新する

投稿者: | 2021-02-07

さて、前回「お名前.comからGoogleDomainsにドメインを移管」でドメインを移管し、とりあえずつながるようにはなりましたが…。
大切なDDNSがまだ設定できていません。

お名前.comはWindows用のみですがDDNSクライアントが用意されていますので、インストールして設定すれば自動でIPアドレスを通知してくれます。

しかし、GoogleDomainsにはそういったものはありませんので、自分でなんとかする必要があります。ヘルプを見てみると、さすがのGoogle様で、自分でなんとかしろと言わんばかりのサポートページです。
https://support.google.com/domains/answer/6147083?hl=ja&ref_topic=9018335

この記載通り、まずはGoogleDomainsでダイナミックDNS用の設定を行います。その後で、自サーバにIP通知の設定をしていきます。

GoogleDomainsの設定画面です。
固定IPを指定する場合は、下部の[カスタム リソース レコード]でIPを指定すればOKです。
DDNSの場合は、上部の[合成レコード]で設定していきます。
画像の[サブドメインの転送]と記載してある箇所のプルダウンから、[ダイナミックDNS]に変更します。


ダイナミックDNSに変更するとこんな具合です。
[サブドメイン]欄にはサブドメインを入力しますが、ルートドメインを指定する場合は[@]を入力します。
すると下部に項目が追加され、[認証情報を表示]からDDNS更新用の認証情報が得られます。

これでGoogleDomains側の基本設定はOKです。
続いて自サーバからIPアドレスを通知する、ここがミソですね。

Googleのヘルプを見ると、DDclientもしくはINADYNでの更新ができるとのことですが、ざっと探しましたがWindows用のクライアントソフトがありません。海外のソフトはいくつかあるようですが、試しても動作しなかったり、そもそも信用できないので微妙ですよね。
DDclientはLinux系はかんたんに使えますので悩む必要がありません。
WindowsServerめ…
はじめはWindows/Linuxともに存在し、長く利用されてきたDDNSクライアントソフトのDiCEをコンフィグ書き換えで使用しようと思っていたのですが、頑張っても動きませんでした。

よくよくヘルプを読んでいると
[APIを使用してダイナミックDNSレコードを更新する]
という項目があります。
httpsでユーザIDとパスワード、ドメインを指定してアクセスすれば更新できるスグレモノです。ブラウザでアクセスしてもできますが、なんとか自動化したい。無い頭を使って、コマンドプロンプトでCurlコマンドを使用することにしました。

中身は超簡単!
[username]は先程のDDNS認証情報のユーザ名
[password]も同じく先程の認証情報のパスワード
[subdomain.yourdomain.com]の部分に更新したいドメイン
[1.2.3.4]の部分に通知するIPアドレスです。
これを自動化すればいいわけですね。

https://username:password@domains.google.com/nic/update?hostname=subdomain.yourdomain.com&myip=1.2.3.4

テスト環境はWindows10でしたので、Curlコマンドが標準で使用できます。
(WindowsServer2016 Standardは付いていない事に後で気づいた)
コマンドプロンプトで実行するには、こんなコマンドです。
curlコマンドに、-kオプションをつけただけです。

curl -k "https://username:password@domains.google.com/nic/update?hostname=subdomain.yourdomain.com&myip=1.2.3.4"

これでコマンドプロンプトで通知できますが、IPアドレスをいちいち手打ちでは自動化できません。また、IPチェック時に更新されていてもされていなくてもGoogleのサーバに通知するのはちょっと気が引けるので、自サーバ側でIPアドレスの変更を感知した場合のみ、Google側に通知する仕組みが必要です。

まず自サーバのグローバルIPアドレスの取得には、Googleの
https://domains.google.com/checkip
にアクセスすると、IPアドレスを返してくれるのでこちらを利用します。
こちらは毎回アクセスするしかありません。
ここもコマンドプロンプトで、curlコマンドで実行できます。

curl -k https://domains.google.com/checkip

実行結果は、IPアドレスのみが返ってきます。

まずはシンプルにIPアドレスを通知するものを作りました。

echo off
chcp 65001
title 手動更新モード
SETLOCAL ENABLEDELAYEDEXPANSION

set username=
set password=
set hostname=
set newip=
set oldip=
set setip=

set /p username=<tmp\user.bin
set /p password=<tmp\pass.bin
set /p hostname=<tmp\host.bin

ren tmp\newip.txt oldip.txt
curl -k https://domains.google.com/checkip >tmp\newip.txt
set /p newip=<tmp\newip.txt
set /p oldip=<tmp\oldip.txt
cls
curl -k "https://%username%:%password%@domains.google.com/nic/update?hostname=!hostname!&myip=%newip%" >tmp\setip.bin
set /p setip=<tmp\setip.bin
cls
echo 手動更新作業が終了しました。
echo ===============================
echo 更新前アドレス:%oldip%
echo 現在のアドレス:%newip%
echo ===============================
echo 設定結果:!setip!
echo ===============================
echo [MANU]%date%-%time%,!setip! >>tmp\log.txt
del tmp\setip.bin
)
del tmp\oldip.txt
echo 10秒後にこのウィンドウは閉じられます。
timeout /t 10 /nobreak

これを定期的に実行するだけでも、IPアドレスの更新はできますが相手側サーバに通知を繰り返すことになるため、あまり好ましくありません。
流れとしては
1.自サーバIPチェック
2.→前回のIPと比較
3.→違う場合は取得したIPを通知,同じ場合は通知を行わない
といった流れにしたい訳です。これをバッチファイルで組んでみました。

echo off
rem 文字コード変更
chcp 65001
SETLOCAL ENABLEDELAYEDEXPANSION
rem 変数の宣言
set username=
set password=
set hostname=
set newip=
set oldip=
set setip=
set size=
rem 変数にID情報等をセット
set /p username=<tmp\user.bin
set /p password=<tmp\pass.bin
set /p hostname=<tmp\host.bin
title 定期更新モード %hostname%
rem 前回取得したIPアドレスのファイル(newip.txt)をリネーム(oldip.txt)
ren tmp\newip.txt oldip.txt
rem 現在のIPアドレスを取得してnewip.txtとして保存する
curl -k https://domains.google.com/checkip >tmp\newip.txt
rem 変数newipとoldipにそれぞれipアドレスを代入する
set /p newip=<tmp\newip.txt
set /p oldip=<tmp\oldip.txt
cls
rem 変数newipとoldipを比較して、一致しない場合は更新する
rem 更新の有無に関わらず、結果をlog.txtに追記していく
if %newip%==%oldip% (
  echo [AUTO]%date%-%time%,nochange >>tmp\log.txt
  echo IPアドレスは変更されていません。更新作業は行われません。
  echo ===============================
  echo 更新前アドレス:%oldip%
  echo 現在のアドレス:%newip%
  echo ===============================
) else (
  echo IPアドレスが違います。更新作業を行います。
  curl -k "https://%username%:%password%@domains.google.com/nic/update?hostname=!hostname!&myip=%newip%" >tmp\setip.bin
  set /p setip=<tmp\setip.bin
  cls
  echo 更新作業が終了しました。
  echo ===============================
  echo 更新前アドレス:%oldip%
  echo 現在のアドレス:%newip%
  echo ===============================
  echo 設定結果:!setip!
  echo ===============================
  echo [AUTO]%date%-%time%,!setip! >>tmp\log.txt
  del tmp\setip.bin
)
rem 比較に使用したoldip.txtを削除する
del tmp\oldip.txt

echo 3秒後にこのウィンドウは閉じられます。
timeout /t 3 /nobreak

改めて見ると、無駄が多い感じですが…。
そもそも全部ファイル出力してから変数に入れる必要が無いとか…。
そのへんはお好きに改造してください。上記バッチは一応、設定用バッチファイルを用意しているのでそちらで設定すれば、かんたんに使用できるようにしている(つもり)です。設定用バッチはこんな具合です。
初回設定時のみ、このバッチファイル内で聞かれたことを入力すればユーザ名とパスワード、ドメイン名のファイルが作成されて保存されます。
このあとで先程のバッチファイルを実行すればOKです。

chcp 65001
echo off
rd /s /q tmp
md tmp
echo 0.0.0.0 > tmp\newip.txt
echo logfile > tmp\log.txt
echo logfile > tmp\log_old.txt
set username=
set password=
set hostname=
cls
echo.
echo ////GoogleDDNS 初期設定ウィザード////
echo.
set /p username="GoogleDDNSユーザ名  ="
set /p password="GoogleDDNSパスワード="
set /p hostname="GoogleDDNS  ホスト名="

echo %username%> tmp\user.bin
echo %password%> tmp\pass.bin
echo %hostname%> tmp\host.bin

cls
echo 以下の内容で設定しました。
echo ===========================================
echo GoogleDDNSユーザ名  = %username%
echo GoogleDDNSパスワード= %password%
echo GoogleDDNS  ホスト名= %hostname%
echo ===========================================
echo.
pause

設定内容の確認だけのバッチファイルも作りました。

echo off
chcp 65001
title 設定内容確認
set username=
set password=
set hostname=
set /p username=<tmp\user.bin
set /p password=<tmp\pass.bin
set /p hostname=<tmp\host.bin
cls
echo 現在の設定内容
echo ===========================================
echo GoogleDDNSユーザ名  = %username%
echo GoogleDDNSパスワード= %password%
echo GoogleDDNS  ホスト名= %hostname%
echo ===========================================
echo.
pause

なおメインのバッチファイルをこのまま使用すると、ログファイルが際限なく増えていきますのでログファイルの制限をしました。
ログファイルが1MBを超えた場合は旧ログとして格納し、新しくログファイルを作成します。新しいログファイルも1MBを超えた場合、旧ログを削除して現状のログをまた旧ログとして格納し、新しいログを作る。といった動作です。
最大で2MB前後のログができるということです。

echo off
chcp 65001
SETLOCAL ENABLEDELAYEDEXPANSION
set username=
set password=
set hostname=
set newip=
set oldip=
set setip=
set size=
set /p username=<tmp\user.bin
set /p password=<tmp\pass.bin
set /p hostname=<tmp\host.bin
title 定期更新モード %hostname%

for %%i in (tmp\log.txt) do set size=%%~zi
cls

if %size% lss 1048576 (
  echo.
  echo ログファイルサイズは1MB未満です。
  echo ==================================
  echo ログファイルのサイズ:%size% byte
  echo ==================================
) else (
  echo.
  echo ファイルサイズは1MBを超えています。
  echo ==================================
  echo ログファイルのサイズ:%size% byte
  echo ==================================
  echo.
  echo 旧ログファイルを削除し、現在のログファイルを旧ログファイルに格納します。
  del tmp\log_old.txt
  ren tmp\log.txt log_old.txt
  echo logfile > tmp\log.txt
  echo.
  
)

timeout /t 3 /nobreak

ren tmp\newip.txt oldip.txt
curl -k https://domains.google.com/checkip >tmp\newip.txt
set /p newip=<tmp\newip.txt
set /p oldip=<tmp\oldip.txt
cls
if %newip%==%oldip% (
  echo [AUTO]%date%-%time%,nochange >>tmp\log.txt
  echo IPアドレスは変更されていません。更新作業は行われません。
  echo ===============================
  echo 更新前アドレス:%oldip%
  echo 現在のアドレス:%newip%
  echo ===============================
) else (
  echo IPアドレスが違います。更新作業を行います。
  curl -k "https://%username%:%password%@domains.google.com/nic/update?hostname=!hostname!&myip=%newip%" >tmp\setip.bin
  set /p setip=<tmp\setip.bin
  cls
  echo 更新作業が終了しました。
  echo ===============================
  echo 更新前アドレス:%oldip%
  echo 現在のアドレス:%newip%
  echo ===============================
  echo 設定結果:!setip!
  echo ===============================
  echo [AUTO]%date%-%time%,!setip! >>tmp\log.txt
  del tmp\setip.bin
)
del tmp\oldip.txt

echo 3秒後にこのウィンドウは閉じられます。
timeout /t 3 /nobreak

ここまで作れたら、本番サーバで実行するだけ…
のはずが、WindowsServer2016にはCurlが入っていない!
仕方ないので、Curlをダウンロードして導入しておきました。
https://curl.se/download.html

これで実行準備はOKです。最後にタスクスケジューラで定期実行して…。
と思ったら、毎回コマンドプロンプトのウィンドウが出て、すごく鬱陶しい!
バッチではどうにもならないので、VBSでバッチを最小化実行するスクリプトを作りました。ただただ、ddns.batを叩き、最小化実行するだけです。

Set objWSHShell = CreateObject("WScript.Shell")
objWSHShell.Run "cmd.exe /c ddns.bat", 7

これで一通りのバッチが組めましたので、あとはタスクスケジューラにお好みのスケジュールで登録して終了です。私は10分間隔で実行するようにしています。

今の所は問題なく使用できているようなので、まぁ良いのではないでしょうか。
一応zipでまとめておきましたので、使用されたい方は自己責任でどうぞ。

CMDDNS
https://zazameta.net/downloads/cmddns.zip

PowerShellで更新する方法もあるようですが、コマンドプロンプトのほうが(まだ)馴染みが深いので使ってみました。
Windows10の場合は先述の通りCurlが標準で入っているのでいいのですが、Curlが入っていない場合は別途導入しないといけないのが微妙ですね。

とはいえ、変なコマンドは使っていない(はず)なので
コマンドプロンプトでCurlさえ動かせれば、多分動くと思います。

当家では
Windows10 x64 (ver.1909)
Windows Server2016 Standard x64 (ver.1607)
で動作することを確認しました。

一応ZIPにはReadmeを書いておきましたので読んで使用してくださいね。



コメントを残す

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