1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter-feeds.git synced 2025-03-09 15:40:03 +00:00

Remove luci-app-firewall fork

This commit is contained in:
Ycarus (Yannick Chabanois) 2024-12-11 16:52:50 +01:00
parent bc68e4194a
commit ed5e82507c
39 changed files with 0 additions and 41294 deletions

View file

@ -1,17 +0,0 @@
#
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Firewall and Portforwarding application
LUCI_DEPENDS:=+@LINUX_5_4:firewall +@(LINUX_5_15||LINUX_6_1||LINUX_6_6||LINUX_6_7):uci-firewall
PKG_LICENSE:=Apache-2.0
#PKG_VERSION:=omr-202103
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,655 +0,0 @@
'use strict';
'require baseclass';
'require dom';
'require ui';
'require uci';
'require form';
'require network';
'require firewall';
'require tools.prng as random';
var protocols = [
'ip', 0, 'IP',
'hopopt', 0, 'HOPOPT',
'icmp', 1, 'ICMP',
'igmp', 2, 'IGMP',
'ggp', 3 , 'GGP',
'ipencap', 4, 'IP-ENCAP',
'st', 5, 'ST',
'tcp', 6, 'TCP',
'egp', 8, 'EGP',
'igp', 9, 'IGP',
'pup', 12, 'PUP',
'udp', 17, 'UDP',
'hmp', 20, 'HMP',
'xns-idp', 22, 'XNS-IDP',
'rdp', 27, 'RDP',
'iso-tp4', 29, 'ISO-TP4',
'dccp', 33, 'DCCP',
'xtp', 36, 'XTP',
'ddp', 37, 'DDP',
'idpr-cmtp', 38, 'IDPR-CMTP',
'ipv6', 41, 'IPv6',
'ipv6-route', 43, 'IPv6-Route',
'ipv6-frag', 44, 'IPv6-Frag',
'idrp', 45, 'IDRP',
'rsvp', 46, 'RSVP',
'gre', 47, 'GRE',
'esp', 50, 'IPSEC-ESP',
'ah', 51, 'IPSEC-AH',
'skip', 57, 'SKIP',
'icmpv6', 58, 'IPv6-ICMP',
'ipv6-icmp', 58, 'IPv6-ICMP',
'ipv6-nonxt', 59, 'IPv6-NoNxt',
'ipv6-opts', 60, 'IPv6-Opts',
'rspf', 73, 'RSPF',
'rspf', 73, 'CPHB',
'vmtp', 81, 'VMTP',
'eigrp', 88, 'EIGRP',
'ospf', 89, 'OSPFIGP',
'ax.25', 93, 'AX.25',
'ipip', 94, 'IPIP',
'etherip', 97, 'ETHERIP',
'encap', 98, 'ENCAP',
'pim', 103, 'PIM',
'ipcomp', 108, 'IPCOMP',
'vrrp', 112, 'VRRP',
'l2tp', 115, 'L2TP',
'isis', 124, 'ISIS',
'sctp', 132, 'SCTP',
'fc', 133, 'FC',
'mh', 135, 'Mobility-Header',
'ipv6-mh', 135, 'Mobility-Header',
'mobility-header', 135, 'Mobility-Header',
'udplite', 136, 'UDPLite',
'mpls-in-ip', 137, 'MPLS-in-IP',
'manet', 138, 'MANET',
'hip', 139, 'HIP',
'shim6', 140, 'Shim6',
'wesp', 141, 'WESP',
'rohc', 142, 'ROHC',
];
function lookupProto(x) {
if (x == null || x === '')
return null;
var s = String(x).toLowerCase();
for (var i = 0; i < protocols.length; i += 3)
if (s == protocols[i] || s == protocols[i+1])
return [ protocols[i+1], protocols[i+2], protocols[i] ];
return [ -1, x, x ];
}
return baseclass.extend({
fmt: function(fmtstr, args, values) {
var repl = [],
wrap = false,
tokens = [];
if (values == null) {
values = [];
wrap = true;
}
var get = function(args, key) {
var names = key.trim().split(/\./),
obj = args,
ctx = obj;
for (var i = 0; i < names.length; i++) {
if (!L.isObject(obj))
return null;
ctx = obj;
obj = obj[names[i]];
}
if (typeof(obj) == 'function')
return obj.call(ctx);
return obj;
};
var isset = function(val) {
if (L.isObject(val) && !dom.elem(val)) {
for (var k in val)
if (val.hasOwnProperty(k))
return true;
return false;
}
else if (Array.isArray(val)) {
return (val.length > 0);
}
else {
return (val !== null && val !== undefined && val !== '' && val !== false);
}
};
var parse = function(tokens, text) {
if (dom.elem(text)) {
tokens.push('<span data-fmt-placeholder="%d"></span>'.format(values.length));
values.push(text);
}
else {
tokens.push(String(text).replace(/\\(.)/g, '$1'));
}
};
for (var i = 0, last = 0; i <= fmtstr.length; i++) {
if (fmtstr.charAt(i) == '%' && fmtstr.charAt(i + 1) == '{') {
if (i > last)
parse(tokens, fmtstr.substring(last, i));
var j = i + 1, nest = 0;
var subexpr = [];
for (var off = j + 1, esc = false; j <= fmtstr.length; j++) {
var ch = fmtstr.charAt(j);
if (esc) {
esc = false;
}
else if (ch == '\\') {
esc = true;
}
else if (ch == '{') {
nest++;
}
else if (ch == '}') {
if (--nest == 0) {
subexpr.push(fmtstr.substring(off, j));
break;
}
}
else if (ch == '?' || ch == ':' || ch == '#') {
if (nest == 1) {
subexpr.push(fmtstr.substring(off, j));
subexpr.push(ch);
off = j + 1;
}
}
}
var varname = subexpr[0].trim(),
op1 = (subexpr[1] != null) ? subexpr[1] : '?',
if_set = (subexpr[2] != null && subexpr[2] != '') ? subexpr[2] : '%{' + varname + '}',
op2 = (subexpr[3] != null) ? subexpr[3] : ':',
if_unset = (subexpr[4] != null) ? subexpr[4] : '';
/* Invalid expression */
if (nest != 0 || subexpr.length > 5 || varname == '') {
return fmtstr;
}
/* enumeration */
else if (op1 == '#' && subexpr.length == 3) {
var items = L.toArray(get(args, varname));
for (var k = 0; k < items.length; k++) {
tokens.push.apply(tokens, this.fmt(if_set, Object.assign({}, args, {
first: k == 0,
next: k > 0,
last: (k + 1) == items.length,
item: items[k]
}), values));
}
}
/* ternary expression */
else if (op1 == '?' && op2 == ':' && (subexpr.length == 1 || subexpr.length == 3 || subexpr.length == 5)) {
var val = get(args, varname);
if (subexpr.length == 1)
parse(tokens, isset(val) ? val : '');
else if (isset(val))
tokens.push.apply(tokens, this.fmt(if_set, args, values));
else
tokens.push.apply(tokens, this.fmt(if_unset, args, values));
}
/* unrecognized command */
else {
return fmtstr;
}
last = j + 1;
i = j;
}
else if (i >= fmtstr.length) {
if (i > last)
parse(tokens, fmtstr.substring(last, i));
}
}
if (wrap) {
var node = E('span', {}, tokens.join('')),
repl = node.querySelectorAll('span[data-fmt-placeholder]');
for (var i = 0; i < repl.length; i++)
repl[i].parentNode.replaceChild(values[repl[i].getAttribute('data-fmt-placeholder')], repl[i]);
return node;
}
else {
return tokens;
}
},
map_invert: function(v, fn) {
return L.toArray(v).map(function(v) {
v = String(v);
if (fn != null && typeof(v[fn]) == 'function')
v = v[fn].call(v);
return {
ival: v,
inv: v.charAt(0) == '!',
val: v.replace(/^!\s*/, '')
};
});
},
lookupProto: lookupProto,
addDSCPOption: function(s, is_target) {
var o = s.taboption(is_target ? 'general' : 'advanced', form.Value, is_target ? 'set_dscp' : 'dscp',
is_target ? _('DSCP mark') : _('Match DSCP'),
is_target ? _('Apply the given DSCP class or value to established connections.') : _('Matches traffic carrying the specified DSCP marking.'));
o.modalonly = true;
o.rmempty = !is_target;
o.placeholder = _('any');
if (is_target)
o.depends('target', 'DSCP');
o.value('CS0');
o.value('CS1');
o.value('CS2');
o.value('CS3');
o.value('CS4');
o.value('CS5');
o.value('CS6');
o.value('CS7');
o.value('BE');
o.value('AF11');
o.value('AF12');
o.value('AF13');
o.value('AF21');
o.value('AF22');
o.value('AF23');
o.value('AF31');
o.value('AF32');
o.value('AF33');
o.value('AF41');
o.value('AF42');
o.value('AF43');
o.value('EF');
o.validate = function(section_id, value) {
if (value == '')
return is_target ? _('DSCP mark required') : true;
if (!is_target)
value = String(value).replace(/^!\s*/, '');
var m = value.match(/^(?:CS[0-7]|BE|AF[1234][123]|EF|(0x[0-9a-f]{1,2}|[0-9]{1,2}))$/);
if (!m || (m[1] != null && +m[1] > 0x3f))
return _('Invalid DSCP mark');
return true;
};
return o;
},
addMarkOption: function(s, is_target) {
var o = s.taboption(is_target ? 'general' : 'advanced', form.Value,
(is_target > 1) ? 'set_xmark' : (is_target ? 'set_mark' : 'mark'),
(is_target > 1) ? _('XOR mark') : (is_target ? _('Set mark') : _('Match mark')),
(is_target > 1) ? _('Apply a bitwise XOR of the given value and the existing mark value on established connections. Format is value[/mask]. If a mask is specified then those bits set in the mask are zeroed out.') :
(is_target ? _('Set the given mark value on established connections. Format is value[/mask]. If a mask is specified then only those bits set in the mask are modified.') :
_('Matches a specific firewall mark or a range of different marks.')));
o.modalonly = true;
o.rmempty = true;
if (is_target > 1)
o.depends('target', 'MARK_XOR');
else if (is_target)
o.depends('target', 'MARK_SET');
o.validate = function(section_id, value) {
if (value == '')
return is_target ? _('Valid firewall mark required') : true;
if (!is_target)
value = String(value).replace(/^!\s*/, '');
var m = value.match(/^(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
if (!m || +m[1] > 0xffffffff || (m[2] != null && +m[2] > 0xffffffff))
return _('Expecting: %s').format(_('valid firewall mark'));
return true;
};
return o;
},
addLimitOption: function(s) {
var o = s.taboption('advanced', form.Value, 'limit',
_('Limit matching'),
_('Limits traffic matching to the specified rate.'));
o.modalonly = true;
o.rmempty = true;
o.placeholder = _('unlimited');
o.value('10/second');
o.value('60/minute');
o.value('3/hour');
o.value('500/day');
o.validate = function(section_id, value) {
if (value == '')
return true;
var m = String(value).toLowerCase().match(/^(?:0x[0-9a-f]{1,8}|[0-9]{1,10})\/([a-z]+)$/),
u = ['second', 'minute', 'hour', 'day'],
i = 0;
if (m)
for (i = 0; i < u.length; i++)
if (u[i].indexOf(m[1]) == 0)
break;
if (!m || i >= u.length)
return _('Invalid limit value');
return true;
};
return o;
},
addLimitBurstOption: function(s) {
var o = s.taboption('advanced', form.Value, 'limit_burst',
_('Limit burst'),
_('Maximum initial number of packets to match: this number gets recharged by one every time the limit specified above is not reached, up to this number.'));
o.modalonly = true;
o.rmempty = true;
o.placeholder = '5';
o.datatype = 'uinteger';
o.depends({ limit: null, '!reverse': true });
return o;
},
transformHostHints: function(family, hosts) {
var choice_values = [], choice_labels = {};
if (!family || family == 'ipv4') {
L.sortedKeys(hosts, 'ipv4', 'addr').forEach(function(mac) {
var val = hosts[mac].ipv4,
txt = hosts[mac].name || mac;
choice_values.push(val);
choice_labels[val] = E([], [ val, ' (', E('strong', {}, [txt]), ')' ]);
});
}
if (!family || family == 'ipv6') {
L.sortedKeys(hosts, 'ipv6', 'addr').forEach(function(mac) {
var val = hosts[mac].ipv6,
txt = hosts[mac].name || mac;
choice_values.push(val);
choice_labels[val] = E([], [ val, ' (', E('strong', {}, [txt]), ')' ]);
});
}
return [choice_values, choice_labels];
},
updateHostHints: function(map, section_id, option, family, hosts) {
var opt = map.lookupOption(option, section_id)[0].getUIElement(section_id),
choices = this.transformHostHints(family, hosts);
opt.clearChoices();
opt.addChoices(choices[0], choices[1]);
},
addIPOption: function(s, tab, name, label, description, family, hosts, multiple) {
var o = s.taboption(tab, multiple ? form.DynamicList : form.Value, name, label, description);
o.modalonly = true;
o.datatype = 'list(neg(ipmask))';
o.placeholder = multiple ? _('-- add IP --') : _('any');
if (family != null) {
var choices = this.transformHostHints(family, hosts);
for (var i = 0; i < choices[0].length; i++)
o.value(choices[0][i], choices[1][choices[0][i]]);
}
/* force combobox rendering */
o.transformChoices = function() {
return this.super('transformChoices', []) || {};
};
return o;
},
addLocalIPOption: function(s, tab, name, label, description, devices) {
var o = s.taboption(tab, form.Value, name, label, description);
o.modalonly = true;
o.datatype = 'ip4addr("nomask")';
o.placeholder = _('any');
L.sortedKeys(devices, 'name').forEach(function(dev) {
var ip4addrs = devices[dev].ipaddrs;
if (!L.isObject(devices[dev].flags) || !Array.isArray(ip4addrs) || devices[dev].flags.loopback)
return;
for (var i = 0; i < ip4addrs.length; i++) {
if (!L.isObject(ip4addrs[i]) || !ip4addrs[i].address)
continue;
o.value(ip4addrs[i].address, E([], [
ip4addrs[i].address, ' (', E('strong', {}, [dev]), ')'
]));
}
});
return o;
},
addMACOption: function(s, tab, name, label, description, hosts) {
var o = s.taboption(tab, form.DynamicList, name, label, description);
o.modalonly = true;
o.datatype = 'list(macaddr)';
o.placeholder = _('-- add MAC --');
L.sortedKeys(hosts).forEach(function(mac) {
o.value(mac, E([], [ mac, ' (', E('strong', {}, [
hosts[mac].name || hosts[mac].ipv4 || hosts[mac].ipv6 || '?'
]), ')' ]));
});
return o;
},
CBIProtocolSelect: form.MultiValue.extend({
__name__: 'CBI.ProtocolSelect',
addChoice: function(value, label) {
if (!Array.isArray(this.keylist) || this.keylist.indexOf(value) == -1)
this.value(value, label);
},
load: function(section_id) {
var cfgvalue = L.toArray(this.super('load', [section_id]) || this.default).sort();
['all', 'tcp', 'udp', 'icmp'].concat(cfgvalue).forEach(L.bind(function(value) {
switch (value) {
case 'all':
case 'any':
case '*':
this.addChoice('all', _('Any'));
break;
case 'tcpudp':
this.addChoice('tcp', 'TCP');
this.addChoice('udp', 'UDP');
break;
default:
var m = value.match(/^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/),
p = lookupProto(m ? +m[1] : value);
this.addChoice(p[2], p[1]);
break;
}
}, this));
return cfgvalue;
},
renderWidget: function(section_id, option_index, cfgvalue) {
var value = (cfgvalue != null) ? cfgvalue : this.default,
choices = this.transformChoices();
var widget = new ui.Dropdown(L.toArray(value), choices, {
id: this.cbid(section_id),
sort: this.keylist,
multiple: true,
optional: false,
display_items: 10,
dropdown_items: -1,
create: true,
validate: function(value) {
var v = L.toArray(value);
for (var i = 0; i < v.length; i++) {
if (v[i] == 'all')
continue;
var m = v[i].match(/^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/);
if (m ? (+m[1] > 255) : (lookupProto(v[i])[0] == -1))
return _('Unrecognized protocol');
}
return true;
}
});
widget.createChoiceElement = function(sb, value) {
var m = value.match(/^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/),
p = lookupProto(lookupProto(m ? +m[1] : value)[0]);
return ui.Dropdown.prototype.createChoiceElement.call(this, sb, p[2], p[1]);
};
widget.createItems = function(sb, value) {
var values = L.toArray(value).map(function(value) {
var m = value.match(/^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/),
p = lookupProto(m ? +m[1] : value);
return (p[0] > -1) ? p[2] : value;
});
return ui.Dropdown.prototype.createItems.call(this, sb, values.join(' '));
};
widget.toggleItem = function(sb, li) {
var value = li.getAttribute('data-value'),
toggleFn = ui.Dropdown.prototype.toggleItem;
toggleFn.call(this, sb, li);
if (value == 'all') {
var items = li.parentNode.querySelectorAll('li[data-value]');
for (var j = 0; j < items.length; j++)
if (items[j] !== li)
toggleFn.call(this, sb, items[j], false);
}
else {
toggleFn.call(this, sb, li.parentNode.querySelector('li[data-value="all"]'), false);
}
};
return widget.render();
}
}),
checkLegacySNAT: function() {
var redirects = uci.sections('firewall', 'redirect');
for (var i = 0; i < redirects.length; i++)
if ((redirects[i]['target'] || '').toLowerCase() == 'snat')
return true;
return false;
},
handleMigration: function(ev) {
var redirects = uci.sections('firewall', 'redirect'),
tasks = [];
var mapping = {
dest: 'src',
reflection: null,
reflection_src: null,
src_dip: 'snat_ip',
src_dport: 'snat_port',
src: null
};
for (var i = 0; i < redirects.length; i++) {
if ((redirects[i]['target'] || '').toLowerCase() != 'snat')
continue;
var sid = uci.add('firewall', 'nat');
for (var opt in redirects[i]) {
if (opt.charAt(0) == '.')
continue;
if (mapping[opt] === null)
continue;
uci.set('firewall', sid, mapping[opt] || opt, redirects[i][opt]);
}
uci.remove('firewall', redirects[i]['.name']);
}
return uci.save()
.then(L.bind(ui.changes.init, ui.changes))
.then(L.bind(ui.changes.apply, ui.changes));
},
renderMigration: function() {
ui.showModal(_('Firewall configuration migration'), [
E('p', _('The existing firewall configuration needs to be changed for LuCI to function properly.')),
E('p', _('Upon pressing "Continue", "redirect" sections with target "SNAT" will be converted to "nat" sections and the firewall will be restarted to apply the updated configuration.')),
E('div', { 'class': 'right' },
E('button', {
'class': 'btn cbi-button-action important',
'click': ui.createHandlerFn(this, 'handleMigration')
}, _('Continue')))
]);
},
});

View file

@ -1,33 +0,0 @@
'use strict';
'require view';
'require fs';
'require ui';
return view.extend({
load: function() {
return L.resolveDefault(fs.read('/etc/firewall.user'), '');
},
handleSave: function(ev) {
var value = (document.querySelector('textarea').value || '').trim().replace(/\r\n/g, '\n') + '\n';
return fs.write('/etc/firewall.user', value).then(function(rc) {
document.querySelector('textarea').value = value;
ui.addNotification(null, E('p', _('Contents have been saved.')), 'info');
fs.exec('/etc/init.d/firewall', ['restart']);
}).catch(function(e) {
ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message)));
});
},
render: function(fwuser) {
return E([
E('h2', _('Firewall - Custom Rules')),
E('p', {}, _('Custom rules allow you to execute arbitrary iptables commands which are not otherwise covered by the firewall framework. The commands are executed after each firewall restart, right after the default ruleset has been loaded.')),
E('p', {}, E('textarea', { 'style': 'width:100%', 'rows': 10 }, [ fwuser != null ? fwuser : '' ]))
]);
},
handleSaveApply: null,
handleReset: null
});

