Browse Source

Use spaces for indentation

master
digital dreamer 10 years ago
parent
commit
80daa05d40
  1. 17
      package.json
  2. 96
      settings.json
  3. 240
      twister-proxy.js

17
package.json

@ -5,19 +5,20 @@
"author": "digital dreamer <digitaldreamer@email.cz>", "author": "digital dreamer <digitaldreamer@email.cz>",
"dependencies": "dependencies":
{ {
"express": ">=2.5.x", "express": ">=2.5.x",
"cors": "*", "cors": "*",
"log-timestamp": ">=0.1.1" "log-timestamp": ">=0.1.1"
}, },
"repository": { "repository":
{
"type": "git", "type": "git",
"url": "https://github.com/digital-dreamer/twister-proxy.git" "url": "https://github.com/digital-dreamer/twister-proxy.git"
}, },
"licenses": "licenses":
[ [
{ {
"type": "Apache 2.0", "type": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html" "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
} }
] ]
} }

96
settings.json

@ -1,65 +1,65 @@
{ {
"Server": "Server":
{ {
"ssl_key_file": "insert/path/to/your/server-key-file", "ssl_key_file": "insert/path/to/your/server-key-file",
"ssl_certificate_file": "insert/path/to/your/ssl-certificate", "ssl_certificate_file": "insert/path/to/your/ssl-certificate",
"enable_https": false, "enable_https": false,
"https_port": 443, "https_port": 443,
"http_port": 80 "http_port": 80
}, },
"RPC": "RPC":
{ {
"host": "localhost", "host": "localhost",
"port": 28332, "port": 28332,
"user": "user", "user": "user",
"password": "pwd" "password": "pwd"
}, },
"CallLimits": "CallLimits":
[ [
{ {
"name": "getbestblockhash", "name": "getbestblockhash",
"maxPerMinute": null, "maxPerMinute": null,
"maxPerMinutePerIP": null "maxPerMinutePerIP": null
}, },
{ {
"name": "getinfo", "name": "getinfo",
"maxPerMinute": null, "maxPerMinute": null,
"maxPerMinutePerIP": null "maxPerMinutePerIP": null
}, },
{ {
"name": "listwalletusers", "name": "listwalletusers",
"maxPerMinute": null, "maxPerMinute": null,
"maxPerMinutePerIP": null "maxPerMinutePerIP": null
}, },
{ {
"name": "getblock", "name": "getblock",
"maxPerMinute": null, "maxPerMinute": null,
"maxPerMinutePerIP": null "maxPerMinutePerIP": null
}, },
{ {
"name": "dhtget", "name": "dhtget",
"maxPerMinute": null, "maxPerMinute": null,
"maxPerMinutePerIP": null "maxPerMinutePerIP": null
}, },
{ {
"name": "listusernamespartial", "name": "listusernamespartial",
"maxPerMinute": null, "maxPerMinute": null,
"maxPerMinutePerIP": null "maxPerMinutePerIP": null
}, },
{ {
"name": "gettrendinghashtags", "name": "gettrendinghashtags",
"maxPerMinute": null, "maxPerMinute": null,
"maxPerMinutePerIP": null "maxPerMinutePerIP": null
} }
], ],
"LogAsAttackThreshold": "LogAsAttackThreshold":
{ {
"callsOverLimits": 30, "callsOverLimits": 30,
"invalidRequests": 30, "invalidRequests": 30,
"forbiddenCalls": 30 "forbiddenCalls": 30
} }
} }

240
twister-proxy.js

