经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
21.4 Python 使用GeoIP2地图定位
来源:cnblogs  作者:lyshark  时间:2023/10/25 10:12:59  对本文有异议

GeoIP2是一种IP地址定位库,它允许开发人员根据IP地址查找有关位置和地理位置的信息。它使用MaxMind公司的IP地址数据库,并提供一个方便的Python API。GeoIP2可以用于许多不同的应用程序,例如网站分析、广告定位和身份验证。GeoIP2提供了许多不同的信息,例如国家、城市、邮政编码、经纬度、时区等等。它还可以使用IPv6地址进行查询。

读者可自行执行pip install geoip2命令安装这个第三方库,并自行下载对应免费版本的GeoLite2-City.mmdb主机数据库文件,当一切准备就绪以后我们就可以使用该数据库定位位置了,如下代码是一个演示案例,首先通过GetPcap将数据包解析并存储值ret变量内返回,当返回后通过geoip2.database加载数据库文件,并通过循环的方式以此查询reader.city数据,并将详细地址输出。

  1. import dpkt
  2. import socket
  3. import geoip2.database
  4. def GetPcap(pcap):
  5. ret = []
  6. for timestamp,packet in pcap:
  7. try:
  8. eth = dpkt.ethernet.Ethernet(packet)
  9. ip = eth.data
  10. src = socket.inet_ntoa(ip.src)
  11. dst = socket.inet_ntoa(ip.dst)
  12. ret.append(dst)
  13. except:
  14. pass
  15. return set(ret)
  16. if __name__ == '__main__':
  17. fp = open('d://lyshark.pcap','rb')
  18. pcap = dpkt.pcap.Reader(fp)
  19. addr = GetPcap(pcap)
  20. reader = geoip2.database.Reader("d://GeoLite2-City.mmdb")
  21. for item in addr:
  22. try:
  23. response = reader.city(item)
  24. print("IP地址: %-16s --> " %item,end="")
  25. print("网段: %-16s --> " %response.traits.network,end="")
  26. print("经度: %-10s 纬度: %-10s --> " %(response.location.latitude, response.location.longitude),end="")
  27. print("地区: {}".format(response.country.names["zh-CN"]),end="\n")
  28. except Exception:
  29. pass

当读者运行上述代码后,则可输出当前抓到数据包的详细信息,其中包括了网段,经纬度,地区等敏感数据,如下图所示;

当获取当经纬度详细信息后,则下一步就是要生成一个Google地图模板,一般Google底部模板采用KML文件格式,如下这段代码则是生成一个对应的地图模板,通过传入所需分析的pcap数据包以及数据库信息,则可以输出一个GoogleEarth.kml模板文件。

  1. import dpkt
  2. import socket
  3. import geoip2.database
  4. from optparse import OptionParser
  5. def GetPcap(pcap):
  6. ret = []
  7. for timestamp,packet in pcap:
  8. try:
  9. eth = dpkt.ethernet.Ethernet(packet)
  10. ip = eth.data
  11. src = socket.inet_ntoa(ip.src)
  12. dst = socket.inet_ntoa(ip.dst)
  13. ret.append(dst)
  14. except:
  15. pass
  16. return set(ret)
  17. def retKML(addr,longitude,latitude):
  18. kml = (
  19. '<Placemark>\n'
  20. '<name>%s</name>\n'
  21. '<Point>\n'
  22. '<coordinates>%6f,%6f</coordinates>\n'
  23. '</Point>\n'
  24. '</Placemark>\n'
  25. ) %(addr, longitude, latitude)
  26. return kml
  27. if __name__ == '__main__':
  28. parser = OptionParser()
  29. parser.add_option("-p", "--pcap", dest="pcap_file", help="set -p *.pcap")
  30. parser.add_option("-d", "--mmdb", dest="mmdb_file", help="set -d *.mmdb")
  31. (options, args) = parser.parse_args()
  32. if options.pcap_file and options.mmdb_file:
  33. fp = open(options.pcap_file,'rb')
  34. pcap = dpkt.pcap.Reader(fp)
  35. addr = GetPcap(pcap)
  36. reader = geoip2.database.Reader(options.mmdb_file)
  37. kmlheader = '<?xml version="1.0" encoding="UTF-8"?> \n<kml xmlns="http://www.opengis.net/kml/2.2">\n<Document>\n'
  38. with open("GoogleEarth.kml", "w") as f:
  39. f.write(kmlheader)
  40. f.close()
  41. for item in addr:
  42. try:
  43. response = reader.city(item)
  44. print("IP地址: %-16s --> " %item,end="")
  45. print("网段: %-16s --> " %response.traits.network,end="")
  46. print("经度: %-10s 纬度: %-10s --> " %(response.location.latitude, response.location.longitude),end="")
  47. print("地区: {}".format(response.country.names["zh-CN"]),end="\n")
  48. with open("GoogleEarth.kml","a+") as f:
  49. f.write(retKML(item,response.location.latitude, response.location.longitude))
  50. f.close()
  51. except Exception:
  52. pass
  53. kmlfooter = '</Document>\n</kml>\n'
  54. with open("GoogleEarth.kml", "a+") as f:
  55. f.write(kmlfooter)
  56. f.close()
  57. else:
  58. parser.print_help()

