Skip to content

Instantly share code, notes, and snippets.

@crimeminister
Created March 20, 2014 19:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save crimeminister/9672525 to your computer and use it in GitHub Desktop.
Save crimeminister/9672525 to your computer and use it in GitHub Desktop.
Express middleware for IP-based access control
'use strict';
var _ = require('lodash');
var keystone = require('keystone');
var range_check = require('range_check');
var util = require('util');
/**
*
*/
exports.ipRangeRestrict = function (req, res, next) {
// Require that ALLOWED_IP_RANGES be set in the environment.
if (_.isUndefined(process.env.ALLOWED_IP_RANGES)) {
throw 'Allowed IP range is not defined';
}
var allowedRanges = process.env.ALLOWED_IP_RANGES.split(/\s+|,/);
// Regular expression for matching IPv4 CIDR ranges.
var cidr = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(\d|[1-2]\d|3[0-2]))$/;
// The set of allowed ranges has to be separated by space or comma
// characters.
allowedRanges = _(allowedRanges)
.filter(function (range) {
return _.isString(range) && range.match(cidr);
})
.value();
// Using req.ips requires that express 'trust proxy' setting is
// true. When it *is* set the value for ips is extracted from the
// X-Forwarded-For request header. The originating IP address is
// the last one in the array.
var requestIP = (req.ips.length > 0) ? req.ips.slice().pop() : req.ip;
// Deny the request if request IP is not in one of the allowed
// IP address range.
var requestAllowed = range_check.in_range(req.ip, allowedRanges);
if (!requestAllowed) {
var msg = '-> blocked request from %s (not in allowed IP range)';
console.log(util.format(msg, req.ip));
// Display error page to the user
var title = 'Sorry, your request is not authorized (403)';
var message = 'Requests from outside permitted IP range are not allowed';
res.status(403).render('errors/403', {
title: title,
message: message
});
}
next();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment