Translated using Weblate (Japanese)
[oweals/luci.git] / applications / luci-app-firewall / htdocs / luci-static / resources / view / firewall / zones.js
1 'use strict';
2 'require view';
3 'require rpc';
4 'require uci';
5 'require form';
6 'require network';
7 'require firewall';
8 'require tools.firewall as fwtool';
9 'require tools.widgets as widgets';
10
11 return view.extend({
12         callConntrackHelpers: rpc.declare({
13                 object: 'luci',
14                 method: 'getConntrackHelpers',
15                 expect: { result: [] }
16         }),
17
18         load: function() {
19                 return Promise.all([
20                         this.callConntrackHelpers(),
21                         firewall.getDefaults()
22                 ]);
23         },
24
25         render: function(data) {
26                 if (fwtool.checkLegacySNAT())
27                         return fwtool.renderMigration();
28                 else
29                         return this.renderZones(data);
30         },
31
32         renderZones: function(data) {
33                 var ctHelpers = data[0],
34                     fwDefaults = data[1],
35                     m, s, o, inp, out;
36
37                 m = new form.Map('firewall', _('Firewall - Zone Settings'),
38                         _('The firewall creates zones over your network interfaces to control network traffic flow.'));
39
40                 s = m.section(form.TypedSection, 'defaults', _('General Settings'));
41                 s.anonymous = true;
42                 s.addremove = false;
43
44                 o = s.option(form.Flag, 'syn_flood', _('Enable SYN-flood protection'));
45                 o = s.option(form.Flag, 'drop_invalid', _('Drop invalid packets'));
46
47                 var p = [
48                         s.option(form.ListValue, 'input', _('Input')),
49                         s.option(form.ListValue, 'output', _('Output')),
50                         s.option(form.ListValue, 'forward', _('Forward'))
51                 ];
52
53                 for (var i = 0; i < p.length; i++) {
54                         p[i].value('REJECT', _('reject'));
55                         p[i].value('DROP', _('drop'));
56                         p[i].value('ACCEPT', _('accept'));
57                 }
58
59                 /* Netfilter flow offload support */
60
61                 if (L.hasSystemFeature('offloading')) {
62                         s = m.section(form.TypedSection, 'defaults', _('Routing/NAT Offloading'),
63                                 _('Experimental feature. Not fully compatible with QoS/SQM.'));
64
65                         s.anonymous = true;
66                         s.addremove = false;
67
68                         o = s.option(form.Flag, 'flow_offloading',
69                                 _('Software flow offloading'),
70                                 _('Software based offloading for routing/NAT'));
71                         o.optional = true;
72
73                         o = s.option(form.Flag, 'flow_offloading_hw',
74                                 _('Hardware flow offloading'),
75                                 _('Requires hardware NAT support. Implemented at least for mt7621'));
76                         o.optional = true;
77                         o.depends('flow_offloading', '1');
78                 }
79
80
81                 s = m.section(form.GridSection, 'zone', _('Zones'));
82                 s.addremove = true;
83                 s.anonymous = true;
84                 s.sortable  = true;
85
86                 s.handleRemove = function(section_id, ev) {
87                         return firewall.deleteZone(section_id).then(L.bind(function() {
88                                 return this.super('handleRemove', [section_id, ev]);
89                         }, this));
90                 };
91
92                 s.tab('general', _('General Settings'));
93                 s.tab('advanced', _('Advanced Settings'));
94                 s.tab('conntrack', _('Conntrack Settings'));
95                 s.tab('extra', _('Extra iptables arguments'));
96
97                 o = s.taboption('general', form.DummyValue, '_generalinfo');
98                 o.rawhtml = true;
99                 o.modalonly = true;
100                 o.cfgvalue = function(section_id) {
101                         var name = uci.get('firewall', section_id, 'name');
102                         if (name == null)
103                                 name = _("this new zone");
104                         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.')
105                                 .replace(/%s/g, name).replace(/%q/g, '"' + name + '"');
106                 };
107
108                 o = s.taboption('general', form.Value, 'name', _('Name'));
109                 o.placeholder = _('Unnamed zone');
110                 o.modalonly = true;
111                 o.rmempty = false;
112                 o.datatype = 'and(uciname,maxlength(11))';
113                 o.write = function(section_id, formvalue) {
114                         var cfgvalue = this.cfgvalue(section_id);
115
116                         if (cfgvalue == null || cfgvalue == '')
117                                 return uci.set('firewall', section_id, 'name', formvalue);
118                         else if (cfgvalue != formvalue)
119                                 return firewall.renameZone(cfgvalue, formvalue);
120                 };
121
122                 o = s.option(widgets.ZoneForwards, '_info', _('Zone ⇒ Forwardings'));
123                 o.editable = true;
124                 o.modalonly = false;
125                 o.cfgvalue = function(section_id) {
126                         return uci.get('firewall', section_id, 'name');
127                 };
128
129                 var p = [
130                         s.taboption('general', form.ListValue, 'input', _('Input')),
131                         s.taboption('general', form.ListValue, 'output', _('Output')),
132                         s.taboption('general', form.ListValue, 'forward', _('Forward'))
133                 ];
134
135                 for (var i = 0; i < p.length; i++) {
136                         p[i].value('REJECT', _('reject'));
137                         p[i].value('DROP', _('drop'));
138                         p[i].value('ACCEPT', _('accept'));
139                         p[i].editable = true;
140                 }
141
142                 p[0].default = fwDefaults.getInput();
143                 p[1].default = fwDefaults.getOutput();
144                 p[2].default = fwDefaults.getForward();
145
146                 o = s.taboption('general', form.Flag, 'masq', _('Masquerading'));
147                 o.editable = true;
148
149                 o = s.taboption('general', form.Flag, 'mtu_fix', _('MSS clamping'));
150                 o.modalonly = true;
151
152                 o = s.taboption('general', widgets.NetworkSelect, 'network', _('Covered networks'));
153                 o.modalonly = true;
154                 o.multiple = true;
155                 o.cfgvalue = function(section_id) {
156                         return uci.get('firewall', section_id, 'network');
157                 };
158                 o.write = function(section_id, formvalue) {
159                         var name = uci.get('firewall', section_id, 'name'),
160                             cfgvalue = this.cfgvalue(section_id);
161
162                         if (typeof(cfgvalue) == 'string' && Array.isArray(formvalue) && (cfgvalue == formvalue.join(' ')))
163                                 return;
164
165                         var tasks = [ firewall.getZone(name) ];
166
167                         if (Array.isArray(formvalue))
168                                 for (var i = 0; i < formvalue.length; i++) {
169                                         var netname = formvalue[i];
170                                         tasks.push(network.getNetwork(netname).then(function(net) {
171                                                 return net || network.addNetwork(netname, { 'proto': 'none' });
172                                         }));
173                                 }
174
175                         return Promise.all(tasks).then(function(zone_networks) {
176                                 if (zone_networks[0])
177                                         for (var i = 1; i < zone_networks.length; i++)
178                                                 zone_networks[0].addNetwork(zone_networks[i].getName());
179                         });
180                 };
181
182                 o = s.taboption('advanced', form.DummyValue, '_advancedinfo');
183                 o.rawhtml = true;
184                 o.modalonly = true;
185                 o.cfgvalue = function(section_id) {
186                         var name = uci.get('firewall', section_id, 'name');
187                         if (name == null)
188                                 name = _("this new zone");
189                         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.')
190                                 .format(name);
191                 };
192
193                 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.'));
194                 o.modalonly = true;
195                 o.noaliases = true;
196                 o.multiple = true;
197
198                 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.'));
199                 o.datatype = 'neg(cidr)';
200                 o.modalonly = true;
201                 o.multiple = true;
202
203                 o = s.taboption('advanced', form.ListValue, 'family', _('Restrict to address family'));
204                 o.value('', _('IPv4 and IPv6'));
205                 o.value('ipv4', _('IPv4 only'));
206                 o.value('ipv6', _('IPv6 only'));
207                 o.modalonly = true;
208
209                 o = s.taboption('advanced', form.DynamicList, 'masq_src', _('Restrict Masquerading to given source subnets'));
210                 o.depends('family', '');
211                 o.depends('family', 'ipv4');
212                 o.datatype = 'list(neg(or(uciname,hostname,ipmask4)))';
213                 o.placeholder = '0.0.0.0/0';
214                 o.modalonly = true;
215
216                 o = s.taboption('advanced', form.DynamicList, 'masq_dest', _('Restrict Masquerading to given destination subnets'));
217                 o.depends('family', '');
218                 o.depends('family', 'ipv4');
219                 o.datatype = 'list(neg(or(uciname,hostname,ipmask4)))';
220                 o.placeholder = '0.0.0.0/0';
221                 o.modalonly = true;
222
223                 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.'));
224                 o.modalonly = true;
225
226                 o = s.taboption('conntrack', form.Flag, 'auto_helper', _('Automatic helper assignment'), _('Automatically assign conntrack helpers based on traffic protocol and port'));
227                 o.default = o.enabled;
228                 o.modalonly = true;
229
230                 o = s.taboption('conntrack', form.MultiValue, 'helper', _('Conntrack helpers'), _('Explicitly choses allowed connection tracking helpers for zone traffic'));
231                 o.depends('auto_helper', '0');
232                 o.modalonly = true;
233                 for (var i = 0; i < ctHelpers.length; i++)
234                         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
236                 o = s.taboption('advanced', form.Flag, 'log', _('Enable logging on this zone'));
237                 o.modalonly = true;
238
239                 o = s.taboption('advanced', form.Value, 'log_limit', _('Limit log messages'));
240                 o.depends('log', '1');
241                 o.placeholder = '10/minute';
242                 o.modalonly = true;
243
244                 o = s.taboption('extra', form.DummyValue, '_extrainfo');
245                 o.rawhtml = true;
246                 o.modalonly = true;
247                 o.cfgvalue = function(section_id) {
248                         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.');
249                 };
250
251                 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.modalonly = true;
253                 o.cfgvalue = function(section_id) {
254                         return uci.get('firewall', section_id, 'extra_src') || uci.get('firewall', section_id, 'extra');
255                 };
256                 o.write = function(section_id, value) {
257                         uci.unset('firewall', section_id, 'extra');
258                         uci.set('firewall', section_id, 'extra_src', value);
259                 };
260
261                 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.modalonly = true;
263                 o.cfgvalue = function(section_id) {
264                         return uci.get('firewall', section_id, 'extra_dest') || uci.get('firewall', section_id, 'extra_src') || uci.get('firewall', section_id, 'extra');
265                 };
266                 o.write = function(section_id, value) {
267                         uci.unset('firewall', section_id, 'extra');
268                         uci.set('firewall', section_id, 'extra_dest', value);
269                 };
270
271                 o = s.taboption('general', form.DummyValue, '_forwardinfo');
272                 o.rawhtml = true;
273                 o.modalonly = true;
274                 o.cfgvalue = function(section_id) {
275                         var name = uci.get('firewall', section_id, 'name');
276                         if (name == null)
277                                 name = _("this new zone");
278                         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.')
279                                 .format(name);
280                 };
281
282                 out = o = s.taboption('general', widgets.ZoneSelect, 'out', _('Allow forward to <em>destination zones</em>:'));
283                 o.nocreate = true;
284                 o.multiple = true;
285                 o.modalonly = true;
286                 o.filter = function(section_id, value) {
287                         return (uci.get('firewall', section_id, 'name') != value);
288                 };
289                 o.cfgvalue = function(section_id) {
290                         var out = (this.option == 'out'),
291                             zone = this.lookupZone(uci.get('firewall', section_id, 'name')),
292                             fwds = zone ? zone.getForwardingsBy(out ? 'src' : 'dest') : [],
293                             value = [];
294
295                         for (var i = 0; i < fwds.length; i++)
296                                 value.push(out ? fwds[i].getDestination() : fwds[i].getSource());
297
298                         return value;
299                 };
300                 o.write = o.remove = function(section_id, formvalue) {
301                         var out = (this.option == 'out'),
302                             zone = this.lookupZone(uci.get('firewall', section_id, 'name')),
303                             fwds = zone ? zone.getForwardingsBy(out ? 'src' : 'dest') : [];
304
305                         if (formvalue == null)
306                                 formvalue = [];
307
308                         if (Array.isArray(formvalue)) {
309                                 for (var i = 0; i < fwds.length; i++) {
310                                         var cmp = out ? fwds[i].getDestination() : fwds[i].getSource();
311                                         if (!formvalue.filter(function(d) { return d == cmp }).length)
312                                                 zone.deleteForwarding(fwds[i]);
313                                 }
314
315                                 for (var i = 0; i < formvalue.length; i++)
316                                         if (out)
317                                                 zone.addForwardingTo(formvalue[i]);
318                                         else
319                                                 zone.addForwardingFrom(formvalue[i]);
320                         }
321                 };
322
323                 inp = o = s.taboption('general', widgets.ZoneSelect, 'in', _('Allow forward from <em>source zones</em>:'));
324                 o.nocreate = true;
325                 o.multiple = true;
326                 o.modalonly = true;
327                 o.write = o.remove = out.write;
328                 o.filter = out.filter;
329                 o.cfgvalue = out.cfgvalue;
330
331                 return m.render();
332         }
333 });