express-ipfilter-secured
Version:
A light-weight IP address based filtering system
217 lines (182 loc) • 5.58 kB
JavaScript
/*!
* Express - IP Filter
* Copyright(c) 2014 Bradley and Montgomery Inc.
* MIT Licensed
*/
;
/**
* Module dependencies.
*/
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _ = require('lodash');
var iputil = require('ip');
var rangeCheck = require('range_check');
var IpDeniedError = require('./deniedError');
/**
* express-ipfilter:
*
* IP Filtering middleware;
*
* Examples:
*
* var ipfilter = require('ipfilter'),
* ips = ['127.0.0.1'];
* getIps = function() { return ['127.0.0.1']; };
*
* app.use(ipfilter(ips));
* app.use(ipfilter(getIps));
*
* Options:
*
* - `mode` whether to deny or grant access to the IPs provided. Defaults to 'deny'.
* - `logF` Function to use for logging.
* - `log` console log actions. Defaults to true.
* - `allowPrivateIPs` whether to allow private IPs.
* - `allowedHeaders` Array of headers to check for forwarded IPs.
* - 'excluding' routes that should be excluded from ip filtering
*
* @param [ips] {Array} IP addresses or {Function} that returns the array of IP addresses
* @param [opts] {Object} options
* @api public
*/
module.exports = function ipfilter(ips, opts) {
ips = ips || false;
var getIps = _.isFunction(ips) ? ips : function () {
return ips;
};
var logger = function logger(message) {
console.log(message);
};
var settings = _.defaults(opts || {}, {
mode: 'deny',
log: true,
logF: logger,
allowedHeaders: [],
allowPrivateIPs: false,
excluding: [],
detectIp: getClientIp
});
function getClientIp(req) {
var ipAddress;
var headerIp = _.reduce(settings.allowedHeaders, function (acc, header) {
var testIp = req.headers[header];
if (testIp != '') {
acc = testIp;
}
return acc;
}, '');
if (headerIp) {
var splitHeaderIp = headerIp.split(',');
ipAddress = splitHeaderIp[0];
}
if (!ipAddress) {
ipAddress = req.connection.remoteAddress;
}
if (!ipAddress) {
return '';
}
if (iputil.isV6Format(ipAddress) && ~ipAddress.indexOf('::ffff')) {
ipAddress = ipAddress.split('::ffff:')[1];
}
if (iputil.isV4Format(ipAddress) && ~ipAddress.indexOf(':')) {
ipAddress = ipAddress.split(':')[0];
}
return ipAddress;
}
var matchClientIp = function matchClientIp(ip) {
var mode = settings.mode.toLowerCase();
var result = _.invokeMap(getIps(), testIp, ip, mode);
if (mode === 'allow') {
return _.some(result);
} else {
return _.every(result);
}
};
var testIp = function testIp(ip, mode) {
var constraint = this;
// Check if it is an array or a string
if (typeof constraint === 'string') {
if (rangeCheck.validRange(constraint)) {
return testCidrBlock(ip, constraint, mode);
} else {
return testExplicitIp(ip, constraint, mode);
}
}
if ((typeof constraint === 'undefined' ? 'undefined' : _typeof(constraint)) === 'object') {
return testRange(ip, constraint, mode);
}
};
var testExplicitIp = function testExplicitIp(ip, constraint, mode) {
if (ip === constraint) {
return mode === 'allow';
} else {
return mode === 'deny';
}
};
var testCidrBlock = function testCidrBlock(ip, constraint, mode) {
if (rangeCheck.inRange(ip, constraint)) {
return mode === 'allow';
} else {
return mode === 'deny';
}
};
var testRange = function testRange(ip, constraint, mode) {
var filteredSet = _.filter(getIps(), function (constraint) {
if (constraint.length > 1) {
var startIp = iputil.toLong(constraint[0]);
var endIp = iputil.toLong(constraint[1]);
var longIp = iputil.toLong(ip);
return longIp >= startIp && longIp <= endIp;
} else {
return ip === constraint[0];
}
});
if (filteredSet.length > 0) {
return mode === 'allow';
} else {
return mode === 'deny';
}
};
var error = function error(ip, next) {
var err = new IpDeniedError('Access denied to IP address: ' + ip);
return next(err);
};
return function (req, res, next) {
if (settings.excluding.length > 0) {
var results = _.filter(settings.excluding, function (exclude) {
var regex = new RegExp(exclude);
return regex.test(req.url);
});
if (results.length > 0) {
if (settings.log && settings.logLevel !== 'deny') {
settings.logF('Access granted for excluded path: ' + results[0]);
}
return next();
}
}
var _ips = getIps();
if (!_ips || !_ips.length) {
if (settings.mode == 'allow') {
// ip list is empty, thus no one allowed
return error('0.0.0.0/0', next);
} else {
// there are no blocked ips, skip
return next();
}
}
var ip = settings.detectIp(req);
if (matchClientIp(ip, req)) {
// Grant access
if (settings.log && settings.logLevel !== 'deny') {
settings.logF('Access granted to IP address: ' + ip);
}
return next();
}
// Deny access
if (settings.log && settings.logLevel !== 'allow') {
settings.logF('Access denied to IP address: ' + ip);
}
return error(ip, next);
};
};
//# sourceMappingURL=ipfilter.js.map