☰
IP归属地查询接口设计:从Whois/RDAP到ASN、PTR与GeoIP数据整合
2026/10/13 7:43:05 网站建设 项目流程

很多做数据分析、风控、网络运维的人都会遇到一个很朴素的需求:给我一个IP,我想知道它在地球的哪个角落、属于哪家公司、自己还是托管机房、有没有反解域名。我自己在做一个内部叫“IP资产画像”的小工具时,把这块完整趟了一遍,今天就把这套东西从接口设计到数据坑一次讲清楚。

这段内容适合后端工程师、安全分析、爬虫开发,以及所有需要把“一串数字地址”翻译成“可读地理位置和归属信息”的开发者。你可以直接拿去设计自己的查询服务,也可以只挑其中几个思路完善现有逻辑。

1. 先搞清楚这类接口到底在解决什么问题

一个IPv4地址本质是32位的二进制数字,例如让人类头疼的114.114.114.114。它本身不含任何地理属性。所谓“IP归属地”,是通过外部数据源(如运营商的IP分配数据库、Whois注册信息、RIR(地区互联网注册机构)下发的记录、商用的GeoIP库)把IP段映射到对应的地理位置、机构名称和网络自治域编号。

1.1 地理位置、组织名、AS号和域名反查四个维度

按我这次的需求,原始标题写得很清楚:IP到地理位置、所属组织名、AS号、域名反查。这四件事正好是四个不同层面:

  • 地理位置:国家、省份、城市、经纬度,甚至区号、时区。这是最常被展示的一层,也是误差容忍度最低的一层。
  • 所属组织名:这个IP段归谁管。比如某个云服务商、某个大学、某个宽带运营商。在Whois里它会以netname、org-name、descr等形式存在。注意这里不是AS的注册人,而是IP段的直接管理人。
  • AS号(自治系统号):标识一个拥有独立路由策略的自治系统。比如某大运营商的骨干网会公告大量IP段,它们都挂在该AS号下。AS号是判断“这个IP是自己机房还是云厂商”的关键。
  • 域名反查:本质上就是PTR记录(Pointer Record),即从IP反查域名,比如1.2.3.4反解出server1.example.com。它不是Whois体系的东西,但往往是IP情报里最后一块拼图,能告诉你这个IP在DNS世界里“叫什么”。

这四个维度组合起来,你才能回答出“这个IP到底是什么”——是一个云上临时虚拟机、某个公司办公宽带的出口、还是一家IDC机房里专门跑业务的物理机。

1.2 为什么要自己封装而不直接用现成库

开源社区有GeoLite2、IP2Region这类离线库,也有各种在线服务商开箱即用的HTTP接口。那为什么还要自己动手封装?

我当时的出发点有三个:

第一,离线库的更新频率和管理成本。GeoLite2需要定期下载,版权IDC数据本身就有精度差异;IP2Region自定义格式非常快,但也是内置在某个时间点的快照里。

第二,在线公开接口免费但不可控。很多所谓“免费IP查询”接口要么限流、要么字段不全、要么经常挂。项目里如果把它当成核心依赖,后果很可怕。

第三,查询规模和数据整合的需求。我手里经常有一批要批量判定的IP,可能是几万条,也可能几十万条。如果走单条调用的公开接口,三天三夜也跑不完。而且我还想把地理位置、ASN、PTR、Whois的org信息统一落库,形成一份可供后续SQL直接筛选的资产表,这明显不是调俩现成接口就能搞定的。

所以在动手写代码之前,我先把数据链路拆成了三个层级:原始Whois协议、RDAP协议、DNS PTR查询。然后在这之上做聚合、缓存和并发控制。

2. 读取IP信息远不止一个“HTTP接口”那么简单

标题里说的“API接口”,本质上是对底层多个数据源的统一封装。要理解这个封装里到底放着什么,需要先知道数据从哪来。这是我和很多人第一次踩坑的地方——以为找个在线API就是全部了,忽略了如何去校验甚至去替代它。

