8 'require tools.firewall as fwtool';
9 'require tools.widgets as widgets';
12 callConntrackHelpers
: rpc
.declare({
14 method
: 'getConntrackHelpers',
15 expect
: { result
: [] }
20 this.callConntrackHelpers(),
21 firewall
.getDefaults()
25 render: function(data
) {
26 if (fwtool
.checkLegacySNAT())
27 return fwtool
.renderMigration();
29 return this.renderZones(data
);
32 renderZones: function(data
) {
33 var ctHelpers
= data
[0],
37 m
= new form
.Map('firewall', _('Firewall - Zone Settings'),
38 _('The firewall creates zones over your network interfaces to control network traffic flow.'));
40 s
= m
.section(form
.TypedSection
, 'defaults', _('General Settings'));
44 o
= s
.option(form
.Flag
, 'synflood_protect', _('Enable SYN-flood protection'));
45 o
.cfgvalue = function(section_id
) {
46 var val
= uci
.get('firewall', section_id
, 'synflood_protect');
47 return (val
!= null) ? val
: uci
.get('firewall', section_id
, 'syn_flood');
49 o
.write = function(section_id
, value
) {
50 uci
.unset('firewall', section_id
, 'syn_flood');
51 uci
.set('firewall', section_id
, 'synflood_protect', value
);
53 o
.remove = function(section_id
) {
54 uci
.unset('firewall', section_id
, 'syn_flood');
55 uci
.unset('firewall', section_id
, 'synflood_protect');
58 o
= s
.option(form
.Flag
, 'drop_invalid', _('Drop invalid packets'));
61 s
.option(form
.ListValue
, 'input', _('Input')),
62 s
.option(form
.ListValue
, 'output', _('Output')),
63 s
.option(form
.ListValue
, 'forward', _('Forward'))
66 for (var i
= 0; i
< p
.length
; i
++) {
67 p
[i
].value('REJECT', _('reject'));
68 p
[i
].value('DROP', _('drop'));
69 p
[i
].value('ACCEPT', _('accept'));
72 /* Netfilter flow offload support */
74 if (L
.hasSystemFeature('offloading')) {
75 s
= m
.section(form
.TypedSection
, 'defaults', _('Routing/NAT Offloading'),
76 _('Experimental feature. Not fully compatible with QoS/SQM.'));
81 o
= s
.option(form
.Flag
, 'flow_offloading',
82 _('Software flow offloading'),
83 _('Software based offloading for routing/NAT'));
86 o
= s
.option(form
.Flag
, 'flow_offloading_hw',
87 _('Hardware flow offloading'),
88 _('Requires hardware NAT support. Implemented at least for mt7621'));
90 o
.depends('flow_offloading', '1');
94 s
= m
.section(form
.GridSection
, 'zone', _('Zones'));
99 s
.handleRemove = function(section_id
, ev
) {
100 return firewall
.deleteZone(section_id
).then(L
.bind(function() {
101 return this.super('handleRemove', [section_id
, ev
]);
105 s
.tab('general', _('General Settings'));
106 s
.tab('advanced', _('Advanced Settings'));
107 s
.tab('conntrack', _('Conntrack Settings'));
108 s
.tab('extra', _('Extra iptables arguments'));
110 o
= s
.taboption('general', form
.DummyValue
, '_generalinfo');
113 o
.cfgvalue = function(section_id
) {
114 var name
= uci
.get('firewall', section_id
, 'name');
116 name
= _("this new zone");
117 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.')
118 .replace(/%s/g, name
).replace(/%q/g, '"' + name
+ '"');
121 o
= s
.taboption('general', form
.Value
, 'name', _('Name'));
122 o
.placeholder
= _('Unnamed zone');
125 o
.datatype
= 'and(uciname,maxlength(11))';
126 o
.write = function(section_id
, formvalue
) {
127 var cfgvalue
= this.cfgvalue(section_id
);
129 if (cfgvalue
== null || cfgvalue
== '')
130 return uci
.set('firewall', section_id
, 'name', formvalue
);
131 else if (cfgvalue
!= formvalue
)
132 return firewall
.renameZone(cfgvalue
, formvalue
);
135 o
= s
.option(widgets
.ZoneForwards
, '_info', _('Zone ⇒ Forwardings'));
138 o
.cfgvalue = function(section_id
) {
139 return uci
.get('firewall', section_id
, 'name');
143 s
.taboption('general', form
.ListValue
, 'input', _('Input')),
144 s
.taboption('general', form
.ListValue
, 'output', _('Output')),
145 s
.taboption('general', form
.ListValue
, 'forward', _('Forward'))
148 for (var i
= 0; i
< p
.length
; i
++) {
149 p
[i
].value('REJECT', _('reject'));
150 p
[i
].value('DROP', _('drop'));
151 p
[i
].value('ACCEPT', _('accept'));
152 p
[i
].editable
= true;
155 p
[0].default = fwDefaults
.getInput();
156 p
[1].default = fwDefaults
.getOutput();
157 p
[2].default = fwDefaults
.getForward();
159 o
= s
.taboption('general', form
.Flag
, 'masq', _('Masquerading'));
161 o
.tooltip = function(section_id
) {
162 var masq_src
= uci
.get('firewall', section_id
, 'masq_src')
163 var masq_dest
= uci
.get('firewall', section_id
, 'masq_dest')
164 if (masq_src
|| masq_dest
)
165 return _('Limited masquerading enabled');
170 o
= s
.taboption('general', form
.Flag
, 'mtu_fix', _('MSS clamping'));
173 o
= s
.taboption('general', widgets
.NetworkSelect
, 'network', _('Covered networks'));
176 o
.cfgvalue = function(section_id
) {
177 return uci
.get('firewall', section_id
, 'network');
179 o
.write = function(section_id
, formvalue
) {
180 var name
= uci
.get('firewall', section_id
, 'name'),
181 cfgvalue
= this.cfgvalue(section_id
);
183 if (typeof(cfgvalue
) == 'string' && Array
.isArray(formvalue
) && (cfgvalue
== formvalue
.join(' ')))
186 var tasks
= [ firewall
.getZone(name
) ];
188 if (Array
.isArray(formvalue
))
189 for (var i
= 0; i
< formvalue
.length
; i
++) {
190 var netname
= formvalue
[i
];
191 tasks
.push(network
.getNetwork(netname
).then(function(net
) {
192 return net
|| network
.addNetwork(netname
, { 'proto': 'none' });
196 return Promise
.all(tasks
).then(function(zone_networks
) {
197 if (zone_networks
[0]) {
198 zone_networks
[0].clearNetworks();
199 for (var i
= 1; i
< zone_networks
.length
; i
++)
200 zone_networks
[0].addNetwork(zone_networks
[i
].getName());
205 o
= s
.taboption('advanced', form
.DummyValue
, '_advancedinfo');
208 o
.cfgvalue = function(section_id
) {
209 var name
= uci
.get('firewall', section_id
, 'name');
211 name
= _("this new zone");
212 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.')
216 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.'));
221 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.'));
222 o
.datatype
= 'neg(cidr)';
226 o
= s
.taboption('advanced', form
.ListValue
, 'family', _('Restrict to address family'));
227 o
.value('', _('IPv4 and IPv6'));
228 o
.value('ipv4', _('IPv4 only'));
229 o
.value('ipv6', _('IPv6 only'));
232 o
= s
.taboption('advanced', form
.DynamicList
, 'masq_src', _('Restrict Masquerading to given source subnets'));
233 o
.depends('family', '');
234 o
.depends('family', 'ipv4');
235 o
.datatype
= 'list(neg(or(uciname,hostname,ipmask4)))';
236 o
.placeholder
= '0.0.0.0/0';
239 o
= s
.taboption('advanced', form
.DynamicList
, 'masq_dest', _('Restrict Masquerading to given destination subnets'));
240 o
.depends('family', '');
241 o
.depends('family', 'ipv4');
242 o
.datatype
= 'list(neg(or(uciname,hostname,ipmask4)))';
243 o
.placeholder
= '0.0.0.0/0';
246 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.'));
249 o
= s
.taboption('conntrack', form
.Flag
, 'auto_helper', _('Automatic helper assignment'), _('Automatically assign conntrack helpers based on traffic protocol and port'));
250 o
.default = o
.enabled
;
253 o
= s
.taboption('conntrack', form
.MultiValue
, 'helper', _('Conntrack helpers'), _('Explicitly choses allowed connection tracking helpers for zone traffic'));
254 o
.depends('auto_helper', '0');
256 for (var i
= 0; i
< ctHelpers
.length
; i
++)
257 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()));
259 o
= s
.taboption('advanced', form
.Flag
, 'log', _('Enable logging on this zone'));
262 o
= s
.taboption('advanced', form
.Value
, 'log_limit', _('Limit log messages'));
263 o
.depends('log', '1');
264 o
.placeholder
= '10/minute';
267 o
= s
.taboption('extra', form
.DummyValue
, '_extrainfo');
270 o
.cfgvalue = function(section_id
) {
271 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.');
274 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.'));
276 o
.cfgvalue = function(section_id
) {
277 return uci
.get('firewall', section_id
, 'extra_src') || uci
.get('firewall', section_id
, 'extra');
279 o
.write = function(section_id
, value
) {
280 uci
.unset('firewall', section_id
, 'extra');
281 uci
.set('firewall', section_id
, 'extra_src', value
);
284 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.'));
286 o
.cfgvalue = function(section_id
) {
287 return uci
.get('firewall', section_id
, 'extra_dest') || uci
.get('firewall', section_id
, 'extra_src') || uci
.get('firewall', section_id
, 'extra');
289 o
.write = function(section_id
, value
) {
290 uci
.unset('firewall', section_id
, 'extra');
291 uci
.set('firewall', section_id
, 'extra_dest', value
);
294 o
= s
.taboption('general', form
.DummyValue
, '_forwardinfo');
297 o
.cfgvalue = function(section_id
) {
298 var name
= uci
.get('firewall', section_id
, 'name');
300 name
= _("this new zone");
301 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.')
305 out
= o
= s
.taboption('general', widgets
.ZoneSelect
, 'out', _('Allow forward to <em>destination zones</em>:'));
309 o
.filter = function(section_id
, value
) {
310 return (uci
.get('firewall', section_id
, 'name') != value
);
312 o
.cfgvalue = function(section_id
) {
313 var out
= (this.option
== 'out'),
314 zone
= this.lookupZone(uci
.get('firewall', section_id
, 'name')),
315 fwds
= zone
? zone
.getForwardingsBy(out
? 'src' : 'dest') : [],
318 for (var i
= 0; i
< fwds
.length
; i
++)
319 value
.push(out
? fwds
[i
].getDestination() : fwds
[i
].getSource());
323 o
.write
= o
.remove = function(section_id
, formvalue
) {
324 var out
= (this.option
== 'out'),
325 zone
= this.lookupZone(uci
.get('firewall', section_id
, 'name')),
326 fwds
= zone
? zone
.getForwardingsBy(out
? 'src' : 'dest') : [];
328 if (formvalue
== null)
331 if (Array
.isArray(formvalue
)) {
332 for (var i
= 0; i
< fwds
.length
; i
++) {
333 var cmp
= out
? fwds
[i
].getDestination() : fwds
[i
].getSource();
334 if (!formvalue
.filter(function(d
) { return d
== cmp
}).length
)
335 zone
.deleteForwarding(fwds
[i
]);
338 for (var i
= 0; i
< formvalue
.length
; i
++)
340 zone
.addForwardingTo(formvalue
[i
]);
342 zone
.addForwardingFrom(formvalue
[i
]);
346 inp
= o
= s
.taboption('general', widgets
.ZoneSelect
, 'in', _('Allow forward from <em>source zones</em>:'));
350 o
.write
= o
.remove
= out
.write
;
351 o
.filter
= out
.filter
;
352 o
.cfgvalue
= out
.cfgvalue
;