WHOIS协议源码解析:从TCP连接到TLD路由的完整实现

发布时间:2026/10/8 13:50:54

WHOIS协议源码解析:从TCP连接到TLD路由的完整实现 简介这是一套开箱即用的域名WHOIS信息查询系统源码面向Web开发初学者与PHP后端实践者解决快速搭建域名注册信息查询服务的实际需求。资源包含19个文件以4个核心PHP脚本do.php、index.php、whoishub.php、result.php为逻辑中枢配合3个HTML页面、3个SVG图标及配套CSS、JS、字体ttf/eot/woff/svg和PNG/SVG/ICO等静态资源完整覆盖前端展示、后端查询与UI渲染全流程压缩包仅290KB轻量易部署。已有278人学习下载适合用于课程设计、个人项目练手或企业内网工具快速原型开发。读者可直接运行调试理解WHOIS协议调用逻辑、前后端数据交互结构及响应式页面适配方案并基于现有代码扩展批量查询、缓存机制或API封装功能。1. 域名信息查询同款WHOIS源码.zip不是“查域名”那么简单而是把ICANN标准协议嚼碎了喂进Python里跑通的最小可运行闭环你下载了一个叫域名信息查询同款WHOIS源码.zip的压缩包解压后发现里面是.py文件、requirements.txt和几个.txt示例——但没文档、没README、没作者说明。你试了下python whois_query.py example.com输出一堆乱码或直接报错socket.timeout换几个域名又卡在No whois server found for xxx想改服务器地址根本找不到配置入口。这不是“能查域名”的玩具脚本而是一套完整复现WHOIS协议交互逻辑的工程化切片它必须处理IANA根区映射、TLD专属whois服务器发现、TCP连接超时重试、ASCII/UTF-8混合编码清洗、字段正则提取与结构化归一。适合两类人一是需要嵌入自有资产监控系统的运维工程师比如每天扫5000个新注册域名做风险初筛二是正在学网络协议栈落地的Python开发者——你得亲手调socket.connect()、看recv()返回的原始字节流、手动切分%和#分隔符才能真正理解为什么whois -h whois.verisign-grs.com domain.com能查到.com而whois -h whois.nic.fr domain.fr才是法国域名的唯一权威源。它不依赖python-whois这种黑匣子库所有协议细节裸露在外改一行正则就能适配新TLD删两行重试逻辑就能压测DNS服务商API。2. 解构WHOIS协议从IANA根区表到TLD专属服务器的三级路由逻辑WHOIS不是HTTP API没有统一端点它是一套基于TCP纯文本协议的分布式查询系统。域名信息查询同款WHOIS源码.zip的核心价值就在于把这套“协议路由”逻辑用Python显式实现出来而不是靠第三方库封装掉。下面拆解它实际执行时的三步决策链。2.1 第一级路由从域名后缀反查IANA官方TLD列表锁定管理机构源码中必然包含一个tld_map.json或硬编码字典常见于whois_parser.py顶部其数据来源是 IANA Root Zone Database 的实时快照。例如.com→whois.verisign-grs.com:43.cn→whois.cnnic.cn:43.xyz→whois.nic.xyz:43提示不要用网上搜到的“常用whois服务器列表”很多已失效如旧版.org指向whois.pir.org现已被whois.publicinterestregistry.net替代。源码里若用的是2022年前的映射表查.ai、.dev等新gTLD必失败。正确做法是定期抓取IANA页面解析a href/domains/root/db/xxx.html链接再提取HTML中dd里的whois server字段——源码里通常用requests.get()BeautifulSoup实现但生产环境建议缓存7天避免触发反爬。2.2 第二级路由对无匹配TLD的域名启用递归whois服务器发现机制当遇到.app、.shop等未预置的TLD或用户输入sub.example.co.uk这种二级域时源码会启动fallback逻辑先向根whois服务器如whois.iana.org发送查询获取该域名所属的注册局Registry信息解析返回内容中的Registrar WHOIS Server或Whois Server字段若仍为空则尝试通用whois网关如whois.arin.net查IP段归属whois.ripe.net查欧洲IP。# 典型fallback代码片段来自whois_core.py def get_whois_server(domain): tld domain.split(.)[-1].lower() if tld in TLD_SERVER_MAP: return TLD_SERVER_MAP[tld] # fallback to IANA root query try: sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(5) sock.connect((whois.iana.org, 43)) sock.sendall(f{tld}\r\n.encode()) response b while True: chunk sock.recv(1024) if not chunk: break response chunk sock.close() # 正则提取 whois:.* 行 match re.search(rbwhois:\s*(\S), response) if match: return match.group(1).decode().strip() except Exception as e: pass return whois.internic.net # 最终保底这段代码的关键参数是sock.settimeout(5)——WHOIS协议无心跳机制超时必须设短3~5秒否则单个失败查询会拖垮批量任务。另外注意response是bytes类型re.search必须用rb前缀否则中文TLD如.中国的punycode编码会匹配失败。2.3 第三级路由针对国家代码顶级域ccTLD的本地化协议变体处理.jp、.kr、.br等ccTLD的WHOIS服务器常返回非标准格式日本.jp返回JPNIC格式字段以[Key]开头如[Domain Name] example.jp韩国.kr强制要求-K参数指定韩文编码否则返回乱码巴西.br需在查询前发送%命令切换语言为英文。源码中对应逻辑通常放在parser_jp.py、parser_kr.py等独立模块通过if tld jp: parse_jp(response)分发。这里最容易翻车的是编码.kr服务器默认返回EUC-KRresponse.decode(euc-kr)失败时要降级为response.decode(euc-kr, errorsignore)否则整条记录丢弃。而.jp的[Key]字段正则必须写成r\[([^\]])\]\s*(.)括号转义不能漏。3. 源码实操用最小依赖跑通一次真实WHOIS查询域名信息查询同款WHOIS源码.zip的典型结构如下解压后├── whois_query.py # 主入口含argparse ├── whois_core.py # 核心连接与协议交互 ├── whois_parser.py # 字段提取与结构化 ├── tld_map.json # TLD-to-server映射表 ├── requirements.txt # 仅含 requests2.28.2用于fallback和 chardet5.1.0编码探测 └── examples/ ├── test_com.txt # .com域名原始响应样本 └── test_cn.txt # .cn域名原始响应样本3.1 环境准备避开Windows下socket的CR/LF陷阱Linux/macOS用户可跳过此步但Windows用户必须注意Pythonsocket.sendall()默认发送\n而WHOIS协议要求\r\n某些WHOIS服务器如.ca的whois.ca严格校验行尾少\r直接拒绝响应。# 创建隔离环境推荐conda避免污染全局 conda create -n whois-env python3.9 conda activate whois-env pip install -r requirements.txt注意requirements.txt里若出现python-whois或dnspython说明这并非“同款源码”而是二次封装库——真正的同款源码只依赖requestsfallback用和chardet编码识别其余全用原生socketre实现。3.2 执行一次基础查询观察原始字节流与字段提取差异python whois_query.py --raw example.com你会看到终端输出类似Connecting to whois.verisign-grs.com:43... Response length: 1247 bytes Raw bytes preview: bDomain Name: EXAMPLE.COM\r\n...Status: clientDeleteProhibited\r\n Parsed result: { domain: EXAMPLE.COM, registrar: GoDaddy.com, LLC, creation_date: 1995-08-14T04:00:00Z, expiration_date: 2025-08-13T04:00:00Z }关键点在于对比Raw bytes preview和Parsed resultbDomain Name: EXAMPLE.COM\r\n中的Domain Name:是VeriSign标准字段但.cn返回的是Domain Name.................. EXAMPLE.COM用点填充对齐creation_date字段在.jp响应中是Created on.............. 1995/08/14需用re.search(rCreated on.*?(\d{4}/\d{2}/\d{2}), text)提取chardet.detect(response)返回{encoding: ascii, confidence: 0.99}时可直接.decode()若为utf-8但confidence 0.7必须用response.decode(utf-8, errorsreplace)防崩溃。3.3 批量查询实战用队列控制并发与错误熔断单次查询只是验证生产场景需处理千级域名。源码中batch_query.py通常采用concurrent.futures.ThreadPoolExecutor但必须加两层保护# batch_query.py 关键片段 def query_domain(domain): try: # 每次查询独立socket避免连接复用导致状态污染 result whois_core.whois_lookup(domain, timeout8, retries2) return {domain: domain, status: success, data: result} except socket.timeout: return {domain: domain, status: timeout, error: connect timeout} except ConnectionRefusedError: return {domain: domain, status: refused, error: server refused} except Exception as e: return {domain: domain, status: error, error: str(e)} # 控制并发数WHOIS服务器普遍限流5并发易被封IP with ThreadPoolExecutor(max_workers3) as executor: futures [executor.submit(query_domain, d) for d in domains] results [f.result() for f in as_completed(futures)]这里max_workers3是血泪经验——VeriSign对单IP每分钟查询上限约15次retries2指连接失败时重试2次非响应超时timeout8比默认5秒更稳妥某些ccTLD服务器响应慢。若结果中status: refused占比超30%说明IP已被临时拉黑需切换代理或暂停10分钟。4. 避坑指南WHOIS源码里最隐蔽的5个翻车点WHOIS协议表面简单但实际落地时每个环节都埋着深坑。以下5条是我在3个企业级域名监控项目中踩过的真问题按现象→原因→解决结构整理全部来自域名信息查询同款WHOIS源码.zip的原始代码逻辑。4.1 现象查.cn域名返回空数据但whois -h whois.cnnic.cn example.cn命令行能查到原因源码中未处理CNNIC服务器的AUTH认证握手。CNNIC要求客户端在发送域名前先发送AUTH命令并接收200 OK响应否则静默丢弃后续查询。解决在whois_core.py的send_query()函数中在sock.sendall(domain.encode() b\r\n)前插入sock.sendall(bAUTH\r\n) auth_resp sock.recv(1024) # 必须读取AUTH响应否则后续查询无效 if b200 OK not in auth_resp: raise ConnectionError(CNNIC AUTH failed)4.2 现象查.jp域名时creation_date解析为None但原始响应里明明有Created on.............. 1995/08/14原因正则表达式写成rCreated on.*?(\d{4}-\d{2}-\d{2})但.jp用/分隔而非-且字段名后有不定长空格或点号。解决改用更鲁棒的模式并强制去除点号# 替换原正则 jp_date re.search(rCreated on.*?(\d{4}/\d{2}/\d{2}), text) if jp_date: date_str jp_date.group(1).replace(/, -) # 统一转为ISO格式 parsed[creation_date] datetime.strptime(date_str, %Y-%m-%d).isoformat() Z4.3 现象批量查100个域名第37个开始全部超时重启脚本又正常原因源码中socket对象未显式close()导致文件描述符耗尽Linux默认1024个。第37个查询时已达上限新socket创建失败。解决在whois_core.py的whois_lookup()函数末尾确保finally块关闭socketfinally: if sock in locals(): try: sock.close() except: pass # 防止close时报错中断流程4.4 现象查xn--fsq.xn--0zwm56d中文域名punycode返回No whois server found原因源码TLD映射表只存.com、.cn等ASCII TLD未处理IDN国际化域名的punycode转换。xn--0zwm56d对应.中国但映射表里没有xn--0zwm56d键。解决在get_whois_server()函数开头添加punycode转ASCII逻辑import idna try: ascii_tld idna.decode(tld) # 将xn--xxx转为中文 # 再查映射表优先匹配ascii_tld再fallback到原始tld if ascii_tld in TLD_SERVER_MAP: return TLD_SERVER_MAP[ascii_tld] except Exception: pass4.5 现象同一域名多次查询expiration_date字段值不一致有时是2025-08-13有时是2025-08-14原因WHOIS服务器返回的时间是UTC但源码解析时未指定时区datetime.strptime()默认按本地时区解析。若服务器在夏令时切换日返回时间本地时区偏移变化导致日期错位。解决所有时间解析强制用UTCfrom datetime import datetime, timezone # 替换原解析逻辑 dt datetime.strptime(date_str, %Y-%m-%d %H:%M:%S) dt_utc dt.replace(tzinfotimezone.utc) # 显式设为UTC parsed[expiration_date] dt_utc.isoformat()5. 进阶技巧把WHOIS源码变成可审计的域名资产台账生成器单纯查域名信息是起点真正让这套源码产生业务价值是把它嵌入资产台账流水线——自动发现新注册域名、标记高危注册信息、关联IP与SSL证书。下面给出一个可直接复用的增强方案不新增外部依赖只改源码逻辑。5.1 步骤一在解析结果中注入注册者风险标签WHOIS里registrar、country、name字段隐含风险信号。在whois_parser.py的parse_response()函数末尾追加风险评估逻辑def add_risk_tags(parsed): # 高危注册商已知售卖给黑产的 registrar high_risk_registrars { Namecheap, Inc., PDR Ltd. d/b/a PublicDomainRegistry.com, 1api GmbH, CSC Corporate Domains, Inc. } if parsed.get(registrar) in high_risk_registrars: parsed[risk_tag] high_registrar # 隐私保护滥用whoisguard.com等代理服务 if privacy in (parsed.get(email, ) parsed.get(name, )).lower(): parsed[risk_tag] privacy_masked # 国家风险根据MITRE ATTCK地理分布数据 high_risk_countries {RU, CN, KP, IR} if parsed.get(country, ).upper() in high_risk_countries: parsed[risk_tag] high_country return parsed # 在主解析流程中调用 result parse_response(raw_text, tld) result add_risk_tags(result)这样输出JSON就自带risk_tag: high_registrar字段可直接导入SIEM做告警。5.2 步骤二关联IP与SSL证书构建完整资产图谱WHOIS只给注册信息但安全分析需要IP和证书。在whois_query.py中扩展--enrich参数python whois_query.py --enrich example.com实现逻辑不依赖额外库用socket.gethostbyname(domain)查A记录注意仅IPv4忽略AAAA用ssl.get_server_certificate((ip, 443))获取证书PEM解析证书中的subjectAltNameSAN提取所有绑定域名。# enrich部分代码放入whois_query.py if args.enrich: try: ip socket.gethostbyname(domain) parsed[ip_address] ip # 获取SSL证书超时3秒避免阻塞 context ssl.create_default_context() with socket.create_connection((ip, 443), timeout3) as sock: ssock context.wrap_socket(sock, server_hostnamedomain) cert ssock.getpeercert() parsed[ssl_issuer] dict(x[0] for x in cert[issuer]) parsed[ssl_subject] dict(x[0] for x in cert[subject]) # 提取SAN try: ext [x for x in cert[extensions] if x[extnID] subjectAltName][0] san_list [d[dNSName] for d in ext[value]] parsed[ssl_san] san_list except: parsed[ssl_san] [] except Exception as e: parsed[enrich_error] str(e)注意ssl.get_server_certificate()在Python 3.10已弃用必须用wrap_socket()方式否则查cloudflare.com等CDN域名会因SNI失败。5.3 步骤三生成可审计的CSV台账字段对齐GDPR与等保2.0要求最终输出不是JSON而是带审计元数据的CSV满足合规检查domainregistrarcreation_dateexpiration_daterisk_tagip_addressssl_issuer_Ossl_subject_CNquery_timequery_ipexample.comGoDaddy.com, LLC1995-08-14T04:00:00Z2025-08-13T04:00:00Znull93.184.216.34DigiCertexample.com2024-06-15T10:22:33Z192.168.1.100生成逻辑--output csv# 输出前添加审计字段 result[query_time] datetime.now(timezone.utc).isoformat() result[query_ip] socket.gethostbyname(socket.gethostname()) # 本机出口IP # 写CSV用csv.DictWriter字段顺序固定 fieldnames [domain,registrar,creation_date,expiration_date,risk_tag, ip_address,ssl_issuer_O,ssl_subject_CN,query_time,query_ip] with open(args.output, w, newline) as f: writer csv.DictWriter(f, fieldnamesfieldnames) writer.writeheader() writer.writerow({ domain: result.get(domain, ), registrar: result.get(registrar, ), creation_date: result.get(creation_date, ), expiration_date: result.get(expiration_date, ), risk_tag: result.get(risk_tag, ), ip_address: result.get(ip_address, ), ssl_issuer_O: result.get(ssl_issuer, {}).get(organizationName, ), ssl_subject_CN: result.get(ssl_subject, {}).get(commonName, ), query_time: result[query_time], query_ip: result[query_ip] })这个CSV可直接导入Excel做排序筛选也能被Splunk、ELK摄入做长期趋势分析——比如统计risk_taghigh_registrar的域名月增长率就是黑产活动水位的先行指标。我坚持不用python-whois这类库就是因为它的抽象层掩盖了协议细节。每次修一个正则、调一次settimeout()、加一行idna.decode()你对互联网基础设施的理解就深一分。这套源码不是终点而是你亲手拆开WHOIS协议黑匣子的第一把螺丝刀。希望帮到你。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/8 13:50:54

