85c126d7aed77a240db4907bc2c3ec13e85bfb4b
7 'require tools.firewall as fwtool';
8 'require tools.widgets as widgets';
10 return L
.view
.extend({
11 callConntrackHelpers
: rpc
.declare({
13 method
: 'getConntrackHelpers',
14 expect
: { result
: [] }
19 this.callConntrackHelpers(),
20 firewall
.getDefaults()
24 render: function(data
) {
25 if (fwtool
.checkLegacySNAT())
26 return fwtool
.renderMigration();
28 return this.renderZones(data
);
31 renderZones: function(data
) {
32 var ctHelpers
= data
[0],
36 m
= new form
.Map('firewall', _('Firewall - Zone Settings'),
37 _('The firewall creates zones over your network interfaces to control network traffic flow.'));
39 s
= m
.section(form
.TypedSection
, 'defaults', _('General Settings'));
43 o
= s
.option(form
.Flag
, 'syn_flood', _('Enable SYN-flood protection'));
44 o
= s
.option(form
.Flag
, 'drop_invalid', _('Drop invalid packets'));
47 s
.option(form
.ListValue
, 'input', _('Input')),
48 s
.option(form
.ListValue
, 'output', _('Output')),
49 s
.option(form
.ListValue
, 'forward', _('Forward'))
52 for (var i
= 0; i
< p
.length
; i
++) {
53 p
[i
].value('REJECT', _('reject'));
54 p
[i
].value('DROP', _('drop'));
55 p
[i
].value('ACCEPT', _('accept'));
58 /* Netfilter flow offload support */
60 if (L
.hasSystemFeature('offloading')) {
61 s
= m
.section(form
.TypedSection
, 'defaults', _('Routing/NAT Offloading'),
62 _('Experimental feature. Not fully compatible with QoS/SQM.'));
67 o
= s
.option(form
.Flag
, 'flow_offloading',
68 _('Software flow offloading'),
69 _('Software based offloading for routing/NAT'));
72 o
= s
.option(form
.Flag
, 'flow_offloading_hw',
73 _('Hardware flow offloading'),
74 _('Requires hardware NAT support. Implemented at least for mt7621'));
76 o
.depends('flow_offloading', '1');
80 s
= m
.section(form
.GridSection
, 'zone', _('Zones'));
85 s
.handleRemove = function(section_id
, ev
) {
86 return firewall
.deleteZone(section_id
).then(L
.bind(function() {
87 return this.super('handleRemove', [section_id
, ev
]);
91 s
.tab('general', _('General Settings'));
92 s
.tab('advanced', _('Advanced Settings'));
93 s
.tab('conntrack', _('Conntrack Settings'));
94 s
.tab('extra', _('Extra iptables arguments'));
96 o
= s
.taboption('general', form
.DummyValue
, '_generalinfo');
99 o
.cfgvalue = function(section_id
) {
100 var name
= uci
.get('firewall', section_id
, 'name');
102 name
= _("this new zone");
103 return _('This section defines common properties of %q. The <em>input</em> and <em>output</em> options set the default policies for traffic entering and leaving this zone while the <em>forward</em> option describes the policy for forwarded traffic between different networks within the zone. <em>Covered networks</em> specifies which available networks are members of this zone.')
104 .replace(/%s/g, name
).replace(/%q/g, '"' + name
+ '"');
107 o
= s
.taboption('general', form
.Value
, 'name', _('Name'));
108 o
.placeholder
= _('Unnamed zone');
111 o
.datatype
= 'and(uciname,maxlength(11))';
112 o
.write = function(section_id
, formvalue
) {
113 var cfgvalue
= this.cfgvalue(section_id
);
115 if (cfgvalue
== null || cfgvalue
== '')
116 return uci
.set('firewall', section_id
, 'name', formvalue
);
117 else if (cfgvalue
!= formvalue
)
118 return firewall
.renameZone(cfgvalue
, formvalue
);
121 o
= s
.option(widgets
.ZoneForwards
, '_info', _('Zone ⇒ Forwardings'));
124 o
.cfgvalue = function(section_id
) {
125 return uci
.get('firewall', section_id
, 'name');
129 s
.taboption('general', form
.ListValue
, 'input', _('Input')),
130 s
.taboption('general', form
.ListValue
, 'output', _('Output')),
131 s
.taboption('general', form
.ListValue
, 'forward', _('Forward'))
134 for (var i
= 0; i
< p
.length
; i
++) {
135 p
[i
].value('REJECT', _('reject'));
136 p
[i
].value('DROP', _('drop'));
137 p
[i
].value('ACCEPT', _('accept'));
138 p
[i
].editable
= true;
141 p
[0].default = fwDefaults
.getInput();
142 p
[1].default = fwDefaults
.getOutput();
143 p
[2].default = fwDefaults
.getForward();
145 o
= s
.taboption('general', form
.Flag
, 'masq', _('Masquerading'));
148 o
= s
.taboption('general', form
.Flag
, 'mtu_fix', _('MSS clamping'));
151 o
= s
.taboption('general', widgets
.NetworkSelect
, 'network', _('Covered networks'));
154 o
.cfgvalue = function(section_id
) {
155 return uci
.get('firewall', section_id
, 'network');
157 o
.write = function(section_id
, formvalue
) {
158 var name
= uci
.get('firewall', section_id
, 'name'),
159 cfgvalue
= this.cfgvalue(section_id
);
161 if (typeof(cfgvalue
) == 'string' && Array
.isArray(formvalue
) && (cfgvalue
== formvalue
.join(' ')))
164 var tasks
= [ firewall
.getZone(name
) ];
166 if (Array
.isArray(formvalue
))
167 for (var i
= 0; i
< formvalue
.length
; i
++) {
168 var netname
= formvalue
[i
];
169 tasks
.push(network
.getNetwork(netname
).then(function(net
) {
170 return net
|| network
.addNetwork(netname
, { 'proto': 'none' });
174 return Promise
.all(tasks
).then(function(zone_networks
) {
175 if (zone_networks
[0])
176 for (var i
= 1; i
< zone_networks
.length
; i
++)
177 zone_networks
[0].addNetwork(zone_networks
[i
].getName());
181 o
= s
.taboption('advanced', form
.DummyValue
, '_advancedinfo');
184 o
.cfgvalue = function(section_id
) {
185 var name
= uci
.get('firewall', section_id
, 'name');
187 name
= _("this new zone");
188 return _('The options below control the forwarding policies between this zone (%s) and other zones. <em>Destination zones</em> cover forwarded traffic <strong>originating from %q</strong>. <em>Source zones</em> match forwarded traffic from other zones <strong>targeted at %q</strong>. The forwarding rule is <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.')
192 o
= s
.taboption('advanced', widgets
.DeviceSelect
, 'device', _('Covered devices'), _('Use this option to classify zone traffic by raw, non-<em>uci</em> managed network devices.'));
197 o
= s
.taboption('advanced', form
.DynamicList
, 'subnet', _('Covered subnets'), _('Use this option to classify zone traffic by source or destination subnet instead of networks or devices.'));
198 o
.datatype
= 'neg(cidr)';
202 o
= s
.taboption('advanced', form
.ListValue
, 'family', _('Restrict to address family'));
203 o
.value('', _('IPv4 and IPv6'));
204 o
.value('ipv4', _('IPv4 only'));
205 o
.value('ipv6', _('IPv6 only'));
208 o
= s
.taboption('advanced', form
.DynamicList
, 'masq_src', _('Restrict Masquerading to given source subnets'));
209 o
.depends('family', '');
210 o
.depends('family', 'ipv4');
211 o
.datatype
= 'list(neg(or(uciname,hostname,ipmask4)))';
212 o
.placeholder
= '0.0.0.0/0';
215 o
= s
.taboption('advanced', form
.DynamicList
, 'masq_dest', _('Restrict Masquerading to given destination subnets'));
216 o
.depends('family', '');
217 o
.depends('family', 'ipv4');
218 o
.datatype
= 'list(neg(or(uciname,hostname,ipmask4)))';
219 o
.placeholder
= '0.0.0.0/0';
222 o
= s
.taboption('conntrack', form
.Flag
, 'masq_allow_invalid', _('Allow "invalid" traffic'), _('Do not install extra rules to reject forwarded traffic with conntrack state <em>invalid</em>. This may be required for complex asymmetric route setups.'));
225 o
= s
.taboption('conntrack', form
.Flag
, 'auto_helper', _('Automatic helper assignment'), _('Automatically assign conntrack helpers based on traffic protocol and port'));
226 o
.default = o
.enabled
;
229 o
= s
.taboption('conntrack', form
.MultiValue
, 'helper', _('Conntrack helpers'), _('Explicitly choses allowed connection tracking helpers for zone traffic'));
230 o
.depends('auto_helper', '0');
232 for (var i
= 0; i
< ctHelpers
.length
; i
++)
233 o
.value(ctHelpers
[i
].name
, '<span class="hide-close">%s (%s)</span><span class="hide-open">%s</span>'.format(ctHelpers
[i
].description
, ctHelpers
[i
].name
.toUpperCase(), ctHelpers
[i
].name
.toUpperCase()));
235 o
= s
.taboption('advanced', form
.Flag
, 'log', _('Enable logging on this zone'));
238 o
= s
.taboption('advanced', form
.Value
, 'log_limit', _('Limit log messages'));
239 o
.depends('log', '1');
240 o
.placeholder
= '10/minute';
243 o
= s
.taboption('extra', form
.DummyValue
, '_extrainfo');
246 o
.cfgvalue = function(section_id
) {
247 return _('Passing raw iptables arguments to source and destination traffic classification rules allows to match packets based on other criteria than interfaces or subnets. These options should be used with extreme care as invalid values could render the firewall ruleset broken, completely exposing all services.');
250 o
= s
.taboption('extra', form
.Value
, 'extra_src', _('Extra source arguments'), _('Additional raw <em>iptables</em> arguments to classify zone source traffic, e.g. <code>-p tcp --sport 443</code> to only match inbound HTTPS traffic.'));
252 o
.cfgvalue = function(section_id
) {
253 return uci
.get('firewall', section_id
, 'extra_src') || uci
.get('firewall', section_id
, 'extra');
255 o
.write = function(section_id
, value
) {
256 uci
.unset('firewall', section_id
, 'extra');
257 uci
.set('firewall', section_id
, 'extra_src', value
);
260 o
= s
.taboption('extra', form
.Value
, 'extra_dest', _('Extra destination arguments'), _('Additional raw <em>iptables</em> arguments to classify zone destination traffic, e.g. <code>-p tcp --dport 443</code> to only match outbound HTTPS traffic.'));
262 o
.cfgvalue = function(section_id
) {
263 return uci
.get('firewall', section_id
, 'extra_dest') || uci
.get('firewall', section_id
, 'extra_src') || uci
.get('firewall', section_id
, 'extra');
265 o
.write = function(section_id
, value
) {
266 uci
.unset('firewall', section_id
, 'extra');
267 uci
.set('firewall', section_id
, 'extra_dest', value
);
270 o
= s
.taboption('general', form
.DummyValue
, '_forwardinfo');
273 o
.cfgvalue = function(section_id
) {
274 var name
= uci
.get('firewall', section_id
, 'name');
276 name
= _("this new zone");
277 return _('The options below control the forwarding policies between this zone (%s) and other zones. <em>Destination zones</em> cover forwarded traffic <strong>originating from %q</strong>. <em>Source zones</em> match forwarded traffic from other zones <strong>targeted at %q</strong>. The forwarding rule is <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.')
281 out
= o
= s
.taboption('general', widgets
.ZoneSelect
, 'out', _('Allow forward to <em>destination zones</em>:'));
285 o
.filter = function(section_id
, value
) {
286 return (uci
.get('firewall', section_id
, 'name') != value
);
288 o
.cfgvalue = function(section_id
) {
289 var out
= (this.option
== 'out'),
290 zone
= this.lookupZone(uci
.get('firewall', section_id
, 'name')),
291 fwds
= zone
? zone
.getForwardingsBy(out
? 'src' : 'dest') : [],
294 for (var i
= 0; i
< fwds
.length
; i
++)
295 value
.push(out
? fwds
[i
].getDestination() : fwds
[i
].getSource());
299 o
.write
= o
.remove = function(section_id
, formvalue
) {
300 var out
= (this.option
== 'out'),
301 zone
= this.lookupZone(uci
.get('firewall', section_id
, 'name')),
302 fwds
= zone
? zone
.getForwardingsBy(out
? 'src' : 'dest') : [];
304 if (formvalue
== null)
307 if (Array
.isArray(formvalue
)) {
308 for (var i
= 0; i
< fwds
.length
; i
++) {
309 var cmp
= out
? fwds
[i
].getDestination() : fwds
[i
].getSource();
310 if (!formvalue
.filter(function(d
) { return d
== cmp
}).length
)
311 zone
.deleteForwarding(fwds
[i
]);
314 for (var i
= 0; i
< formvalue
.length
; i
++)
316 zone
.addForwardingTo(formvalue
[i
]);
318 zone
.addForwardingFrom(formvalue
[i
]);
322 inp
= o
= s
.taboption('general', widgets
.ZoneSelect
, 'in', _('Allow forward from <em>source zones</em>:'));
326 o
.write
= o
.remove
= out
.write
;
327 o
.filter
= out
.filter
;
328 o
.cfgvalue
= out
.cfgvalue
;