applications/luci-firewall: complete rework
This commit is contained in:
parent
26ba050939
commit
b04c13bdcc
6 changed files with 384 additions and 208 deletions
|
@ -5,9 +5,9 @@ function index()
|
||||||
local i18n = luci.i18n.translate
|
local i18n = luci.i18n.translate
|
||||||
|
|
||||||
entry({"admin", "network", "firewall"}, alias("admin", "network", "firewall", "zones"), i18n("Firewall"), 60).i18n = "luci-fw"
|
entry({"admin", "network", "firewall"}, alias("admin", "network", "firewall", "zones"), i18n("Firewall"), 60).i18n = "luci-fw"
|
||||||
entry({"admin", "network", "firewall", "zones"}, cbi("luci_fw/zones"), i18n("Zones"), 10)
|
entry({"admin", "network", "firewall", "zones"}, arcombine(cbi("luci_fw/zones"), cbi("luci_fw/zone")), nil, 10).leaf = true
|
||||||
entry({"admin", "network", "firewall", "redirect"}, arcombine(cbi("luci_fw/redirect"), cbi("luci_fw/rrule")), i18n("Traffic Redirection"), 30).leaf = true
|
entry({"admin", "network", "firewall", "rule"}, arcombine(cbi("luci_fw/zones"), cbi("luci_fw/trule")), nil, 20).leaf = true
|
||||||
entry({"admin", "network", "firewall", "rule"}, arcombine(cbi("luci_fw/traffic"), cbi("luci_fw/trule")), i18n("Traffic Control"), 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}), i18n("Port forwarding"), 70).i18n = "luci-fw"
|
entry({"mini", "network", "portfw"}, cbi("luci_fw/miniportfw", {autoapply=true}), i18n("Port forwarding"), 70).i18n = "luci-fw"
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,52 +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("Traffic Redirection"),
|
|
||||||
translate("Traffic redirection allows you to change the " ..
|
|
||||||
"destination address of forwarded packets."))
|
|
||||||
|
|
||||||
|
|
||||||
s = m:section(TypedSection, "redirect", "")
|
|
||||||
s.template = "cbi/tblsection"
|
|
||||||
s.addremove = true
|
|
||||||
s.anonymous = true
|
|
||||||
s.extedit = luci.dispatcher.build_url("admin", "network", "firewall", "redirect", "%s")
|
|
||||||
|
|
||||||
name = s:option(Value, "_name", translate("Name"), translate("(optional)"))
|
|
||||||
name.size = 10
|
|
||||||
|
|
||||||
iface = s:option(ListValue, "src", translate("Zone"))
|
|
||||||
iface.default = "wan"
|
|
||||||
luci.model.uci.cursor():foreach("firewall", "zone",
|
|
||||||
function (section)
|
|
||||||
iface:value(section.name)
|
|
||||||
end)
|
|
||||||
|
|
||||||
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("Source port"))
|
|
||||||
dport.size = 5
|
|
||||||
|
|
||||||
to = s:option(Value, "dest_ip", translate("Destination IP"))
|
|
||||||
for i, dataset in ipairs(luci.sys.net.arptable()) do
|
|
||||||
to:value(dataset["IP address"])
|
|
||||||
end
|
|
||||||
|
|
||||||
toport = s:option(Value, "dest_port", translate("Destination port"))
|
|
||||||
toport.size = 5
|
|
||||||
|
|
||||||
return m
|
|
|
@ -2,6 +2,7 @@
|
||||||
LuCI - Lua Configuration Interface
|
LuCI - Lua Configuration Interface
|
||||||
|
|
||||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
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");
|
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.
|
||||||
|
@ -11,70 +12,130 @@ You may obtain a copy of the License at
|
||||||
|
|
||||||
$Id$
|
$Id$
|
||||||
]]--
|
]]--
|
||||||
require("luci.sys")
|
|
||||||
|
local sys = require "luci.sys"
|
||||||
|
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"),
|
||||||
translate("Traffic redirection allows you to change the " ..
|
translate("Traffic redirection allows you to change the " ..
|
||||||
"destination address of forwarded packets."))
|
"destination address of forwarded packets."))
|
||||||
|
|
||||||
|
m.redirect = dsp.build_url("admin", "network", "firewall")
|
||||||
|
|
||||||
|
if not m.uci:get(arg[1]) == "redirect" then
|
||||||
|
luci.http.redirect(m.redirect)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local has_v2 = nixio.fs.access("/lib/firewall/fw.sh")
|
||||||
|
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 = m:section(NamedSection, arg[1], "redirect", "")
|
||||||
s.anonymous = true
|
s.anonymous = true
|
||||||
s.addremove = false
|
s.addremove = false
|
||||||
|
|
||||||
back = s:option(DummyValue, "_overview", translate("Overview"))
|
s:tab("general", translate("General Settings"))
|
||||||
|
s:tab("advanced", translate("Advanced Settings"))
|
||||||
|
|
||||||
|
back = s:taboption("general", DummyValue, "_overview", translate("Overview"))
|
||||||
back.value = ""
|
back.value = ""
|
||||||
back.titleref = luci.dispatcher.build_url("admin", "network", "firewall", "redirect")
|
back.titleref = luci.dispatcher.build_url("admin", "network", "firewall", "redirect")
|
||||||
|
|
||||||
name = s:option(Value, "_name", translate("Name"))
|
name = s:taboption("general", Value, "_name", translate("Name"))
|
||||||
name.rmempty = true
|
name.rmempty = true
|
||||||
name.size = 10
|
name.size = 10
|
||||||
|
|
||||||
iface = s:option(ListValue, "src", translate("Source zone"))
|
src = s:taboption("general", Value, "src", translate("Source zone"))
|
||||||
iface.default = "wan"
|
src.nocreate = true
|
||||||
luci.model.uci.cursor():foreach("firewall", "zone",
|
src.default = "wan"
|
||||||
function (section)
|
src.template = "cbi/firewall_zonelist"
|
||||||
iface:value(section.name)
|
|
||||||
end)
|
|
||||||
|
|
||||||
s:option(Value, "src_ip", translate("Source IP address")).optional = true
|
|
||||||
s:option(Value, "src_mac", translate("Source MAC-address")).optional = true
|
|
||||||
|
|
||||||
sport = s:option(Value, "src_port", translate("Source port"),
|
proto = s:taboption("general", ListValue, "proto", translate("Protocol"))
|
||||||
translate("Match incoming traffic originating from the given " ..
|
|
||||||
"source port or port range on the client host"))
|
|
||||||
sport.optional = true
|
|
||||||
sport:depends("proto", "tcp")
|
|
||||||
sport:depends("proto", "udp")
|
|
||||||
sport:depends("proto", "tcpudp")
|
|
||||||
|
|
||||||
proto = s:option(ListValue, "proto", translate("Protocol"))
|
|
||||||
proto.optional = true
|
proto.optional = true
|
||||||
proto:value("")
|
proto:value("tcpudp", "TCP+UDP")
|
||||||
proto:value("tcp", "TCP")
|
proto:value("tcp", "TCP")
|
||||||
proto:value("udp", "UDP")
|
proto:value("udp", "UDP")
|
||||||
proto:value("tcpudp", "TCP+UDP")
|
|
||||||
|
|
||||||
dport = s:option(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.size = 5
|
dport.datatype = "portrange"
|
||||||
dport:depends("proto", "tcp")
|
dport:depends("proto", "tcp")
|
||||||
dport:depends("proto", "udp")
|
dport:depends("proto", "udp")
|
||||||
dport:depends("proto", "tcpudp")
|
dport:depends("proto", "tcpudp")
|
||||||
|
|
||||||
to = s:option(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"
|
||||||
for i, dataset in ipairs(luci.sys.net.arptable()) do
|
for i, dataset in ipairs(luci.sys.net.arptable()) do
|
||||||
to:value(dataset["IP address"])
|
to:value(dataset["IP address"])
|
||||||
end
|
end
|
||||||
|
|
||||||
toport = s:option(Value, "dest_port", translate("Internal port (optional)"),
|
toport = s:taboption("general", Value, "dest_port", translate("Internal port (optional)"),
|
||||||
translate("Redirect matched incoming traffic to the given port on " ..
|
translate("Redirect matched incoming traffic to the given port on " ..
|
||||||
"the internal host"))
|
"the internal host"))
|
||||||
toport.optional = true
|
toport.optional = true
|
||||||
toport.size = 5
|
toport.size = 5
|
||||||
|
|
||||||
|
|
||||||
|
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.nocreate = true
|
||||||
|
dest.default = "lan"
|
||||||
|
dest.template = "cbi/firewall_zonelist"
|
||||||
|
|
||||||
|
src_dip = s:taboption("advanced", Value, "src_dip",
|
||||||
|
translate("Intended destination address"),
|
||||||
|
translate(
|
||||||
|
"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.datatype = "ip4addr"
|
||||||
|
|
||||||
|
src_mac = s:taboption("advanced", Value, "src_mac", translate("Source MAC address"))
|
||||||
|
src_mac.optional = true
|
||||||
|
src_mac.datatype = "macaddr"
|
||||||
|
|
||||||
|
src_ip = s:taboption("advanced", Value, "src_ip", translate("Source IP address"))
|
||||||
|
src_ip.optional = true
|
||||||
|
src_ip.datatype = "ip4addr"
|
||||||
|
|
||||||
|
sport = s:taboption("advanced", Value, "src_port", translate("Source port"),
|
||||||
|
translate("Match incoming traffic originating from the given " ..
|
||||||
|
"source port or port range on the client host"))
|
||||||
|
sport.optional = true
|
||||||
|
sport.datatype = "portrange"
|
||||||
|
sport:depends("proto", "tcp")
|
||||||
|
sport:depends("proto", "udp")
|
||||||
|
sport:depends("proto", "tcpudp")
|
||||||
|
|
||||||
|
reflection = s:taboption("advanced", Flag, "reflection", translate("Enable NAT Loopback"))
|
||||||
|
reflection.rmempty = true
|
||||||
|
reflection:depends({ target = "DNAT", src = wan_zone })
|
||||||
|
reflection.cfgvalue = function(...)
|
||||||
|
return Flag.cfgvalue(...) or "1"
|
||||||
|
end
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
--[[
|
|
||||||
LuCI - Lua Configuration Interface
|
|
||||||
|
|
||||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
|
||||||
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
|
||||||
|
|
||||||
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$
|
|
||||||
]]--
|
|
||||||
|
|
||||||
m = Map("firewall", translate("Traffic Control"))
|
|
||||||
s = m:section(TypedSection, "forwarding", translate("Zone-to-Zone traffic"),
|
|
||||||
translate("Here you can specify which network traffic is allowed " ..
|
|
||||||
"to flow between network zones. Only new connections will " ..
|
|
||||||
"be matched. Packets belonging to already open " ..
|
|
||||||
"connections are automatically allowed to pass the " ..
|
|
||||||
"firewall. If you experience occasional connection " ..
|
|
||||||
"problems try enabling MSS Clamping otherwise disable it " ..
|
|
||||||
"for performance reasons."))
|
|
||||||
s.template = "cbi/tblsection"
|
|
||||||
s.addremove = true
|
|
||||||
s.anonymous = true
|
|
||||||
|
|
||||||
iface = s:option(ListValue, "src", translate("Source"))
|
|
||||||
oface = s:option(ListValue, "dest", translate("Destination"))
|
|
||||||
|
|
||||||
luci.model.uci.cursor():foreach("firewall", "zone",
|
|
||||||
function (section)
|
|
||||||
iface:value(section.name)
|
|
||||||
oface:value(section.name)
|
|
||||||
end)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
s = m:section(TypedSection, "rule", translate("Rules"))
|
|
||||||
s.addremove = true
|
|
||||||
s.anonymous = true
|
|
||||||
s.template = "cbi/tblsection"
|
|
||||||
s.extedit = luci.dispatcher.build_url("admin", "network", "firewall", "rule", "%s")
|
|
||||||
s.defaults.target = "ACCEPT"
|
|
||||||
|
|
||||||
local created = nil
|
|
||||||
|
|
||||||
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(luci.dispatcher.build_url(
|
|
||||||
"admin", "network", "firewall", "rule", created
|
|
||||||
))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
s:option(DummyValue, "_name", translate("Name"))
|
|
||||||
s:option(DummyValue, "proto", translate("Protocol"))
|
|
||||||
|
|
||||||
src = s:option(DummyValue, "src", translate("Source"))
|
|
||||||
function src.cfgvalue(self, s)
|
|
||||||
return "%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 "*"
|
|
||||||
}
|
|
||||||
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
|
|
|
@ -2,6 +2,7 @@
|
||||||
LuCI - Lua Configuration Interface
|
LuCI - Lua Configuration Interface
|
||||||
|
|
||||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
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");
|
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.
|
||||||
|
@ -11,62 +12,121 @@ You may obtain a copy of the License at
|
||||||
|
|
||||||
$Id$
|
$Id$
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
|
local has_v2 = nixio.fs.access("/lib/firewall/fw.sh")
|
||||||
|
local dsp = require "luci.dispatcher"
|
||||||
|
|
||||||
arg[1] = arg[1] or ""
|
arg[1] = arg[1] or ""
|
||||||
|
|
||||||
m = Map("firewall", translate("Advanced Rules"),
|
m = Map("firewall", translate("Advanced Rules"),
|
||||||
translate("Advanced rules let you customize the firewall to your " ..
|
translate("Advanced rules let you customize the firewall to your " ..
|
||||||
"needs. Only new connections will be matched. Packets " ..
|
"needs. Only new connections will be matched. Packets " ..
|
||||||
"belonging to already open connections are automatically " ..
|
"belonging to already open connections are automatically " ..
|
||||||
"allowed to pass the firewall."))
|
"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 = m:section(NamedSection, arg[1], "rule", "")
|
||||||
s.anonymous = true
|
s.anonymous = true
|
||||||
s.addremove = false
|
s.addremove = false
|
||||||
|
|
||||||
|
s:tab("general", translate("General Settings"))
|
||||||
|
s:tab("advanced", translate("Advanced Options"))
|
||||||
|
|
||||||
back = s:option(DummyValue, "_overview", translate("Overview"))
|
back = s:option(DummyValue, "_overview", translate("Overview"))
|
||||||
back.value = ""
|
back.value = ""
|
||||||
back.titleref = luci.dispatcher.build_url("admin", "network", "firewall", "rule")
|
back.titleref = dsp.build_url("admin", "network", "firewall", "rule")
|
||||||
|
|
||||||
|
|
||||||
name = s:option(Value, "_name", translate("Name").." "..translate("(optional)"))
|
name = s:taboption("general", Value, "_name", translate("Name").." "..translate("(optional)"))
|
||||||
name.rmempty = true
|
name.rmempty = true
|
||||||
|
|
||||||
iface = s:option(ListValue, "src", translate("Source zone"))
|
src = s:taboption("general", Value, "src", translate("Source zone"))
|
||||||
iface.rmempty = true
|
src.nocreate = true
|
||||||
|
src.default = "wan"
|
||||||
|
src.template = "cbi/firewall_zonelist"
|
||||||
|
|
||||||
oface = s:option(ListValue, "dest", translate("Destination zone"))
|
dest = s:taboption("advanced", Value, "dest", translate("Destination zone"))
|
||||||
oface:value("", translate("any"))
|
dest.nocreate = true
|
||||||
oface.rmempty = true
|
dest.default = "lan"
|
||||||
|
dest.template = "cbi/firewall_zonelist"
|
||||||
|
|
||||||
luci.model.uci.cursor():foreach("firewall", "zone",
|
proto = s:taboption("general", Value, "proto", translate("Protocol"))
|
||||||
function (section)
|
|
||||||
iface:value(section.name)
|
|
||||||
oface:value(section.name)
|
|
||||||
end)
|
|
||||||
|
|
||||||
proto = s:option(Value, "proto", translate("Protocol"))
|
|
||||||
proto.optional = true
|
proto.optional = true
|
||||||
proto:value("")
|
|
||||||
proto:value("all", translate("Any"))
|
proto:value("all", translate("Any"))
|
||||||
proto:value("tcpudp", "TCP+UDP")
|
proto:value("tcpudp", "TCP+UDP")
|
||||||
proto:value("tcp", "TCP")
|
proto:value("tcp", "TCP")
|
||||||
proto:value("udp", "UDP")
|
proto:value("udp", "UDP")
|
||||||
proto:value("icmp", "ICMP")
|
proto:value("icmp", "ICMP")
|
||||||
|
|
||||||
s:option(Value, "src_ip", translate("Source address")).optional = true
|
icmpt = s:taboption("general", Value, "icmp_type", translate("Match ICMP type"))
|
||||||
s:option(Value, "dest_ip", translate("Destination address")).optional = true
|
icmpt:depends("proto", "icmp")
|
||||||
s:option(Value, "src_mac", translate("Source MAC-address")).optional = true
|
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")
|
||||||
|
|
||||||
sport = s:option(Value, "src_port", translate("Source port"))
|
src_ip = s:taboption("general", Value, "src_ip", translate("Source address"))
|
||||||
|
src_ip.optional = true
|
||||||
|
src_ip.datatype = has_v2 and "ipaddr" or "ip4addr"
|
||||||
|
|
||||||
|
sport = s:taboption("general", Value, "src_port", translate("Source port"))
|
||||||
|
sport.optional = true
|
||||||
|
sport.datatype = "portrange"
|
||||||
sport:depends("proto", "tcp")
|
sport:depends("proto", "tcp")
|
||||||
sport:depends("proto", "udp")
|
sport:depends("proto", "udp")
|
||||||
sport:depends("proto", "tcpudp")
|
sport:depends("proto", "tcpudp")
|
||||||
|
|
||||||
dport = s:option(Value, "dest_port", translate("Destination port"))
|
dest_ip = s:taboption("general", Value, "dest_ip", translate("Destination address"))
|
||||||
|
dest_ip.optional = true
|
||||||
|
dest_ip.datatype = has_v2 and "ipaddr" or "ip4addr"
|
||||||
|
|
||||||
|
dport = s:taboption("general", Value, "dest_port", translate("Destination port"))
|
||||||
|
dport.optional = true
|
||||||
|
dport.datatype = "portrange"
|
||||||
dport:depends("proto", "tcp")
|
dport:depends("proto", "tcp")
|
||||||
dport:depends("proto", "udp")
|
dport:depends("proto", "udp")
|
||||||
dport:depends("proto", "tcpudp")
|
dport:depends("proto", "tcpudp")
|
||||||
|
|
||||||
jump = s:option(ListValue, "target", translate("Action"))
|
jump = s:taboption("general", ListValue, "target", translate("Action"))
|
||||||
jump.rmempty = true
|
jump.rmempty = true
|
||||||
jump.default = "ACCEPT"
|
jump.default = "ACCEPT"
|
||||||
jump:value("DROP", translate("drop"))
|
jump:value("DROP", translate("drop"))
|
||||||
|
@ -74,4 +134,14 @@ jump:value("ACCEPT", translate("accept"))
|
||||||
jump:value("REJECT", translate("reject"))
|
jump:value("REJECT", translate("reject"))
|
||||||
|
|
||||||
|
|
||||||
|
s:taboption("advanced", Value, "src_mac", translate("Source MAC-address")).optional = true
|
||||||
|
|
||||||
|
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
|
return m
|
||||||
|
|
|
@ -14,6 +14,9 @@ $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 ds = require "luci.dispatcher"
|
||||||
|
|
||||||
|
local has_v2 = nixio.fs.access("/lib/firewall/fw.sh")
|
||||||
|
|
||||||
require("luci.tools.webadmin")
|
require("luci.tools.webadmin")
|
||||||
m = Map("firewall", translate("Firewall"), translate("The firewall creates zones over your network interfaces to control network traffic flow."))
|
m = Map("firewall", translate("Firewall"), translate("The firewall creates zones over your network interfaces to control network traffic flow."))
|
||||||
|
@ -25,18 +28,22 @@ s = m:section(TypedSection, "defaults")
|
||||||
s.anonymous = true
|
s.anonymous = true
|
||||||
s.addremove = false
|
s.addremove = false
|
||||||
|
|
||||||
s:option(Flag, "syn_flood", translate("Enable SYN-flood protection"))
|
s:tab("general", translate("General Settings"))
|
||||||
|
s:tab("custom", translate("Custom Rules"))
|
||||||
|
|
||||||
local di = s:option(Flag, "drop_invalid", translate("Drop invalid packets"))
|
|
||||||
|
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
|
di.rmempty = false
|
||||||
function di.cfgvalue(...)
|
function di.cfgvalue(...)
|
||||||
return AbstractValue.cfgvalue(...) or "1"
|
return AbstractValue.cfgvalue(...) or "1"
|
||||||
end
|
end
|
||||||
|
|
||||||
p = {}
|
p = {}
|
||||||
p[1] = s:option(ListValue, "input", translate("Input"))
|
p[1] = s:taboption("general", ListValue, "input", translate("Input"))
|
||||||
p[2] = s:option(ListValue, "output", translate("Output"))
|
p[2] = s:taboption("general", ListValue, "output", translate("Output"))
|
||||||
p[3] = s:option(ListValue, "forward", translate("Forward"))
|
p[3] = 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"))
|
||||||
|
@ -44,14 +51,41 @@ for i, v in ipairs(p) do
|
||||||
v:value("ACCEPT", translate("accept"))
|
v:value("ACCEPT", translate("accept"))
|
||||||
end
|
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)
|
||||||
|
nixio.fs.writefile("/etc/firewall.user", value)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
s = m:section(TypedSection, "zone", translate("Zones"))
|
s = m:section(TypedSection, "zone", translate("Zones"))
|
||||||
s.template = "cbi/tblsection"
|
s.template = "cbi/tblsection"
|
||||||
s.anonymous = true
|
s.anonymous = true
|
||||||
s.addremove = true
|
s.addremove = true
|
||||||
|
s.extedit = ds.build_url("admin", "network", "firewall", "zones", "%s")
|
||||||
|
|
||||||
name = s:option(Value, "name", translate("Name"))
|
function s.create(self)
|
||||||
name.size = 8
|
local z = fw:new_zone()
|
||||||
|
if z then
|
||||||
|
luci.http.redirect(
|
||||||
|
ds.build_url("admin", "network", "firewall", "zones", z.sid)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
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 = {}
|
||||||
p[1] = s:option(ListValue, "input", translate("Input"))
|
p[1] = s:option(ListValue, "input", translate("Input"))
|
||||||
|
@ -67,15 +101,166 @@ end
|
||||||
s:option(Flag, "masq", translate("Masquerading"))
|
s:option(Flag, "masq", translate("Masquerading"))
|
||||||
s:option(Flag, "mtu_fix", translate("MSS clamping"))
|
s:option(Flag, "mtu_fix", translate("MSS clamping"))
|
||||||
|
|
||||||
net = s:option(MultiValue, "network", translate("Network"))
|
|
||||||
net.template = "cbi/network_netlist"
|
|
||||||
net.widget = "checkbox"
|
|
||||||
net.rmempty = true
|
|
||||||
luci.tools.webadmin.cbi_add_networks(net)
|
|
||||||
|
|
||||||
function net.cfgvalue(self, section)
|
local created = nil
|
||||||
local value = MultiValue.cfgvalue(self, section)
|
|
||||||
return value or name:cfgvalue(section)
|
--
|
||||||
|
-- Redirects
|
||||||
|
--
|
||||||
|
|
||||||
|
s = m:section(TypedSection, "redirect", translate("Redirections"))
|
||||||
|
s.template = "cbi/tblsection"
|
||||||
|
s.addremove = true
|
||||||
|
s.anonymous = true
|
||||||
|
s.extedit = ds.build_url("admin", "network", "firewall", "redirect", "%s")
|
||||||
|
|
||||||
|
function s.create(self, section)
|
||||||
|
created = TypedSection.create(self, section)
|
||||||
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
|
||||||
|
|
||||||
|
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.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
|
return m
|
||||||
|
|
Loading…
Reference in a new issue