| 1 | --[[ |
|---|
| 2 | LuCI - Lua Configuration Interface |
|---|
| 3 | |
|---|
| 4 | Copyright 2008 Steven Barth <steven@midlink.org> |
|---|
| 5 | |
|---|
| 6 | Licensed under the Apache License, Version 2.0 (the "License"); |
|---|
| 7 | you may not use this file except in compliance with the License. |
|---|
| 8 | You may obtain a copy of the License at |
|---|
| 9 | |
|---|
| 10 | http://www.apache.org/licenses/LICENSE-2.0 |
|---|
| 11 | |
|---|
| 12 | $Id$ |
|---|
| 13 | ]]-- |
|---|
| 14 | |
|---|
| 15 | local nw = require "luci.model.network" |
|---|
| 16 | local fw = require "luci.model.firewall" |
|---|
| 17 | local ds = require "luci.dispatcher" |
|---|
| 18 | local ut = require "luci.util" |
|---|
| 19 | |
|---|
| 20 | local m, p, i, v |
|---|
| 21 | local s, name, net, family, msrc, mdest, log, lim |
|---|
| 22 | local s2, out, inp |
|---|
| 23 | |
|---|
| 24 | |
|---|
| 25 | m = Map("firewall", translate("Firewall - Zone Settings")) |
|---|
| 26 | m.redirect = luci.dispatcher.build_url("admin/network/firewall/zones") |
|---|
| 27 | |
|---|
| 28 | fw.init(m.uci) |
|---|
| 29 | nw.init(m.uci) |
|---|
| 30 | |
|---|
| 31 | |
|---|
| 32 | local zone = fw:get_zone(arg[1]) |
|---|
| 33 | if not zone then |
|---|
| 34 | luci.http.redirect(dsp.build_url("admin/network/firewall/zones")) |
|---|
| 35 | return |
|---|
| 36 | else |
|---|
| 37 | m.title = "%s - %s" %{ |
|---|
| 38 | translate("Firewall - Zone Settings"), |
|---|
| 39 | translatef("Zone %q", zone:name() or "?") |
|---|
| 40 | } |
|---|
| 41 | end |
|---|
| 42 | |
|---|
| 43 | |
|---|
| 44 | s = m:section(NamedSection, zone.sid, "zone", |
|---|
| 45 | translatef("Zone %q", zone:name()), |
|---|
| 46 | translatef("This section defines common properties of %q. \ |
|---|
| 47 | The <em>input</em> and <em>output</em> options set the default \ |
|---|
| 48 | policies for traffic entering and leaving this zone while the \ |
|---|
| 49 | <em>forward</em> option describes the policy for forwarded traffic \ |
|---|
| 50 | between different networks within the zone. \ |
|---|
| 51 | <em>Covered networks</em> specifies which available networks are \ |
|---|
| 52 | member of this zone.", zone:name())) |
|---|
| 53 | |
|---|
| 54 | s.anonymous = true |
|---|
| 55 | s.addremove = false |
|---|
| 56 | |
|---|
| 57 | m.on_commit = function(map) |
|---|
| 58 | local zone = fw:get_zone(arg[1]) |
|---|
| 59 | if zone then |
|---|
| 60 | s.section = zone.sid |
|---|
| 61 | s2.section = zone.sid |
|---|
| 62 | end |
|---|
| 63 | end |
|---|
| 64 | |
|---|
| 65 | |
|---|
| 66 | s:tab("general", translate("General Settings")) |
|---|
| 67 | s:tab("advanced", translate("Advanced Settings")) |
|---|
| 68 | |
|---|
| 69 | |
|---|
| 70 | name = s:taboption("general", Value, "name", translate("Name")) |
|---|
| 71 | name.optional = false |
|---|
| 72 | name.forcewrite = true |
|---|
| 73 | name.datatype = "uciname" |
|---|
| 74 | |
|---|
| 75 | function name.write(self, section, value) |
|---|
| 76 | if zone:name() ~= value then |
|---|
| 77 | fw:rename_zone(zone:name(), value) |
|---|
| 78 | out.exclude = value |
|---|
| 79 | inp.exclude = value |
|---|
| 80 | end |
|---|
| 81 | |
|---|
| 82 | m.redirect = ds.build_url("admin/network/firewall/zones", value) |
|---|
| 83 | m.title = "%s - %s" %{ |
|---|
| 84 | translate("Firewall - Zone Settings"), |
|---|
| 85 | translatef("Zone %q", value or "?") |
|---|
| 86 | } |
|---|
| 87 | end |
|---|
| 88 | |
|---|
| 89 | p = { |
|---|
| 90 | s:taboption("general", ListValue, "input", translate("Input")), |
|---|
| 91 | s:taboption("general", ListValue, "output", translate("Output")), |
|---|
| 92 | s:taboption("general", ListValue, "forward", translate("Forward")) |
|---|
| 93 | } |
|---|
| 94 | |
|---|
| 95 | for i, v in ipairs(p) do |
|---|
| 96 | v:value("REJECT", translate("reject")) |
|---|
| 97 | v:value("DROP", translate("drop")) |
|---|
| 98 | v:value("ACCEPT", translate("accept")) |
|---|
| 99 | end |
|---|
| 100 | |
|---|
| 101 | s:taboption("general", Flag, "masq", translate("Masquerading")) |
|---|
| 102 | s:taboption("general", Flag, "mtu_fix", translate("MSS clamping")) |
|---|
| 103 | |
|---|
| 104 | net = s:taboption("general", Value, "network", translate("Covered networks")) |
|---|
| 105 | net.template = "cbi/network_netlist" |
|---|
| 106 | net.widget = "checkbox" |
|---|
| 107 | net.cast = "string" |
|---|
| 108 | |
|---|
| 109 | function net.formvalue(self, section) |
|---|
| 110 | return Value.formvalue(self, section) or "-" |
|---|
| 111 | end |
|---|
| 112 | |
|---|
| 113 | function net.cfgvalue(self, section) |
|---|
| 114 | return Value.cfgvalue(self, section) or name:cfgvalue(section) |
|---|
| 115 | end |
|---|
| 116 | |
|---|
| 117 | function net.write(self, section, value) |
|---|
| 118 | zone:clear_networks() |
|---|
| 119 | |
|---|
| 120 | local n |
|---|
| 121 | for n in ut.imatch(value) do |
|---|
| 122 | zone:add_network(n) |
|---|
| 123 | end |
|---|
| 124 | end |
|---|
| 125 | |
|---|
| 126 | |
|---|
| 127 | family = s:taboption("advanced", ListValue, "family", |
|---|
| 128 | translate("Restrict to address family")) |
|---|
| 129 | |
|---|
| 130 | family.rmempty = true |
|---|
| 131 | family:value("", translate("IPv4 and IPv6")) |
|---|
| 132 | family:value("ipv4", translate("IPv4 only")) |
|---|
| 133 | family:value("ipv6", translate("IPv6 only")) |
|---|
| 134 | |
|---|
| 135 | msrc = s:taboption("advanced", DynamicList, "masq_src", |
|---|
| 136 | translate("Restrict Masquerading to given source subnets")) |
|---|
| 137 | |
|---|
| 138 | msrc.optional = true |
|---|
| 139 | msrc.datatype = "neg_network_ip4addr" |
|---|
| 140 | msrc.placeholder = "0.0.0.0/0" |
|---|
| 141 | msrc:depends("family", "") |
|---|
| 142 | msrc:depends("family", "ipv4") |
|---|
| 143 | |
|---|
| 144 | mdest = s:taboption("advanced", DynamicList, "masq_dest", |
|---|
| 145 | translate("Restrict Masquerading to given destination subnets")) |
|---|
| 146 | |
|---|
| 147 | mdest.optional = true |
|---|
| 148 | mdest.datatype = "neg_network_ip4addr" |
|---|
| 149 | mdest.placeholder = "0.0.0.0/0" |
|---|
| 150 | mdest:depends("family", "") |
|---|
| 151 | mdest:depends("family", "ipv4") |
|---|
| 152 | |
|---|
| 153 | s:taboption("advanced", Flag, "conntrack", |
|---|
| 154 | translate("Force connection tracking")) |
|---|
| 155 | |
|---|
| 156 | log = s:taboption("advanced", Flag, "log", |
|---|
| 157 | translate("Enable logging on this zone")) |
|---|
| 158 | |
|---|
| 159 | log.rmempty = true |
|---|
| 160 | log.enabled = "1" |
|---|
| 161 | |
|---|
| 162 | lim = s:taboption("advanced", Value, "log_limit", |
|---|
| 163 | translate("Limit log messages")) |
|---|
| 164 | |
|---|
| 165 | lim.placeholder = "10/minute" |
|---|
| 166 | lim:depends("log", "1") |
|---|
| 167 | |
|---|
| 168 | |
|---|
| 169 | s2 = m:section(NamedSection, zone.sid, "fwd_out", |
|---|
| 170 | translate("Inter-Zone Forwarding"), |
|---|
| 171 | translatef("The options below control the forwarding policies between \ |
|---|
| 172 | this zone (%s) and other zones. <em>Destination zones</em> cover \ |
|---|
| 173 | forwarded traffic <strong>originating from %q</strong>. \ |
|---|
| 174 | <em>Source zones</em> match forwarded traffic from other zones \ |
|---|
| 175 | <strong>targeted at %q</strong>. The forwarding rule is \ |
|---|
| 176 | <em>unidirectional</em>, e.g. a forward from lan to wan does \ |
|---|
| 177 | <em>not</em> imply a permission to forward from wan to lan as well.", |
|---|
| 178 | zone:name(), zone:name(), zone:name() |
|---|
| 179 | |
|---|
| 180 | )) |
|---|
| 181 | |
|---|
| 182 | out = s2:option(Value, "out", |
|---|
| 183 | translate("Allow forward to <em>destination zones</em>:")) |
|---|
| 184 | |
|---|
| 185 | out.nocreate = true |
|---|
| 186 | out.widget = "checkbox" |
|---|
| 187 | out.exclude = zone:name() |
|---|
| 188 | out.template = "cbi/firewall_zonelist" |
|---|
| 189 | |
|---|
| 190 | inp = s2:option(Value, "in", |
|---|
| 191 | translate("Allow forward from <em>source zones</em>:")) |
|---|
| 192 | |
|---|
| 193 | inp.nocreate = true |
|---|
| 194 | inp.widget = "checkbox" |
|---|
| 195 | inp.exclude = zone:name() |
|---|
| 196 | inp.template = "cbi/firewall_zonelist" |
|---|
| 197 | |
|---|
| 198 | function out.cfgvalue(self, section) |
|---|
| 199 | local v = { } |
|---|
| 200 | local f |
|---|
| 201 | for _, f in ipairs(zone:get_forwardings_by("src")) do |
|---|
| 202 | v[#v+1] = f:dest() |
|---|
| 203 | end |
|---|
| 204 | return table.concat(v, " ") |
|---|
| 205 | end |
|---|
| 206 | |
|---|
| 207 | function inp.cfgvalue(self, section) |
|---|
| 208 | local v = { } |
|---|
| 209 | local f |
|---|
| 210 | for _, f in ipairs(zone:get_forwardings_by("dest")) do |
|---|
| 211 | v[#v+1] = f:src() |
|---|
| 212 | end |
|---|
| 213 | return v |
|---|
| 214 | end |
|---|
| 215 | |
|---|
| 216 | function out.formvalue(self, section) |
|---|
| 217 | return Value.formvalue(self, section) or "-" |
|---|
| 218 | end |
|---|
| 219 | |
|---|
| 220 | function inp.formvalue(self, section) |
|---|
| 221 | return Value.formvalue(self, section) or "-" |
|---|
| 222 | end |
|---|
| 223 | |
|---|
| 224 | function out.write(self, section, value) |
|---|
| 225 | zone:del_forwardings_by("src") |
|---|
| 226 | |
|---|
| 227 | local f |
|---|
| 228 | for f in ut.imatch(value) do |
|---|
| 229 | zone:add_forwarding_to(f) |
|---|
| 230 | end |
|---|
| 231 | end |
|---|
| 232 | |
|---|
| 233 | function inp.write(self, section, value) |
|---|
| 234 | zone:del_forwardings_by("dest") |
|---|
| 235 | |
|---|
| 236 | local f |
|---|
| 237 | for f in ut.imatch(value) do |
|---|
| 238 | zone:add_forwarding_from(f) |
|---|
| 239 | end |
|---|
| 240 | end |
|---|
| 241 | |
|---|
| 242 | return m |
|---|