Python使用GeoIP2實(shí)現(xiàn)地圖定位
GeoIP2是一種IP地址定位庫,它允許開發(fā)人員根據(jù)IP
地址查找有關(guān)位置和地理位置的信息。它使用MaxMind
公司的IP地址數(shù)據(jù)庫,并提供一個(gè)方便的Python API。GeoIP2可以用于許多不同的應(yīng)用程序,例如網(wǎng)站分析、廣告定位和身份驗(yàn)證。GeoIP2提供了許多不同的信息,例如國(guó)家、城市、郵政編碼、經(jīng)緯度、時(shí)區(qū)等等。它還可以使用IPv6地址進(jìn)行查詢。
安裝第三方庫:pip install geoip2
GitHub地址:https://github.com/maxmind/GeoIP2-python
離線數(shù)據(jù)庫:https://www.maxmind.com/en/accounts/current/geoip/downloads
讀者可自行執(zhí)行pip install geoip2
命令安裝這個(gè)第三方庫,并自行下載對(duì)應(yīng)免費(fèi)版本的GeoLite2-City.mmdb
主機(jī)數(shù)據(jù)庫文件,當(dāng)一切準(zhǔn)備就緒以后我們就可以使用該數(shù)據(jù)庫定位位置了,如下代碼是一個(gè)演示案例,首先通過GetPcap
將數(shù)據(jù)包解析并存儲(chǔ)值ret
變量?jī)?nèi)返回,當(dāng)返回后通過geoip2.database
加載數(shù)據(jù)庫文件,并通過循環(huán)的方式以此查詢reader.city
數(shù)據(jù),并將詳細(xì)地址輸出。
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("網(wǎng)段: %-16s --> " %response.traits.network,end="") print("經(jīng)度: %-10s 緯度: %-10s --> " %(response.location.latitude, response.location.longitude),end="") print("地區(qū): {}".format(response.country.names["zh-CN"]),end="\n") except Exception: pass
當(dāng)讀者運(yùn)行上述代碼后,則可輸出當(dāng)前抓到數(shù)據(jù)包的詳細(xì)信息,其中包括了網(wǎng)段,經(jīng)緯度,地區(qū)等敏感數(shù)據(jù),如下圖所示;
當(dāng)獲取當(dāng)經(jīng)緯度詳細(xì)信息后,則下一步就是要生成一個(gè)Google
地圖模板,一般Google
底部模板采用KML
文件格式,如下這段代碼則是生成一個(gè)對(duì)應(yīng)的地圖模板,通過傳入所需分析的pcap
數(shù)據(jù)包以及數(shù)據(jù)庫信息,則可以輸出一個(gè)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("網(wǎng)段: %-16s --> " %response.traits.network,end="") print("經(jīng)度: %-10s 緯度: %-10s --> " %(response.location.latitude, response.location.longitude),end="") print("地區(qū): {}".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()
此時(shí)打開谷歌地圖,并選擇左側(cè)的項(xiàng)目
菜單,選擇從計(jì)算機(jī)中導(dǎo)入KML文件,并自行將googleearth.kml
文件導(dǎo)入到地圖文件內(nèi),如下圖所示;
當(dāng)導(dǎo)入成功后,此時(shí)在地圖左側(cè)將會(huì)出現(xiàn)一些坐標(biāo)信息,此時(shí)讀者可自行點(diǎn)擊這些坐標(biāo)以確定當(dāng)前IP地址的詳細(xì)位置,當(dāng)然該地址僅供參考,因?yàn)槟承┲鳈C(jī)的地址可能會(huì)使用隱藏IP的方式并不一定確保一定準(zhǔn)確。
當(dāng)然了上述代碼只是一個(gè)演示案例,在實(shí)際過濾中我們可以會(huì)進(jìn)行多層解析,例如如下這段代碼,其中AnalysisIP_To_Address
函數(shù)就可用于接收一個(gè)過濾規(guī)則,代碼中dport ==80 or dport == 443
則用于只過濾出目標(biāo)端口是80
或443
的主機(jī)信息,讀者也可自行增加一條符合規(guī)則的過濾條件進(jìn)行自定義捕捉,此處僅僅只是一個(gè)演示案例。
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) # 解析過濾出網(wǎng)絡(luò)層(三層)中的IP數(shù)據(jù)包 if eth.data.__class__.__name__ == "IP": ip = eth.data src = socket.inet_ntoa(ip.src) dst = socket.inet_ntoa(ip.dst) # 解析過濾出傳輸層(四層)中的TCP數(shù)據(jù)包 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("[+] 時(shí)間戳: %-17s 源地址: %-14s:%-2s ---> 目標(biāo)地址: %-16s:%-2s" %(timestamp,src, sport, dst, dport)) RecvData = eth.data.data.data if len(RecvData) and b"GET" in RecvData: #print("[*] 時(shí)間戳: {} 源地址: {} <--- 訪問網(wǎng)頁: {}".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("網(wǎng)段: %-16s --> " %response.traits.network,end="") print("經(jīng)度: %-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="設(shè)置抓到的數(shù)據(jù)包 *.pcap") parser.add_argument("-d", "--mmdb", dest="mmdb", help="設(shè)置城市數(shù)據(jù)庫 GeoLite2-City.mmdb") args = parser.parse_args() # 使用方式: main.py -p data.pcap -d GeoLite2-City.mmdb (分析數(shù)據(jù)包中IP) if args.pcap and args.mmdb: AnalysisIP_To_Address(args.pcap,args.mmdb) else: parser.print_help()
到此這篇關(guān)于Python使用GeoIP2實(shí)現(xiàn)地圖定位的文章就介紹到這了,更多相關(guān)python GeoIP2地圖定位內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用python監(jiān)控服務(wù)器的cpu,磁盤空間,內(nèi)存,超過郵件報(bào)警
這篇文章主要介紹了如果用python監(jiān)控服務(wù)器的cpu,磁盤空間,內(nèi)存,超過郵件報(bào)警,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2021-01-01分析Python字符串拼接+=和join()哪個(gè)速度更快
這篇文章主要分析了Python中字符串拼接+=和join()哪個(gè)速度更快,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02Python技法之如何用re模塊實(shí)現(xiàn)簡(jiǎn)易tokenizer
當(dāng)我們?cè)赑ython中開始新的東西時(shí),我通常首先看一些模塊或庫來使用,下面這篇文章主要給大家介紹了關(guān)于Python技法之如何用re模塊實(shí)現(xiàn)簡(jiǎn)易tokenizer的相關(guān)資料,需要的朋友可以參考下2022-05-05Python遞歸函數(shù) 二分查找算法實(shí)現(xiàn)解析
這篇文章主要介紹了Python遞歸函數(shù) 二分查找算法實(shí)現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08TensorFlow命名空間和TensorBoard圖節(jié)點(diǎn)實(shí)例
今天小編就為大家分享一篇TensorFlow命名空間和TensorBoard圖節(jié)點(diǎn)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-01-01Python使用SQLAlchemy進(jìn)行復(fù)雜查詢的操作代碼
SQLAlchemy 是 Python 生態(tài)系統(tǒng)中非常流行的數(shù)據(jù)庫處理庫,它提供了一種高效、簡(jiǎn)潔的方式與數(shù)據(jù)庫進(jìn)行交互,在數(shù)據(jù)驅(qū)動(dòng)的應(yīng)用程序中,復(fù)雜查詢是必不可少的,本文將通過一些常見的示例介紹如何使用 SQLAlchemy 編寫復(fù)雜查詢,需要的朋友可以參考下2024-10-10python實(shí)現(xiàn)DNS正向查詢、反向查詢的例子
這篇文章主要介紹了python實(shí)現(xiàn)DNS正向查詢、反向查詢的例子,需要的朋友可以參考下2014-04-04