Add originBlacklist + originWhitelist

- originWhitelist resolves #24
- originBlacklist may help with #32
This commit is contained in:
Rob Wu
2015-08-16 01:05:26 +02:00
parent 7a138b36cc
commit 837dee582c
4 changed files with 94 additions and 0 deletions

View File

@@ -21,6 +21,7 @@ var port = process.env.PORT || 8080;
var cors_proxy = require('cors-anywhere');
cors_proxy.createServer({
originWhitelist: [], // Allow all origins
requireHeader: ['origin', 'x-requested-with'],
removeHeaders: ['cookie', 'cookie2']
}).listen(port, host, function() {
@@ -89,6 +90,11 @@ The module exports two properties: `getHandler` and `createServer`.
The following options are recognized by both methods:
* array of strings `originBlacklist` - If set, requests whose origin is listed are blocked.
Example: `['https://bad.example.com', 'http://bad.example.com']`
* array of strings `originWhitelist` - If set, requests whose origin is not listed are blocked.
If this list is empty, all origins are allowed.
Example: `['https://good.example.com', 'http://good.example.com']`
* array of strings `requireHeader` - If set, the request must include this header or the API will refuse to proxy.
Recommended if you want to prevent users from using the proxy for normal browsing.
Example: `['Origin', 'X-Requested-With']`.

View File

@@ -197,6 +197,8 @@ function parseURL(req_url) {
var getHandler = exports.getHandler = function(options, proxy) {
var corsAnywhere = {
maxRedirects: 5, // Maximum number of redirects to be followed.
originBlacklist: [], // Requests from these origins will be blocked.
originWhitelist: [], // If non-empty, requests not from an origin in this list will be blocked.
requireHeader: null, // Require a header to be set?
removeHeaders: [] // Strip these request headers
};
@@ -271,6 +273,19 @@ var getHandler = exports.getHandler = function(options, proxy) {
return;
}
var origin = req.headers.origin || '';
if (corsAnywhere.originBlacklist.indexOf(origin) >= 0) {
res.writeHead(403, 'Forbidden', cors_headers);
res.end('The origin "' + origin + '" was blacklisted by the operator of this proxy.');
return;
}
if (corsAnywhere.originWhitelist.length && corsAnywhere.originWhitelist.indexOf(origin) === -1) {
res.writeHead(403, 'Forbidden', cors_headers);
res.end('The origin "' + origin + '" was not whitelisted by the operator of this proxy.');
return;
}
var isRequestedOverHttps = req.connection.encrypted || /^\s*https/.test(req.headers['x-forwarded-proto']);
var proxyBaseUrl = (isRequestedOverHttps ? 'https://' : 'http://') + req.headers.host;

View File

@@ -2,8 +2,15 @@
var host = process.env.PORT ? '0.0.0.0' : '127.0.0.1';
var port = process.env.PORT || 8080;
// Grab the blacklist from the command-line so that we can update the blacklist without deploying
// again. CORS Anywhere is open by design, and this blacklist is not used, except for countering
// immediate abuse (e.g. denial of service). If you want to block all origins except for some,
// use originWhitelist instead.
var originBlacklist = (process.env.CORSANYWHERE_BLACKLIST || '').split(',');
var cors_proxy = require('./lib/cors-anywhere');
cors_proxy.createServer({
originBlacklist: originBlacklist,
requireHeader: ['origin', 'x-requested-with'],
removeHeaders: [
'cookie',

View File

@@ -345,6 +345,72 @@ describe('server on https', function() {
});
});
describe('originBlacklist', function() {
before(function() {
cors_anywhere = createServer({
originBlacklist: ['http://denied.origin.test'],
});
cors_anywhere_port = cors_anywhere.listen(0).address().port;
});
after(stopServer);
it('GET /example.com with denied origin', function(done) {
request(cors_anywhere)
.get('/example.com/')
.set('Origin', 'http://denied.origin.test')
.expect('Access-Control-Allow-Origin', '*')
.expect(403, done);
});
it('GET /example.com without denied origin', function(done) {
request(cors_anywhere)
.get('/example.com/')
.set('Origin', 'https://denied.origin.test') // Note: different scheme!
.expect('Access-Control-Allow-Origin', '*')
.expect(200, done);
});
it('GET /example.com without origin', function(done) {
request(cors_anywhere)
.get('/example.com/')
.expect('Access-Control-Allow-Origin', '*')
.expect(200, done);
});
});
describe('originWhitelist', function() {
before(function() {
cors_anywhere = createServer({
originWhitelist: ['https://permitted.origin.test'],
});
cors_anywhere_port = cors_anywhere.listen(0).address().port;
});
after(stopServer);
it('GET /example.com with permitted origin', function(done) {
request(cors_anywhere)
.get('/example.com/')
.set('Origin', 'https://permitted.origin.test')
.expect('Access-Control-Allow-Origin', '*')
.expect(200, done);
});
it('GET /example.com without permitted origin', function(done) {
request(cors_anywhere)
.get('/example.com/')
.set('Origin', 'http://permitted.origin.test') // Note: different scheme!
.expect('Access-Control-Allow-Origin', '*')
.expect(403, done);
});
it('GET /example.com without origin', function(done) {
request(cors_anywhere)
.get('/example.com/')
.expect('Access-Control-Allow-Origin', '*')
.expect(403, done);
});
});
describe('requireHeader', function() {
before(function() {
cors_anywhere = createServer({