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

Older firewall app

This commit is contained in:
Ycarus (Yannick Chabanois) 2020-01-03 08:36:30 +01:00
parent fb63bb0bda
commit 383b5b72d4
41 changed files with 11736 additions and 11618 deletions

View file

@ -1,312 +0,0 @@
'use strict';
'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',
'ipv6-icmp', 58, 'IPv6-ICMP',
'ipv6-nonxt', 59, 'IPv6-NoNxt',
'ipv6-opts', 60, 'IPv6-Opts',
'rspf', 73, 'RSPF', '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',
'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] ];
return [ -1, x ];
}
return L.Class.extend({
fmt_neg: function(x) {
var rv = E([]),
v = (typeof(x) == 'string') ? x.replace(/^ *! */, '') : '';
L.dom.append(rv, (v != '' && v != x) ? [ _('not') + ' ', v ] : [ '', x ]);
return rv;
},
fmt_mac: function(x) {
var rv = E([]), l = L.toArray(x);
if (l.length == 0)
return null;
L.dom.append(rv, [ _('MAC') + ' ' ]);
for (var i = 0; i < l.length; i++) {
var n = this.fmt_neg(l[i]);
L.dom.append(rv, (i > 0) ? [ ', ', n ] : n);
}
if (rv.childNodes.length > 2)
rv.firstChild.data = _('MACs') + ' ';
return rv;
},
fmt_port: function(x, d) {
var rv = E([]), l = L.toArray(x);
if (l.length == 0) {
if (d) {
L.dom.append(rv, E('var', {}, d));
return rv;
}
return null;
}
L.dom.append(rv, [ _('port') + ' ' ]);
for (var i = 0; i < l.length; i++) {
var n = this.fmt_neg(l[i]),
m = n.lastChild.data.match(/^(\d+)\D+(\d+)$/);
if (i > 0)
L.dom.append(rv, [ ', ' ]);
if (m) {
rv.firstChild.data = _('ports') + ' ';
L.dom.append(rv, E('var', [ n.firstChild, m[1], '-', m[2] ]));
}
else {
L.dom.append(rv, E('var', {}, n));
}
}
if (rv.childNodes.length > 2)
rv.firstChild.data = _('ports') + ' ';
return rv;
},
fmt_ip: function(x, d) {
var rv = E([]), l = L.toArray(x);
if (l.length == 0) {
if (d) {
L.dom.append(rv, E('var', {}, d));
return rv;
}
return null;
}
L.dom.append(rv, [ _('IP') + ' ' ]);
for (var i = 0; i < l.length; i++) {
var n = this.fmt_neg(l[i]),
m = n.lastChild.data.match(/^(\S+)\/(\d+\.\S+)$/);
if (i > 0)
L.dom.append(rv, [ ', ' ]);
if (m)
rv.firstChild.data = _('IP range') + ' ';
else if (n.lastChild.data.match(/^[a-zA-Z0-9_]+$/))
rv.firstChild.data = _('Network') + ' ';
L.dom.append(rv, E('var', {}, n));
}
if (rv.childNodes.length > 2)
rv.firstChild.data = _('IPs') + ' ';
return rv;
},
fmt_zone: function(x, d) {
if (x == '*')
return E('var', _('any zone'));
else if (x != null && x != '')
return E('var', {}, [ x ]);
else if (d != null && d != '')
return E('var', {}, d);
else
return null;
},
fmt_icmp_type: function(x) {
var rv = E([]), l = L.toArray(x);
if (l.length == 0)
return null;
L.dom.append(rv, [ _('type') + ' ' ]);
for (var i = 0; i < l.length; i++) {
var n = this.fmt_neg(l[i]);
if (i > 0)
L.dom.append(rv, [ ', ' ]);
L.dom.append(rv, E('var', {}, n));
}
if (rv.childNodes.length > 2)
rv.firstChild.data = _('types') + ' ';
return rv;
},
fmt_family: function(family) {
if (family == 'ipv4')
return _('IPv4');
else if (family == 'ipv6')
return _('IPv6');
else
return _('IPv4 and IPv6');
},
fmt_proto: function(x, icmp_types) {
var rv = E([]), l = L.toArray(x);
if (l.length == 0)
return null;
var t = this.fmt_icmp_type(icmp_types);
for (var i = 0; i < l.length; i++) {
var n = this.fmt_neg(l[i]),
p = lookupProto(n.lastChild.data);
if (n.lastChild.data == 'all')
continue;
if (i > 0)
L.dom.append(rv, [ ', ' ]);
if (t && (p[0] == 1 || p[0] == 58))
L.dom.append(rv, [ _('%s%s with %s').format(n.firstChild.data, p[1], ''), t ]);
else
L.dom.append(rv, [ n.firstChild.data, p[1] ]);
}
return rv;
},
fmt_limit: function(limit, burst) {
if (limit == null || limit == '')
return null;
var m = String(limit).match(/^(\d+)\/(\w+)$/),
u = m[2] || 'second',
l = +(m[1] || limit),
b = +burst;
if (!isNaN(l)) {
if (u.match(/^s/))
u = _('second');
else if (u.match(/^m/))
u = _('minute');
else if (u.match(/^h/))
u = _('hour');
else if (u.match(/^d/))
u = _('day');
if (!isNaN(b) && b > 0)
return E('<span>' +
_('<var>%d</var> pkts. per <var>%s</var>, burst <var>%d</var> pkts.').format(l, u, b) +
'</span>');
else
return E('<span>' +
_('<var>%d</var> pkts. per <var>%s</var>').format(l, u) +
'</span>');
}
},
fmt_target: function(x, src, dest) {
if (src == null || src == '') {
if (x == 'ACCEPT')
return _('Accept output');
else if (x == 'REJECT')
return _('Refuse output');
else if (x == 'NOTRACK')
return _('Do not track output');
else /* if (x == 'DROP') */
return _('Discard output');
}
else if (dest != null && dest != '') {
if (x == 'ACCEPT')
return _('Accept forward');
else if (x == 'REJECT')
return _('Refuse forward');
else if (x == 'NOTRACK')
return _('Do not track forward');
else /* if (x == 'DROP') */
return _('Discard forward');
}
else {
if (x == 'ACCEPT')
return _('Accept input');
else if (x == 'REJECT' )
return _('Refuse input');
else if (x == 'NOTRACK')
return _('Do not track input');
else /* if (x == 'DROP') */
return _('Discard input');
}
}
});

View file

