ルーターの状態を監視し異常を通知する

管理番号:YMHRT-4583 
(最終更新日: 2023/7/26)

Luaスクリプト機能の対応機種は、RTX5000RTX3510RTX3500RTX1300RTX1220RTX1210RTX1200(Rev.10.01.16以降)、RTX830RTX810NVR700WNVR510NVR500FWX120vRXです。

ルーターの状態を監視し異常を通知する

定期的にルーターの状態を監視し、異常を検出した場合にメールで通知するLuaスクリプトです。
以下の状態ごとに閾値を指定し、閾値を超えた場合は異常が発生したと見なしてメールを送ります。

  • CPU使用率
  • メモリ使用率
  • 筐体内温度(※)
  • PPインターフェース回線使用率(送信負荷、受信負荷)
  • IPマスカレードで使用中のポート数

(※) 筐体内温度の計測に対応した機種を使用する場合だけ監視を行います。

NAT動作タイプによって、使用するLuaスクリプトが異なります。ご注意ください。
NAT動作タイプについての詳細は、NAT動作タイプの違いについて をご参照ください。

光回線に接続するためには、別途ONUが必要です。
NVR700WとNVR510は、本体のONUポートに小型ONUを装着することで、光回線に接続できます。

対応機種のうち、設定例を掲載している機種は、以下のとおりです。

機種 掲載内容 備考
NAT動作タイプ1 RTX5000 RTX3500 RTX1200 RTX810 NVR500 コマンド設定例
Luaスクリプト例
 
NAT動作タイプ2 RTX3510 RTX1300 RTX1220 RTX1210 RTX830 NVR700W NVR510 コマンド設定例
Luaスクリプト例
 

ルーターの設定例

ゲートウェイの設定 ip route default gateway pp 1
LANインターフェースの設定
(LAN1ポートを使用)
ip lan1 address 192.168.0.1/24
WANインターフェースの設定
(LAN2ポートを使用)
pp select 1
pp always-on on
pppoe use lan2
pp auth accept pap chap
pp auth myname (ISPに接続するID) (ISPに接続するパスワード)
ppp lcp mru on 1454
ppp ipcp ipaddress on
ppp ipcp msext on
ip pp mtu 1454
ip pp nat descriptor 1
ip pp secure filter in 1020 1030 2000
ip pp secure filter out 1010 1011 1012 1013 1014 1015 3000 dynamic 100 101 102 103 104 105 106 107
pp enable 1
フィルターの設定 ip filter source-route on
ip filter directed-broadcast on
ip filter 1010 reject * * udp,tcp 135 *
ip filter 1011 reject * * udp,tcp * 135
ip filter 1012 reject * * udp,tcp netbios_ns-netbios_ssn *
ip filter 1013 reject * * udp,tcp * netbios_ns-netbios_ssn
ip filter 1014 reject * * udp,tcp 445 *
ip filter 1015 reject * * udp,tcp * 445
ip filter 1020 reject 192.168.0.0/24 *
ip filter 1030 pass * 192.168.0.0/24 icmp
ip filter 2000 reject * *
ip filter 3000 pass * *
ip filter dynamic 100 * * ftp
ip filter dynamic 101 * * www
ip filter dynamic 102 * * domain
ip filter dynamic 103 * * smtp
ip filter dynamic 104 * * pop3
ip filter dynamic 105 * * submission
ip filter dynamic 106 * * tcp
ip filter dynamic 107 * * udp
NATの設定 nat descriptor type 1 masquerade
DHCPの設定 dhcp service server
dhcp server rfc2131 compliant except remain-silent
dhcp scope 1 192.168.0.2-192.168.0.100/24
DNSの設定 dns host lan1
dns server (ISPより指定されたDNSサーバーのIPアドレス)
dns private address spoof on
Luaスクリプトのスケジュール設定 schedule at 1 startup * lua (Luaスクリプトファイル名)

Luaスクリプト例 (NAT動作タイプ1)

下記のLuaスクリプトを取り出すことができます。

設定値

-- 監視間隔 (1-864000 秒)
idle_time = (監視間隔)

