域名是互联网的基石,为网站提供易记的地址。理解域名背后的管理机制对于网页开发、数字营销或域名注册者都很重要。当前已全面取代 WHOIS 的 RDAP 协议已经是主流了,如何使用 Python 脚本来做到域名查询、域名抢注,可以看下方内容。
简单解释版
域名注册局与注册商的角色
-
注册局(Registry): 负责管理特定顶级域名(TLD)或国家代码顶级域名(ccTLD)。例如,VeriSign 管理 .com 和 .net,维护这些 TLD 下的所有域名数据库,确保唯一性。
-
注册商(Registrar): 作为代理,代表注册局向公众销售域名。常见的注册商包括 GoDaddy、Namecheap 和 Google Domains。注册商是用户与注册局之间的中介。
-
关系与外包: 一些注册局可能不直接管理操作,而是外包给技术服务商。这些公司既提供技术支持,也可作为注册商。一个注册商可以连接多个注册局,提供多种 TLD 的注册服务。此外,一些提供域名注册的网站实际上只是注册商的代理,而非注册商本身。
WHOIS 系统的详细说明
WHOIS 是一种协议,允许用户查询域名注册数据库,获取如注册人信息、注册时间和到期时间等详情。
-
IANA 的角色: IANA 维护顶级 WHOIS 服务器 whois.iana.org,存储注册局信息和其 WHOIS 服务器地址。
-
查询过程: 要找到某个 TLD 的 WHOIS 服务器,可先查询 IANA 的服务器。例如,输入 “com” 可得到 .com 域名的 WHOIS 服务器为 whois.verisign-grs.com。接着,可连接到该服务器的 43 端口,发送完整域名(如 qq.com)并回车,获取详细信息。
-
格式差异: 不同注册局的 WHOIS 响应格式可能不同,需编写程序并使用正则表达式解析提取有用信息。例如,查询已注册域名可得注册人信息和时间,未注册域名则返回明确标志。
-
隐私保护: 由于隐私问题,近年注册商的 WHOIS 服务器已不再返回详细联系信息,仅提供基本注册信息。
RDAP 协议的介绍与过渡
RDAP(注册数据访问协议)是 WHOIS 的继任者,使用 HTTP 接口返回 JSON 数据,具有以下优势:
-
支持国际化,适合多语言环境。
-
提供更安全的访问控制。
-
数据格式标准化,便于解析。
ICANN 宣布,自 2025 年 1 月 28 日起,RDAP 将成为通用顶级域名(gTLD)注册信息的权威来源,取代 WHOIS 服务。这一日期基于 ICANN 的公告,标志着 WHOIS 服务的逐步退出。用户可使用 ICANN 的 RDAP 查找工具 或 GitHub 上的开源命令行客户端(如 ICANN RDAP Lookup Client)进行查询。
实践中的注意事项
-
批量查询: 进行大量域名查询时,部分注册局可能限制单个 IP 的短时间内查询次数。为此,建议使用多个 IP 地址或实现查询速率限制,以避免触发限制。
-
TLD 特定信息: 不同注册局提供的信息可能有所不同。例如,.ai 域名的注册局不返回注册时间和到期时间,需特别注意。
以下是通过 AI 整理的、经过核验详细版本,有点 AI 味儿,但信息是没错的。
1. 域名注册体系详解
1.1 注册局与注册商的角色区分
域名注册局 (Registry)是特定顶级域名 (TLD) 的管理机构,负责维护该 TLD 下所有域名的中央数据库。例如:
-
VeriSign 管理.com 和.net
-
Public Interest Registry 管理.org
-
CNNIC 管理.cn
-
Afilias 管理.info
域名注册商 (Registrar)是获得 ICANN(互联网名称与数字地址分配机构) 认证的实体,作为注册局与终端用户之间的中介。知名注册商包括:
-
GoDaddy
-
Namecheap
-
Google Domains(现已被 Squarespace 收购)
-
NameSilo
-
Cloudflare Registrar
1.2 注册体系的层级结构
域名注册体系呈现明确的层级结构:
-
ICANN:位于顶层,制定政策并认证注册商
-
注册局:负责特定 TLD 的技术运营
-
注册商:向用户提供域名注册服务
-
用户:最终的域名持有者
1.3 特殊情况与变体
某些情况下,注册体系的角色可能出现交叉:
-
技术服务外包:部分注册局将技术运营外包给第三方公司,这些公司既提供注册局服务,也可能作为注册商
-
注册商代理:市场上存在许多域名注册服务提供商,它们实际上只是注册商的代理或分销商,不具备 ICANN 认证资格
-
垂直整合:某些大型公司同时扮演注册局和注册商的角色,如 Verisign 既管理.com 和.net,也提供注册服务
2. WHOIS 系统全面解析
2.1 WHOIS 的定义与历史
WHOIS(读作 "who is") 是一个查询和响应协议,用于查询域名的注册信息。它起源于 1982 年,最初设计用于识别负责特定互联网资源的实体。随着互联网的发展,WHOIS 成为查询域名注册信息的标准方式。
2.2 WHOIS 服务器层级
WHOIS 系统由多层服务器组成:
-
IANA 的顶级 WHOIS 服务器:whois.iana.org,存储所有 TLD 的注册局信息
-
注册局 WHOIS 服务器:每个 TLD 的注册局维护自己的 WHOIS 服务器
-
注册商 WHOIS 服务器:每个注册商也维护自己的 WHOIS 服务器
2.3 WHOIS 查询的详细步骤
以查询 "example.com" 为例,完整的 WHOIS 查询流程如下:
步骤 1:查询 IANA 的顶级 WHOIS 服务器
# 使用命令行工具
whois -h whois.iana.org com
# 或使用Socket连接
telnet whois.iana.org 43
# 然后输入"com"并回车
返回结果将包含.com 的注册局信息和 WHOIS 服务器地址:whois.verisign-grs.com
步骤 2:查询注册局的 WHOIS 服务器
# 使用命令行工具
whois -h whois.verisign-grs.com example.com
# 或使用Socket连接
telnet whois.verisign-grs.com 43
# 然后输入"example.com"并回车
返回结果将包含域名的基本注册信息,包括:
-
域名状态 (如已注册、转移锁定等)
-
注册日期和到期日期
-
域名服务器信息
-
注册商信息及其 WHOIS 服务器
步骤 3:查询注册商的 WHOIS 服务器 (可选)
# 假设注册商的WHOIS服务器是whois.registrar.example
whois -h whois.registrar.example example.com
然而,由于隐私保护政策,现在注册商的 WHOIS 服务器通常不会返回详细的注册人信息。
2.4 WHOIS 信息解析挑战
不同注册局的 WHOIS 响应格式各不相同,这给自动化解析带来了挑战。以下是几个主要 TLD 的 WHOIS 格式差异示例:
-
.com/.net:由 Verisign 管理,格式相对标准化
-
.org:提供更详细的状态信息
-
.io:格式简洁,但包含完整的注册日期
-
.ai:不返回注册日期和到期日期
解析 WHOIS 信息通常需要为每个 TLD 编写专门的正则表达式。以下是一个简单的 Python 示例,用于解析.com 域名的 WHOIS 信息:
import re
import socket
def query_whois(domain, server, port=43):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((server, port))
s.send((domain + "\r\n").encode())
response = b""
while True:
data = s.recv(4096)
if not data:
break
response += data
s.close()
return response.decode('utf-8', errors='ignore')
def parse_com_whois(whois_data):
# 解析注册日期
creation_date_match = re.search(r'Creation Date: (.+)', whois_data)
creation_date = creation_date_match.group(1) if creation_date_match else "未找到"
# 解析到期日期
expiration_date_match = re.search(r'Registry Expiry Date: (.+)', whois_data)
expiration_date = expiration_date_match.group(1) if expiration_date_match else "未找到"
# 解析注册商
registrar_match = re.search(r'Registrar: (.+)', whois_data)
registrar = registrar_match.group(1) if registrar_match else "未找到"
return {
"creation_date": creation_date,
"expiration_date": expiration_date,
"registrar": registrar
}
# 使用示例
domain = "example.com"
whois_data = query_whois(domain, "whois.verisign-grs.com")
parsed_data = parse_com_whois(whois_data)
print(parsed_data)
2.5 WHOIS 的局限性
WHOIS 系统存在多项局限性,这也是推动 RDAP 协议发展的原因:
-
格式不统一:不同注册局的响应格式各异
-
国际化支持有限:不支持非 ASCII 字符的域名 (IDN)
-
隐私问题:早期 WHOIS 公开了太多个人信息
-
查询限制:没有标准化的速率限制机制
-
缺乏身份验证:无法区分不同用户的访问权限
3. RDAP 协议:WHOIS 的现代替代品
3.1 RDAP 的定义与优势
注册数据访问协议 (Registration Data Access Protocol, RDAP) 是 WHOIS 的现代替代品,由 IETF 在 RFC 7480-7484 中定义。RDAP 通过 HTTP/HTTPS 提供服务,返回标准化的 JSON 格式数据。
RDAP 相比 WHOIS 具有显著优势:
-
标准化 JSON 格式:便于程序解析和处理
-
支持国际化域名 (IDN):完全支持 Unicode 字符
-
分层访问控制:可根据用户身份提供不同级别的信息
-
标准化查询参数:统一的查询语法
-
内置分页机制:适合大量数据返回
-
安全传输:支持 HTTPS 加密
3.2 ICANN 政策变更与 RDAP 过渡
ICANN 于 2025 年 1 月 27 日发布重要公告,宣布从 2025 年 1 月 28 日起,RDAP 将成为提供通用顶级域名 (gTLD) 注册信息的权威来源,正式取代 WHOIS 服务。这一决定基于 2023 年全球修订的 gTLD 注册协议,标志着域名查询系统的重大转变。
过渡时间表:
-
2023 年 5 月:ICANN 董事会批准 RDAP 修订
-
2024 年:过渡准备期
-
2025 年 1 月 28 日:RDAP 正式成为 gTLD 注册信息的权威来源
-
2025 年后:WHOIS 服务将逐步停用
3.3 RDAP 查询详细步骤
RDAP 查询比 WHOIS 更加直观,遵循 RESTful API 设计原则:
步骤 1:确定 RDAP 服务器
IANA 维护着 RDAP 服务器的 JSON 列表,可通过以下 URL 获取:
https://data.iana.org/rdap/dns.json
这个文件包含了各 TLD 对应的 RDAP 服务器地址。
步骤 2:构建 RDAP 查询 URL
RDAP 查询 URL 的一般格式为:
https://{rdap-server}/domain/{domain-name}
例如,查询 example.com 的 RDAP 信息:
https://rdap.verisign.com/com/v1/domain/example.com
步骤 3:发送 HTTP 请求并解析 JSON 响应
使用 HTTP 客户端发送 GET 请求,并解析返回的 JSON 数据。以下是使用 Python 的示例:
import requests
import json
def query_rdap(domain):
# 这里简化处理,实际应先查询IANA的RDAP服务器列表
tld = domain.split('.')[-1]
if tld == 'com':
rdap_server = "https://rdap.verisign.com/com/v1"
else:
# 处理其他TLD的逻辑
return {"error": "Unsupported TLD"}
url = f"{rdap_server}/domain/{domain}"
try:
response = requests.get(url)
if response.status_code == 200:
return response.json()
else:
return {"error": f"HTTP error: {response.status_code}"}
except Exception as e:
return {"error": str(e)}
# 使用示例
domain = "example.com"
rdap_data = query_rdap(domain)
print(json.dumps(rdap_data, indent=2))
RDAP 返回的 JSON 数据通常包含以下信息:
-
域名状态
-
注册日期和到期日期
-
域名服务器信息
-
注册商信息
-
联系人信息 (如果可用)
-
事件历史 (如创建、更新、转移等)
3.4 RDAP 工具与资源
以下是一些有用的 RDAP 工具和资源:
-
ICANN RDAP 查找工具:https://lookup.icann.org/en
-
RDAP 演示客户端:https://client.rdap.org/
-
RDAP 服务器列表:https://data.iana.org/rdap/dns.json
-
RDAP 支持的域名列表:https://deployment.rdap.org/
-
ICANN RDAP 命令行客户端:https://github.com/icann/rdap-lookup-client
4. 实用查询策略与最佳实践
4.1 批量查询策略
进行大规模域名查询时,需要注意以下几点:
查询速率限制
不同注册局和注册商对 WHOIS/RDAP 查询有不同的速率限制。例如:
-
Verisign(.com/.net):每 IP 每天约 1000-2000 次查询
-
Afilias(.org/.info):每 IP 每小时约 60-100 次查询
-
某些小型 TLD:限制更严格,可能只允许每 IP 每小时 10-20 次查询
多 IP 轮询策略
为避免触发速率限制,可采用多 IP 轮询策略:
import requests
import time
import random
def query_with_ip_rotation(domains, proxy_list):
results = {}
for domain in domains:
# 随机选择一个代理
proxy = random.choice(proxy_list)
try:
# 使用选定的代理发送请求
response = requests.get(
f"https://rdap.verisign.com/com/v1/domain/{domain}",
proxies={"http": proxy, "https": proxy},
timeout=10
)
if response.status_code == 200:
results[domain] = response.json()
else:
results[domain] = {"error": f"HTTP error: {response.status_code}"}
except Exception as e:
results[domain] = {"error": str(e)}
# 添加随机延迟,避免请求过于集中
time.sleep(random.uniform(1, 3))
return results
# 使用示例
domains = ["example1.com", "example2.com", "example3.com"]
proxy_list = [
"http://proxy1.example:8080",
"http://proxy2.example:8080",
"http://proxy3.example:8080"
]
results = query_with_ip_rotation(domains, proxy_list)
指数退避策略
当遇到限制时,可采用指数退避策略:
import time
import random
def exponential_backoff(max_retries=5):
for attempt in range(max_retries):
try:
# 执行查询操作
# ...
return result # 成功则返回结果
except RateLimitException:
if attempt < max_retries - 1: # 如果不是最后一次尝试
# 计算等待时间:2^尝试次数 + 随机数(0-1秒)
wait_time = (2 ** attempt) + random.random()
print(f"Rate limited, retrying in {wait_time:.2f} seconds...")
time.sleep(wait_time)
else:
raise # 达到最大重试次数,抛出异常
4.2 解析和存储查询结果
规范化数据结构
无论使用 WHOIS 还是 RDAP,都应将查询结果规范化为统一的数据结构:
def normalize_domain_data(data, source="rdap"):
normalized = {
"domain": "",
"status": [],
"created_date": None,
"updated_date": None,
"expiration_date": None,
"registrar": "",
"nameservers": [],
"raw_data": data # 保留原始数据以备后用
}
if source == "rdap":
# 解析RDAP JSON数据
normalized["domain"] = data.get("ldhName", "")
normalized["status"] = data.get("status", [])
# 解析事件日期
for event in data.get("events", []):
if event.get("eventAction") == "registration":
normalized["created_date"] = event.get("eventDate")
elif event.get("eventAction") == "expiration":
normalized["expiration_date"] = event.get("eventDate")
elif event.get("eventAction") == "last update":
normalized["updated_date"] = event.get("eventDate")
# 解析注册商信息
for entity in data.get("entities", []):
if "registrar" in entity.get("roles", []):
normalized["registrar"] = entity.get("ldhName", "")
# 解析域名服务器
for ns in data.get("nameservers", []):
normalized["nameservers"].append(ns.get("ldhName", ""))
elif source == "whois":
# 使用正则表达式解析WHOIS文本数据
# ...
return normalized
数据存储选项
根据查询规模和需求,可选择不同的存储方案:
-
小规模查询:CSV 或 JSON 文件
-
中等规模:SQLite 数据库
-
大规模查询:PostgreSQL 或 MongoDB
示例 SQLite 模式:
CREATE TABLE domains (
id INTEGER PRIMARY KEY,
domain TEXT UNIQUE,
status TEXT,
created_date TEXT,
updated_date TEXT,
expiration_date TEXT,
registrar TEXT,
query_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE nameservers (
id INTEGER PRIMARY KEY,
domain_id INTEGER,
nameserver TEXT,
FOREIGN KEY (domain_id) REFERENCES domains(id)
);
CREATE TABLE raw_data (
domain_id INTEGER PRIMARY KEY,
data TEXT,
FOREIGN KEY (domain_id) REFERENCES domains(id)
);
4.3 特殊 TLD 的处理策略
不同 TLD 的 WHOIS/RDAP 响应可能有显著差异,需要特别处理:
.ai 域名 (安圭拉)
.ai 域名的注册局不返回注册日期和到期日期,可通过以下方法估算:
-
使用历史 WHOIS 记录 (如有)
-
通过域名的 DNS 记录创建时间推测
-
使用 Internet Archive 的首次抓取时间作为参考
新 gTLD
对于.app、.dev 等新 gTLD,RDAP 是首选查询方式,因为这些 TLD 从设计之初就支持 RDAP。
国家代码 TLD(ccTLD)
某些 ccTLD(如.de、.uk) 有自己的查询系统和格式,可能需要特定的适配器。
5. 域名监控与安全应用
5.1 域名到期监控系统
利用 WHOIS/RDAP 数据构建域名到期监控系统:
import datetime
import smtplib
from email.mime.text import MIMEText
def check_expiring_domains(domains, days_threshold=30):
today = datetime.datetime.now()
expiring_soon = []
for domain in domains:
# 查询RDAP信息
data = query_rdap(domain)
normalized = normalize_domain_data(data)
if normalized["expiration_date"]:
expiry_date = datetime.datetime.fromisoformat(normalized["expiration_date"].replace("Z", "+00:00"))
days_remaining = (expiry_date - today).days
if days_remaining <= days_threshold:
expiring_soon.append({
"domain": domain,
"expiry_date": expiry_date,
"days_remaining": days_remaining
})
return expiring_soon
def send_expiry_notification(expiring_domains, email):
if not expiring_domains:
return
# 构建邮件内容
subject = f"域名到期提醒:{len(expiring_domains)}个域名即将到期"
body = "以下域名即将到期,请及时续费:\n\n"
for domain in expiring_domains:
body += f"- {domain['domain']}: 将在{domain['days_remaining']}天后到期 ({domain['expiry_date'].strftime('%Y-%m-%d')})\n"
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = "noreply@example.com"
msg['To'] = email
# 发送邮件
# ...
# 使用示例
domains = ["example1.com", "example2.com", "example3.com"]
expiring = check_expiring_domains(domains, days_threshold=45)
send_expiry_notification(expiring, "admin@example.com")
5.2 域名抢注监控
监控高价值域名的到期状态,为可能的抢注做准备:
def monitor_valuable_domains(domains_list, check_interval_days=7):
# 读取域名列表
with open(domains_list, 'r') as f:
domains = [line.strip() for line in f if line.strip()]
results = {}
for domain in domains:
try:
data = query_rdap(domain)
# 检查域名是否已注册
if "errorCode" in data and data["errorCode"] == 404:
results[domain] = "未注册,可立即注册"
else:
# 域名已注册,检查到期日期
normalized = normalize_domain_data(data)
if normalized["expiration_date"]:
expiry_date = datetime.datetime.fromisoformat(normalized["expiration_date"].replace("Z", "+00:00"))
today = datetime.datetime.now()
days_remaining = (expiry_date - today).days
results[domain] = f"已注册,还有{days_remaining}天到期"
else:
results[domain] = "已注册,到期日期未知"
except Exception as e:
results[domain] = f"查询错误: {str(e)}"
return results
5.3 网络安全应用
WHOIS/RDAP 数据在网络安全领域有广泛应用:
钓鱼域名检测
检测与特定品牌相似的可疑域名:
import re
from difflib import SequenceMatcher
def detect_suspicious_domains(brand_name, tlds=["com", "net", "org"]):
suspicious = []
# 生成可能的变体
variants = [
brand_name, # 完全匹配
brand_name.replace("o", "0"), # 字母替换为数字
brand_name.replace("i", "1"),
brand_name.replace("l", "1"),
brand_name.replace("e", "3"),
brand_name + "secure", # 常见后缀
brand_name + "login",
"my" + brand_name,
# 添加更多变体...
]
# 检查每个变体在不同TLD下是否已注册
for variant in variants:
for tld in tlds:
domain = f"{variant}.{tld}"
try:
data = query_rdap(domain)
# 如果域名已注册
if "errorCode" not in data:
# 获取注册日期
normalized = normalize_domain_data(data)
created_date = normalized["created_date"]
# 如果是最近注册的域名,更可疑
if created_date:
created = datetime.datetime.fromisoformat(created_date.replace("Z", "+00:00"))
days_since_creation = (datetime.datetime.now() - created).days
if days_since_creation <= 30: # 30天内注册的域名
suspicious.append({
"domain": domain,
"created_date": created,
"days_since_creation": days_since_creation,
"suspicion_level": "高"
})
else:
suspicious.append({
"domain": domain,
"created_date": created,
"days_since_creation": days_since_creation,
"suspicion_level": "中"
})
except Exception:
# 查询失败,继续下一个
continue
return suspicious
6. 未来趋势与发展
6.1 RDAP 的全面普及
随着 ICANN 正式将 RDAP 确立为 gTLD 注册信息的权威来源,我们可以预期:
-
WHOIS 服务将在未来几年内逐步淘汰
-
更多 ccTLD 将采用 RDAP 标准
-
RDAP 客户端工具将更加丰富和易用
6.2 隐私保护的加强
随着全球隐私法规 (如 GDPR) 的实施,域名注册信息的隐私保护将进一步加强:
-
个人信息将默认隐藏
-
分层访问控制将更加精细
-
合法执法和知识产权保护需求与隐私保护之间的平衡将继续调整
6.3 API 集成与自动化
RDAP 的 JSON 格式天然适合 API 集成,未来将看到:
-
更多域名管理平台集成 RDAP 查询
-
自动化域名监控和安全系统的普及
-
基于机器学习的域名分析工具
7. 总结
域名注册系统和查询协议是互联网基础设施的重要组成部分。从早期的 WHOIS 到现代的 RDAP,查询机制不断演进,以适应互联网的发展需求。随着 ICANN 宣布 RDAP 将在 2025 年 1 月 28 日成为 gTLD 注册信息的权威来源,我们正在见证一个重要的技术过渡期。
对于开发者、网络管理员和域名投资者而言,掌握这些知识不仅有助于进行域名管理和监控,还能帮助识别潜在的网络安全威胁。通过本文提供的详细步骤和代码示例,读者可以构建自己的域名查询和监控系统,充分利用 WHOIS 和 RDAP 提供的信息。
随着互联网的不断发展,域名注册和查询系统也将继续演进。保持对最新标准和实践的了解,将有助于更高效地管理域名资产和保护网络安全。