@ -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 = { } ;