@ -1,274 +0,0 @@
'use strict';
'require ui';
'require rpc';
'require uci';
'require form';
'require tools.firewall as fwtool';
'require tools.widgets as widgets';
function fmt(fmt /*, ...*/) {
var repl = [], wrap = false;
for (var i = 1; i < arguments.length; i++) {
if (L.dom.elem(arguments[i])) {
switch (arguments[i].nodeType) {
case 1:
repl.push(arguments[i].outerHTML);
wrap = true;
break;
case 3:
repl.push(arguments[i].data);
break;
case 11:
var span = E('span');
span.appendChild(arguments[i]);
repl.push(span.innerHTML);
wrap = true;
break;
default:
repl.push('');
}
}
else {
repl.push(arguments[i]);
}
}
var rv = fmt.format.apply(fmt, repl);
return wrap ? E('span', rv) : rv;
}
function forward_proto_txt(s) {
return fmt('%s-%s',
fwtool.fmt_family(uci.get('firewall', s, 'family')),
fwtool.fmt_proto(uci.get('firewall', s, 'proto'),
uci.get('firewall', s, 'icmp_type')) || 'TCP+UDP');
}
function forward_src_txt(s) {
var z = fwtool.fmt_zone(uci.get('firewall', s, 'src'), _('any zone')),
a = fwtool.fmt_ip(uci.get('firewall', s, 'src_ip'), _('any host')),
p = fwtool.fmt_port(uci.get('firewall', s, 'src_port')),
m = fwtool.fmt_mac(uci.get('firewall', s, 'src_mac'));
if (p && m)
return fmt(_('From %s in %s with source %s and %s'), a, z, p, m);
else if (p || m)
return fmt(_('From %s in %s with source %s'), a, z, p || m);
else
return fmt(_('From %s in %s'), a, z);
}
function forward_via_txt(s) {
var a = fwtool.fmt_ip(uci.get('firewall', s, 'src_dip'), _('any router IP')),
p = fwtool.fmt_port(uci.get('firewall', s, 'src_dport'));
if (p)
return fmt(_('Via %s at %s'), a, p);
else
return fmt(_('Via %s'), a);
}
return L.view.extend({
callHostHints: rpc.declare({
object: 'luci',
method: 'getHostHints',
expect: { '': {} }
}),
load: function() {
return Promise.all([
this.callHostHints()
]);
},
render: function(data) {
var hosts = data[0],
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', [
forward_proto_txt(s), E('br'),
forward_src_txt(s), E('br'),
forward_via_txt(s)
]);
};
o = s.option(form.ListValue, '_dest', _('Forward to'));
o.modalonly = false;
o.textvalue = function(s) {
var z = fwtool.fmt_zone(uci.get('firewall', s, 'dest'), _('any zone')),
a = fwtool.fmt_ip(uci.get('firewall', s, 'dest_ip'), _('any host')),
p = fwtool.fmt_port(uci.get('firewall', s, 'dest_port')) ||
fwtool.fmt_port(uci.get('firewall', s, 'src_dport'));
if (p)
return fmt(_('%s, %s in %s'), a, p, z);
else
return fmt(_('%s in %s'), a, z);
};
o = s.option(form.Flag, 'enabled', _('Enable'));
o.modalonly = false;
o.default = o.enabled;
o.editable = true;
o = s.taboption('general', form.Value, 'proto', _('Protocol'));
o.modalonly = true;
o.default = 'tcp udp';
o.value('tcp udp', 'TCP+UDP');
o.value('tcp', 'TCP');
o.value('udp', 'UDP');
o.value('icmp', 'ICMP');
o.cfgvalue = function(/* ... */) {
var v = this.super('cfgvalue', arguments);
return (v == 'tcpudp') ? 'tcp udp' : v;
};
o = s.taboption('general', widgets.ZoneSelect, 'src', _('Source zone'));
o.modalonly = true;
o.rmempty = false;
o.nocreate = true;
o.default = 'wan';
o = s.taboption('advanced', form.Value, 'src_mac', _('Source MAC address'),
_('Only match incoming traffic from these MACs.'));
o.modalonly = true;
o.rmempty = true;
o.datatype = 'neg(macaddr)';
o.placeholder = E('em', _('any'));
L.sortedKeys(hosts).forEach(function(mac) {
o.value(mac, '%s (%s)'.format(
mac,
hosts[mac].name || hosts[mac].ipv4 || hosts[mac].ipv6 || '?'
));
});
o = s.taboption('advanced', form.Value, 'src_ip', _('Source IP address'),
_('Only match incoming traffic from this IP or range.'));
o.modalonly = true;
o.rmempty = true;
o.datatype = 'neg(ipmask4)';
o.placeholder = E('em', _('any'));
L.sortedKeys(hosts, 'ipv4', 'addr').forEach(function(mac) {
o.value(hosts[mac].ipv4, '%s (%s)'.format(
hosts[mac].ipv4,
hosts[mac].name || mac
));
});
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');
o.depends('proto', 'udp');
o.depends('proto', 'tcp udp');
o.depends('proto', 'tcpudp');
o = s.taboption('advanced', form.Value, 'src_dip', _('External IP address'),
_('Only match incoming traffic directed at the given IP address.'));
o.modalonly = true;
o.rmempty = true;
o.datatype = 'neg(ipmask4)';
o.placeholder = E('em', _('any'));
L.sortedKeys(hosts, 'ipv4', 'addr').forEach(function(mac) {
o.value(hosts[mac].ipv4, '%s (%s)'.format(
hosts[mac].ipv4,
hosts[mac].name || mac
));
});
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');
o.depends('proto', 'udp');
o.depends('proto', 'tcp udp');
o.depends('proto', 'tcpudp');
o = s.taboption('general', widgets.ZoneSelect, 'dest', _('Internal zone'));
o.modalonly = true;
o.rmempty = true;
o.nocreate = true;
o.default = 'lan';
o = s.taboption('general', form.Value, 'dest_ip', _('Internal IP address'),
_('Redirect matched incoming traffic to the specified internal host'));
o.modalonly = true;
o.rmempty = true;
o.datatype = 'ipmask4';
L.sortedKeys(hosts, 'ipv4', 'addr').forEach(function(mac) {
o.value(hosts[mac].ipv4, '%s (%s)'.format(
hosts[mac].ipv4,
hosts[mac].name || mac
));
});
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');
o.depends('proto', 'udp');
o.depends('proto', 'tcp udp');
o.depends('proto', 'tcpudp');
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.Value, 'extra', _('Extra arguments'),
_('Passes additional arguments to iptables. Use with care!'));
o.modalonly = true;
o.rmempty = true;
return m.render();
}
});

View file

