首页 文章

tshark导出FIX消息

提问于
浏览
3

目标

我正在努力实现以下目标:

  • 捕获包含FIX protocol中对话的网络流量

  • 将来自网络流量的各个FIX消息提取为"nice"格式,例如, CSV

  • 对导出的"nice"格式数据进行一些数据分析

我通过以下方式实现了:

  • 使用pcap捕获网络流量

  • 使用tshark将相关数据打印为CSV

  • 使用Python(pandas)来分析数据

问题

问题是一些捕获的TCP数据包包含多个FIX消息,这意味着当我使用tshark导出到CSV时,我没有得到每行的FIX消息 . 这使得消费CSV变得困难 .

这是我用来提取相关FIX字段的tshark命令行,因为CSV是:

tshark -r dump.pcap \
-R \'(fix.MsgType[0]=="G" or fix.MsgType[0]=="D" or fix.MsgType[0]=="8" or \ fix.MsgType[0]=="F") and fix.ClOrdID != "0"\' \ 
-Tfields -Eseparator=, -Eoccurrence=l -e frame.time_relative \
-e fix.MsgType -e fix.SenderCompID \
-e fix.SenderSubID -e fix.Symbol -e fix.Side \
-e fix.Price -e fix.OrderQty -e fix.ClOrdID \
-e fix.OrderID -e fix.OrdStatus'

请注意,我正在使用“-Eoccurrence = l”来获取在数据包中出现多个字段的情况下最后一次出现的命名字段 . 这不是一个可接受的解决方案,因为当数据包中有多个FIX消息时,信息将被丢弃 .

这是我期望在导出的CSV文件中的每一行(来自一个FIX消息的字段)中看到的内容:

16.508949000,D,XXX,XXX,YTZ2,2,97480,34,646427,,

这是我在TCP数据包中有多个FIX消息(本例中为三个)并且使用命令行标志“-Eoccurrence = a”时看到的内容:

16.515886000,F,F,G,XXX,XXX,XXX,XXX,XXX,XXX,XTZ2,2,97015,22,646429,646430,646431,323180,323175,301151,

问题

有没有办法(不一定使用tshark)从pcap文件中提取每个特定于协议的消息?

1 回答

  • 3

    Better Solution

    使用 tcpflow 可以在不离开命令行的情况下正确完成此操作 .

    我目前的方法是使用类似的东西:

    tshark -nr <input_file> -Y'fix' -w- | tcpdump -r- -l -w- | tcpflow -r- -C -B
    

    tcpflow 确保遵循TCP流,因此不会丢失FIX消息(在单个TCP数据包包含多于1个FIX消息的情况下) . -C 写入控制台, -B 确保二进制输出 . 这种方法与Wireshark中的TCP流不同 .

    保留了FIX分隔符,这意味着我可以对输出进行一些方便的操作,例如

    ... | tcpflow -r- -C -B | grep -P "\x0135=8\x01"
    

    提取所有执行报告 . 注意grep的 -P 参数允许非常强大的perl正则表达式 .

    A (Previous) Solution

    我正在使用 Scapy (另见Scapy DocumentationThe Very Unofficial Dummies Guide to Scapy)读取pcap文件并从数据包中提取每个单独的FIX消息 .

    以下是我正在使用的代码的基础:

    from scapy.all import *
    
    def ExtractFIX(pcap):
        """A generator that iterates over the packets in a scapy pcap iterable
    and extracts the FIX messages.
    In the case where there are multiple FIX messages in one packet, yield each
    FIX message individually."""
        for packet in pcap:
            if packet.haslayer('Raw'):
                # Only consider TCP packets which contain raw data.
                load = packet.getlayer('Raw').load
    
                # Ignore raw data that doesn't contain FIX.
                if not 'FIX' in load:
                    continue
    
                # Replace \x01 with '|'.
                load = re.sub(r'\x01', '|', load)
    
                # Split out each individual FIX message in the packet by putting a 
                # ';' between them and then using split(';').
                for subMessage in re.sub(r'\|8=FIX', '|;8=FIX', load).split(';'):
                    # Yield each sub message. More often than not, there will only be one.
                    assert subMessage[-1:] == '|'
                    yield subMessage
            else:
                continue
    
    pcap = rdpcap('dump.pcap')
    for fixMessage in ExtractFIX(pcap):
        print fixMessage
    

    我仍然希望能够从网络数据包的“帧”层获取其他信息,特别是相对(或参考)时间 . 不幸的是,Scapy数据包对象似乎没有 - 它的最顶层是Ether层,如下所示 .

    In [229]: pcap[0]
    Out[229]: <Ether  dst=00:0f:53:08:14:81 src=24:b6:fd:cd:d5:f7 type=0x800 |<IP  version=4L ihl=5L tos=0x0 len=215 id=16214 flags=DF frag=0L ttl=128 proto=tcp chksum=0xa53d src=10.129.0.25 dst=10.129.0.115 options=[] |<TCP  sport=2634 dport=54611 seq=3296969378 ack=2383325407 dataofs=8L reserved=0L flags=PA window=65319 chksum=0x4b73 urgptr=0 options=[('NOP', None), ('NOP', None), ('Timestamp', (581177, 2013197542))] |<Raw  load='8=FIX.4.0\x019=0139\x0135=U\x0149=XXX\x0134=110169\x015006=20\x0150=XXX\x0143=N\x0152=20121210-00:12:13\x01122=20121210-00:12:13\x015001=6\x01100=SFE\x0155=AP\x015009=F3\x015022=45810\x015023=3\x015057=2\x0110=232\x01' |>>>>
    In [245]: pcap[0].summary()
    Out[245]: 'Ether / IP / TCP 10.129.0.25:2634 > 10.129.0.115:54611 PA / Raw'
    

相关问题