CinemaPress/lib/CP_bots.js

289 lines
9.2 KiB
JavaScript

'use strict';
/**
* Configuration dependencies.
*/
var config = require('../config/production/config');
Object.keys(config).length === 0 &&
(config = require('../config/production/config.backup'));
var config_md5 = require('md5')(JSON.stringify(config));
setInterval(function() {
if (
config_md5 &&
process.env['CP_CONFIG_MD5'] &&
config_md5 !== process.env['CP_CONFIG_MD5']
) {
config = require('../config/production/config');
Object.keys(config).length === 0 &&
(config = require('../config/production/config.backup'));
config_md5 = process.env['CP_CONFIG_MD5'];
}
}, 3333);
/**
* Node dependencies.
*/
var ipRangeCheck = require('ip-range-check');
var crypto = require('crypto').createHash;
var isbot = require('isbot');
var dns = require('dns');
var LRU = require('lru-cache');
var success_ips = new LRU({ maxAge: 3600000, max: 1000 });
module.exports = function() {
return function(req, res, next) {
var ua = req.get('user-agent') ? req.get('user-agent').toLowerCase() : '';
var bot_main = null;
var date = new Date();
req.userinfo = {
bot: { all: isbot(ua), main: false },
ip: (
(
req.headers['x-real-ip'] ||
req.headers['cf-connecting-ip'] ||
req.headers['x-forwarded-for'] ||
''
)
.split(',')
.pop()
.trim() ||
req.ip ||
req.connection.remoteAddress
).replace('::ffff:', '')
};
if (!config.bots || !config.bots.length) {
return next();
}
var hash = crypto('sha1')
.update(req.userinfo.ip + '' + ua)
.digest('base64');
var success_ip = success_ips.get(hash);
if (success_ip && success_ip.status) {
if (success_ip.status === 1) {
req.userinfo.bot.all = true;
req.userinfo.bot.main = true;
} else if (success_ip.status === 2) {
req.userinfo.bot.all = false;
req.userinfo.bot.main = false;
} else if (success_ip.status === 3) {
var time = Array(3)
.fill([3600, success_ip.time.getTime() - new Date().getTime()])
.map((v, i, a) => {
a[i + 1] = [
a[i][0] / 60,
((v[1] / (v[0] * 1000)) % 1) * (v[0] * 1000)
];
return (
'<span class=w>' +
('0' + Math.floor(v[1] / (v[0] * 1000)) + '').slice(-2) +
'</span>'
);
})
.join(':');
return next({
status: 403,
message: success_ip.message + '<br><br>' + time
});
}
return next();
}
for (var i = 0; i < config.bots.length; i++) {
config.bots[i] = config.bots[i].trim();
if (config.bots[i] && config.bots[i].charAt(0) !== '#') {
var config_bot = config.bots[i].replace(/\s*~\s*/g, '~').split('~');
if (config_bot[0] && ua.indexOf(config_bot[0].toLowerCase()) + 1) {
bot_main = {
keyword: config_bot[0].toUpperCase(),
domains: config_bot[1]
? config_bot[1]
.replace(/\s*,\s*/g, ',')
.split(',')
.filter(Boolean)
: [],
ips: config_bot[2]
? config_bot[2]
.replace(/\s*,\s*/g, ',')
.split(',')
.filter(Boolean)
: [],
message: config_bot[3] ? config_bot[3] : '',
time: new Date(new Date().setHours(new Date().getHours() + 1))
};
break;
}
}
}
if (!bot_main) {
return next();
}
if (bot_main.ips && bot_main.ips.length) {
if (!ipRangeCheck(req.userinfo.ip, bot_main.ips)) {
console.log(
'FAKE BOT DETECTED [IP]',
req.userinfo.ip,
bot_main.keyword,
('00' + (new Date() - date)).slice(-3) + 'ms'
);
req.userinfo.bot.all = false;
req.userinfo.bot.main = false;
if (bot_main.message) {
success_ips.set(hash, {
message: bot_main.message,
time: bot_main.time,
status: 3
});
return next({
status: 403,
message:
bot_main.message +
'<br><br><span class="w">01</span>:<span class="w">00</span>:<span class="w">00</span>'
});
} else {
success_ips.set(hash, { status: 2 });
return next();
}
} else {
console.log(
'TRUE BOT DETECTED [IP]',
req.userinfo.ip,
bot_main.keyword,
('00' + (new Date() - date)).slice(-3) + 'ms'
);
req.userinfo.bot.all = true;
req.userinfo.bot.main = true;
success_ips.set(hash, { status: 1 });
return next();
}
} else if (bot_main.domains && bot_main.domains.length) {
dns.reverse(req.userinfo.ip, function(err, domains) {
if (err !== null || !domains || !domains.length) {
console.log(
'FAKE BOT DETECTED [REVERSE]',
req.userinfo.ip,
bot_main.keyword,
('00' + (new Date() - date)).slice(-3) + 'ms',
err !== null ? err : ''
);
req.userinfo.bot.all = false;
req.userinfo.bot.main = false;
if (bot_main.message) {
success_ips.set(hash, {
message: bot_main.message,
time: bot_main.time,
status: 3
});
return next({
status: 403,
message:
bot_main.message +
'<br><br><span class="w">01</span>:<span class="w">00</span>:<span class="w">00</span>'
});
} else {
success_ips.set(hash, { status: 2 });
return next();
}
}
domains.forEach(function(domain) {
var not_domain = true;
for (var i = 0; i < bot_main.domains.length; i++) {
var reg_domain = new RegExp(bot_main.domains[i] + '$', 'i');
if (reg_domain.test(domain)) {
not_domain = false;
break;
}
}
if (not_domain) {
console.log(
'FAKE BOT DETECTED [DOMAIN]',
req.userinfo.ip,
bot_main.keyword,
('00' + (new Date() - date)).slice(-3) + 'ms'
);
req.userinfo.bot.all = false;
req.userinfo.bot.main = false;
if (bot_main.message) {
success_ips.set(hash, {
message: bot_main.message,
time: bot_main.time,
status: 3
});
return next({
status: 403,
message:
bot_main.message +
'<br><br><span class="w">01</span>:<span class="w">00</span>:<span class="w">00</span>'
});
} else {
success_ips.set(hash, { status: 2 });
return next();
}
}
dns.lookup(
domain,
/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(
req.userinfo.ip
)
? 4
: 6,
function(err, address, family) {
if (err !== null || !address || req.userinfo.ip !== address) {
console.log(
'FAKE BOT DETECTED [ADDRESS]',
req.userinfo.ip,
bot_main.keyword,
('00' + (new Date() - date)).slice(-3) + 'ms',
err !== null ? err : ''
);
req.userinfo.bot.all = false;
req.userinfo.bot.main = false;
if (bot_main.message) {
success_ips.set(hash, {
message: bot_main.message,
time: bot_main.time,
status: 3
});
return next({
status: 403,
message:
bot_main.message +
'<br><br><span class="w">01</span>:<span class="w">00</span>:<span class="w">00</span>'
});
} else {
success_ips.set(hash, { status: 2 });
return next();
}
} else {
console.log(
'TRUE BOT DETECTED [ADDRESS]',
req.userinfo.ip,
bot_main.keyword,
('00' + (new Date() - date)).slice(-3) + 'ms'
);
req.userinfo.bot.all = true;
req.userinfo.bot.main = true;
success_ips.set(hash, { status: 1 });
return next();
}
}
);
});
});
} else {
req.userinfo.bot.all = true;
req.userinfo.bot.main = true;
return next();
}
};
};