Added support for X-forwarded-for and host blacklisting
parent
61cbd07c95
commit
7dd6defa73
|
|
@ -4,4 +4,5 @@ exports.fetch_regex = /^\/fetch\/(.*)$/; // The URL to look for when parsing the
|
||||||
exports.proxy_request_timeout_ms = 10000; // The lenght of time we'll wait for a proxy server to respond before timing out.
|
exports.proxy_request_timeout_ms = 10000; // The lenght of time we'll wait for a proxy server to respond before timing out.
|
||||||
exports.max_request_length = 100000; // The maximum length of characters allowed for a request or a response.
|
exports.max_request_length = 100000; // The maximum length of characters allowed for a request or a response.
|
||||||
exports.enable_rate_limiting = true;
|
exports.enable_rate_limiting = true;
|
||||||
exports.max_requests_per_second = 10; // The maximum number of requests per second to allow from a given IP.
|
exports.max_requests_per_second = 10; // The maximum number of requests per second to allow from a given IP.
|
||||||
|
exports.blacklist_hostname_regex = /^(10\.|192\.|localhost$)/i; // Good for limiting access to internal IP addresses and hosts.
|
||||||
21
package.json
21
package.json
|
|
@ -1,12 +1,13 @@
|
||||||
{
|
{
|
||||||
"name": "thingproxy.freeboard.io",
|
"name": "thingproxy.freeboard.io",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "A simple forward proxy server for processing API calls to servers that don't send CORS headers or support HTTPS.",
|
"description": "A simple forward proxy server for processing API calls to servers that don't send CORS headers or support HTTPS.",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"author": "Jim Heising <jim@buglabs.net>",
|
"author": "Jim Heising <jim@buglabs.net>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"request": "2.40.0",
|
"request": "2.40.0",
|
||||||
"tokenthrottle": "1.1.0"
|
"tokenthrottle": "1.1.0",
|
||||||
}
|
"public-address": "^0.1.1"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
38
server.js
38
server.js
|
|
@ -4,6 +4,17 @@ var url = require("url");
|
||||||
var request = require("request");
|
var request = require("request");
|
||||||
var throttle = require("tokenthrottle")({rate: config.max_requests_per_second});
|
var throttle = require("tokenthrottle")({rate: config.max_requests_per_second});
|
||||||
|
|
||||||
|
var publicAddressFinder = require("public-address");
|
||||||
|
var publicIP;
|
||||||
|
|
||||||
|
// Get our public IP address
|
||||||
|
publicAddressFinder(function(err, data){
|
||||||
|
if(!err && data)
|
||||||
|
{
|
||||||
|
publicIP = data.address;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function addCORSHeaders(req, res)
|
function addCORSHeaders(req, res)
|
||||||
{
|
{
|
||||||
if (req.method.toUpperCase() === "OPTIONS")
|
if (req.method.toUpperCase() === "OPTIONS")
|
||||||
|
|
@ -75,11 +86,30 @@ function processRequest(req, res)
|
||||||
return writeResponse(res, 404, "relative URLS are not supported");
|
return writeResponse(res, 404, "relative URLS are not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Naughty, naughty— deny requests to blacklisted hosts
|
||||||
|
if(config.blacklist_hostname_regex.test(remoteURL.hostname))
|
||||||
|
{
|
||||||
|
return writeResponse(res, 400, "naughty, naughty...");
|
||||||
|
}
|
||||||
|
|
||||||
// We only support http and https
|
// We only support http and https
|
||||||
if (remoteURL.protocol != "http:" && remoteURL.protocol !== "https:") {
|
if (remoteURL.protocol != "http:" && remoteURL.protocol !== "https:") {
|
||||||
return writeResponse(res, 400, "only http and https are supported");
|
return writeResponse(res, 400, "only http and https are supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(publicIP)
|
||||||
|
{
|
||||||
|
// Add an X-Forwarded-For header
|
||||||
|
if(req.headers["x-forwarded-for"])
|
||||||
|
{
|
||||||
|
req.headers["x-forwarded-for"] += ", " + publicIP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
req.headers["x-forwarded-for"] = req.clientIP + ", " + publicIP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var proxyRequest = request({
|
var proxyRequest = request({
|
||||||
url: remoteURL,
|
url: remoteURL,
|
||||||
headers: req.headers,
|
headers: req.headers,
|
||||||
|
|
@ -140,17 +170,19 @@ http.createServer(function (req, res) {
|
||||||
return writeResponse(res, 200);
|
return writeResponse(res, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
var remoteIP = getClientAddress(req);
|
var clientIP = getClientAddress(req);
|
||||||
|
|
||||||
|
req.clientIP = clientIP;
|
||||||
|
|
||||||
// Log our request
|
// Log our request
|
||||||
if(config.enable_logging)
|
if(config.enable_logging)
|
||||||
{
|
{
|
||||||
console.log("%s %s %s", (new Date()).toJSON(), remoteIP, req.method, req.url);
|
console.log("%s %s %s", (new Date()).toJSON(), clientIP, req.method, req.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(config.enable_rate_limiting)
|
if(config.enable_rate_limiting)
|
||||||
{
|
{
|
||||||
throttle.rateLimit(remoteIP, function(err, limited) {
|
throttle.rateLimit(clientIP, function(err, limited) {
|
||||||
if (limited)
|
if (limited)
|
||||||
{
|
{
|
||||||
return writeResponse(res, 429, "enhance your calm");
|
return writeResponse(res, 429, "enhance your calm");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue