@aikidosec/firewall
Version:
Zen by Aikido is an embedded Application Firewall that autonomously protects Node.js apps against common and critical attacks, provides rate limiting, detects malicious traffic (including bots), and more.
144 lines (143 loc) • 4.58 kB
JavaScript
"use strict";
// Based on https://github.com/demskie/netparser
// MIT License - Copyright (c) 2019 alex
Object.defineProperty(exports, "__esModule", { value: true });
exports.Network = void 0;
const parse = require("./parse");
const Address_1 = require("./Address");
const BEFORE = -1;
const EQUALS = 0;
const AFTER = 1;
class Network {
constructor(network) {
this.addr = new Address_1.Address();
this.netbits = -1;
if (network) {
const net = parse.network(network);
if (net) {
this.addr.setBytes(net.bytes);
this.netbits = net.cidr;
}
}
}
destroy() {
if (!this.addr.isValid()) {
this.addr.destroy();
}
this.netbits = -1;
return this;
}
cidr() {
if (this.isValid()) {
return this.netbits;
}
return Number.NaN;
}
isValid() {
return this.addr.isValid() && this.netbits !== -1;
}
duplicate() {
const network = new Network();
if (this.isValid()) {
network.addr.setBytes(this.addr.bytes().slice());
network.netbits = this.netbits;
}
return network;
}
next() {
this.addr.increase(this.netbits);
return this;
}
setCIDR(cidr) {
if (!this.addr.isValid()) {
this.destroy();
}
else {
cidr = Math.floor(cidr);
if (cidr >= 0 && cidr <= this.addr.bytes().length * 8) {
this.netbits = cidr;
}
else {
this.destroy();
}
}
return this;
}
compare(network) {
// check that both networks are valid
if (!this.isValid() || !network.isValid())
return null;
// compare addresses
const cmp = this.addr.compare(network.addr);
if (cmp !== EQUALS)
return cmp;
// compare subnet mask length
if (this.netbits < network.netbits)
return BEFORE;
if (this.netbits > network.netbits)
return AFTER;
// otherwise they must be equal
return EQUALS;
}
contains(network) {
// check that both networks are valid
if (!this.isValid() || !network.isValid())
return false;
// ensure that both IPs are of the same type
if (this.addr.bytes().length !== network.addr.bytes().length)
return false;
// handle edge cases
if (this.netbits === 0)
return true;
if (network.netbits === 0)
return false;
// our base address should be less than or equal to the other base address
if (this.addr.compare(network.addr) === AFTER)
return false;
// get the next network address for both
const next = this.duplicate().next();
const otherNext = network.duplicate().next();
// handle edge case where our next network address overflows
if (!next.isValid())
return true;
// our address should be more than or equal to the other address
if (next.addr.compare(otherNext.addr) === BEFORE)
return false;
// must be a child subnet
return true;
}
adjacent(network) {
// check that both networks are valid
if (!this.isValid() || !network.isValid())
return false;
// ensure that both IPs are of the same type
if (this.addr.bytes().length !== network.addr.bytes().length)
return false;
// handle edge cases
if (this.netbits === 0 || network.netbits === 0)
return true;
const cmp = this.addr.compare(network.addr);
if (cmp === EQUALS)
return false;
// ensure that alpha addr contains the baseAddress that comes first
let alpha, bravo;
if (cmp === BEFORE) {
alpha = this.duplicate().next();
bravo = network;
}
else {
alpha = network.duplicate().next();
// eslint-disable-next-line @typescript-eslint/no-this-alias
bravo = this;
}
// if alpha overflows then an adjacency is not possible
if (!alpha.isValid())
return false;
// alpha addr should equal bravo for them to be perfectly adjacent
if (alpha.addr.compare(bravo.addr) === EQUALS)
return true;
// otherwise we aren't adjacent
return false;
}
}
exports.Network = Network;