View file

@ -1,297 +0,0 @@
'use strict';
'require view';
'require ui';
'require rpc';
'require uci';
'require form';
'require firewall as fwmodel';
'require tools.firewall as fwtool';
'require tools.widgets as widgets';
function rule_proto_txt(s, ctHelpers) {
var proto = L.toArray(uci.get('firewall', s, 'proto')).filter(function(p) {
return (p != '*' && p != 'any' && p != 'all');
}).map(function(p) {
var pr = fwtool.lookupProto(p);
return {
num: pr[0],
name: pr[1],
types: (pr[0] == 1 || pr[0] == 58) ? L.toArray(uci.get('firewall', s, 'icmp_type')) : null
};
});
m = String(uci.get('firewall', s, 'helper') || '').match(/^(!\s*)?(\S+)$/);
var h = m ? {
val: m[0].toUpperCase(),
inv: m[1],
name: (ctHelpers.filter(function(ctH) { return ctH.name.toLowerCase() == m[2].toLowerCase() })[0] || {}).description
} : null;
m = String(uci.get('firewall', s, 'mark')).match(/^(!\s*)?(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
var f = m ? {
val: m[0].toUpperCase().replace(/X/g, 'x'),
inv: m[1],
num: '0x%02X'.format(+m[2]),
mask: m[3] ? '0x%02X'.format(+m[3]) : null
} : null;
return fwtool.fmt(_('Incoming IPv4%{proto?, protocol %{proto#%{next?, }%{item.types?<var class="cbi-tooltip-container">%{item.name}<span class="cbi-tooltip">ICMP with types %{item.types#%{next?, }<var>%{item}</var>}</span></var>:<var>%{item.name}</var>}}}%{mark?, mark <var%{mark.inv? data-tooltip="Match fwmarks except %{mark.num}%{mark.mask? with mask %{mark.mask}}.":%{mark.mask? data-tooltip="Mask fwmark value with %{mark.mask} before compare."}}>%{mark.val}</var>}%{helper?, helper %{helper.inv?<var data-tooltip="Match any helper except &quot;%{helper.name}&quot;">%{helper.val}</var>:<var data-tooltip="%{helper.name}">%{helper.val}</var>}}'), {
proto: proto,
helper: h,
mark: f
});
}
function rule_src_txt(s, hosts) {
var z = uci.get('firewall', s, 'src');
return fwtool.fmt(_('From %{src}%{src_ip?, IP %{src_ip#%{next?, }<var%{item.inv? data-tooltip="Match IP addresses except %{item.val}."}>%{item.ival}</var>}}%{src_port?, port %{src_port#%{next?, }<var%{item.inv? data-tooltip="Match ports except %{item.val}."}>%{item.ival}</var>}}%{src_mac?, MAC %{src_mac#%{next?, }<var%{item.inv? data-tooltip="Match MACs except %{item.val}%{item.hint.name? a.k.a. %{item.hint.name}}.":%{item.hint.name? data-tooltip="%{item.hint.name}"}}>%{item.ival}</var>}}'), {
src: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName((z && z != '*') ? z : null) }, [(z == '*') ? E('em', _('any zone')) : (z || E('em', _('this device')))]),
src_ip: fwtool.map_invert(uci.get('firewall', s, 'src_ip'), 'toLowerCase'),
src_mac: fwtool.map_invert(uci.get('firewall', s, 'src_mac'), 'toUpperCase').map(function(v) { return Object.assign(v, { hint: hosts[v.val] }) }),
src_port: fwtool.map_invert(uci.get('firewall', s, 'src_port'))
});
}
function rule_dest_txt(s) {
return fwtool.fmt(_('To %{dest}%{dest_ip?, IP %{dest_ip#%{next?, }<var%{item.inv? data-tooltip="Match IP addresses except %{item.val}."}>%{item.ival}</var>}}%{dest_port?, port %{dest_port#%{next?, }<var%{item.inv? data-tooltip="Match ports except %{item.val}."}>%{item.ival}</var>}}'), {
dest: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName(null) }, [E('em', _('this device'))]),
dest_ip: fwtool.map_invert(uci.get('firewall', s, 'src_dip'), 'toLowerCase'),
dest_port: fwtool.map_invert(uci.get('firewall', s, 'src_dport'))
});
}
function rule_limit_txt(s) {
var m = String(uci.get('firewall', s, 'limit')).match(/^(\d+)\/([smhd])\w*$/i),
l = m ? {
num: +m[1],
unit: ({ s: _('second'), m: _('minute'), h: _('hour'), d: _('day') })[m[2]],
burst: uci.get('firewall', s, 'limit_burst')
} : null;
if (!l)
return '';
return fwtool.fmt(_('Limit matching to <var>%{limit.num}</var> packets per <var>%{limit.unit}</var>%{limit.burst? burst <var>%{limit.burst}</var>}'), { limit: l });
}
function rule_target_txt(s) {
var z = uci.get('firewall', s, 'dest');
return fwtool.fmt(_('<var data-tooltip="DNAT">Forward</var> to %{dest}%{dest_ip? IP <var>%{dest_ip}</var>}%{dest_port? port <var>%{dest_port}</var>}'), {
dest: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName((z && z != '*') ? z : null) }, [(z == '*') ? E('em', _('any zone')) : (z || E('em', _('this device')))]),
dest_ip: (uci.get('firewall', s, 'dest_ip') || '').toLowerCase(),
dest_port: uci.get('firewall', s, 'dest_port')
});
}
return view.extend({
callHostHints: rpc.declare({
object: 'luci-rpc',
method: 'getHostHints',
expect: { '': {} }
}),
callConntrackHelpers: rpc.declare({
object: 'luci',
method: 'getConntrackHelpers',
expect: { result: [] }
}),
callNetworkDevices: rpc.declare({
object: 'luci-rpc',
method: 'getNetworkDevices',
expect: { '': {} }
}),
load: function() {
return Promise.all([
this.callHostHints(),
this.callConntrackHelpers(),
this.callNetworkDevices(),
uci.load('firewall')
]);
},
render: function(data) {
if (fwtool.checkLegacySNAT())
return fwtool.renderMigration();
else
return this.renderForwards(data);
},
renderForwards: function(data) {
var hosts = data[0],
ctHelpers = data[1],
devs = data[2],
m, s, o;
m = new form.Map('firewall', _('Firewall - Port Forwards'),
_('Port forwarding allows remote computers on the Internet to connect to a specific computer or service within the private LAN.'));
s = m.section(form.GridSection, 'redirect', _('Port Forwards'));
s.addremove = true;
s.anonymous = true;
s.sortable = true;
s.tab('general', _('General Settings'));
s.tab('advanced', _('Advanced Settings'));
s.filter = function(section_id) {
return (uci.get('firewall', section_id, 'target') != 'SNAT');
};
s.sectiontitle = function(section_id) {
return uci.get('firewall', section_id, 'name') || _('Unnamed forward');
};
s.handleAdd = function(ev) {
var config_name = this.uciconfig || this.map.config,
section_id = uci.add(config_name, this.sectiontype);
uci.set(config_name, section_id, 'target', 'DNAT');
this.addedSection = section_id;
this.renderMoreOptionsModal(section_id);
};
o = s.taboption('general', form.Value, 'name', _('Name'));
o.placeholder = _('Unnamed forward');
o.modalonly = true;
o = s.option(form.DummyValue, '_match', _('Match'));
o.modalonly = false;
o.textvalue = function(s) {
return E('small', [
rule_proto_txt(s, ctHelpers), E('br'),
rule_src_txt(s, hosts), E('br'),
rule_dest_txt(s), E('br'),
rule_limit_txt(s)
]);
};
o = s.option(form.ListValue, '_dest', _('Action'));
o.modalonly = false;
o.textvalue = function(s) {
return E('small', [
rule_target_txt(s)
]);
};
o = s.option(form.Flag, 'enabled', _('Enable'));
o.modalonly = false;
o.default = o.enabled;
o.editable = true;
o = s.taboption('general', fwtool.CBIProtocolSelect, 'proto', _('Protocol'));
o.modalonly = true;
o.default = 'tcp udp';
o = s.taboption('general', widgets.ZoneSelect, 'src', _('Source zone'));
o.modalonly = true;
o.rmempty = false;
o.nocreate = true;
o.default = 'wan';
o = fwtool.addMACOption(s, 'advanced', 'src_mac', _('Source MAC address'),
_('Only match incoming traffic from these MACs.'), hosts);
o.rmempty = true;
o.datatype = 'list(neg(macaddr))';
o = fwtool.addIPOption(s, 'advanced', 'src_ip', _('Source IP address'),
_('Only match incoming traffic from this IP or range.'), 'ipv4', hosts);
o.rmempty = true;
o.datatype = 'neg(ipmask4)';
o = s.taboption('advanced', form.Value, 'src_port', _('Source port'),
_('Only match incoming traffic originating from the given source port or port range on the client host'));
o.modalonly = true;
o.rmempty = true;
o.datatype = 'neg(portrange)';
o.placeholder = _('any');
o.depends({ proto: 'tcp', '!contains': true });
o.depends({ proto: 'udp', '!contains': true });
o = fwtool.addLocalIPOption(s, 'advanced', 'src_dip', _('External IP address'),
_('Only match incoming traffic directed at the given IP address.'), devs);
o.datatype = 'neg(ipmask4)';
o.rmempty = true;
o = s.taboption('general', form.Value, 'src_dport', _('External port'),
_('Match incoming traffic directed at the given destination port or port range on this host'));
o.modalonly = true;
o.rmempty = false;
o.datatype = 'neg(portrange)';
o.depends({ proto: 'tcp', '!contains': true });
o.depends({ proto: 'udp', '!contains': true });
o = s.taboption('general', widgets.ZoneSelect, 'dest', _('Internal zone'));
o.modalonly = true;
o.rmempty = true;
o.nocreate = true;
o.default = 'lan';
o = fwtool.addIPOption(s, 'general', 'dest_ip', _('Internal IP address'),
_('Redirect matched incoming traffic to the specified internal host'), 'ipv4', hosts);
o.rmempty = true;
o.datatype = 'ipmask4';
o = s.taboption('general', form.Value, 'dest_port', _('Internal port'),
_('Redirect matched incoming traffic to the given port on the internal host'));
o.modalonly = true;
o.rmempty = true;
o.placeholder = _('any');
o.datatype = 'portrange';
o.depends({ proto: 'tcp', '!contains': true });
o.depends({ proto: 'udp', '!contains': true });
o = s.taboption('advanced', form.Flag, 'reflection', _('Enable NAT Loopback'));
o.modalonly = true;
o.rmempty = true;
o.default = o.enabled;
o = s.taboption('advanced', form.ListValue, 'reflection_src', _('Loopback source IP'), _('Specifies whether to use the external or the internal IP address for reflected traffic.'));
o.modalonly = true;
o.depends('reflection', '1');
o.value('internal', _('Use internal IP address'));
o.value('external', _('Use external IP address'));
o.write = function(section_id, value) {
uci.set('firewall', section_id, 'reflection_src', (value != 'internal') ? value : null);
};
o = s.taboption('advanced', form.Value, 'helper', _('Match helper'), _('Match traffic using the specified connection tracking helper.'));
o.modalonly = true;
o.placeholder = _('any');
for (var i = 0; i < ctHelpers.length; i++)
o.value(ctHelpers[i].name, '%s (%s)'.format(ctHelpers[i].description, ctHelpers[i].name.toUpperCase()));
o.validate = function(section_id, value) {
if (value == '' || value == null)
return true;
value = value.replace(/^!\s*/, '');
for (var i = 0; i < ctHelpers.length; i++)
if (value == ctHelpers[i].name)
return true;
return _('Unknown or not installed conntrack helper "%s"').format(value);
};
fwtool.addMarkOption(s, false);
fwtool.addLimitOption(s);
fwtool.addLimitBurstOption(s);
o = s.taboption('advanced', form.Flag, 'v2ray', _('Use V2Ray/XRay'),
_('Forward a port (not a range) from server using V2Ray/XRay proxy (if enabled) instead of VPN'));
o.modalonly = true;
o.editable = true;
o.depends({ src: 'vpn', '!contains': true });
o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
_('Passes additional arguments to iptables. Use with care!'));
o.modalonly = true;
o.rmempty = true;
return m.render();
}
});

