Queries multiple public resolvers via DNS-over-HTTPS (DoH), lists per-resolver answers, aggregates unique IPs, and can �ping� (HTTP/TCP reachability) each IP to see if services are up.
// server.js
// ICMP ping + TCP port check + DoH proxy to avoid CORS
const express = require('express');
const fetch = require('node-fetch');
const net = require('net');
const ping = require('ping'); // npm i express node-fetch ping
const app = express();
// CORS
app.use((_,res,next)=>{res.set('Access-Control-Allow-Origin','*'); next();});
// DoH proxy (optional)
app.get('/proxy', async (req,res)=>{
const url = req.query.u;
if(!url) return res.status(400).json({error:'missing u'});
try{
const r = await fetch(url,{headers:{'Accept':'application/dns-json'}});
const txt = await r.text();
res.set('Content-Type', r.headers.get('content-type')||'application/json');
res.send(txt);
}catch(e){ res.status(502).json({error:String(e)}) }
});
// ICMP + TCP check
app.get('/check', async (req,res)=>{
const ip = req.query.ip; // required
const ports = (req.query.ports||'80,443').split(',').map(p=>parseInt(p,10)).filter(Boolean);
if(!ip) return res.status(400).json({error:'missing ip'});
// ICMP
let icmp = null;
try{
const pr = await ping.promise.probe(ip,{timeout:2});
icmp = {alive: pr.alive, time_ms: pr.time ? Number(pr.time) : null};
}catch{icmp = {alive:null,time_ms:null}}
// TCP ports
async function checkPort(port, timeout=2000){
return new Promise(resolve=>{
const start = Date.now();
const sock = net.createConnection({host:ip,port,timeout}, ()=> {
const ms = Date.now()-start;
sock.destroy();
resolve({port, status:'open', time_ms:ms});
});
sock.on('timeout',()=>{sock.destroy(); resolve({port,status:'timeout',time_ms:timeout});});
sock.on('error',err=>{resolve({port,status:err.code||'error',time_ms:null});});
});
}
const tcp = await Promise.all(ports.map(p=>checkPort(p)));
res.json({ip, icmp, tcp, when: new Date().toISOString()});
});
app.listen(3000,()=>console.log('Checker listening on :3000'));