--[[ ●IP マスカレードテーブル監視スクリプト   IP マスカレードテーブル使用ポート数を監視し、使用数が設定値 th_port を超え   たら、使用数が多い内側 IP アドレスと使用数を管理者にメールで送信するスクリ   プトです。 <説明> ・このファイルを 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 = (監視間隔) -- ★ -- 使用状況を監視する IP マスカレードの NAT ディスクリプタ番号(1 - 2147483647) nat_descriptor = (NAT ディスクリプタ番号) -- ★ -- 使用ポート数の閾値(1 - NAT 同時セッション数の最大値) th_port = (使用ポート数) -- ★ -- 抽出する内側 IP アドレスの個数(1, 2 ..) ip_num = (内側 IP アドレスの個数) -- ★ -- メールの設定 mail_tbl = { -- ★ smtp_address = "(SMTP サーバのアドレス)", from = "(送信元メールアドレス)", to = "(宛先メールアドレス)" } -- メールの送信に失敗した時に出力する SYSLOG のレベル(info, debug, notice) log_level = "(SYSLOG レベル)" -- ★ ----------------------## 設定値ここまで ##---------------------------- ------------------------------------------------------------ -- 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 ------------------------------------------------------------ -- IP マスカレードの使用ポート数を -- -- 内側 IP アドレスごとに求める関数 -- ------------------------------------------------------------ function nattbl_info(str, num) local rt_name rt_name = string.match(_RT_FIRM_REVISION, "(%w+) ") if (rt_name == "FWX120") then return nattbl_info_rtx1200(str, num) else return nattbl_info_srt100(str, num) end end ---------------------------------------------------------------- -- IP マスカレードの使用ポート数を -- -- 内側 IP アドレスごとに求める関数(FWX120版) -- ---------------------------------------------------------------- function nattbl_info_rtx1200(str, num) local result, n local ptn = "%s+%d+%s+(%d+%.%d+%.%d+%.%d+)%s+(%d+)" local t = {} n = 1 for k, v in string.gmatch(str, ptn) do t[n] = {k, v} if (n + 1 > num) then break end n = n + 1 end if (n < num) then num = n end result = string.format("ポート使用数の多い内側IPアドレス(上位%d個)\r\n", num) result = result .. string.format("No. 内側IPアドレス 使用中のポート数\r\n") for i, v in ipairs(t) do result = result .. string.format("%3d %14s %5d\r\n", i, v[1], v[2]) end return result end ------------------------------------------------------------ -- IP マスカレードの使用ポート数を -- -- 内側 IP アドレスごとに求める関数(SRT100 版) -- ------------------------------------------------------------ function nattbl_info_srt100(str, num) local result, n local ptn = "%s+%u+%s+(%d+%.%d+%.%d+%.%d+)%.%d+%s+%d+" local t = {} local a = {} for v in string.gmatch(str, ptn) do if (not t[v]) then t[v] = 1 else t[v] = t[v] + 1 end end n = 0 for k, v in pairs(t) do a[n + 1] = {k, v} n = n + 1 end bubble_sort(a, true) if (n < num) then num = n end result = string.format("ポート使用数の多い内側IPアドレス(上位%d個)\r\n", num) result = result .. string.format("No. 内側IPアドレス 使用中のポート数\r\n") for i, v in ipairs(a) do result = result .. string.format("%3d %14s %5d\r\n", i, v[1], v[2]) if (i + 1 > num) then break end end return result end ------------------------------------------------------------ -- 配列の並び替えを行う関数 -- ------------------------------------------------------------ function bubble_sort(t, reverse) local i, j for i = 1, #t do j = #t while (j > i) do if (reverse) then if (t[j-1][2] < t[j][2]) then t[j-1], t[j] = swap(t[j-1], t[j]) end else if (tbl[j-1][2] > tbl[j][2]) then t[j-1], t[j] = swap(t[j-1], t[j]) end end j = j - 1 end end end ------------------------------------------------------------ -- 2つの値を入れ替える関数 -- ------------------------------------------------------------ function swap(x, y) local temp temp = x x = y y = temp return x, y 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 rtn, nat_use, str local title = "NAT マスカレードテーブル 使用ポート数" local unit = "個" while (true) do mail_tbl.text = "" rtn, nat_use, str = natmsq_use_status(nat_descriptor) if (rtn) then if (nat_use) and (str) then if (nat_use > th_port) then mail_tbl.text = mail_tbl.text .. title .. "が閾値を超えています。\r\n" mail_tbl.text = mail_tbl.text .. string.format(" %s: %d%s\r\n 閾値: %d%s\r\n\r\n", title, nat_use, unit, th_port, unit) .. nattbl_info(str, ip_num) end end else mail_tbl.text = str end if (mail_tbl.text:len() > 0) then mail_tbl.subject = string.format("nat masquerade table (%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