mirror of
https://github.com/JamesonHuang/OpenWrt_Luci_Lua.git
synced 2024-11-24 06:10:11 +00:00
266 lines
7.3 KiB
Lua
266 lines
7.3 KiB
Lua
|
module ("xiaoqiang.module.XQPortForward", package.seeall)
|
|||
|
|
|||
|
local XQFunction = require("xiaoqiang.common.XQFunction")
|
|||
|
local XQConfigs = require("xiaoqiang.common.XQConfigs")
|
|||
|
|
|||
|
--
|
|||
|
-- Event
|
|||
|
--
|
|||
|
function hookLanIPChangeEvent(ip)
|
|||
|
if XQFunction.isStrNil(ip) then
|
|||
|
return
|
|||
|
end
|
|||
|
local uci = require("luci.model.uci").cursor()
|
|||
|
local lan = ip:gsub(".%d+$","")
|
|||
|
uci:foreach("firewall", "redirect",
|
|||
|
function(s)
|
|||
|
local ftype = tonumber(s.ftype)
|
|||
|
if ftype then
|
|||
|
local destip = s.dest_ip
|
|||
|
destip = lan.."."..destip:match(".(%d+)$")
|
|||
|
uci:set("firewall", s[".name"], "dest_ip", destip)
|
|||
|
end
|
|||
|
end
|
|||
|
)
|
|||
|
uci:commit("firewall")
|
|||
|
end
|
|||
|
|
|||
|
-- proto
|
|||
|
-- 1: tcp
|
|||
|
-- 2: udp
|
|||
|
-- 3: tcp and udp
|
|||
|
-- default: 1/tcp
|
|||
|
function _protoHelper(proto)
|
|||
|
if proto and type(proto) == "number" then
|
|||
|
if proto == 1 then
|
|||
|
return "tcp"
|
|||
|
elseif proto == 2 then
|
|||
|
return "udp"
|
|||
|
elseif proto == 3 then
|
|||
|
return "tcpudp"
|
|||
|
else
|
|||
|
return "tcp"
|
|||
|
end
|
|||
|
end
|
|||
|
if proto and type("proto") == "string" then
|
|||
|
if proto == "tcp" then
|
|||
|
return 1
|
|||
|
elseif proto == "udp" then
|
|||
|
return 2
|
|||
|
elseif proto == "tcpudp" then
|
|||
|
return 3
|
|||
|
else
|
|||
|
return 1
|
|||
|
end
|
|||
|
end
|
|||
|
return nil
|
|||
|
end
|
|||
|
|
|||
|
function _portCheck(port)
|
|||
|
if port and type(port) == "number" and port > 0 then
|
|||
|
return true
|
|||
|
else
|
|||
|
return false
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function _portRangeOverlap(port1, port2)
|
|||
|
local LuciUtil = require("luci.util")
|
|||
|
if port1 and port2 then
|
|||
|
port1 = tostring(port1)
|
|||
|
port2 = tostring(port2)
|
|||
|
if port1 == port2 then
|
|||
|
return false
|
|||
|
end
|
|||
|
local range1 = {}
|
|||
|
local range2 = {}
|
|||
|
if port1:match("-") then
|
|||
|
local sp = LuciUtil.split(port1, "-")
|
|||
|
range1["f"] = tonumber(sp[1])
|
|||
|
range1["t"] = tonumber(sp[2])
|
|||
|
else
|
|||
|
range1["f"] = tonumber(port1)
|
|||
|
range1["t"] = tonumber(port1)
|
|||
|
end
|
|||
|
if port2:match("-") then
|
|||
|
local sp = LuciUtil.split(port2, "-")
|
|||
|
range2["f"] = tonumber(sp[1])
|
|||
|
range2["t"] = tonumber(sp[2])
|
|||
|
else
|
|||
|
range2["f"] = tonumber(port2)
|
|||
|
range2["t"] = tonumber(port2)
|
|||
|
end
|
|||
|
if (range1.f >= range2.f and range1.f <= range2.t) or
|
|||
|
(range1.t >= range2.f and range1.t <= range2.t) then
|
|||
|
return true
|
|||
|
end
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
function _portConflictCheck(port)
|
|||
|
local uci = require("luci.model.uci").cursor()
|
|||
|
local result = false
|
|||
|
uci:foreach("firewall", "redirect",
|
|||
|
function(s)
|
|||
|
if _portRangeOverlap(port, s.src_dport) then
|
|||
|
result = true
|
|||
|
end
|
|||
|
end
|
|||
|
)
|
|||
|
return result
|
|||
|
end
|
|||
|
|
|||
|
function moduleOn()
|
|||
|
return #portForwards(0) > 0
|
|||
|
end
|
|||
|
|
|||
|
-- status
|
|||
|
-- 0:关闭
|
|||
|
-- 1:开启
|
|||
|
-- 2:冲突(DMZ功能开启,NAT功能就不能开启)
|
|||
|
function portForwardInfo()
|
|||
|
local XQDMZModule = require("xiaoqiang.module.XQDMZModule")
|
|||
|
local info = {}
|
|||
|
if XQDMZModule.moduleOn() then
|
|||
|
info["status"] = 2
|
|||
|
else
|
|||
|
info["status"] = moduleOn() and 1 or 0
|
|||
|
end
|
|||
|
return info
|
|||
|
end
|
|||
|
|
|||
|
-- ftype
|
|||
|
-- 0: all
|
|||
|
-- 1: port
|
|||
|
-- 2: range
|
|||
|
function portForwards(ftype)
|
|||
|
local uci = require("luci.model.uci").cursor()
|
|||
|
local portforwards = {}
|
|||
|
local forwardtype = tonumber(ftype) or 0
|
|||
|
uci:foreach("firewall", "redirect",
|
|||
|
function(s)
|
|||
|
local ftype = tonumber(s.ftype)
|
|||
|
if ftype and forwardtype == 0 or forwardtype == ftype then
|
|||
|
local item = {}
|
|||
|
item.name = s.name
|
|||
|
item.destip = s.dest_ip
|
|||
|
item.proto = _protoHelper(s.proto) or 1
|
|||
|
if ftype == 1 then
|
|||
|
item.srcport = tonumber(s.src_dport)
|
|||
|
item.destport = s.dest_port
|
|||
|
item.ftype = 1
|
|||
|
elseif ftype == 2 then
|
|||
|
item.ftype = 2
|
|||
|
local portrange = {}
|
|||
|
local LuciUtil = require("luci.util")
|
|||
|
local sp = LuciUtil.split(s.src_dport, "-")
|
|||
|
item.srcport = {
|
|||
|
["f"] = tonumber(sp[1]),
|
|||
|
["t"] = tonumber(sp[2])
|
|||
|
}
|
|||
|
end
|
|||
|
table.insert(portforwards, item)
|
|||
|
end
|
|||
|
end
|
|||
|
)
|
|||
|
return portforwards
|
|||
|
end
|
|||
|
|
|||
|
-- return
|
|||
|
-- 0: 设置成功
|
|||
|
-- 1: 参数不合法
|
|||
|
-- 2: 端口冲突(设置的端口和已有端口有重叠)
|
|||
|
-- 3: 功能冲突由于DMZ开启
|
|||
|
function setPortForward(name, ip, sport, dport, proto)
|
|||
|
if not XQFunction.isStrNil(ip) and _portCheck(tonumber(sport)) and _portCheck(tonumber(dport)) then
|
|||
|
local uci = require("luci.model.uci").cursor()
|
|||
|
if portForwardInfo().status == 2 then
|
|||
|
return 3
|
|||
|
end
|
|||
|
if _portConflictCheck(sport) then
|
|||
|
return 2
|
|||
|
end
|
|||
|
local sname = string.format("wan%srdr", tostring(sport))
|
|||
|
local options = {
|
|||
|
["src"] = "wan",
|
|||
|
["src_dport"] = sport,
|
|||
|
["proto"] = _protoHelper(tonumber(proto)) or "tcp",
|
|||
|
["target"] = "DNAT",
|
|||
|
["dest"] = "lan",
|
|||
|
["dest_port"] = dport,
|
|||
|
["dest_ip"] = ip,
|
|||
|
["ftype"] = 1,
|
|||
|
["name"] = name or ""
|
|||
|
}
|
|||
|
uci:section("firewall", "redirect", sname, options)
|
|||
|
uci:commit("firewall")
|
|||
|
return 0
|
|||
|
end
|
|||
|
return 1
|
|||
|
end
|
|||
|
|
|||
|
-- return
|
|||
|
-- 0: 设置成功
|
|||
|
-- 1: 参数不合法
|
|||
|
-- 2: 端口冲突(设置的端口和已有端口有重叠)
|
|||
|
function setRangePortForward(name, ip, fport, tport, proto)
|
|||
|
if not XQFunction.isStrNil(ip) and _portCheck(tonumber(fport)) and _portCheck(tonumber(tport)) then
|
|||
|
if tonumber(fport) > tonumber(tport) then
|
|||
|
return 1
|
|||
|
end
|
|||
|
local uci = require("luci.model.uci").cursor()
|
|||
|
local sport = tostring(fport).."-"..tostring(tport)
|
|||
|
if portForwardInfo().status == 2 then
|
|||
|
return 3
|
|||
|
end
|
|||
|
if _portConflictCheck(sport) then
|
|||
|
return 2
|
|||
|
end
|
|||
|
local sname = string.format("wan%srdr", tostring(fport))
|
|||
|
local options = {
|
|||
|
["src"] = "wan",
|
|||
|
["src_dport"] = sport,
|
|||
|
["proto"] = _protoHelper(tonumber(proto)) or "tcp",
|
|||
|
["target"] = "DNAT",
|
|||
|
["dest"] = "lan",
|
|||
|
["dest_ip"] = ip,
|
|||
|
["ftype"] = 2,
|
|||
|
["name"] = name or ""
|
|||
|
}
|
|||
|
uci:section("firewall", "redirect", sname, options)
|
|||
|
uci:commit("firewall")
|
|||
|
return 0
|
|||
|
end
|
|||
|
return 1
|
|||
|
end
|
|||
|
|
|||
|
function deletePortForward(port)
|
|||
|
if _portCheck(tonumber(port)) then
|
|||
|
local uci = require("luci.model.uci").cursor()
|
|||
|
local sname = string.format("wan%srdr", tostring(port))
|
|||
|
uci:delete("firewall", sname)
|
|||
|
uci:commit("firewall")
|
|||
|
return true
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
function deleteAllPortForward()
|
|||
|
local uci = require("luci.model.uci").cursor()
|
|||
|
uci:delete_all("firewall", "redirect",
|
|||
|
function(s)
|
|||
|
if s.ftype then
|
|||
|
return true
|
|||
|
else
|
|||
|
return false
|
|||
|
end
|
|||
|
end
|
|||
|
)
|
|||
|
uci:commit("firewall")
|
|||
|
return true
|
|||
|
end
|
|||
|
|
|||
|
function restart()
|
|||
|
os.execute("/etc/init.d/firewall restart")
|
|||
|
end
|