Last active
December 2, 2016 16:57
-
-
Save spacelatte/bf29f658a10e6259b98d362a243190b2 to your computer and use it in GitHub Desktop.
check whois, ssl cert and smtp from node.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
const fs = require("fs"); | |
const tls = require("tls"); | |
const net = require("net"); | |
const dns = require("dns"); | |
const whois = require("whois"); | |
const sql = require("sql.js"); | |
const whoistabname = "whois"; | |
const certtabname = "cert"; | |
const smtptabname = "smtp"; | |
const _domain = "e.x.a.m.p.l.e.com"; | |
const default_cooldown = 111; | |
const mail_user = "n0r3ply"; | |
const def_tout_val = 999; | |
var db = null; | |
const matchtable = { | |
"tr": [ | |
"expires on", | |
], | |
"com": [ | |
"expiration date", | |
"expiry date", | |
], | |
"net": [ | |
"expiration date", | |
], | |
"org": [ | |
"expiry date", | |
], | |
"me": [ | |
"expiry date", | |
], | |
"io": [ | |
"expiry", | |
], | |
"co": [ | |
"domain expiration date", | |
], | |
}; | |
const matchfunc = { | |
"local": function(arg) { | |
return arg.split(":").slice(1).join(":").trim(); | |
}, | |
"space": function(arg) { | |
return this.local(arg.replace(/ /g,"")); | |
}, | |
"verisign": function(arg) { | |
if('\r' == arg[arg.length-1]) { | |
arg = arg.substring(0,arg.length-2); // removal of carriage return; | |
// } else if('Z' != arg[arg.length-1]) { | |
// arg += 'Z'; | |
} | |
return matchfunc.local(arg); | |
}, | |
"tr": [ | |
function(arg) { | |
return matchfunc.space(arg); | |
}, | |
], | |
"com": [ | |
function(arg) { | |
return matchfunc.verisign(arg); | |
}, | |
function(arg) { | |
return matchfunc.local(arg); | |
}, | |
], | |
"net": [ | |
function(arg) { | |
return matchfunc.verisign(arg); | |
}, | |
], | |
"org": [ | |
function(arg) { | |
return matchfunc.space(arg); | |
}, | |
], | |
"me": [ | |
function(arg) { | |
return matchfunc.space(arg); | |
}, | |
], | |
"io": [ | |
function(arg) { | |
return matchfunc.space(arg); | |
}, | |
], | |
"co": [ | |
function(arg) { | |
return matchfunc.local(arg.replace(/\s+/g," ")); | |
}, | |
], | |
}; | |
function check(host,delay) { | |
// var dt = Date.now(); while(dt+delay > Date.now()) continue; | |
// get tld | |
var tld = host.split(".").pop(); | |
whois.lookup(host, { | |
"server": null, | |
"follow": 5, | |
"timeout": 0, | |
"verbose": false, | |
}, | |
function(err, data, addr) { | |
if(err) { | |
return console.log("[fail] whois network:", err.code, ":", err.errno, host); | |
} | |
data = data.split("\n"); | |
var dates = []; | |
data.forEach(function(line,index,orig) { | |
for(i=0;i<matchtable[tld].length;i++) { | |
if(line.toLowerCase().indexOf(matchtable[tld][i]) > -1) { | |
dates.push(matchfunc[tld][i](line)); | |
} | |
} | |
}); | |
var str = dates.join(null); | |
//str = str.split("T")[0]; | |
var d = new Date(str); | |
if(str == null || d.getTime().toString().indexOf("NaN") >= 0) { | |
return console.log("[fail] whois response:", host, [data.join("\r")]); | |
} | |
try { | |
db.run("insert into" | |
+ " '" + whoistabname + "' " | |
+ "values(null,:host,:time);", { | |
":host": host, | |
":time": d.getTime(), | |
} | |
); | |
} catch(e) { | |
db.run("update" | |
+ " '" + whoistabname + "' " | |
+ "set exp = " | |
+ " '"+d.getTime()+"' " | |
+ "where host = " | |
+ " '" + host + "' " + ";" | |
); | |
} | |
console.log("[ ok ] whois:", d, host); | |
return; | |
} | |
); | |
//let types = tls.getCiphers(); | |
//types.push(null); | |
[null].forEach(function(ctype,ci,clist) { | |
var conn = tls.connect(443, host, { | |
"rejectUnauthorized":false, | |
"ciphers": ctype, | |
}, function() { | |
cert = this.getPeerCertificate(true); | |
cert_dates = [ | |
new Date(cert.valid_from), | |
new Date(cert.valid_to), | |
]; | |
// console.log(this.getProtocol(), host, cert_dates, | |
// cert.valid_from, cert.valid_to, cert.subjectaltname); | |
if(this.getProtocol === undefined) { | |
this.getProtocol = function() { | |
return null; | |
}; | |
} | |
cert.subjectaltname = cert.subjectaltname.replace(/, /g, "\n"); | |
try { | |
db.run("insert into" | |
+" '"+certtabname+"' " | |
+" values(null,:host,:cs,:ce,:dns,:prot);", { | |
":host": host, | |
":cs": cert_dates[0].getTime(), | |
":ce": cert_dates[1].getTime(), | |
":dns": cert.subjectaltname, | |
":prot": this.getProtocol(), | |
} | |
); | |
} catch(e) { | |
db.run("update '"+certtabname+"' set " | |
+ " 'cert_start' = '" + cert_dates[0].getTime() + "'," | |
+ " 'cert_end' = '" + cert_dates[1].getTime() + "'," | |
+ " 'dns' = '" + cert.subjectaltname + "'," | |
+ " 'prot' = '" + this.getProtocol() + "' " | |
+ " where " | |
+ " host = '" + host + "' " | |
+ " ;" | |
); | |
} | |
console.log("[ ok ] certificate:", | |
cert_dates[0],cert_dates[1], | |
this.getProtocol(), ctype, host | |
); | |
this.destroy(); | |
return; | |
}); | |
conn.on("error", function(err) { | |
console.log("[fail] certificate:", host, err.toString().split("\n")[0], ctype ); | |
return; | |
}); | |
setTimeout(function() { | |
conn.destroy(); | |
return; | |
},def_tout_val); | |
return; | |
}); | |
dns.resolveMx(host,function(err,addr) { | |
if(addr == null) { | |
return console.log("[fail] smtp n/w:", host, err); | |
} | |
var is_relay = 0; | |
var servers = []; | |
addr.forEach(function(elem,index,array) { | |
servers.push(elem.exchange); | |
var smtp = net.connect(25, elem.exchange, function(e,a) { | |
smtp.on("data", function(data) { | |
data.toString().split("\r\n").forEach(function(elem,index,array) { | |
if(parseInt(elem.split(" ")[0]) == 354) { | |
is_relay |= 1; | |
return; | |
} else if(parseInt(elem.split(" ")[0]) == 550) { | |
is_relay |= 0; | |
return; | |
} | |
return; | |
}); | |
return; | |
}); | |
var mc = []; | |
mc.push("HELO " + host + ""); | |
mc.push("MAIL FROM: " + mail_user + "@" + host + " "); | |
mc.push("RCPT TO: " + mail_user + "@" + _domain + " "); | |
// mc.push("DATA"); | |
// mc.push("Open Relay Test"); | |
// mc.push("."); | |
mc.push("QUIT"); | |
smtp.write(mc.join("\r\n")); | |
setTimeout(function() { | |
smtp.destroy(); | |
return; | |
},def_tout_val); | |
// console.log(mc.join("\n")); | |
return; | |
}); | |
smtp.on("error", function(err) { | |
console.log("[fail] smtp:", host, addr, err.code, ":", err.errno); | |
return; | |
}); | |
return; | |
}); | |
console.log("[ ok ] smtp:", host, servers.join(", "), | |
(is_relay?"RELAY DETECTED!":"") | |
); | |
try { | |
db.run("insert into" | |
+ " '" + smtptabname + "' " | |
+ "values(null,:host,:mx,:relay);", { | |
":host": host, | |
":mx": servers.join(",\n"), | |
":relay": is_relay, | |
} | |
); | |
} catch(e) { | |
db.run("update" | |
+ " '" + smtptabname + "' " | |
+ "set relay = " | |
+ " '" + is_relay + "', " | |
+ " servers = " | |
+ " '" + servers.join(",\n") + "' " | |
+ "where host = " | |
+ " '" + host + "' " + ";" | |
); | |
} | |
return; | |
}); | |
return; | |
} | |
function dbinit(filename) { | |
try { | |
fs.statSync(filename); | |
} catch(e) { | |
fs.closeSync( | |
fs.openSync(filename,"w") | |
); | |
} | |
db = new sql.Database( | |
fs.readFileSync( | |
filename,{ | |
"flag":"r", | |
} | |
) | |
); | |
db.exec("create table if not exists" | |
+ " '" + whoistabname + "' " | |
+ " ( " | |
+ " id integer primary key," | |
+ " host text not null unique," | |
+ " exp integer not null" | |
+ " );" | |
); | |
db.exec("create table if not exists" | |
+ " '" + certtabname + "' " | |
+ " (" | |
+ " id integer primary key," | |
+ " host text not null unique," | |
+ " cert_start int," | |
+ " cert_end int," | |
+ " dns text," | |
+ " prot text" | |
+ " );" | |
); | |
db.exec("create table if not exists" | |
+ " '" + smtptabname + "' " | |
+ " (" | |
+ " id integer primary key," | |
+ " host text not null unique," | |
+ " servers text," | |
+ " relay int not null" | |
+ " );" | |
); | |
return; | |
} | |
function dbsave(filename) { | |
fs.writeFileSync(filename, | |
new Buffer(db.export())); | |
return; | |
} | |
if(require.main === module) { | |
if(process.argv.length <= 2) { | |
console.log("arg missing"); | |
return; | |
} | |
console.log("starting..."); | |
dbinit(process.argv[2]); | |
process.on("beforeExit", function() { | |
dbsave(process.argv[2]); | |
}); | |
var chost = null; | |
switch(process.argv[3]) { | |
case "update": | |
var res = db.exec("select host from" | |
+ " ( " | |
+ " select host from " | |
+ " '" + certtabname + "' " | |
+ " union all " | |
+ " select host from " | |
+ " '" + whoistabname + "' " | |
+ " union all " | |
+ " select host from " | |
+ " '" + smtptabname + "' " | |
+ " ) " | |
+ " group by host " | |
+ " ;" | |
); | |
if(!res || res.length < 1) { | |
break; | |
} | |
for(i=0;i<res[0].values.length;i++) { | |
chost = res[0].values[i][0]; | |
// setTimeout(function() { | |
check(chost, default_cooldown); | |
// return; | |
// },i*default_cooldown); | |
continue; | |
} | |
break; | |
default: | |
for(var i=3;i<process.argv.length;i++) { | |
chost = process.argv[i]; | |
// setTimeout(function() { | |
check(chost, default_cooldown); | |
// return; | |
// },i*default_cooldown); | |
continue; | |
} | |
break; | |
} | |
return; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
NODE = node | |
FLAGS = --harmony | |
DBNAME = test.db | |
MAINFN = checker.js | |
SQLITE = sqlite3 | |
%.org %.com %.net %.co %.tr %.io %.me: | |
$(NODE) $(FLAGS) $(MAINFN) $(DBNAME) $@ | |
auto: init | |
$(NODE) $(FLAGS) $(MAINFN) $(DBNAME) $$(cat hosts.txt | tr \\n \ ) | |
init: node_modules | |
npm install | |
node_modules: | |
-mkdir -p $@ | |
update: | |
$(NODE) $(FLAGS) $(MAINFN) $(DBNAME) $@ | |
%.test: | |
$(SQLITE) $(DBNAME) "select * from $$(basename $@ .test)"; | |
test: whois.test cert.test smtp.test | |
$(SQLITE) $(DBNAME) ".tables" | |
.PHONY: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "lcheck", | |
"version": "0.1.0", | |
"description": "check various net info from external sources", | |
"main": "main.js", | |
"dependencies": { | |
"sql.js": "^0.3.2", | |
"whois": "^2.1.6" | |
}, | |
"devDependencies": {}, | |
"scripts": { | |
"test": "node main.js save.db google.com" | |
}, | |
"keywords": [ | |
"whois", | |
"check", | |
"network", | |
"sqlite" | |
], | |
"author": "mert akengin", | |
"license": "ISC", | |
"repository": { | |
"type": "git", | |
"url": "http://gist.github.com/pvtmert/bf29f658a10e6259b98d362a243190b2" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment