Python使用GeoIP2实现地图定位
作者:lyshark
GeoIP2是一种IP地址定位库,它允许开发人员根据IP
地址查找有关位置和地理位置的信息。它使用MaxMind
公司的IP地址数据库,并提供一个方便的Python API。GeoIP2可以用于许多不同的应用程序,例如网站分析、广告定位和身份验证。GeoIP2提供了许多不同的信息,例如国家、城市、邮政编码、经纬度、时区等等。它还可以使用IPv6地址进行查询。
安装第三方库:pip install geoip2
GitHub地址:https://github.com/maxmind/GeoIP2-python
离线数据库:https://www.maxmind.com/en/accounts/current/geoip/downloads
读者可自行执行pip install geoip2
命令安装这个第三方库,并自行下载对应免费版本的GeoLite2-City.mmdb
主机数据库文件,当一切准备就绪以后我们就可以使用该数据库定位位置了,如下代码是一个演示案例,首先通过GetPcap
将数据包解析并存储值ret
变量内返回,当返回后通过geoip2.database
加载数据库文件,并通过循环的方式以此查询reader.city
数据,并将详细地址输出。
import dpkt import socket import geoip2.database def GetPcap(pcap): ret = [] for timestamp,packet in pcap: try: eth = dpkt.ethernet.Ethernet(packet) ip = eth.data src = socket.inet_ntoa(ip.src) dst = socket.inet_ntoa(ip.dst) ret.append(dst) except: pass return set(ret) if __name__ == '__main__': fp = open('d://lyshark.pcap','rb') pcap = dpkt.pcap.Reader(fp) addr = GetPcap(pcap) reader = geoip2.database.Reader("d://GeoLite2-City.mmdb") for item in addr: try: response = reader.city(item) print("IP地址: %-16s --> " %item,end="") print("网段: %-16s --> " %response.traits.network,end="") print("经度: %-10s 纬度: %-10s --> " %(response.location.latitude, response.location.longitude),end="") print("地区: {}".format(response.country.names["zh-CN"]),end="\n") except Exception: pass
当读者运行上述代码后,则可输出当前抓到数据包的详细信息,其中包括了网段,经纬度,地区等敏感数据,如下图所示;
当获取当经纬度详细信息后,则下一步就是要生成一个Google
地图模板,一般Google
底部模板采用KML
文件格式,如下这段代码则是生成一个对应的地图模板,通过传入所需分析的pcap
数据包以及数据库信息,则可以输出一个GoogleEarth.kml
模板文件。
import dpkt import socket import geoip2.database from optparse import OptionParser def GetPcap(pcap): ret = [] for timestamp,packet in pcap: try: eth = dpkt.ethernet.Ethernet(packet) ip = eth.data src = socket.inet_ntoa(ip.src) dst = socket.inet_ntoa(ip.dst) ret.append(dst) except: pass return set(ret) def retKML(addr,longitude,latitude): kml = ( '<Placemark>\n' '<name>%s</name>\n' '<Point>\n' '<coordinates>%6f,%6f</coordinates>\n' '</Point>\n' '</Placemark>\n' ) %(addr, longitude, latitude) return kml if __name__ == '__main__': parser = OptionParser() parser.add_option("-p", "--pcap", dest="pcap_file", help="set -p *.pcap") parser.add_option("-d", "--mmdb", dest="mmdb_file", help="set -d *.mmdb") (options, args) = parser.parse_args() if options.pcap_file and options.mmdb_file: fp = open(options.pcap_file,'rb') pcap = dpkt.pcap.Reader(fp) addr = GetPcap(pcap) reader = geoip2.database.Reader(options.mmdb_file) kmlheader = '<?xml version="1.0" encoding="UTF-8"?>\ \n<kml xmlns="http://www.opengis.net/kml/2.2">\n<Document>\n' with open("GoogleEarth.kml", "w") as f: f.write(kmlheader) f.close() for item in addr: try: response = reader.city(item) print("IP地址: %-16s --> " %item,end="") print("网段: %-16s --> " %response.traits.network,end="") print("经度: %-10s 纬度: %-10s --> " %(response.location.latitude, response.location.longitude),end="") print("地区: {}".format(response.country.names["zh-CN"]),end="\n") with open("GoogleEarth.kml","a+") as f: f.write(retKML(item,response.location.latitude, response.location.longitude)) f.close() except Exception: pass kmlfooter = '</Document>\n</kml>\n' with open("GoogleEarth.kml", "a+") as f: f.write(kmlfooter) f.close() else: parser.print_help()
此时打开谷歌地图,并选择左侧的项目
菜单,选择从计算机中导入KML文件,并自行将googleearth.kml
文件导入到地图文件内,如下图所示;
当导入成功后,此时在地图左侧将会出现一些坐标信息,此时读者可自行点击这些坐标以确定当前IP地址的详细位置,当然该地址仅供参考,因为某些主机的地址可能会使用隐藏IP的方式并不一定确保一定准确。
当然了上述代码只是一个演示案例,在实际过滤中我们可以会进行多层解析,例如如下这段代码,其中AnalysisIP_To_Address
函数就可用于接收一个过滤规则,代码中dport ==80 or dport == 443
则用于只过滤出目标端口是80
或443
的主机信息,读者也可自行增加一条符合规则的过滤条件进行自定义捕捉,此处仅仅只是一个演示案例。
import argparse import socket,dpkt import geoip2.database def AnalysisPace(DpktPack,Filter): respon = [] with open(DpktPack,"rb") as fp: pcap = dpkt.pcap.Reader(fp) for timestamp, packet in pcap: try: eth = dpkt.ethernet.Ethernet(packet) # 解析过滤出网络层(三层)中的IP数据包 if eth.data.__class__.__name__ == "IP": ip = eth.data src = socket.inet_ntoa(ip.src) dst = socket.inet_ntoa(ip.dst) # 解析过滤出传输层(四层)中的TCP数据包 if eth.data.data.__class__.__name__ == "TCP": sport = eth.data.data.sport dport = eth.data.data.dport # 过滤出源地址是192.168.1.2且目的端口是80或者443的流量 # if src == "192.168.1.2" and dport == 80 or dport == 443: if eval(Filter): dic = { "src":"None","sport":0 , "dst":"None","dport":0 } #print("[+] 时间戳: %-17s 源地址: %-14s:%-2s ---> 目标地址: %-16s:%-2s" %(timestamp,src, sport, dst, dport)) RecvData = eth.data.data.data if len(RecvData) and b"GET" in RecvData: #print("[*] 时间戳: {} 源地址: {} <--- 访问网页: {}".format(timestamp,src,bytes.decode(RecvData).split("\n")[1])) pass dic['src'] = src dic['dst'] = dst dic['sport'] = sport dic['dport'] = dport respon.append(dic) except Exception: pass return respon def AnalysisIP_To_Address(PcapFile,MmdbFile): IPDict = AnalysisPace(PcapFile,"dport ==80 or dport == 443") NoRepeat = [] for item in range(len(IPDict)): NoRepeat.append(IPDict[item].get("dst")) NoRepeat = set(NoRepeat) reader = geoip2.database.Reader(MmdbFile) for item in NoRepeat: try: response = reader.city(item) print("[+] IP地址: %-16s --> " %item,end="") print("网段: %-16s --> " %response.traits.network,end="") print("经度: %-10s 纬度: %-10s --> " %(response.location.latitude, response.location.longitude),end="") print("定位: {} {} {}".format(response.country.names["zh-CN"],response.subdivisions.most_specific.name,response.city.name),end="\n") except Exception: print("定位: None None None") pass if __name__ == '__main__': Banner() parser = argparse.ArgumentParser() parser.add_argument("-p", "--pcap", dest="pcap", help="设置抓到的数据包 *.pcap") parser.add_argument("-d", "--mmdb", dest="mmdb", help="设置城市数据库 GeoLite2-City.mmdb") args = parser.parse_args() # 使用方式: main.py -p data.pcap -d GeoLite2-City.mmdb (分析数据包中IP) if args.pcap and args.mmdb: AnalysisIP_To_Address(args.pcap,args.mmdb) else: parser.print_help()
到此这篇关于Python使用GeoIP2实现地图定位的文章就介绍到这了,更多相关python GeoIP2地图定位内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!