BERT+BiLSTM+CRF在医疗NER中的实战应用与知识图谱构建

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 13:50:54

YOLOv8农田虫情测报灯害虫识别系统实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 13:50:54

SSH远程服务器上codex登录403错误排查实战指南

最近帮一个同事排查问题,场景很典型:SSH 连远程服务器一切正常,密码和密钥都过了,服务器上的服务也跑得没问题。结果他想在这台远程服务器上用 codex 登录,命令敲下去,终端直接甩了一个 403 错误。更让人头…

2026/10/8 14:41:11

ChineseLyrics中文歌词数据库:面向隐喻理解与情感建模的NLP垂直语料

简介:ChineseLyrics中文歌词数据库是面向NLP研究者、自然语言处理初学者及文本分析实践者的高质量中文语料资源,专为词向量训练、韵律建模、歌词生成、情感分析等任务提供真实、结构化、可直接加载的原始数据支撑。资源共6个文件,含5个按歌手…

2026/10/8 14:41:11

Django实现豆瓣电影推荐系统:协同过滤实战指南

1. 这不是“又一个推荐系统”,而是用Django把协同过滤真正跑通的实战记录我带过十几期Python后端训练营,每次讲到推荐系统,学员眼睛都亮——但一动手就卡在“算法写出来了,可怎么塞进Web里?”、“用户行为数据存哪儿&a…

