Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,27 @@ The rules object contains a set of key-value pairs mapping a regex-supported url
## Other Notes
* `(?:\\W|$)` is appended to the end of the regex-supported url path, so that if there is a key like `.*/test` in the rules, the module matches paths `/test`, `/test/`, `/test?` but not `/testing`.
* As long as object keys continued to be ordered in V8, if there are multiple rules that match against a given url path, the module will pick the matching rule listed first for the translation.

## IP Whitelisting
At times there is a need to block proxy requests from ip addresses you have not already whitelisted. To support this use case you may now provide an object to apply additional 'rules' for proxying.


```js
// Set up proxy rules instance
var proxyRules = new HttpProxyRules({
rules: {
'.*/ipTest1/': {
'whitelist': [ // only allow whitelist
"127.0.0.1" // Explicit IP Address Whitelisted
],
'target': 'http://localhost:8080/cool3/'
},
'.*/ipTest2/': {
'whitelist': [ // only allow whitelist
"8.8.8.0/24" //CIDR IP Range notation
],
'target': 'http://localhost:8080/cool4/'
},

```
Note the two options available. You may provide an IP address to allow or you may also provide Classless Inter-Doman Routing notation. For more information on CIDR notation see the wikipedia article [https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation]
22 changes: 20 additions & 2 deletions example/simple.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,25 @@ module.exports = function spawnReverseProxy(cb) {
var proxyRules = new HttpProxyRules({
rules: {
'.*/test': 'http://localhost:8080/cool', // Rule (1)
'.*/test2/': 'http://localhost:8080/cool2/' // Rule (2)
'.*/test2/': 'http://localhost:8080/cool2/', // Rule (2)
'.*/ipTest1/': { // Rule (3)
'whitelist': [
"127.0.0.1/24" // only allow whitelist
],
'target': 'http://localhost:8080/cool3/'
},
'.*/ipTest2/': { // Rule (4)
'whitelist': [
"8.8.8.0/24" // only allow whitelist
],
'target': 'http://localhost:8080/cool4/'
},
'.*/ipTest3/': { // Rule (5)
'whitelist': [
"127.0.0.1" // only allow whitelist
],
'target': 'http://localhost:8080/cool5/'
}
},
default: 'http://localhost:8080' // default target
});
Expand All @@ -32,6 +50,6 @@ module.exports = function spawnReverseProxy(cb) {

res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('The request url and path did not match any of the listed rules!');
}).listen(6010, cb);
}).listen(6010, '0.0.0.0', cb);

};
26 changes: 23 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@

var rangeCheck = require('range_check');
var requestIp = require('request-ip');
/**
* This is a constructor for a HttpProxyRules instance.
* @param {Object} options Takes in a `rules` obj, (optional) `default` target
*/
function HttpProxyRules(options) {
this.rules = options.rules;
this.default = options.default || null;

return this;
};

Expand Down Expand Up @@ -41,7 +42,26 @@ HttpProxyRules.prototype.match = function match(req) {
if (testPrefixMatch && testPrefixMatch.index === 0) {
urlPrefix = pathEndsWithSlash ? testPrefixMatch[0] : testPrefixMatch[1];
req.url = path.replace(urlPrefix, '');
target = rules[pathPrefix];
// Check to see if value of key value pair is an object
if (typeof rules[pathPrefix] === 'object') {
// Check to see if there is ip matching logic in place
var ip = requestIp.getClientIp(req);
if (rules[pathPrefix].whitelist) {
for (var range in rules[pathPrefix].whitelist) {
if (rules[pathPrefix].whitelist.hasOwnProperty(range)) {
if ((rules[pathPrefix].whitelist[range].indexOf('/') > -1 && rangeCheck.inRange(ip, rules[pathPrefix].whitelist[range]))
|| (rules[pathPrefix].whitelist[range] === ip)) {
target = rules[pathPrefix].target;
}
}
}
} else {
target = rules[pathPrefix].target;
}
} else {
target = rules[pathPrefix];
}

break;
}
}
Expand Down
13 changes: 12 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,16 @@
"mocha": "^2.3.4",
"request": "^2.67.0"
},
"keywords": ["node-http-proxy", "http-proxy", "http-proxy-table", "proxy-table", "proxy-rules", "proxy"]
"keywords": [
"node-http-proxy",
"http-proxy",
"http-proxy-table",
"proxy-table",
"proxy-rules",
"proxy"
],
"dependencies": {
"range_check": "^1.2.0",
"request-ip": "^1.1.4"
}
}
36 changes: 35 additions & 1 deletion test/index.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('Proxy Routes', function () {
// response includes the url that you tried to access
translatedPath: req.url
}));
}).listen(targetPort, function mockServerReady() {
}).listen(targetPort, '0.0.0.0', function mockServerReady() {
spawnReverseProxy(function proxyServerReady() {
done(); // call done to start running test suite
});
Expand All @@ -32,6 +32,40 @@ describe('Proxy Routes', function () {
// runs after all tests in this block
done();
});

it('should allow whitelisted ipv4 and deny non-whitelisted ipv4 addresses', function(done) {
async.parallel([
function(cb) {
request({
url: 'http://127.0.0.1:' + proxyServerPort + "/ipTest1/",
json: true
}, function processResp(err, res, body) {
expect(res.statusCode).to.equal(200);
cb();
});
},
function(cb) {
request({
url: 'http://127.0.0.1:' + proxyServerPort + "/ipTest2/",
json: true
}, function processResp(err, res, body) {
expect(body.translatedPath).to.not.equal('');
cb();
});
},
function(cb) {
request({
url: 'http://127.0.0.1:' + proxyServerPort + "/ipTest3/",
json: true
}, function processResp(err, res, body) {
expect(body.translatedPath).to.not.equal('');
cb();
});
}
], function(){
done();
});
});

it('should translate the url correctly', function (done) {

Expand Down