UNPKG

@xyz/whois

Version:

A powerful TypeScript/JavaScript tool for comprehensive domain analysis, featuring detailed WHOIS data with registration dates, registrars, and domain status. Offers SSL certificate extraction (with PEM support), DNS records, and server details. Includes

189 lines (188 loc) 8.19 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.queryWhoisServer = queryWhoisServer; exports.followWhoisReferrals = followWhoisReferrals; const net_1 = require("net"); const tls = __importStar(require("tls")); const dns = __importStar(require("dns")); const referral_1 = require("./patterns/referral"); const logger_1 = __importDefault(require("./logger")); /** * Queries a WHOIS server for domain information * @param domain The domain to query * @param server The WHOIS server to query * @param timeout Timeout in milliseconds * @param debug Whether to enable debug logging * @returns Promise resolving to the raw WHOIS response */ async function queryWhoisServer(domain, server, timeout = 10000, debug = false) { return new Promise((resolve, reject) => { logger_1.default.logInfo(debug, 'Querying WHOIS server', `${server} for domain ${domain}`); try { // Resolve the WHOIS server hostname to an IP address dns.lookup(server, (err, address) => { if (err) { logger_1.default.logError(debug, 'DNS lookup', err); reject(new Error(`Failed to resolve WHOIS server: ${err.message}`)); return; } // First try with TLS const tlsSocket = tls.connect({ host: server, port: 43, rejectUnauthorized: false, // Allow self-signed certificates servername: server, // SNI support }); let data = ''; let triedPlain = false; tlsSocket.setTimeout(timeout); tlsSocket.on('timeout', () => { logger_1.default.logError(debug, 'WHOIS query', 'Connection timeout'); tlsSocket.destroy(); reject(new Error('Connection timeout')); }); tlsSocket.on('error', (error) => { if (!triedPlain && error.message.includes('EPROTO')) { // If TLS fails, try plain TCP triedPlain = true; const plainSocket = new net_1.Socket(); plainSocket.setTimeout(timeout); data = ''; plainSocket.on('timeout', () => { logger_1.default.logError(debug, 'WHOIS query', 'Connection timeout'); plainSocket.destroy(); reject(new Error('Connection timeout')); }); plainSocket.on('error', (error) => { logger_1.default.logError(debug, 'WHOIS query', error); reject(error); }); plainSocket.on('data', (chunk) => { data += chunk.toString(); }); plainSocket.on('end', () => { logger_1.default.logInfo(debug, 'WHOIS query', 'Connection closed'); resolve(data); }); plainSocket.connect(43, address, () => { logger_1.default.logInfo(debug, 'WHOIS query', `Connected to ${server} (${address}) via plain TCP`); plainSocket.write(`${domain}\r\n`); }); } else { logger_1.default.logError(debug, 'WHOIS query', error); reject(error); } }); tlsSocket.on('data', (chunk) => { data += chunk.toString(); }); tlsSocket.on('end', () => { logger_1.default.logInfo(debug, 'WHOIS query', 'Connection closed'); resolve(data); }); tlsSocket.on('secureConnect', () => { logger_1.default.logInfo(debug, 'WHOIS query', `Connected to ${server} (${address}) via TLS`); tlsSocket.write(`${domain}\r\n`); }); }); } catch (error) { logger_1.default.logError(debug, 'WHOIS query', error); reject(error); } }); } /** * Follows WHOIS server referrals to get the most complete data * @param domain The domain to query * @param initialServer The initial WHOIS server to query * @param maxReferrals Maximum number of referrals to follow * @param debug Whether to enable debug logging * @returns Promise resolving to the combined WHOIS response */ async function followWhoisReferrals(domain, initialServer, maxReferrals = 3, debug = false) { let response = await queryWhoisServer(domain, initialServer, 10000, debug); let currentServer = initialServer; let referralCount = 0; let finalResponse = response; if (debug) { console.log(`\n[DEBUG] Starting referral chain from ${initialServer}`); } // Check for WHOIS server redirection and follow if found while (referralCount < maxReferrals) { const nextServer = (0, referral_1.findReferralServer)(response, currentServer); if (nextServer) { if (debug) { console.log(`[DEBUG] Found referral to ${nextServer}`); } // Follow the referral try { const nextResponse = await queryWhoisServer(domain, nextServer, 10000, debug); // If we get a meaningful response (not just a referral back) if (nextResponse && nextResponse.length > 100) { response = nextResponse; finalResponse += '\n\n# ' + nextServer + '\n\n' + nextResponse; currentServer = nextServer; } } catch (error) { // If the referral fails, just use what we have if (debug) { console.warn(`[DEBUG] Failed to follow WHOIS referral: ${error instanceof Error ? error.message : String(error)}`); } break; } } else { if (debug) { console.log('[DEBUG] No more referrals found'); } break; } referralCount++; } if (debug) { console.log(`\n[DEBUG] Final combined response:`); console.log('='.repeat(80)); console.log(finalResponse); console.log('='.repeat(80)); } return finalResponse; }