diff --git a/README.md b/README.md index eaec700..4399376 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This package provides easy IP based access control. This can be achieved either [![Build Status](https://secure.travis-ci.org/baminteractive/node-ipfilter.png?branch=master)](http://travis-ci.org/baminteractive/node-ipfilter) ## Version -0.0.6 +0.0.7 ## Installation @@ -53,13 +53,6 @@ app.listen(3000); Using CIDR subnet masks for ranges: ```javascript -// Init dependencies -var express = require('express') - , ipfilter = require('ipfilter') - , app = express.createServer() - ; - -// Blacklist the following IPs var ips = ['127.0.0.1/24']; // Create the server @@ -67,8 +60,22 @@ app.use(ipfilter(ips, {mode: 'allow'})); app.listen(3000); ``` +Using IP ranges: + +```javascript +var ips = [['127.0.0.1','127.0.0.10']]; + +// Create the server +app.use(ipfilter(ips, {mode: 'allow'})); +app.listen(3000); +``` + ## Changelog +0.0.7 + +* Add support ip ranges. + 0.0.6 * Fixed a bug when using console output diff --git a/lib/ipfilter.js b/lib/ipfilter.js index ccb8a93..f0f1e79 100644 --- a/lib/ipfilter.js +++ b/lib/ipfilter.js @@ -8,7 +8,7 @@ /** * Module dependencies. */ -var _ = require('underscore') +var _ = require('lodash') , iputil = require('ip') , Netmask = require('netmask').Netmask; @@ -47,6 +47,7 @@ var _ = require('underscore') , errorMessage: 'Unauthorized' , allowPrivateIPs: false , cidr: false + , ranges: false }); var getClientIp = function(req) { @@ -85,6 +86,21 @@ var _ = require('underscore') isPrivateIpOkay = settings.allowPrivateIPs && iputil.isPrivate(ip); } } + }else if(settings.ranges){ + var filteredSet = _.filter(ips,function(ipSet){ + if(ipSet.length > 1){ + var startIp = iputil.toLong(ipSet[0]); + var endIp = iputil.toLong(ipSet[1]); + var longIp = iputil.toLong(ip); + return longIp >= startIp && longIp <= endIp; + }else{ + return ip == ipSet[0]; + } + }); + + allowedIp = (mode == 'allow' && filteredSet.length > 0); + notBannedIp = (mode == 'deny' && filteredSet.length === 0); + isPrivateIpOkay = settings.allowPrivateIPs && iputil.isPrivate(ip) && !(mode == 'deny' && filteredSet.length > 0); }else{ allowedIp = (mode == 'allow' && ips.indexOf(ip) !== -1); notBannedIp = (mode == 'deny' && ips.indexOf(ip) === -1); diff --git a/package.json b/package.json index cef9a82..5d64bd5 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "express-ipfilter", "description": "A light-weight IP address based filtering system", - "version": "0.0.6", + "version": "0.0.7", "author": "BaM Interactive", "dependencies": { - "underscore": "1.3.3", "netmask": "~1.0.4", - "ip": "~0.3.0" + "ip": "~0.3.0", + "lodash": "~2.4.1" }, "devDependencies": { "mocha": "~1.4.2" diff --git a/test.js b/test.js index 9557e85..73a9897 100644 --- a/test.js +++ b/test.js @@ -233,3 +233,162 @@ describe('using cidr block',function(){ }); }); }); + +describe('using ranges',function(){ + describe('enforcing whitelist restrictions',function(){ + beforeEach(function(){ + // Ip range: 127.0.0.1 - 127.0.0.14 + this.ipfilter = ipfilter([ ['127.0.0.1','127.0.0.3'] ], { ranges: true, log: false, mode: 'allow' }); + this.req = { + session: {}, + headers: [], + connection: { + remoteAddress: '' + } + }; + }); + + it('should allow whitelisted ips', function( done ){ + this.req.connection.remoteAddress = '127.0.0.1'; + this.ipfilter( this.req, {}, function(){ + done(); + }); + }); + + it('should allow whitelisted forwarded ips', function( done ){ + this.req.headers['x-forwarded-for'] = '127.0.0.1'; + this.ipfilter( this.req, {}, function(){ + done(); + }); + }); + + it('should deny all non-whitelisted ips', function( done ){ + this.req.connection.remoteAddress = '127.0.0.17'; + var res = { + end: function(msg){ + assert.equal( 401, res.statusCode ); + done(); + } + }; + + this.ipfilter( this.req, res, function(){}); + }); + + it('should deny all non-whitelisted forwarded ips', function( done ){ + this.req.headers['x-forwarded-for'] = '127.0.0.17'; + var res = { + end: function(msg){ + assert.equal( 401, res.statusCode ); + done(); + } + }; + + this.ipfilter( this.req, res, function(){}); + }); + }); + + describe('enforcing ip restrictions with only one ip in the range',function(){ + beforeEach(function(){ + // Ip range: 127.0.0.1 - 127.0.0.14 + this.ipfilter = ipfilter([ ['127.0.0.1'] ], { ranges: true, log: false, mode: 'allow' }); + this.req = { + session: {}, + headers: [], + connection: { + remoteAddress: '' + } + }; + }); + + it('should allow whitelisted ips', function( done ){ + this.req.connection.remoteAddress = '127.0.0.1'; + this.ipfilter( this.req, {}, function(){ + done(); + }); + }); + + it('should deny all non-whitelisted ips', function( done ){ + this.req.connection.remoteAddress = '127.0.0.17'; + var res = { + end: function(msg){ + assert.equal( 401, res.statusCode ); + done(); + } + }; + + this.ipfilter( this.req, res, function(){}); + }); + }); + + describe('enforcing IP address blacklist restrictions', function(){ + + beforeEach(function(){ + this.ipfilter = ipfilter([ ['127.0.0.1','127.0.0.3'] ], { ranges: true, log: false }); + this.req = { + session: {}, + headers: [], + connection: { + remoteAddress: '' + } + }; + }); + + it('should allow all non-blacklisted ips', function( done ){ + this.req.connection.remoteAddress = '127.0.0.17'; + this.ipfilter( this.req, {}, function(){ + done(); + }); + }); + + it('should allow all non-blacklisted forwarded ips', function( done ){ + this.req.headers['x-forwarded-for'] = '127.0.0.17'; + this.ipfilter( this.req, {}, function(){ + done(); + }); + }); + + it('should deny all blacklisted ips', function( done ){ + this.req.connection.remoteAddress = '127.0.0.1'; + var res = { + end: function(msg){ + assert.equal( 401, res.statusCode ); + done(); + } + }; + + this.ipfilter( this.req, res, function(){}); + }); + + it('should deny all blacklisted forwarded ips', function( done ){ + this.req.headers['x-forwarded-for'] = '127.0.0.1'; + var res = { + end: function(msg){ + assert.equal( 401, res.statusCode ); + done(); + } + }; + + this.ipfilter( this.req, res, function(){}); + }); + }); + + describe("enforcing private ip restrictions",function(){ + beforeEach(function(){ + this.ipfilter = ipfilter([ ['127.0.0.1','127.0.0.3'] ], { ranges: true, log: false, allowPrivateIPs: true }); + this.req = { + session: {}, + headers: [], + connection: { + remoteAddress: '' + } + }; + }); + + it('should allow all private ips', function( done ){ + this.req.connection.remoteAddress = '10.0.0.0'; + this.ipfilter( this.req, {}, function(){ + done(); + }); + }); + }); +});