@ -1,383 +0,0 @@
'use strict';
'require ui';
'require rpc';
'require uci';
'require form';
'require tools.firewall as fwtool';
'require tools.widgets as widgets';
function fmt(fmt /*, ...*/) {
var repl = [], wrap = false;
for (var i = 1; i < arguments.length; i++) {
if (L.dom.elem(arguments[i])) {
switch (arguments[i].nodeType) {
case 1:
repl.push(arguments[i].outerHTML);
wrap = true;
break;
case 3:
repl.push(arguments[i].data);
break;
case 11:
var span = E('span');
span.appendChild(arguments[i]);
repl.push(span.innerHTML);
wrap = true;
break;
default:
repl.push('');
}
}
else {
repl.push(arguments[i]);
}
}
var rv = fmt.format.apply(fmt, repl);
return wrap ? E('span', rv) : rv;
}
function forward_proto_txt(s) {
return fmt('%s-%s',
fwtool.fmt_family(uci.get('firewall', s, 'family')),
fwtool.fmt_proto(uci.get('firewall', s, 'proto'),
uci.get('firewall', s, 'icmp_type')) || 'TCP+UDP');
}
function rule_src_txt(s) {
var z = fwtool.fmt_zone(uci.get('firewall', s, 'src')),
p = fwtool.fmt_port(uci.get('firewall', s, 'src_port')),
m = fwtool.fmt_mac(uci.get('firewall', s, 'src_mac'));
// Forward/Input
if (z) {
var a = fwtool.fmt_ip(uci.get('firewall', s, 'src_ip'), _('any host'));
if (p && m)
return fmt(_('From %s in %s with source %s and %s'), a, z, p, m);
else if (p || m)
return fmt(_('From %s in %s with source %s'), a, z, p || m);
else
return fmt(_('From %s in %s'), a, z);
}
// Output
else {
var a = fwtool.fmt_ip(uci.get('firewall', s, 'src_ip'), _('any router IP'));
if (p && m)
return fmt(_('From %s on <var>this device</var> with source %s and %s'), a, p, m);
else if (p || m)
return fmt(_('From %s on <var>this device</var> with source %s'), a, p || m);
else
return fmt(_('From %s on <var>this device</var>'), a);
}
}
function rule_dest_txt(s) {
var z = fwtool.fmt_zone(uci.get('firewall', s, 'dest')),
p = fwtool.fmt_port(uci.get('firewall', s, 'dest_port'));
// Forward
if (z) {
var a = fwtool.fmt_ip(uci.get('firewall', s, 'dest_ip'), _('any host'));
if (p)
return fmt(_('To %s, %s in %s'), a, p, z);
else
return fmt(_('To %s in %s'), a, z);
}
// Input
else {
var a = fwtool.fmt_ip(uci.get('firewall', s, 'dest_ip'), _('any router IP'));
if (p)
return fmt(_('To %s at %s on <var>this device</var>'), a, p);
else
return fmt(_('To %s on <var>this device</var>'), a);
}
}
function rule_target_txt(s) {
var t = fwtool.fmt_target(uci.get('firewall', s, 'target'), uci.get('firewall', s, 'src'), uci.get('firewall', s, 'dest')),
l = fwtool.fmt_limit(uci.get('firewall', s, 'limit'), uci.get('firewall', s, 'limit_burst'));
if (l)
return fmt(_('<var>%s</var> and limit to %s'), t, l);
else
return fmt('<var>%s</var>', t);
}
return L.view.extend({
callHostHints: rpc.declare({
object: 'luci',
method: 'getHostHints',
expect: { '': {} }
}),
load: function() {
return this.callHostHints().catch(function(e) {
console.debug('load fail', e);
});
},
render: function(hosts) {
var 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');
};
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', [
forward_proto_txt(s), E('br'),
rule_src_txt(s), E('br'),
rule_dest_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;
//ft.opt_enabled(s, Button);
//ft.opt_name(s, Value, _('Name'));
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 = s.taboption('general', form.Value, 'proto', _('Protocol'));
o.modalonly = true;
o.default = 'tcp udp';
o.value('all', _('Any'));
o.value('tcp udp', 'TCP+UDP');
o.value('tcp', 'TCP');
o.value('udp', 'UDP');
o.value('icmp', 'ICMP');
o.cfgvalue = function(/* ... */) {
var v = this.super('cfgvalue', arguments);
return (v == 'tcpudp') ? 'tcp udp' : v;
};
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('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');
o = s.taboption('general', widgets.ZoneSelect, 'src', _('Source zone'));
o.modalonly = true;
o.nocreate = true;
o.allowany = true;
o.allowlocal = 'src';
o = s.taboption('advanced', form.Value, 'src_mac', _('Source MAC address'));
o.modalonly = true;
o.datatype = 'list(macaddr)';
o.placeholder = _('any');
L.sortedKeys(hosts).forEach(function(mac) {
o.value(mac, '%s (%s)'.format(
mac,
hosts[mac].name || hosts[mac].ipv4 || hosts[mac].ipv6 || '?'
));
});
o = s.taboption('general', form.Value, 'src_ip', _('Source address'));
o.modalonly = true;
o.datatype = 'list(neg(ipmask))';
o.placeholder = _('any');
L.sortedKeys(hosts, 'ipv4', 'addr').forEach(function(mac) {
o.value(hosts[mac].ipv4, '%s (%s)'.format(
hosts[mac].ipv4,
hosts[mac].name || mac
));
});
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');
o.depends('proto', 'udp');
o.depends('proto', 'tcp udp');
o.depends('proto', 'tcpudp');
o = s.taboption('general', widgets.ZoneSelect, 'dest', _('Destination zone'));
o.modalonly = true;
o.nocreate = true;
o.allowany = true;
o.allowlocal = true;
o = s.taboption('general', form.Value, 'dest_ip', _('Destination address'));
o.modalonly = true;
o.datatype = 'list(neg(ipmask))';
o.placeholder = _('any');
L.sortedKeys(hosts, 'ipv4', 'addr').forEach(function(mac) {
o.value(hosts[mac].ipv4, '%s (%s)'.format(
hosts[mac].ipv4,
hosts[mac].name || mac
));
});
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');
o.depends('proto', 'udp');
o.depends('proto', 'tcp udp');
o.depends('proto', 'tcpudp');
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 = 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 = s.taboption('timed', form.MultiValue, 'monthdays', _('Month Days'));
o.modalonly = true;
o.multiple = true;
o.display_size = 15;
o.placeholder = _('Any day');
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,321 +0,0 @@
'use strict';
'require rpc';
'require uci';
'require form';
'require network';
'require firewall';
'require tools.widgets as widgets';
return L.view.extend({
callConntrackHelpers: rpc.declare({
object: 'luci',
method: 'getConntrackHelpers',
expect: { result: [] }
}),
load: function() {
return Promise.all([
this.callConntrackHelpers(),
firewall.getDefaults()
]);
},
render: 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.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, 'mtu_fix', _('MSS clamping'));
o.modalonly = true;
o = s.taboption('general', widgets.NetworkSelect, 'network', _('Covered networks'));
o.modalonly = true;
o.multiple = true;
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])
for (var i = 1; i < zone_networks.length; i++)
zone_networks[0].addNetwork(zone_networks[i].getName());
});
};
o.remove = function(section_id) {
return uci.set('firewall', section_id, 'network', ' ');
};
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, 'conntrack', _('Force connection tracking'), _('Prevent the installation of <em>NOTRACK</em> rules which would bypass connection tracking.'));
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 = 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();
}
});

View file