2.1 Whois协议:最古老也最啰嗦的文本来源

Whois使用TCP 43端口,查询起来非常原始:你连上服务器的43端口,发送一个ip 1.2.3.4\r\n,服务端就会把一大串纯文本返回给你。里面对人类友好,但对机器很不友好:

inetnum: 1.2.3.0 - 1.2.3.255 netname: EXAMPLE-NET descr: Example Cloud Services country: SG org: ORG-EX1-RIPE

这种格式因RIR(RIPE、APNIC、ARIN等)不同而不同,而且Whois服务器还可能返回一个“请去另一个Whois服务器查询”的跳转。早期版本里我和同事写正则解析过APNIC的返回,说实话,维护起来非常痛苦。你永远不知道下一行会不会多出一个你没有见过的属性名。

Whois最坑的一点是:它不是标准化的。有的RIR叫netname,有的叫NetName;有的注册信息里根本没有地理精度。这就直接催生了RDAP。

2.2 RDAP:今天更推荐的注册数据访问协议

RDAP(Registration Data Access Protocol)是Whois的官方进化版,基于HTTP和JSON。它把Whois里梳理的注册实体、网络路由、反查点都结构化返回。查询体验就像这样:

访问https://rdap.apnic.net/ip/1.2.3.4会得到一组JSON,其中包括handle、name、country、entities(注册实体)、cidr等。RIR还提供bootstrap服务,让客户端知道该去哪个RIR的RDAP服务器查询,减少跳转。

用RDAP的优势非常直接:

  • 输出是JSON,字段有相对稳定的定义,不用再写脆弱的文本正则;
  • 支持查询IP、ASN、域名、实体等不同对象;
  • 支持错误码和中文化的错误消息(这块看部署方);
  • 很多RIR自带的RDAP还带events、status等元信息,对判断IP是否被封禁、是否保留都很有用。

在我这次做的项目里,把绝大部分 Whoas 文本解析都换成了 RDAP,只有个别老旧的RIR落地没有RDAP服务时才退回到Whois。

2.3 ASN关联:从IP到自治域的换算

拿到AS号本身也是一种协议交互。通常做法是先通过Whois/RDAP拿到IP段所属的origin或aut-num,然后再去查询AS的注册信息。举个例子,IP段1.2.3.0/24的origin可能是AS12345,然后你再查AS12345的Whois,得到它的机构名、国家、邮箱等。

这里有一个实际使用中容易忽略的点:一个IP段可能对应多个AS号。特别是运营商之间互联的地址、以及新接入点上的前缀,注册表里会同时列出origin和member-of。你如果只取第一个,可能出现错判。所以我返回的时候干脆保留了origin_asns数组,而不是一个单独的asn字段。

2.4 DNS PTR反查:域名反查的底层实现

域名反查走的是DNS协议里的PTR记录,不是HTTP接口。查询逻辑是把IPv4地址反过来拼成x.x.x.x.in-addr.arpa,比如4.3.2.1.in-addr.arpa,然后发起PTR类型查询。IPv6则对应.ip6.arpa。命令行的dig -x 1.2.3.4就是干这事的。

PTR记录的权威性通常由拥有该IP段的机构自己维护。云厂商会给每台服务器自动生成类似ip-1-2-3-4.ap-northeast-1.compute.internal这样的反解名;企业自建机房可能维护更友好的名称。这和大名鼎鼎的“域名解析到IP”是反过来的,所以叫反查。

PTR查询有自己的坑:很多IP根本没有PTR记录,或者PTR记录和实际域名相差十万八千里。我通常是把它作为辅助判断,绝不当主要证据。一句话总结:PTR有值提高置信度,PTR没值说明不了什么。

3. 接口设计:把多数据源收敛成一个稳定响应