@ -21,21 +21,21 @@ if(settings.Server.enable_https)
{ {
try try
{ {
var privateKey = fs.readFileSync(settings.Server.ssl_key_file).toString(); var privateKey = fs.readFileSync(settings.Server.ssl_key_file).toString();
} }
catch(e) catch(e)
{ {
console.log("Error: unable to load SSL key. Please edit setting.json and put the correct path to your SSL private key file into \"ssl_key_file.\""); console.log("Error: unable to load SSL key. Please edit setting.json and put the correct path to your SSL private key file into \"ssl_key_file.\"");
process.exit(1); process.exit(1);
} }
try try
{ {
var certificate = fs.readFileSync(settings.Server.ssl_certificate_file).toString(); var certificate = fs.readFileSync(settings.Server.ssl_certificate_file).toString();
} }
catch(e) catch(e)
{ {
console.log("Error: unable to load SSL certificate. Please edit setting.json and put the correct path to your SSL certificate file into \"ssl_certificate_file.\""); console.log("Error: unable to load SSL certificate. Please edit setting.json and put the correct path to your SSL certificate file into \"ssl_certificate_file.\"");
process.exit(1); process.exit(1);
} }
var credentials = {key: privateKey, cert: certificate}; var credentials = {key: privateKey, cert: certificate};
} }
@ -67,8 +67,8 @@ CounterInstance = function()
this.callsRemaining={}; this.callsRemaining={};
for (x in maxCallsPerMinutePerIP) for (x in maxCallsPerMinutePerIP)
{ {
if(maxCallsPerMinutePerIP[x]!==null) if(maxCallsPerMinutePerIP[x]!==null)
this.callsRemaining[x]=maxCallsPerMinutePerIP[x]; this.callsRemaining[x]=maxCallsPerMinutePerIP[x];
} }
} }
@ -80,30 +80,30 @@ app.get("*", function(request, response)
{ {
if(settings.Server.enable_https&&request.protocol=="http") if(settings.Server.enable_https&&request.protocol=="http")
{ {
if(settings.Server.https_port==443) if(settings.Server.https_port==443)
secureUrl="https://"+request.host+request.path; secureUrl="https://"+request.host+request.path;
else else
secureUrl="https://"+request.host+":"+settings.Server.https_port+request.path; secureUrl="https://"+request.host+":"+settings.Server.https_port+request.path;
response.writeHead(302, {"Location": secureUrl}); response.writeHead(302, {"Location": secureUrl});
response.end(); response.end();
return; return;
} }
request.headers.Authorization = auth; request.headers.Authorization = auth;
var webProxy = http.request({host: settings.RPC.host, port: settings.RPC.port, method: request.method, path: request.path, headers: request.headers}, function (proxy_res) var webProxy = http.request({host: settings.RPC.host, port: settings.RPC.port, method: request.method, path: request.path, headers: request.headers}, function (proxy_res)
{ {
proxy_res.pipe(response, {end: true}); proxy_res.pipe(response, {end: true});
}); });
webProxy.on("error", function(error) webProxy.on("error", function(error)
{ {
if(!connectionErrorMessageDisplayed) if(!connectionErrorMessageDisplayed)
{ {
console.log("Error: cannot connect to twisterd.\nSee Troubleshooting section in README.md for instructions."); console.log("Error: cannot connect to twisterd.\nSee Troubleshooting section in README.md for instructions.");
connectionErrorMessageDisplayed=true; connectionErrorMessageDisplayed=true;
} }
response.send(502); response.send(502);
}); });
request.pipe(webProxy, {end: true}); request.pipe(webProxy, {end: true});
@ -122,82 +122,82 @@ app.post("/", function(request, response)
request.addListener("end", function() request.addListener("end", function()
{ {
var remoteIP = request.connection.remoteAddress; var remoteIP = request.connection.remoteAddress;
if(perIPCounter[remoteIP]===undefined) if(perIPCounter[remoteIP]===undefined)
{ {
perIPCounter[remoteIP]=new CounterInstance(); perIPCounter[remoteIP]=new CounterInstance();
} }
try try
{ {
bodyJson=JSON.parse(request.rawBody); bodyJson=JSON.parse(request.rawBody);
rpcMethod=bodyJson.method; rpcMethod=bodyJson.method;
} }
catch(e) catch(e)
{ {
perIPCounter[remoteIP].invalidRequests++; perIPCounter[remoteIP].invalidRequests++;
invalidRequestCounter++; invalidRequestCounter++;
return; return;
} }
if(maxCallsPerMinute[rpcMethod]===undefined) if(maxCallsPerMinute[rpcMethod]===undefined)
{ {
perIPCounter[remoteIP].forbiddenCalls++; perIPCounter[remoteIP].forbiddenCalls++;
forbiddenCallCounter++; forbiddenCallCounter++;
return; return;
} }
if(maxCallsPerMinute[rpcMethod]!==null) if(maxCallsPerMinute[rpcMethod]!==null)
{ {
if(callsRemaining[rpcMethod]<1) if(callsRemaining[rpcMethod]<1)
{ {
droppedCallsCounter[rpcMethod]++; droppedCallsCounter[rpcMethod]++;
return; return;
} }
else else
{ {
callsRemaining[rpcMethod]--; callsRemaining[rpcMethod]--;
} }
} }
if(maxCallsPerMinutePerIP[rpcMethod]!==null) if(maxCallsPerMinutePerIP[rpcMethod]!==null)
{ {
if(perIPCounter[remoteIP].callsRemaining[rpcMethod]<1) if(perIPCounter[remoteIP].callsRemaining[rpcMethod]<1)
{ {
perIPCounter[remoteIP].overLimit++; perIPCounter[remoteIP].overLimit++;
return; return;
} }
else else
{ {
perIPCounter[remoteIP].callsRemaining[rpcMethod]--; perIPCounter[remoteIP].callsRemaining[rpcMethod]--;
} }
} }
var rpcProxy = http.request({host: settings.RPC.host, port: settings.RPC.port, method: request.method, headers: request.headers}, function(proxy_res) var rpcProxy = http.request({host: settings.RPC.host, port: settings.RPC.port, method: request.method, headers: request.headers}, function(proxy_res)
{ {
proxy_res.on("data", function(chunk) proxy_res.on("data", function(chunk)
{ {
response.write(chunk, "binary"); response.write(chunk, "binary");
}); });
proxy_res.on("end", function(chunk) proxy_res.on("end", function(chunk)
{ {
response.end(); response.end();
}); });
proxy_res.on("error", function(error) proxy_res.on("error", function(error)
{ {
if(!connectionErrorMessageDisplayed) if(!connectionErrorMessageDisplayed)
{ {
console.log("Error: cannot connect to twisterd.\nSee Troubleshooting section in README.md for instructions."); console.log("Error: cannot connect to twisterd.\nSee Troubleshooting section in README.md for instructions.");
connectionErrorMessageDisplayed=true; connectionErrorMessageDisplayed=true;
} }
response.send(502); response.send(502);
}); });
response.writeHead(proxy_res.statusCode, proxy_res.headers); response.writeHead(proxy_res.statusCode, proxy_res.headers);
}); });
rpcProxy.write(request.rawBody, "binary"); rpcProxy.write(request.rawBody, "binary");
rpcProxy.end(); rpcProxy.end();
}); });
}); });
@ -212,38 +212,38 @@ setInterval(function()
{ {
for(method in maxCallsPerMinute) for(method in maxCallsPerMinute)
{ {
callsRemaining[method] = maxCallsPerMinute[method]; callsRemaining[method] = maxCallsPerMinute[method];
if(droppedCallsCounter[method]!==0) if(droppedCallsCounter[method]!==0)
{ {
console.log("Dropped "+droppedCallsCounter[method]+" calls to "+method+" over the limit of "+maxCallsPerMinute[method]); console.log("Dropped "+droppedCallsCounter[method]+" calls to "+method+" over the limit of "+maxCallsPerMinute[method]);
droppedCallsCounter[method] = 0; droppedCallsCounter[method] = 0;
} }
}; };
if(invalidRequestCounter!==0) if(invalidRequestCounter!==0)
{ {
console.log("Received "+invalidRequestCounter+" invalid POST requests."); console.log("Received "+invalidRequestCounter+" invalid POST requests.");
invalidRequestCounter = 0; invalidRequestCounter = 0;
} }
if(forbiddenCallCounter!==0) if(forbiddenCallCounter!==0)
{ {
console.log("Denied "+forbiddenCallCounter+" attempts to access forbidden API calls."); console.log("Denied "+forbiddenCallCounter+" attempts to access forbidden API calls.");
forbiddenCallCounter = 0; forbiddenCallCounter = 0;
} }
for(ip in perIPCounter) for(ip in perIPCounter)
{ {
if(perIPCounter[ip].overLimit>=settings.LogAsAttackThreshold.callsOverLimits) if(perIPCounter[ip].overLimit>=settings.LogAsAttackThreshold.callsOverLimits)
{ {
console.log("IP "+ip+" tried to send "+perIPCounter[ip].overLimit+" calls more than the limits allow."); console.log("IP "+ip+" tried to send "+perIPCounter[ip].overLimit+" calls more than the limits allow.");
}; };
if(perIPCounter[ip].invalidRequests>=settings.LogAsAttackThreshold.invalidRequests) if(perIPCounter[ip].invalidRequests>=settings.LogAsAttackThreshold.invalidRequests)
{ {
console.log("IP "+ip+" sent "+perIPCounter[ip].invalidRequests+" invalid request that couldn't be parsed."); console.log("IP "+ip+" sent "+perIPCounter[ip].invalidRequests+" invalid request that couldn't be parsed.");
}; };
if(perIPCounter[ip].forbiddenCalls>=settings.LogAsAttackThreshold.forbiddenCalls) if(perIPCounter[ip].forbiddenCalls>=settings.LogAsAttackThreshold.forbiddenCalls)
{ {
console.log("IP "+ip+" tried to send "+perIPCounter[ip].forbiddenCalls+" calls to forbidden functions."); console.log("IP "+ip+" tried to send "+perIPCounter[ip].forbiddenCalls+" calls to forbidden functions.");
}; };
} }
perIPCounter = {}; perIPCounter = {};

Loading…
Cancel
Save