├── Dockerfile ├── README.md ├── app.js ├── manutencao.js └── package.json /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mhart/alpine-node:6 2 | 3 | RUN apk add --no-cache make gcc g++ python 4 | 5 | # Create app directory 6 | RUN mkdir -p /usr/src/app 7 | WORKDIR /usr/src/app 8 | 9 | # Install app dependencies 10 | COPY package.json /usr/src/app/ 11 | RUN npm install 12 | 13 | RUN npm install pm2 -g 14 | 15 | # Bundle app source 16 | COPY . /usr/src/app 17 | 18 | EXPOSE 8000 19 | 20 | CMD [ "pm2-docker", "app.js" ] 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ISPTools 2 | 3 | Ferramenta Brasileira online para testes externos de rede. 4 | 5 | Ferramenta criada pelo Brasileiro GIOVANE HELENO para resolução de vários problemas expostos na lista “CAIU?“, reune em um portal web uma série de ferramentas simples para que você, administrador de redes/sistemas, possa tirar suas próprias conclusões sobre o status de sua estrutura de forma independente, fugindo da máxima “aqui está tudo normal, o problema deve ser aí!”. 6 | 7 | Agora Dockerizado, facilitando a instalação. 8 | 9 | ## Você vai precisar de... 10 | 11 | * Usuário não-root com privilégios sudo. 12 | * Recomendo máquina dedicada para o ISPTools, evite utilizar em máquinas com outras funções (firewall, erp, dns, etc). 13 | 14 | ## Em sua distro favorita, instale o Docker. 15 | 16 | Instruções de instalação em https://www.docker.com/get-docker 17 | 18 | Em distros mais atuais, pode tentar o instalador automático do docker, executando: 19 | 20 | ```sh 21 | $ curl -fsSL https://get.docker.com/ | sh 22 | ``` 23 | 24 | 25 | ## Faça o pull do ISPTools 26 | 27 | Execute: 28 | 29 | ```sh 30 | $ docker pull isptools/probe 31 | ``` 32 | 33 | Este comando fará o download do ISPTools para sua máquina, já totalmente configurado. 34 | 35 | ## Rode o ISPTools 36 | 37 | Execute: 38 | 39 | ```sh 40 | $ docker run --restart=always -p 8000:8000 -d isptools/probe 41 | ``` 42 | 43 | Este comando, executará o ISPTools em sua máquina, mapeando a porta 8000 (TCP) e configurando para inicializar na inicialização da máquina. 44 | 45 | 46 | ## Pronto! 47 | 48 | Agora vá em http://www.isptools.com.br/painel e ative seu servidor. 49 | 50 | 51 | 52 | ## Contribua com o código! 53 | 54 | O código do probe é aberto, contribua: 55 | 56 | https://github.com/isptools/isptools 57 | 58 | 59 | ## Dúvidas? 60 | 61 | Entre em contato contato@isptools.com.br para maiores informações. 62 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | global.version = "1.1.2"; 2 | global.updated = true; 3 | global.timeout = 5000; 4 | version = global.version; 5 | 6 | var manut = require('./manutencao'); 7 | setInterval(manut.atualizar, 60 * 60 * 1000); 8 | manut.atualizar(); 9 | 10 | var Step = require('step'); 11 | var ping = require('net-ping'); 12 | var net = require('net'); 13 | var dns = require('dns'); 14 | var url = require('url'); 15 | var http = require('http'); 16 | var https = require('https'); 17 | var express = require('express'); 18 | var app = express(); 19 | var sID = 0; 20 | var login = false; 21 | 22 | app.use(function (req, res, next) { 23 | res.header("X-powered-by", "Giovane Heleno - www.giovane.pro.br"); 24 | res.header("X-version", version); 25 | res.header("Server", "Giovane"); 26 | res.header("Access-Control-Allow-Origin", "*"); 27 | res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'); 28 | 29 | var hora = new Date().toISOString(). 30 | replace(/T/, ' '). // replace T with a space 31 | replace(/\..+/, ''); 32 | sID++; 33 | sID = (sID >= 65535) ? 0 : sID; 34 | var ipremoto = req.header('x-forwarded-for') || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress; // Get the requestor's IP 35 | console.log((hora + " - " + ipremoto + ' - ' + req.url)); // Print LOG 36 | next(); 37 | }); 38 | 39 | /** 40 | * HOME 41 | * 42 | * @date 2014-03-10 43 | * 44 | * @author Giovane Heleno - www.giovane.pro.br 45 | * 46 | * @param {[type]} req 47 | * @param {[type]} res 48 | * 49 | * @return {[type]} 50 | */ 51 | app.get('/', function (req, res) { 52 | res.json({ 53 | "version": version, 54 | "updated": global.updated, 55 | "query": req.query, 56 | "auth": login, 57 | pid: process.pid, 58 | memory: process.memoryUsage(), 59 | uptime: process.uptime() 60 | }); 61 | }); 62 | 63 | /** 64 | * PING 65 | * 66 | * @date 2014-03-10 67 | * 68 | * @author Giovane Heleno - www.giovane.pro.br 69 | * 70 | * @param {[type]} req [description] 71 | * @param {[type]} res [description] 72 | * 73 | * @return {[type]} [description] 74 | */ 75 | app.get('/PING/:id/:ttl?', function (req, res) { 76 | var attrTTL = req.params.ttl; 77 | var sent, rcvd, ms; 78 | attrTTL = (attrTTL == null) ? 128 : parseInt(trim(attrTTL)); 79 | var attrIP = req.params.id; 80 | var sessionID = req.query.sessionID; 81 | var notfound = 0; 82 | 83 | attrIP = attrIP.toString(); 84 | Step( 85 | function resolveIP() { 86 | dns.resolve(attrIP, this); 87 | }, 88 | function pingar(err, domains) { 89 | xattrIP = attrIP; 90 | if (!net.isIP(attrIP)) { 91 | if (domains == undefined) { 92 | res.json({ 93 | "datetime": Date(), 94 | "target": attrIP, 95 | "err": 'host not found', 96 | "sessionID": sessionID, 97 | "query": req.query 98 | }); 99 | notfound = 1; 100 | } else 101 | xattrIP = domains[Math.floor(Math.random() * domains.length)]; 102 | } 103 | var session = ping.createSession({ 104 | "ttl": attrTTL, 105 | 'sessionId': sID, 106 | 'retries': 2, 107 | 'timeout': (global.timeout / 3), 108 | 'networkProtocol': ping.NetworkProtocol.IPv4 109 | }); 110 | session.pingHost(xattrIP, function (err, target, sent, rcvd) { 111 | var ms = rcvd - sent; 112 | if (!notfound) 113 | res.json({ 114 | "datetime": Date(), 115 | "ip": domains, 116 | "target": xattrIP, 117 | "ms": ((ms == 0) ? 1 : ms), 118 | "ttl": attrTTL, 119 | "err": err, 120 | "sessionID": sessionID, 121 | "sID": sID, 122 | "query": req.query 123 | }); 124 | session.close(); 125 | }); 126 | } 127 | ); 128 | }); 129 | 130 | /** 131 | * DNS Tool 132 | * 133 | * @date 2014-03-10 134 | * 135 | * @author Giovane Heleno - www.giovane.pro.br 136 | * 137 | * @param {[type]} req [description] 138 | * @param {[type]} res [description] 139 | * 140 | * @return {[type]} [description] 141 | */ 142 | app.get('/DNS/:method/:id', function (req, res) { 143 | var attrIP = req.params.id; 144 | var method = req.params.method; 145 | attrIP = attrIP.toString(); 146 | method = method.toString().toUpperCase(); 147 | if (method == "PTR" && !net.isIP(attrIP)) { 148 | res.json({ 149 | "datetime": Date(), 150 | "method": method, 151 | "host": attrIP, 152 | "err": { 153 | code: 'BADFAMILY' 154 | }, 155 | "ipv": (net.isIP(attrIP) ? (net.isIPv6(attrIP) ? 6 : 4) : 0), 156 | "query": req.query 157 | }); 158 | } else 159 | dns.resolve(attrIP, method, function (err, domains) { 160 | res.json({ 161 | "datetime": Date(), 162 | "method": method, 163 | "host": attrIP, 164 | "result": domains, 165 | "err": err, 166 | "ipv": (net.isIP(attrIP) ? (net.isIPv6(attrIP) ? 6 : 4) : 0), 167 | "query": req.query 168 | }); 169 | }); 170 | }); 171 | 172 | /** 173 | * HTTP Tool 174 | * 175 | * @date 2014-03-10 176 | * 177 | * @author Giovane Heleno - www.giovane.pro.br 178 | * 179 | * @param {[type]} req [description] 180 | * @param {[type]} res [description] 181 | * 182 | * @return {[type]} [description] 183 | */ 184 | 185 | app.get('/HTTP/:id', function (req, res) { 186 | var attrIP = req.params.id; 187 | attrIP = new Buffer(attrIP, 'base64').toString('ascii'); 188 | //attrIP = attrIP.toString(); 189 | if (url.parse(attrIP).protocol == null) { 190 | attrIP = "http://" + attrIP; 191 | } 192 | 193 | attrIPoriginal = attrIP; 194 | attrIP = injection(attrIP); 195 | if (url.parse(attrIP).protocol == 'http:') { 196 | var httpreq = http.get(attrIP, function (e) { 197 | res.json({ 198 | "datetime": Date(), 199 | "url": url.parse(attrIPoriginal), 200 | "status": e.statusCode, 201 | "response": e.headers, 202 | "err": null, 203 | "query": req.query 204 | }); 205 | }) 206 | .on('error', function (e) { 207 | res.json({ 208 | "datetime": Date(), 209 | "url": attrIP, 210 | "err": (e.message == 'socket hang up') ? 'TIMEOUT' : e.message, 211 | "query": req.query 212 | }); 213 | }); 214 | httpreq.setTimeout(global.timeout, function () { 215 | httpreq.abort(); 216 | }); 217 | } else if (url.parse(attrIP).protocol == 'https:') { 218 | var httpsreq = https.get(attrIP, function (e) { 219 | res.json({ 220 | "datetime": Date(), 221 | "url": url.parse(attrIP), 222 | "status": e.statusCode, 223 | "response": e.headers, 224 | "err": null, 225 | "query": req.query 226 | }); 227 | }) 228 | .on('error', function (e) { 229 | res.json({ 230 | "datetime": Date(), 231 | "url": attrIP, 232 | "err": (e.message == 'socket hang up') ? 'TIMEOUT' : e.message, 233 | "query": req.query 234 | }); 235 | }); 236 | httpsreq.setTimeout(global.timeout, function () { 237 | httpsreq.abort(); 238 | }); 239 | } else 240 | res.json({ 241 | "datetime": Date(), 242 | "url": attrIP, 243 | "err": "invalid URL - need URL encoded - HTTP/HTTPS only", 244 | "query": req.query 245 | }); 246 | 247 | }); 248 | 249 | /** 250 | * Habilita servidor porta 8000 251 | */ 252 | var serverPort = process.env.OPENSHIFT_NODEJS_PORT || 8000; 253 | var server = app.listen(serverPort, function () { 254 | 255 | console.log(''); 256 | console.log(''); 257 | console.log(''); 258 | console.log('------------------------------------------------------'); 259 | console.log('- ISP Tools - www.isptools.com.br -'); 260 | console.log('- Giovane Heleno (www.giovane.pro.br) -'); 261 | console.log('------------------------------------------------------'); 262 | console.log('Service started... litening port %d.', server.address().port); 263 | console.log(''); 264 | console.log(''); 265 | console.log(''); 266 | 267 | }); 268 | 269 | 270 | 271 | /** 272 | * Functions 273 | */ 274 | 275 | // TRIM 276 | var trim = function (s) { 277 | var m = s.length; 278 | 279 | for (var i = 0; i < m && s.charCodeAt(i) < 33; i++) {} 280 | for (var j = m - 1; j > i && s.charCodeAt(j) < 33; j--) {} 281 | 282 | return s.substring(i, j + 1); 283 | }; 284 | 285 | function injection(x) { 286 | var urlparse = url.parse(x); 287 | delete urlparse["query"]; 288 | delete urlparse["search"]; 289 | return url.format(urlparse); 290 | } 291 | -------------------------------------------------------------------------------- /manutencao.js: -------------------------------------------------------------------------------- 1 | var sys = require('sys'); 2 | var http = require('http'); 3 | var colors = require('colors'); 4 | var exec = require('child_process').exec; 5 | 6 | module.exports = { 7 | atualizar: function () { 8 | 9 | http.get('http://www.isptools.com.br/ok/version/?nocache='+(new Date()).getTime(), function (e) { 10 | e.on('data', function (body) { 11 | if(version_compare(body,global.version)>0) { 12 | global.updated = false; 13 | console.log(' '.inverse.yellow); 14 | console.log(' Necessário ATUALIZAR '.inverse.yellow); 15 | console.log(' '.inverse.yellow); 16 | console.log(''); 17 | console.log('Versão Atual: '+global.version); 18 | console.log('Nova Versão: '+body); 19 | console.log(''); 20 | console.log('Instruções em:'); 21 | console.log('http://www.isptools.com.br/atualizar'.cyan); 22 | console.log('------------------------------------------------------------------'.yellow); 23 | 24 | executa('sudo at -f upgrade.sh -v now + 1 minutes'); 25 | 26 | exec('echo "\n\n+-----------------------------------------+\n| ISP Tools DESATUALIZADO. |\n| |\n| Acesse: |\n| http://www.isptools.com.br/atualizar |\n+-----------------------------------------+\n\n " | wall'); 27 | 28 | } 29 | }); 30 | }); 31 | 32 | 33 | return true; 34 | } 35 | }; 36 | 37 | function executa(comando) { 38 | exec(comando, function (error, stdout, stderr) { 39 | console.log('stdout: ' + stdout); 40 | console.log('stderr: ' + stderr); 41 | if (error !== null) { 42 | console.log('exec error: ' + error); 43 | } 44 | }); 45 | } 46 | 47 | 48 | /** 49 | * Compara versão 50 | * @param {[type]} v1 Versão 1 51 | * @param {[type]} v2 Versão 2 52 | * @param {[type]} operator Operador de comparação 53 | */ 54 | function version_compare(v1, v2, operator) { 55 | // discuss at: http://phpjs.org/functions/version_compare/ 56 | // original by: Philippe Jausions (http://pear.php.net/user/jausions) 57 | // original by: Aidan Lister (http://aidanlister.com/) 58 | // reimplemented by: Kankrelune (http://www.webfaktory.info/) 59 | // improved by: Brett Zamir (http://brett-zamir.me) 60 | // improved by: Scott Baker 61 | // improved by: Theriault 62 | // example 1: version_compare('8.2.5rc', '8.2.5a'); 63 | // returns 1: 1 64 | // example 2: version_compare('8.2.50', '8.2.52', '<'); 65 | // returns 2: true 66 | // example 3: version_compare('5.3.0-dev', '5.3.0'); 67 | // returns 3: -1 68 | // example 4: version_compare('4.1.0.52','4.01.0.51'); 69 | // returns 4: 1 70 | 71 | this.php_js = this.php_js || {}; 72 | this.php_js.ENV = this.php_js.ENV || {}; 73 | // END REDUNDANT 74 | // Important: compare must be initialized at 0. 75 | var i = 0, 76 | x = 0, 77 | compare = 0, 78 | // vm maps textual PHP versions to negatives so they're less than 0. 79 | // PHP currently defines these as CASE-SENSITIVE. It is important to 80 | // leave these as negatives so that they can come before numerical versions 81 | // and as if no letters were there to begin with. 82 | // (1alpha is < 1 and < 1.1 but > 1dev1) 83 | // If a non-numerical value can't be mapped to this table, it receives 84 | // -7 as its value. 85 | vm = { 86 | 'dev': -6, 87 | 'alpha': -5, 88 | 'a': -5, 89 | 'beta': -4, 90 | 'b': -4, 91 | 'RC': -3, 92 | 'rc': -3, 93 | '#': -2, 94 | 'p': 1, 95 | 'pl': 1 96 | }, 97 | // This function will be called to prepare each version argument. 98 | // It replaces every _, -, and + with a dot. 99 | // It surrounds any nonsequence of numbers/dots with dots. 100 | // It replaces sequences of dots with a single dot. 101 | // version_compare('4..0', '4.0') == 0 102 | // Important: A string of 0 length needs to be converted into a value 103 | // even less than an unexisting value in vm (-7), hence [-8]. 104 | // It's also important to not strip spaces because of this. 105 | // version_compare('', ' ') == 1 106 | prepVersion = function(v) { 107 | v = ('' + v) 108 | .replace(/[_\-+]/g, '.'); 109 | v = v.replace(/([^.\d]+)/g, '.$1.') 110 | .replace(/\.{2,}/g, '.'); 111 | return (!v.length ? [-8] : v.split('.')); 112 | }; 113 | // This converts a version component to a number. 114 | // Empty component becomes 0. 115 | // Non-numerical component becomes a negative number. 116 | // Numerical component becomes itself as an integer. 117 | numVersion = function(v) { 118 | return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); 119 | }; 120 | v1 = prepVersion(v1); 121 | v2 = prepVersion(v2); 122 | x = Math.max(v1.length, v2.length); 123 | for (i = 0; i < x; i++) { 124 | if (v1[i] == v2[i]) { 125 | continue; 126 | } 127 | v1[i] = numVersion(v1[i]); 128 | v2[i] = numVersion(v2[i]); 129 | if (v1[i] < v2[i]) { 130 | compare = -1; 131 | break; 132 | } else if (v1[i] > v2[i]) { 133 | compare = 1; 134 | break; 135 | } 136 | } 137 | if (!operator) { 138 | return compare; 139 | } 140 | 141 | // Important: operator is CASE-SENSITIVE. 142 | // "No operator" seems to be treated as "<." 143 | // Any other values seem to make the function return null. 144 | switch (operator) { 145 | case '>': 146 | case 'gt': 147 | return (compare > 0); 148 | case '>=': 149 | case 'ge': 150 | return (compare >= 0); 151 | case '<=': 152 | case 'le': 153 | return (compare <= 0); 154 | case '==': 155 | case '=': 156 | case 'eq': 157 | return (compare === 0); 158 | case '<>': 159 | case '!=': 160 | case 'ne': 161 | return (compare !== 0); 162 | case '': 163 | case '<': 164 | case 'lt': 165 | return (compare < 0); 166 | default: 167 | return null; 168 | } 169 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ISPTools", 3 | "version": "1.1.2", 4 | "private": true, 5 | "description": "Ferramentas para ISP", 6 | "main": "app.js", 7 | "dependencies": { 8 | "colors": "0.6.x", 9 | "express": "3.4.x", 10 | "net-ping": "1.1.x", 11 | "step": "0.0.x" 12 | }, 13 | "scripts": { 14 | "start": "node app.js" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/giovaneh/isptools.git" 19 | }, 20 | "author": "Giovane Heleno", 21 | "license": "MIT" 22 | } 23 | --------------------------------------------------------------------------------