NATディスクリプターを監視する

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

図 NATディスクリプターを監視する

IPマスカレードの使用ポート数を監視し、閾値を超えた場合にメールで通知するLuaスクリプトです。
使用するポート数の多い内側IPアドレスを抽出し、それぞれのIPアドレスが使用するポート数を通知します。

通知された内側IPアドレスが非常に多くのポートを占有している場合、そのアドレスに対してIPマスカレード変換セッション数制限機能で使用可能なポート数に制限をかけることにより、各ホストが均等にIPマスカレード変換を利用できるようになります。

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

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

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

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

ルーターの設定例

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 route default gateway pp 1
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 server (ISPより指定されたDNSサーバーのIPアドレス)
dns private address spoof on
フィルターの設定 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
Luaスクリプトのスケジュール設定 schedule at 1 startup * lua (Luaスクリプトファイル名)

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

設定値

-- 監視間隔 (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 == "RTX1200") or (rt_name == "NVR500") or (rt_name == "RTX3500") or (rt_name == "RTX5000") or (rt_name == "RTX810")) then
  return nattbl_info_rtx1200(str, num)
 else
  return nattbl_info_srt100(str, num)
 end
end

IPマスカレードの使用ポート数を内側IPアドレスごとに求める関数
(RTX5000、RTX3500、RTX1200、RTX810、NVR500)

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

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

設定値

-- 監視間隔 (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アドレスごとに求める関数
(RTX1210、RTX830、NVR700W、NVR510)

function nattbl_info_type2(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

配列の並び替えを行う関数

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_type2(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

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