WHOIS查询源码实战:从端口43直连到RDAP与批量监控
发布时间:2026/9/28 12:50:46 锦皓数字建站

简介域名信息查询同款WHOIS源码.zip 是一套面向网站开发者与站长的域名WHOIS查询功能实现基于PHP后端查询逻辑与前端页面搭配可用于解析域名注册信息、名字服务器等详细数据。资源包共19个文件压缩后仅290KB包含4个PHP处理脚本、3个HTML页面模板与3个SVG图形资源另有CSS样式、JS交互脚本、WOFF/TTF/EOT字体及PNG/ICO图标等覆盖查询、展示、美化各环节结构简洁适合快速部署或二次开发。目前已有278人学习/下载适合需要搭建自有域名查询工具或学习WHOIS协议应用的入门到中级开发者。通过源码可掌握域名信息查询的前后端交互流程包括查询参数接收、WHOIS数据解析、结果展示与页面美化PHP脚本与页面文件分离便于按需替换查询源或增加批量查询等扩展功能。整体体积小、依赖简单是一份实用的域名信息查询参考样例。1. 域名信息查询同款WHOIS源码.zip为什么你绕不开这套经典方案做域名监控、到期提醒、批量选品留档的人几乎都会在某天下载一份“域名信息查询同款WHOIS源码.zip”。这套源码包的价值在于它把端口43上的纯文本应答、多个注册局的解析差异、过期时间计算这些没人愿意反复踩的坑一次性打包成了可运行的本地服务。对开发者、运维和域名投资者来说搭起它就能脱离对第三方付费接口的依赖自己控制缓存和限流把查询从“每次等对方返回”变成“本地一份干净数据”。这篇笔记会从协议差异讲起带你走完解压、启动、封装、避坑和批量查询的完整流程新手能照做熟手能直接拿走参数。2. 先立住查询原理端口43直连、RDAP与新顶级域的响应差异WHOIS 之所以“看起来简单做起来翻车”是因为同一个查询动作背后有三套数据通道老源码用得最多的是 TCP 43 直连最近几年才是 RDAP。如果一开始不把这层关系理顺后面解析代码怎么写都会觉得像在猜谜。2.1 端口43直连免费、直接但响应是给人读的文本传统 WHOIS 协议非常简单客户端通过 TCP 连上注册局服务器的 43 端口发送一行域名加回车换行服务器就用纯文本把注册信息回给你。没有 HTTP 状态码没有 JSON没有分页一套响应里既有注册商、注册日期、到期日期也有状态、Name Server甚至还有注册局的免责声明。很多源码包里的核心逻辑就是一层这么薄的 socket 封装。常见做法是先用whois.iana.org确认域名所属注册局再跳到具体的 WHOIS 服务器问一次。最小实现可以这样写import socket def whois_raw_query(domain: str, server: str, port: int 43, timeout: float 6.0) - str: 向指定 WHOIS 服务器发送一条查询返回原始文本。 sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(timeout) try: sock.connect((server, port)) sock.send(f{domain}\r\n.encode(ascii)) chunks [] while True: data sock.recv(4096) if not data: break chunks.append(data.decode(utf-8, errorsignore)) return .join(chunks) finally: sock.close() # .com/.net 可以直连 VeriSign 的 GR Server print(whois_raw_query(qq.com, whois.verisign-grs.com))这段代码的核心在于 socket 读取是阻塞式的服务器断开连接才算响应结束所以timeout参数很关键。设太小跨国链路稍微抖动就报超时设太大服务线程容易被慢连接拖死。我一般会取 5 到 6 秒配合重试控制既不显得急躁也不会把线程池占满。还要注意编码。老注册局的响应可能是 ASCII也可能是 GBK 或 UTF-8直接decode(utf-8, errorsignore)会把中文注册商截掉。实际工程中应当先做编码探测拿不到明确编码时用 UTF-8 失败回退 GB18030这到解析章节再展开。2.2 RDAP 是正规军为什么老源码还坚持 43 端口RDAP 是近几年注册数据访问的标准方向走 HTTPS 443响应是标准 JSON 结构字段名统一还带 HTTP 限流头。比如查询 .com 域名可以请求https://rdap.verisign.com/com/v1/domain/qq.com返回里的events数组会明确标出注册时间和过期时间几乎不用写正则。既然 RDAP 这么规范为什么标题里的这套源码还要坚持走 43 端口原因很现实第一老代码发布时 RDAP 还没普及到所有注册局很多新顶级域只能靠 WHOIS 跳转第二RDAP 端点分散在 IANA 的 bootstrap 文件里调用方要先拉取数据再决定请求哪个端点这套逻辑比“查一次 IANA 再查一次注册局”更绕第三大量 PHP 源码跑在共享虚拟主机上出站 443 随时可用但编辑和扩展一套 socket 脚本比引入 RDAP 客户端库更省事。我的判断是新项目应优先考虑 RDAP老源码改造则不必推翻重来。在 43 端口实现外面包一层适配器优先走 RDAP失败再回退到 socket 查询这样兼容性和可维护性都拿得住也是目前最主流的渐进方案。2.3 动手前先建一张 TLD 映射表不论用 43 端口还是 RDAP第一步都是确定“这个域名该问谁”。不同后缀的查询服务器差别很大不能硬编码一套。这里整理了平时最常用的一批后缀WHOIS 服务器响应格式备注com/netwhois.verisign-grs.comkey: value字段最规整适合先拿来调试解析器cnwhois.cnnic.cn中文字段 英文混排编码常是 GBK字段名与 com 差异大orgwhois.pir.orgkey: value状态字段多需要按多值处理iowhois.nic.iokey: value字段较少但存在服务器跳动xyz/top 等新顶级域需先查 IANA常见“refer”跳转很可能第一层响应只是指引需二次查询把这五类跑通基本就能覆盖绝大多数查询需求。注意表格里的映射关系会随注册局运营变更建议在服务里留一个可热更新的配置文件而不是把服务器地址写死在代码里。等源码落地之后这张表就是你要维护的第一个基础设施。3. 从zip包到本地服务解压、识别项目类型、最小启动命令拿到“域名信息查询同款WHOIS源码.zip”之后很多人习惯性双击解压然后对着目录发呆。这里最容易踩的第一个坑不是代码跑不起来而是包根本就没解干净。先花两分钟检查包内格式能省下后面一整段排错时间。3.1 解压前先处理伪加密这一步能省一下午网上流传的源码 zip 包经常带一个“有密码”的假象解压时提示 password required但发布者从头到尾没说过有密码。这多半是 zip 伪加密——打包工具把加密标志位置了 1实际文件内容并没有加密只是部分解压工具看到标志位就要密码。判断方法很简单用 Python 读 zip 的中央目录直接看 General Purpose Bit Flag 的最低 bit。伪加密的标志能被无损剥离处理脚本如下import struct def strip_fake_encryption(src: str, dst: str) - None: 把 zip 文件里的加密标志位强制清零处理伪加密后另存。 data bytearray(open(src, rb).read()) for signature in (bPK\x03\x04, bPK\x01\x02): offset 0 while True: pos data.find(signature, offset) if pos -1: break flags_pos pos 6 flags struct.unpack_from(H, data, flags_pos)[0] if flags 0x1: struct.pack_into(H, data, flags_pos, flags 0xFFFE) offset pos 1 with open(dst, wb) as f: f.write(data) stripped strip_fake_encryption(WHOIS源码.zip, whois_stripped.zip)代码把本地文件头和中央目录里的加密标志一并清零避免有些工具读取中央目录后仍然报错。参数上只需要注意路径别覆盖原文件处理完先unzip -l whois_stripped.zip看一眼文件列表。如果清零后仍要密码那就是真加密这种只能联系发布者要原始密码别浪费时间在字典爆破上。这也是 zip 源码包最典型的“虚晃一枪”解决掉它后续流程才走得下去。3.2 识别包内技术栈用启动方式反过来认项目解压后先不要急着找 README直接看目录结构。源码包的技术栈通常从文件特征一眼就能认出不同结构对应完全不同的启动方式目录特征技术栈最小启动命令app.py requirements.txt templates/Python Flaskpython app.pyindex.php config.php sql/原生 PHPphp -S 0.0.0.0:8080 -t publicvendor/ composer.jsonPHP 全家桶项目composer install 后 php artisan servepackage.json server.jsNode.jsnpm install npm startdocker-compose.yml容器化docker compose up -d标题里这类“同款源码”最常碰到的是 Python Flask 和原生 PHP 两种。PHP 版本的解析逻辑一般集中在whois.php或function.php用fsockopen连 43 端口Python 版本则通常拆成了whois_client.py、parser.py和app.py。不管哪一类先跑ls -R大概浏览一遍找到入口文件再决定用哪条启动命令。3.3 最小启动命令与本地自测以最常见的情况为例解压出来是 Flask 项目。先建虚拟环境再装依赖最后启动python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt python app.py参数说明端口默认在 Flask 代码里通常是 5000如果被占用改成 5001host建议写成127.0.0.1先本地验证不要一上来就绑0.0.0.0。requirements.txt里如果带了mysqlclient或lxml在 Windows 上经常要编译装不动就先把那几行注释掉等主流程跑通再补。启动成功后的自测命令curl -s http://127.0.0.1:5000/api/whois?domainqq.com | head -c 800能返回 JSON 或一段注册信息文本说明整条链路已经通了。不同源码的响应字段命名可能不同但这一步只要能拿到数据就证明 socket 查询、解析、HTTP 层三个环节都工作正常。接下来要做的就是把这些数据变成“敢直接拿去用”的服务。4. 把查询做成服务响应解析、缓存策略与并发限流源码能查出原始文本和能提供稳定服务之间隔着解析、缓存、限流三座山。很多免费的“同款源码”只做到前两步中的一半所以跑起来总给人一种“能用但不敢用”的感觉。这一章把这三个模块逐个补齐。4.1 注册局文本响应差异用“TLD 分支”解析而不是一个正则打天下把原始文本转成结构化字典是所有 WHOIS 服务里最容易翻车的一段。com 的字段是英文Creation Date:cn 的字段却可能是中文“注册日期:”加 GBK 编码org 的 Status 还会出现多行重复。同一个域名在不同注册局解析出来的字段名、取值格式完全不同所以解析器第一条原则就是按 TLD 分支处理。import re def parse_whois(raw: bytes, tld: str) - dict: 按 TLD 分支解析注册局原始响应返回结构化字段。 try: text raw.decode(utf-8) except UnicodeDecodeError: text raw.decode(gb18030, errorsreplace) out {registrar: , creation: , expiration: , status: [], ns: []} if tld in (com, net): patterns { registrar: rRegistrar:\s*(.), creation: rCreation Date:\s*([0-9T:.\-Z]), expiration: rRegistry Expiry Date:\s*([0-9T:.\-Z]), status: rStatus:\s*(.), ns: rName Server:\s*(\S), } elif tld cn: patterns { registrar: r注册商:\s*(.), creation: r注册日期:\s*(.), expiration: r到期日期:\s*(.), status: r状态:\s*(.), ns: rName Server:\s*(\S), } else: patterns { registrar: rRegistrar:\s*(.), creation: rCreation Date:\s*(.), expiration: rExpiry Date:\s*(.), status: rStatus:\s*(.), ns: rName Server:\s*(\S), } for key, pattern in patterns.items(): matches re.findall(pattern, text) if key in (status, ns): out[key] matches elif matches: out[key] matches[0].rstrip() return out这段代码的关键在两点status和ns是典型的多值字段必须用findall收集完整列表否则后续做状态判断时只能看到最后一条编码回退放在解析前先试 UTF-8失败转 GB18030能同时覆盖中英文响应。字段取值上注册商、日期类的单值字段处理成空字符串而不是None这样下游做告警判断时不会因为类型不统一而报错。这套解析器还不够完美真实响应里偶尔会出现 “Creation Date” 值被截断的情况建议在返回前补一层字段清洗把日期统一转成YYYY-MM-DD无法识别的日期宁可留空也不要硬算一个错误值进数据库。4.2 缓存参数为什么 WHOIS 服务不能每次都打注册局很多人抱怨免费源码查询慢剖开看多半是没有缓存。WHOIS 数据的本质是低频变化信息绝大多数域名的注册商、创建日期、到期日期不会在几小时内改变。每一条查询都向 43 端口打一次等于把简单请求压在一个极易受限流的通道上。内存缓存是最简单的方案不必一上来就上 Redisimport time CACHE {} def get_whois_cached(domain: str, ttl: int 86400) - dict: 带 TTL 的内存缓存查询结果默认缓存一天。 now time.time() cached CACHE.get(domain) if cached and now - cached[1] ttl: return cached[0] data query_and_parse(domain) CACHE[domain] (data, now) return data参数说明ttl默认给 86400 秒适合域名到期监控、资产盘点这类批量场景。如果服务是给注册商内部用的刚过户、刚注册的域名查询频率高可以把 TTL 压到 300 到 600 秒再配合更新时间字段手动失效。内存缓存只要维护一份字典加时间戳就足够单机部署完全不需要引入外部组件。4.3 并发与限流线程数、间隔、退避三个参数WHOIS 服务器的限流策略通常不公开但行为很直白单位时间内查询过多连接直接被重置。源码包里常见的错误是用了无限制线程池50 个域名同时发出去前几条成功后面全被 RST。常见做法是用信号量把并发压到 1 到 2并在每次查询后强制间隔import threading import time semaphore threading.Semaphore(2) def limited_query(domain: str) - dict: 限制并发查数每次查询后强制等待再释放。 with semaphore: try: data get_whois_cached(domain) return data finally: time.sleep(1.0)并发参数不是拍脑袋定的Semaphore(2)表示同时最多两个 socket 连接避免大量连接堆积time.sleep(1.0)放在锁内保证同一时刻全局只有一个请求在间隔窗口外执行。批量场景实测下来每秒 1 到 2 个请求是大多数注册局能接受的安全水位比这个高就容易触发封禁。配合重试退避时要注意失败后第一次等 1 秒第二次 2 秒第三次 4 秒最多重试三次不要一失败就无限重试把限流放大。这些参数在源码里写成常量统一可调。5. WHOIS查询服务避坑zip伪加密、端口超时与IP被限前面把服务和参数都讲透了接下来是实际运行中一定会遇到的几个硬坑。每一条都是“现象 → 原因 → 解决”的完整套路遇到同款问题时直接照着排查。5.1 现象解压报 password required但发布者从未设密码解压工具弹出要密码源码包里又没附带任何密码说明第一反应通常是怀疑包损坏或者去想“发布者是不是忘了给密码”。实际上这叫 zip 伪加密打包工具或者修改工具把加密标志位置 1文件内容本身没有加密。原因部分老的压缩工具在生成 zip 时会把 General Purpose Bit Flag 的 bit 0 误置为 1Windows 资源管理器和部分解压软件看到这个标志就要求输入密码。解决按 3.1 节的方法把本地文件头和中央目录里的加密标志清零后重新另存再用unzip -l验证。如果清零后仍然提示密码说明是真加密仔细看发布页的说明文件一般不提供密码的包不值得花工夫去爆破。5.2 现象本地 curl 正常程序里 connect 43 端口超时很多源码在本机能跑通 HTTP 自测部署到云服务器后却卡在 connect 超时。表现是socket.connect阶段就卡满 timeout查询完全无法返回。原因有几种目标 WHOIS 服务器拒绝该网段访问云厂商安全组或宿主网络对出站 43 端口做限制还有少数注册局对某些机房 IP 段有成规模的封禁记录。解决先换一个注册局服务器测试比如 .com 的whois.verisign-grs.com换成whois.crsnic.net再不行把超时降到 5 秒以内配合重试最稳妥的后备方案是给查询模块加一层 RDAP 回退443 端口出站几乎不会遇到这类限制。查 .cn 域名走whois.cnnic.cn一般不会碰到网络限制问题优先排查你的部署位置到目标机房的路由。5.3 现象同一套解析代码查 .com 正常查 .cn 丢字段、乱码源码自带的解析器可能只针对 .com 调过跑 .cn 时注册商变成空值日期字段解析失败甚至出现中文乱码。这不是解析器 bug是数据和协议的差异。原因.cn 由 CNNIC 托管字段名是“注册商”“注册日期”“到期日期”这类中文响应编码多为 GBK而已有的解析器写死了英文正则也没做编码回退。解决把解析逻辑显式按 TLD 分支.cn 分支用 4.1 节的中文正则不可能同时兼容所有英文格式。编码处理上先尝试 UTF-8 解码捕获异常后转 GB18030。注意有的中文注册局返回里会混入 UTF-8 英文段落建议在字段清洗环节统一strip()避免明明有值却因为换行符没匹配上。5.4 现象查询结果只有 refer 跳转提示没有实际域名信息某些新顶级域比如 xxx 和部分 ccTLD第一层查询拿到的不再是注册信息而是一小段跳转提示类似“Whois Server: whois.nic.abc”更老的响应里甚至只有一行 URL。原因IANA 层面的 WHOIS 服务器只负责告诉你这个 TLD 的注册数据在哪不直接存域名记录。源码如果没有实现跳转跟随自然拿不到真正数据。解决实现两层查询。先向whois.iana.org发起查询从响应里提取refer行再向目标服务器发第二层请求。更省事的方案是维护一张 TLD 映射表把 .com、.cn 这类常见后缀直接写死到对应服务器新顶级域走动态查表逻辑。两年以上的老源码大多没有这层逻辑需要自己补上。5.5 现象批量查询二三十条后 connect 被直接断开批量脚本跑到一半连接开始被对方瞬间 RST连不上也读不到数据等几分钟又恢复一些。这是最典型注册局限流行为。原因对方没有返回任何限流提示直接断开连接从客户端看像是网络故障。本质上是对单 IP 的查询速率或总量做限制超过阈值就拉黑一段时间。解决把并发降到 1查询间隔加到 1 秒以上重试退避按 1s/2s/4s 推进并且不做无限重试。必要时把部分高频公共后缀切换到 RDAPRDAP 端点的限流策略更透明HTTP 头会直接告诉你何时可以重试。不要想着绕过限流注册局封禁是持续性的正确做法是让批量的速率曲线保持平稳。6. 批量查询与结果对账把单点工具变成长效监控服务稳定之后最常用的动作是把一批域名丢进去集中查询然后把结果落盘留档。这里给一个通用的批量脚本骨架按行读取域名列表逐个调本地接口间隔参数可根据注册局反馈调整。import json import time import urllib.request def batch_check(domain_file: str, endpoint: str http://127.0.0.1:5000/api/whois) - None: with open(domain_file, encodingutf-8) as f: domains [line.strip() for line in f if line.strip()] with open(result.jsonl, a, encodingutf-8) as out: for i, domain in enumerate(domains): req urllib.request.Request( endpoint, datafdomain{domain}.encode(), methodPOST, ) with urllib.request.urlopen(req, timeout10) as resp: record json.load(resp) record[checked_at] time.time() out.write(json.dumps(record, ensure_asciiFalse) \n) if i % 20 0: print(fprogress {i}/{len(domains)}) time.sleep(1.2)脚本里最关键的两个参数是timeout10和sleep(1.2)。前者防止单个域名卡住整个队列后者保证整体请求密度保持在安全水位jsonl格式比 CSV 更灵活每行一条完整记录字段变化不需要改表结构。对账技巧在于每周把result.jsonl里expiration距当前时间少于 30 天的记录筛出来单独导成告警清单同时随机抽几条原始响应手工比对验证解析器没被注册局改版带偏。如果发现某一天开始批量结果里过期时间普遍异常优先怀疑解析正则而不是域名数据真的变了。我吃过一次并发过大被临时限流的亏之后养成的习惯是任何 WHOIS 批量脚本都默认带 1.2 秒间隔并把每条查询的原始报文和解析结果一起落盘留档。这样出了问题至少能分清是代码改坏了还是注册局接口变了而不是对着黑匣子猜。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。