接下来聊最关键的部分——怎么把自己要的“IP到地理位置、所属组织名、AS号、域名反查”做成一个实打实的接口。我这里不限定语言和框架,直接讲通用的HTTP接口设计,只要你后端会话能处理,就能直接照搬。

3.1 请求参数设计

对外暴露的查询接口建议设计成简单的GET请求:

GET /ip/1.2.3.4 GET /ip/1.2.3.4?lang=zh-CN&fields=geo,asn,ptr

参数设计我用过两套:

  • lang:控制返回里的中文文案,比如组织名的本地化描述。默认en,支持zh-CN。
  • fields:让调用方只取需要的字段,减少响应体大小。有人只需要ASN做判断,没必要强制拉回PTR。
  • refresh:布尔值,默认false。加上之后强制绕过缓存重新拉Whois/RDAP。这个参数在排查数据异常时特别好用,但要配频控,防止有人故意刷源站。
  • ip:支持单个IPv4/IPv6,也可以只接收路径参数。批量查询我建议单独开一个POST /ip/batch,最大条数比如500,内部并发,这样避免在URL里塞一大排地址。

3.2 响应字段设计

这是标题四个维度的落地位置。我的响应会长这样:

{ "code": 0, "message": "ok", "data": { "ip": "1.2.3.4", "version": 4, "geo": { "continent": "AS", "country": "SG", "country_name": "Singapore", "province": null, "city": null, "postal_code": null, "latitude": 1.3521, "longitude": 103.8198, "timezone": "Asia/Singapore" }, "asn": { "asn_list": [12345, 67890], "org_name": "Example Cloud Pte. Ltd.", "route": "1.2.3.0/24", "rir": "APNIC" }, "ptr": { "value": "server-1.example.com.", "truncated": false, "last_checked": "2025-01-01T00:00:00Z" }, "cache": { "hit": 1, "source": "RDAP", "ttl": 3600 } } }

字段设计有几点的心得:

  • asn_list我特意用数组而非单个整数。前面说过,RIR注册信息里一个路由可能对应多个AS号。数组比单个数字兼容度更高。
  • geo里我区分了国家级别和城市级别。因为免费数据源的城市级精度很差,如果源库没给,就显式置null,不要瞎猜。
  • ptr.value如果DNS里没有记录,设置为null,不去造一个空字符串。
  • cache.source可以告诉调用方当前数据来自哪一层,对排障非常有价值。如果是RDAP/LIVE表示刚抓到,如果是MEMORY表示直接从缓存返回。

3.3 错误码和边界情况

IP查询最大的问题是参数本身不合法。我设计的错误码:

状态码业务码说明
2000成功
4001001IP格式不合法(包含字符串、端口号、超范围)
4041002IP在任何数据库中都无记录
4221003输入为保留/私有地址,无法定位到公网位置
5001004上游RIR/DNS查询失败
4291005超出调用频率限制,提示等待

这里特别注意1003。很多人查询内网IP会发现得到“局域网”这种结果。其实对于10.0.0.0/8、192.168.0.0/16这类私有地址,直接返回保留地址标识就好,不必硬查Whois。RFC 1918定义的私网地址不注册公网路由,硬查出来的数据也不具备参考意义。当然,如果要求做内网资产扫描,你可以在内部额外挂一套自定义映射表。

还有IPv4-mapped IPv6地址,比如::ffff:1.2.3.4,在解析层要先转成IPv4,否则RDAP查询会失败。这类小细节不做处理,非常容易在联调阶段翻车。

4. 数据质量:接口好写,数据难搞

接口写一天就能跑通,数据质量才是真正决定项目生死的东西。最开始我从免费库和RIR快照直接拉数据,结果在一批真实IP上测试,准确率低得让人怀疑人生。后来慢慢把数据源分级、交叉校验、设置过期策略后,才渐渐能看。

4.1 数据来源分级

