IP 信息查询
查询 IP 地址的地理位置、ISP、ASN 等详细信息
IPv4 vs IPv6:为什么需要 IPv6?
IPv4(1981 年)
格式:4 组十进制数(如 192.168.1.1)
总数:约 43 亿个地址(2³² = 4,294,967,296)
问题:地址已接近枯竭,早在 2011 年就已分配完毕
长度:32 位
IPv6(1998 年)
格式:8 组十六进制数(如 2001:0db8::1)
总数:约 340 万亿亿亿亿个地址(2¹²⁸)
优势:地址数量几乎无限,足够分配给地球上每一粒沙子
长度:128 位
为什么 IPv4 不够用?
- • 全球人口 80 亿,每人至少有 2-3 台设备(手机、电脑、平板)
- • 物联网设备爆发式增长(智能家居、汽车、可穿戴设备)
- • 企业和数据中心需要大量 IP 地址
- • 早期分配不合理(如 MIT 拥有 1600 万个 IP)
特殊 IP 地址段
回环地址(Loopback)
127.0.0.0/8(127.0.0.1 - 127.255.255.255)
用于本机测试,数据不会发送到网络,常用 127.0.0.1 表示 localhost
用途:测试本地服务、开发调试
私有地址(Private)
- 10.0.0.0/8(10.0.0.0 - 10.255.255.255)- A 类
- 172.16.0.0/12(172.16.0.0 - 172.31.255.255)- B 类
- 192.168.0.0/16(192.168.0.0 - 192.168.255.255)- C 类
用于局域网内部,不能直接访问互联网,需要 NAT 转换
用途:家庭网络、企业内网
APIPA 地址
169.254.0.0/16
当 DHCP 服务器不可用时,系统自动分配的临时地址
用途:自动配置(表示网络配置失败)
组播地址(Multicast)
224.0.0.0/4(224.0.0.0 - 239.255.255.255)
用于一对多通信,如视频直播、IPTV
保留地址
- 0.0.0.0/8 - 表示"本网络"
- 255.255.255.255 - 广播地址
- 192.0.2.0/24 - 文档示例专用
- 198.18.0.0/15 - 基准测试专用
最强公共 DNS 服务器
Google DNS
8.8.8.8 / 8.8.4.4
2001:4860:4860::8888 / 2001:4860:4860::8844
全球最快、最稳定、支持 DNSSEC
Cloudflare DNS
1.1.1.1 / 1.0.0.1
2606:4700:4700::1111 / 2606:4700:4700::1001
注重隐私、速度极快、不记录日志
Quad9 DNS
9.9.9.9 / 149.112.112.112
安全防护、阻止恶意网站
OpenDNS
208.67.222.222 / 208.67.220.220
家长控制、内容过滤
亚洲地区 DNS
- 阿里云 DNS(中国):223.5.5.5 / 223.6.6.6
- DNSPod(中国):119.29.29.29
- 114 DNS(中国):114.114.114.114
有趣的 IP 知识
💰 最贵的 IP 地址段
1.0.0.0/8 曾被 APNIC 以数百万美元购买,用于研究。某些"靓号" IP(如 8.8.8.8、1.1.1.1)价值连城,Cloudflare 花费巨资从电信公司手中购买了 1.1.1.1。
📍 为什么同一个 IP 会显示不同位置?
- • IP 地理位置数据库不同(各家 API 数据源不同)
- • 动态 IP 地址会变化(运营商重新分配)
- • VPN/代理服务器(显示代理服务器位置)
- • CDN 节点(显示最近的 CDN 服务器位置)
- • 移动网络(基站位置可能不准确)
📊 IPv6 普及率
截至 2024 年,全球 IPv6 普及率约 40%,印度、美国、德国领先,中国约 30%。比利时是全球 IPv6 普及率最高的国家,超过 60%。
🎂 第一个 IP 地址
1983 年 1 月 1 日,互联网正式采用 TCP/IP 协议,第一个 IP 地址诞生。BBN Technologies 的 Leonard Kleinrock 被认为是第一个使用 IP 地址的人。
🗑️ IP 地址分配的不合理
早期互联网分配 IP 极其慷慨:MIT(一所大学)拥有 1600 万个 IP(整个 18.0.0.0/8),苹果公司拥有 1600 万个 IP(17.0.0.0/8)。而整个中国大陆只分配到约 3.3 亿个 IP,却要服务近 10 亿互联网用户——按人均 2 台设备计算,至少需要 20 亿个 IP。这种分配不均导致中国不得不大量使用 NAT 技术共享 IP。
🚫 IP 黑名单
全球有多个 IP 黑名单数据库(如 Spamhaus),用于标记垃圾邮件、恶意软件、DDoS 攻击等来源 IP。一旦 IP 被列入黑名单,可能导致邮件被拒收、网站被屏蔽。
🤯 IP 地理位置的奇葩案例
美国堪萨斯州一户普通人家因为被 MaxMind 公司的 IP 数据库设为默认位置(坐标 38°N 97°W,美国地理中心),导致数百万个无法精确定位的 IP 都指向这里。这家人莫名成了"全美国的黑客窝点",收到无数 FBI、警察、债主、诈骗受害者的骚扰电话和上门拜访,甚至有人深夜破门而入。2016 年,这家人将 MaxMind 告上法庭,最终获得赔偿。
💸 IPv4 地址可以买卖
由于 IPv4 地址枯竭,IP 地址已成为可交易商品。黑市价格可达 40 美元/个。2011 年,微软以 750 万美元从破产的 Nortel 公司购买了 66.6 万个 IP 地址,平均每个 IP 约 11.25 美元。2014 年,亚马逊、微软等科技巨头疯狂抢购 IPv4 地址,价格一度飙升。
🤦 IPv4 设计者的"失算"
1981 年,IPv4 的设计者们认为"42 亿个地址,人类一辈子都用不完"。他们完全没想到互联网会发展到今天的规模:全球 80 亿人口,每人至少 2-3 台设备,加上物联网设备的爆发式增长。如果当初设计成 64 位或 128 位,就不会有今天的地址枯竭问题了。
🏠 127.0.0.1 的秘密
127.0.0.1(localhost)不仅仅是一个地址,整个 127.0.0.0/8 段(约 1600 万个地址)都是回环地址。你可以 ping 127.0.0.2、127.1.2.3 等任意地址,都会指向本机。
⏰ IPv4 地址枯竭时间线
2011 年 2 月 3 日,IANA 分配完最后的 IPv4 地址块。2011 年 4 月 15 日,亚太地区(APNIC)耗尽。2012 年 9 月,欧洲(RIPE NCC)耗尽。2015 年 9 月,北美(ARIN)耗尽。
📏 最长的 IP 地址
IPv6 地址最长可以写成 39 个字符(8 组,每组 4 个十六进制数字,加 7 个冒号)。但通过省略规则,可以大幅缩短,如 ::1 表示 IPv6 回环地址。
🚀 IP 地址与网速无关
很多人误以为更换 IP 地址可以提升网速,但实际上 IP 地址只是网络中的"门牌号",网速取决于带宽、路由、服务器等因素,与 IP 地址本身无关。
相关 IP 信息查询服务
本工具使用以下 API 提供服务,同时推荐其他优秀的 IP 查询服务:
IP-API.com
本工具使用 ⭐本工具主要使用的 API。完全免费(非商业用途),支持批量查询,提供 JSON/XML/CSV 格式。限制:45 次/分钟。
IPapi.co
本工具使用 ⭐本工具备用 API。提供货币、语言、连接类型等额外信息。免费版每月 30,000 次请求。
IPInfo.io
数据准确、API 友好提供详细的 IP 信息、ASN 数据、地理位置、公司信息等。提供免费计划(Free Plan)。
IPGeolocation.io
功能丰富提供 IP 地理位置、时区、货币、天气等信息。免费版每月 30,000 次请求。
MaxMind GeoIP2
最准确、企业级业界标准的 IP 地理位置数据库,准确度高。提供离线数据库和在线 API。
IPStack
安全检测支持 IPv4 和 IPv6,提供安全模块(检测代理、VPN、Tor)。免费版每月 100 次请求。
IPData.co
威胁情报提供威胁情报、ASN 信息、公司数据。免费版每天 1,500 次请求。
Abstract API
简单易用简单易用的 IP 地理位置 API。免费版每月 1,000 次请求,限制 1 次/秒。
IPRegistry
注册送 10 万次提供 IP 地理位置、公司信息、威胁检测、用户代理解析。注册后赠送 100,000 次免费额度。
DB-IP
开源数据库提供免费的 IP 地理位置数据库下载,也有在线查询服务。
IPify
获取公网 IP专注于获取公网 IP 地址,简单快速,完全免费。
如何通过编程获取 IP 地址?
以下是在不同编程语言中获取访问者 IP 地址的示例代码:
Java (Spring Boot)
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@RestController
public class IpController {
@GetMapping('/ip')
public String getClientIp(HttpServletRequest request) {
String ip = request.getHeader("CF-Connecting-IP");
if (ip == null || ip.isEmpty()) {
ip = request.getHeader("X-Forwarded-For");
if (ip != null) {
ip = ip.split(",")[0];
}
}
if (ip == null || ip.isEmpty()) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.isEmpty()) {
ip = request.getRemoteAddr();
}
return ip;
}
}
PHP
function getClientIp() {
$ipKeys = [
'HTTP_CF_CONNECTING_IP',
'HTTP_X_FORWARDED_FOR',
'HTTP_X_REAL_IP',
'REMOTE_ADDR'
];
foreach ($ipKeys as $key) {
if (!empty($_SERVER[$key])) {
$ips = explode(',', $_SERVER[$key]);
return trim($ips[0]);
}
}
return $_SERVER['REMOTE_ADDR'] ?? 'Unknown';
}
$ip = getClientIp();
echo "Your IP: " . $ip;
JavaScript (Node.js)
const express = require('express');
const app = express();
app.get('/ip', (req, res) => {
const ip = req.headers['cf-connecting-ip'] ||
req.headers['x-forwarded-for']?.split(',')[0] ||
req.headers['x-real-ip'] ||
req.socket.remoteAddress;
res.json({ ip: ip });
});
app.listen(3000);
Python (Flask)
from flask import Flask, request
app = Flask(__name__)
@app.route('/ip')
def get_ip():
ip = request.headers.get('CF-Connecting-IP') or \
request.headers.get('X-Forwarded-For', '').split(',')[0] or \
request.headers.get('X-Real-IP') or \
request.remote_addr
return {'ip': ip}
if __name__ == '__main__':
app.run()
Rust
use actix_web::{web, App, HttpRequest, HttpServer, Responder};
fn get_client_ip(req: &HttpRequest) -> String {
if let Some(ip) = req.headers().get("CF-Connecting-IP") {
return ip.to_str().unwrap_or("").to_string();
}
if let Some(forwarded) = req.headers().get("X-Forwarded-For") {
if let Ok(forwarded_str) = forwarded.to_str() {
if let Some(first_ip) = forwarded_str.split(',').next() {
return first_ip.trim().to_string();
}
}
}
if let Some(ip) = req.headers().get("X-Real-IP") {
return ip.to_str().unwrap_or("").to_string();
}
req.peer_addr()
.map(|addr| addr.ip().to_string())
.unwrap_or_else(|| "Unknown".to_string())
}
async fn ip_handler(req: HttpRequest) -> impl Responder {
let ip = get_client_ip(&req);
format!("Your IP: {}", ip)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new().route("/ip", web::get().to(ip_handler))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Go
package main
import (
"net/http"
"strings"
)
func getClientIP(r *http.Request) string {
if ip := r.Header.Get("CF-Connecting-IP"); ip != "" {
return ip
}
if forwarded := r.Header.Get("X-Forwarded-For"); forwarded != "" {
ips := strings.Split(forwarded, ",")
return strings.TrimSpace(ips[0])
}
if ip := r.Header.Get("X-Real-IP"); ip != "" {
return ip
}
return r.RemoteAddr
}
func handler(w http.ResponseWriter, r *http.Request) {
ip := getClientIP(r)
w.Write([]byte("Your IP: " + ip))
}
func main() {
http.HandleFunc("/ip", handler)
http.ListenAndServe(":8080", nil)
}
注意事项:
- • 注意:如果网站使用了 CDN(如 Cloudflare)或反向代理(如 Nginx),需要从特定的 HTTP 头中获取真实 IP
- • 优先级:CF-Connecting-IP > X-Forwarded-For > X-Real-IP > RemoteAddr
- • X-Forwarded-For 可能包含多个 IP(逗号分隔),第一个是客户端真实 IP
- • 浏览器端 JavaScript 无法直接获取 IP,需要调用第三方 API