View file

@ -1,477 +0,0 @@
'use strict';
'require view';
'require ui';
'require rpc';
'require uci';
'require form';
'require firewall as fwmodel';
'require tools.firewall as fwtool';
'require tools.widgets as widgets';
function rule_proto_txt(s, ctHelpers) {
var f = (uci.get('firewall', s, 'family') || '').toLowerCase().replace(/^(?:any|\*)$/, '');
var proto = L.toArray(uci.get('firewall', s, 'proto')).filter(function(p) {
return (p != '*' && p != 'any' && p != 'all');
}).map(function(p) {
var pr = fwtool.lookupProto(p);
return {
num: pr[0],
name: pr[1],
types: (pr[0] == 1 || pr[0] == 58) ? L.toArray(uci.get('firewall', s, 'icmp_type')) : null
};
});
m = String(uci.get('firewall', s, 'helper') || '').match(/^(!\s*)?(\S+)$/);
var h = m ? {
val: m[0].toUpperCase(),
inv: m[1],
name: (ctHelpers.filter(function(ctH) { return ctH.name.toLowerCase() == m[2].toLowerCase() })[0] || {}).description
} : null;
m = String(uci.get('firewall', s, 'mark')).match(/^(!\s*)?(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
var w = m ? {
val: m[0].toUpperCase().replace(/X/g, 'x'),
inv: m[1],
num: '0x%02X'.format(+m[2]),
mask: m[3] ? '0x%02X'.format(+m[3]) : null
} : null;
m = String(uci.get('firewall', s, 'dscp')).match(/^(!\s*)?(?:(CS[0-7]|BE|AF[1234][123]|EF)|(0x[0-9a-f]{1,2}|[0-9]{1,2}))$/);
var d = m ? {
val: m[0],
inv: m[1],
name: m[2],
num: m[3] ? '0x%02X'.format(+m[3]) : null
} : null;
return fwtool.fmt(_('%{src?%{dest?Forwarded:Incoming}:Outgoing} %{ipv6?%{ipv4?<var>IPv4</var> and <var>IPv6</var>:<var>IPv6</var>}:<var>IPv4</var>}%{proto?, protocol %{proto#%{next?, }%{item.types?<var class="cbi-tooltip-container">%{item.name}<span class="cbi-tooltip">ICMP with types %{item.types#%{next?, }<var>%{item}</var>}</span></var>:<var>%{item.name}</var>}}}%{mark?, mark <var%{mark.inv? data-tooltip="Match fwmarks except %{mark.num}%{mark.mask? with mask %{mark.mask}}.":%{mark.mask? data-tooltip="Mask fwmark value with %{mark.mask} before compare."}}>%{mark.val}</var>}%{dscp?, DSCP %{dscp.inv?<var data-tooltip="Match DSCP classifications except %{dscp.num?:%{dscp.name}}">%{dscp.val}</var>:<var>%{dscp.val}</var>}}%{helper?, helper %{helper.inv?<var data-tooltip="Match any helper except &quot;%{helper.name}&quot;">%{helper.val}</var>:<var data-tooltip="%{helper.name}">%{helper.val}</var>}}'), {
ipv4: (!f || f == 'ipv4'),
ipv6: (!f || f == 'ipv6'),
src: uci.get('firewall', s, 'src'),
dest: uci.get('firewall', s, 'dest'),
proto: proto,
helper: h,
mark: w,
dscp: d
});
}
function rule_src_txt(s, hosts) {
var z = uci.get('firewall', s, 'src'),
d = (uci.get('firewall', s, 'direction') == 'in') ? uci.get('firewall', s, 'device') : null;
return fwtool.fmt(_('From %{src}%{src_device?, interface <var>%{src_device}</var>}%{src_ip?, IP %{src_ip#%{next?, }<var%{item.inv? data-tooltip="Match IP addresses except %{item.val}."}>%{item.ival}</var>}}%{src_port?, port %{src_port#%{next?, }<var%{item.inv? data-tooltip="Match ports except %{item.val}."}>%{item.ival}</var>}}%{src_mac?, MAC %{src_mac#%{next?, }<var%{item.inv? data-tooltip="Match MACs except %{item.val}%{item.hint.name? a.k.a. %{item.hint.name}}.":%{item.hint.name? data-tooltip="%{item.hint.name}"}}>%{item.ival}</var>}}'), {
src: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName((z && z != '*') ? z : null) }, [(z == '*') ? E('em', _('any zone')) : (z || E('em', _('this device')))]),
src_ip: fwtool.map_invert(uci.get('firewall', s, 'src_ip'), 'toLowerCase'),
src_mac: fwtool.map_invert(uci.get('firewall', s, 'src_mac'), 'toUpperCase').map(function(v) { return Object.assign(v, { hint: hosts[v.val] }) }),
src_port: fwtool.map_invert(uci.get('firewall', s, 'src_port')),
src_device: d
});
}
function rule_dest_txt(s) {
var z = uci.get('firewall', s, 'dest'),
d = (uci.get('firewall', s, 'direction') == 'out') ? uci.get('firewall', s, 'device') : null;
return fwtool.fmt(_('To %{dest}%{dest_device?, interface <var>%{dest_device}</var>}%{dest_ip?, IP %{dest_ip#%{next?, }<var%{item.inv? data-tooltip="Match IP addresses except %{item.val}."}>%{item.ival}</var>}}%{dest_port?, port %{dest_port#%{next?, }<var%{item.inv? data-tooltip="Match ports except %{item.val}."}>%{item.ival}</var>}}'), {
dest: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName((z && z != '*') ? z : null) }, [(z == '*') ? E('em', _('any zone')) : (z || E('em', _('this device')))]),
dest_ip: fwtool.map_invert(uci.get('firewall', s, 'dest_ip'), 'toLowerCase'),
dest_port: fwtool.map_invert(uci.get('firewall', s, 'dest_port')),
dest_device: d
});
}
function rule_limit_txt(s) {
var m = String(uci.get('firewall', s, 'limit')).match(/^(\d+)\/([smhd])\w*$/i),
l = m ? {
num: +m[1],
unit: ({ s: _('second'), m: _('minute'), h: _('hour'), d: _('day') })[m[2]],
burst: uci.get('firewall', s, 'limit_burst')
} : null;
if (!l)
return '';
return fwtool.fmt(_('Limit matching to <var>%{limit.num}</var> packets per <var>%{limit.unit}</var>%{limit.burst? burst <var>%{limit.burst}</var>}'), { limit: l });
}
function rule_target_txt(s, ctHelpers) {
var t = uci.get('firewall', s, 'target'),
h = (uci.get('firewall', s, 'set_helper') || '').toUpperCase(),
s = {
target: t,
src: uci.get('firewall', s, 'src'),
dest: uci.get('firewall', s, 'dest'),
set_helper: h,
set_mark: uci.get('firewall', s, 'set_mark'),
set_xmark: uci.get('firewall', s, 'set_xmark'),
set_dscp: uci.get('firewall', s, 'set_dscp'),
helper_name: (ctHelpers.filter(function(ctH) { return ctH.name.toUpperCase() == h })[0] || {}).description
};
switch (t) {
case 'DROP':
return fwtool.fmt(_('<var data-tooltip="DROP">Drop</var> %{src?%{dest?forward:input}:output}'), s);
case 'ACCEPT':
return fwtool.fmt(_('<var data-tooltip="ACCEPT">Accept</var> %{src?%{dest?forward:input}:output}'), s);
case 'REJECT':
return fwtool.fmt(_('<var data-tooltip="REJECT">Reject</var> %{src?%{dest?forward:input}:output}'), s);
case 'NOTRACK':
return fwtool.fmt(_('<var data-tooltip="NOTRACK">Do not track</var> %{src?%{dest?forward:input}:output}'), s);
case 'HELPER':
return fwtool.fmt(_('<var data-tooltip="HELPER">Assign conntrack</var> helper <var%{helper_name? data-tooltip="%{helper_name}"}>%{set_helper}</var>'), s);
case 'MARK':
return fwtool.fmt(_('<var data-tooltip="MARK">%{set_mark?Assign:XOR}</var> firewall mark <var>%{set_mark?:%{set_xmark}}</var>'), s);
case 'DSCP':
return fwtool.fmt(_('<var data-tooltip="DSCP">Assign DSCP</var> classification <var>%{set_dscp}</var>'), s);
default:
return t;
}
}
return view.extend({
callHostHints: rpc.declare({
object: 'luci-rpc',
method: 'getHostHints',
expect: { '': {} }
}),
callConntrackHelpers: rpc.declare({
object: 'luci',
method: 'getConntrackHelpers',
expect: { result: [] }
}),
load: function() {
return Promise.all([
this.callHostHints(),
this.callConntrackHelpers(),
uci.load('firewall')
]);
},
render: function(data) {
if (fwtool.checkLegacySNAT())
return fwtool.renderMigration();
else
return this.renderRules(data);
},
renderRules: function(data) {
var hosts = data[0],
ctHelpers = data[1],
m, s, o;
m = new form.Map('firewall', _('Firewall - Traffic Rules'),
_('Traffic rules define policies for packets traveling between different zones, for example to reject traffic between certain hosts or to open WAN ports on the router.'));
s = m.section(form.GridSection, 'rule', _('Traffic Rules'));
s.addremove = true;
s.anonymous = true;
s.sortable = true;
s.tab('general', _('General Settings'));
s.tab('advanced', _('Advanced Settings'));
s.tab('timed', _('Time Restrictions'));
s.filter = function(section_id) {
//return (uci.get('firewall', section_id, 'target') != 'SNAT');
return (uci.get('firewall', section_id, 'target') != 'SNAT' && section_id.startsWith('omr_dst') == false && section_id.startsWith('omr_dscp') == false);
};
s.sectiontitle = function(section_id) {
return uci.get('firewall', section_id, 'name') || _('Unnamed rule');
};
s.handleAdd = function(ev) {
var config_name = this.uciconfig || this.map.config,
section_id = uci.add(config_name, this.sectiontype),
opt1, opt2;
for (var i = 0; i < this.children.length; i++)
if (this.children[i].option == 'src')
opt1 = this.children[i];
else if (this.children[i].option == 'dest')
opt2 = this.children[i];
opt1.default = 'wan';
opt2.default = 'lan';
this.addedSection = section_id;
this.renderMoreOptionsModal(section_id);
delete opt1.default;
delete opt2.default;
};
o = s.taboption('general', form.Value, 'name', _('Name'));
o.placeholder = _('Unnamed rule');
o.modalonly = true;
o = s.option(form.DummyValue, '_match', _('Match'));
o.modalonly = false;
o.textvalue = function(s) {
return E('small', [
rule_proto_txt(s, ctHelpers), E('br'),
rule_src_txt(s, hosts), E('br'),
rule_dest_txt(s), E('br'),
rule_limit_txt(s)
]);
};
o = s.option(form.ListValue, '_target', _('Action'));
o.modalonly = false;
o.textvalue = function(s) {
return rule_target_txt(s, ctHelpers);
};
o = s.option(form.Flag, 'enabled', _('Enable'));
o.modalonly = false;
o.default = o.enabled;
o.editable = true;
o = s.taboption('advanced', form.ListValue, 'direction', _('Match device'));
o.modalonly = true;
o.value('', _('unspecified'));
o.value('in', _('Inbound device'));
o.value('out', _('Outbound device'));
o.cfgvalue = function(section_id) {
var val = uci.get('firewall', section_id, 'direction');
switch (val) {
case 'in':
case 'ingress':
return 'in';
case 'out':
case 'egress':
return 'out';
}
return null;
};
o = s.taboption('advanced', widgets.DeviceSelect, 'device', _('Device name'),
_('Specifies whether to tie this traffic rule to a specific inbound or outbound network device.'));
o.modalonly = true;
o.noaliases = true;
o.rmempty = false;
o.depends('direction', 'in');
o.depends('direction', 'out');
o = s.taboption('advanced', form.ListValue, 'family', _('Restrict to address family'));
o.modalonly = true;
o.rmempty = true;
o.value('', _('IPv4 and IPv6'));
o.value('ipv4', _('IPv4 only'));
o.value('ipv6', _('IPv6 only'));
o.validate = function(section_id, value) {
fwtool.updateHostHints(this.map, section_id, 'src_ip', value, hosts);
fwtool.updateHostHints(this.map, section_id, 'dest_ip', value, hosts);
return true;
};
o = s.taboption('general', fwtool.CBIProtocolSelect, 'proto', _('Protocol'));
o.modalonly = true;
o.default = 'tcp udp';
o = s.taboption('advanced', form.MultiValue, 'icmp_type', _('Match ICMP type'));
o.modalonly = true;
o.multiple = true;
o.custom = true;
o.cast = 'table';
o.placeholder = _('any');
o.value('', 'any');
o.value('address-mask-reply');
o.value('address-mask-request');
o.value('communication-prohibited');
o.value('destination-unreachable');
o.value('echo-reply');
o.value('echo-request');
o.value('fragmentation-needed');
o.value('host-precedence-violation');
o.value('host-prohibited');
o.value('host-redirect');
o.value('host-unknown');
o.value('host-unreachable');
o.value('ip-header-bad');
o.value('neighbour-advertisement');
o.value('neighbour-solicitation');
o.value('network-prohibited');
o.value('network-redirect');
o.value('network-unknown');
o.value('network-unreachable');
o.value('packet-too-big');
o.value('parameter-problem');
o.value('port-unreachable');
o.value('precedence-cutoff');
o.value('protocol-unreachable');
o.value('redirect');
o.value('required-option-missing');
o.value('router-advertisement');
o.value('router-solicitation');
o.value('source-quench');
o.value('source-route-failed');
o.value('time-exceeded');
o.value('timestamp-reply');
o.value('timestamp-request');
o.value('TOS-host-redirect');
o.value('TOS-host-unreachable');
o.value('TOS-network-redirect');
o.value('TOS-network-unreachable');
o.value('ttl-zero-during-reassembly');
o.value('ttl-zero-during-transit');
o.depends({ proto: 'icmp', '!contains': true });
o.depends({ proto: 'icmpv6', '!contains': true });
o = s.taboption('general', widgets.ZoneSelect, 'src', _('Source zone'));
o.modalonly = true;
o.nocreate = true;
o.allowany = true;
o.allowlocal = 'src';
fwtool.addMACOption(s, 'advanced', 'src_mac', _('Source MAC address'), null, hosts);
fwtool.addIPOption(s, 'general', 'src_ip', _('Source address'), null, '', hosts, true);
o = s.taboption('general', form.Value, 'src_port', _('Source port'));
o.modalonly = true;
o.datatype = 'list(neg(portrange))';
o.placeholder = _('any');
o.depends({ proto: 'tcp', '!contains': true });
o.depends({ proto: 'udp', '!contains': true });
o = s.taboption('general', widgets.ZoneSelect, 'dest', _('Destination zone'));
o.modalonly = true;
o.nocreate = true;
o.allowany = true;
o.allowlocal = true;
fwtool.addIPOption(s, 'general', 'dest_ip', _('Destination address'), null, '', hosts, true);
o = s.taboption('general', form.Value, 'dest_port', _('Destination port'));
o.modalonly = true;
o.datatype = 'list(neg(portrange))';
o.placeholder = _('any');
o.depends({ proto: 'tcp', '!contains': true });
o.depends({ proto: 'udp', '!contains': true });
o = s.taboption('general', form.ListValue, 'target', _('Action'));
o.modalonly = true;
o.default = 'ACCEPT';
o.value('DROP', _('drop'));
o.value('ACCEPT', _('accept'));
o.value('REJECT', _('reject'));
o.value('NOTRACK', _("don't track"));
o.value('HELPER', _('assign conntrack helper'));
o.value('MARK_SET', _('apply firewall mark'));
o.value('MARK_XOR', _('XOR firewall mark'));
o.value('DSCP', _('DSCP classification'));
o.cfgvalue = function(section_id) {
var t = uci.get('firewall', section_id, 'target'),
m = uci.get('firewall', section_id, 'set_mark');
if (t == 'MARK')
return m ? 'MARK_SET' : 'MARK_XOR';
return t;
};
o.write = function(section_id, value) {
return this.super('write', [section_id, (value == 'MARK_SET' || value == 'MARK_XOR') ? 'MARK' : value]);
};
fwtool.addMarkOption(s, 1);
fwtool.addMarkOption(s, 2);
fwtool.addDSCPOption(s, true);
o = s.taboption('general', form.ListValue, 'set_helper', _('Tracking helper'), _('Assign the specified connection tracking helper to matched traffic.'));
o.modalonly = true;
o.placeholder = _('any');
o.depends('target', 'HELPER');
for (var i = 0; i < ctHelpers.length; i++)
o.value(ctHelpers[i].name, '%s (%s)'.format(ctHelpers[i].description, ctHelpers[i].name.toUpperCase()));
o = s.taboption('advanced', form.Value, 'helper', _('Match helper'), _('Match traffic using the specified connection tracking helper.'));
o.modalonly = true;
o.placeholder = _('any');
for (var i = 0; i < ctHelpers.length; i++)
o.value(ctHelpers[i].name, '%s (%s)'.format(ctHelpers[i].description, ctHelpers[i].name.toUpperCase()));
o.validate = function(section_id, value) {
if (value == '' || value == null)
return true;
value = value.replace(/^!\s*/, '');
for (var i = 0; i < ctHelpers.length; i++)
if (value == ctHelpers[i].name)
return true;
return _('Unknown or not installed conntrack helper "%s"').format(value);
};
fwtool.addMarkOption(s, false);
fwtool.addDSCPOption(s, false);
fwtool.addLimitOption(s);
fwtool.addLimitBurstOption(s);
o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
_('Passes additional arguments to iptables. Use with care!'));
o.modalonly = true;
o = s.taboption('timed', form.MultiValue, 'weekdays', _('Week Days'));
o.modalonly = true;
o.multiple = true;
o.display = 5;
o.placeholder = _('Any day');
o.value('Sun', _('Sunday'));
o.value('Mon', _('Monday'));
o.value('Tue', _('Tuesday'));
o.value('Wed', _('Wednesday'));
o.value('Thu', _('Thursday'));
o.value('Fri', _('Friday'));
o.value('Sat', _('Saturday'));
o.write = function(section_id, value) {
return this.super('write', [ section_id, L.toArray(value).join(' ') ]);
};
o = s.taboption('timed', form.MultiValue, 'monthdays', _('Month Days'));
o.modalonly = true;
o.multiple = true;
o.display_size = 15;
o.placeholder = _('Any day');
o.write = function(section_id, value) {
return this.super('write', [ section_id, L.toArray(value).join(' ') ]);
};
for (var i = 1; i <= 31; i++)
o.value(i);
o = s.taboption('timed', form.Value, 'start_time', _('Start Time (hh.mm.ss)'));
o.modalonly = true;
o.datatype = 'timehhmmss';
o = s.taboption('timed', form.Value, 'stop_time', _('Stop Time (hh.mm.ss)'));
o.modalonly = true;
o.datatype = 'timehhmmss';
o = s.taboption('timed', form.Value, 'start_date', _('Start Date (yyyy-mm-dd)'));
o.modalonly = true;
o.datatype = 'dateyyyymmdd';
o = s.taboption('timed', form.Value, 'stop_date', _('Stop Date (yyyy-mm-dd)'));
o.modalonly = true;
o.datatype = 'dateyyyymmdd';
o = s.taboption('timed', form.Flag, 'utc_time', _('Time in UTC'));
o.modalonly = true;
o.default = o.disabled;
return m.render();
}
});