-- CPU使用率を監視する単位時間("5sec", "1min" または "5min")
cpu_time = "(単位時間)"

-- 監視する相手先情報番号(1 - 30)
peer_num = (相手先情報番号)

-- 使用状況を監視するIPマスカレードのNATディスクリプター番号(1 - 2147483647)
nat_descriptor = (NATディスクリプター番号)

-- 各状態の閾値
th_tbl = {
 cpu = (CPU使用率(%)),
 mem = (メモリ使用率(%)),
 tmp = (筐体内温度(℃)), -- RTX1200, RTX3500, RTX5000
 snd = (PPインターフェース送信負荷率(%)),
 rcv = (PPインターフェース受信負荷率(%)),
 nat = (IPマスカレード 使用ポート数(個))
}

-- 連続で閾値を超えたら異常と判断する回数、または正常な状態に復帰したと判断する回数(1, 2 ..)
count = (回数)

-- 正常な状態に復帰した場合にもメールを送るか否か(送る:true / 送らない:false)
down_mail = (true / false)

-- メールの設定
mail_tbl = {
 smtp_address = "(SMTPサーバーのアドレス)",
 from = "(送信元メールアドレス)",
 to = "(宛先メールアドレス)"
}

-- メールの送信に失敗したときに出力する SYSLOG のレベル(info, debug, notice)
log_level = "(SYSLOGレベル)"

指定した単位時間のCPU使用率を取得するための検索文字列を設定する関数

function set_cpu_ptn(key)
 local ptn

 if (key == "5sec") or (key == "1min") or (key == "5min") then
  ptn = "(%d+)%%%(" .. key .. "%)"
  return ptn
 end

 return nil
end

ルーターのハードウェアリソースの使用状況を取得する関数

function rt_res_status(t)
 local rtn, str
 local cmd = "show environment"
 
 rtn, str = rt.command(cmd)
 if (rtn) and (str) then
  for k, v in pairs(t) do
   v.val = str:match(v.ptn)
   if (v.val) then
    v.val = tonumber(v.val)
   end
  end
 else
  str = cmd .. "コマンド実行失敗\r\n\r\n"
 end

 return rtn, str
end

PPインターフェースの回線負荷率を求める関数

function pp_load_info(num)
 local rtn, snd, rcv, str, n
 local t = {}
 local cmd = "show status pp " .. tostring(num)
 local ptn = "負荷%:%s+(%d+)%.%d+%%"

 rtn, str = rt.command(cmd)
 if (rtn) and (str) then
  n = 1
  for w in string.gmatch(str, ptn) do
   t[n] = w
   n = n + 1
  end

  if (t[1]) then
   rcv = tonumber(t[1])
  end
  if (t[2]) then
   snd = tonumber(t[2])
  end
 end

 return rtn, rcv, snd, str
end

IPマスカレード使用ポート数を返す関数

function natmsq_use_status(id)
 local rtn, str, num
 local cmd = "show nat descriptor address " .. tostring(id)
 local ptn = "(%d+)個使用中"
 
 rtn, str = rt.command(cmd)
 if (rtn) and (str) then
  num = str:match(ptn)
  if (num) then
   num = tonumber(num)
  end
 else
  str = cmd .. "コマンド実行失敗\r\n"
 end

 return rtn, num, str
end

各状態の数値が閾値を超えたとき、または正常に復帰したときにメッセージを返す関数

function make_msg(t, val, th, down)
 local rtn
 local str = ""

 if (val) then
  rtn = count_proc(t, val, th)
  if (rtn < 0) then
   if (down) then
    str = t.title .. "が閾値以下の値に下がりました。\r\n"
   end
  elseif (rtn > 0) then
   str = t.title .. "が閾値を超えました。\r\n"
   str = str .. string.format(" %s: %d%s\r\n 閾値: %d%s\r\n\r\n",
      t.title, val, t.unit, th, t.unit)
  end
 end

 return str
end

閾値を超えた(または下回った)連続回数をカウントする関数

