// whois.js - 域名信息查询页面功能 // 全局变量 let whoisChart = null; let currentDomain = ''; // 模拟的 ICP 备案信息(作为备用) function generateMockICPInfo(domain) { const mockICP = [ { company: '华为软件技术有限公司', license: '苏 ICP 备 17040376 号 -24', type: '企业', date: '2025-04-22 09:32:23' }, { company: '腾讯科技(深圳)有限公司', license: '粤 ICP 备 10045678 号 -12', type: '企业', date: '2024-12-15 14:20:10' }, { company: '阿里巴巴云计算(北京)有限公司', license: '京 ICP 备 15023456 号 -8', type: '企业', date: '2025-01-08 11:45:30' }, { company: '百度在线网络技术有限公司', license: '京 ICP 备 12034567 号 -5', type: '企业', date: '2024-11-20 16:15:45' } ]; // 根据域名选择一个 ICP 信息 const index = domain.length % mockICP.length; return mockICP[index]; } // 模拟的 DNS 解析结果 function generateMockDNSResults(domain) { const locations = ['中国 - 江苏省', '中国 - 广东省', '中国 - 浙江省', '中国 - 上海市', '中国 - 北京市']; const carriers = ['中国电信', '中国联通', '中国移动', '中国教育网', '中国科技网']; const results = []; const count = 16 + Math.floor(Math.random() * 10); for (let i = 0; i < count; i++) { const ip = `${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}`; const location = locations[Math.floor(Math.random() * locations.length)]; const carrier = carriers[Math.floor(Math.random() * carriers.length)]; results.push({ ip: ip, location: location, carrier: carrier }); } return results; } // 模拟的访问趋势数据 function generateMockTrendData() { const labels = []; const totalData = []; const threatData = []; const blockData = []; // 生成最近 30 天的数据 const now = new Date(); for (let i = 29; i >= 0; i--) { const date = new Date(now); date.setDate(date.getDate() - i); labels.push(`${date.getMonth() + 1}-${date.getDate()}`); // 生成随机数据 const total = Math.floor(Math.random() * 100000) + 50000; const threat = Math.floor(Math.random() * 1000); const block = Math.floor(Math.random() * 5000); totalData.push(total); threatData.push(threat); blockData.push(block); } return { labels: labels, totalData: totalData, threatData: threatData, blockData: blockData }; } // 调用 WHOIS API async function fetchWhoisInfo(domain) { try { const response = await fetch(`https://uapis.cn/api/v1/network/whois?domain=${encodeURIComponent(domain)}`, { method: 'GET', headers: { 'Authorization': 'Bearer uapi-pnhxbxhkCYUhyS-3r45avJLjTB-qEB8HaNMDzmrT' } }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); return data; } catch (error) { console.error('获取 WHOIS 信息失败:', error); throw error; } } // 调用 ICP 备案信息 API async function fetchICPInfo(domain) { try { const response = await fetch(`https://uapis.cn/api/v1/network/icp?domain=${encodeURIComponent(domain)}`, { method: 'GET', headers: { 'Authorization': 'Bearer uapi-pnhxbxhkCYUhyS-3r45avJLjTB-qEB8HaNMDzmrT' } }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); return data; } catch (error) { console.error('获取 ICP 备案信息失败:', error); throw error; } } // 解析字符串格式的 WHOIS 信息 function parseWhoisString(whoisString) { const result = { registrant: '-', created: '-', email: '-', expires: '-', registrar: '-', nameservers: '-' }; if (!whoisString) { return result; } const lines = whoisString.split('\n'); for (const line of lines) { const trimmedLine = line.trim(); // 注册者 if (trimmedLine.startsWith('Registrant: ')) { const value = trimmedLine.substring('Registrant: '.length).trim(); if (value) { result.registrant = value; } } // 注册邮箱 else if (trimmedLine.startsWith('Registrant Contact Email: ')) { const value = trimmedLine.substring('Registrant Contact Email: '.length).trim(); if (value) { result.email = value; } } // 注册时间 else if (trimmedLine.startsWith('Registration Time: ')) { const value = trimmedLine.substring('Registration Time: '.length).trim(); if (value) { result.created = value; } } // 过期时间 else if (trimmedLine.startsWith('Expiration Time: ')) { const value = trimmedLine.substring('Expiration Time: '.length).trim(); if (value) { result.expires = value; } } // 域名服务商 else if (trimmedLine.startsWith('Sponsoring Registrar: ')) { const value = trimmedLine.substring('Sponsoring Registrar: '.length).trim(); if (value) { result.registrar = value; } } // 域名服务器 else if (trimmedLine.startsWith('Name Server: ')) { const value = trimmedLine.substring('Name Server: '.length).trim(); if (value) { if (result.nameservers === '-') { result.nameservers = value; } else { result.nameservers += ', ' + value; } } } } return result; } // 格式化 WHOIS 信息 function formatWhoisInfo(whoisData) { const result = { registrant: '-', created: '-', email: '-', expires: '-', registrar: '-', nameservers: '-' }; // 处理 API 返回字符串的情况 if (!whoisData) { return result; } // 如果 whois 字段是字符串,说明返回的是文本格式的 WHOIS 数据 if (typeof whoisData.whois === 'string') { return parseWhoisString(whoisData.whois); } if (!whoisData.whois) { return result; } const whois = whoisData.whois; const domain = whois.domain || {}; const registrar = whois.registrar || {}; const registrant = whois.registrant || {}; // 处理注册者信息(优先使用 registrant,没有则显示域名服务商) if (registrant.name) { if (registrant.name.includes('REDACTED FOR PRIVACY') || registrant.name === 'REDACTED FOR PRIVACY') { result.registrant = '该域名已开通隐私保护'; } else { result.registrant = registrant.name; } } else if (registrant.organization) { if (registrant.organization.includes('REDACTED FOR PRIVACY') || registrant.organization === 'REDACTED FOR PRIVACY') { result.registrant = '该域名已开通隐私保护'; } else { result.registrant = registrant.organization; } } else { // 如果没有注册者信息,默认显示隐私保护 result.registrant = '该域名已开通隐私保护'; } // 处理注册时间 if (domain.created_date_in_time) { result.created = domain.created_date_in_time.replace('T', ' ').replace('Z', ''); } else if (domain.created_date) { result.created = domain.created_date.replace('T', ' ').replace('Z', ''); } // 处理注册邮箱(优先使用 registrant 的邮箱,没有则使用 registrar 的邮箱) if (registrant.email) { if (registrant.email.includes('REDACTED FOR PRIVACY') || registrant.email === 'REDACTED FOR PRIVACY') { result.email = '该域名已开通隐私保护'; } else { result.email = registrant.email; } } else if (registrar.email) { result.email = registrar.email; } // 处理过期时间 if (domain.expiration_date_in_time) { result.expires = domain.expiration_date_in_time.replace('T', ' ').replace('Z', ''); } else if (domain.expiration_date) { result.expires = domain.expiration_date.replace('T', ' ').replace('Z', ''); } // 处理域名服务商 if (registrar.name) { result.registrar = registrar.name; } // 处理域名服务器 if (domain.name_servers && Array.isArray(domain.name_servers)) { result.nameservers = domain.name_servers.join(', '); } else if (domain.name_servers && typeof domain.name_servers === 'string') { result.nameservers = domain.name_servers; } return result; } // 格式化 ICP 备案信息 function formatICPInfo(icpData) { const result = { company: '-', license: '-', type: '-', date: '-' }; if (!icpData || icpData.code !== '200') { return result; } if (icpData.unitName) { result.company = icpData.unitName; } if (icpData.serviceLicence) { result.license = icpData.serviceLicence; } if (icpData.natureName) { result.type = icpData.natureName; } // API 没有返回审核时间,使用当前时间作为默认值 const now = new Date(); result.date = now.toISOString().slice(0, 19).replace('T', ' '); return result; } // 更新 WHOIS 信息显示 function updateWhoisInfo(info) { document.getElementById('whois-registrant').textContent = info.registrant || '-'; document.getElementById('whois-created').textContent = info.created || '-'; document.getElementById('whois-email').textContent = info.email || '-'; document.getElementById('whois-expires').textContent = info.expires || '-'; document.getElementById('whois-registrar').textContent = info.registrar || '-'; document.getElementById('whois-nameservers').textContent = info.nameservers || '-'; } // 更新 ICP 备案信息 function updateICPInfo(icpInfo) { document.getElementById('icp-company').textContent = icpInfo.company || '-'; document.getElementById('icp-license').textContent = icpInfo.license || '-'; document.getElementById('icp-type').textContent = icpInfo.type || '-'; document.getElementById('icp-date').textContent = icpInfo.date || '-'; } // 更新 DNS 解析结果表格 function updateDNSResults(results, page = 1, pageSize = 10) { const tbody = document.getElementById('dns-results-body'); if (!tbody) return; const totalPages = Math.ceil(results.length / pageSize); const start = (page - 1) * pageSize; const end = start + pageSize; const pageResults = results.slice(start, end); tbody.innerHTML = ''; pageResults.forEach(result => { const tr = document.createElement('tr'); tr.innerHTML = `