View file

@ -1,303 +0,0 @@
'use strict';
'require view';
'require ui';
'require rpc';
'require uci';
'require form';
'require firewall as fwmodel';
'require tools.firewall as fwtool';
'require tools.widgets as widgets';
function rule_proto_txt(s) {
var proto = L.toArray(uci.get('firewall', s, 'proto')).filter(function(p) {
return (p != '*' && p != 'any' && p != 'all');
}).map(function(p) {
var pr = fwtool.lookupProto(p);
return {
num: pr[0],
name: pr[1]
};
});
m = String(uci.get('firewall', s, 'mark')).match(/^(!\s*)?(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
var f = m ? {
val: m[0].toUpperCase().replace(/X/g, 'x'),
inv: m[1],
num: '0x%02X'.format(+m[2]),
mask: m[3] ? '0x%02X'.format(+m[3]) : null
} : null;
return fwtool.fmt(_('Forwarded IPv4%{proto?, protocol %{proto#%{next?, }<var>%{item.name}</var>}}%{mark?, mark <var%{mark.inv? data-tooltip="Match fwmarks except %{mark.num}%{mark.mask? with mask %{mark.mask}}.":%{mark.mask? data-tooltip="Mask fwmark value with %{mark.mask} before compare."}}>%{mark.val}</var>}'), {
proto: proto,
mark: f
});
}
function rule_src_txt(s, hosts) {
var z = uci.get('firewall', s, 'src');
return fwtool.fmt(_('From %{src}%{src_device?, interface <var>%{src_device}</var>}%{src_ip?, IP %{src_ip#%{next?, }<var%{item.inv? data-tooltip="Match IP addresses except %{item.val}."}>%{item.ival}</var>}}%{src_port?, port %{src_port#%{next?, }<var%{item.inv? data-tooltip="Match ports except %{item.val}."}>%{item.ival}</var>}}'), {
src: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName(null) }, [E('em', _('any zone'))]),
src_ip: fwtool.map_invert(uci.get('firewall', s, 'src_ip'), 'toLowerCase'),
src_port: fwtool.map_invert(uci.get('firewall', s, 'src_port'))
});
}
function rule_dest_txt(s) {
var z = uci.get('firewall', s, 'src');
return fwtool.fmt(_('To %{dest}%{dest_device?, via interface <var>%{dest_device}</var>}%{dest_ip?, IP %{dest_ip#%{next?, }<var%{item.inv? data-tooltip="Match IP addresses except %{item.val}."}>%{item.ival}</var>}}%{dest_port?, port %{dest_port#%{next?, }<var%{item.inv? data-tooltip="Match ports except %{item.val}."}>%{item.ival}</var>}}'), {
dest: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName((z && z != '*') ? z : null) }, [(z == '*') ? E('em', _('any zone')) : (z || E('em', _('this device')))]),
dest_ip: fwtool.map_invert(uci.get('firewall', s, 'dest_ip'), 'toLowerCase'),
dest_port: fwtool.map_invert(uci.get('firewall', s, 'dest_port')),
dest_device: uci.get('firewall', s, 'device')
});
}
function rule_limit_txt(s) {
var m = String(uci.get('firewall', s, 'limit')).match(/^(\d+)\/([smhd])\w*$/i),
l = m ? {
num: +m[1],
unit: ({ s: _('second'), m: _('minute'), h: _('hour'), d: _('day') })[m[2]],
burst: uci.get('firewall', s, 'limit_burst')
} : null;
if (!l)
return '';
return fwtool.fmt(_('Limit matching to <var>%{limit.num}</var> packets per <var>%{limit.unit}</var>%{limit.burst? burst <var>%{limit.burst}</var>}'), { limit: l });
}
function rule_target_txt(s) {
var t = uci.get('firewall', s, 'target'),
s = {
target: t,
snat_ip: uci.get('firewall', s, 'snat_ip'),
snat_port: uci.get('firewall', s, 'snat_port')
};
switch (t) {
case 'SNAT':
return fwtool.fmt(_('<var data-tooltip="SNAT">Statically rewrite</var> to source %{snat_ip?IP <var>%{snat_ip}</var>} %{snat_port?port <var>%{snat_port}</var>}'), s);
case 'MASQUERADE':
return fwtool.fmt(_('<var data-tooltip="MASQUERADE">Automatically rewrite</var> source IP'));
case 'ACCEPT':
return fwtool.fmt(_('<var data-tooltip="ACCEPT">Prevent source rewrite</var>'));
default:
return t;
}
}
return view.extend({
callHostHints: rpc.declare({
object: 'luci-rpc',
method: 'getHostHints',
expect: { '': {} }
}),
callNetworkDevices: rpc.declare({
object: 'luci-rpc',
method: 'getNetworkDevices',
expect: { '': {} }
}),
load: function() {
return Promise.all([
this.callHostHints(),
this.callNetworkDevices(),
uci.load('firewall')
]);
},
render: function(data) {
if (fwtool.checkLegacySNAT())
return fwtool.renderMigration();
else
return this.renderNats(data);
},
renderNats: function(data) {
var hosts = data[0],
devs = data[1],
m, s, o;
m = new form.Map('firewall', _('Firewall - NAT Rules'),
_('NAT rules allow fine grained control over the source IP to use for outbound or forwarded traffic.'));
s = m.section(form.GridSection, 'nat', _('NAT Rules'));
s.addremove = true;
s.anonymous = true;
s.sortable = true;
s.tab('general', _('General Settings'));
s.tab('advanced', _('Advanced Settings'));
s.tab('timed', _('Time Restrictions'));
s.sectiontitle = function(section_id) {
return uci.get('firewall', section_id, 'name') || _('Unnamed NAT');
};
o = s.taboption('general', form.Value, 'name', _('Name'));
o.placeholder = _('Unnamed NAT');
o.modalonly = true;
o = s.option(form.DummyValue, '_match', _('Match'));
o.modalonly = false;
o.textvalue = function(s) {
return E('small', [
rule_proto_txt(s), E('br'),
rule_src_txt(s, hosts), E('br'),
rule_dest_txt(s), E('br'),
rule_limit_txt(s)
]);
};
o = s.option(form.ListValue, '_target', _('Action'));
o.modalonly = false;
o.textvalue = function(s) {
return rule_target_txt(s);
};
o = s.option(form.Flag, 'enabled', _('Enable'));
o.modalonly = false;
o.default = o.enabled;
o.editable = true;
o = s.taboption('general', fwtool.CBIProtocolSelect, 'proto', _('Protocol'));
o.modalonly = true;
o.default = 'all';
o = s.taboption('general', widgets.ZoneSelect, 'src', _('Outbound zone'));
o.modalonly = true;
o.rmempty = false;
o.nocreate = true;
o.allowany = true;
o.default = 'lan';
o = fwtool.addIPOption(s, 'general', 'src_ip', _('Source address'),
_('Match forwarded traffic from this IP or range.'), 'ipv4', hosts);
o.rmempty = true;
o.datatype = 'neg(ipmask4)';
o = s.taboption('general', form.Value, 'src_port', _('Source port'),
_('Match forwarded traffic originating from the given source port or port range.'));
o.modalonly = true;
o.rmempty = true;
o.datatype = 'neg(portrange)';
o.placeholder = _('any');
o.depends({ proto: 'tcp', '!contains': true });
o.depends({ proto: 'udp', '!contains': true });
o = fwtool.addIPOption(s, 'general', 'dest_ip', _('Destination address'),
_('Match forwarded traffic directed at the given IP address.'), 'ipv4', hosts);
o.rmempty = true;
o.datatype = 'neg(ipmask4)';
o = s.taboption('general', form.Value, 'dest_port', _('Destination port'),
_('Match forwarded traffic directed at the given destination port or port range.'));
o.modalonly = true;
o.rmempty = true;
o.placeholder = _('any');
o.datatype = 'neg(portrange)';
o.depends({ proto: 'tcp', '!contains': true });
o.depends({ proto: 'udp', '!contains': true });
o = s.taboption('general', form.ListValue, 'target', _('Action'));
o.modalonly = true;
o.default = 'SNAT';
o.value('SNAT', _('SNAT - Rewrite to specific source IP or port'));
o.value('MASQUERADE', _('MASQUERADE - Automatically rewrite to outbound interface IP'));
o.value('ACCEPT', _('ACCEPT - Disable address rewriting'));
o = fwtool.addLocalIPOption(s, 'general', 'snat_ip', _('Rewrite IP address'),
_('Rewrite matched traffic to the specified source IP address.'), devs);
o.placeholder = null;
o.depends('target', 'SNAT');
o.validate = function(section_id, value) {
var port = this.map.lookupOption('snat_port', section_id),
a = this.formvalue(section_id),
p = port ? port[0].formvalue(section_id) : null;
if ((a == null || a == '') && (p == null || p == '') && value == '')
return _('A rewrite IP must be specified!');
return true;
};
o = s.taboption('general', form.Value, 'snat_port', _('Rewrite port'),
_('Rewrite matched traffic to the specified source port or port range.'));
o.modalonly = true;
o.rmempty = true;
o.placeholder = _('do not rewrite');
o.datatype = 'portrange';
o.depends({ proto: 'tcp', '!contains': true });
o.depends({ proto: 'udp', '!contains': true });
o = s.taboption('advanced', widgets.DeviceSelect, 'device', _('Outbound device'),
_('Matches forwarded traffic using the specified outbound network device.'));
o.noaliases = true;
o.modalonly = true;
o.rmempty = true;
fwtool.addMarkOption(s, false);
fwtool.addLimitOption(s);
fwtool.addLimitBurstOption(s);
o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
_('Passes additional arguments to iptables. Use with care!'));
o.modalonly = true;
o.rmempty = true;
o = s.taboption('timed', form.MultiValue, 'weekdays', _('Week Days'));
o.modalonly = true;
o.multiple = true;
o.display = 5;
o.placeholder = _('Any day');
o.value('Sun', _('Sunday'));
o.value('Mon', _('Monday'));
o.value('Tue', _('Tuesday'));
o.value('Wed', _('Wednesday'));
o.value('Thu', _('Thursday'));
o.value('Fri', _('Friday'));
o.value('Sat', _('Saturday'));
o.write = function(section_id, value) {
return this.super('write', [ section_id, L.toArray(value).join(' ') ]);
};
o = s.taboption('timed', form.MultiValue, 'monthdays', _('Month Days'));
o.modalonly = true;
o.multiple = true;
o.display_size = 15;
o.placeholder = _('Any day');
o.write = function(section_id, value) {
return this.super('write', [ section_id, L.toArray(value).join(' ') ]);
};
for (var i = 1; i <= 31; i++)
o.value(i);
o = s.taboption('timed', form.Value, 'start_time', _('Start Time (hh.mm.ss)'));
o.modalonly = true;
o.datatype = 'timehhmmss';
o = s.taboption('timed', form.Value, 'stop_time', _('Stop Time (hh.mm.ss)'));
o.modalonly = true;
o.datatype = 'timehhmmss';
o = s.taboption('timed', form.Value, 'start_date', _('Start Date (yyyy-mm-dd)'));
o.modalonly = true;
o.datatype = 'dateyyyymmdd';
o = s.taboption('timed', form.Value, 'stop_date', _('Stop Date (yyyy-mm-dd)'));
o.modalonly = true;
o.datatype = 'dateyyyymmdd';
o = s.taboption('timed', form.Flag, 'utc_time', _('Time in UTC'));
o.modalonly = true;
o.default = o.disabled;
return m.render();
}
});

