Python使用GeoIP2實(shí)現(xiàn)地圖定位
GeoIP2是一種IP地址定位庫(kù),它允許開(kāi)發(fā)人員根據(jù)IP地址查找有關(guān)位置和地理位置的信息。它使用MaxMind公司的IP地址數(shù)據(jù)庫(kù),并提供一個(gè)方便的Python API。GeoIP2可以用于許多不同的應(yīng)用程序,例如網(wǎng)站分析、廣告定位和身份驗(yàn)證。GeoIP2提供了許多不同的信息,例如國(guó)家、城市、郵政編碼、經(jīng)緯度、時(shí)區(qū)等等。它還可以使用IPv6地址進(jìn)行查詢(xún)。
安裝第三方庫(kù):pip install geoip2
GitHub地址:https://github.com/maxmind/GeoIP2-python
離線(xiàn)數(shù)據(jù)庫(kù):https://www.maxmind.com/en/accounts/current/geoip/downloads
讀者可自行執(zhí)行pip install geoip2命令安裝這個(gè)第三方庫(kù),并自行下載對(duì)應(yīng)免費(fèi)版本的GeoLite2-City.mmdb主機(jī)數(shù)據(jù)庫(kù)文件,當(dāng)一切準(zhǔn)備就緒以后我們就可以使用該數(shù)據(jù)庫(kù)定位位置了,如下代碼是一個(gè)演示案例,首先通過(guò)GetPcap將數(shù)據(jù)包解析并存儲(chǔ)值ret變量?jī)?nèi)返回,當(dāng)返回后通過(guò)geoip2.database加載數(shù)據(jù)庫(kù)文件,并通過(guò)循環(huán)的方式以此查詢(xú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)的地圖模板,通過(guò)傳入所需分析的pcap數(shù)據(jù)包以及數(shù)據(jù)庫(kù)信息,則可以輸出一個(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í)打開(kāi)谷歌地圖,并選擇左側(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í)際過(guò)濾中我們可以會(huì)進(jìn)行多層解析,例如如下這段代碼,其中AnalysisIP_To_Address函數(shù)就可用于接收一個(gè)過(guò)濾規(guī)則,代碼中dport ==80 or dport == 443則用于只過(guò)濾出目標(biāo)端口是80或443的主機(jī)信息,讀者也可自行增加一條符合規(guī)則的過(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)
# 解析過(guò)濾出網(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)
# 解析過(guò)濾出傳輸層(四層)中的TCP數(shù)據(jù)包
if eth.data.data.__class__.__name__ == "TCP":
sport = eth.data.data.sport
dport = eth.data.data.dport
# 過(guò)濾出源地址是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í)間戳: {} 源地址: {} <--- 訪(fǎng)問(wèn)網(wǎng)頁(yè): {}".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ù)庫(kù) 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,磁盤(pán)空間,內(nèi)存,超過(guò)郵件報(bào)警
這篇文章主要介紹了如果用python監(jiān)控服務(wù)器的cpu,磁盤(pán)空間,內(nèi)存,超過(guò)郵件報(bào)警,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2021-01-01
分析Python字符串拼接+=和join()哪個(gè)速度更快
這篇文章主要分析了Python中字符串拼接+=和join()哪個(gè)速度更快,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02
Python技法之如何用re模塊實(shí)現(xiàn)簡(jiǎn)易tokenizer
當(dāng)我們?cè)赑ython中開(kāi)始新的東西時(shí),我通常首先看一些模塊或庫(kù)來(lái)使用,下面這篇文章主要給大家介紹了關(guān)于Python技法之如何用re模塊實(shí)現(xiàn)簡(jiǎn)易tokenizer的相關(guān)資料,需要的朋友可以參考下2022-05-05
Python遞歸函數(shù) 二分查找算法實(shí)現(xiàn)解析
這篇文章主要介紹了Python遞歸函數(shù) 二分查找算法實(shí)現(xiàn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
TensorFlow命名空間和TensorBoard圖節(jié)點(diǎn)實(shí)例
今天小編就為大家分享一篇TensorFlow命名空間和TensorBoard圖節(jié)點(diǎn)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-01-01
Python使用SQLAlchemy進(jìn)行復(fù)雜查詢(xún)的操作代碼
SQLAlchemy 是 Python 生態(tài)系統(tǒng)中非常流行的數(shù)據(jù)庫(kù)處理庫(kù),它提供了一種高效、簡(jiǎn)潔的方式與數(shù)據(jù)庫(kù)進(jìn)行交互,在數(shù)據(jù)驅(qū)動(dòng)的應(yīng)用程序中,復(fù)雜查詢(xún)是必不可少的,本文將通過(guò)一些常見(jiàn)的示例介紹如何使用 SQLAlchemy 編寫(xiě)復(fù)雜查詢(xún),需要的朋友可以參考下2024-10-10
python實(shí)現(xiàn)DNS正向查詢(xún)、反向查詢(xún)的例子
這篇文章主要介紹了python實(shí)現(xiàn)DNS正向查詢(xún)、反向查詢(xún)的例子,需要的朋友可以參考下2014-04-04
python opencv 畫(huà)外接矩形框的完整代碼
這篇文章主要介紹了python-opencv-畫(huà)外接矩形框的實(shí)例代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09