此时打开谷歌地图,并选择左侧的项目菜单,选择从计算机中导入KML文件,并自行将googleearth.kml文件导入到地图文件内,如下图所示;

当导入成功后,此时在地图左侧将会出现一些坐标信息,此时读者可自行点击这些坐标以确定当前IP地址的详细位置,当然该地址仅供参考,因为某些主机的地址可能会使用隐藏IP的方式并不一定确保一定准确。

当然了上述代码只是一个演示案例,在实际过滤中我们可以会进行多层解析,例如如下这段代码,其中AnalysisIP_To_Address函数就可用于接收一个过滤规则,代码中dport ==80 or dport == 443则用于只过滤出目标端口是80443的主机信息,读者也可自行增加一条符合规则的过滤条件进行自定义捕捉,此处仅仅只是一个演示案例。

  1. import argparse
  2. import socket,dpkt
  3. import geoip2.database
  4. def AnalysisPace(DpktPack,Filter):
  5. respon = []
  6. with open(DpktPack,"rb") as fp:
  7. pcap = dpkt.pcap.Reader(fp)
  8. for timestamp, packet in pcap:
  9. try:
  10. eth = dpkt.ethernet.Ethernet(packet)
  11. # 解析过滤出网络层(三层)中的IP数据包
  12. if eth.data.__class__.__name__ == "IP":
  13. ip = eth.data
  14. src = socket.inet_ntoa(ip.src)
  15. dst = socket.inet_ntoa(ip.dst)
  16. # 解析过滤出传输层(四层)中的TCP数据包
  17. if eth.data.data.__class__.__name__ == "TCP":
  18. sport = eth.data.data.sport
  19. dport = eth.data.data.dport
  20. # 过滤出源地址是192.168.1.2且目的端口是80或者443的流量
  21. # if src == "192.168.1.2" and dport == 80 or dport == 443:
  22. if eval(Filter):
  23. dic = { "src":"None","sport":0 , "dst":"None","dport":0 }
  24. #print("[+] 时间戳: %-17s 源地址: %-14s:%-2s ---> 目标地址: %-16s:%-2s" %(timestamp,src, sport, dst, dport))
  25. RecvData = eth.data.data.data
  26. if len(RecvData) and b"GET" in RecvData:
  27. #print("[*] 时间戳: {} 源地址: {} <--- 访问网页: {}".format(timestamp,src,bytes.decode(RecvData).split("\n")[1]))
  28. pass
  29. dic['src'] = src
  30. dic['dst'] = dst
  31. dic['sport'] = sport
  32. dic['dport'] = dport
  33. respon.append(dic)
  34. except Exception:
  35. pass
  36. return respon
  37. def AnalysisIP_To_Address(PcapFile,MmdbFile):
  38. IPDict = AnalysisPace(PcapFile,"dport ==80 or dport == 443")
  39. NoRepeat = []
  40. for item in range(len(IPDict)):
  41. NoRepeat.append(IPDict[item].get("dst"))
  42. NoRepeat = set(NoRepeat)
  43. reader = geoip2.database.Reader(MmdbFile)
  44. for item in NoRepeat:
  45. try:
  46. response = reader.city(item)
  47. print("[+] IP地址: %-16s --> " %item,end="")
  48. print("网段: %-16s --> " %response.traits.network,end="")
  49. print("经度: %-10s 纬度: %-10s --> " %(response.location.latitude, response.location.longitude),end="")
  50. print("定位: {} {} {}".format(response.country.names["zh-CN"],response.subdivisions.most_specific.name,response.city.name),end="\n")
  51. except Exception:
  52. print("定位: None None None")
  53. pass
  54. if __name__ == '__main__':
  55. Banner()
  56. parser = argparse.ArgumentParser()
  57. parser.add_argument("-p", "--pcap", dest="pcap", help="设置抓到的数据包 *.pcap")
  58. parser.add_argument("-d", "--mmdb", dest="mmdb", help="设置城市数据库 GeoLite2-City.mmdb")
  59. args = parser.parse_args()
  60. # 使用方式: main.py -p data.pcap -d GeoLite2-City.mmdb (分析数据包中IP)
  61. if args.pcap and args.mmdb:
  62. AnalysisIP_To_Address(args.pcap,args.mmdb)
  63. else:
  64. parser.print_help()

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/647f46e.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

原文链接:https://www.cnblogs.com/LyShark/p/17785448.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号