function count_proc(t, val, th)
 local rtn = 0

 if (val > th) then
  if (not t.flag) then
   t.over = t.over + 1
   if (t.over == count) then
    rtn = 1
    t.flag = true
   end
  else
   if (t.down > 0) then
    t.down = 0
   end
  end
 else
  if (t.flag) then
   t.down = t.down + 1
   if (t.down == count) then
    rtn = -1
    t.flag = false
    t.over = 0
    t.down = 0
   end
  else
   if (t.over > 0) then
    t.over = 0
   end
  end
 end

 return rtn

end

現在の日時を取得する関数

function time_stamp()
 local t

 t = os.date("*t")
 return string.format("%d/%02d/%02d %02d:%02d:%02d",
  t.year, t.month, t.day, t.hour, t.min, t.sec)
end

メインルーチン

-- ハードウェアリソース情報テーブル
local res_tbl = {
 cpu = {ptn = "", val = 0, over = 0, down = 0, flag = false, title = "CPU負荷率(" .. cpu_time .. ")", unit = "%"},
 mem = {ptn = "(%d+)%% used", val = 0, over = 0, down = 0, flag = false, title = "メモリ使用率", unit = "%"},
 tmp = {ptn = "筐体内温度%(℃%): (%d+)", val = 0, over = 0, down = 0, flag = false, title = "筐体内温度", unit = "℃"}
}
local pp_tbl = {
 rcv = {over = 0, down = 0, flag = false, title = "PP 受信負荷率", unit = "%"},
 snd = {over = 0, down = 0, flag = false, title = "PP 送信負荷率", unit = "%"}
}
local nat_tbl = {over = 0, down = 0, flag = false, title = "NAT マスカレードテーブル 使用ポート数", unit = "個"}

local rtn, str, nat_use
local rt_name = string.match(_RT_FIRM_REVISION, "(%w+)")

res_tbl.cpu.ptn = set_cpu_ptn(cpu_time)
assert(res_tbl.cpu.ptn)

while (true) do
 mail_tbl.text = ""

 -- CPU使用率, メモリ使用率 (,筐体内温度 RTX1200, RTX3500, RTX5000, RTX810)
 rtn, str = rt_res_status(res_tbl)
 if (rtn) then
  mail_tbl.text = mail_tbl.text .. make_msg(res_tbl.cpu, res_tbl.cpu.val, th_tbl.cpu, down_mail)
  mail_tbl.text = mail_tbl.text .. make_msg(res_tbl.mem, res_tbl.mem.val, th_tbl.mem, down_mail)
  if ((rt_name == "RTX1200") or (rt_name == "RTX3500") or (rt_name == "RTX5000") or (rt_name == "RTX810")) then
   mail_tbl.text = mail_tbl.text .. make_msg(res_tbl.tmp, res_tbl.tmp.val, th_tbl.tmp, down_mail)
  end
 end

 -- PPインターフェース 回線負荷率
 rtn, rcv, snd, str = pp_load_info(peer_num)
 if (rtn) then
  mail_tbl.text = mail_tbl.text .. make_msg(pp_tbl.rcv, rcv, th_tbl.rcv, down_mail)
  mail_tbl.text = mail_tbl.text .. make_msg(pp_tbl.snd, snd, th_tbl.snd, down_mail)
 else
  mail_tbl.text = str
 end

 -- IPマスカレード 使用ポート数
 rtn, nat_use, str = natmsq_use_status(nat_descriptor)
 if (rtn) then
  if (nat_use) then
   mail_tbl.text = mail_tbl.text .. make_msg(nat_tbl, nat_use, th_tbl.nat, down_mail)
  end
 else
  mail_tbl.text = str
 end

 if (mail_tbl.text:len() > 0) then
  mail_tbl.subject = string.format("resource loadwatch (%s)", time_stamp())
  rtn = rt.mail(mail_tbl)
  if (not rtn) then
   rt.syslog(log_level, "failed to send mail. (Luaスクリプトファイル名)")
  end
 end

 rt.sleep(idle_time)
end

Luaスクリプト例 (NAT動作タイプ2)

下記のLuaスクリプトを取り出すことができます。

設定値

