Chap-2. Dynamic DNS について

Sec-1.dynamicDNS を使って個人のドメインを運用するとは?
Sec-2.できる限り簡単にやるには
Sec-3.参考:ちょっとだけ凝ってみる(外部サイトを利用して自分のアドレスをチェック)
Sec-4.参考:もうちょっと、凝ってみる(ルータからIP address を切り出してみる。自前のサーバでやる)
Sec-5.参考:更に、凝ってみる(yamaha-NVR500 で全部やる)
Sec-6.参考:更に、ややこしい話。ーー 動的更新って何?

 現時点は 2019-11 です。このチャプターは、最初、2005年頃に書いた記憶があります。もう14年ほど前!
そのころと比べると、ネット回線も CPU もディスクもメモリも、ぐんと高速・大容量になりました。
2005 年頃は「いたずらにトラフィックを増やさないようにしなくちゃ!」という感覚で書いたものですが、今は、そんなこと、気にする必要がなくなってきました。
ネットの有名サイトとかスポーツ関係のサイトを見ると、CM の動画が貼り付けてあって、いたずらにトラフィックを増やしまくってますね。すごいトラフィック量だと思います。みんな、トラフィック量なんて気にしなくなってきた。
一方でサーバだって、高速 CPU になり、ディスクも高速大容量です。14年前とは比較になりません。
それで、トーンを変えて2019 年風に書き直しました。内容はそれほど変わっていませんが・・・時代に少しだけ迎合してみます。(笑)

このサイトは PC-UNIX のサイト、つまり宅サバ、宅 UNIX、宅プログラミングのサイトです。なので、そういう利用をしようとする方の、多少は参考になるようにしたいと思います。

なお、本当に必要なのは、Sec-1. Sec-2. だけです。後のセクションは単なる参考です。



Sec-1.dynamicDNS を使って個人のドメインを運用するとは?

 いきなり dynamicDNS を使うなどと聞くと、難しいことをやるようなイメージを持つかもしれません。でも、やることはシンプルです。下の図を見てください。

ddns-image1

 これは、マイドメインを非固定IP address で運用するときのイメージです。

万事この調子なら、うまく行きます。他にやることは無いです。しかし、非固定IP address なので、そうは行きません。何かの都合でアドレスが変わったりします。次の図です。

ddns-image2

 IP address が突然変わってしまった。そうすると、またネームサーバに届け出しないとなりません。そうでないと、次の人が自分のサイトにアクセスしようとしても、正しいアドレスが教えられないので、アクセス出来ません。
なので、さっきと同じようにネームサーバのサイトに届け出します。そうすると、次の問い合わせに対しては、先ほどと同じように正しいアドレスが通知されて、自分のサイトにアクセス可能になります。(^^)

自分のサイトに関してやることは、「ちゃんと届け出る」ってこと。それだけです。
では、dynamicDNS って何?って話ですが、それは「どこかのネームサーバのサイトの中でやること」です。
ドメインを運用する側では、特に知らなくても良いことです。参考に、Sec-6. に「DNS の動的更新」をごく簡単に説明していますが、はっきり言って余分な説明。不要な説明です。特別に興味があれば Sec-6. 見てください。





Sec-2.できる限り簡単にやるには

 ここのセクションが、多分本番ですね。(^^)
2005 年頃に記述した時は「なるべく余分なトラフィックを増加させないようにしよう」という意識で書きました。
でも、今日ではそんな心配は特にしなくても良いです。たかが、ネームサーバのサイトに届け出るアクセスなんて、せいぜい一時間に5回や10回くらいでしょう。そんなの、ネットに対しても、相手方のサーバに対しても、問題にならないと思います。遠慮なくアクセスしましょう。(笑)

2005 年頃の考え方、上から順に大事にしました。

当然、上から順に、ネームサーバのサイトに対するアクセスや外部へのアクセスは多くなっていきます。
でも、2019-11 現在は、順を逆転して考えても良いと思います。つまり

上から順番に、簡単なやり方です。
このセクションでは、1)のやり方を書きます。
それは、一行のシェルスクリプトを作って、cron を使い、(例えば)5分間隔でネームサーバのサイトに届け出するってやり方です。
単純明快。
下のが、その一行スクリプトです。例として私が利用している value-domain のサンプルです。こちらのIPアドレスは書かなくても大丈夫です。アクセスしてきたアドレスを使ってDDNS やってくれます。

