mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-05 01:44:16 +08:00
⛄ Sync 2026-04-23 20:32:35
This commit is contained in:
1 parent
17738c6f79
commit
fe51d2b304
206 files changed
+725671
No files matched your search
@@ -0,0 +1,594 @@
|
||||
'use strict';
|
||||
'require uci';
|
||||
'require rpc';
|
||||
'require tools.prng as random';
|
||||
|
||||
|
||||
/**
|
||||
* Load the firewall configuration.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function initFirewallState() {
|
||||
return L.resolveDefault(uci.load('firewall'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an enum value.
|
||||
* @param {?string} s
|
||||
* @param {Array<string>} values
|
||||
* @returns {string}
|
||||
*/
|
||||
function parseEnum(s, values) {
|
||||
if (s == null)
|
||||
return null;
|
||||
|
||||
s = String(s).toUpperCase();
|
||||
|
||||
if (s == '')
|
||||
return null;
|
||||
|
||||
for (var i = 0; i < values.length; i++)
|
||||
if (values[i].toUpperCase().indexOf(s) == 0)
|
||||
return values[i];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a policy value, or defaultValue if not found.
|
||||
* @param {?string} s
|
||||
* @param {Array<string>} [defaultValue=['DROP', 'REJECT', 'ACCEPT']]
|
||||
* @returns {?string}
|
||||
*/
|
||||
function parsePolicy(s, defaultValue) {
|
||||
return parseEnum(s, ['DROP', 'REJECT', 'ACCEPT']) || (arguments.length < 2 ? null : defaultValue);
|
||||
}
|
||||
|
||||
|
||||
var Firewall, AbstractFirewallItem, Defaults, Zone, Forwarding, Redirect, Rule;
|
||||
|
||||
/**
|
||||
* Look up a firewall zone.
|
||||
* @param {?string} name
|
||||
* @returns {?Zone}
|
||||
*/
|
||||
function lookupZone(name) {
|
||||
var z = uci.get('firewall', name);
|
||||
|
||||
if (z != null && z['.type'] == 'zone')
|
||||
return new Zone(z['.name']);
|
||||
|
||||
var sections = uci.sections('firewall', 'zone');
|
||||
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
if (sections[i].name != name)
|
||||
continue;
|
||||
|
||||
return new Zone(sections[i]['.name']);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a colour for a name.
|
||||
* @param {?string} forName
|
||||
* @returns {string}
|
||||
*/
|
||||
function getColorForName(forName) {
|
||||
if (forName == null)
|
||||
return '#eeeeee';
|
||||
else if (forName == 'lan')
|
||||
return '#90f090';
|
||||
else if (forName == 'wan')
|
||||
return '#f09090';
|
||||
|
||||
return random.derive_color(forName);
|
||||
}
|
||||
|
||||
|
||||
Firewall = L.Class.extend({
|
||||
getDefaults: function() {
|
||||
return initFirewallState().then(function() {
|
||||
return new Defaults();
|
||||
});
|
||||
},
|
||||
|
||||
newZone: function() {
|
||||
return initFirewallState().then(L.bind(async function() {
|
||||
var name = 'newzone',
|
||||
count = 1;
|
||||
|
||||
while ((await this.getZone(name)) != null)
|
||||
name = 'newzone%d'.format(++count);
|
||||
|
||||
return this.addZone(name);
|
||||
}, this));
|
||||
},
|
||||
|
||||
addZone: function(name) {
|
||||
return initFirewallState().then(L.bind(function() {
|
||||
if (name == null || !/^[a-zA-Z0-9_]+$/.test(name))
|
||||
return null;
|
||||
|
||||
if (lookupZone(name) != null)
|
||||
return null;
|
||||
|
||||
var d = new Defaults(),
|
||||
z = uci.add('firewall', 'zone');
|
||||
|
||||
uci.set('firewall', z, 'name', name);
|
||||
uci.set('firewall', z, 'input', d.getInput() || 'DROP');
|
||||
uci.set('firewall', z, 'output', d.getOutput() || 'DROP');
|
||||
uci.set('firewall', z, 'forward', d.getForward() || 'DROP');
|
||||
|
||||
return new Zone(z);
|
||||
}, this));
|
||||
},
|
||||
|
||||
getZone: function(name) {
|
||||
return initFirewallState().then(function() {
|
||||
return lookupZone(name);
|
||||
});
|
||||
},
|
||||
|
||||
getZones: function() {
|
||||
return initFirewallState().then(function() {
|
||||
const sections = uci.sections('firewall', 'zone');
|
||||
const zones = [];
|
||||
|
||||
for (let s of sections)
|
||||
zones.push(new Zone(s['.name']));
|
||||
|
||||
zones.sort(function(a, b) { return L.naturalCompare(a.getName() || '', b.getName() || '') });
|
||||
|
||||
return zones;
|
||||
});
|
||||
},
|
||||
|
||||
getZoneByNetwork: function(network) {
|
||||
return initFirewallState().then(function() {
|
||||
const sections = uci.sections('firewall', 'zone');
|
||||
|
||||
for (let s of sections)
|
||||
if (L.toArray(s.network).indexOf(network) != -1)
|
||||
return new Zone(s['.name']);
|
||||
|
||||
return null;
|
||||
});
|
||||
},
|
||||
|
||||
deleteZone: function(name) {
|
||||
return initFirewallState().then(function() {
|
||||
const section = uci.get('firewall', name);
|
||||
let found = false;
|
||||
|
||||
if (section != null && section['.type'] == 'zone') {
|
||||
found = true;
|
||||
name = section.name;
|
||||
uci.remove('firewall', section['.name']);
|
||||
}
|
||||
else if (name != null) {
|
||||
const sections = uci.sections('firewall', 'zone');
|
||||
|
||||
for (let s of sections) {
|
||||
if (s.name != name)
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
uci.remove('firewall', s['.name']);
|
||||
}
|
||||
}
|
||||
|
||||
if (found == true) {
|
||||
const sections = uci.sections('firewall');
|
||||
|
||||
for (let s of sections) {
|
||||
if (s['.type'] != 'rule' &&
|
||||
s['.type'] != 'redirect' &&
|
||||
s['.type'] != 'forwarding')
|
||||
continue;
|
||||
|
||||
if (s.src == name || s.dest == name)
|
||||
uci.remove('firewall', s['.name']);
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
});
|
||||
},
|
||||
|
||||
renameZone: function(oldName, newName) {
|
||||
return initFirewallState().then(L.bind(function() {
|
||||
if (oldName == null || newName == null || !/^[a-zA-Z0-9_]+$/.test(newName))
|
||||
return false;
|
||||
|
||||
if (lookupZone(newName) != null)
|
||||
return false;
|
||||
|
||||
const sections = uci.sections('firewall', 'zone');
|
||||
let found = false;
|
||||
|
||||
for (let s of sections) {
|
||||
if (s.name != oldName)
|
||||
continue;
|
||||
|
||||
uci.set('firewall', s['.name'], 'name', newName);
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (found == true) {
|
||||
const sections = uci.sections('firewall');
|
||||
|
||||
for (let s of sections) {
|
||||
if (s['.type'] != 'rule' &&
|
||||
s['.type'] != 'redirect' &&
|
||||
s['.type'] != 'forwarding')
|
||||
continue;
|
||||
|
||||
if (s.src == oldName)
|
||||
uci.set('firewall', s['.name'], 'src', newName);
|
||||
|
||||
if (s.dest == oldName)
|
||||
uci.set('firewall', s['.name'], 'dest', newName);
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}, this));
|
||||
},
|
||||
|
||||
deleteNetwork: function(network) {
|
||||
return this.getZones().then(L.bind(function(zones) {
|
||||
var rv = false;
|
||||
|
||||
for (var i = 0; i < zones.length; i++)
|
||||
if (zones[i].deleteNetwork(network))
|
||||
rv = true;
|
||||
|
||||
return rv;
|
||||
}, this));
|
||||
},
|
||||
|
||||
getColorForName: getColorForName,
|
||||
|
||||
getZoneColorStyle: function(zone) {
|
||||
var hex = (zone instanceof Zone) ? zone.getColor() : getColorForName((zone != null && zone != '*') ? zone : null);
|
||||
|
||||
return '--zone-color-rgb:%d, %d, %d; background-color:rgb(var(--zone-color-rgb))'.format(
|
||||
parseInt(hex.substring(1, 3), 16),
|
||||
parseInt(hex.substring(3, 5), 16),
|
||||
parseInt(hex.substring(5, 7), 16)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
AbstractFirewallItem = L.Class.extend({
|
||||
get: function(option) {
|
||||
return uci.get('firewall', this.sid, option);
|
||||
},
|
||||
|
||||
set: function(option, value) {
|
||||
return uci.set('firewall', this.sid, option, value);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Defaults = AbstractFirewallItem.extend({
|
||||
__init__: function() {
|
||||
var sections = uci.sections('firewall', 'defaults');
|
||||
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
this.sid = sections[i]['.name'];
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.sid == null)
|
||||
this.sid = uci.add('firewall', 'defaults');
|
||||
},
|
||||
|
||||
isSynFlood: function() {
|
||||
return (this.get('syn_flood') == '1');
|
||||
},
|
||||
|
||||
isDropInvalid: function() {
|
||||
return (this.get('drop_invalid') == '1');
|
||||
},
|
||||
|
||||
getInput: function() {
|
||||
return parsePolicy(this.get('input'), 'DROP');
|
||||
},
|
||||
|
||||
getOutput: function() {
|
||||
return parsePolicy(this.get('output'), 'DROP');
|
||||
},
|
||||
|
||||
getForward: function() {
|
||||
return parsePolicy(this.get('forward'), 'DROP');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Zone = AbstractFirewallItem.extend({
|
||||
__init__: function(name) {
|
||||
var section = uci.get('firewall', name);
|
||||
|
||||
if (section != null && section['.type'] == 'zone') {
|
||||
this.sid = name;
|
||||
this.data = section;
|
||||
}
|
||||
else if (name != null) {
|
||||
var sections = uci.get('firewall', 'zone');
|
||||
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
if (sections[i].name != name)
|
||||
continue;
|
||||
|
||||
this.sid = sections[i]['.name'];
|
||||
this.data = sections[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
isMasquerade: function() {
|
||||
return (this.get('masq') == '1');
|
||||
},
|
||||
|
||||
getName: function() {
|
||||
return this.get('name');
|
||||
},
|
||||
|
||||
getNetwork: function() {
|
||||
return this.get('network');
|
||||
},
|
||||
|
||||
getInput: function() {
|
||||
return parsePolicy(this.get('input'), (new Defaults()).getInput());
|
||||
},
|
||||
|
||||
getOutput: function() {
|
||||
return parsePolicy(this.get('output'), (new Defaults()).getOutput());
|
||||
},
|
||||
|
||||
getForward: function() {
|
||||
return parsePolicy(this.get('forward'), (new Defaults()).getForward());
|
||||
},
|
||||
|
||||
addNetwork: function(network) {
|
||||
var section = uci.get('network', network);
|
||||
|
||||
if (section == null || section['.type'] != 'interface')
|
||||
return false;
|
||||
|
||||
var newNetworks = this.getNetworks();
|
||||
|
||||
if (newNetworks.filter(function(net) { return net == network }).length)
|
||||
return false;
|
||||
|
||||
newNetworks.push(network);
|
||||
this.set('network', newNetworks);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
deleteNetwork: function(network) {
|
||||
var oldNetworks = this.getNetworks(),
|
||||
newNetworks = oldNetworks.filter(function(net) { return net != network });
|
||||
|
||||
if (newNetworks.length > 0)
|
||||
this.set('network', newNetworks);
|
||||
else
|
||||
this.set('network', null);
|
||||
|
||||
return (newNetworks.length < oldNetworks.length);
|
||||
},
|
||||
|
||||
getNetworks: function() {
|
||||
return L.toArray(this.get('network'));
|
||||
},
|
||||
|
||||
clearNetworks: function() {
|
||||
this.set('network', null);
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return L.toArray(this.get('device'));
|
||||
},
|
||||
|
||||
getSubnets: function() {
|
||||
return L.toArray(this.get('subnet'));
|
||||
},
|
||||
|
||||
getForwardingsBy: function(what) {
|
||||
var sections = uci.sections('firewall', 'forwarding'),
|
||||
forwards = [];
|
||||
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
if (sections[i].src == null || sections[i].dest == null)
|
||||
continue;
|
||||
|
||||
if (sections[i][what] != this.getName())
|
||||
continue;
|
||||
|
||||
forwards.push(new Forwarding(sections[i]['.name']));
|
||||
}
|
||||
|
||||
return forwards;
|
||||
},
|
||||
|
||||
addForwardingTo: function(dest) {
|
||||
var forwards = this.getForwardingsBy('src'),
|
||||
zone = lookupZone(dest);
|
||||
|
||||
if (zone == null || zone.getName() == this.getName())
|
||||
return null;
|
||||
|
||||
for (var i = 0; i < forwards.length; i++)
|
||||
if (forwards[i].getDestination() == zone.getName())
|
||||
return null;
|
||||
|
||||
var sid = uci.add('firewall', 'forwarding');
|
||||
|
||||
uci.set('firewall', sid, 'src', this.getName());
|
||||
uci.set('firewall', sid, 'dest', zone.getName());
|
||||
|
||||
return new Forwarding(sid);
|
||||
},
|
||||
|
||||
addForwardingFrom: function(src) {
|
||||
var forwards = this.getForwardingsBy('dest'),
|
||||
zone = lookupZone(src);
|
||||
|
||||
if (zone == null || zone.getName() == this.getName())
|
||||
return null;
|
||||
|
||||
for (var i = 0; i < forwards.length; i++)
|
||||
if (forwards[i].getSource() == zone.getName())
|
||||
return null;
|
||||
|
||||
var sid = uci.add('firewall', 'forwarding');
|
||||
|
||||
uci.set('firewall', sid, 'src', zone.getName());
|
||||
uci.set('firewall', sid, 'dest', this.getName());
|
||||
|
||||
return new Forwarding(sid);
|
||||
},
|
||||
|
||||
deleteForwardingsBy: function(what) {
|
||||
var sections = uci.sections('firewall', 'forwarding'),
|
||||
found = false;
|
||||
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
if (sections[i].src == null || sections[i].dest == null)
|
||||
continue;
|
||||
|
||||
if (sections[i][what] != this.getName())
|
||||
continue;
|
||||
|
||||
uci.remove('firewall', sections[i]['.name']);
|
||||
found = true;
|
||||
}
|
||||
|
||||
return found;
|
||||
},
|
||||
|
||||
deleteForwarding: function(forwarding) {
|
||||
if (!(forwarding instanceof Forwarding))
|
||||
return false;
|
||||
|
||||
var section = uci.get('firewall', forwarding.sid);
|
||||
|
||||
if (!section || section['.type'] != 'forwarding')
|
||||
return false;
|
||||
|
||||
uci.remove('firewall', section['.name']);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
addRedirect: function(options) {
|
||||
var sid = uci.add('firewall', 'redirect');
|
||||
|
||||
if (options != null && typeof(options) == 'object')
|
||||
for (var key in options)
|
||||
if (options.hasOwnProperty(key))
|
||||
uci.set('firewall', sid, key, options[key]);
|
||||
|
||||
uci.set('firewall', sid, 'src', this.getName());
|
||||
|
||||
return new Redirect(sid);
|
||||
},
|
||||
|
||||
addRule: function(options) {
|
||||
var sid = uci.add('firewall', 'rule');
|
||||
|
||||
if (options != null && typeof(options) == 'object')
|
||||
for (var key in options)
|
||||
if (options.hasOwnProperty(key))
|
||||
uci.set('firewall', sid, key, options[key]);
|
||||
|
||||
uci.set('firewall', sid, 'src', this.getName());
|
||||
|
||||
return new Rule(sid);
|
||||
},
|
||||
|
||||
getColor: function(forName) {
|
||||
var name = (arguments.length > 0 ? forName : this.getName());
|
||||
|
||||
return getColorForName(name);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Forwarding = AbstractFirewallItem.extend({
|
||||
__init__: function(sid) {
|
||||
this.sid = sid;
|
||||
},
|
||||
|
||||
getSource: function() {
|
||||
return this.get('src');
|
||||
},
|
||||
|
||||
getDestination: function() {
|
||||
return this.get('dest');
|
||||
},
|
||||
|
||||
getSourceZone: function() {
|
||||
return lookupZone(this.getSource());
|
||||
},
|
||||
|
||||
getDestinationZone: function() {
|
||||
return lookupZone(this.getDestination());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Rule = AbstractFirewallItem.extend({
|
||||
__init__: function(sid) {
|
||||
this.sid = sid;
|
||||
},
|
||||
|
||||
getSource: function() {
|
||||
return this.get('src');
|
||||
},
|
||||
|
||||
getDestination: function() {
|
||||
return this.get('dest');
|
||||
},
|
||||
|
||||
getSourceZone: function() {
|
||||
return lookupZone(this.getSource());
|
||||
},
|
||||
|
||||
getDestinationZone: function() {
|
||||
return lookupZone(this.getDestination());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Redirect = AbstractFirewallItem.extend({
|
||||
__init__: function(sid) {
|
||||
this.sid = sid;
|
||||
},
|
||||
|
||||
getSource: function() {
|
||||
return this.get('src');
|
||||
},
|
||||
|
||||
getDestination: function() {
|
||||
return this.get('dest');
|
||||
},
|
||||
|
||||
getSourceZone: function() {
|
||||
return lookupZone(this.getSource());
|
||||
},
|
||||
|
||||
getDestinationZone: function() {
|
||||
return lookupZone(this.getDestination());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return Firewall;
|
||||
Reference in new issue
Block a user