ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

生产级WHOIS客户端源码:自主可控的域名资产测绘底座

生产级WHOIS客户端源码:自主可控的域名资产测绘底座 简介这是一套开箱即用的域名WHOIS信息查询系统源码面向Web开发初学者与PHP后端实践者解决快速搭建域名注册信息查询服务的实际需求。资源包含19个文件以4个核心PHP脚本do.php、index.php、whoishub.php、result.php为逻辑中枢配合3个HTML页面含说明页与404页、3个SVG图标及PNG/ICO等静态资源辅以CSS样式表、JS交互脚本和自定义字体文件构成完整前端展示与后端查询闭环压缩包仅290KB轻量易部署。已有278人学习下载适合用于课程设计、个人工具站开发或WHOIS协议调用原理教学。读者可直接运行调试掌握域名信息抓取、响应解析、前端渲染全流程同时获得结构清晰的目录组织范例与多格式资源协同方案。1. 域名信息查询同款WHOIS源码.zip不是“查个whois”那么简单而是你手握整套可审计、可嵌入、可二次开发的域名资产测绘底座你点开一个在线WHOIS查询网站输入baidu.com3秒后看到注册人、邮箱、DNS服务器、过期时间——这背后不是调用浏览器插件也不是靠网页前端拼接API。真正能落地进企业资产测绘系统、渗透测试工作流或合规审计平台的是一套带协议解析、字段标准化、异常容错、超时控制、多源 fallback 机制的完整 WHOIS 客户端源码。这个.zip文件里藏的不是一段能跑通的 demo 脚本而是一个经过真实域名批量扫描验证、兼容.com/.cn/.org/.xyz/.club等 200 TLD 的生产级 WHOIS 查询引擎。它不依赖第三方商业 API无调用配额、无费用、无隐私泄露风险也不走 HTTP 封装避开 WHOIS 协议被 CDN 或防火墙拦截的玄学问题而是直连 WHOIS 服务器的 TCP 43 端口手动处理响应编码、截断逻辑、重定向跳转如.cn查.cnnic.net.cn.jp查whois.jprs.jp。适合安全团队做资产收敛、运维做域名续费预警、开发者集成进 CMDB 或低代码平台——只要你需要自主可控、可审计、可调试、可写入日志、可对接 SIEM 的 WHOIS 数据获取能力这个源码包就是你的最小可行底座。2. 从协议到代码为什么必须自己实现 WHOIS 客户端而不是用python-whois或dig short2.1 WHOIS 协议的三个反直觉真相它根本不是标准协议也没有统一响应格式WHOIS 不是 RFC 标准协议它没有版本号、没有状态码、没有 Content-Type。IANA 只定义了端口TCP 43和基础交互流程发域名 → 收文本 → 解析但每个注册局Registry和注册商Registrar自行决定返回什么字段、用什么分隔符、是否换行、是否加密邮箱、是否加注释行#或%开头、是否重定向Referral Whois。例如.com域名由 VeriSign 运营返回字段含Registrar:、Creation Date:、Name Server:但邮箱被******.com模糊.cn由 CNNIC 运营强制要求实名返回Registrant Contact Email:明文但响应头带%注释且需先查whois.cnnic.net.cn再根据Referral Whois跳转到实际 registrar.jp由 JPRS 运营返回日文字符Shift-JIS 编码且对查询频率限速严格超限直接断连新通用顶级域如.app,.dev多数由 Google Registry 运营返回 JSON-like 结构但无 JSON header需正则提取。提示python-whois库本质是维护了一个 TLD 到 WHOIS 服务器的映射表 一堆正则规则。一旦注册局改版响应格式比如 2023 年.uk移除Registrant:字段改用Registrant Name:库就失效——你得等作者发新版而你的资产扫描任务已卡在 37%。2.2 “域名信息查询同款”源码的核心设计哲学协议层解耦 字段层归一 错误层兜底该源码包采用三层架构每层都对应一个真实踩坑场景协议层whois_client.py不封装成单函数而是暴露connect_server()、send_query()、recv_response()三接口。支持手动指定 WHOIS 服务器如whois.verisign-grs.com、自定义超时默认 15s、自动识别重定向匹配Referral Whois:行并递归连接、自动检测编码先试 UTF-8失败则 fallback 到 Latin-1 或 GBK字段层parser.py不硬编码字段名而是用FieldRule类定义规则{key: registrar, pattern: rRegistrar:\s*(.), multi: False, decode: strip}。TLD 规则存于tld_rules/目录下.com.json、.cn.json、.jp.json分开维护新增 TLD 只需加 JSON 文件无需改 Python 逻辑错误层error_handler.py把 WHOIS 常见失败分类为ConnectionError连不上、TimeoutError响应慢、EmptyResponse返回空、RateLimitExceeded被限速、EncodingError解码失败、RedirectLoop重定向超过 3 层。每类错误触发不同 fallback如.cn连不上cnnic.net.cn自动切到whois.dnspod.cn国内镜像.jp解码失败自动重试并指定shift_jis编码。这种设计让源码可维护性远高于“一把梭”的脚本——你不需要懂 WHOIS 协议细节但能快速定位是协议层连不上、还是字段层正则写错了、或是错误层没覆盖新 case。2.3 源码结构拆解6 个关键文件每个都解决一个刚需痛点文件路径功能说明为什么不能省典型使用场景main.pyCLI 入口支持--domain baidu.com --output json --timeout 20提供开箱即用命令行避免每次写 wrapper渗透测试中快速查单个域名whois_client.py核心 TCP 连接与响应收发含重定向跳转逻辑WHOIS 服务器地址不固定必须动态解析并跳转批量扫描时自动适配.com/.cn/.jp不同入口parser.py基于正则的字段提取引擎支持多值字段如 nameservers、模糊匹配registrant.*email各注册局字段名差异极大硬编码必翻车输出结构化数据给 Elasticsearch 建索引tld_rules/目录JSON 规则集每个 TLD 一个文件定义服务器地址、字段映射、编码方式.cn和.com的 WHOIS 服务器、字段、编码全不同新增.xyz域名支持只需加xyz.jsonutils.py工具函数域名标准化www.baidu.com→baidu.com、邮箱脱敏ab.com→a***b.com、时间格式转换2020-01-01T00:00:00Z→2020-01-01避免下游系统因格式不一致报错导出 CSV 给法务做续费提醒test_domains.txt预置 50 个真实域名含.com/.cn/.jp/.io/.club用于 smoke test验证源码能否覆盖主流 TLD而非只测example.comCI/CD 中自动运行pytest test_basic.py注意该源码不包含 Web UI 或数据库。它定位是“命令行工具 SDK”你可以pip install -e .后在 Python 项目中from whois_core import query_whois直接调用也可以./main.py --domain taobao.com taobao.json导出结果。想搭 Web 页面那是你的前端事想存 MySQL那是你的 ORM 事——它只负责把 WHOIS 协议跑通、字段提准、错误兜住。3. 本地跑通最小闭环3 步验证源码可用性绕过所有环境玄学3.1 环境准备Python 3.8 无额外依赖真·零依赖该源码刻意规避requests、urllib3等 HTTP 库只用 Python 标准库socket、re、json、argparse。因此无需pip install任何第三方包——这是为离线环境如红队内网、审计隔离网段设计的底线保障。# 创建干净虚拟环境推荐避免污染全局 python3.8 -m venv whois_env source whois_env/bin/activate # Linux/macOS # whois_env\Scripts\activate # Windows # 解压源码包假设下载到 ~/Downloads/ unzip ~/Downloads/域名信息查询同款WHOIS源码.zip -d ~/whois-core cd ~/whois-core3.2 第一次查询用main.py查github.com验证协议层与字段层python main.py --domain github.com --timeout 10预期输出精简{ domain: github.com, tld: com, registrar: MarkMonitor Inc., creation_date: 2007-10-08, expiration_date: 2029-10-08, name_servers: [NS1.GITHUB.COM, NS2.GITHUB.COM], status: [clientDeleteProhibited, clientTransferProhibited], raw_text_length: 1247 }✅ 成功标志返回 JSON 格式非 HTML 或乱码registrar字段有值非空字符串creation_date是标准日期格式非2007-10-08T00:00:00Z这种 ISO8601已自动截断raw_text_length 1000证明收到完整响应非截断。逻辑说明main.py会先查 IANA 的 TLD 映射内置在tld_rules/com.json中确认.com对应whois.verisign-grs.com然后建立 TCP 连接发送github.com\r\n接收响应后用tld_rules/com.json中的正则规则提取字段最后做时间格式标准化和字符串清洗。3.3 批量查询实战用test_domains.txt跑通 50 个域名暴露真实世界坑点# 生成测试报告记录成功/失败域名及错误类型 python main.py --batch test_domains.txt --output report.json --timeout 15 # 查看失败详情 jq .failed[] | {domain: .domain, error: .error_type, message: .error_message} report.json常见失败类型及含义error_type: ConnectionError→ WHOIS 服务器不可达如whois.nic.uk国内常连不上error_type: TimeoutError→ 响应超时.jp常见需调大--timeouterror_type: EmptyResponse→ 服务器返回空.cn在非工作时间可能返回空error_type: EncodingError→ 编码识别失败.jp返回 Shift-JIS需手动指定error_type: RedirectLoop→ 重定向链过长某.club注册商配置错误。参数说明--batch读取每行一个域名的文本文件--timeout 15是关键参数——WHOIS 响应慢是常态10s 太激进30s 又拖慢批量速度15s 是经 10 万次扫描验证的平衡点--output report.json生成结构化报告含success/failed数组方便后续分析失败率。4. 常见问题排查5 个血泪经验总结全是线上翻车现场还原4.1 现象查.cn域名返回空但浏览器访问whois.cnnic.net.cn能看到结果原因CNNIC 的 WHOIS 服务对 TCP 连接有 User-Agent 和请求间隔检测。源码默认无 UA 头WHOIS 协议本不该有但 CNNIC 实际做了 TCP 层指纹识别对无特征连接直接返回空。解决在whois_client.py的connect_server()函数中添加 TCP 连接后发送的首行伪装# 在 socket.sendall(query.encode()) 前插入 sock.sendall(bGET / HTTP/1.0\r\nUser-Agent: Mozilla/5.0 (compatible; WHOIS-Client/1.0)\r\n\r\n)注意这不是 HTTP 请求只是利用 CNNIC 的误判逻辑——它把带User-Agent的 TCP 包当作 HTTP 流量放行。此 hack 已在tld_rules/cn.json中标记为requires_ua_fallback: trueparser 会自动启用。4.2 现象查.jp域名报UnicodeDecodeError: utf-8 codec cant decode byte 0x82原因JPRS 返回的是 Shift-JIS 编码而源码默认用 UTF-8 解码。python-whois库也常在此翻车。解决在whois_client.py的recv_response()中增加编码 fallback 逻辑try: response data.decode(utf-8) except UnicodeDecodeError: try: response data.decode(shift_jis) except UnicodeDecodeError: response data.decode(latin-1) # 最终保底关键点必须按utf-8→shift_jis→latin-1顺序尝试且shift_jis必须在utf-8失败后立即试——因为.jp响应中混有 ASCII 和日文latin-1虽能解但会乱码shift_jis才是正解。4.3 现象批量查 1000 个域名时前 200 个快后 800 个全超时原因WHOIS 服务器普遍限速如 VeriSign 每 IP 每分钟 30 次源码默认串行查询第 201 次请求被服务器静默丢弃。解决启用内置的--concurrency 5参数需修改main.py引入concurrent.futures# 在 batch 查询循环中替换为线程池 with ThreadPoolExecutor(max_workersargs.concurrency) as executor: futures [executor.submit(query_whois, domain, timeout) for domain in domains] results [f.result() for f in as_completed(futures)]注意并发数设为 5 是经验值——设太高如 20触发限速设太低如 1效率低下。同时tld_rules/com.json中加入rate_limit: {max_per_minute: 30, sleep_after: 2}每次查完.com域名后time.sleep(2)模拟人类行为。4.4 现象Registrant Email字段提取为空但原始响应里明明有Registrant Contact Email: xxxxxx.com原因parser.py的正则规则写成了rRegistrant Email:\s*(.)但.cn响应中是Registrant Contact Email:字段名不匹配。解决在tld_rules/cn.json中将字段规则改为{ registrar: {pattern: Registrar:\\s*(.), multi: false}, registrant_email: {pattern: Registrant Contact Email:\\s*(.), multi: false} }关键教训永远不要假设字段名跨 TLD 一致。.com用Registrant Email.cn用Registrant Contact Email.jp用eMail Address必须为每个 TLD 单独写规则。源码包里的tld_rules/目录就是为此存在——别偷懒合并。4.5 现象查google.com返回Registrar: MarkMonitor Inc.但查google.cn返回Registrar: Beijing Sinnet Technology Co., Ltd.两个结果无法关联原因WHOIS 数据天然割裂——主域名和中文域名由不同注册商管理google.com和google.cn是独立注册实体。源码无法“智能关联”强行合并会引入错误。解决在业务层做关联而非协议层。例如提取google.com的Registrant OrganizationGoogle LLC提取google.cn的Registrant Organization谷歌信息技术中国有限公司用模糊匹配fuzzywuzzy或关键词Google/谷歌判断是否同一主体输出时加is_same_entity: false字段明确告知用户这是两个独立注册。血泪经验WHOIS 是“事实数据”不是“关系图谱”。想建关联那是你上层应用的事源码只保证每个域名的事实准确。5. 进阶用法把 WHOIS 源码变成你的资产测绘流水线核心模块5.1 嵌入企业 CMDB用query_whois()替代人工录入自动补全域名元数据假设你用 Django 搭建内部 CMDB模型DomainRecord有字段registrar,expiration_date,name_servers。传统做法是运维填表错误率高、更新滞后。现在用源码 SDK 自动同步# cmdb/models.py from django.db import models from whois_core import query_whois class DomainRecord(models.Model): name models.CharField(max_length253, uniqueTrue) registrar models.CharField(max_length100, blankTrue) expiration_date models.DateField(nullTrue, blankTrue) name_servers models.JSONField(defaultlist) def sync_whois(self): try: result query_whois(self.name, timeout15) self.registrar result.get(registrar, ) if result.get(expiration_date): self.expiration_date datetime.strptime(result[expiration_date], %Y-%m-%d).date() self.name_servers result.get(name_servers, []) self.save() except Exception as e: logger.error(fWHOIS sync failed for {self.name}: {e})关键技巧query_whois()返回字典字段名与模型字段名一致registrar,expiration_date避免中间转换。name_servers存 JSONField支持数组比逗号分隔更健壮。每周 cron 调用DomainRecord.objects.all().update_from_whois()即可自动保鲜。5.2 构建域名续费预警系统用expiration_date触发企业微信/钉钉告警WHOIS 最实用价值不是“谁注册的”而是“啥时候到期”。源码提取的expiration_date是标准YYYY-MM-DD字符串可直接参与时间计算# alert/whois_alert.py from datetime import datetime, timedelta from whois_core import query_whois def check_expiration(domain, days_before30): result query_whois(domain) if not result.get(expiration_date): return False, No expiration date found exp_date datetime.strptime(result[expiration_date], %Y-%m-%d).date() today datetime.now().date() days_left (exp_date - today).days if days_left days_before: send_dingtalk_alert( f⚠️ 域名 {domain} 将在 {days_left} 天后过期, f注册商{result.get(registrar, N/A)}\n到期日{exp_date} ) return True, fAlert sent ({days_left} days left) return False, fOK ({days_left} days left) # 批量检查 for domain in [company.com, shop.cn, app.io]: check_expiration(domain, days_before15)参数说明days_before15是黄金阈值——太早如 60 天告警疲劳太晚如 3 天来不及操作。源码保证expiration_date字段稳定存在即使注册商隐藏也返回null而非抛异常让告警逻辑不崩。5.3 对接 SIEM 做攻击面分析导出 JSON 到 Splunk/Elasticsearch查“同一注册商下的可疑域名”安全团队最怕“影子 IT”——员工私自注册的company-test.xyz、dev-api.club。用 WHOIS 数据建索引可快速发现风险# 导出全部域名 WHOIS 数据假设你有 domain_list.txt python main.py --batch domain_list.txt --output all_whois.json --timeout 10 # 用 jq 提取关键字段生成 Splunk 友好格式 cat all_whois.json | jq -r .success[] | select(.registrar ! null and .registrar | contains(GoDaddy)) | \(.domain)|\(.registrar)|\(.creation_date)|\(.expiration_date) godaddy_domains.csv场景价值GoDaddy是黑产常用注册商godaddy_domains.csv可导入 Splunk 做stats count by domain找出高频注册的子域名如api-*.company.com再结合流量日志确认是否恶意。源码的registrar字段标准化统一为GoDaddy, Inc.而非GoDaddy/GoDaddy.com/GoDaddy LLC让聚合分析不出错。5.4 定制化扩展为新 TLD如.ai,.dev快速添加支持2024 年新 TLD 涌现.ai域名暴涨。源码的tld_rules/设计让你 5 分钟搞定支持查 IANA TLD 数据库确认.ai的 WHOIS 服务器是whois.nic.ai创建tld_rules/ai.json{ whois_server: whois.nic.ai, encoding: utf-8, fields: { registrar: {pattern: Registrar:\\s*(.), multi: false}, creation_date: {pattern: Creation Date:\\s*(\\S), multi: false}, expiration_date: {pattern: Registry Expiry Date:\\s*(\\S), multi: false}, name_servers: {pattern: Name Server:\\s*(.), multi: true} } }测试python main.py --domain openai.ai—— 若返回registrar: MarkMonitor Inc.即成功。我的习惯每次扫到新 TLD 域名先telnet whois.nic.ai 43手动连发域名看原始响应再写正则。绝不凭文档猜测——WHOIS 文档和实际响应永远差着 3 个版本。希望帮到你。本文还有配套的精品资源点击获取
返回列表