#!/bin/sh
/bin/wget -q -O /HOGE/HOGEHOGE/log 'https://dyn.value-domain.com/cgi-bin/dyn.fcg?d=YOUR-DOMAIN&p=YOUR-PASSWD&h=*'
exit 0

例えばこれを実行属性 755 にして /usr/local/sbin/ddns-tool とかって入れておきます。その後は cron を使って(例えば)5分ごとにこれを走らせればオケですね。
debian なら、仮の例として以下のファイルを /etc/cron.d/root としておきます。

  2-57/5  *  *  *  * daemon  /usr/local/sbin/ddns-tool;touch /var/ddns/log

これは、/usr/local/sbin/ddns-tool 走らせて、その後 /var/ddns/log にタッチします。タッチするのは日付を残しておくためです。
一番最初の項目 2-57/5 は、毎時2分から始めて、5分おきに走らせます。毎時、2分、7、12、17、22、27って感じです。
なお、走らせる時、仮に daemon のユーザとして走らせると、何がしかのメールがしょっちゅう daemon 宛に来ちゃうかもしれません。なので、(見る必要なんて無いから)/etc/aliases を編集して、(例えば) daemon 宛のメールだとして、これを全部捨てておきます。こんな感じ。

daemon:        /dev/null

これを/etc/aliases に書き足して、# newliases コマンドを走らせ、DBを更新しておきます。それで、余分なメールはなくなります。
多分、こんなような方法が一番簡単で確実だと思います。
dyanmicDNS のネームサーバを引き受けてくれるサイトでは、たいてい上記のような wget コマンドを使ったやり方が書いてあるはずです。それを使えば、他のサイトでも上記と同じようにできるはずです。

このチャプタの記述としては、ここまでで終わりです。以上、です。
ここから下のセクションはもうちょっと趣味的にプログラムを楽しんでみようって感じの事柄です。やるべき必然性とか、やらなくてはならない必然性は、時代とともに、どんどんなくなっていきます。(笑)



Sec-3.参考:ちょっとだけ凝ってみる(外部サイトを利用して自分のアドレスをチェック)

 ちょっとだけ凝ってプログラム作ってみます。興味がなければ、見る必要の無いセクションです。
なお、プログラミング言語として、Lua を使います。
Lua を使う理由は
  1) 簡単な言語(言語仕様が小さくて、わかりやすい構造)
  2) 関数もデータで扱えるとか、コルーチンがあるとか、C言語とのFFIが使いやすいとか、後発言語らしく、よく出来てます。
  3) 処理系のコンパイル・インストールが簡単
  4) インタープリタ形式なので、扱いが柔軟、楽
こんなところが、選定の理由です。多分、ちょこっとC言語をかじっていれば、使うのは割合と簡単だし、perl あたりよりは使いやすいと思います。
 一方、Lua の欠点とかイマイチな点は、なんとなく、全体に「ゆるい」感じがするところ・・・かなあ。(笑)
なんとなくですが、ぴりっと引き締まった言語仕様・実装ではなくて、ゆるい感じがします。でも、面白いことに、その割には使いやすいです。これ、ひょっとしたらブラジル人の気質??(ブラジルの人が読んでたら、ごめんなさい)
ちょこっと「ゆるい」感じはするけど高性能って、なんだか、ブラジルサッカーみたいです(笑)
 言語選びとして、python って手もあると思いますが、インデント記述がブロック構造になるって、エディタの設定が変になっちゃったら、たちどころにプログラムの意味が変わっちゃう。そんなの使う自信がありません。明快なブロック記述子がある言語のほうが、安心です。なので、今の所 Lua -- do と end とか Scheme -- ( と ) が気にいってます。でも、世間での評判は python の圧勝ですね。
余談でした・・・・(汗)

外部には、自分の(my domain)のサイトのアドレスを教えてくれるところがあります。例えば

http://checkip.dyndns.org/
http://info.ddo.jp/remote_addr.php/

こんなところです。
上のサイトなら、アクセスするとこんな感じで答えてくれます。

dyn-screen

  

なので、これを wget コマンドで取得します。


$ wget  -O  log  http://checkip.dyndns.org/

 とすることにより


