前回に続き今回もLuaスクリプト機能の利用を紹介します。これまでルータの状態を定期的にメールで通知したり、ネットワーク内にある特定のパソコンをpingで応答監視する設定を紹介しました。今回はルータに異常が発生した時に管理者へメールで通知するLuaスクリプトを紹介します。ルータの停止・故障は社内ネットワークに多大な影響を与えます。ルータの過負荷や設置場所の環境による熱暴走など事前に異常を感知することで障害を防いだり被害を最小限にとどめることが可能になります。
ネットワーク構成
今回のネットワーク構成は下記になります。
ルータの設定はパソコンからインターネットの閲覧やメールが利用できるようになっています。
ルータ設定内容
今回利用するRTX1200の設定内容です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
login password * administrator password * console character euc ip route default gateway pp 1 ip filter source-route on ip filter directed-broadcast on ip lan1 address 192.168.0.1/24 pp select 1 pp keepalive interval 30 retry-interval=30 count=12 pp always-on on pppoe use lan2 pppoe auto connect on pppoe auto disconnect off pp auth accept pap chap pp auth myname (ISPの接続アカウント) (ISPのパスワード) ppp lcp mru on 1454 ppp ipcp ipaddress on ppp ipcp msext on ip pp mtu 1454 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 ip pp nat descriptor 1 pp enable 1 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 * * netmeeting ip filter dynamic 106 * * tcp ip filter dynamic 107 * * udp nat descriptor type 1 masquerade tftp host any dhcp service server dhcp server rfc2131 compliant except remain-silent dhcp scope 1 192.168.0.101-192.168.0.200/24 dns server pp 1 dns private address spoof on |
前回と同じインターネットに接続する一般的な設定になります。
ルータ監視スクリプト
今回もヤマハのサイトで公開されているLuaスクリプトを利用させて頂きます。
今回のLuaスクリプトはルータの状態を定期的にチェックし異常を検知した時に管理者にメールで異常を検知したことを通知します。今回、状態をチェックする項目は下記になります。
- CPU使用率
- メモリ使用率
- 筐体内温度
- PPインターフェース回線使用率(送信負荷、受信負荷)
- IPマスカレードで使用中のポート数
下記の内容をメモ帳にコピーして「rtx1200-monitoring.lua」のファイル名で保存します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
--[[ ●ルーターリソース監視スクリプト 一定の監視間隔毎にルーターの状態を監視し、設定した閾値を超えたら管理者に メールを送信して知らせるスクリプトです。 監視する情報は以下の通りです。 ・CPU 使用率 ・メモリ使用率 ・筐体内温度(RTX1200, RTX3500, RTX5000, RTX1210) ・PP 側回線使用率(送信/受信) ・IP マスカレード使用ポート数 各リソースの値が閾値を指定した回数だけ連続して超えた場合に、管理者にメール を送信します。その後、値が閾値を指定した回数だけ連続して下回った場合には、 正常値に戻ったと判断します。設定値 down_mail を true に設定している場合には、 正常値に戻った際にもメールを送信します。 <説明> ・このファイルを RTFS か外部メモリに保存してください。 ・本項目の config の設定では schedule at コマンドでルーター起動時に Lua スク リプトが実行されるように設定しています。 ・スクリプトを停止するときは terminate lua コマンドを実行してください。 ・再度、Lua スクリプトを実行する場合は lua コマンドで実行してください。 ・★マークの付いた設定値は変更が可能です。 <ノート> ・メールの送信失敗時に出力する SYSLOG レベルを指定可能です。 SYSLOG のレベルを指定するには、log_level を設定してください。 debug レベル、notice レベルの SYSLOG を出力するためには、それぞれ以下の設定 が必要です。 debug レベル ・・・ syslog debug on notice レベル・・・ syslog notice on ・本スクリプトファイルを編集する場合、文字コードは必ず Shift-JIS を使用してく ださい。 ]] --------------------------## 設定値 ##-------------------------------- -- 監視間隔(1 - 864000 秒) idle_time = 60 -- ★ -- CPU 負荷率を監視する単位時間("5sec" or "1min" or "5min") cpu_time = "1min" -- ★ -- 監視する相手先情報番号(1 - 30) peer_num = 1 -- ★ -- 使用状況を監視するIP マスカレードの NAT ディスクリプタ番号(1 - 2147483647) nat_descriptor = 1-- ★ -- 各リソースの閾値(1 - 99) th_tbl = { -- ★ cpu = 80, mem = 80, tmp = 40, -- RTX1200, RTX3500, RTX5000, RTX1210 snd = 80, rcv = 80, nat = 20 } -- 連続で閾値を超えたら異常と判断する回数、または正常な状態に復帰したと判断する回数(1, 2 ..) count = 1 -- ★ -- 正常な状態に復帰した場合にもメールを送るか否か(送る: true / 送らない: false) down_mail = true -- ★ -- メールの設定 mail_tbl = { -- ★ smtp_address = "(SMTPサーバのアドレス)", smtp_port = "587", smtp_auth_protocol = "plain", smtp_auth_name = "(アカウント名)", smtp_auth_password = "(パスワード)", from = "(送信元メールアドレス)", to = "(送信先メールアドレス)" } -- メールの送信に失敗した時に出力する SYSLOG のレベル (info, debug, notice) log_level = "info" -- ★ ----------------------## 設定値ここまで ##---------------------------- ------------------------------------------------------------ -- 指定した単位時間の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 .. "が閾値以下の値に下がりました。" 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, mem (,temp -- RTX1200, RTX3500, RTX5000, 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 == "RTX1200") or (rt_name == "RTX3500") or (rt_name == "RTX5000") or (rt_name == "RTX1210")) 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 -- nat 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. (rtx1200-monitoring.lua)") end end rt.sleep(idle_time) end |
各項目について説明します。
41行目
1 |
idle_time = 60 |
ルータの状態をチェックする間隔を設定します。設定値は秒で設定します。上記は60秒に1回ルータの状態をチェックし数値に異常がないかチェックします。
44行目
1 |
cpu_time = "1min" |
CPUの使用率をチェックする時間を設定します。設定値は「5sec」「1min」「5min」の中から得選択します。「1min」では1分間に1回CPUの使用率をチェックします。
47行目
1 |
peer_num = 1 |
監視する相手先番号を指定します。ルータ設定の8行目に
1 |
pp select 1 |
と指定しているので「1」を設定します。
50行目
1 |
nat_descriptor = 1 |
IP マスカレードの使用ポート数をチェックするため、IPマスカレードのNATディスクリプタ番号を指定します。ルータ設定の42行目に
1 |
nat descriptor type 1 masquerade |
と設定しているので「1」を設定します。
53行目から59行目
1 2 3 4 5 6 |
cpu = 80, mem = 80, tmp = 40, snd = 80, rcv = 80, nat = 20 |
各状態のしきい値を設定します。ここで設定した数値を超えると管理者にメールで異常を通知します。
- cpu・・・CPU使用率(%)
- mem・・・メモリ使用率(%)
- tmp・・・ルータの筐体温度(℃)
- snd・・・PPインターフェース送信の負荷率(%)
- rcv・・・PPインターフェース受信の負荷率(%)
- nat・・・IPマスカレードの使用ポート数(%)
63行目
1 |
count = 1 |
連続でしきい値を超えたら異常と判断する回数を設定します。ここでは1回でもしきい値を超えたら異常と判断したいため「1」を設定します。
66行目
1 |
down_mail = true |
しきい値が正常な値になった時にメールを通知するかしないかの設定になります。
「true」は正常な状態になった時に復旧メールを通知します。
「false」は正常な状態になった時に復旧メールを通知しません。
70行目から76行目
1 2 3 4 5 6 7 |
smtp_address = "(SMTPサーバのアドレス)", smtp_port = "587", smtp_auth_protocol = "plain", smtp_auth_name = "(アカウント名)", smtp_auth_password = "(パスワード)", from = "(送信元メールアドレス)", to = "(送信先メールアドレス)" |
メールを送信するための設定になります。
SubmissionポートやSMTP認証が必要な場合は上記設定が必須になります。
ファイルのアップロードから実行まで
ファイルのアップロード
ファイルのアップロードはTFTPコマンドを利用してルータへアップロードしました。
ルータ設定
TFTP接続を一時的に許可します。
1 |
tftp host any |
パソコンからのアップロードコマンド
1 2 |
cd c:\lua tftp 192.168.0.1 put rtx1200-monitoring.lua /rtx1200-monitoring.lua/(Administratorパス |
ルータのコンソールからファイルがアップロードされていることを確認します。
確認コマンド
1 |
show file list / |
Luaスクリプトの実行
今回も時間指定でスクリプトを実行させます。
1 |
schedule at 1 14:30:00 * lua /rtx1200-monitoring.lua |
これでルータの監視が開始されます。
ルータからのメール
■メモリ使用率、ルータ筐体内温度のしきい値を小さくした時のメール通知内容
■NATマスカレード使用数がしきい値を超えた時のメール通知内容
■NATマスカレード使用数がしきい値より下がった時のメール復旧通知内容
メール通知の内容は設定したしきい値を超えた項目・現在の数値・しきい値が記載されます。値が正常値になった時はしきい値より下がったという内容のメールが届きました。
まとめ
今回のLuaスクリプトを利用することでルータに異常が起きた際はすぐに検知することができます。特に筐体内温度などは実際ルータを直接触らないとわかならいことなので夏や通気性の良くないところへルータを設置している場合には非常に便利なLuaスクリプトになります。