deCloudflare/tool/cfdomains/source.js
2022-04-17 04:35:51 +00:00

316 lines
9.1 KiB
JavaScript

const args = process.argv,
fs = require('fs');
const {
Curl,
CurlHttpVersion
} = require('node-libcurl');
const cur1 = new Curl();
cur1.setOpt('SSL_VERIFYPEER', false);
cur1.setOpt('HTTP_VERSION', CurlHttpVersion.V2PriorKnowledge);
cur1.setOpt('FOLLOWLOCATION', true);
cur1.setOpt('CONNECTTIMEOUT', 8);
cur1.setOpt('TIMEOUT', 600);
const Fconfig = require('os').homedir() + '/.cfdomains.cfg',
Fproxy = require('os').homedir() + '/.cfdomains_sox.cfg';
let Dlist = './cfdomains_Data/',
myproxy = '';
function forceExit(m) {
console.log('\x1b[31m%s\x1b[0m', m);
process.exit();
}
function is_domain(x) {
return /^([a-z0-9]{1})([a-z0-9.-]{0,254})\.([a-z]{2,50})$/.test(x);
}
if (fs.existsSync(Fconfig)) {
Dlist = fs.readFileSync(Fconfig);
if (!fs.existsSync(Dlist)) {
try {
fs.unlinkSync(Fconfig);
} catch (e) {}
forceExit('List directory is not okay! Fix this by running --dir');
}
}
if (fs.existsSync(Fproxy)) {
myproxy = fs.readFileSync(Fproxy);
if (myproxy.indexOf(':') < 6) {
myproxy = '';
}
}
function showUsage() {
console.log("\n \x1b[33mCfDomains\x1b[0m v1.0.2.3\n");
console.log('\x1b[36mUsage:\x1b[0m');
console.log(' cfdomains \x1b[43mexample.com\x1b[0m');
console.log(' cfdomains --dir');
console.log(' cfdomains --proxy');
console.log(' cfdomains [--dl|--dl2][ |0,1,...,a,b,...z]');
console.log(" cfdomains [--report|--delist] \x1b[43mexample.com\x1b[0m\n");
console.log('\x1b[36mDetails:\x1b[0m');
console.log(' cfdomains \x1b[43mexample.com\x1b[0m');
console.log(' return "\x1b[32my\x1b[0m", "\x1b[32mn\x1b[0m", or "\x1b[32me\x1b[0m"');
console.log(' \x1b[32my\x1b[0m: Domain is on the list');
console.log(' \x1b[32mn\x1b[0m: Domain is not listed');
console.log(" \x1b[32me\x1b[0m: List data not found (fix it by running --dl)\n");
console.log(' cfdomains --dir');
console.log(' Change list directory');
console.log(' \x1b[4mCurrent directory\x1b[0m: ' + Dlist + "\n");
console.log(' cfdomains --proxy');
console.log(' Set or Unset SOCKS proxy');
console.log(' \x1b[4mCurrent SOCKS proxy\x1b[0m: ' + myproxy + "\n");
console.log(' cfdomains --dl|dl2');
console.log(' cfdomains --dl|dl2 \x1b[43ma,b,c\x1b[0m');
console.log(' \x1b[32mdl\x1b[0m: Download list files from Archive.org');
console.log(' \x1b[32mdl2\x1b[0m: Download list files from deCloudflare git');
console.log(" \x1b[32ma,b,c\x1b[0m: Download only these files (comma-separated)\n");
console.log(' cfdomains --report|delist \x1b[43mexample.com\x1b[0m');
console.log(' Submit domain to #Karma for automated analysis');
console.log(' \x1b[4mOnly the domain will be submitted\x1b[0m. We NEVER record anything else.');
console.log(' \x1b[32mreport\x1b[0m: Report not-yet-listed domain (New Cloudflare)');
console.log(" \x1b[32mdelist\x1b[0m: Report currently-listed domain (Left Cloudflare)\n");
console.log();
process.exit();
}
function chgLDR() {
const rle = require('readline');
let rl = rle.createInterface(process.stdin, process.stdout);
console.log('Current save directory: ' + Dlist);
console.log('Set "empty" to use default location.');
rl.question('List save directory: ', (l) => {
rl.close();
if (l.length > 1 && l !== 'empty') {
if (l.indexOf('/', l.length - 1) !== -1) {
if (fs.existsSync(l) && fs.lstatSync(l).isDirectory()) {
fs.writeFileSync(Fconfig, l);
} else {
forceExit('Directory not found');
}
} else {
forceExit('Directory is not ended with /');
}
} else {
try {
fs.unlinkSync(Fconfig);
} catch (e) {}
}
process.exit();
});
}
function chgPROXY() {
const rle = require('readline');
let rl = rle.createInterface(process.stdin, process.stdout);
console.log('Current SOCKS Proxy: ' + myproxy);
console.log('Set none to use direct connection.');
rl.question('Input SOCKS Proxy [IP:Port]: ', (l) => {
rl.close();
if (/^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\:([0-9]{1,5})$/.test(l)) {
fs.writeFileSync(Fproxy, l);
} else {
try {
fs.unlinkSync(Fproxy);
} catch (e) {}
}
process.exit();
});
}
function dlFile(bu, i) {
return new Promise((okay, nope) => {
const curl = cur1.dupHandle(false);
curl.setOpt('URL', bu + 'cloudflare_' + i + '.json');
curl.setOpt('USERAGENT', 'CfDomains');
if (myproxy != '') {
curl.setOpt('HTTPPROXYTUNNEL', 1);
curl.setOpt('PROXY', 'socks5h://' + myproxy + '/');
}
curl.on('error', (er, ec) => {
curl.close();
console.log('\x1b[31m%s\x1b[0m', er);
forceExit('Connection Error while downloading list ' + i);
});
curl.on('end', (sc, b) => {
curl.close();
if (sc != 200) {
forceExit('Server error ' + r.statusCode);
}
try {
JSON.parse(b)
} catch (e1) {
forceExit('Bad Data Error while downloading list ' + i);
}
fs.writeFileSync(Dlist + i, b);
okay();
});
curl.perform();
});
}
function shuffle(array) {
let currentIndex = array.length,
randomIndex;
while (currentIndex != 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]
];
}
return array;
}
async function dlFiles(bu) {
if (!fs.existsSync(Dlist)) {
fs.mkdirSync(Dlist);
}
if (!fs.existsSync(Dlist)) {
forceExit('Directory not found!');
}
if (myproxy == '') {
console.log('\x1b[36mNOTICE\x1b[0m: You are not using Tor.');
}
console.log('Downloading lists: ' + bu);
let w, names = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
let aonly = args[3];
if (aonly && aonly.length > 0) {
let names1 = [];
for (x of aonly.split(',')) {
if (names.indexOf(x) > -1) {
names1.push(x);
}
}
if (names1.length > 0) {
names = names1;
} else {
forceExit('invalid input');
}
}
shuffle(names);
for (x of names) {
console.log('Downloading ' + x);
w = await dlFile(bu, x);
}
for (x of names) {
console.log('Testing ' + x);
if (!fs.existsSync(Dlist + x)) {
forceExit('File not found');
}
let data = fs.readFileSync(Dlist + x, {
encoding: 'utf8'
});
try {
JSON.parse(data)
} catch (e) {
forceExit('Bad data found');
}
}
process.exit();
}
function queryDom() {
let dom = args[2];
if (!is_domain(dom)) {
showUsage();
}
if (!fs.existsSync(Dlist + dom[0])) {
process.stdout.write('e');
process.exit();
}
let data = fs.readFileSync(Dlist + dom[0], {
encoding: 'utf8'
});
data = JSON.parse(data);
if (data[dom]) {
process.stdout.write('y');
} else {
process.stdout.write('n');
}
process.exit();
}
function reporter(dom, t) {
return new Promise((okay, nope) => {
const curl = cur1.dupHandle(false);
curl.setOpt('URL', 'https://karma.crimeflare.eu.org/api/is_cf.php');
curl.setOpt('USERAGENT', 'CfDomains');
if (myproxy != '') {
curl.setOpt('HTTPPROXYTUNNEL', 1);
curl.setOpt('PROXY', 'socks5h://' + myproxy + '/');
}
curl.setOpt(Curl.option.POST, true);
curl.setOpt(Curl.option.POSTFIELDS, 'ana=' + t + '&f=' + dom);
curl.on('error', (er, ec) => {
curl.close();
console.log('\x1b[31m%s\x1b[0m', er);
forceExit('Connection Error');
});
curl.on('end', (sc, b) => {
curl.close();
if (sc != 404) {
forceExit('Server error');
}
try {
JSON.parse(b)
} catch (e1) {
forceExit('Bad Response Error');
}
console.log('Done!');
okay(b);
});
curl.perform();
});
}
async function reporters(yn) {
let dom = args[3];
if (!is_domain(dom)) {
showUsage();
}
if (!fs.existsSync(Dlist + dom[0])) {
forceExit('List not found');
}
let data = fs.readFileSync(Dlist + dom[0], {
encoding: 'utf8'
});
data = JSON.parse(data);
if (data[dom]) {
if (yn == 'y') {
forceExit('Already exist, no need to report.');
}
} else {
if (yn == 'n') {
forceExit('Already not listed, no need to report.');
}
}
if (myproxy == '') {
console.log('\x1b[36mNOTICE\x1b[0m: You are not using Tor.');
}
console.log('Reporting ' + dom);
let w = await reporter(dom, yn);
if (yn == 'y') {
if (w == '[true,true]') {
console.log('\x1b[32mResponse\x1b[0m: \x1b[33mNo\x1b[0m, It is already known.');
} else if (w == '[true,false]') {
console.log('\x1b[32mResponse\x1b[0m: \x1b[35mRequest received\x1b[0m. It is not listed in \x1b[4mdelayed\x1b[0m channel at this moment.');
} else {
forceExit('Bad Response Error!');
}
} else {
if (w == '[true,false]') {
console.log('\x1b[32mResponse\x1b[0m: \x1b[33mNo\x1b[0m, It is not listed.');
} else if (w == '[true,true]') {
console.log('\x1b[32mResponse\x1b[0m: \x1b[35mRequest received\x1b[0m. It is listed in \x1b[4mdelayed\x1b[0m channel at this moment.');
} else {
forceExit('Bad Response Error!');
}
}
process.exit();
}
if (args.length <= 2) {
showUsage();
} else if (args[2] === '--dir') {
chgLDR();
} else if (args[2] === '--proxy') {
chgPROXY();
} else if (args[2] === '--dl') {
dlFiles('https://archive.org/download/crimeflare/');
} else if (args[2] === '--dl2') {
dlFiles('https://framagit.org/dCF/deCloudflare/-/raw/master/cloudflare_users/domains/JSON/');
} else if (args[2] === '--report') {
reporters('y');
} else if (args[2] === '--delist') {
reporters('n');
} else {
queryDom();
}