<html><head><title>Current IP Check</title></head><body>Current IP Address: 218.47.200.14</body></html>

 という log が得られます。見れば分かるように、ここにIPアドレスがありますので、これからアドレスを切り出せます。まず "IP Address:"という文字でスプリットして、前を捨て、次に "</body>" でスプリットして後ろを捨てれば、所望の IP アドレスだけを切り出せます。以下にスクリプトを示します。
プログラム中では、目的とするアドレスの前の余分な空白も、string.find(l, "%d")で見つけて、string.sub(l, a, #l) で削除しています。


local function getip()
    local url = "/bin/wget -O %s http://checkip.dyndns.org/"
    local fl = "/var/ddns/tmpfile"
    local cmd = string.format(url, fl)
    os.execute(cmd)
--
    local l;
    local a = io.open(fl)
    l = a:read("l")
    a:close()
    os.remove(fl)
--
    local a, b = string.find(l, "IP Address:")
    l = string.sub(l, b, #l)
    a, b = string.find(l, "</body>")
    l = string.sub(l, 1, a -1)
    a, b = string.find(l, "%d")
    l = string.sub(l, a, #l)
    return l
--
end

このローカル関数で IP address が戻り値になります。なので、後はこれを、あらかじめ取っておいたIP address と比較し、違っていればネームサーバのサイトに届け出します。以下に残りのプログラムを示します。以下は、私が使っている value-domain の例です。


#! /usr/local/bin/lua
local fl  = "/var/ddns/tmpfile"
local fl2 = "/var/ddns/ip-file"
--
local dm_url = "/usr/bin/wget -q -O %s 'http://dyn.value-domain.com/cgi-bin/dyn.fcg?d=%s&p=%s&h=*&i=%s'"
local dm_name = "hogehoge"
local dm_pw = "hogehoge"
local logfile = "/var/ddns/log"
--
--
local function getip()

  ここは、前のリスト利用

end
--
local function ipcmp(p, fl)
    local a = io.open(fl, "r")
    local ip = a:read("l")
    io.close(a)
--
    if ip == p then return true
    else return false
    end
end
--
local function update_file(fl, ip)
    a = io.open(fl, "w+")
    a:write(ip)
    io.close(a)
end
--
local function update_web (ip)
    local cmd
    cmd = string.format (dm_url, logfile, dm_name, dm_pw, ip)
    os.execute(cmd)
end
---
--- main program
---
--
local on = "off"
if (#arg == 1) and (arg[1] == "-f") then on = "on" end
local ip = getip()
if (on == "on") or (ipcmp(ip, fl2) == false) then
    update_file(fl2, ip); update_web(ip)
end
--

予め IP address を保存するファイルは /var/ddns/ip-file というファイルにしています。仮ファイルは同様のディレクトリを使って tmpfile としています。ログは同様のディレクトリを使って log という名前で残します。書き込みが成功したとか失敗したとか、ログを一回分だけ残します。

このプログラムの名前を仮に /usr/local/sbin/ddns-tool とかつけます。オプションとして引数に -f をつけて呼び出すと強制的にネームサーバのサイトに書き込みに行きます。なにも引数をつけずに実行すると、予め保存してある IP address と比較して違っていたときのみ、これを保存して、ネームサーバのサイトに書き込みに行きます。
使う時は、Sec-2. と同様に、cron を利用します。

Lua のプログラムリストはダウンロードできるようにしていません。今の時代のお勧めは Sec-2.です。一行スクリプトなのでリスト不要ですね。





Sec-4.参考:もうちょっと、凝ってみる(ルータからIP address を切り出してみる。自前のサーバでやる)

 今度は、Sec-3. の getip() 部分を、ローカルルータからIP address を読み出すように変えてみます。
今てもとにある余ったルータはNEC wr8700 って無線ルータです。なので、とりあえずこれでやってみます。
ルータにブラウザでアクセスすると、下のような画面になりますが、これは通称「ベーシック認証」ってやつです。


basic

(ここでは、仮にルータのIP address (lan 側)を192.168.0.18 にしてあります)
ベーシック認証のルータなら、Sec-3. と同じように wget コマンドを使ってページを読み込むことが出来ます。
なので、あらかじめどのページに目的の IP address があるかチェックしておきます。
wr8700 の場合は、index.cgi/info_main というページにアドレスがあります。なので

$ wget -O logfile --http-user='admin' --http-passwd='hogehoge' 'http://192.168.0.18/index.cgi/info_main'

こんな感じでページを取得出来ます。
これで取得できたものは logfile ってファイルになりますので、これを emacs で読んでみます。見づらい画面ですが、気にしない。



wget-screen


これをemacs で順に見ていって、WAN 側 IP address のところにたどり着く手順をチェックします。例えば

そんな具合にパターンを見つければ、後は Lua を使ってその一行を抽出します。
それで、目的の行(一行)を抽出したら、次にその一行文字列の中で、不要な部分を削除して IP address だけを抜き出します。
おそらく lua の文字列処理のライブラリ関数を使えば簡単です。
以下に、そうやって IP address を切り出した getip() 関数のリストを示します。これができれば、Sec-3. のリストで getip() のところだけ入れ替えれば、使えると思います。

local rt_url = "http://192.168.0.18/index.cgi/info_main"
local rt_uid = "admin"
local rt_pw = "hogehoge"
local fl  = "/var/ddns/tmpfile"
local fl2 = "/var/ddns/ip-file"
--
local function getip()
    local cmd = string.format("wget -O %s --http-user='%s' --http-passwd='%s' '%s'", fl, rt_uid, rt_pw, rt_url)
    os.execute(cmd)
--
-- 目的の行を抽出する
--
    local ll = nil
    local  i = 1
    for l in io.lines(fl) do
        i = i + 1
        if (i == 340) then
           ll = l; break;
        end
    end
    os.remove(fl)
--
-- 一行の中の余分な文字を削除する
--
    local a, b = string.find(ll, "<td class='small_item_td2'>")
    ll = string.sub(ll, b, #ll)
    a, b = string.find(ll, "/24</td>")
    ll = string.sub(ll, 1, a - 1)
    a, b = string.find(ll, "%d")
    ll = string.sub(ll, a, #ll)
    return ll
end


こんな具合にやると、自分のサイト内だけで作業が完結します。ネームサーバのサイトに書き込みに行く時以外は、ネットへのアクセスがありません。
2005 年頃はこんなようなやり方にこだわっていました。古い話です。でも、冒頭に書いたとおり、いまはネット回線が高速・大容量の時代です。もう、律儀にこんなやり方にこだわる必要は、なくなってきましたね。Sec-2. のやり方で十分だと思います。

このセクションのリストもダウンロードできるようにはしていません。やるなら Sec-2. のやり方がお勧めです。

そんな具合なので、このセクションとか、一つ前の Sec-3. を書いていて、なんとなく、虚しくなってきます(笑)
「俺って、どうでも良いこと、一生懸命やってるなあ・・・」って。(汗)
ま、でも、そもそも宅サバが、やってもやらなくても良い趣味的なことなので、それは言わないことにします(笑)




Sec-5.参考:更に、凝ってみる(yamaha-NVR500 で全部やる)

Sec-5-1.Luaプログラム本体

 今度はYAMAHAのルータ、NVR500に内蔵している言語 Lua を使って、ルータだけで dynamicDNS ツールが動くようにしてみます。接続の方法はPPPoEを前提にします。

Sec-4.でやったことを、ルータ単体の中で実行するだけです。以下にリストを示して、そこで説明を加えます。

なお、IPスプーフィングを弾くフィルターを自動設定するようにしています。
つまり、自分のサイトのアドレスを名乗る偽造パケットを弾きます。普通は、フィルター定義の中で書いておくのですが、動的dnsの場合は、自分のアドレスが随時変化するため、フィルター定義ファイルの中で決め打ちすることが出来ません。
そこで、dynamicDNS を実行する都度、自動的にフィルターを定義するようにしました。YAMAHA のLuaだと、以下の様に割合と簡単に実現出来ます。(^^)
なお、フィルター番号は200004 にしてあります。これはお好きな番号に変更してください。
もしも、そんなものは不要だ、という場合は、main プログラム中の ipfilter(ip) という行をコメントアウトしてください。

---
function getip ( )----------------------------------------------- ルータからIPアドレスを読み出す関数
  local s, s1, s2, i
--
  i, s = rt.command("show status pp 1")-------------------------- 読み出し
  i, s1 = string.find(s, "IP Address Local: ")------------------- IPアドレスの前の目印
  s1 = s1 + 1
  s2 = s1 + 23
  s = string.sub (s, s1, s2);
  s2 = string.find(s, ", Remote:")------------------------------- IPアドレスのすぐ後ろの目印
  s2 = s2 - 1
  s = string.sub(s, 1, s2)--------------------------------------- IPアドレスだけを切り出す
  return s------------------------------------------------------- 関数の戻り値として、IPアドレスを返す
end
---
function ipcmp( ip0, fl )---------------------------------------- 受け取ったIPアドレスとファイルの中のIPアドレスを比較する関数
  local fp, ip
  fp = io.open (fl);
  ip = fp:read ("*l");------------------------------------------- ファイルを開けて、IPアドレスを読む
  io.close (fp);
---
  if ip0 == ip then
    return true;------------------------------------------------- もし一致していたら、true を返す
  else
    fp = io.open(fl, "w")
    fp:write( ip0 )---------------------------------------------- もし一致していなければ、新しいIPアドレスをファイルに書いて
    io.close(fp)
    return false;------------------------------------------------ false を返す
  end
end
---
function update_web (ip) ---------------------------------------- 受け取ったIPアドレスでvalue-domain に書き込む
  url_val = "http://dyn.value-domain.com/cgi-bin/dyn.fcg?d=%s&p=%s&h=*&i=%s";
  dm = "*********";
  pw = "*********";
  tbl_rq = {url = "", method = "GET", save_file = "usb1:/data/log"};
  tbl_rq.url = string.format (url_val, dm, pw, ip);
---
  rt.httprequest (tbl_rq);--------------------------------------- ここで書き込む
end
---
function ipfilter(ip) ------------------------------------------- IPスプーフィングを弾くフィルターの自動設定(2017年5月追加)
    local cmd;
    cmd = string.format("ip filter 200004 reject %s/32 * * * *", ip) ----- IPアドレスは引数で与えます。
    rt.command("pp select 1")
    rt.command(cmd) --------------------------------------------- フィルター定義。
    rt.command("pp select none")
    rt.command("save") ------------------------------------------ 保存する。
end
---
--- main program------------------------------------------------- 非常に短い main プログラム
---
local fl, ip
if #arg == 0 then
  fl = "usb1:/data/ipfile";
else
  fl  = arg[1];
end
---
ip = getip()
if ipcmp(ip, fl) == false then----------------------------------- もしルータから取得したIPアドレスがファイルと一致しないなら
  update_web (ip);----------------------------------------------- update する
  ipfilter (ip); ------------------------------------------------ 併せて、IPスプーフィングを弾くようにする。
end
---

 プログラムに逐次解説入れてますので、これ以上の説明は不要と思います。二点注意。
*Lua 5.1、Lua 5.2ではファイルから一行読むのは、file:read("*l")ですが、Lua 5.3では file:read("l")です。仕様が変わっています。
*YAMAHAルータのコマンド rt.httprequest は https に対応していません。http のみです。
では、ここに上記ファイル及び付属スクリプトや readme の tar を置いておきます。



2017-11-07 補足
この日現在 NVR510 と NVR700W の Lua は https をサポートしています。それ以外の機種では、まだ未サポートです。
ここ "http://www.rtpro.yamaha.co.jp/RT/docs/lua/#version" を参照してください。
この様子から判断して、しばらくすると全機種で https がサポートされそうです。期待しましょう。(^^)

2019-10-23 補足
・・・・様子を見続けても、なかなか https に対応しませんね(汗)。NVR500 はメモリが少ないので、内蔵させるのは無理なのかもしれません。ssl ってかなりの大きなソフトらしいから・・・




Sec-5-2.使い方(NVR500)

 次にこのスクリプトの使い方です。

 NVR500は、まず本体にユーザーズエリアとしてRTFSというファイルシステムがあります。いわゆる / です。

# show  file  list  /  all

ってやるとファイルとして何が入っているか、分かります。いわゆる ls -l です。買ったままだと、当然カラ。
他に外部メモリーとして、USBが二つと、SDが一つ使えます。外部メモリーとLuaを使うためには、それぞれNVR500で設定が必要です。コマンド・リファレンス見てください。
ここでは、基本的にUSBのスロット1を使う前提で説明します。以下のような具合にファイルを収めます。

usb1:image

本体内臓のフラッシュメモリーの / を使うことも出来ますが、YAMAHAの説明では、本体内臓のメモリーを頻繁に読み書きすると、メモリがダメになることがあるとか・・・・・フラッシュメモリーって、そもそも、そういう物です。
なので、繰り返し読み書きする時はUSBかSDを使った方が良いです。いまどき、USBもSDもずいぶん安いので、おかしくなったら、新品に交換すればすみます。ルータ本体の補修(有料です)は、高くつきそう。

上の図のディレクトリー構成だと、コマンド実行するときは

# lua  usb1:/bin/ddns-tool.lua  [arg]

てな具合です。
説明が前後してますが、NVR500でUSBを使うときはFAT16またはFAT32でフォーマットしてないとダメです。YAMAHAのマニュアルには書いてあります。
それを読まずに、NTFSでフォーマットして使ってみたけど、ダメでした。FAT32だと、うまくいきました。
10年近く前に買った2GBのUSBですが、無事に動いてます。
上記のtarをPC-UNIXの適当なディレクトリで展開すると、ddns-tool.lua、cat.lua、init.lua の三つのスクリプトとreadme及びおまけのファイルができます。
value-domain であれば、本体プログラム中の update_web 関数で、ドメイン名とパスワードだけ直せば使えると思います。

各プログラムですが

です。

上の図を見て、手持ちのUSBメモリーにプログラムを入れてください。dataディレクトリは、最初のうちカラ・ディレクトリで構いません。やっているうちにipfile、logの二つのファイルが出来てきます。

試しにNVR500にUSBを挿して

# lua usb1:/bin/cat.lua usb1:/bin/init.lua

とかすると、init.luaの中身がcat出力されます。NVR500にはcatコマンドが無くて不便なので、このあんちょこなので、しのいでいます。
catプログラムが動いたら、次は本体、ddns-tool.luaを試してみます。

# lua usb1:/bin/ddns-tool.lua

すると、うまく動けば、空だった data ディレクトリに二つのファイル、ipfile、logが出来るはずです。さっきのcat.luaを使ってlogの中を見て

status=0
OK

の字が見えれば、オーケです。value-domain への書き込みに成功しました。
また、cat.luaを使ってipfileを見ると、IPアドレスが入っていると思います。自分のサイトのIPアドレスです。
このスクリプトはルータからIPアドレスを取ってきて、それを あらかじめ保存してあった ipfile と比較します。変化があれば新しいIPアドレスを ipfile に書き込んだ後、value-domain に書き込みに行きます。変化がなければ何もせずに終了です。
 もしも、すぐにもう一度試したいとき、そのまま試すと、次に取得するIPアドレスは、前に保存したipfileと同じです。なので、アドレスを取得し、比較して変化がなくて、プログラム終了です。value-domainのウェブサイトへ書き込みに行きません。書き込みに行かせるためには、ipfile の中身をクリアしておくのが手っ取り早い。それで

# lua  usb1:/bin/init.lua

とすると、一旦 ipfile がゼロクリアされますので、もう一度 ddns-tool.lua を実行したとき、value-domain のウェブサイトに書き込みに行きます。ログの時間をみれば、実際に書き込みに行ったかどうか、わかります。

 ここまで、お試しがうまく行ったら後は NVR500 のスケジュール機能を使って、定期的に実行するだけです。基本的な考え方として

となります。例えば、value-domainだと、一ヶ月に一度程度書き込みに行けば十分です。だからinit.luaは月一回実行します。一方、mydns.jpのサイトを見ると「一週間以上書き込みがないとアカウント削除」とかって書いてあった気がします。ですから、mydns.jpなら、一日一回くらいinit.luaを実行するのが良いと思います。
スケジュール機能の使い方も、NVR500コマンド・リファレンスを見てください。

参考までに、2016年12月上旬から NTT 光に変更した当サイトでは、以下のスケジュール(value-domain)です。
スタートアップ時はやらずに、年中、常に 5 分おきにIPアドレスチェックすることにしました。
また、毎月3日の午前3時3分にinit.lua を実行します。従って、少なくとも毎月3日の午前3時5分には、value-domain に書き込みに行きます。
今のところ、これで調子良く dynamicDNS 運用ができています。ヤマハルータ、頑張ってます。

なお、ddns-tool.lua のスクリプトは、IPアドレスが変わった時のみ USB メモリーにアドレスを保存書き込みします。IPアドレスの変更がなければ、書き込みをしません。だから毎 5 分ごとにチェックするといっても、USB メモリーへの書き込み頻度はそれほど高くないはずです。

schedule at 10 */* *:0,5,10,15,20,25,30,35,40,45,50,55 * lua usb1:/bin/ddns-tool.lua
schedule at 11 */3 3:03 * lua usb1:/bin/init.lua

補足1:
NVR500 のコンソール表示言語は、念のために US-ASCII モードにしてください。

補足2:
このやり方を一番上流側のルータでやれば、ルータの sshd、telnetd、httpd、ftpd、tftpd 等を落としておくことができます。すると仮に DMZ に置いた公開サーバが乗っ取られても、ルータの設定を勝手に書き換えられることは無くなります。YAMAHAルータならLAN内部からシリアル回線で管理が出来ますからね。
ルータにとってはシリアル回線って、すごく重要です。





Sec-6.参考:更に、ややこしい話 ーー 動的更新って何?

 やってみると動的更新の理解が深まりますが、あくまで参考程度のセクションです。知らなくてもなんら困りません。
あなたが既に自宅サーバで named を運用していて、ゾーンファイルなどの設定をやったことがあるものと仮定します。動的更新を実現するために、まずは named.conf を一部だけ書きなおします。
適当なゾーンを作り(実際に無くても良いので)これに動的更新を試みます。ここでは 192.168.200.0/24 をそのゾーンにします。
仮にこのゾーンを hoge.lan と名付けましょう。
あなたの named.conf に以下の行を追加しましょう。

zone "hoge.lan"{
   type  master;
   file  "hoge.lan";
   allow-update{ (あなたが named を運用しているホストのアドレス); };
};

 次に、hoge.lan というゾーンファイルを作成します。ゾーンファイルの作り方は、、、おわかりですよね。わからない方はオライリーの参考文献*を読んでください。ネットをやるなら必読書です。さて、そのゾーンファイルの中で

host1  in  a  192.168.200.1

 としておきます。つまり架空の hoge.lan というゾーンの中で、 host1 という架空のホストのアドレスを 192.168.200.1 としておくわけです。
この2つのファイルを所定の位置にコピーします。通常 named.conf は /etc に置かれ、ゾーンファイルは /etc/namedb に置かれます。あなたのホストの所定の位置に置いてください。それから named に対して

# kill  -HUP  (named の pid)

 と入力しますと、今設定した内容を named が読み込みます。これで動的更新を試す準備が整いました。さっそく試してみます。まず

$ host  host1.hoge.lan

と入力しますと

192.168.200.1

 と回答が帰ります。ゾーンファイルが正しく設定されたことがわかります。次に

$ nsupdate

 と入力した後に、続けて

>update    delete     host1.hoge.lan.    a
>update    add        host1.hoge.lan.    30    a    192.168.200.2
>

 と入力します。最後に一行空行を入れる必要があります。その後もう一度

$ host      host1.hoge.lan

 と入力すると

192.168.200.2

と回答が返り、動的に IP アドレスが変わったのが確認できます。
このようにして、手でゾーンファイルを書き換えることなく named に対してアドレスの変更を伝えるのが DNS の動的更新機能です。
ここでは動的更新の実感をつかむために、nsupdate というコマンドを試してみました。実施のサイトではこれと同様のことが自動で行われているはずですが、nsupdate コマンドを使っているとは限りません。また、ここで試したように IP アドレスを指定して動的更新を許しているわけではないと思います。BIND には認証キーを使うメカニズムがあるため、実際は認証キーを示してきた動的更新のみを許可する設定になっていると思います。
これは named.conf のなかで

allow-update { key  hogehogehoge.... };

 等のようにして、認証キーを使います。いまは、動的更新を試してみるだけですのでこれ以上深入りしません。興味のある人は参考文献*を読んでください。とりあえずここでは


「私たちが DynamicDNS のサイトに IP アドレスを届け出れば後はこれと同様の事、つまりDNS動的更新がそのサイト内で行われている」


と認識しておくにとどめます。



と、2005 年頃(10数年前)に書きました。でも、いま(2019-11)読み直してみると、どうでも良いことですね(汗)
書き直す機会に、よっぽど削除しようかと思いましたが、結局残しました。ま、せっかく書いたんだから、残させてください(笑)