我把数据源分成三个层级:

  • 权威源:RIR/RDAP(APNIC、ARIN、RIPE、LACNIC、AFRINIC)。这些数据不包含精确经纬度,但组织名、AS号、国家字段都是官方注册信息,可信任度最高。
  • 半权威源:各类Whois镜像、RIR每日更新文件、公开的BGP路由表(BGP dump)。
  • 第三方推断源:商业GeoIP、IP2Location、MaxMind等。它们的地理位置是“推断”出来的,通过测量延迟、路由路径、用户上报等混合手段得到,城市级精度波动大。

在我的方案里,Whois/RDAP作为支撑ASN和机构名的底座,GeoIP类库作为地理位置层的补充。两者拼起来,得到标题所列的完整四维数据。

4.2 交叉校验和置信度

有了多个数据源之后,不能简单地“哪个先返回用哪个”,要做交叉校验。我遇到的典型案例是:某RIR的country字段是CN,但MaxMind判断城市为Hong Kong,而ASN的注册国家是US。这种情况不交叉校验就会产生错判。

我最后做的逻辑是:

  1. RDAP的主country与Whois的country是否一致?一致则给国别置信度加分。
  2. 第三方GeoIP的城市和RDAP记录的city/addr是否能对上?能对上就用城市级信息;对不上则只保留国家级别,城市置null。
  3. ASN的注册国家与IP的国家差异较大(比如超过一定距离),则在响应中附一个ambiguous_geo标记,让调用方自行决定是否信任。

这个设计谈不上完美,但至少避免了“看到城市名就不管真假”的粗暴行为。

4.3 缓存与更新策略

数据是“长期有效但并非永远有效”。IP段分配的变动不像热搜词每天变,但确实有常态化回收、合并、转移。因此:

  • RDAP查询结果缓存24小时,源站的刷新基本以天为单位。
  • GeoIP库每周同步一次,尽量选择周级增量包。
  • PTR记录缓存时间要短很多,我设的是1小时。因为DNS PTR属于运维配置,随时可能被改。某些海外主机商更容易出现PTR漂移。

另外,建议在内存缓存中记录每个IP的最近一次last_checked。当日志里出现大量“同一IP高频查询”时,可以直接走缓存,不要每次都打RDAP,否则很快会触发源站限流。

5. 落地实践:把单条查询扩展成批量服务

上面这些核心逻辑都验证通过后,我搭了一个可以处理几十万IP的批量判定服务。这块值得单独拿出来写,因为很多人卡在“接口写好了,但一跑批量就崩溃”。

5.1 批量查询的并发模型

几十万条IP如果要逐条走HTTP查询,哪怕每条300ms,也要10万秒,不可接受。实际做法是:

  1. 先用内存去重,把重复IP去掉;
  2. 按IP段做聚类,比如相同/24的IP只查一次路由,然后用段结果批量填充;
  3. 设置并发池。我用了协程池,控制同时发出的查询数量在20-50之间,避免源站和带宽被打爆;
  4. 使用持久队列做失败重试。对瞬时网络错误,重试2次;对永久错误(如RDAP 404),标记后放弃。

这里关键是“聚类”。对于要在同一 /24 段里的IP,整个段的结果95%相同。只查询段级信息,再用段结果填充段内各IP,速度能提升10倍以上。如果IP段刚好跨地理边界,再用单IP回源补齐。

5.2 本地构建离线索引

为了给更大规模的数据使用,我实际建立了一个本地SQLite索引。表结构大概是:

CREATE TABLE ip_asset ( ip TEXT NOT NULL, network TEXT NOT NULL, country TEXT, province TEXT, city TEXT, asn INTEGER, org_name TEXT, ptr_value TEXT, source TEXT, updated_at DATETIME ); CREATE INDEX idx_ip_asset_ip ON ip_asset(ip);

把查询结果落库后,后续的审计和报告需求直接用SQL完成,甚至可以用窗口函数统计一个国家下的ASN分布。对于几十万条数据的临时性查询,SQLite已经足够;如果长期更新,则考虑换成DuckDB或Parquet。