-- 監視間隔 (1-864000 秒)
idle_time = (監視間隔)

-- CPU使用率を監視する単位時間("5sec", "1min" または "5min")
cpu_time = "(単位時間)"

-- 監視する相手先情報番号(1 - 30)
peer_num = (相手先情報番号)

-- 使用状況を監視するIPマスカレードのNATディスクリプター番号(1 - 2147483647)
nat_descriptor = (NATディスクリプター番号)

-- 各状態の閾値
th_tbl = {
 cpu = (CPU使用率(%)),
 mem = (メモリ使用率(%)),
 tmp = (筐体内温度(℃)), -- RTX1220, RTX1210
 snd = (PPインターフェース送信負荷率(%)),
 rcv = (PPインターフェース受信負荷率(%)),
 nat = (IPマスカレード 使用ポート数(セッション))
}

-- 連続で閾値を超えたら異常と判断する回数、または正常な状態に復帰したと判断する回数(1, 2 ..)
count = (回数)

-- 正常な状態に復帰した場合にもメールを送るか否か(送る:true / 送らない:false)
down_mail = (true / false)

-- メールの設定
mail_tbl = {
 smtp_address = "(SMTPサーバーのアドレス)",
 from = "(送信元メールアドレス)",
 to = "(宛先メールアドレス)"
}

-- メールの送信に失敗したときに出力する SYSLOG のレベル(info, debug, notice)
log_level = "(SYSLOGレベル)"

指定した単位時間のCPU使用率を取得するための検索文字列を設定する関数

function set_cpu_ptn(key)
 local ptn

 if (key == "5sec") or (key == "1min") or (key == "5min") then
  ptn = "(%d+)%%%(" .. key .. "%)"
  return ptn
 end

 return nil
end

ルーターのハードウェアリソースの使用状況を取得する関数

function rt_res_status(t)
 local rtn, str
 local cmd = "show environment"
 
 rtn, str = rt.command(cmd)
 if (rtn) and (str) then
  for k, v in pairs(t) do
   v.val = str:match(v.ptn)
   if (v.val) then
    v.val = tonumber(v.val)
   end
  end
 else
  str = cmd .. "コマンド実行失敗\r\n\r\n"
 end

 return rtn, str
end

PPインターフェースの回線負荷率を求める関数

function pp_load_info(num)
 local rtn, snd, rcv, str, n
 local t = {}
 local cmd = "show status pp " .. tostring(num)
 local ptn = "負荷%:%s+(%d+)%.%d+%%"

 rtn, str = rt.command(cmd)
 if (rtn) and (str) then
  n = 1
  for w in string.gmatch(str, ptn) do
   t[n] = w
   n = n + 1
  end

  if (t[1]) then
   rcv = tonumber(t[1])
  end
  if (t[2]) then
   snd = tonumber(t[2])
  end
 end

 return rtn, rcv, snd, str
end

IPマスカレード使用ポート数を返す関数

function natmsq_use_status(id)
 local rtn, str, num
 local cmd = "show nat descriptor address " .. tostring(id)
 local ptn = "(%d+) セッション"
 
 rtn, str = rt.command(cmd)
 if (rtn) and (str) then
  num = str:match(ptn)
  if (num) then
   num = tonumber(num)
  end
 else
  str = cmd .. "コマンド実行失敗\r\n"
 end

 return rtn, num, str
end

各状態の数値が閾値を超えたとき、または正常に復帰したときにメッセージを返す関数

function make_msg(t, val, th, down)
 local rtn
 local str = ""

 if (val) then
  rtn = count_proc(t, val, th)
  if (rtn < 0) then
   if (down) then
    str = t.title .. "が閾値以下の値に下がりました。\r\n"
   end
  elseif (rtn > 0) then
   str = t.title .. "が閾値を超えました。\r\n"
   str = str .. string.format(" %s: %d%s\r\n 閾値: %d%s\r\n\r\n",
      t.title, val, t.unit, th, t.unit)
  end
 end

 return str
end

閾値を超えた(または下回った)連続回数をカウントする関数

