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 |