2026/10/8 14:41:11

Linux基础指令进阶:从文件权限到Shell脚本实战

上一期把 ls 、 cd 、 cat 这些最基础的指令过了一遍,这期顺势往上走一层。标题叫“Linux基础指令(2)”,其实我已经刻意回避了那些“一查手册就知道”的内容,挑的都是在日常运维、写脚本、排查故障时真正高频使用…

2026/10/8 14:41:11

Java实现巨洞冒险:面向对象建模与游戏状态机设计

简介:本资源是一份面向Java初学者与高校软件工程实践者的完整课程项目开发包,聚焦经典文本冒险游戏“巨洞冒险”的功能拓展与工程化重构。资源以Java面向对象设计为核心,涵盖代码注释完善、类图建模(EA)、开发过程记录…

2026/10/8 14:41:11

Java数据结构全解析:从ArrayList到HashMap与红黑树

1. 先想明白:数据结构在Java里到底是什么 做Java开发三五年的人,跳槽面试时被问“HashMap为什么线程不安全”“ArrayList和LinkedList什么时候选谁”,十有八九会一愣——不是不会,是平时写业务代码根本用不到这些细究。但数据结构…

2026/10/8 14:36:10

Notepad++五大核心插件实战指南:轻量IDE级文本处理工作流

简介:本资源是面向程序员、Web开发者及系统运维人员的Notepad高效开发环境配置包,专为解决新装或重装Notepad后需逐一手动下载配置插件的繁琐问题而设计。压缩包为ZIP格式,共包含数十个经实测兼容的常用插件,涵盖代码比对&#xf…

2026/10/8 10:03:18

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/8 10:03:20

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/8 6:05:44

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 0:02:17

自然数立方等于连续奇数之和:从证明到编程验证

十几年来我一直游走在数学科普和编程教学这两块内容之间,对“看起来像魔法、拆开全是数学”的结论总是格外敏感。最近翻资料时又撞见一句话:任何一个自然数 m 的立方,都可以写成 m 个连续奇数之和。2 的立方等于 3 加 5,3 的立方等…

2026/10/8 0:02:17

C#上位机SSH连接实战:用SSH.NET补齐超时、批量与密钥认证

简介:这是一份基于 C# 开发的 SSH 连接功能半成品工程,原本作为另一个主项目的子功能模块,现独立打包分享。工程采用 WinForms 界面,包含源码、解决方案、安装部署工程、NuGet 依赖包及说明文档,适合正在做远程连接、网…

2026/10/8 0:02:17

Java SpringBoot一体化智能售后系统设计与实现全解析

毕业设计年年做,Java Web 方向的题目翻来覆去就那么几个,但“一体化智能售后系统”这个题,每次看到我都觉得值得认真聊一聊。它不是一个简单 curd 堆出来的管理系统,而是把客户、工单、派单、处理、回访、统计整条链路串起来的一套…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