@ -6,13 +6,16 @@ function index()
_("Firewall"), 60) _("Firewall"), 60)
entry({"admin", "network", "firewall", "zones"}, entry({"admin", "network", "firewall", "zones"},
view("firewall/zones"), _("General Settings"), 10) arcombine(cbi("firewall/zones"), cbi("firewall/zone-details")),
_("General Settings"), 10).leaf = true
entry({"admin", "network", "firewall", "forwards"}, entry({"admin", "network", "firewall", "forwards"},
view("firewall/forwards"), _("Port Forwards"), 20) arcombine(cbi("firewall/forwards"), cbi("firewall/forward-details")),
_("Port Forwards"), 20).leaf = true
entry({"admin", "network", "firewall", "rules"}, entry({"admin", "network", "firewall", "rules"},
view("firewall/rules"), _("Traffic Rules"), 30) arcombine(cbi("firewall/rules"), cbi("firewall/rule-details")),
_("Traffic Rules"), 30).leaf = true
entry({"admin", "network", "firewall", "custom"}, entry({"admin", "network", "firewall", "custom"},
form("firewall/custom"), form("firewall/custom"),

View file

@ -0,0 +1,162 @@
-- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
-- Licensed to the public under the Apache License 2.0.
local sys = require "luci.sys"
local dsp = require "luci.dispatcher"
local ft = require "luci.tools.firewall"
local m, s, o
arg[1] = arg[1] or ""
m = Map("firewall",
translate("Firewall - Port Forwards"),
translate("This page allows you to change advanced properties of the port \
forwarding entry. In most cases there is no need to modify \
those settings."))
m.redirect = dsp.build_url("admin/network/firewall/forwards")
if m.uci:get("firewall", arg[1]) ~= "redirect" then
luci.http.redirect(m.redirect)
return
else
local name = m:get(arg[1], "name") or m:get(arg[1], "_name")
if not name or #name == 0 then
name = translate("(Unnamed Entry)")
end
m.title = "%s - %s" %{ translate("Firewall - Port Forwards"), name }
end
s = m:section(NamedSection, arg[1], "redirect", "")
s.anonymous = true
s.addremove = false
ft.opt_enabled(s, Button)
ft.opt_name(s, Value, translate("Name"))
o = s:option(Value, "proto", translate("Protocol"))
o:value("tcp udp", "TCP+UDP")
o:value("tcp", "TCP")
o:value("udp", "UDP")
o:value("icmp", "ICMP")
function o.cfgvalue(...)
local v = Value.cfgvalue(...)
if not v or v == "tcpudp" then
return "tcp udp"
end
return v
end
o = s:option(Value, "src", translate("Source zone"))
o.nocreate = true
o.default = "wan"
o.template = "cbi/firewall_zonelist"
o.rmempty = false
o = s:option(DynamicList, "src_mac",
translate("Source MAC address"),
translate("Only match incoming traffic from these MACs."))
o.rmempty = true
o.datatype = "neg(macaddr)"
o.placeholder = translate("any")
luci.sys.net.mac_hints(function(mac, name)
o:value(mac, "%s (%s)" %{ mac, name })
end)
o = s:option(Value, "src_ip",
translate("Source IP address"),
translate("Only match incoming traffic from this IP or range."))
o.rmempty = true
o.datatype = "neg(ipmask4)"
o.placeholder = translate("any")
luci.sys.net.ipv4_hints(function(ip, name)
o:value(ip, "%s (%s)" %{ ip, name })
end)
o = s:option(Value, "src_port",
translate("Source port"),
translate("Only match incoming traffic originating from the given source port or port range on the client host"))
o.rmempty = true
o.datatype = "neg(portrange)"
o.placeholder = translate("any")
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(Value, "src_dip",
translate("External IP address"),
translate("Only match incoming traffic directed at the given IP address."))
luci.sys.net.ipv4_hints(function(ip, name)
o:value(ip, "%s (%s)" %{ ip, name })
end)
o.rmempty = true
o.datatype = "neg(ipmask4)"
o.placeholder = translate("any")
o = s:option(Value, "src_dport", translate("External port"),
translate("Match incoming traffic directed at the given " ..
"destination port or port range on this host"))
o.datatype = "neg(portrange)"
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(Value, "dest", translate("Internal zone"))
o.nocreate = true
o.default = "lan"
o.template = "cbi/firewall_zonelist"
o = s:option(Value, "dest_ip", translate("Internal IP address"),
translate("Redirect matched incoming traffic to the specified \
internal host"))
o.datatype = "ipmask4"
luci.sys.net.ipv4_hints(function(ip, name)
o:value(ip, "%s (%s)" %{ ip, name })
end)
o = s:option(Value, "dest_port",
translate("Internal port"),
translate("Redirect matched incoming traffic to the given port on \
the internal host"))
o.placeholder = translate("any")
o.datatype = "portrange"
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(Flag, "reflection", translate("Enable NAT Loopback"))
o.rmempty = true
o.default = o.enabled
o.cfgvalue = function(...)
return Flag.cfgvalue(...) or "1"
end
s:option(Value, "extra",
translate("Extra arguments"),
translate("Passes additional arguments to iptables. Use with care!"))
return m

View file

@ -0,0 +1,133 @@
-- Copyright 2008 Steven Barth <steven@midlink.org>
-- Copyright 2010-2012 Jo-Philipp Wich <jow@openwrt.org>
-- Licensed to the public under the Apache License 2.0.
local ds = require "luci.dispatcher"
local ft = require "luci.tools.firewall"
m = Map("firewall", translate("Firewall - Port Forwards"),
translate("Port forwarding allows remote computers on the Internet to \
connect to a specific computer or service within the \
private LAN."))
--
-- Port Forwards
--
s = m:section(TypedSection, "redirect", translate("Port Forwards"))
s.template = "cbi/tblsection"
s.addremove = true
s.anonymous = true
s.sortable = true
s.extedit = ds.build_url("admin/network/firewall/forwards/%s")
s.template_addremove = "firewall/cbi_addforward"
function s.create(self, section)
local n = m:formvalue("_newfwd.name")
local p = m:formvalue("_newfwd.proto")
local E = m:formvalue("_newfwd.extzone")
local e = m:formvalue("_newfwd.extport")
local I = m:formvalue("_newfwd.intzone")
local a = m:formvalue("_newfwd.intaddr")
local i = m:formvalue("_newfwd.intport")
if p == "other" or (p and a) then
created = TypedSection.create(self, section)
self.map:set(created, "target", "DNAT")
self.map:set(created, "src", E or "wan")
self.map:set(created, "dest", I or "lan")
self.map:set(created, "proto", (p ~= "other") and p or "all")
self.map:set(created, "src_dport", e)
self.map:set(created, "dest_ip", a)
self.map:set(created, "dest_port", i)
self.map:set(created, "name", n)
end
if p ~= "other" then
created = nil
end
end
function s.parse(self, ...)
TypedSection.parse(self, ...)
if created then
m.uci:save("firewall")
luci.http.redirect(ds.build_url(
"admin/network/firewall/forwards", created
))
end
end
function s.filter(self, sid)
return (self.map:get(sid, "target") ~= "SNAT")
end
function s.sectiontitle(self, sid)
return (self.map:get(sid, "name") or translate("Unnamed forward"))
end
local function forward_proto_txt(self, s)
return "%s-%s" %{
translate("IPv4"),
ft.fmt_proto(self.map:get(s, "proto"),
self.map:get(s, "icmp_type")) or "TCP+UDP"
}
end
local function forward_src_txt(self, s)
local z = ft.fmt_zone(self.map:get(s, "src"), translate("any zone"))
local a = ft.fmt_ip(self.map:get(s, "src_ip"), translate("any host"))
local p = ft.fmt_port(self.map:get(s, "src_port"))
local m = ft.fmt_mac(self.map:get(s, "src_mac"))
if p and m then
return translatef("From %s in %s with source %s and %s", a, z, p, m)
elseif p or m then
return translatef("From %s in %s with source %s", a, z, p or m)
else
return translatef("From %s in %s", a, z)
end
end
local function forward_via_txt(self, s)
local a = ft.fmt_ip(self.map:get(s, "src_dip"), translate("any router IP"))
local p = ft.fmt_port(self.map:get(s, "src_dport"))
if p then
return translatef("Via %s at %s", a, p)
else
return translatef("Via %s", a)
end
end
match = s:option(DummyValue, "match", translate("Match"))
match.rawhtml = true
function match.cfgvalue(self, s)
return "<small>%s<br />%s<br />%s</small>" % {
forward_proto_txt(self, s),
forward_src_txt(self, s),
forward_via_txt(self, s)
}
end
dest = s:option(DummyValue, "dest", translate("Forward to"))
dest.rawhtml = true
function dest.cfgvalue(self, s)
local z = ft.fmt_zone(self.map:get(s, "dest"), translate("any zone"))
local a = ft.fmt_ip(self.map:get(s, "dest_ip"), translate("any host"))
local p = ft.fmt_port(self.map:get(s, "dest_port")) or
ft.fmt_port(self.map:get(s, "src_dport"))
if p then
return translatef("%s, %s in %s", a, p, z)
else
return translatef("%s in %s", a, z)
end
end
ft.opt_enabled(s, Flag, translate("Enable"))
return m

View file

@ -0,0 +1,365 @@
-- Copyright 2008 Steven Barth <steven@midlink.org>
-- Copyright 2010-2012 Jo-Philipp Wich <jow@openwrt.org>
-- Licensed to the public under the Apache License 2.0.
local dsp = require "luci.dispatcher"
local ft = require "luci.tools.firewall"
local nw = require "luci.model.network"
local m, s, o, v, _
arg[1] = arg[1] or ""
m = Map("firewall",
translate("Firewall - Traffic Rules"),
translate("This page allows you to change advanced properties of the \
traffic rule entry, such as matched source and destination \
hosts."))
m.redirect = dsp.build_url("admin/network/firewall/rules")
nw.init(m.uci)
local rule_type = m.uci:get("firewall", arg[1])
if rule_type == "redirect" and m:get(arg[1], "target") ~= "SNAT" then
rule_type = nil
end
if not rule_type then
luci.http.redirect(m.redirect)
return
--
-- SNAT
--
elseif rule_type == "redirect" then
local name = m:get(arg[1], "name") or m:get(arg[1], "_name")
if not name or #name == 0 then
name = translate("(Unnamed SNAT)")
else
name = "SNAT %s" % name
end
m.title = "%s - %s" %{ translate("Firewall - Traffic Rules"), name }
s = m:section(NamedSection, arg[1], "redirect", "")
s.anonymous = true
s.addremove = false
ft.opt_enabled(s, Button)
ft.opt_name(s, Value, translate("Name"))
o = s:option(Value, "proto",
translate("Protocol"),
translate("You may specify multiple by selecting \"-- custom --\" and \
then entering protocols separated by space."))
o:value("all", "All protocols")
o:value("tcp udp", "TCP+UDP")
o:value("tcp", "TCP")
o:value("udp", "UDP")
o:value("icmp", "ICMP")
function o.cfgvalue(...)
local v = Value.cfgvalue(...)
if not v or v == "tcpudp" then
return "tcp udp"
end
return v
end
o = s:option(Value, "src", translate("Source zone"))
o.nocreate = true
o.default = "wan"
o.template = "cbi/firewall_zonelist"
o = s:option(Value, "src_ip", translate("Source IP address"))
o.rmempty = true
o.datatype = "neg(ipmask4)"
o.placeholder = translate("any")
luci.sys.net.ipv4_hints(function(ip, name)
o:value(ip, "%s (%s)" %{ ip, name })
end)
o = s:option(Value, "src_port",
translate("Source port"),
translate("Match incoming traffic originating from the given source \
port or port range on the client host."))
o.rmempty = true
o.datatype = "neg(portrange)"
o.placeholder = translate("any")
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(Value, "dest", translate("Destination zone"))
o.nocreate = true
o.default = "lan"
o.template = "cbi/firewall_zonelist"
o = s:option(Value, "dest_ip", translate("Destination IP address"))
o.datatype = "neg(ipmask4)"
luci.sys.net.ipv4_hints(function(ip, name)
o:value(ip, "%s (%s)" %{ ip, name })
end)
o = s:option(Value, "dest_port",
translate("Destination port"),
translate("Match forwarded traffic to the given destination port or \
port range."))
o.rmempty = true
o.placeholder = translate("any")
o.datatype = "neg(portrange)"
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(Value, "src_dip",
translate("SNAT IP address"),
translate("Rewrite matched traffic to the given address."))
o.rmempty = false
o.datatype = "ip4addr"
for _, v in ipairs(nw:get_interfaces()) do
local a
for _, a in ipairs(v:ipaddrs()) do
o:value(a:host():string(), '%s (%s)' %{
a:host():string(), v:shortname()
})
end
end
o = s:option(Value, "src_dport", translate("SNAT port"),
translate("Rewrite matched traffic to the given source port. May be \
left empty to only rewrite the IP address."))
o.datatype = "portrange"
o.rmempty = true
o.placeholder = translate('Do not rewrite')
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
s:option(Value, "extra",
translate("Extra arguments"),
translate("Passes additional arguments to iptables. Use with care!"))
--
-- Rule
--
else
local name = m:get(arg[1], "name") or m:get(arg[1], "_name")
if not name or #name == 0 then
name = translate("(Unnamed Rule)")
end
m.title = "%s - %s" %{ translate("Firewall - Traffic Rules"), name }
s = m:section(NamedSection, arg[1], "rule", "")
s.anonymous = true
s.addremove = false
ft.opt_enabled(s, Button)
ft.opt_name(s, Value, translate("Name"))
o = s:option(ListValue, "family", translate("Restrict to address family"))
o.rmempty = true
o:value("", translate("IPv4 and IPv6"))
o:value("ipv4", translate("IPv4 only"))
o:value("ipv6", translate("IPv6 only"))
o = s:option(Value, "proto", translate("Protocol"))
o:value("all", translate("Any"))
o:value("tcp udp", "TCP+UDP")
o:value("tcp", "TCP")
o:value("udp", "UDP")
o:value("icmp", "ICMP")
function o.cfgvalue(...)
local v = Value.cfgvalue(...)
if not v or v == "tcpudp" then
return "tcp udp"
end
return v
end
o = s:option(DropDown, "icmp_type", translate("Match ICMP type"))
o.multiple = true
o.display = 10
o.dropdown = 10
o.custom = true
o.cast = "table"
o:value("", "any")
o:value("echo-reply")
o:value("destination-unreachable")
o:value("network-unreachable")
o:value("host-unreachable")
o:value("protocol-unreachable")
o:value("port-unreachable")
o:value("fragmentation-needed")
o:value("source-route-failed")
o:value("network-unknown")
o:value("host-unknown")
o:value("network-prohibited")
o:value("host-prohibited")
o:value("TOS-network-unreachable")
o:value("TOS-host-unreachable")
o:value("communication-prohibited")
o:value("host-precedence-violation")
o:value("precedence-cutoff")
o:value("source-quench")
o:value("redirect")
o:value("network-redirect")
o:value("host-redirect")
o:value("TOS-network-redirect")
o:value("TOS-host-redirect")
o:value("echo-request")
o:value("router-advertisement")
o:value("router-solicitation")
o:value("time-exceeded")
o:value("ttl-zero-during-transit")
o:value("ttl-zero-during-reassembly")
o:value("parameter-problem")
o:value("ip-header-bad")
o:value("required-option-missing")
o:value("timestamp-request")
o:value("timestamp-reply")
o:value("address-mask-request")
o:value("address-mask-reply")
o:depends("proto", "icmp")
o = s:option(Value, "src", translate("Source zone"))
o.nocreate = true
o.allowany = true
o.allowlocal = "src"
o.template = "cbi/firewall_zonelist"
o = s:option(Value, "src_mac", translate("Source MAC address"))
o.datatype = "list(macaddr)"
o.placeholder = translate("any")
luci.sys.net.mac_hints(function(mac, name)
o:value(mac, "%s (%s)" %{ mac, name })
end)
o = s:option(Value, "src_ip", translate("Source address"))
o.datatype = "list(neg(ipmask))"
o.placeholder = translate("any")
luci.sys.net.ipv4_hints(function(ip, name)
o:value(ip, "%s (%s)" %{ ip, name })
end)
o = s:option(Value, "src_port", translate("Source port"))
o.datatype = "list(neg(portrange))"
o.placeholder = translate("any")
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(Value, "dest_local", translate("Output zone"))
o.nocreate = true
o.allowany = true
o.template = "cbi/firewall_zonelist"
o.alias = "dest"
o:depends("src", "")
o = s:option(Value, "dest_remote", translate("Destination zone"))
o.nocreate = true
o.allowany = true
o.allowlocal = true
o.template = "cbi/firewall_zonelist"
o.alias = "dest"
o:depends({["src"] = "", ["!reverse"] = true})
o = s:option(Value, "dest_ip", translate("Destination address"))
o.datatype = "list(neg(ipmask))"
o.placeholder = translate("any")
luci.sys.net.ipv4_hints(function(ip, name)
o:value(ip, "%s (%s)" %{ ip, name })
end)
o = s:option(Value, "dest_port", translate("Destination port"))
o.datatype = "list(neg(portrange))"
o.placeholder = translate("any")
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(ListValue, "target", translate("Action"))
o.default = "ACCEPT"
o:value("DROP", translate("drop"))
o:value("ACCEPT", translate("accept"))
o:value("REJECT", translate("reject"))
o:value("NOTRACK", translate("don't track"))
s:option(Value, "extra",
translate("Extra arguments"),
translate("Passes additional arguments to iptables. Use with care!"))
end
o = s:option(DropDown, "weekdays", translate("Week Days"))
o.multiple = true
o.display = 5
o:value("Sun", translate("Sunday"))
o:value("Mon", translate("Monday"))
o:value("Tue", translate("Tuesday"))
o:value("Wed", translate("Wednesday"))
o:value("Thu", translate("Thursday"))
o:value("Fri", translate("Friday"))
o:value("Sat", translate("Saturday"))
o = s:option(DropDown, "monthdays", translate("Month Days"))
o.multiple = true
o.display = 15
for i = 1,31 do
o:value(translate(i))
end
o = s:option(Value, "start_time", translate("Start Time (hh:mm:ss)"))
o.datatype = "timehhmmss"
o = s:option(Value, "stop_time", translate("Stop Time (hh:mm:ss)"))
o.datatype = "timehhmmss"
o = s:option(Value, "start_date", translate("Start Date (yyyy-mm-dd)"))
o.datatype = "dateyyyymmdd"
o = s:option(Value, "stop_date", translate("Stop Date (yyyy-mm-dd)"))
o.datatype = "dateyyyymmdd"
o = s:option(Flag, "utc_time", translate("Time in UTC"))
o.default = o.disabled
return m

View file

@ -0,0 +1,273 @@
-- Copyright 2008 Steven Barth <steven@midlink.org>
-- Copyright 2010-2012 Jo-Philipp Wich <jow@openwrt.org>
-- Licensed to the public under the Apache License 2.0.
local ds = require "luci.dispatcher"
local ft = require "luci.tools.firewall"
m = Map("firewall",
translate("Firewall - Traffic Rules"),
translate("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."))
--
-- Rules
--
s = m:section(TypedSection, "rule", translate("Traffic Rules"))
s.addremove = true
s.anonymous = true
s.sortable = true
s.template = "cbi/tblsection"
s.extedit = ds.build_url("admin/network/firewall/rules/%s")
s.defaults.target = "ACCEPT"
s.template_addremove = "firewall/cbi_addrule"
function s.create(self, section)
created = TypedSection.create(self, section)
end
function s.parse(self, ...)
TypedSection.parse(self, ...)
local i_n = m:formvalue("_newopen.name")
local i_p = m:formvalue("_newopen.proto")
local i_e = m:formvalue("_newopen.extport")
local i_x = m:formvalue("_newopen.submit")
local f_n = m:formvalue("_newfwd.name")
local f_s = m:formvalue("_newfwd.src")
local f_d = m:formvalue("_newfwd.dest")
local f_x = m:formvalue("_newfwd.submit")
if i_x then
created = TypedSection.create(self, section)
self.map:set(created, "target", "ACCEPT")
self.map:set(created, "src", "wan")
self.map:set(created, "proto", (i_p ~= "other") and i_p or "all")
self.map:set(created, "dest_port", i_e)
self.map:set(created, "name", i_n)
if i_p ~= "other" and i_e and #i_e > 0 then
created = nil
end
elseif f_x then
created = TypedSection.create(self, section)
self.map:set(created, "target", "ACCEPT")
self.map:set(created, "src", f_s)
self.map:set(created, "dest", f_d)
self.map:set(created, "name", f_n)
end
if created then
m.uci:save("firewall")
luci.http.redirect(ds.build_url(
"admin/network/firewall/rules", created
))
end
end
function s.sectiontitle(self, sid)
return (self.map:get(sid, "name") or translate("Unnamed rule"))
end
local function rule_proto_txt(self, s)
local f = self.map:get(s, "family")
local p = ft.fmt_proto(self.map:get(s, "proto"),
self.map:get(s, "icmp_type")) or translate("traffic")
if f and f:match("4") then
return "%s-%s" %{ translate("IPv4"), p }
elseif f and f:match("6") then
return "%s-%s" %{ translate("IPv6"), p }
else
return "%s %s" %{ translate("Any"), p }
end
end
local function rule_src_txt(self, s)
local z = ft.fmt_zone(self.map:get(s, "src"))
local p = ft.fmt_port(self.map:get(s, "src_port"))
local m = ft.fmt_mac(self.map:get(s, "src_mac"))
-- Forward/Input
if z and #z > 0 then
local a = ft.fmt_ip(self.map:get(s, "src_ip"), translate("any host"))
if p and m then
return translatef("From %s in %s with source %s and %s", a, z, p, m)
elseif p or m then
return translatef("From %s in %s with source %s", a, z, p or m)
else
return translatef("From %s in %s", a, z)
end
-- Output
else
local a = ft.fmt_ip(self.map:get(s, "src_ip"), translate("any router IP"))
if p and m then
return translatef("From %s on <var>this device</var> with source %s and %s", a, p, m)
elseif p or m then
return translatef("From %s on <var>this device</var> with source %s", a, p or m)
else
return translatef("From %s on <var>this device</var>", a)
end
end
end
local function rule_dest_txt(self, s)
local z = ft.fmt_zone(self.map:get(s, "dest"))
local p = ft.fmt_port(self.map:get(s, "dest_port"))
-- Forward
if z then
local a = ft.fmt_ip(self.map:get(s, "dest_ip"), translate("any host"))
if p then
return translatef("To %s, %s in %s", a, p, z)
else
return translatef("To %s in %s", a, z)
end
-- Input
else
local a = ft.fmt_ip(self.map:get(s, "dest_ip"),
translate("any router IP"))
if p then
return translatef("To %s at %s on <var>this device</var>", a, p)
else
return translatef("To %s on <var>this device</var>", a)
end
end
end
local function snat_dest_txt(self, s)
local z = ft.fmt_zone(self.map:get(s, "dest"), translate("any zone"))
local a = ft.fmt_ip(self.map:get(s, "dest_ip"), translate("any host"))
local p = ft.fmt_port(self.map:get(s, "dest_port")) or
ft.fmt_port(self.map:get(s, "src_dport"))
if p then
return translatef("To %s, %s in %s", a, p, z)
else
return translatef("To %s in %s", a, z)
end
end
match = s:option(DummyValue, "match", translate("Match"))
match.rawhtml = true
function match.cfgvalue(self, s)
return "<small>%s<br />%s<br />%s</small>" % {
rule_proto_txt(self, s),
rule_src_txt(self, s),
rule_dest_txt(self, s)
}
end
target = s:option(DummyValue, "target", translate("Action"))
target.rawhtml = true
function target.cfgvalue(self, s)
local t = ft.fmt_target(self.map:get(s, "target"), self.map:get(s, "src"), self.map:get(s, "dest"))
local l = ft.fmt_limit(self.map:get(s, "limit"),
self.map:get(s, "limit_burst"))
if l then
return translatef("<var>%s</var> and limit to %s", t, l)
else
return "<var>%s</var>" % t
end
end
ft.opt_enabled(s, Flag, translate("Enable"))
--
-- SNAT
--
s = m:section(TypedSection, "redirect",
translate("Source NAT"),
translate("Source NAT is a specific form of masquerading which allows \
fine grained control over the source IP used for outgoing traffic, \
for example to map multiple WAN addresses to internal subnets."))
s.template = "cbi/tblsection"
s.addremove = true
s.anonymous = true
s.sortable = true
s.extedit = ds.build_url("admin/network/firewall/rules/%s")
s.template_addremove = "firewall/cbi_addsnat"
function s.create(self, section)
created = TypedSection.create(self, section)
end
function s.parse(self, ...)
TypedSection.parse(self, ...)
local n = m:formvalue("_newsnat.name")
local s = m:formvalue("_newsnat.src")
local d = m:formvalue("_newsnat.dest")
local a = m:formvalue("_newsnat.dip")
local p = m:formvalue("_newsnat.dport")
local x = m:formvalue("_newsnat.submit")
if x and a and #a > 0 then
created = TypedSection.create(self, section)
self.map:set(created, "target", "SNAT")
self.map:set(created, "src", s)
self.map:set(created, "dest", d)
self.map:set(created, "proto", "all")
self.map:set(created, "src_dip", a)
self.map:set(created, "src_dport", p)
self.map:set(created, "name", n)
end
if created then
m.uci:save("firewall")
luci.http.redirect(ds.build_url(
"admin/network/firewall/rules", created
))
end
end
function s.filter(self, sid)
return (self.map:get(sid, "target") == "SNAT")
end
function s.sectiontitle(self, sid)
return (self.map:get(sid, "name") or translate("Unnamed SNAT"))
end
match = s:option(DummyValue, "match", translate("Match"))
match.rawhtml = true
function match.cfgvalue(self, s)
return "<small>%s<br />%s<br />%s</small>" % {
rule_proto_txt(self, s),
rule_src_txt(self, s),
snat_dest_txt(self, s)
}
end
snat = s:option(DummyValue, "via", translate("Action"))
snat.rawhtml = true
function snat.cfgvalue(self, s)
local a = ft.fmt_ip(self.map:get(s, "src_dip"))
local p = ft.fmt_port(self.map:get(s, "src_dport"))
if a and p then
return translatef("Rewrite to source %s, %s", a, p)
else
return translatef("Rewrite to source %s", a or p)
end
end
ft.opt_enabled(s, Flag, translate("Enable"))
return m

View file

@ -0,0 +1,229 @@
-- Copyright 2008 Steven Barth <steven@midlink.org>
-- Copyright 2010-2011 Jo-Philipp Wich <jow@openwrt.org>
-- Licensed to the public under the Apache License 2.0.
local nw = require "luci.model.network"
local fw = require "luci.model.firewall"
local ds = require "luci.dispatcher"
local ut = require "luci.util"
local m, p, i, v
local s, name, net, family, msrc, mdest, log, lim
local s2, out, inp
m = Map("firewall", translate("Firewall - Zone Settings"))
m.redirect = luci.dispatcher.build_url("admin/network/firewall/zones")
fw.init(m.uci)
nw.init(m.uci)
local zone = fw:get_zone(arg[1])
if not zone then
luci.http.redirect(ds.build_url("admin/network/firewall/zones"))
return
else
m.title = "%s - %s" %{
translate("Firewall - Zone Settings"),
translatef("Zone %q", zone:name() or "?")
}
end
s = m:section(NamedSection, zone.sid, "zone",
translatef("Zone %q", zone:name()),
translatef("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.", zone:name()))
s.anonymous = true
s.addremove = false
m.on_commit = function(map)
local zone = fw:get_zone(arg[1])
if zone then
s.section = zone.sid
s2.section = zone.sid
end
end
s:tab("general", translate("General Settings"))
s:tab("advanced", translate("Advanced Settings"))
name = s:taboption("general", Value, "name", translate("Name"))
name.optional = false
name.forcewrite = true
name.datatype = "and(uciname,maxlength(11))"
function name.write(self, section, value)
if zone:name() ~= value then
fw:rename_zone(zone:name(), value)
out.exclude = value
inp.exclude = value
end
end
p = {
s:taboption("general", ListValue, "input", translate("Input")),
s:taboption("general", ListValue, "output", translate("Output")),
s:taboption("general", ListValue, "forward", translate("Forward"))
}
for i, v in ipairs(p) do
v:value("REJECT", translate("reject"))
v:value("DROP", translate("drop"))
v:value("ACCEPT", translate("accept"))
end
s:taboption("general", Flag, "masq", translate("Masquerading"))
s:taboption("general", Flag, "mtu_fix", translate("MSS clamping"))
net = s:taboption("general", Value, "network", translate("Covered networks"))
net.template = "cbi/network_netlist"
net.widget = "checkbox"
net.cast = "string"
function net.formvalue(self, section)
return Value.formvalue(self, section) or "-"
end
function net.cfgvalue(self, section)
return Value.cfgvalue(self, section) or name:cfgvalue(section)
end
function net.write(self, section, value)
zone:clear_networks()
local net
for net in ut.imatch(value) do
local n = nw:get_network(net) or nw:add_network(net, { proto = "none" })
if n then
zone:add_network(n:name())
end
end
end
family = s:taboption("advanced", ListValue, "family",
translate("Restrict to address family"))
family.rmempty = true
family:value("", translate("IPv4 and IPv6"))
family:value("ipv4", translate("IPv4 only"))
family:value("ipv6", translate("IPv6 only"))
msrc = s:taboption("advanced", DynamicList, "masq_src",
translate("Restrict Masquerading to given source subnets"))
msrc.optional = true
msrc.datatype = "list(neg(or(uciname,hostname,ipmask4)))"
msrc.placeholder = "0.0.0.0/0"
msrc:depends("family", "")
msrc:depends("family", "ipv4")
mdest = s:taboption("advanced", DynamicList, "masq_dest",
translate("Restrict Masquerading to given destination subnets"))
mdest.optional = true
mdest.datatype = "list(neg(or(uciname,hostname,ipmask4)))"
mdest.placeholder = "0.0.0.0/0"
mdest:depends("family", "")
mdest:depends("family", "ipv4")
s:taboption("advanced", Flag, "conntrack",
translate("Force connection tracking"))
log = s:taboption("advanced", Flag, "log",
translate("Enable logging on this zone"))
log.rmempty = true
log.enabled = "1"
lim = s:taboption("advanced", Value, "log_limit",
translate("Limit log messages"))
lim.placeholder = "10/minute"
lim:depends("log", "1")
s2 = m:section(NamedSection, zone.sid, "fwd_out",
translate("Inter-Zone Forwarding"),
translatef("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.",
zone:name(), zone:name(), zone:name()
))
out = s2:option(Value, "out",
translate("Allow forward to <em>destination zones</em>:"))
out.nocreate = true
out.widget = "checkbox"
out.exclude = zone:name()
out.template = "cbi/firewall_zonelist"
inp = s2:option(Value, "in",
translate("Allow forward from <em>source zones</em>:"))
inp.nocreate = true
inp.widget = "checkbox"
inp.exclude = zone:name()
inp.template = "cbi/firewall_zonelist"
function out.cfgvalue(self, section)
local v = { }
local f
for _, f in ipairs(zone:get_forwardings_by("src")) do
v[#v+1] = f:dest()
end
return table.concat(v, " ")
end
function inp.cfgvalue(self, section)
local v = { }
local f
for _, f in ipairs(zone:get_forwardings_by("dest")) do
v[#v+1] = f:src()
end
return v
end
function out.formvalue(self, section)
return Value.formvalue(self, section) or "-"
end
function inp.formvalue(self, section)
return Value.formvalue(self, section) or "-"
end
function out.write(self, section, value)
zone:del_forwardings_by("src")
local f
for f in ut.imatch(value) do
zone:add_forwarding_to(f)
end
end
function inp.write(self, section, value)
zone:del_forwardings_by("dest")
local f
for f in ut.imatch(value) do
zone:add_forwarding_from(f)
end
end
return m

View file

@ -0,0 +1,104 @@
-- Copyright 2008 Steven Barth <steven@midlink.org>
-- Licensed to the public under the Apache License 2.0.
local ds = require "luci.dispatcher"
local fw = require "luci.model.firewall"
local fs = require "nixio.fs"
local m, s, o, p, i, v
m = Map("firewall",
translate("Firewall - Zone Settings"),
translate("The firewall creates zones over your network interfaces to control network traffic flow."))
fw.init(m.uci)
s = m:section(TypedSection, "defaults", translate("General Settings"))
s.anonymous = true
s.addremove = false
s:option(Flag, "syn_flood", translate("Enable SYN-flood protection"))
o = s:option(Flag, "drop_invalid", translate("Drop invalid packets"))
p = {
s:option(ListValue, "input", translate("Input")),
s:option(ListValue, "output", translate("Output")),
s:option(ListValue, "forward", translate("Forward"))
}
for i, v in ipairs(p) do
v:value("REJECT", translate("reject"))
v:value("DROP", translate("drop"))
v:value("ACCEPT", translate("accept"))
end
-- Netfilter flow offload support
local offload = fs.access("/sys/module/xt_FLOWOFFLOAD/refcnt")
if offload then
s:option(DummyValue, "offload_advice",
translate("Routing/NAT Offloading"),
translate("Experimental feature. Not fully compatible with QoS/SQM."))
o = s:option(Flag, "flow_offloading",
translate("Software flow offloading"),
translate("Software based offloading for routing/NAT"))
o.optional = true
o = s:option(Flag, "flow_offloading_hw",
translate("Hardware flow offloading"),
translate("Requires hardware NAT support. Implemented at least for mt7621"))
o.optional = true
o:depends( "flow_offloading", 1)
end
-- Firewall zones
s = m:section(TypedSection, "zone", translate("Zones"))
s.template = "cbi/tblsection"
s.anonymous = true
s.addremove = true
s.extedit = ds.build_url("admin", "network", "firewall", "zones", "%s")
function s.sectiontitle(self, sid)
local z = fw:get_zone(sid)
return z:name()
end
function s.create(self)
local z = fw:new_zone()
if z then
luci.http.redirect(
ds.build_url("admin", "network", "firewall", "zones", z.sid)
)
end
end
function s.remove(self, section)
return fw:del_zone(section)
end
o = s:option(DummyValue, "_info", translate("Zone ⇒ Forwardings"))
o.template = "cbi/firewall_zoneforwards"
o.cfgvalue = function(self, section)
return self.map:get(section, "name")
end
p = {
s:option(ListValue, "input", translate("Input")),
s:option(ListValue, "output", translate("Output")),
s:option(ListValue, "forward", translate("Forward"))
}
for i, v in ipairs(p) do
v:value("REJECT", translate("reject"))
v:value("DROP", translate("drop"))
v:value("ACCEPT", translate("accept"))
end
s:option(Flag, "masq", translate("Masquerading"))
s:option(Flag, "mtu_fix", translate("MSS clamping"))
return m

View file

@ -0,0 +1,90 @@
<%-
local fw = require "luci.model.firewall".init()
local izl = { }
local ezl = { }
local _, z
for _, z in ipairs(fw:get_zones()) do
if z:name() ~= "wan" then
izl[#izl+1] = z
end
if z:name() ~= "lan" then
ezl[#ezl+1] = z
end
end
local keys, vals = { }, { }
luci.sys.net.ipv4_hints(function(ip, name)
keys[#keys+1] = ip
vals[#vals+1] = '%s (%s)' %{ ip, name }
end)
-%>
<h4><%:New port forward%></h4>
<div class="table">
<div class="tr table-titles">
<div class="th"><%:Name%></div>
<div class="th"><%:Protocol%></div>
<div class="th"><%:External zone%></div>
<div class="th"><%:External port%></div>
<div class="th"><%:Internal zone%></div>
<div class="th"><%:Internal IP address%></div>
<div class="th"><%:Internal port%></div>
<div class="th"></div>
</div>
<div class="tr">
<div class="td">
<input type="text" class="cbi-input-text" id="_newfwd.name" name="_newfwd.name" placeholder="<%:New port forward%>" />
</div>
<div class="td">
<select class="cbi-input-select" id="_newfwd.proto" name="_newfwd.proto">
<option value="tcp udp">TCP+UDP</option>
<option value="tcp">TCP</option>
<option value="udp">UDP</option>
<option value="other"><%:Other...%></option>
</select>
</div>
<div class="td">
<select class="cbi-input-select" id="_newfwd.extzone" name="_newfwd.extzone">
<% for _, z in ipairs(ezl) do -%><option value="<%=z:name()%>"><%=z:name()%></option><%- end %>
</select>
</div>
<div class="td">
<input type="text" class="cbi-input-text" id="_newfwd.extport" name="_newfwd.extport" data-type="portrange" data-optional="true" />
</div>
<div class="td">
<select class="cbi-input-select" id="_newfwd.intzone" name="_newfwd.intzone">
<% for _, z in ipairs(izl) do -%><option value="<%=z:name()%>"><%=z:name()%></option><%- end %>
</select>
</div>
<div class="td">
<input type="text" class="cbi-input-text" id="_newfwd.intaddr" name="_newfwd.intaddr" data-type="host" data-optional="true"<%=
ifattr(#keys > 0, "data-choices", {keys, vals})
%>/>
</div>
<div class="td">
<input type="text" class="cbi-input-text" id="_newfwd.intport" name="_newfwd.intport" data-type="portrange" data-optional="true" />
</div>
<div class="td bottom">
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
</div>
</div>
</div>
<script type="text/javascript">//<![CDATA[
document.getElementById('_newfwd.extport').addEventListener('blur',
function() {
var n = document.getElementById('_newfwd.name');
var p = document.getElementById('_newfwd.proto');
var i = document.getElementById('_newfwd.intport');
if (!this.className.match(/invalid/))
{
if (!i.value) i.value = this.value;
if (!n.value)
{
n.value = 'Forward' + this.value;
}
}
});
//]]></script>

View file

@ -0,0 +1,89 @@
<%
local fw = require "luci.model.firewall".init()
local zones = fw:get_zones()
%>
<% if #zones > 0 then %>
<h4><%:Open ports on router%></h4>
<div class="table">
<div class="tr cbi-section-table-titles">
<div class="th"><%:Name%></div>
<div class="th"><%:Protocol%></div>
<div class="th"><%:External port%></div>
<div class="th"></div>
</div>
<div class="tr">
<div class="td">
<input type="text" class="cbi-input-text" id="_newopen.name" name="_newopen.name" placeholder="<%:New input rule%>" />
</div>
<div class="td">
<select class="cbi-input-select" id="_newopen.proto" name="_newopen.proto">
<option value="tcp udp">TCP+UDP</option>
<option value="tcp">TCP</option>
<option value="udp">UDP</option>
<option value="other"><%:Other...%></option>
</select>
</div>
<div class="td">
<input type="text" class="cbi-input-text" id="_newopen.extport" name="_newopen.extport" />
</div>
<div class="td bottom">
<input type="submit" class="cbi-button cbi-button-add" name="_newopen.submit" value="<%:Add%>" />
</div>
</div>
</div>
<% end %>
<% if #zones > 1 then %>
<h4><%:New forward rule%></h4>
<div class="table">
<div class="tr cbi-section-table-titles">
<div class="th"><%:Name%></div>
<div class="th"><%:Source zone%></div>
<div class="th"><%:Destination zone%></div>
<div class="th"></div>
</div>
<div class="tr">
<div class="td">
<input type="text" class="cbi-input-text" id="_newfwd.name" name="_newfwd.name" placeholder="<%:New forward rule%>" />
</div>
<div class="td">
<select class="cbi-input-text" id="_newfwd.src" name="_newfwd.src">
<% local k, v; for k, v in ipairs(fw:get_zones()) do -%>
<option<%=ifattr(v:name() == "wan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option>
<%- end %>
</select>
</div>
<div class="td">
<select class="cbi-input-text" id="_newfwd.dest" name="_newfwd.dest">
<% local k, v; for k, v in ipairs(fw:get_zones()) do -%>
<option<%=ifattr(v:name() == "lan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option>
<%- end %>
</select>
</div>
<div class="td bottom">
<input type="submit" class="cbi-button cbi-button-link" name="_newfwd.submit" value="<%:Add and edit...%>" />
</div>
</div>
</div>
<% else %>
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
<% end %>
<% if #zones > 0 then %>
<script type="text/javascript">//<![CDATA[
cbi_validate_field('_newopen.extport', true, 'list(neg(portrange))');
document.getElementById('_newopen.extport').addEventListener('blur',
function() {
var n = document.getElementById('_newopen.name');
var p = document.getElementById('_newopen.proto');
if (!this.className.match(/invalid/))
{
if (!n.value && this.value)
{
n.value = 'Open' + this.value;
}
}
});
//]]></script>
<% end %>

View file

@ -0,0 +1,59 @@
<%
local fw = require "luci.model.firewall".init()
local nw = require "luci.model.network".init()
local zones = fw:get_zones()
local keys, vals, a, k, v = {}, {}
for k, v in ipairs(nw:get_interfaces()) do
for k, a in ipairs(v:ipaddrs()) do
keys[#keys+1] = a:host():string()
vals[#vals+1] = '%s (%s)' %{ a:host(), v:shortname() }
end
end
%>
<% if #zones > 1 then %>
<h4><%:New source NAT%></h4>
<div class="table">
<div class="tr cbi-section-table-titles">
<div class="th"><%:Name%></div>
<div class="th"><%:Source zone%></div>
<div class="th"><%:Destination zone%></div>
<div class="th"><%:To source IP%></div>
<div class="th"><%:To source port%></div>
<div class="th"></div>
</div>
<div class="tr">
<div class="td">
<input type="text" class="cbi-input-text" id="_newsnat.name" name="_newsnat.name" placeholder="<%:New SNAT rule%>" />
</div>
<div class="td">
<select class="cbi-input-text" id="_newsnat.src" name="_newsnat.src">
<% local k, v; for k, v in ipairs(fw:get_zones()) do -%>
<option<%=ifattr(v:name() == "lan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option>
<%- end %>
</select>
</div>
<div class="td">
<select class="cbi-input-text" id="_newsnat.dest" name="_newsnat.dest">
<% local k, v; for k, v in ipairs(fw:get_zones()) do -%>
<option<%=ifattr(v:name() == "wan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option>
<%- end %>
</select>
</div>
<div class="td">
<input type="text" class="cbi-input-text" id="_newsnat.dip" name="_newsnat.dip" placeholder="<%:Do not rewrite%>" data-type="ip4addr" data-optional="true"<%=
ifattr(#keys > 0, "data-choices", { keys, vals })
%> />
</div>
<div class="td">
<input type="text" class="cbi-input-text" id="_newsnat.dport" name="_newsnat.dport" placeholder="<%:Do not rewrite%>" data-type="portrange" data-optional="true" />
</div>
<div class="td bottom">
<input type="submit" class="cbi-button cbi-button-link" name="_newsnat.submit" value="<%:Add and edit...%>" />
</div>
</div>
</div>
<% else %>
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
<% end %>

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