一、简述
通过python解析纯真IP数据库,并且能够快速匹配查询指定的IP归属地。
二、纯真数据库简述
纯真(CZ88.NET)自2005年起一直为广大社区用户提供社区版IP地址库,只要获得纯真的授权就能免费使用,并不断获取后续更新的版本。
纯真除了免费的社区版IP库外,还提供数据更加准确、服务更加周全的商业版IP地址查询数据。纯真围绕IP地址,基于 网络空间拓扑测绘 + 移动位置大数据 方案,对IP地址定位、IP网络风险、IP使用场景、IP网络类型、秒拨侦测、VPN侦测、代理侦测、爬虫侦测、真人度等均有近20年丰富的数据沉淀。
三、纯真IP数据库社区版获取方法
1)通过关注公众号,获取社区版数据库文章地址
2)下载并安装应用程序后,点击解压,获取到txt格式的IP数据库
四、通过python解析导出的txt类型数据库
1)基本思路
将IP数据库的每行读取出来,然后进去切割,切割后的数据存储到区间树中。
2)加载IP数据库到内存中
这个过程会比较久,原因是在生成节点添加到区间树的时候会有较大开销。
def load_ip_data(self, file_path):
"""
加载IP地址范围和实际地址的数据
:param file_path: 包含IP地址范围数据的文件路径
:return: 包含所有IP范围与实际地址映射的字典
"""
ip_data = {}
with open(file_path, 'r') as file:
for line in file:
parts = line.strip().split()
if len(parts) >= 3:
start_ip = int(parts[0])
end_ip = int(parts[1])
location = ' '.join(parts[2:])
#ip_data[(start_ip, end_ip)] = location
if start_ip !=end_ip:
self.tree.add(Interval(start_ip, end_ip,location))
self.rangs[start_ip]=location
else:
self.rangs[start_ip]=location
#print('ip:',start_ip,'location:',location)
return ip_data
3)给定一个IP,返回对应的实际地址
def find_ip_location(self, ip):
"""
根据输入的IP地址查找实际地址
:param ip: 输入的IP地址
:return: 输入IP地址对应的地理位置,如果未找到则返回""
"""
ip_int=int.from_bytes(socket.inet_aton(ip), byteorder='big')
matching_intervals = self.tree[ip_int]
data=''
if matching_intervals:
for match in matching_intervals:
data=match.data
else:
if ip_int in self.rangs:
data = self.rangs[ip_int]
else:
print(f"值 {ip} 不在任何区间内。")
return data
4)对IP段内仅仅只有一个IP的处理方式
以起始IP为key,用一个字典存储
if start_ip !=end_ip:
self.tree.add(Interval(start_ip, end_ip,location))
self.rangs[start_ip]=location
else:
self.rangs[start_ip]=location
5)完整代码
import socket
from intervaltree import Interval, IntervalTree
class IPGeoLocator:
def __init__(self, ip_data_file):
"""
初始化IP地址地理位置定位器
:param ip_data_file: 包含IP地址范围数据的文件路径
"""
self.tree= IntervalTree()
self.rangs={}
self.load_ip_data(ip_data_file)
def load_ip_data(self, file_path):
"""
加载IP地址范围和实际地址的数据
:param file_path: 包含IP地址范围数据的文件路径
:return: 包含所有IP范围与实际地址映射的字典
"""
ip_data = {}
with open(file_path, 'r') as file:
for line in file:
parts = line.strip().split()
if len(parts) >= 3:
start_ip = int(parts[0])
end_ip = int(parts[1])
location = ' '.join(parts[2:])
#ip_data[(start_ip, end_ip)] = location
if start_ip !=end_ip:
self.tree.add(Interval(start_ip, end_ip,location))
self.rangs[start_ip]=location
else:
self.rangs[start_ip]=location
#print('ip:',start_ip,'location:',location)
return ip_data
def find_ip_location(self, ip):
"""
根据输入的IP地址查找实际地址
:param ip: 输入的IP地址
:return: 输入IP地址对应的地理位置,如果未找到则返回""
"""
ip_int=int.from_bytes(socket.inet_aton(ip), byteorder='big')
matching_intervals = self.tree[ip_int]
data=''
if matching_intervals:
for match in matching_intervals:
data=match.data
else:
if ip_int in self.rangs:
data = self.rangs[ip_int]
else:
print(f"值 {ip} 不在任何区间内。")
return data
# 使用示例
if __name__ == "__main__":
ip_locator = IPGeoLocator("ip_ranges.txt") # 假设你的文本文件名为ip_ranges.txt
# 示例查询
query_ip = "127.0.0.1"
location = ip_locator.find_ip_location(query_ip)
print(f"IP地址 {query_ip} 对应的实际地址是:{location}")
五、总结
记录下IP归属地解析的方法,在安全运维以溯源中都是挺好用的工具。可以在解析了中间件日志,如access.log、IIS访问日志时,对IP归属地进行解析,能方便看出一些异常情况。