如何将 dpkt 与 802.1Q 和 SLL 一起使用?
How to use dpkt with 802.1Q and SLL?
我正在 python 开发 PCAP 并使用 dpkt 读取它。 PCAP文件中的数据是Linux Cooked Capture, SLL for friends。这是在 Wireshark 中看到的 示例数据包 :
Frame 3: 578 bytes on wire (4624 bits), 578 bytes captured (4624 bits)
Linux cooked capture
Packet type: Unicast to another host (3)
Link-layer address type: 1
Link-layer address length: 6
Source: VMware_ZZ:ZZ:ZZ (ZZ:ZZ:ZZ:ZZ:ZZ:ZZ)
Unused: 0000
Protocol: IPv4 (0x0800)
Internet Protocol Version 4, Src: XX.X.XX.XX, Dst: YYY.YY.YYY.YYY
Transmission Control Protocol, Src Port: 65382, Dst Port: 443, Seq: 1, Ack: 1, Len: 522
Transport Layer Security
这是我用来获取 TCP 数据的代码:
import dpkt
pcap_path = 'example-packet.pcap'
with open(pcap_path, 'rb') as fp:
try:
capture = dpkt.pcap.Reader(fp)
except ValueError as e:
raise Exception("Wrong file: %s" % e)
for timestamp, buf in capture:
eth = dpkt.sll.SLL(buf)
print("Ethernet: ", eth)
ip = eth.data
print("IP: ", ip)
tcp = ip.data # <-- This is line 15, for error reference
print("TCP: ", tcp)
这是代码 output,其中 是 byte-coded,但是这样很好 ,因为剩下的该程序不在乎,我不需要它 human-readable:
Ethernet: b'\x00\x03\x00\x01\x00\x06\x00PV\x9auT\x00\x00\x08\x00E\x00\x05\x8cT3@\x00...
IP: b'E\x00\x05\x8cT3@\x00\x80\x06O\x1f\xac\x1f\xaed\xc6\x8f1\x06\x01\xbb%\x7f\xccz...
TCP: b'\x01\xbb%\x7f\xccz\xdf\x9d\xe5\xbe\xb98\x80\x10\x01\xfd\x047\x00\x00\x01\x01...
现在,问题。我转移到另一个 PCAP,仍然是 Linux Cooked Capture,但是这个有 IP over 802.1Q VLAN。所以这里我们有 问题数据包:
Frame 11: 577 bytes on wire (4616 bits), 577 bytes captured (4616 bits)
Linux cooked capture
Packet type: Unicast to another host (3)
Link-layer address type: 1
Link-layer address length: 6
Source: Cisco_ZZ:ZZ:ZZ (ZZ:ZZ:ZZ:ZZ:ZZ:ZZ)
Unused: 0000
Protocol: 802.1Q Virtual LAN (0x8100)
802.1Q Virtual LAN, PRI: 0, DEI: 0, ID: 1328
000. .... .... .... = Priority: Best Effort (default) (0)
...0 .... .... .... = DEI: Ineligible
.... 0101 0011 0000 = ID: 1328
Type: IPv4 (0x0800)
Internet Protocol Version 4, Src: XXX.XX.XXX.XX, Dst: YY.YYY.YYY.YY
Transmission Control Protocol, Src Port: 54545, Dst Port: 443, Seq: 1, Ack: 1, Len: 517
Transport Layer Security
但是如果我 运行 相同的代码 ,这是 输出 我得到:
Traceback (most recent call last):
File "myproject.py", line 15, in <module>
tcp = ip.data
AttributeError: 'bytes' object has no attribute 'data'
Ethernet: b'\x00\x03\x00\x01\x00\x06\x00PV\xa7(\x93\x00\x00\x81\x00\x050\x08\x00E\x00\x00...
IP: b'\x050\x08\x00E\x00\x00\xb2\xba\xd6@\x004\x06y\xf7_\xf9H \xac\x15\xbdI...
现在,我想问题在于添加到数据包的 4 字节 802.1Q:eth.data 被读取为字节,因为没有 IP Header 被识别,所以当我去做ip.data 如前所述,没有属性 'data'。但我不知道如何规避这个问题。这是另一个捕获吗,我知道 dpkt 有一个 dpkt.ethernet.VLANTag8021Q class,但就我所尝试的而言,这不适用于 Linux Cooked Capture。
我可以考虑转移到 dpkt 以外的库,但我真的不想这样做,因为这是一个工作项目的一部分,截止日期非常严格。
那么,当 TCP 数据通过 IP、802.1Q、"over" 使用 dpkt 的 SLL 时,我该如何访问它们?
我几乎感到惭愧,我以前没有想到这一点。
由于 vlan 标记 eth.data 被视为字节,因此它是 sliceable.Therefore:
for timestamp, buf in capture:
eth = dpkt.sll.SLL(buf)
print("Ethernet: ", eth)
ip = eth.data
print("IP: ", ip)
tcp = ip.data
print("TCP: ", tcp)
变成了这个:
for timestamp, buf in capture:
eth = dpkt.sll.SLL(buf)
print("Ethernet: ", eth)
if not isinstance(eth.data, dpkt.ip.IP):
vlan_tag = dpkt.ethernet.VLANtag8021Q(eth.data[:4])
ip = dpkt.ip.IP(eth.data[4:])
else:
ip = eth.data
print("IP: ", ip)
tcp = ip.data
print("TCP: ", tcp)
仅此而已。
请注意进一步参考这对我有用,因为我已经知道我的整个捕获仅由 IP 数据包组成。如果您的捕获中有其他协议,这将有不同的行为,您将必须修改 if-else 语句,以便检查这 4 个字节以查找 IP Header 或 VLAN 标记。我实际上可以那样做,因为它更正确,但这超出了这个问题的范围。
我正在 python 开发 PCAP 并使用 dpkt 读取它。 PCAP文件中的数据是Linux Cooked Capture, SLL for friends。这是在 Wireshark 中看到的 示例数据包 :
Frame 3: 578 bytes on wire (4624 bits), 578 bytes captured (4624 bits)
Linux cooked capture
Packet type: Unicast to another host (3)
Link-layer address type: 1
Link-layer address length: 6
Source: VMware_ZZ:ZZ:ZZ (ZZ:ZZ:ZZ:ZZ:ZZ:ZZ)
Unused: 0000
Protocol: IPv4 (0x0800)
Internet Protocol Version 4, Src: XX.X.XX.XX, Dst: YYY.YY.YYY.YYY
Transmission Control Protocol, Src Port: 65382, Dst Port: 443, Seq: 1, Ack: 1, Len: 522
Transport Layer Security
这是我用来获取 TCP 数据的代码:
import dpkt
pcap_path = 'example-packet.pcap'
with open(pcap_path, 'rb') as fp:
try:
capture = dpkt.pcap.Reader(fp)
except ValueError as e:
raise Exception("Wrong file: %s" % e)
for timestamp, buf in capture:
eth = dpkt.sll.SLL(buf)
print("Ethernet: ", eth)
ip = eth.data
print("IP: ", ip)
tcp = ip.data # <-- This is line 15, for error reference
print("TCP: ", tcp)
这是代码 output,其中 是 byte-coded,但是这样很好 ,因为剩下的该程序不在乎,我不需要它 human-readable:
Ethernet: b'\x00\x03\x00\x01\x00\x06\x00PV\x9auT\x00\x00\x08\x00E\x00\x05\x8cT3@\x00...
IP: b'E\x00\x05\x8cT3@\x00\x80\x06O\x1f\xac\x1f\xaed\xc6\x8f1\x06\x01\xbb%\x7f\xccz...
TCP: b'\x01\xbb%\x7f\xccz\xdf\x9d\xe5\xbe\xb98\x80\x10\x01\xfd\x047\x00\x00\x01\x01...
现在,问题。我转移到另一个 PCAP,仍然是 Linux Cooked Capture,但是这个有 IP over 802.1Q VLAN。所以这里我们有 问题数据包:
Frame 11: 577 bytes on wire (4616 bits), 577 bytes captured (4616 bits)
Linux cooked capture
Packet type: Unicast to another host (3)
Link-layer address type: 1
Link-layer address length: 6
Source: Cisco_ZZ:ZZ:ZZ (ZZ:ZZ:ZZ:ZZ:ZZ:ZZ)
Unused: 0000
Protocol: 802.1Q Virtual LAN (0x8100)
802.1Q Virtual LAN, PRI: 0, DEI: 0, ID: 1328
000. .... .... .... = Priority: Best Effort (default) (0)
...0 .... .... .... = DEI: Ineligible
.... 0101 0011 0000 = ID: 1328
Type: IPv4 (0x0800)
Internet Protocol Version 4, Src: XXX.XX.XXX.XX, Dst: YY.YYY.YYY.YY
Transmission Control Protocol, Src Port: 54545, Dst Port: 443, Seq: 1, Ack: 1, Len: 517
Transport Layer Security
但是如果我 运行 相同的代码 ,这是 输出 我得到:
Traceback (most recent call last):
File "myproject.py", line 15, in <module>
tcp = ip.data
AttributeError: 'bytes' object has no attribute 'data'
Ethernet: b'\x00\x03\x00\x01\x00\x06\x00PV\xa7(\x93\x00\x00\x81\x00\x050\x08\x00E\x00\x00...
IP: b'\x050\x08\x00E\x00\x00\xb2\xba\xd6@\x004\x06y\xf7_\xf9H \xac\x15\xbdI...
现在,我想问题在于添加到数据包的 4 字节 802.1Q:eth.data 被读取为字节,因为没有 IP Header 被识别,所以当我去做ip.data 如前所述,没有属性 'data'。但我不知道如何规避这个问题。这是另一个捕获吗,我知道 dpkt 有一个 dpkt.ethernet.VLANTag8021Q class,但就我所尝试的而言,这不适用于 Linux Cooked Capture。 我可以考虑转移到 dpkt 以外的库,但我真的不想这样做,因为这是一个工作项目的一部分,截止日期非常严格。
那么,当 TCP 数据通过 IP、802.1Q、"over" 使用 dpkt 的 SLL 时,我该如何访问它们?
我几乎感到惭愧,我以前没有想到这一点。 由于 vlan 标记 eth.data 被视为字节,因此它是 sliceable.Therefore:
for timestamp, buf in capture:
eth = dpkt.sll.SLL(buf)
print("Ethernet: ", eth)
ip = eth.data
print("IP: ", ip)
tcp = ip.data
print("TCP: ", tcp)
变成了这个:
for timestamp, buf in capture:
eth = dpkt.sll.SLL(buf)
print("Ethernet: ", eth)
if not isinstance(eth.data, dpkt.ip.IP):
vlan_tag = dpkt.ethernet.VLANtag8021Q(eth.data[:4])
ip = dpkt.ip.IP(eth.data[4:])
else:
ip = eth.data
print("IP: ", ip)
tcp = ip.data
print("TCP: ", tcp)
仅此而已。
请注意进一步参考这对我有用,因为我已经知道我的整个捕获仅由 IP 数据包组成。如果您的捕获中有其他协议,这将有不同的行为,您将必须修改 if-else 语句,以便检查这 4 个字节以查找 IP Header 或 VLAN 标记。我实际上可以那样做,因为它更正确,但这超出了这个问题的范围。