You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Python网络追踪代码仅输出KML头尾,无IP位置信息?

问题排查:Python网络追踪工具仅输出KML头尾无IP位置内容

我参照教程用Python、Wireshark和Google Maps制作可视化网络追踪工具,理解整体原理,但代码仅输出KML头和尾,没有生成IP相关的位置内容。猜测代码未正确读取pcap文件,但找不到问题所在,请求协助排查。

原代码如下:

import dpkt
import socket
import pygeoip


def plotIPs(pcap):
    kmlPts = ''
    for (ts, buf) in pcap:
        try:
            eth = dpkt.ethernet.Ethernet(buf)
            ip = eth.data
            src = socket.inet_ntoa(ip.src)
            dst = socket.inet_ntoa(ip.dst)
            KML = retKML(dst, src)
            kmlPts = kmlPts + KML
        except:
            pass
    return kmlPts

def retKML(dstip, srcip):
    dst = gi.record_by_name(dstip)
    src = gi.record_by_name('x.xxx.xxx.xxx')
    try:
        dstlongitude = dst['longitude']
        dstlatitude = dst['latitude']
        srclongitude = src['longitude']
        srclatitude = src['latitude']
        kml = (
            '<Placemark>\n'
            '<name>%s</name>\n'
            '<extrude>1</extrude>\n'
            '<tessellate>1</tessellate>\n'
            '<styleUrl>#transBluePoly</styleUrl>\n'
            '<LineString>\n'
            '<coordinates>%6f,%6f\n%6f,%6f</coordinates>\n'
            '</LineString>\n'
            '</Placemark>\n'
        )%(dstip, dstlongitude, dstlatitude, srclongitude, srclatitude)
        return kml
    except:
        return ''

def main():
    f = open('DataCapture.pcap', 'rb')
    pcap = dpkt.pcap.Reader(f)
    kmlheader = '<?xml version="1.0" encoding="UTF-8"?> \n<kml     xmlns="http://www.opengis.net/kml/2.2">\n<Document>\n'\
'<Style id="transBluePoly">' \
            '<LineStyle>' \
            '<width>1.5</width>' \
            '<color>501400E6</color>' \
            '</LineStyle>' \
            '</Style>'
    kmlfooter = '</Document>\n</kml>\n'
    kmldoc=kmlheader+plotIPs(pcap)+kmlfooter
    print(kmldoc)

if __name__ == '__main__':
    main()

核心问题及修复方案

1. 未初始化GeoIP数据库实例

代码中直接调用gi.record_by_name()但从未定义gi对象,这会直接触发异常,导致retKML返回空字符串。

  • 修复:在main函数中初始化GeoIP实例,确保你已下载GeoLiteCity数据库文件(如GeoLiteCity.dat)并放在代码可访问路径:
    gi = pygeoip.GeoIP('GeoLiteCity.dat')
    

2. 宽泛异常捕获掩盖错误

代码中用except:捕获所有异常,无法定位具体问题(比如pcap解析失败、IP无定位记录、字段不存在等)。

  • 修复:替换为捕获特定异常并打印错误信息,例如:
    在plotIPs的异常块中:
    except Exception as e:
        print(f"数据包解析失败: {e}")
        pass
    
    在retKML的异常块中:
    except Exception as e:
        print(f"KML生成失败(目标IP: {dstip}): {e}")
        return ''
    

3. 源IP硬编码且逻辑错误

retKML中硬编码源IP为'x.xxx.xxx.xxx',既未使用传入的srcip参数,也无法保证该IP能被GeoIP识别。

  • 修复:改用传入的源IP参数:
    src = gi.record_by_name(srcip)
    
    同时注意:内网IP无法被GeoIP定位,若测试用数据包多为内网流量,需筛选公网IP。

4. 未过滤非IP数据包

pcap文件中可能包含ARP等非IP数据包,直接解析eth.data会导致错误。

  • 修复:在plotIPs中增加IP类型判断:
    if not isinstance(ip, dpkt.ip.IP):
        continue
    

5. KML转义字符冗余

原代码中使用<、"等转义字符,直接写普通XML标签即可,避免解析问题。


修复后完整代码

import dpkt
import socket
import pygeoip

def plotIPs(pcap, gi):
    kmlPts = ''
    for (ts, buf) in pcap:
        try:
            eth = dpkt.ethernet.Ethernet(buf)
            ip = eth.data
            # 过滤非IP数据包
            if not isinstance(ip, dpkt.ip.IP):
                continue
            src = socket.inet_ntoa(ip.src)
            dst = socket.inet_ntoa(ip.dst)
            KML = retKML(dst, src, gi)
            kmlPts += KML
        except Exception as e:
            print(f"数据包解析失败: {e}")
            pass
    return kmlPts

def retKML(dstip, srcip, gi):
    try:
        dst = gi.record_by_name(dstip)
        src = gi.record_by_name(srcip)
        # 跳过无法定位的IP
        if not dst or not src:
            return ''
        dstlongitude = dst['longitude']
        dstlatitude = dst['latitude']
        srclongitude = src['longitude']
        srclatitude = src['latitude']
        kml = (
            '<Placemark>\n'
            '<name>%s</name>\n'
            '<extrude>1</extrude>\n'
            '<tessellate>1</tessellate>\n'
            '<styleUrl>#transBluePoly</styleUrl>\n'
            '<LineString>\n'
            '<coordinates>%6f,%6f\n%6f,%6f</coordinates>\n'
            '</LineString>\n'
            '</Placemark>\n'
        ) % (dstip, dstlongitude, dstlatitude, srclongitude, srclatitude)
        return kml
    except Exception as e:
        print(f"KML生成失败(目标IP: {dstip}): {e}")
        return ''

def main():
    # 初始化GeoIP数据库
    try:
        gi = pygeoip.GeoIP('GeoLiteCity.dat')
    except Exception as e:
        print(f"GeoIP数据库加载失败: {e}")
        return
    # 读取pcap文件
    try:
        with open('DataCapture.pcap', 'rb') as f:
            pcap = dpkt.pcap.Reader(f)
            kmlheader = '<?xml version="1.0" encoding="UTF-8"?> \n<kml xmlns="http://www.opengis.net/kml/2.2">\n<Document>\n'\
            '<Style id="transBluePoly">' \
                        '<LineStyle>' \
                        '<width>1.5</width>' \
                        '<color>501400E6</color>' \
                        '</LineStyle>' \
                        '</Style>'
            kmlfooter = '</Document>\n</kml>\n'
            kmldoc = kmlheader + plotIPs(pcap, gi) + kmlfooter
            print(kmldoc)
    except Exception as e:
        print(f"pcap文件打开失败: {e}")

if __name__ == '__main__':
    main()

内容的提问来源于stack exchange,提问作者papasamil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 12:05:21