function count_proc(t, val, th)
 local rtn = 0

 if (val > th) then
  if (not t.flag) then
   t.over = t.over + 1
   if (t.over == count) then
    rtn = 1
    t.flag = true
   end
  else
   if (t.down > 0) then
    t.down = 0
   end
  end
 else
  if (t.flag) then
   t.down = t.down + 1
   if (t.down == count) then
    rtn = -1
    t.flag = false
    t.over = 0
    t.down = 0
   end
  else
   if (t.over > 0) then
    t.over = 0
   end
  end
 end

 return rtn

end

現在の日時を取得する関数

function time_stamp()
 local t

 t = os.date("*t")
 return string.format("%d/%02d/%02d %02d:%02d:%02d",
  t.year, t.month, t.day, t.hour, t.min, t.sec)
end

メインルーチン

-- ハードウェアリソース情報テーブル
local res_tbl = {
 cpu = {ptn = "", val = 0, over = 0, down = 0, flag = false, title = "CPU負荷率(" .. cpu_time .. ")", unit = "%"},
 mem = {ptn = "(%d+)%% used", val = 0, over = 0, down = 0, flag = false, title = "メモリ使用率", unit = "%"},
 tmp = {ptn = "筐体内温度%(℃%): (%d+)", val = 0, over = 0, down = 0, flag = false, title = "筐体内温度", unit = "℃"}
}
local pp_tbl = {
 rcv = {over = 0, down = 0, flag = false, title = "PP 受信負荷率", unit = "%"},
 snd = {over = 0, down = 0, flag = false, title = "PP 送信負荷率", unit = "%"}
}
local nat_tbl = {over = 0, down = 0, flag = false, title = "NAT マスカレードテーブル 使用ポート数", unit = " セッション"}

local rtn, str, nat_use
local rt_name = string.match(_RT_FIRM_REVISION, "(%w+)")

res_tbl.cpu.ptn = set_cpu_ptn(cpu_time)
assert(res_tbl.cpu.ptn)

while (true) do
 mail_tbl.text = ""

 -- CPU使用率, メモリ使用率 (,筐体内温度 RTX1220, RTX1210)
 rtn, str = rt_res_status(res_tbl)
 if (rtn) then
  mail_tbl.text = mail_tbl.text .. make_msg(res_tbl.cpu, res_tbl.cpu.val, th_tbl.cpu, down_mail)
  mail_tbl.text = mail_tbl.text .. make_msg(res_tbl.mem, res_tbl.mem.val, th_tbl.mem, down_mail)
  if ((rt_name == "RTX1210") or (rt_name == "RTX1220")) then
   mail_tbl.text = mail_tbl.text .. make_msg(res_tbl.tmp, res_tbl.tmp.val, th_tbl.tmp, down_mail)
  end
 end

 -- PPインターフェース 回線負荷率
 rtn, rcv, snd, str = pp_load_info(peer_num)
 if (rtn) then
  mail_tbl.text = mail_tbl.text .. make_msg(pp_tbl.rcv, rcv, th_tbl.rcv, down_mail)
  mail_tbl.text = mail_tbl.text .. make_msg(pp_tbl.snd, snd, th_tbl.snd, down_mail)
 else
  mail_tbl.text = str
 end

 -- IPマスカレード 使用ポート数
 rtn, nat_use, str = natmsq_use_status(nat_descriptor)
 if (rtn) then
  if (nat_use) then
   mail_tbl.text = mail_tbl.text .. make_msg(nat_tbl, nat_use, th_tbl.nat, down_mail)
  end
 else
  mail_tbl.text = str
 end

 if (mail_tbl.text:len() > 0) then
  mail_tbl.subject = string.format("resource loadwatch (%s)", time_stamp())
  rtn = rt.mail(mail_tbl)
  if (not rtn) then
   rt.syslog(log_level, "failed to send mail. (Luaスクリプトファイル名)")
  end
 end

 rt.sleep(idle_time)
end

【ご注意】
本設定例は、設定の参考例を示したもので、動作を保証するものではございません。
ご利用いただく際には、十分に評価・検証を実施してください。

メール

ご相談・お問い合わせ