5.3 部署监控

接口上线后别忘了监控三样东西:

  • 源站查询成功率:RDAP是否大面积5xx、DNS解析是否超时。
  • 缓存命中率:如果命中率低于70%,说明缓存策略或者查询分布有问题。
  • PTR与RDAP的延迟分布:有些RDAP在全球不同节点访问速度差异明显,实时调用的尾延迟可能非常高。

我把监控结果集成到内部看板里,一跑就是两周。期间发现,某个海外的Whois服务器在凌晨两三点经常超时,后来在代码里加了个直连回退逻辑,问题才缓解。

6. 我踩过的数据坑,一次贴给你

最后一个部分专门说坑。这里没有代码,但每一个都是用真金白银换来的经验。如果你做的是IP类数据服务,几乎都会遇到。

6.1 Whoas文本解析的“想当然”坑

一开始我自写正则解析Whois返回。因为当时觉得“格式虽乱,但总归有规律,大不了多写几个边界判断”。结果APNIC返回的descr可以跨两行,ARIN的OrgName大小写不固定,RIPE的org字段长度经常变化。调试到后面,每加一个RIR就要多写一堆特殊处理,终于忍无可忍切换到了RDAP。

所以如果你还没走到这一步,我的建议很直接:直接用RDAP,不要用原始Whois做主力解析。Whois只作为RDAP缺失时的兜底。

6.2 “位置”这个词的误解

很多人以为“IP地理位置”一定精确到街道。实际上,大量IP段的地理信息只到国家或省份,运营商级NAT下,同一出口IP在同一个城市的不同区县都很正常。我曾拿着一批某城市热力公司IP去查城市,返回结果是隔壁城市,原因是该运营商没有细分机房,只在省份层面做了注册。这种事真的不是数据源“错了”,而是它本来就“只有这么粗的维度”。

解决方案就一个:产品文档里写清楚精度级别,并在数据返回中标注accuracy_radius或明确city可能是推断值。宁可让用户看到“省份”,也不要为了显得专业硬填一个“城市”。

6.3 PTR记录被反向利用

域名反查容易让人产生一个错觉:PTR是这个IP的“官方名称”。实际上PTR可以由IP持有人随意配置,很多人会故意设置成google.com、cloudflare.com来误导扫描器。所以只凭PTR里的面子域名判断IP归属,完全不可靠。

正确用法是:把PTR作为IP归类的一个次要标签,必须和ASN、组织名结合。比如看到PTR里出现example-cloud.net,不急着认定就是该业务域名,先看ASN是不是注册给这个机构的,再看证书和HTTP响应,综合判断。

6.4 IPv6世界不是“免费加大”

IPv6地址块2001:db8::/32看起来数量巨大,但很多RIR对IPv6段不设城市级GeoIP信息,只有国家和“地区级”粗粒度数据。拿IPv4那套经验直接套IPv6会水土不服。批量查询IPv6时,更是要注意它没有“城市”概念,必须接受省份/州级别的定位粒度。

6.5 频率限制不只是为了礼貌

几家RIR的RDAP服务也有限流。实际遇到过在一次批量任务里,因为并发拉太多,晚上发现整个办公室出口IP被对方临时限制,连手动查询都被拒了。后来我在设计里加了三件事:符合规范的User-Agent、合理的缓存TTL、每客户端令牌桶限流。限流不是为了刁难调用方,是为了保护上游数据源,也是给自己服务续命。


做IP到地理位置、组织名、AS号、域名反查这类接口,技术门槛不算高,真正的门槛在于数据整合、异常处理和边界情况的覆盖。只要把RDAP、DNS PTR、GeoIP三个数据源理清楚,再用缓存和并发控制把它们组装起来,这套服务就能稳定跑很久。如果后续你有批量IP需要打标签、做资产测绘,可以直接参照上面的方案动手试试。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询