applications/luci-firewall: complete rework firewall ui
- split zone setup, port forwards, traffic rules and firewall.user - add quickadd forms for various common rules like port forwards - add tool class for textual formatting and descriptions of rules - simplify controller, remove old mini admin remainders
This commit is contained in:
parent
24c4cce3ae
commit
033de64a0f
16 changed files with 1464 additions and 572 deletions
23
applications/luci-firewall/luasrc/controller/firewall.lua
Normal file
23
applications/luci-firewall/luasrc/controller/firewall.lua
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
module("luci.controller.firewall", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
entry({"admin", "network", "firewall"},
|
||||||
|
alias("admin", "network", "firewall", "zones"),
|
||||||
|
_("Firewall"), 60).i18n = "firewall"
|
||||||
|
|
||||||
|
entry({"admin", "network", "firewall", "zones"},
|
||||||
|
arcombine(cbi("firewall/zones"), cbi("firewall/zone-details")),
|
||||||
|
_("General Settings"), 10).leaf = true
|
||||||
|
|
||||||
|
entry({"admin", "network", "firewall", "forwards"},
|
||||||
|
arcombine(cbi("firewall/forwards"), cbi("firewall/forward-details")),
|
||||||
|
_("Port Forwards"), 20).leaf = true
|
||||||
|
|
||||||
|
entry({"admin", "network", "firewall", "rules"},
|
||||||
|
arcombine(cbi("firewall/rules"), cbi("firewall/rule-details")),
|
||||||
|
_("Traffic Rules"), 30).leaf = true
|
||||||
|
|
||||||
|
entry({"admin", "network", "firewall", "custom"},
|
||||||
|
cbi("firewall/custom"),
|
||||||
|
_("Custom Rules"), 40).leaf = true
|
||||||
|
end
|
|
@ -1,10 +0,0 @@
|
||||||
module("luci.controller.luci_fw.luci_fw", package.seeall)
|
|
||||||
|
|
||||||
function index()
|
|
||||||
entry({"admin", "network", "firewall"}, alias("admin", "network", "firewall", "zones"), _("Firewall"), 60).i18n = "firewall"
|
|
||||||
entry({"admin", "network", "firewall", "zones"}, arcombine(cbi("luci_fw/zones"), cbi("luci_fw/zone")), nil, 10).leaf = true
|
|
||||||
entry({"admin", "network", "firewall", "rule"}, arcombine(cbi("luci_fw/zones"), cbi("luci_fw/trule")), nil, 20).leaf = true
|
|
||||||
entry({"admin", "network", "firewall", "redirect"}, arcombine(cbi("luci_fw/zones"), cbi("luci_fw/rrule")), nil, 30).leaf = true
|
|
||||||
|
|
||||||
entry({"mini", "network", "portfw"}, cbi("luci_fw/miniportfw", {autoapply=true}), _("Port forwarding"), 70).i18n = "firewall"
|
|
||||||
end
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
--[[
|
||||||
|
LuCI - Lua Configuration Interface
|
||||||
|
|
||||||
|
Copyright 2011 Jo-Philipp Wich <xm@subsignal.org>
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local fs = require "nixio.fs"
|
||||||
|
|
||||||
|
local f = SimpleForm("firewall",
|
||||||
|
translate("Firewall - Custom Rules"),
|
||||||
|
translate("Custom rules allow you to execute arbritary iptables commands \
|
||||||
|
which are not otherwise covered by the firewall framework. \
|
||||||
|
The commands are executed after each firewall restart, right after \
|
||||||
|
the default ruleset has been loaded."))
|
||||||
|
|
||||||
|
local o = f:field(Value, "_custom")
|
||||||
|
|
||||||
|
o.template = "cbi/tvalue"
|
||||||
|
o.rows = 20
|
||||||
|
|
||||||
|
function o.cfgvalue(self, section)
|
||||||
|
return fs.readfile("/etc/firewall.user")
|
||||||
|
end
|
||||||
|
|
||||||
|
function o.write(self, section, value)
|
||||||
|
value = value:gsub("\r\n?", "\n")
|
||||||
|
fs.writefile("/etc/firewall.user", value)
|
||||||
|
end
|
||||||
|
|
||||||
|
return f
|
|
@ -1,8 +1,7 @@
|
||||||
--[[
|
--[[
|
||||||
LuCI - Lua Configuration Interface
|
LuCI - Lua Configuration Interface
|
||||||
|
|
||||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
Copyright 2011 Jo-Philipp Wich <xm@subsignal.org>
|
||||||
Copyright 2010 Jo-Philipp Wich <xm@subsignal.org>
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -18,18 +17,25 @@ local dsp = require "luci.dispatcher"
|
||||||
|
|
||||||
arg[1] = arg[1] or ""
|
arg[1] = arg[1] or ""
|
||||||
|
|
||||||
m = Map("firewall", translate("Traffic Redirection"),
|
m = Map("firewall",
|
||||||
translate("Traffic redirection allows you to change the " ..
|
translate("Firewall - Port Forwards"),
|
||||||
"destination address of forwarded packets."))
|
translate("This page allows you to change advanced properties of the port \
|
||||||
|
forwarding entry. In most cases there is no need to modify \
|
||||||
|
those settings."))
|
||||||
|
|
||||||
m.redirect = dsp.build_url("admin", "network", "firewall")
|
m.redirect = dsp.build_url("admin/network/firewall/forwards")
|
||||||
|
|
||||||
if not m.uci:get(arg[1]) == "redirect" then
|
if m.uci:get("firewall", arg[1]) ~= "redirect" then
|
||||||
luci.http.redirect(m.redirect)
|
luci.http.redirect(m.redirect)
|
||||||
return
|
return
|
||||||
|
else
|
||||||
|
local name = m:get(arg[1], "_name")
|
||||||
|
if not name or #name == 0 then
|
||||||
|
name = translate("(Unnamed Entry)")
|
||||||
|
end
|
||||||
|
m.title = "%s - %s" %{ translate("Firewall - Port Forwards"), name }
|
||||||
end
|
end
|
||||||
|
|
||||||
local has_v2 = nixio.fs.access("/lib/firewall/fw.sh")
|
|
||||||
local wan_zone = nil
|
local wan_zone = nil
|
||||||
|
|
||||||
m.uci:foreach("firewall", "zone",
|
m.uci:foreach("firewall", "zone",
|
||||||
|
@ -57,7 +63,7 @@ name = s:taboption("general", Value, "_name", translate("Name"))
|
||||||
name.rmempty = true
|
name.rmempty = true
|
||||||
name.size = 10
|
name.size = 10
|
||||||
|
|
||||||
src = s:taboption("general", Value, "src", translate("Source zone"))
|
src = s:taboption("advanced", Value, "src", translate("Source zone"))
|
||||||
src.nocreate = true
|
src.nocreate = true
|
||||||
src.default = "wan"
|
src.default = "wan"
|
||||||
src.template = "cbi/firewall_zonelist"
|
src.template = "cbi/firewall_zonelist"
|
||||||
|
@ -67,20 +73,26 @@ proto.optional = true
|
||||||
proto:value("tcp udp", "TCP+UDP")
|
proto:value("tcp udp", "TCP+UDP")
|
||||||
proto:value("tcp", "TCP")
|
proto:value("tcp", "TCP")
|
||||||
proto:value("udp", "UDP")
|
proto:value("udp", "UDP")
|
||||||
|
proto:value("icmp", "ICMP")
|
||||||
|
|
||||||
|
function proto.cfgvalue(...)
|
||||||
|
local v = Value.cfgvalue(...)
|
||||||
|
if not v or v == "tcpudp" then
|
||||||
|
return "tcp udp"
|
||||||
|
end
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
|
||||||
dport = s:taboption("general", Value, "src_dport", translate("External port"),
|
dport = s:taboption("general", Value, "src_dport", translate("External port"),
|
||||||
translate("Match incoming traffic directed at the given " ..
|
translate("Match incoming traffic directed at the given " ..
|
||||||
"destination port or port range on this host"))
|
"destination port or port range on this host"))
|
||||||
dport.datatype = "portrange"
|
dport.datatype = "portrange"
|
||||||
dport:depends("proto", "tcp")
|
|
||||||
dport:depends("proto", "udp")
|
|
||||||
dport:depends("proto", "tcpudp")
|
|
||||||
|
|
||||||
to = s:taboption("general", Value, "dest_ip", translate("Internal IP address"),
|
to = s:taboption("general", Value, "dest_ip", translate("Internal IP address"),
|
||||||
translate("Redirect matched incoming traffic to the specified " ..
|
translate("Redirect matched incoming traffic to the specified " ..
|
||||||
"internal host"))
|
"internal host"))
|
||||||
to.datatype = "ip4addr"
|
to.datatype = "ip4addr"
|
||||||
for i, dataset in ipairs(luci.sys.net.arptable()) do
|
for i, dataset in ipairs(sys.net.arptable()) do
|
||||||
to:value(dataset["IP address"])
|
to:value(dataset["IP address"])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -90,13 +102,6 @@ toport = s:taboption("general", Value, "dest_port", translate("Internal port (op
|
||||||
toport.optional = true
|
toport.optional = true
|
||||||
toport.placeholder = "0-65535"
|
toport.placeholder = "0-65535"
|
||||||
toport.datatype = "portrange"
|
toport.datatype = "portrange"
|
||||||
toport:depends("proto", "tcp")
|
|
||||||
toport:depends("proto", "udp")
|
|
||||||
toport:depends("proto", "tcpudp")
|
|
||||||
|
|
||||||
target = s:taboption("advanced", ListValue, "target", translate("Redirection type"))
|
|
||||||
target:value("DNAT")
|
|
||||||
target:value("SNAT")
|
|
||||||
|
|
||||||
dest = s:taboption("advanced", Value, "dest", translate("Destination zone"))
|
dest = s:taboption("advanced", Value, "dest", translate("Destination zone"))
|
||||||
dest.nocreate = true
|
dest.nocreate = true
|
||||||
|
@ -105,34 +110,32 @@ dest.template = "cbi/firewall_zonelist"
|
||||||
|
|
||||||
src_dip = s:taboption("advanced", Value, "src_dip",
|
src_dip = s:taboption("advanced", Value, "src_dip",
|
||||||
translate("Intended destination address"),
|
translate("Intended destination address"),
|
||||||
translate(
|
translate("Only match incoming traffic directed at the given IP address."))
|
||||||
"For DNAT, match incoming traffic directed at the given destination "..
|
|
||||||
"ip address. For SNAT rewrite the source address to the given address."
|
|
||||||
))
|
|
||||||
|
|
||||||
src_dip.optional = true
|
src_dip.optional = true
|
||||||
src_dip.datatype = "ip4addr"
|
src_dip.datatype = "ip4addr"
|
||||||
src_dip.placeholder = translate("any")
|
src_dip.placeholder = translate("any")
|
||||||
|
|
||||||
src_mac = s:taboption("advanced", Value, "src_mac", translate("Source MAC address"))
|
src_mac = s:taboption("advanced", DynamicList, "src_mac",
|
||||||
|
translate("Source MAC address"),
|
||||||
|
translate("Only match incoming traffic from these MACs."))
|
||||||
src_mac.optional = true
|
src_mac.optional = true
|
||||||
src_mac.datatype = "macaddr"
|
src_mac.datatype = "macaddr"
|
||||||
src_mac.placeholder = translate("any")
|
src_mac.placeholder = translate("any")
|
||||||
|
|
||||||
src_ip = s:taboption("advanced", Value, "src_ip", translate("Source IP address"))
|
src_ip = s:taboption("advanced", Value, "src_ip",
|
||||||
|
translate("Source IP address"),
|
||||||
|
translate("Only match incoming traffic from this IP or range."))
|
||||||
src_ip.optional = true
|
src_ip.optional = true
|
||||||
src_ip.datatype = "neg_ip4addr"
|
src_ip.datatype = "neg(ip4addr)"
|
||||||
src_ip.placeholder = translate("any")
|
src_ip.placeholder = translate("any")
|
||||||
|
|
||||||
sport = s:taboption("advanced", Value, "src_port", translate("Source port"),
|
sport = s:taboption("advanced", Value, "src_port",
|
||||||
translate("Match incoming traffic originating from the given " ..
|
translate("Source port"),
|
||||||
"source port or port range on the client host"))
|
translate("Only match incoming traffic originating from the given source port or port range on the client host"))
|
||||||
sport.optional = true
|
sport.optional = true
|
||||||
sport.datatype = "portrange"
|
sport.datatype = "portrange"
|
||||||
sport.placeholder = "0-65536"
|
sport.placeholder = translate("any")
|
||||||
sport:depends("proto", "tcp")
|
|
||||||
sport:depends("proto", "udp")
|
|
||||||
sport:depends("proto", "tcpudp")
|
|
||||||
|
|
||||||
reflection = s:taboption("advanced", Flag, "reflection", translate("Enable NAT Loopback"))
|
reflection = s:taboption("advanced", Flag, "reflection", translate("Enable NAT Loopback"))
|
||||||
reflection.rmempty = true
|
reflection.rmempty = true
|
|
@ -0,0 +1,141 @@
|
||||||
|
--[[
|
||||||
|
LuCI - Lua Configuration Interface
|
||||||
|
|
||||||
|
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local ds = require "luci.dispatcher"
|
||||||
|
local ft = require "luci.tools.firewall"
|
||||||
|
|
||||||
|
m = Map("firewall", translate("Firewall - Port Forwards"),
|
||||||
|
translate("Port forwarding allows remote computers on the Internet to \
|
||||||
|
connect to a specific computer or service within the \
|
||||||
|
private LAN."))
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Port Forwards
|
||||||
|
--
|
||||||
|
|
||||||
|
s = m:section(TypedSection, "redirect", translate("Port Forwards"))
|
||||||
|
s.template = "cbi/tblsection"
|
||||||
|
s.addremove = true
|
||||||
|
s.anonymous = true
|
||||||
|
s.sortable = true
|
||||||
|
s.extedit = ds.build_url("admin/network/firewall/forwards/%s")
|
||||||
|
s.template_addremove = "firewall/cbi_addforward"
|
||||||
|
|
||||||
|
function s.create(self, section)
|
||||||
|
local n = m:formvalue("_newfwd.name")
|
||||||
|
local p = m:formvalue("_newfwd.proto")
|
||||||
|
local e = m:formvalue("_newfwd.extport")
|
||||||
|
local a = m:formvalue("_newfwd.intaddr")
|
||||||
|
local i = m:formvalue("_newfwd.intport")
|
||||||
|
|
||||||
|
if p == "other" or (p and a) then
|
||||||
|
created = TypedSection.create(self, section)
|
||||||
|
|
||||||
|
self.map:set(created, "target", "DNAT")
|
||||||
|
self.map:set(created, "src", "wan")
|
||||||
|
self.map:set(created, "dest", "lan")
|
||||||
|
self.map:set(created, "proto", (p ~= "other") and p or "all")
|
||||||
|
self.map:set(created, "src_dport", e)
|
||||||
|
self.map:set(created, "dest_ip", a)
|
||||||
|
self.map:set(created, "dest_port", i)
|
||||||
|
self.map:set(created, "_name", n)
|
||||||
|
end
|
||||||
|
|
||||||
|
if p ~= "other" then
|
||||||
|
created = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function s.parse(self, ...)
|
||||||
|
TypedSection.parse(self, ...)
|
||||||
|
if created then
|
||||||
|
m.uci:save("firewall")
|
||||||
|
luci.http.redirect(ds.build_url(
|
||||||
|
"admin", "network", "firewall", "redirect", created
|
||||||
|
))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function s.filter(self, sid)
|
||||||
|
return (self.map:get(sid, "target") ~= "SNAT")
|
||||||
|
end
|
||||||
|
|
||||||
|
name = s:option(DummyValue, "_name", translate("Name"))
|
||||||
|
function name.cfgvalue(self, s)
|
||||||
|
return self.map:get(s, "_name") or "-"
|
||||||
|
end
|
||||||
|
|
||||||
|
proto = s:option(DummyValue, "proto", translate("Protocol"))
|
||||||
|
proto.rawhtml = true
|
||||||
|
function proto.cfgvalue(self, s)
|
||||||
|
return ft.fmt_proto(self.map:get(s, "proto")) or "Any"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
src = s:option(DummyValue, "src", translate("Source"))
|
||||||
|
src.rawhtml = true
|
||||||
|
src.width = "20%"
|
||||||
|
function src.cfgvalue(self, s)
|
||||||
|
local z = ft.fmt_zone(self.map:get(s, "src"))
|
||||||
|
local a = ft.fmt_ip(self.map:get(s, "src_ip"))
|
||||||
|
local p = ft.fmt_port(self.map:get(s, "src_port"))
|
||||||
|
local m = ft.fmt_mac(self.map:get(s, "src_mac"))
|
||||||
|
|
||||||
|
local s = "From %s in %s " %{
|
||||||
|
(a or "<var>any host</var>"),
|
||||||
|
(z or "<var>any zone</var>")
|
||||||
|
}
|
||||||
|
|
||||||
|
if p and m then
|
||||||
|
s = s .. "with source %s and %s" %{ p, m }
|
||||||
|
elseif p or m then
|
||||||
|
s = s .. "with source %s" %( p or m )
|
||||||
|
end
|
||||||
|
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
via = s:option(DummyValue, "via", translate("Via"))
|
||||||
|
via.rawhtml = true
|
||||||
|
via.width = "20%"
|
||||||
|
function via.cfgvalue(self, s)
|
||||||
|
local a = ft.fmt_ip(self.map:get(s, "src_dip"))
|
||||||
|
local p = ft.fmt_port(self.map:get(s, "src_dport"))
|
||||||
|
|
||||||
|
--local z = self.map:get(s, "src")
|
||||||
|
--local s = "To %s " %(a or "<var>any %s IP</var>" %( z or "router" ))
|
||||||
|
|
||||||
|
return "To %s%s" %{
|
||||||
|
(a or "<var>any router IP</var>"),
|
||||||
|
(p and " at %s" % p or "")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
dest = s:option(DummyValue, "dest", translate("Destination"))
|
||||||
|
dest.rawhtml = true
|
||||||
|
dest.width = "30%"
|
||||||
|
function dest.cfgvalue(self, s)
|
||||||
|
local z = ft.fmt_zone(self.map:get(s, "dest"))
|
||||||
|
local a = ft.fmt_ip(self.map:get(s, "dest_ip"))
|
||||||
|
local p = ft.fmt_port(self.map:get(s, "dest_port")) or
|
||||||
|
ft.fmt_port(self.map:get(s, "src_dport"))
|
||||||
|
|
||||||
|
return "Forward to %s%s in %s " %{
|
||||||
|
(a or "<var>any host</var>"),
|
||||||
|
(p and ", %s" % p or ""),
|
||||||
|
(z or "<var>any zone</var>")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
return m
|
|
@ -0,0 +1,300 @@
|
||||||
|
--[[
|
||||||
|
LuCI - Lua Configuration Interface
|
||||||
|
|
||||||
|
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||||
|
Copyright 2010 Jo-Philipp Wich <xm@subsignal.org>
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local sys = require "luci.sys"
|
||||||
|
local dsp = require "luci.dispatcher"
|
||||||
|
local nxo = require "nixio"
|
||||||
|
|
||||||
|
local nw = require "luci.model.network"
|
||||||
|
local m, s, o, k, v
|
||||||
|
|
||||||
|
arg[1] = arg[1] or ""
|
||||||
|
|
||||||
|
m = Map("firewall",
|
||||||
|
translate("Firewall - Traffic Rules"),
|
||||||
|
translate("This page allows you to change advanced properties of the \
|
||||||
|
traffic rule entry, such as matched source and destination \
|
||||||
|
hosts."))
|
||||||
|
|
||||||
|
m.redirect = dsp.build_url("admin/network/firewall/rules")
|
||||||
|
|
||||||
|
nw.init(m.uci)
|
||||||
|
|
||||||
|
local rule_type = m.uci:get("firewall", arg[1])
|
||||||
|
if rule_type == "redirect" and m:get(arg[1], "target") ~= "SNAT" then
|
||||||
|
rule_type = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if not rule_type then
|
||||||
|
luci.http.redirect(m.redirect)
|
||||||
|
return
|
||||||
|
|
||||||
|
--
|
||||||
|
-- SNAT
|
||||||
|
--
|
||||||
|
elseif rule_type == "redirect" then
|
||||||
|
|
||||||
|
local name = m:get(arg[1], "_name")
|
||||||
|
if not name or #name == 0 then
|
||||||
|
name = translate("(Unnamed SNAT)")
|
||||||
|
else
|
||||||
|
name = "SNAT %s" % name
|
||||||
|
end
|
||||||
|
|
||||||
|
m.title = "%s - %s" %{ translate("Firewall - Traffic Rules"), name }
|
||||||
|
|
||||||
|
local wan_zone = nil
|
||||||
|
|
||||||
|
m.uci:foreach("firewall", "zone",
|
||||||
|
function(s)
|
||||||
|
local n = s.network or s.name
|
||||||
|
if n then
|
||||||
|
local i
|
||||||
|
for i in n:gmatch("%S+") do
|
||||||
|
if i == "wan" then
|
||||||
|
wan_zone = s.name
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
s = m:section(NamedSection, arg[1], "redirect", "")
|
||||||
|
s.anonymous = true
|
||||||
|
s.addremove = false
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "_name", translate("Name"))
|
||||||
|
o.rmempty = true
|
||||||
|
o.size = 10
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "proto",
|
||||||
|
translate("Protocol"),
|
||||||
|
translate("You may specify multiple by selecting \"-- custom --\" and \
|
||||||
|
then entering protocols separated by space."))
|
||||||
|
|
||||||
|
o:value("all", "All protocols")
|
||||||
|
o:value("tcp udp", "TCP+UDP")
|
||||||
|
o:value("tcp", "TCP")
|
||||||
|
o:value("udp", "UDP")
|
||||||
|
o:value("icmp", "ICMP")
|
||||||
|
|
||||||
|
function o.cfgvalue(...)
|
||||||
|
local v = Value.cfgvalue(...)
|
||||||
|
if not v or v == "tcpudp" then
|
||||||
|
return "tcp udp"
|
||||||
|
end
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "src", translate("Source zone"))
|
||||||
|
o.nocreate = true
|
||||||
|
o.default = "wan"
|
||||||
|
o.template = "cbi/firewall_zonelist"
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(DynamicList, "src_mac", translate("Source MAC address"))
|
||||||
|
o.rmempty = true
|
||||||
|
o.datatype = "neg(macaddr)"
|
||||||
|
o.placeholder = translate("any")
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "src_ip", translate("Source IP address"))
|
||||||
|
o.rmempty = true
|
||||||
|
o.datatype = "neg(ip4addr)"
|
||||||
|
o.placeholder = translate("any")
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "src_port",
|
||||||
|
translate("Source port"),
|
||||||
|
translate("Match incoming traffic originating from the given source \
|
||||||
|
port or port range on the client host."))
|
||||||
|
o.rmempty = true
|
||||||
|
o.datatype = "neg(portrange)"
|
||||||
|
o.placeholder = translate("any")
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "dest", translate("Destination zone"))
|
||||||
|
o.nocreate = true
|
||||||
|
o.default = "lan"
|
||||||
|
o.template = "cbi/firewall_zonelist"
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "dest_ip", translate("Destination IP address"))
|
||||||
|
o.datatype = "neg(ip4addr)"
|
||||||
|
|
||||||
|
for i, dataset in ipairs(luci.sys.net.arptable()) do
|
||||||
|
o:value(dataset["IP address"])
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "dest_port",
|
||||||
|
translate("Destination port"),
|
||||||
|
translate("Match forwarded traffic to the given destination port or \
|
||||||
|
port range."))
|
||||||
|
|
||||||
|
o.rmempty = true
|
||||||
|
o.placeholder = translate("any")
|
||||||
|
o.datatype = "portrange"
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "src_dip",
|
||||||
|
translate("SNAT IP address"),
|
||||||
|
translate("Rewrite matched traffic to the given address."))
|
||||||
|
o.rmempty = false
|
||||||
|
o.datatype = "ip4addr"
|
||||||
|
|
||||||
|
for k, v in ipairs(nw:get_interfaces()) do
|
||||||
|
local a
|
||||||
|
for k, a in ipairs(v:ipaddrs()) do
|
||||||
|
o:value(a:host():string(), '%s (%s)' %{
|
||||||
|
a:host():string(), v:shortname()
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "src_dport", translate("SNAT port"),
|
||||||
|
translate("Rewrite matched traffic to the given source port. May be \
|
||||||
|
left empty to only rewrite the IP address."))
|
||||||
|
o.datatype = "portrange"
|
||||||
|
o.rmempty = true
|
||||||
|
o.placeholder = translate('Do not rewrite')
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Rule
|
||||||
|
--
|
||||||
|
else
|
||||||
|
s = m:section(NamedSection, arg[1], "rule", "")
|
||||||
|
s.anonymous = true
|
||||||
|
s.addremove = false
|
||||||
|
|
||||||
|
s:option(Value, "_name", translate("Name").." "..translate("(optional)"))
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(ListValue, "family", translate("Restrict to address family"))
|
||||||
|
o.rmempty = true
|
||||||
|
o:value("", translate("IPv4 and IPv6"))
|
||||||
|
o:value("ipv4", translate("IPv4 only"))
|
||||||
|
o:value("ipv6", translate("IPv6 only"))
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "proto", translate("Protocol"))
|
||||||
|
o:value("all", translate("Any"))
|
||||||
|
o:value("tcp udp", "TCP+UDP")
|
||||||
|
o:value("tcp", "TCP")
|
||||||
|
o:value("udp", "UDP")
|
||||||
|
o:value("icmp", "ICMP")
|
||||||
|
|
||||||
|
function o.cfgvalue(...)
|
||||||
|
local v = Value.cfgvalue(...)
|
||||||
|
if not v or v == "tcpudp" then
|
||||||
|
return "tcp udp"
|
||||||
|
end
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(DynamicList, "icmp_type", translate("Match ICMP type"))
|
||||||
|
o:value("", "any")
|
||||||
|
o:value("echo-reply")
|
||||||
|
o:value("destination-unreachable")
|
||||||
|
o:value("network-unreachable")
|
||||||
|
o:value("host-unreachable")
|
||||||
|
o:value("protocol-unreachable")
|
||||||
|
o:value("port-unreachable")
|
||||||
|
o:value("fragmentation-needed")
|
||||||
|
o:value("source-route-failed")
|
||||||
|
o:value("network-unknown")
|
||||||
|
o:value("host-unknown")
|
||||||
|
o:value("network-prohibited")
|
||||||
|
o:value("host-prohibited")
|
||||||
|
o:value("TOS-network-unreachable")
|
||||||
|
o:value("TOS-host-unreachable")
|
||||||
|
o:value("communication-prohibited")
|
||||||
|
o:value("host-precedence-violation")
|
||||||
|
o:value("precedence-cutoff")
|
||||||
|
o:value("source-quench")
|
||||||
|
o:value("redirect")
|
||||||
|
o:value("network-redirect")
|
||||||
|
o:value("host-redirect")
|
||||||
|
o:value("TOS-network-redirect")
|
||||||
|
o:value("TOS-host-redirect")
|
||||||
|
o:value("echo-request")
|
||||||
|
o:value("router-advertisement")
|
||||||
|
o:value("router-solicitation")
|
||||||
|
o:value("time-exceeded")
|
||||||
|
o:value("ttl-zero-during-transit")
|
||||||
|
o:value("ttl-zero-during-reassembly")
|
||||||
|
o:value("parameter-problem")
|
||||||
|
o:value("ip-header-bad")
|
||||||
|
o:value("required-option-missing")
|
||||||
|
o:value("timestamp-request")
|
||||||
|
o:value("timestamp-reply")
|
||||||
|
o:value("address-mask-request")
|
||||||
|
o:value("address-mask-reply")
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "src", translate("Source zone"))
|
||||||
|
o.nocreate = true
|
||||||
|
o.allowany = true
|
||||||
|
o.default = "wan"
|
||||||
|
o.template = "cbi/firewall_zonelist"
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "src_mac", translate("Source MAC address"))
|
||||||
|
o.datatype = "list(macaddr)"
|
||||||
|
o.placeholder = translate("any")
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "src_ip", translate("Source address"))
|
||||||
|
o.datatype = "neg(ipaddr)"
|
||||||
|
o.placeholder = translate("any")
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "src_port", translate("Source port"))
|
||||||
|
o.datatype = "list(neg,portrange)"
|
||||||
|
o.placeholder = translate("any")
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "dest", translate("Destination zone"))
|
||||||
|
o.nocreate = true
|
||||||
|
o.allowany = true
|
||||||
|
o.allowlocal = true
|
||||||
|
o.template = "cbi/firewall_zonelist"
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "dest_ip", translate("Destination address"))
|
||||||
|
o.datatype = "neg(ipaddr)"
|
||||||
|
o.placeholder = translate("any")
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(Value, "dest_port", translate("Destination port"))
|
||||||
|
o.datatype = "list(neg,portrange)"
|
||||||
|
o.placeholder = translate("any")
|
||||||
|
|
||||||
|
|
||||||
|
o = s:option(ListValue, "target", translate("Action"))
|
||||||
|
o.default = "ACCEPT"
|
||||||
|
o:value("DROP", translate("drop"))
|
||||||
|
o:value("ACCEPT", translate("accept"))
|
||||||
|
o:value("REJECT", translate("reject"))
|
||||||
|
o:value("NOTRACK", translate("don't track"))
|
||||||
|
end
|
||||||
|
|
||||||
|
return m
|
300
applications/luci-firewall/luasrc/model/cbi/firewall/rules.lua
Normal file
300
applications/luci-firewall/luasrc/model/cbi/firewall/rules.lua
Normal file
|
@ -0,0 +1,300 @@
|
||||||
|
--[[
|
||||||
|
LuCI - Lua Configuration Interface
|
||||||
|
|
||||||
|
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local ds = require "luci.dispatcher"
|
||||||
|
local ft = require "luci.tools.firewall"
|
||||||
|
|
||||||
|
m = Map("firewall",
|
||||||
|
translate("Firewall - Traffic Rules"),
|
||||||
|
translate("Traffic rules define policies for packets traveling between \
|
||||||
|
different zones, for example to reject traffic between certain hosts \
|
||||||
|
or to open WAN ports on the router."))
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Rules
|
||||||
|
--
|
||||||
|
|
||||||
|
s = m:section(TypedSection, "rule", translate("Traffic Rules"))
|
||||||
|
s.addremove = true
|
||||||
|
s.anonymous = true
|
||||||
|
s.sortable = true
|
||||||
|
s.template = "cbi/tblsection"
|
||||||
|
s.extedit = ds.build_url("admin/network/firewall/rules/%s")
|
||||||
|
s.defaults.target = "ACCEPT"
|
||||||
|
s.template_addremove = "firewall/cbi_addrule"
|
||||||
|
|
||||||
|
|
||||||
|
function s.create(self, section)
|
||||||
|
created = TypedSection.create(self, section)
|
||||||
|
end
|
||||||
|
|
||||||
|
function s.parse(self, ...)
|
||||||
|
TypedSection.parse(self, ...)
|
||||||
|
|
||||||
|
local i_n = m:formvalue("_newopen.name")
|
||||||
|
local i_p = m:formvalue("_newopen.proto")
|
||||||
|
local i_e = m:formvalue("_newopen.extport")
|
||||||
|
local i_x = m:formvalue("_newopen.submit")
|
||||||
|
|
||||||
|
local f_n = m:formvalue("_newfwd.name")
|
||||||
|
local f_s = m:formvalue("_newfwd.src")
|
||||||
|
local f_d = m:formvalue("_newfwd.dest")
|
||||||
|
local f_x = m:formvalue("_newfwd.submit")
|
||||||
|
|
||||||
|
if i_x then
|
||||||
|
created = TypedSection.create(self, section)
|
||||||
|
|
||||||
|
self.map:set(created, "target", "ACCEPT")
|
||||||
|
self.map:set(created, "src", "wan")
|
||||||
|
self.map:set(created, "proto", (i_p ~= "other") and i_p or "all")
|
||||||
|
self.map:set(created, "dest_port", i_e)
|
||||||
|
self.map:set(created, "_name", i_n)
|
||||||
|
|
||||||
|
if i_p ~= "other" and i_e and #i_e > 0 then
|
||||||
|
created = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif f_x then
|
||||||
|
created = TypedSection.create(self, section)
|
||||||
|
|
||||||
|
self.map:set(created, "target", "ACCEPT")
|
||||||
|
self.map:set(created, "src", f_s)
|
||||||
|
self.map:set(created, "dest", f_d)
|
||||||
|
self.map:set(created, "_name", f_n)
|
||||||
|
end
|
||||||
|
|
||||||
|
if created then
|
||||||
|
m.uci:save("firewall")
|
||||||
|
luci.http.redirect(ds.build_url(
|
||||||
|
"admin", "network", "firewall", "rules", created
|
||||||
|
))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
name = s:option(DummyValue, "_name", translate("Name"))
|
||||||
|
function name.cfgvalue(self, s)
|
||||||
|
return self.map:get(s, "_name") or "-"
|
||||||
|
end
|
||||||
|
|
||||||
|
family = s:option(DummyValue, "family", translate("Family"))
|
||||||
|
function family.cfgvalue(self, s)
|
||||||
|
local f = self.map:get(s, "family")
|
||||||
|
if f and f:match("4") then
|
||||||
|
return translate("IPv4")
|
||||||
|
elseif f and f:match("6") then
|
||||||
|
return translate("IPv6")
|
||||||
|
else
|
||||||
|
return translate("Any")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
proto = s:option(DummyValue, "proto", translate("Protocol"))
|
||||||
|
proto.rawhtml = true
|
||||||
|
proto.width = "20%"
|
||||||
|
function proto.cfgvalue(self, s)
|
||||||
|
return ft.fmt_proto(self.map:get(s, "proto"), self.map:get(s, "icmp_type"))
|
||||||
|
or "TCP+UDP"
|
||||||
|
end
|
||||||
|
|
||||||
|
src = s:option(DummyValue, "src", translate("Source"))
|
||||||
|
src.rawhtml = true
|
||||||
|
src.width = "20%"
|
||||||
|
function src.cfgvalue(self, s)
|
||||||
|
local z = ft.fmt_zone(self.map:get(s, "src"))
|
||||||
|
local a = ft.fmt_ip(self.map:get(s, "src_ip"))
|
||||||
|
local p = ft.fmt_port(self.map:get(s, "src_port"))
|
||||||
|
local m = ft.fmt_mac(self.map:get(s, "src_mac"))
|
||||||
|
|
||||||
|
local s = "From %s in %s " %{
|
||||||
|
(a or "<var>any host</var>"),
|
||||||
|
(z or "<var>any zone</var>")
|
||||||
|
}
|
||||||
|
|
||||||
|
if p and m then
|
||||||
|
s = s .. "with source %s and %s" %{ p, m }
|
||||||
|
elseif p or m then
|
||||||
|
s = s .. "with source %s" %( p or m )
|
||||||
|
end
|
||||||
|
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
dest = s:option(DummyValue, "dest", translate("Destination"))
|
||||||
|
dest.rawhtml = true
|
||||||
|
dest.width = "20%"
|
||||||
|
function dest.cfgvalue(self, s)
|
||||||
|
local z = ft.fmt_zone(self.map:get(s, "dest"))
|
||||||
|
local a = ft.fmt_ip(self.map:get(s, "dest_ip"))
|
||||||
|
local p = ft.fmt_port(self.map:get(s, "dest_port"))
|
||||||
|
|
||||||
|
-- Forward
|
||||||
|
if z then
|
||||||
|
return "To %s%s in %s" %{
|
||||||
|
(a or "<var>any host</var>"),
|
||||||
|
(p and ", %s" % p or ""),
|
||||||
|
z
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Input
|
||||||
|
else
|
||||||
|
return "To %s%s on <var>this device</var>" %{
|
||||||
|
(a or "<var>any router IP</var>"),
|
||||||
|
(p and " at %s" % p or "")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
target = s:option(DummyValue, "target", translate("Action"))
|
||||||
|
target.rawhtml = true
|
||||||
|
target.width = "20%"
|
||||||
|
function target.cfgvalue(self, s)
|
||||||
|
local z = ft.fmt_zone(self.map:get(s, "dest"))
|
||||||
|
local l = ft.fmt_limit(self.map:get(s, "limit"), self.map:get(s, "limit_burst"))
|
||||||
|
local t = ft.fmt_target(self.map:get(s, "target"))
|
||||||
|
|
||||||
|
return "<var>%s</var> %s%s" %{
|
||||||
|
t,
|
||||||
|
(z and "forward" or "input"),
|
||||||
|
(l and " and limit to %s" % l or "")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- SNAT
|
||||||
|
--
|
||||||
|
|
||||||
|
s = m:section(TypedSection, "redirect",
|
||||||
|
translate("Source NAT"),
|
||||||
|
translate("Source NAT is a specific form of masquerading which allows \
|
||||||
|
fine grained control over the source IP used for outgoing traffic, \
|
||||||
|
for example to map multiple WAN addresses to internal subnets."))
|
||||||
|
s.template = "cbi/tblsection"
|
||||||
|
s.addremove = true
|
||||||
|
s.anonymous = true
|
||||||
|
s.sortable = true
|
||||||
|
s.extedit = ds.build_url("admin/network/firewall/rules/%s")
|
||||||
|
s.template_addremove = "firewall/cbi_addsnat"
|
||||||
|
|
||||||
|
function s.create(self, section)
|
||||||
|
created = TypedSection.create(self, section)
|
||||||
|
end
|
||||||
|
|
||||||
|
function s.parse(self, ...)
|
||||||
|
TypedSection.parse(self, ...)
|
||||||
|
|
||||||
|
local n = m:formvalue("_newsnat.name")
|
||||||
|
local s = m:formvalue("_newsnat.src")
|
||||||
|
local d = m:formvalue("_newsnat.dest")
|
||||||
|
local a = m:formvalue("_newsnat.dip")
|
||||||
|
local p = m:formvalue("_newsnat.dport")
|
||||||
|
local x = m:formvalue("_newsnat.submit")
|
||||||
|
|
||||||
|
if x and a and #a > 0 then
|
||||||
|
created = TypedSection.create(self, section)
|
||||||
|
|
||||||
|
self.map:set(created, "target", "SNAT")
|
||||||
|
self.map:set(created, "src", s)
|
||||||
|
self.map:set(created, "dest", d)
|
||||||
|
self.map:set(created, "proto", "all")
|
||||||
|
self.map:set(created, "src_dip", a)
|
||||||
|
self.map:set(created, "src_dport", p)
|
||||||
|
self.map:set(created, "_name", n)
|
||||||
|
end
|
||||||
|
|
||||||
|
if created then
|
||||||
|
m.uci:save("firewall")
|
||||||
|
luci.http.redirect(ds.build_url(
|
||||||
|
"admin/network/firewall/rules", created
|
||||||
|
))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function s.filter(self, sid)
|
||||||
|
return (self.map:get(sid, "target") == "SNAT")
|
||||||
|
end
|
||||||
|
|
||||||
|
name = s:option(DummyValue, "_name", translate("Name"))
|
||||||
|
function name.cfgvalue(self, s)
|
||||||
|
return self.map:get(s, "_name") or "-"
|
||||||
|
end
|
||||||
|
|
||||||
|
proto = s:option(DummyValue, "proto", translate("Protocol"))
|
||||||
|
proto.rawhtml = true
|
||||||
|
function proto.cfgvalue(self, s)
|
||||||
|
return ft.fmt_proto(self.map:get(s, "proto")) or "TCP+UDP"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
src = s:option(DummyValue, "src", translate("Source"))
|
||||||
|
src.rawhtml = true
|
||||||
|
src.width = "20%"
|
||||||
|
function src.cfgvalue(self, s)
|
||||||
|
local z = ft.fmt_zone(self.map:get(s, "src"))
|
||||||
|
local a = ft.fmt_ip(self.map:get(s, "src_ip"))
|
||||||
|
local p = ft.fmt_port(self.map:get(s, "src_port"))
|
||||||
|
local m = ft.fmt_mac(self.map:get(s, "src_mac"))
|
||||||
|
|
||||||
|
local s = "From %s in %s " %{
|
||||||
|
(a or "<var>any host</var>"),
|
||||||
|
(z or "<var>any zone</var>")
|
||||||
|
}
|
||||||
|
|
||||||
|
if p and m then
|
||||||
|
s = s .. "with source %s and %s" %{ p, m }
|
||||||
|
elseif p or m then
|
||||||
|
s = s .. "with source %s" %( p or m )
|
||||||
|
end
|
||||||
|
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
dest = s:option(DummyValue, "dest", translate("Destination"))
|
||||||
|
dest.rawhtml = true
|
||||||
|
dest.width = "30%"
|
||||||
|
function dest.cfgvalue(self, s)
|
||||||
|
local z = ft.fmt_zone(self.map:get(s, "dest"))
|
||||||
|
local a = ft.fmt_ip(self.map:get(s, "dest_ip"))
|
||||||
|
local p = ft.fmt_port(self.map:get(s, "dest_port")) or
|
||||||
|
ft.fmt_port(self.map:get(s, "src_dport"))
|
||||||
|
|
||||||
|
return "To %s%s in %s " %{
|
||||||
|
(a or "<var>any host</var>"),
|
||||||
|
(p and ", %s" % p or ""),
|
||||||
|
(z or "<var>any zone</var>")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
snat = s:option(DummyValue, "via", translate("SNAT"))
|
||||||
|
snat.rawhtml = true
|
||||||
|
snat.width = "20%"
|
||||||
|
function snat.cfgvalue(self, s)
|
||||||
|
local a = ft.fmt_ip(self.map:get(s, "src_dip"))
|
||||||
|
local p = ft.fmt_port(self.map:get(s, "src_dport"))
|
||||||
|
|
||||||
|
--local z = self.map:get(s, "src")
|
||||||
|
--local s = "To %s " %(a or "<var>any %s IP</var>" %( z or "router" ))
|
||||||
|
|
||||||
|
if a and p then
|
||||||
|
return "Rewrite to source %s, %s" %{ a, p }
|
||||||
|
elseif a or p then
|
||||||
|
return "Rewrite to source %s" %( a or p )
|
||||||
|
else
|
||||||
|
return "Bug"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return m
|
|
@ -14,15 +14,16 @@ $Id$
|
||||||
|
|
||||||
local nw = require "luci.model.network"
|
local nw = require "luci.model.network"
|
||||||
local fw = require "luci.model.firewall"
|
local fw = require "luci.model.firewall"
|
||||||
local utl = require "luci.util"
|
local ds = require "luci.dispatcher"
|
||||||
local dsp = require "luci.dispatcher"
|
local ut = require "luci.util"
|
||||||
|
|
||||||
|
local m, p, i, v
|
||||||
|
local s, name, net, family, msrc, mdest, log, lim
|
||||||
|
local s2, out, inp
|
||||||
|
|
||||||
local has_v2 = nixio.fs.access("/lib/firewall/fw.sh")
|
|
||||||
local out, inp
|
|
||||||
|
|
||||||
require("luci.tools.webadmin")
|
|
||||||
m = Map("firewall", translate("Firewall - Zone Settings"))
|
m = Map("firewall", translate("Firewall - Zone Settings"))
|
||||||
m.redirect = luci.dispatcher.build_url("admin/network/firewall")
|
m.redirect = luci.dispatcher.build_url("admin/network/firewall/zones")
|
||||||
|
|
||||||
fw.init(m.uci)
|
fw.init(m.uci)
|
||||||
nw.init(m.uci)
|
nw.init(m.uci)
|
||||||
|
@ -30,20 +31,25 @@ nw.init(m.uci)
|
||||||
|
|
||||||
local zone = fw:get_zone(arg[1])
|
local zone = fw:get_zone(arg[1])
|
||||||
if not zone then
|
if not zone then
|
||||||
luci.http.redirect(dsp.build_url("admin", "network", "firewall"))
|
luci.http.redirect(dsp.build_url("admin/network/firewall/zones"))
|
||||||
return
|
return
|
||||||
|
else
|
||||||
|
m.title = "%s - %s" %{
|
||||||
|
translate("Firewall - Zone Settings"),
|
||||||
|
translatef("Zone %q", zone:name() or "?")
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
s = m:section(NamedSection, zone.sid, "zone",
|
s = m:section(NamedSection, zone.sid, "zone",
|
||||||
translatef("Zone %q", zone:name()),
|
translatef("Zone %q", zone:name()),
|
||||||
translatef("This section defines common properties of %q. " ..
|
translatef("This section defines common properties of %q. \
|
||||||
"The <em>input</em> and <em>output</em> options set the default "..
|
The <em>input</em> and <em>output</em> options set the default \
|
||||||
"policies for traffic entering and leaving this zone while the " ..
|
policies for traffic entering and leaving this zone while the \
|
||||||
"<em>forward</em> option describes the policy for forwarded traffic " ..
|
<em>forward</em> option describes the policy for forwarded traffic \
|
||||||
"between different networks within the zone. " ..
|
between different networks within the zone. \
|
||||||
"<em>Covered networks</em> specifies which available networks are " ..
|
<em>Covered networks</em> specifies which available networks are \
|
||||||
"member of this zone.", zone:name()))
|
member of this zone.", zone:name()))
|
||||||
|
|
||||||
s.anonymous = true
|
s.anonymous = true
|
||||||
s.addremove = false
|
s.addremove = false
|
||||||
|
@ -73,15 +79,18 @@ function name.write(self, section, value)
|
||||||
inp.exclude = value
|
inp.exclude = value
|
||||||
end
|
end
|
||||||
|
|
||||||
m.redirect = luci.dispatcher.build_url(
|
m.redirect = ds.build_url("admin/network/firewall/zones", value)
|
||||||
"admin", "network", "firewall", "zones", value
|
m.title = "%s - %s" %{
|
||||||
)
|
translate("Firewall - Zone Settings"),
|
||||||
|
translatef("Zone %q", value or "?")
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
p = {}
|
p = {
|
||||||
p[1] = s:taboption("general", ListValue, "input", translate("Input"))
|
s:taboption("general", ListValue, "input", translate("Input")),
|
||||||
p[2] = s:taboption("general", ListValue, "output", translate("Output"))
|
s:taboption("general", ListValue, "output", translate("Output")),
|
||||||
p[3] = s:taboption("general", ListValue, "forward", translate("Forward"))
|
s:taboption("general", ListValue, "forward", translate("Forward"))
|
||||||
|
}
|
||||||
|
|
||||||
for i, v in ipairs(p) do
|
for i, v in ipairs(p) do
|
||||||
v:value("REJECT", translate("reject"))
|
v:value("REJECT", translate("reject"))
|
||||||
|
@ -109,13 +118,12 @@ function net.write(self, section, value)
|
||||||
zone:clear_networks()
|
zone:clear_networks()
|
||||||
|
|
||||||
local n
|
local n
|
||||||
for n in utl.imatch(value) do
|
for n in ut.imatch(value) do
|
||||||
zone:add_network(n)
|
zone:add_network(n)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
if has_v2 then
|
|
||||||
family = s:taboption("advanced", ListValue, "family",
|
family = s:taboption("advanced", ListValue, "family",
|
||||||
translate("Restrict to address family"))
|
translate("Restrict to address family"))
|
||||||
|
|
||||||
|
@ -123,13 +131,12 @@ if has_v2 then
|
||||||
family:value("", translate("IPv4 and IPv6"))
|
family:value("", translate("IPv4 and IPv6"))
|
||||||
family:value("ipv4", translate("IPv4 only"))
|
family:value("ipv4", translate("IPv4 only"))
|
||||||
family:value("ipv6", translate("IPv6 only"))
|
family:value("ipv6", translate("IPv6 only"))
|
||||||
end
|
|
||||||
|
|
||||||
msrc = s:taboption("advanced", DynamicList, "masq_src",
|
msrc = s:taboption("advanced", DynamicList, "masq_src",
|
||||||
translate("Restrict Masquerading to given source subnets"))
|
translate("Restrict Masquerading to given source subnets"))
|
||||||
|
|
||||||
msrc.optional = true
|
msrc.optional = true
|
||||||
msrc.datatype = "neg(network)"
|
msrc.datatype = "neg_network_ip4addr"
|
||||||
msrc.placeholder = "0.0.0.0/0"
|
msrc.placeholder = "0.0.0.0/0"
|
||||||
msrc:depends("family", "")
|
msrc:depends("family", "")
|
||||||
msrc:depends("family", "ipv4")
|
msrc:depends("family", "ipv4")
|
||||||
|
@ -138,7 +145,7 @@ mdest = s:taboption("advanced", DynamicList, "masq_dest",
|
||||||
translate("Restrict Masquerading to given destination subnets"))
|
translate("Restrict Masquerading to given destination subnets"))
|
||||||
|
|
||||||
mdest.optional = true
|
mdest.optional = true
|
||||||
mdest.datatype = "neg(network)"
|
mdest.datatype = "neg_network_ip4addr"
|
||||||
mdest.placeholder = "0.0.0.0/0"
|
mdest.placeholder = "0.0.0.0/0"
|
||||||
mdest:depends("family", "")
|
mdest:depends("family", "")
|
||||||
mdest:depends("family", "ipv4")
|
mdest:depends("family", "ipv4")
|
||||||
|
@ -146,7 +153,6 @@ mdest:depends("family", "ipv4")
|
||||||
s:taboption("advanced", Flag, "conntrack",
|
s:taboption("advanced", Flag, "conntrack",
|
||||||
translate("Force connection tracking"))
|
translate("Force connection tracking"))
|
||||||
|
|
||||||
if has_v2 then
|
|
||||||
log = s:taboption("advanced", Flag, "log",
|
log = s:taboption("advanced", Flag, "log",
|
||||||
translate("Enable logging on this zone"))
|
translate("Enable logging on this zone"))
|
||||||
|
|
||||||
|
@ -158,18 +164,17 @@ if has_v2 then
|
||||||
|
|
||||||
lim.placeholder = "10/minute"
|
lim.placeholder = "10/minute"
|
||||||
lim:depends("log", "1")
|
lim:depends("log", "1")
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
s2 = m:section(NamedSection, zone.sid, "fwd_out",
|
s2 = m:section(NamedSection, zone.sid, "fwd_out",
|
||||||
translate("Inter-Zone Forwarding"),
|
translate("Inter-Zone Forwarding"),
|
||||||
translatef("The options below control the forwarding policies between " ..
|
translatef("The options below control the forwarding policies between \
|
||||||
"this zone (%s) and other zones. <em>Destination zones</em> cover " ..
|
this zone (%s) and other zones. <em>Destination zones</em> cover \
|
||||||
"forwarded traffic <strong>originating from %q</strong>. " ..
|
forwarded traffic <strong>originating from %q</strong>. \
|
||||||
"<em>Source zones</em> match forwarded traffic from other zones " ..
|
<em>Source zones</em> match forwarded traffic from other zones \
|
||||||
"<strong>targeted at %q</strong>. The forwarding rule is " ..
|
<strong>targeted at %q</strong>. The forwarding rule is \
|
||||||
"<em>unidirectional</em>, e.g. a forward from lan to wan does " ..
|
<em>unidirectional</em>, e.g. a forward from lan to wan does \
|
||||||
"<em>not</em> imply a permission to forward from wan to lan as well.",
|
<em>not</em> imply a permission to forward from wan to lan as well.",
|
||||||
zone:name(), zone:name(), zone:name()
|
zone:name(), zone:name(), zone:name()
|
||||||
|
|
||||||
))
|
))
|
||||||
|
@ -220,7 +225,7 @@ function out.write(self, section, value)
|
||||||
zone:del_forwardings_by("src")
|
zone:del_forwardings_by("src")
|
||||||
|
|
||||||
local f
|
local f
|
||||||
for f in utl.imatch(value) do
|
for f in ut.imatch(value) do
|
||||||
zone:add_forwarding_to(f)
|
zone:add_forwarding_to(f)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -229,7 +234,7 @@ function inp.write(self, section, value)
|
||||||
zone:del_forwardings_by("dest")
|
zone:del_forwardings_by("dest")
|
||||||
|
|
||||||
local f
|
local f
|
||||||
for f in utl.imatch(value) do
|
for f in ut.imatch(value) do
|
||||||
zone:add_forwarding_from(f)
|
zone:add_forwarding_from(f)
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -0,0 +1,88 @@
|
||||||
|
--[[
|
||||||
|
LuCI - Lua Configuration Interface
|
||||||
|
|
||||||
|
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local ds = require "luci.dispatcher"
|
||||||
|
local fw = require "luci.model.firewall"
|
||||||
|
|
||||||
|
local m, s, o, p, i, v
|
||||||
|
|
||||||
|
m = Map("firewall",
|
||||||
|
translate("Firewall - Zone Settings"),
|
||||||
|
translate("The firewall creates zones over your network interfaces to control network traffic flow."))
|
||||||
|
|
||||||
|
fw.init(m.uci)
|
||||||
|
|
||||||
|
s = m:section(TypedSection, "defaults", translate("General Settings"))
|
||||||
|
s.anonymous = true
|
||||||
|
s.addremove = false
|
||||||
|
|
||||||
|
s:option(Flag, "syn_flood", translate("Enable SYN-flood protection"))
|
||||||
|
|
||||||
|
o = s:option(Flag, "drop_invalid", translate("Drop invalid packets"))
|
||||||
|
o.default = o.disabled
|
||||||
|
|
||||||
|
p = {
|
||||||
|
s:option(ListValue, "input", translate("Input")),
|
||||||
|
s:option(ListValue, "output", translate("Output")),
|
||||||
|
s:option(ListValue, "forward", translate("Forward"))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, v in ipairs(p) do
|
||||||
|
v:value("REJECT", translate("reject"))
|
||||||
|
v:value("DROP", translate("drop"))
|
||||||
|
v:value("ACCEPT", translate("accept"))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
s = m:section(TypedSection, "zone", translate("Zones"))
|
||||||
|
s.template = "cbi/tblsection"
|
||||||
|
s.anonymous = true
|
||||||
|
s.addremove = true
|
||||||
|
s.extedit = ds.build_url("admin", "network", "firewall", "zones", "%s")
|
||||||
|
|
||||||
|
function s.create(self)
|
||||||
|
local z = fw:new_zone()
|
||||||
|
if z then
|
||||||
|
luci.http.redirect(
|
||||||
|
ds.build_url("admin", "network", "firewall", "zones", z.sid)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function s.remove(self, section)
|
||||||
|
return fw:del_zone(section)
|
||||||
|
end
|
||||||
|
|
||||||
|
o = s:option(DummyValue, "_info", translate("Zone ⇒ Forwardings"))
|
||||||
|
o.template = "cbi/firewall_zoneforwards"
|
||||||
|
o.cfgvalue = function(self, section)
|
||||||
|
return self.map:get(section, "name")
|
||||||
|
end
|
||||||
|
|
||||||
|
p = {
|
||||||
|
s:option(ListValue, "input", translate("Input")),
|
||||||
|
s:option(ListValue, "output", translate("Output")),
|
||||||
|
s:option(ListValue, "forward", translate("Forward"))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, v in ipairs(p) do
|
||||||
|
v:value("REJECT", translate("reject"))
|
||||||
|
v:value("DROP", translate("drop"))
|
||||||
|
v:value("ACCEPT", translate("accept"))
|
||||||
|
end
|
||||||
|
|
||||||
|
s:option(Flag, "masq", translate("Masquerading"))
|
||||||
|
s:option(Flag, "mtu_fix", translate("MSS clamping"))
|
||||||
|
|
||||||
|
return m
|
|
@ -1,48 +0,0 @@
|
||||||
--[[
|
|
||||||
LuCI - Lua Configuration Interface
|
|
||||||
|
|
||||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
$Id$
|
|
||||||
]]--
|
|
||||||
require("luci.sys")
|
|
||||||
m = Map("firewall", translate("Port forwarding"),
|
|
||||||
translate("Port forwarding allows to provide network services in " ..
|
|
||||||
"the internal network to an external network."))
|
|
||||||
|
|
||||||
|
|
||||||
s = m:section(TypedSection, "redirect", "")
|
|
||||||
s:depends("src", "wan")
|
|
||||||
s.defaults.src = "wan"
|
|
||||||
|
|
||||||
s.template = "cbi/tblsection"
|
|
||||||
s.addremove = true
|
|
||||||
s.anonymous = true
|
|
||||||
|
|
||||||
name = s:option(Value, "_name", translate("Name"), translate("(optional)"))
|
|
||||||
name.size = 10
|
|
||||||
|
|
||||||
proto = s:option(ListValue, "proto", translate("Protocol"))
|
|
||||||
proto:value("tcp", "TCP")
|
|
||||||
proto:value("udp", "UDP")
|
|
||||||
proto:value("tcpudp", "TCP+UDP")
|
|
||||||
|
|
||||||
dport = s:option(Value, "src_dport", translate("External port"))
|
|
||||||
dport.size = 5
|
|
||||||
|
|
||||||
to = s:option(Value, "dest_ip", translate("Internal IP address"))
|
|
||||||
for i, dataset in ipairs(luci.sys.net.arptable()) do
|
|
||||||
to:value(dataset["IP address"])
|
|
||||||
end
|
|
||||||
|
|
||||||
toport = s:option(Value, "dest_port", translate("Internal port"),
|
|
||||||
translate("(optional)"))
|
|
||||||
toport.size = 5
|
|
||||||
|
|
||||||
return m
|
|
|
@ -1,155 +0,0 @@
|
||||||
--[[
|
|
||||||
LuCI - Lua Configuration Interface
|
|
||||||
|
|
||||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
|
||||||
Copyright 2010 Jo-Philipp Wich <xm@subsignal.org>
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
$Id$
|
|
||||||
]]--
|
|
||||||
|
|
||||||
local has_v2 = nixio.fs.access("/lib/firewall/fw.sh")
|
|
||||||
local dsp = require "luci.dispatcher"
|
|
||||||
|
|
||||||
arg[1] = arg[1] or ""
|
|
||||||
|
|
||||||
m = Map("firewall", translate("Advanced Rules"),
|
|
||||||
translate("Advanced rules let you customize the firewall to your " ..
|
|
||||||
"needs. Only new connections will be matched. Packets " ..
|
|
||||||
"belonging to already open connections are automatically " ..
|
|
||||||
"allowed to pass the firewall."))
|
|
||||||
|
|
||||||
m.redirect = dsp.build_url("admin", "network", "firewall")
|
|
||||||
|
|
||||||
if not m.uci:get(arg[1]) == "rule" then
|
|
||||||
luci.http.redirect(m.redirect)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
s = m:section(NamedSection, arg[1], "rule", "")
|
|
||||||
s.anonymous = true
|
|
||||||
s.addremove = false
|
|
||||||
|
|
||||||
s:tab("general", translate("General Settings"))
|
|
||||||
s:tab("advanced", translate("Advanced Options"))
|
|
||||||
|
|
||||||
back = s:option(DummyValue, "_overview", translate("Overview"))
|
|
||||||
back.value = ""
|
|
||||||
back.titleref = dsp.build_url("admin", "network", "firewall", "rule")
|
|
||||||
|
|
||||||
|
|
||||||
name = s:taboption("general", Value, "_name", translate("Name").." "..translate("(optional)"))
|
|
||||||
name.rmempty = true
|
|
||||||
|
|
||||||
src = s:taboption("general", Value, "src", translate("Source zone"))
|
|
||||||
src.nocreate = true
|
|
||||||
src.default = "wan"
|
|
||||||
src.template = "cbi/firewall_zonelist"
|
|
||||||
|
|
||||||
dest = s:taboption("advanced", Value, "dest", translate("Destination zone"))
|
|
||||||
dest.nocreate = true
|
|
||||||
dest.allowlocal = true
|
|
||||||
dest.template = "cbi/firewall_zonelist"
|
|
||||||
|
|
||||||
proto = s:taboption("general", Value, "proto", translate("Protocol"))
|
|
||||||
proto.optional = true
|
|
||||||
proto:value("all", translate("Any"))
|
|
||||||
proto:value("tcpudp", "TCP+UDP")
|
|
||||||
proto:value("tcp", "TCP")
|
|
||||||
proto:value("udp", "UDP")
|
|
||||||
proto:value("icmp", "ICMP")
|
|
||||||
|
|
||||||
icmpt = s:taboption("general", Value, "icmp_type", translate("Match ICMP type"))
|
|
||||||
icmpt:depends("proto", "icmp")
|
|
||||||
icmpt:value("", "any")
|
|
||||||
icmpt:value("echo-reply")
|
|
||||||
icmpt:value("destination-unreachable")
|
|
||||||
icmpt:value("network-unreachable")
|
|
||||||
icmpt:value("host-unreachable")
|
|
||||||
icmpt:value("protocol-unreachable")
|
|
||||||
icmpt:value("port-unreachable")
|
|
||||||
icmpt:value("fragmentation-needed")
|
|
||||||
icmpt:value("source-route-failed")
|
|
||||||
icmpt:value("network-unknown")
|
|
||||||
icmpt:value("host-unknown")
|
|
||||||
icmpt:value("network-prohibited")
|
|
||||||
icmpt:value("host-prohibited")
|
|
||||||
icmpt:value("TOS-network-unreachable")
|
|
||||||
icmpt:value("TOS-host-unreachable")
|
|
||||||
icmpt:value("communication-prohibited")
|
|
||||||
icmpt:value("host-precedence-violation")
|
|
||||||
icmpt:value("precedence-cutoff")
|
|
||||||
icmpt:value("source-quench")
|
|
||||||
icmpt:value("redirect")
|
|
||||||
icmpt:value("network-redirect")
|
|
||||||
icmpt:value("host-redirect")
|
|
||||||
icmpt:value("TOS-network-redirect")
|
|
||||||
icmpt:value("TOS-host-redirect")
|
|
||||||
icmpt:value("echo-request")
|
|
||||||
icmpt:value("router-advertisement")
|
|
||||||
icmpt:value("router-solicitation")
|
|
||||||
icmpt:value("time-exceeded")
|
|
||||||
icmpt:value("ttl-zero-during-transit")
|
|
||||||
icmpt:value("ttl-zero-during-reassembly")
|
|
||||||
icmpt:value("parameter-problem")
|
|
||||||
icmpt:value("ip-header-bad")
|
|
||||||
icmpt:value("required-option-missing")
|
|
||||||
icmpt:value("timestamp-request")
|
|
||||||
icmpt:value("timestamp-reply")
|
|
||||||
icmpt:value("address-mask-request")
|
|
||||||
icmpt:value("address-mask-reply")
|
|
||||||
|
|
||||||
src_ip = s:taboption("general", Value, "src_ip", translate("Source address"))
|
|
||||||
src_ip.optional = true
|
|
||||||
src_ip.datatype = has_v2 and "neg_ipaddr" or "neg_ip4addr"
|
|
||||||
src_ip.placeholder = translate("any")
|
|
||||||
|
|
||||||
sport = s:taboption("general", Value, "src_port", translate("Source port"))
|
|
||||||
sport.optional = true
|
|
||||||
sport.datatype = "portrange"
|
|
||||||
sport.placeholder = "0-65535"
|
|
||||||
sport:depends("proto", "tcp")
|
|
||||||
sport:depends("proto", "udp")
|
|
||||||
sport:depends("proto", "tcpudp")
|
|
||||||
|
|
||||||
dest_ip = s:taboption("general", Value, "dest_ip", translate("Destination address"))
|
|
||||||
dest_ip.optional = true
|
|
||||||
dest_ip.datatype = has_v2 and "neg_ipaddr" or "neg_ip4addr"
|
|
||||||
dest_ip.placeholder = translate("any")
|
|
||||||
|
|
||||||
dport = s:taboption("general", Value, "dest_port", translate("Destination port"))
|
|
||||||
dport.optional = true
|
|
||||||
dport.datatype = "portrange"
|
|
||||||
dport:depends("proto", "tcp")
|
|
||||||
dport:depends("proto", "udp")
|
|
||||||
dport:depends("proto", "tcpudp")
|
|
||||||
dport.placeholder = "0-65535"
|
|
||||||
|
|
||||||
jump = s:taboption("general", ListValue, "target", translate("Action"))
|
|
||||||
jump.rmempty = true
|
|
||||||
jump.default = "ACCEPT"
|
|
||||||
jump:value("DROP", translate("drop"))
|
|
||||||
jump:value("ACCEPT", translate("accept"))
|
|
||||||
jump:value("REJECT", translate("reject"))
|
|
||||||
jump:value("NOTRACK", translate("don't track"))
|
|
||||||
|
|
||||||
|
|
||||||
smac = s:taboption("advanced", Value, "src_mac", translate("Source MAC address"))
|
|
||||||
smac.optional = true
|
|
||||||
smac.datatype = "macaddr"
|
|
||||||
smac.placeholder = translate("any")
|
|
||||||
|
|
||||||
if has_v2 then
|
|
||||||
family = s:taboption("advanced", ListValue, "family", translate("Restrict to address family"))
|
|
||||||
family.rmempty = true
|
|
||||||
family:value("", translate("IPv4 and IPv6"))
|
|
||||||
family:value("ipv4", translate("IPv4 only"))
|
|
||||||
family:value("ipv6", translate("IPv6 only"))
|
|
||||||
end
|
|
||||||
|
|
||||||
return m
|
|
|
@ -1,273 +0,0 @@
|
||||||
--[[
|
|
||||||
LuCI - Lua Configuration Interface
|
|
||||||
|
|
||||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
$Id$
|
|
||||||
]]--
|
|
||||||
|
|
||||||
local nw = require "luci.model.network"
|
|
||||||
local fw = require "luci.model.firewall"
|
|
||||||
local ds = require "luci.dispatcher"
|
|
||||||
|
|
||||||
local has_v2 = nixio.fs.access("/lib/firewall/fw.sh")
|
|
||||||
|
|
||||||
require("luci.tools.webadmin")
|
|
||||||
m = Map("firewall", translate("Firewall"), translate("The firewall creates zones over your network interfaces to control network traffic flow."))
|
|
||||||
|
|
||||||
fw.init(m.uci)
|
|
||||||
nw.init(m.uci)
|
|
||||||
|
|
||||||
s = m:section(TypedSection, "defaults")
|
|
||||||
s.anonymous = true
|
|
||||||
s.addremove = false
|
|
||||||
|
|
||||||
s:tab("general", translate("General Settings"))
|
|
||||||
s:tab("custom", translate("Custom Rules"))
|
|
||||||
|
|
||||||
|
|
||||||
s:taboption("general", Flag, "syn_flood", translate("Enable SYN-flood protection"))
|
|
||||||
|
|
||||||
local di = s:taboption("general", Flag, "drop_invalid", translate("Drop invalid packets"))
|
|
||||||
di.rmempty = false
|
|
||||||
function di.cfgvalue(...)
|
|
||||||
return AbstractValue.cfgvalue(...) or "1"
|
|
||||||
end
|
|
||||||
|
|
||||||
p = {}
|
|
||||||
p[1] = s:taboption("general", ListValue, "input", translate("Input"))
|
|
||||||
p[2] = s:taboption("general", ListValue, "output", translate("Output"))
|
|
||||||
p[3] = s:taboption("general", ListValue, "forward", translate("Forward"))
|
|
||||||
|
|
||||||
for i, v in ipairs(p) do
|
|
||||||
v:value("REJECT", translate("reject"))
|
|
||||||
v:value("DROP", translate("drop"))
|
|
||||||
v:value("ACCEPT", translate("accept"))
|
|
||||||
end
|
|
||||||
|
|
||||||
custom = s:taboption("custom", Value, "_custom",
|
|
||||||
translate("Custom Rules (/etc/firewall.user)"))
|
|
||||||
|
|
||||||
custom.template = "cbi/tvalue"
|
|
||||||
custom.rows = 20
|
|
||||||
|
|
||||||
function custom.cfgvalue(self, section)
|
|
||||||
return nixio.fs.readfile("/etc/firewall.user")
|
|
||||||
end
|
|
||||||
|
|
||||||
function custom.write(self, section, value)
|
|
||||||
value = value:gsub("\r\n?", "\n")
|
|
||||||
nixio.fs.writefile("/etc/firewall.user", value)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
s = m:section(TypedSection, "zone", translate("Zones"))
|
|
||||||
s.template = "cbi/tblsection"
|
|
||||||
s.anonymous = true
|
|
||||||
s.addremove = true
|
|
||||||
s.extedit = ds.build_url("admin", "network", "firewall", "zones", "%s")
|
|
||||||
|
|
||||||
function s.create(self)
|
|
||||||
local z = fw:new_zone()
|
|
||||||
if z then
|
|
||||||
luci.http.redirect(
|
|
||||||
ds.build_url("admin", "network", "firewall", "zones", z.sid)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function s.remove(self, section)
|
|
||||||
return fw:del_zone(section)
|
|
||||||
end
|
|
||||||
|
|
||||||
info = s:option(DummyValue, "_info", translate("Zone ⇒ Forwardings"))
|
|
||||||
info.template = "cbi/firewall_zoneforwards"
|
|
||||||
function info.cfgvalue(self, section)
|
|
||||||
return self.map:get(section, "name")
|
|
||||||
end
|
|
||||||
|
|
||||||
p = {}
|
|
||||||
p[1] = s:option(ListValue, "input", translate("Input"))
|
|
||||||
p[2] = s:option(ListValue, "output", translate("Output"))
|
|
||||||
p[3] = s:option(ListValue, "forward", translate("Forward"))
|
|
||||||
|
|
||||||
for i, v in ipairs(p) do
|
|
||||||
v:value("REJECT", translate("reject"))
|
|
||||||
v:value("DROP", translate("drop"))
|
|
||||||
v:value("ACCEPT", translate("accept"))
|
|
||||||
end
|
|
||||||
|
|
||||||
s:option(Flag, "masq", translate("Masquerading"))
|
|
||||||
s:option(Flag, "mtu_fix", translate("MSS clamping"))
|
|
||||||
|
|
||||||
|
|
||||||
local created = nil
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Redirects
|
|
||||||
--
|
|
||||||
|
|
||||||
s = m:section(TypedSection, "redirect", translate("Redirections"))
|
|
||||||
s.template = "cbi/tblsection"
|
|
||||||
s.addremove = true
|
|
||||||
s.anonymous = true
|
|
||||||
s.sortable = true
|
|
||||||
s.extedit = ds.build_url("admin", "network", "firewall", "redirect", "%s")
|
|
||||||
|
|
||||||
function s.create(self, section)
|
|
||||||
created = TypedSection.create(self, section)
|
|
||||||
end
|
|
||||||
|
|
||||||
function s.parse(self, ...)
|
|
||||||
TypedSection.parse(self, ...)
|
|
||||||
if created then
|
|
||||||
m.uci:save("firewall")
|
|
||||||
luci.http.redirect(ds.build_url(
|
|
||||||
"admin", "network", "firewall", "redirect", created
|
|
||||||
))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
name = s:option(DummyValue, "_name", translate("Name"))
|
|
||||||
function name.cfgvalue(self, s)
|
|
||||||
return self.map:get(s, "_name") or "-"
|
|
||||||
end
|
|
||||||
|
|
||||||
proto = s:option(DummyValue, "proto", translate("Protocol"))
|
|
||||||
function proto.cfgvalue(self, s)
|
|
||||||
local p = self.map:get(s, "proto")
|
|
||||||
if not p or p == "tcpudp" then
|
|
||||||
return "TCP+UDP"
|
|
||||||
else
|
|
||||||
return p:upper()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
src = s:option(DummyValue, "src", translate("Source"))
|
|
||||||
function src.cfgvalue(self, s)
|
|
||||||
local rv = "%s:%s:%s" % {
|
|
||||||
self.map:get(s, "src") or "*",
|
|
||||||
self.map:get(s, "src_ip") or "0.0.0.0/0",
|
|
||||||
self.map:get(s, "src_port") or "*"
|
|
||||||
}
|
|
||||||
|
|
||||||
local mac = self.map:get(s, "src_mac")
|
|
||||||
if mac then
|
|
||||||
rv = rv .. ", MAC " .. mac
|
|
||||||
end
|
|
||||||
|
|
||||||
return rv
|
|
||||||
end
|
|
||||||
|
|
||||||
via = s:option(DummyValue, "via", translate("Via"))
|
|
||||||
function via.cfgvalue(self, s)
|
|
||||||
return "%s:%s:%s" % {
|
|
||||||
translate("Device"),
|
|
||||||
self.map:get(s, "src_dip") or "0.0.0.0/0",
|
|
||||||
self.map:get(s, "src_dport") or "*"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
dest = s:option(DummyValue, "dest", translate("Destination"))
|
|
||||||
function dest.cfgvalue(self, s)
|
|
||||||
return "%s:%s:%s" % {
|
|
||||||
self.map:get(s, "dest") or "*",
|
|
||||||
self.map:get(s, "dest_ip") or "0.0.0.0/0",
|
|
||||||
self.map:get(s, "dest_port") or "*"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
target = s:option(DummyValue, "target", translate("Action"))
|
|
||||||
function target.cfgvalue(self, s)
|
|
||||||
return self.map:get(s, "target") or "DNAT"
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Rules
|
|
||||||
--
|
|
||||||
|
|
||||||
s = m:section(TypedSection, "rule", translate("Rules"))
|
|
||||||
s.addremove = true
|
|
||||||
s.anonymous = true
|
|
||||||
s.sortable = true
|
|
||||||
s.template = "cbi/tblsection"
|
|
||||||
s.extedit = ds.build_url("admin", "network", "firewall", "rule", "%s")
|
|
||||||
s.defaults.target = "ACCEPT"
|
|
||||||
|
|
||||||
function s.create(self, section)
|
|
||||||
local created = TypedSection.create(self, section)
|
|
||||||
m.uci:save("firewall")
|
|
||||||
luci.http.redirect(ds.build_url(
|
|
||||||
"admin", "network", "firewall", "rule", created
|
|
||||||
))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
name = s:option(DummyValue, "_name", translate("Name"))
|
|
||||||
function name.cfgvalue(self, s)
|
|
||||||
return self.map:get(s, "_name") or "-"
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_v2 then
|
|
||||||
family = s:option(DummyValue, "family", translate("Family"))
|
|
||||||
function family.cfgvalue(self, s)
|
|
||||||
local f = self.map:get(s, "family")
|
|
||||||
if f and f:match("4") then
|
|
||||||
return translate("IPv4 only")
|
|
||||||
elseif f and f:match("6") then
|
|
||||||
return translate("IPv6 only")
|
|
||||||
else
|
|
||||||
return translate("IPv4 and IPv6")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
proto = s:option(DummyValue, "proto", translate("Protocol"))
|
|
||||||
function proto.cfgvalue(self, s)
|
|
||||||
local p = self.map:get(s, "proto")
|
|
||||||
local t = self.map:get(s, "icmp_type")
|
|
||||||
if p == "icmp" and t then
|
|
||||||
return "ICMP (%s)" % t
|
|
||||||
elseif p == "tcpudp" or not p then
|
|
||||||
return "TCP+UDP"
|
|
||||||
else
|
|
||||||
return p:upper()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
src = s:option(DummyValue, "src", translate("Source"))
|
|
||||||
function src.cfgvalue(self, s)
|
|
||||||
local rv = "%s:%s:%s" % {
|
|
||||||
self.map:get(s, "src") or "*",
|
|
||||||
self.map:get(s, "src_ip") or "0.0.0.0/0",
|
|
||||||
self.map:get(s, "src_port") or "*"
|
|
||||||
}
|
|
||||||
|
|
||||||
local mac = self.map:get(s, "src_mac")
|
|
||||||
if mac then
|
|
||||||
rv = rv .. ", MAC " .. mac
|
|
||||||
end
|
|
||||||
|
|
||||||
return rv
|
|
||||||
end
|
|
||||||
|
|
||||||
dest = s:option(DummyValue, "dest", translate("Destination"))
|
|
||||||
function dest.cfgvalue(self, s)
|
|
||||||
return "%s:%s:%s" % {
|
|
||||||
self.map:get(s, "dest") or translate("Device"),
|
|
||||||
self.map:get(s, "dest_ip") or "0.0.0.0/0",
|
|
||||||
self.map:get(s, "dest_port") or "*"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
s:option(DummyValue, "target", translate("Action"))
|
|
||||||
|
|
||||||
return m
|
|
213
applications/luci-firewall/luasrc/tools/firewall.lua
Normal file
213
applications/luci-firewall/luasrc/tools/firewall.lua
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
--[[
|
||||||
|
LuCI - Lua Configuration Interface
|
||||||
|
|
||||||
|
Copyright 2011 Jo-Philipp Wich <xm@subsignal.org>
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
]]--
|
||||||
|
|
||||||
|
module("luci.tools.firewall", package.seeall)
|
||||||
|
|
||||||
|
local ut = require "luci.util"
|
||||||
|
local ip = require "luci.ip"
|
||||||
|
local nx = require "nixio"
|
||||||
|
|
||||||
|
local tr, trf = luci.i18n.translate, luci.i18n.translatef
|
||||||
|
|
||||||
|
function fmt_neg(x)
|
||||||
|
if type(x) == "string" then
|
||||||
|
local v, neg = x:gsub("^ *! *", "")
|
||||||
|
if neg > 0 then
|
||||||
|
return v, "%s " % tr("not")
|
||||||
|
else
|
||||||
|
return x, ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return x, ""
|
||||||
|
end
|
||||||
|
|
||||||
|
function fmt_mac(x)
|
||||||
|
if x and #x > 0 then
|
||||||
|
local m, n
|
||||||
|
local l = { tr("MAC"), " " }
|
||||||
|
for m in ut.imatch(x) do
|
||||||
|
m, n = fmt_neg(m)
|
||||||
|
l[#l+1] = "<var>%s%s</var>" %{ n, m }
|
||||||
|
l[#l+1] = ", "
|
||||||
|
end
|
||||||
|
if #l > 1 then
|
||||||
|
l[#l] = nil
|
||||||
|
if #l > 3 then
|
||||||
|
l[1] = tr("MACs")
|
||||||
|
end
|
||||||
|
return table.concat(l, "")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function fmt_port(x)
|
||||||
|
if x and #x > 0 then
|
||||||
|
local p, n
|
||||||
|
local l = { tr("port"), " " }
|
||||||
|
for p in ut.imatch(x) do
|
||||||
|
p, n = fmt_neg(p)
|
||||||
|
local a, b = p:match("(%d+)%D+(%d+)")
|
||||||
|
if a and b then
|
||||||
|
l[1] = tr("ports")
|
||||||
|
l[#l+1] = "<var>%s%d-%d</var>" %{ n, a, b }
|
||||||
|
else
|
||||||
|
l[#l+1] = "<var>%s%d</var>" %{ n, p }
|
||||||
|
end
|
||||||
|
l[#l+1] = ", "
|
||||||
|
end
|
||||||
|
if #l > 1 then
|
||||||
|
l[#l] = nil
|
||||||
|
if #l > 3 then
|
||||||
|
l[1] = tr("ports")
|
||||||
|
end
|
||||||
|
return table.concat(l, "")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function fmt_ip(x)
|
||||||
|
if x and #x > 0 then
|
||||||
|
local l = { tr("IP"), " " }
|
||||||
|
local v, a, n
|
||||||
|
for v in ut.imatch(x) do
|
||||||
|
v, n = fmt_neg(v)
|
||||||
|
a, m = v:match("(%S+)/(%d+%.%S+)")
|
||||||
|
a = a or v
|
||||||
|
a = a:match(":") and ip.IPv6(a, m) or ip.IPv4(a, m)
|
||||||
|
if a and (a:is6() or a:prefix() < 32) then
|
||||||
|
l[1] = tr("IP range")
|
||||||
|
l[#l+1] = "<var title='%s - %s'>%s%s</var>" %{
|
||||||
|
a:minhost():string(),
|
||||||
|
a:maxhost():string(),
|
||||||
|
n, a:string()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
l[#l+1] = "<var>%s%s</var>" %{
|
||||||
|
n,
|
||||||
|
a and a:string() or v
|
||||||
|
}
|
||||||
|
end
|
||||||
|
l[#l+1] = ", "
|
||||||
|
end
|
||||||
|
if #l > 1 then
|
||||||
|
l[#l] = nil
|
||||||
|
if #l > 3 then
|
||||||
|
l[1] = tr("IPs")
|
||||||
|
end
|
||||||
|
return table.concat(l, "")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function fmt_zone(x)
|
||||||
|
if x == "*" then
|
||||||
|
return "<var>%s</var>" % tr("any zone")
|
||||||
|
elseif x and #x > 0 then
|
||||||
|
return "<var>%s</var>" % x
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function fmt_icmp_type(x)
|
||||||
|
if x and #x > 0 then
|
||||||
|
local t, v, n
|
||||||
|
local l = { tr("type"), " " }
|
||||||
|
for v in ut.imatch(x) do
|
||||||
|
v, n = fmt_neg(v)
|
||||||
|
l[#l+1] = "<var>%s%s</var>" %{ n, v }
|
||||||
|
l[#l+1] = ", "
|
||||||
|
end
|
||||||
|
if #l > 1 then
|
||||||
|
l[#l] = nil
|
||||||
|
if #l > 3 then
|
||||||
|
l[1] = tr("types")
|
||||||
|
end
|
||||||
|
return table.concat(l, "")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function fmt_proto(x, icmp_types)
|
||||||
|
if x and #x > 0 then
|
||||||
|
local v, n
|
||||||
|
local l = { }
|
||||||
|
local t = fmt_icmp_type(icmp_types)
|
||||||
|
for v in ut.imatch(x) do
|
||||||
|
v, n = fmt_neg(v)
|
||||||
|
if v == "tcpudp" then
|
||||||
|
l[#l+1] = "TCP"
|
||||||
|
l[#l+1] = "UDP"
|
||||||
|
l[#l+1] = ", "
|
||||||
|
elseif v ~= "all" then
|
||||||
|
local p = nx.getproto(v)
|
||||||
|
if p then
|
||||||
|
-- ICMP
|
||||||
|
if (p.proto == 1 or p.proto == 58) and t then
|
||||||
|
l[#l+1] = trf(
|
||||||
|
"%s%s with %s",
|
||||||
|
n, p.aliases[1] or p.name, t
|
||||||
|
)
|
||||||
|
else
|
||||||
|
l[#l+1] = "%s%s" %{
|
||||||
|
n,
|
||||||
|
p.aliases[1] or p.name
|
||||||
|
}
|
||||||
|
end
|
||||||
|
l[#l+1] = ", "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #l > 0 then
|
||||||
|
l[#l] = nil
|
||||||
|
return table.concat(l, "")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function fmt_limit(limit, burst)
|
||||||
|
burst = tonumber(burst)
|
||||||
|
if limit and #limit > 0 then
|
||||||
|
local l, u = limit:match("(%d+)/(%w+)")
|
||||||
|
l = tonumber(l or limit)
|
||||||
|
u = u or "second"
|
||||||
|
if l then
|
||||||
|
if u:match("^s") then
|
||||||
|
u = tr("second")
|
||||||
|
elseif u:match("^m") then
|
||||||
|
u = tr("minute")
|
||||||
|
elseif u:match("^h") then
|
||||||
|
u = tr("hour")
|
||||||
|
elseif u:match("^d") then
|
||||||
|
u = tr("day")
|
||||||
|
end
|
||||||
|
if burst and burst > 0 then
|
||||||
|
return trf("<var>%d</var> pkts. per <var>%s</var>, \
|
||||||
|
burst <var>%d</var> pkts.", l, u, burst)
|
||||||
|
else
|
||||||
|
return trf("<var>%d</var> pkts. per <var>%s</var>", l, u)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function fmt_target(x)
|
||||||
|
if x == "ACCEPT" then
|
||||||
|
return tr("Accept")
|
||||||
|
elseif x == "REJECT" then
|
||||||
|
return tr("Refuse")
|
||||||
|
elseif x == "NOTRACK" then
|
||||||
|
return tr("Do not track")
|
||||||
|
else --if x == "DROP" then
|
||||||
|
return tr("Discard")
|
||||||
|
end
|
||||||
|
end
|
90
applications/luci-firewall/luasrc/view/cbi_addforward.htm
Normal file
90
applications/luci-firewall/luasrc/view/cbi_addforward.htm
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
<div class="cbi-section-create cbi-tblsection-create">
|
||||||
|
<br />
|
||||||
|
<table class="cbi-section-table" style="width:700px; margin-left:5px">
|
||||||
|
<tr class="cbi-section-table-titles">
|
||||||
|
<th class="cbi-section-table-cell" colspan="6"><%:New port forward%>:</th>
|
||||||
|
</tr>
|
||||||
|
<tr class="cbi-section-table-descr">
|
||||||
|
<th class="cbi-section-table-cell"><%:Name%></th>
|
||||||
|
<th class="cbi-section-table-cell"><%:Protocol%></th>
|
||||||
|
<th class="cbi-section-table-cell"><%:External port%></th>
|
||||||
|
<th class="cbi-section-table-cell"><%:Internal IP address%></th>
|
||||||
|
<th class="cbi-section-table-cell"><%:Internal port%></th>
|
||||||
|
<th class="cbi-section-table-cell"></th>
|
||||||
|
</tr>
|
||||||
|
<tr class="cbi-section-table-row">
|
||||||
|
<td class="cbi-section-table-cell">
|
||||||
|
<input type="text" class="cbi-input-text" id="_newfwd.name" name="_newfwd.name" placeholder="<%:New port forward%>" />
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell" style="width:110px">
|
||||||
|
<select class="cbi-input-select" id="_newfwd.proto" name="_newfwd.proto">
|
||||||
|
<option value="tcp udp">TCP+UDP</option>
|
||||||
|
<option value="tcp">TCP</option>
|
||||||
|
<option value="udp">UDP</option>
|
||||||
|
<option value="other"><%:Other...%></option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell" style="width:110px">
|
||||||
|
<input type="text" class="cbi-input-text" id="_newfwd.extport" name="_newfwd.extport" />
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell" style="width:110px">
|
||||||
|
<input type="text" class="cbi-input-text" id="_newfwd.intaddr" name="_newfwd.intaddr" />
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell" style="width:110px">
|
||||||
|
<input type="text" class="cbi-input-text" id="_newfwd.intport" name="_newfwd.intport" />
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell">
|
||||||
|
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script type="text/javascript">//<![CDATA[
|
||||||
|
cbi_validate_field('_newfwd.extport', true, 'portrange');
|
||||||
|
cbi_validate_field('_newfwd.intaddr', true, 'host');
|
||||||
|
cbi_validate_field('_newfwd.intport', true, 'portrange');
|
||||||
|
|
||||||
|
cbi_combobox_init('_newfwd.intaddr', {
|
||||||
|
<% local i, e; for i, e in ipairs(luci.sys.net.arptable()) do -%>
|
||||||
|
<%- if i > 1 then %>,<% end -%>'<%=e["IP address"]%>': '<%=e["IP address"]%>'
|
||||||
|
<%- end %> }, '', '<%: -- custom -- %>');
|
||||||
|
|
||||||
|
cbi_bind(document.getElementById('_newfwd.extport'), 'blur',
|
||||||
|
function() {
|
||||||
|
var n = document.getElementById('_newfwd.name');
|
||||||
|
var p = document.getElementById('_newfwd.proto');
|
||||||
|
var i = document.getElementById('_newfwd.intport');
|
||||||
|
var hints = {
|
||||||
|
/* port name 0=both, 1=tcp, 2=udp, 3=other */
|
||||||
|
21: [ 'FTP', 1 ],
|
||||||
|
22: [ 'SSH', 1 ],
|
||||||
|
53: [ 'DNS', 0 ],
|
||||||
|
80: [ 'HTTP', 1 ],
|
||||||
|
443: [ 'HTTPS', 1 ],
|
||||||
|
3389: [ 'RDP', 1 ],
|
||||||
|
5900: [ 'VNC', 1 ],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!this.className.match(/invalid/))
|
||||||
|
{
|
||||||
|
if (!i.value) i.value = this.value;
|
||||||
|
|
||||||
|
var hint = hints[this.value || 0] || hints[i.value || 0];
|
||||||
|
if (hint)
|
||||||
|
{
|
||||||
|
p.selectedIndex = hint[1];
|
||||||
|
|
||||||
|
if (!n.value)
|
||||||
|
n.value = hint[0];
|
||||||
|
}
|
||||||
|
else if (!n.value)
|
||||||
|
{
|
||||||
|
n.value = 'Forward' + this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
cbi_validate_field('cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>', true, 'uciname');
|
||||||
|
//]]></script>
|
||||||
|
</div>
|
112
applications/luci-firewall/luasrc/view/cbi_addrule.htm
Normal file
112
applications/luci-firewall/luasrc/view/cbi_addrule.htm
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
<%
|
||||||
|
local fw = require "luci.model.firewall".init()
|
||||||
|
local wz = fw:get_zone("wan")
|
||||||
|
local lz = fw:get_zone("lan")
|
||||||
|
%>
|
||||||
|
|
||||||
|
<div class="cbi-section-create cbi-tblsection-create">
|
||||||
|
<% if wz and lz then %>
|
||||||
|
<br />
|
||||||
|
<table class="cbi-section-table" style="margin-left:5px">
|
||||||
|
<tr class="cbi-section-table-titles">
|
||||||
|
<th class="cbi-section-table-cell left" colspan="4"><%:Open ports on router%>:</th>
|
||||||
|
</tr>
|
||||||
|
<tr class="cbi-section-table-descr">
|
||||||
|
<th class="cbi-section-table-cell"><%:Name%></th>
|
||||||
|
<th class="cbi-section-table-cell"><%:Protocol%></th>
|
||||||
|
<th class="cbi-section-table-cell"><%:External port%></th>
|
||||||
|
<th class="cbi-section-table-cell"></th>
|
||||||
|
</tr>
|
||||||
|
<tr class="cbi-section-table-row">
|
||||||
|
<td class="cbi-section-table-cell" style="width:130px">
|
||||||
|
<input type="text" class="cbi-input-text" id="_newopen.name" name="_newopen.name" placeholder="<%:New input rule%>" />
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell" style="width:110px">
|
||||||
|
<select class="cbi-input-select" id="_newopen.proto" name="_newopen.proto">
|
||||||
|
<option value="tcp udp">TCP+UDP</option>
|
||||||
|
<option value="tcp">TCP</option>
|
||||||
|
<option value="udp">UDP</option>
|
||||||
|
<option value="other"><%:Other...%></option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell" style="width:110px">
|
||||||
|
<input type="text" class="cbi-input-text" id="_newopen.extport" name="_newopen.extport" />
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell left">
|
||||||
|
<input type="submit" class="cbi-button cbi-button-add" name="_newopen.submit" value="<%:Add%>" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table class="cbi-section-table" style="margin-left:5px">
|
||||||
|
<tr class="cbi-section-table-titles">
|
||||||
|
<th class="cbi-section-table-cell left" colspan="6"><br /><%:New forward rule%>:</th>
|
||||||
|
</tr>
|
||||||
|
<tr class="cbi-section-table-descr">
|
||||||
|
<th class="cbi-section-table-cell"><%:Name%></th>
|
||||||
|
<th class="cbi-section-table-cell"><%:Source zone%></th>
|
||||||
|
<th class="cbi-section-table-cell"><%:Destination zone%></th>
|
||||||
|
<th class="cbi-section-table-cell"></th>
|
||||||
|
</tr>
|
||||||
|
<tr class="cbi-section-table-row">
|
||||||
|
<td class="cbi-section-table-cell" style="width:130px">
|
||||||
|
<input type="text" class="cbi-input-text" id="_newfwd.name" name="_newfwd.name" placeholder="<%:New forward rule%>" />
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell" style="width:110px">
|
||||||
|
<select class="cbi-input-text" id="_newfwd.src" name="_newfwd.src">
|
||||||
|
<% local k, v; for k, v in ipairs(fw:get_zones()) do -%>
|
||||||
|
<option<%=ifattr(v:name() == "lan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option>
|
||||||
|
<%- end %>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell" style="width:110px">
|
||||||
|
<select class="cbi-input-text" id="_newfwd.dest" name="_newfwd.dest">
|
||||||
|
<% local k, v; for k, v in ipairs(fw:get_zones()) do -%>
|
||||||
|
<option<%=ifattr(v:name() == "wan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option>
|
||||||
|
<%- end %>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell left">
|
||||||
|
<input type="submit" class="cbi-button cbi-button-link" name="_newfwd.submit" value="<%:Add and edit...%>" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script type="text/javascript">//<![CDATA[
|
||||||
|
cbi_validate_field('_newopen.extport', true, 'list(portrange)');
|
||||||
|
cbi_bind(document.getElementById('_newopen.extport'), 'blur',
|
||||||
|
function() {
|
||||||
|
var n = document.getElementById('_newopen.name');
|
||||||
|
var p = document.getElementById('_newopen.proto');
|
||||||
|
var hints = {
|
||||||
|
/* port name 0=both, 1=tcp, 2=udp, 3=other */
|
||||||
|
22: [ 'SSH', 1 ],
|
||||||
|
53: [ 'DNS', 0 ],
|
||||||
|
80: [ 'HTTP', 1 ],
|
||||||
|
443: [ 'HTTPS', 1 ],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!this.className.match(/invalid/))
|
||||||
|
{
|
||||||
|
var hint = hints[this.value || 0];
|
||||||
|
if (hint)
|
||||||
|
{
|
||||||
|
p.selectedIndex = hint[1];
|
||||||
|
|
||||||
|
if (!n.value)
|
||||||
|
n.value = hint[0];
|
||||||
|
}
|
||||||
|
else if (!n.value && this.value)
|
||||||
|
{
|
||||||
|
n.value = 'Open' + this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
cbi_validate_field('cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>', true, 'uciname');
|
||||||
|
//]]></script>
|
||||||
|
<% else %>
|
||||||
|
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
|
||||||
|
<% end %>
|
||||||
|
</div>
|
65
applications/luci-firewall/luasrc/view/cbi_addsnat.htm
Normal file
65
applications/luci-firewall/luasrc/view/cbi_addsnat.htm
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
<%
|
||||||
|
local fw = require "luci.model.firewall".init()
|
||||||
|
local nw = require "luci.model.network".init()
|
||||||
|
local wz = fw:get_zone("wan")
|
||||||
|
local lz = fw:get_zone("lan")
|
||||||
|
%>
|
||||||
|
|
||||||
|
<div class="cbi-section-create cbi-tblsection-create">
|
||||||
|
<% if wz and lz then %>
|
||||||
|
<br />
|
||||||
|
<table class="cbi-section-table" style="width:700px; margin-left:5px">
|
||||||
|
<tr class="cbi-section-table-titles">
|
||||||
|
<th class="cbi-section-table-cell left" colspan="6"><%:New source NAT%>:</th>
|
||||||
|
</tr>
|
||||||
|
<tr class="cbi-section-table-descr">
|
||||||
|
<th class="cbi-section-table-cell"><%:Name%></th>
|
||||||
|
<th class="cbi-section-table-cell"><%:Source zone%></th>
|
||||||
|
<th class="cbi-section-table-cell"><%:Destination zone%></th>
|
||||||
|
<th class="cbi-section-table-cell"><%:To source IP%></th>
|
||||||
|
<th class="cbi-section-table-cell"><%:To source port%></th>
|
||||||
|
<th class="cbi-section-table-cell"></th>
|
||||||
|
</tr>
|
||||||
|
<tr class="cbi-section-table-row">
|
||||||
|
<td class="cbi-section-table-cell">
|
||||||
|
<input type="text" class="cbi-input-text" id="_newsnat.name" name="_newsnat.name" placeholder="<%:New SNAT rule%>" />
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell" style="width:110px">
|
||||||
|
<select class="cbi-input-text" id="_newsnat.src" name="_newsnat.src">
|
||||||
|
<% local k, v; for k, v in ipairs(fw:get_zones()) do -%>
|
||||||
|
<option<%=ifattr(v:name() == "lan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option>
|
||||||
|
<%- end %>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell" style="width:110px">
|
||||||
|
<select class="cbi-input-text" id="_newsnat.dest" name="_newsnat.dest">
|
||||||
|
<% local k, v; for k, v in ipairs(fw:get_zones()) do -%>
|
||||||
|
<option<%=ifattr(v:name() == "wan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option>
|
||||||
|
<%- end %>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell" style="width:110px">
|
||||||
|
<input type="text" class="cbi-input-text" id="_newsnat.dip" name="_newsnat.dip" />
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell" style="width:110px">
|
||||||
|
<input type="text" class="cbi-input-text" id="_newsnat.dport" name="_newsnat.dport" placeholder="<%:Do not rewrite%>" />
|
||||||
|
</td>
|
||||||
|
<td class="cbi-section-table-cell">
|
||||||
|
<input type="submit" class="cbi-button cbi-button-link" name="_newsnat.submit" value="<%:Add and edit...%>" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script type="text/javascript">//<![CDATA[
|
||||||
|
cbi_validate_field('_newsnat.dport', true, 'portrange');
|
||||||
|
cbi_combobox_init('_newsnat.dip', {
|
||||||
|
<% local c, k, v = 0; for k, v in ipairs(nw:get_interfaces()) do -%>
|
||||||
|
<%- local a; for k, a in ipairs(v:ipaddrs()) do c = c + 1 -%>
|
||||||
|
<% if c > 1 then %>,<% end %>'<%=a:host():string()%>': '<%=a:host():string()%> (<%=v:shortname()%>)',
|
||||||
|
<%- end %>
|
||||||
|
<%- end %> }, '<%: -- Please choose -- %>', '<%: -- custom -- %>');
|
||||||
|
//]]></script>
|
||||||
|
<% else %>
|
||||||
|
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
|
||||||
|
<% end %>
|
||||||
|
</div>
|
Loading…
Reference in a new issue