View file

@ -1,346 +0,0 @@
'use strict';
'require view';
'require rpc';
'require uci';
'require form';
'require network';
'require firewall';
'require tools.firewall as fwtool';
'require tools.widgets as widgets';
return view.extend({
callConntrackHelpers: rpc.declare({
object: 'luci',
method: 'getConntrackHelpers',
expect: { result: [] }
}),
load: function() {
return Promise.all([
this.callConntrackHelpers(),
firewall.getDefaults()
]);
},
render: function(data) {
if (fwtool.checkLegacySNAT())
return fwtool.renderMigration();
else
return this.renderZones(data);
},
renderZones: function(data) {
var ctHelpers = data[0],
fwDefaults = data[1],
m, s, o, inp, out;
m = new form.Map('firewall', _('Firewall - Zone Settings'),
_('The firewall creates zones over your network interfaces to control network traffic flow.'));
s = m.section(form.TypedSection, 'defaults', _('General Settings'));
s.anonymous = true;
s.addremove = false;
o = s.option(form.Flag, 'syn_flood', _('Enable SYN-flood protection'));
o = s.option(form.Flag, 'drop_invalid', _('Drop invalid packets'));
var p = [
s.option(form.ListValue, 'input', _('Input')),
s.option(form.ListValue, 'output', _('Output')),
s.option(form.ListValue, 'forward', _('Forward'))
];
for (var i = 0; i < p.length; i++) {
p[i].value('REJECT', _('reject'));
p[i].value('DROP', _('drop'));
p[i].value('ACCEPT', _('accept'));
}
/* Netfilter flow offload support */
if (L.hasSystemFeature('offloading')) {
s = m.section(form.TypedSection, 'defaults', _('Routing/NAT Offloading'),
_('Experimental feature. Not fully compatible with QoS/SQM.'));
s.anonymous = true;
s.addremove = false;
o = s.option(form.Flag, 'flow_offloading',
_('Software flow offloading'),
_('Software based offloading for routing/NAT'));
o.optional = true;
o = s.option(form.Flag, 'flow_offloading_hw',
_('Hardware flow offloading'),
_('Requires hardware NAT support. Implemented at least for mt7621'));
o.optional = true;
o.depends('flow_offloading', '1');
}
s = m.section(form.GridSection, 'zone', _('Zones'));
s.addremove = true;
s.anonymous = true;
s.sortable = true;
s.handleRemove = function(section_id, ev) {
return firewall.deleteZone(section_id).then(L.bind(function() {
return this.super('handleRemove', [section_id, ev]);
}, this));
};
s.tab('general', _('General Settings'));
s.tab('advanced', _('Advanced Settings'));
s.tab('conntrack', _('Conntrack Settings'));
s.tab('extra', _('Extra iptables arguments'));
o = s.taboption('general', form.DummyValue, '_generalinfo');
o.rawhtml = true;
o.modalonly = true;
o.cfgvalue = function(section_id) {
var name = uci.get('firewall', section_id, 'name');
if (name == null)
name = _("this new zone");
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.')
.replace(/%s/g, name).replace(/%q/g, '"' + name + '"');
};
o = s.taboption('general', form.Value, 'name', _('Name'));
o.placeholder = _('Unnamed zone');
o.modalonly = true;
o.rmempty = false;
o.datatype = 'and(uciname,maxlength(11))';
o.write = function(section_id, formvalue) {
var cfgvalue = this.cfgvalue(section_id);
if (cfgvalue == null || cfgvalue == '')
return uci.set('firewall', section_id, 'name', formvalue);
else if (cfgvalue != formvalue)
return firewall.renameZone(cfgvalue, formvalue);
};
o = s.option(widgets.ZoneForwards, '_info', _('Zone ⇒ Forwardings'));
o.editable = true;
o.modalonly = false;
o.cfgvalue = function(section_id) {
return uci.get('firewall', section_id, 'name');
};
var p = [
s.taboption('general', form.ListValue, 'input', _('Input')),
s.taboption('general', form.ListValue, 'output', _('Output')),
s.taboption('general', form.ListValue, 'forward', _('Forward'))
];
for (var i = 0; i < p.length; i++) {
p[i].value('REJECT', _('reject'));
p[i].value('DROP', _('drop'));
p[i].value('ACCEPT', _('accept'));
p[i].editable = true;
}
p[0].default = fwDefaults.getInput();
p[1].default = fwDefaults.getOutput();
p[2].default = fwDefaults.getForward();
o = s.taboption('general', form.Flag, 'masq', _('Masquerading'));
o.editable = true;
o = s.taboption('general', form.Flag, 'fullcone', _('Full Cone'));
o.editable = true;
o.depends('masq', '1');
o = s.taboption('general', form.Flag, 'fullcone6', _('Full Cone IPv6'));
o.editable = true;
o.depends('masq', '1');
o = s.taboption('general', form.Flag, 'mtu_fix', _('MSS clamping'));
o.modalonly = true;
o = s.taboption('general', widgets.NetworkSelect, 'network', _('Covered networks'));
o.modalonly = true;
o.multiple = true;
o.cfgvalue = function(section_id) {
return uci.get('firewall', section_id, 'network');
};
o.write = function(section_id, formvalue) {
var name = uci.get('firewall', section_id, 'name'),
cfgvalue = this.cfgvalue(section_id);
/*
if (typeof(cfgvalue) == 'string' && Array.isArray(formvalue) && (cfgvalue == formvalue.join(' ')))
return;
*/
var tasks = [ firewall.getZone(name) ];
if (Array.isArray(formvalue))
for (var i = 0; i < formvalue.length; i++) {
var netname = formvalue[i];
tasks.push(network.getNetwork(netname).then(function(net) {
return net || network.addNetwork(netname, { 'proto': 'none' });
}));
}
return Promise.all(tasks).then(function(zone_networks) {
if (zone_networks[0]) {
zone_networks[0].clearNetworks();
for (var i = 1; i < zone_networks.length; i++)
zone_networks[0].addNetwork(zone_networks[i].getName());
}
});
};
o = s.taboption('advanced', form.DummyValue, '_advancedinfo');
o.rawhtml = true;
o.modalonly = true;
o.cfgvalue = function(section_id) {
var name = uci.get('firewall', section_id, 'name');
if (name == null)
name = _("this new zone");
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.')
.format(name);
};
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.'));
o.modalonly = true;
o.noaliases = true;
o.multiple = true;
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.'));
o.datatype = 'neg(cidr)';
o.modalonly = true;
o.multiple = true;
o = s.taboption('advanced', form.ListValue, 'family', _('Restrict to address family'));
o.value('', _('IPv4 and IPv6'));
o.value('ipv4', _('IPv4 only'));
o.value('ipv6', _('IPv6 only'));
o.modalonly = true;
o = s.taboption('advanced', form.DynamicList, 'masq_src', _('Restrict Masquerading to given source subnets'));
o.depends('family', '');
o.depends('family', 'ipv4');
o.datatype = 'list(neg(or(uciname,hostname,ipmask4)))';
o.placeholder = '0.0.0.0/0';
o.modalonly = true;
o = s.taboption('advanced', form.DynamicList, 'masq_dest', _('Restrict Masquerading to given destination subnets'));
o.depends('family', '');
o.depends('family', 'ipv4');
o.datatype = 'list(neg(or(uciname,hostname,ipmask4)))';
o.placeholder = '0.0.0.0/0';
o.modalonly = true;
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.'));
o.modalonly = true;
o = s.taboption('conntrack', form.Flag, 'auto_helper', _('Automatic helper assignment'), _('Automatically assign conntrack helpers based on traffic protocol and port'));
o.default = o.enabled;
o.modalonly = true;
o = s.taboption('conntrack', form.MultiValue, 'helper', _('Conntrack helpers'), _('Explicitly choses allowed connection tracking helpers for zone traffic'));
o.depends('auto_helper', '0');
o.modalonly = true;
for (var i = 0; i < ctHelpers.length; i++)
//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()));
o.value(ctHelpers[i].name, '%s (%s)'.format(ctHelpers[i].description, ctHelpers[i].name.toUpperCase()));
o = s.taboption('advanced', form.Flag, 'log', _('Enable logging on this zone'));
o.modalonly = true;
o = s.taboption('advanced', form.Value, 'log_limit', _('Limit log messages'));
o.depends('log', '1');
o.placeholder = '10/minute';
o.modalonly = true;
o = s.taboption('extra', form.DummyValue, '_extrainfo');
o.rawhtml = true;
o.modalonly = true;
o.cfgvalue = function(section_id) {
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.');
};
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.'));
o.modalonly = true;
o.cfgvalue = function(section_id) {
return uci.get('firewall', section_id, 'extra_src') || uci.get('firewall', section_id, 'extra');
};
o.write = function(section_id, value) {
uci.unset('firewall', section_id, 'extra');
uci.set('firewall', section_id, 'extra_src', value);
};
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.'));
o.modalonly = true;
o.cfgvalue = function(section_id) {
return uci.get('firewall', section_id, 'extra_dest') || uci.get('firewall', section_id, 'extra_src') || uci.get('firewall', section_id, 'extra');
};
o.write = function(section_id, value) {
uci.unset('firewall', section_id, 'extra');
uci.set('firewall', section_id, 'extra_dest', value);
};
o = s.taboption('general', form.DummyValue, '_forwardinfo');
o.rawhtml = true;
o.modalonly = true;
o.cfgvalue = function(section_id) {
var name = uci.get('firewall', section_id, 'name');
if (name == null)
name = _("this new zone");
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.')
.format(name);
};
out = o = s.taboption('general', widgets.ZoneSelect, 'out', _('Allow forward to <em>destination zones</em>:'));
o.nocreate = true;
o.multiple = true;
o.modalonly = true;
o.filter = function(section_id, value) {
return (uci.get('firewall', section_id, 'name') != value);
};
o.cfgvalue = function(section_id) {
var out = (this.option == 'out'),
zone = this.lookupZone(uci.get('firewall', section_id, 'name')),
fwds = zone ? zone.getForwardingsBy(out ? 'src' : 'dest') : [],
value = [];
for (var i = 0; i < fwds.length; i++)
value.push(out ? fwds[i].getDestination() : fwds[i].getSource());
return value;
};
o.write = o.remove = function(section_id, formvalue) {
var out = (this.option == 'out'),
zone = this.lookupZone(uci.get('firewall', section_id, 'name')),
fwds = zone ? zone.getForwardingsBy(out ? 'src' : 'dest') : [];
if (formvalue == null)
formvalue = [];
if (Array.isArray(formvalue)) {
for (var i = 0; i < fwds.length; i++) {
var cmp = out ? fwds[i].getDestination() : fwds[i].getSource();
if (!formvalue.filter(function(d) { return d == cmp }).length)
zone.deleteForwarding(fwds[i]);
}
for (var i = 0; i < formvalue.length; i++)
if (out)
zone.addForwardingTo(formvalue[i]);
else
zone.addForwardingFrom(formvalue[i]);
}
};
inp = o = s.taboption('general', widgets.ZoneSelect, 'in', _('Allow forward from <em>source zones</em>:'));
o.nocreate = true;
o.multiple = true;
o.modalonly = true;
o.write = o.remove = out.write;
o.filter = out.filter;
o.cfgvalue = out.cfgvalue;
return m.render();
}
});

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,61 +0,0 @@
{
"admin/network/firewall": {
"title": "Firewall",
"order": 60,
"action": {
"type": "alias",
"path": "admin/network/firewall/zones"
},
"depends": {
"acl": [ "luci-app-firewall" ],
"fs": { "/sbin/fw3": "executable" },
"uci": { "firewall": true }
}
},
"admin/network/firewall/zones": {
"title": "General Settings",
"order": 10,
"action": {
"type": "view",
"path": "firewall/zones"
}
},
"admin/network/firewall/forwards": {
"title": "Port Forwards",
"order": 20,
"action": {
"type": "view",
"path": "firewall/forwards"
}
},
"admin/network/firewall/rules": {
"title": "Traffic Rules",
"order": 30,
"action": {
"type": "view",
"path": "firewall/rules"
}
},
"admin/network/firewall/snats": {
"title": "NAT Rules",
"order": 40,
"action": {
"type": "view",
"path": "firewall/snats"
}
},
"admin/network/firewall/custom": {
"title": "Custom Rules",
"order": 50,
"action": {
"type": "view",
"path": "firewall/custom"
}
}
}

View file

@ -1,24 +0,0 @@
{
"luci-app-firewall": {
"description": "Grant access to firewall configuration",
"read": {
"file": {
"/etc/firewall.user": [ "read" ]
},
"ubus": {
"file": [ "read" ],
"luci": [ "getConntrackHelpers" ]
},
"uci": [ "firewall" ]
},
"write": {
"file": {
"/etc/firewall.user": [ "write" ]
},
"ubus": {
"file": [ "write" ]
},
"uci": [ "firewall" ]
}
}
}