Permalink
Browse files

rbl check for alias creation

I just have to be careful not to use a DUN list I guess. Aside of that,
I really want the RBL check for creation as in theory, a botnet could
generate thousands of aliases without ever hitting the rate limit.

Speaking of rate limit: This code here fixes the little async-screwup I
made in the rate limit code earlier
  • Loading branch information...
1 parent afd017d commit 72517501aa178b20ae08bdd055e1655c84a93212 @pilif committed Jun 25, 2010
Showing with 73 additions and 44 deletions.
  1. +1 −0 config.ini.template
  2. +5 −1 lib/config.js
  3. +67 −43 lib/tempalias_http.js
View
@@ -2,6 +2,7 @@
port=8080 ; port to listen on for HTTP
listen=127.0.0.1 ; interface to bind webserver to (empty for all)
rate_limit=30000 ; time users have to wait before generating another alias
+rbls=examplea.com,exampleb.com ; rbl domains to check for HTTP (alias generation)
[smtp]
port=2525 ; port to listen on for SMTP
View
@@ -4,7 +4,7 @@ fs = require('fs');
var config_file = __dirname + '/../config.ini';
-exports.http = {port: 8080, listen: null, rate_limit: 30000 };
+exports.http = {port: 8080, listen: null, rate_limit: 30000, rbls: [] };
exports.smtp = {
port: 2525,
listen: null,
@@ -28,6 +28,10 @@ if (cf.isFile()){
if (c.http.port) exports.http.port = parseInt(c.http.port, 10);
if (c.http.rate_limit) exports.http.rate_limit = parseInt(c.http.rate_limit, 10);
if (c.http.listen) exports.http.listen = c.http.listen;
+ if (c.http.rbls){
+ exports.http.rbls = c.http.rbls.split(',');
+ }
+
}
if (c.general){
if (c.http.listen) exports.general.pidFile = c.general.pidFile;
View
@@ -55,53 +55,77 @@ fs.realpath('lib/../public', function(err, public_root){
res.end(body);
};
- // too bad SETNX counts as a write operation even when it doesn't write.
- // that's why I can't just use redis' EXPIRE command
- var lock_key = 'lock:'+req.socket.remoteAddress;
- var t = (new Date()).getTime();
- redis.setnx(lock_key, t+30000, function(lr){
- if (!lr){
- redis.get(lock_key, function(exp){
- if (parseInt(exp, 10) < (t)){
- redis.del(lock_key);
- }else{
- err(403, {error: 'rate-limited', description: 'please wait a moment before generating the next alias'});
- }
- });
- }
- });
-
- process.addListener('uncaughtException', function (e) {
- var msg = (e && e.message) ? e.message : 'unknown';
- err(500, {error: 'server-error', description: msg});
- });
-
var genAlias = function(data){
- var alias = p.getNew();
- try{
- alias.setInfo(data);
- }catch(e){
- err(400, {
- error: "invalid-data",
- description: e.message
- });
- }
- try{
- p.save(alias, function(id){
- try{
- alias.currentDate = new Date();
- var f = alias.valid_from ? alias.valid_from.getDate() : new Date();
- if (alias.valid_until && !alias.valid_from){
- alias.days = Math.ceil((alias.valid_until.getTime()-f.getTime())/(1000*60*60*24));
+ var generate = function(){
+ var alias = p.getNew();
+ try{
+ alias.setInfo(data);
+ }catch(e){
+ err(400, {
+ error: "invalid-data",
+ description: e.message
+ });
+ }
+ try{
+ p.save(alias, function(id){
+ try{
+ alias.currentDate = new Date();
+ var f = alias.valid_from ? alias.valid_from.getDate() : new Date();
+ if (alias.valid_until && !alias.valid_from){
+ alias.days = Math.ceil((alias.valid_until.getTime()-f.getTime())/(1000*60*60*24));
+ }
+ sendAlias(alias);
+ }catch(e){
+ err(500, {error: "server-exception", description: e.message});
+ }
+ });
+ }catch(e){
+ err(500, {error: "server-exception", description: e.message});
+ }
+ };
+
+ var rbl_check = function(){
+ if (config.http.rbls){
+ sys.debug('rbls set');
+ var addr = req.socket.remoteAddress;
+ require('rbl').check(addr, config.http.rbls, function(found){
+ if (found){
+ err(403, {error: 'rbl-check-failed', description: 'refused to generate alias for your IP-address'});
+ }else{
+ generate();
}
- sendAlias(alias);
- }catch(e){
- err(500, {error: "server-exception", description: e.message});
+ });
+ }else{
+ generate();
+ }
+ };
+
+ var rate_limit_check = function(){
+ // too bad SETNX counts as a write operation even when it doesn't write.
+ // that's why I can't just use redis' EXPIRE command
+ var lock_key = 'lock:'+req.socket.remoteAddress;
+ var t = (new Date()).getTime();
+ redis.setnx(lock_key, t+config.http.rate_limit, function(lr){
+ if (!lr){
+ redis.get(lock_key, function(exp){
+ if (parseInt(exp, 10) < (t)){
+ sys.debug('lock key found but expired');
+ redis.set(lock_key, t+config.http.rate_limit, function(){
+ sys.debug('lock key updated');
+ rbl_check();
+ });
+ }else{
+ err(403, {error: 'rate-limited', description: 'please wait a moment before generating the next alias'});
+ }
+ });
+ }else{
+ sys.debug('lock key not found. Was set to '+lr);
+ rbl_check();
}
});
- }catch(e){
- err(500, {error: "server-exception", description: e.message});
- }
+ };
+
+ rate_limit_check();
};
if (!url.query.callback){

0 comments on commit 7251750

Please sign in to comment.