如何使用Scapy解析802.1q三重标记帧?

问题描述:

背景:如何使用Scapy解析802.1q三重标记帧?

我与scapy工作解析IEEE 802.1Q triple tagged frames。我使用scapy生成测试帧并将它们捕获到pcap文件。 解析是通过阅读pcap文件在单独的脚本中完成的。我可以成功使用第一个802.1q标记。

问题:

这不是我清楚如何在第二和第三802.1Q标签访问。我试图使用haslayer()getlayer来有条件地检查帧头。 haslayer(Dot1Q)返回与第一个Dot1Q标签关联的 值。

问:

如果第一个标签的type0x8100,那么第二个标签存在。有没有办法提前到第二个和第三个标签?我查看了l2.py源代码并进行了实验,但还没有运气。

代码:

发送三重标签帧:

sendp(Ether(dst='78:2B:CB:33:4B:9F',src="D4:AE:52:89:BA:FA")/Dot1Q(vlan=1,id=3,prio=2)/Dot1Q(vlan=2,id=3,prio=2)/Dot1Q(vlan=3,id=3,prio=2)/IP(dst='10.25.222.222')/ICMP()) 

帧显示:

###[ Ethernet ]### 
    dst  = 78:2b:cb:33:4b:9f 
    src  = d4:ae:52:89:ba:fa 
    type  = 0x8100 
###[ 802.1Q ]### 
    prio  = 2L 
    id  = 1L 
    vlan  = 1L 
    type  = 0x8100 
###[ 802.1Q ]### 
     prio  = 2L 
     id  = 1L 
     vlan  = 2L 
     type  = 0x8100 
###[ 802.1Q ]### 
      prio  = 2L 
      id  = 1L 
      vlan  = 3L 
      type  = 0x800 
###[ IP ]### 
       version = 4L 
       ihl  = 5L 
       tos  = 0x0 
       len  = 28 
       id  = 1 
       flags  = 
       frag  = 0L 
       ttl  = 64 
       proto  = icmp 
       chksum = 0xc55 
       src  = 10.25.123.123 
       dst  = 10.25.222.222 
       \options \ 
###[ ICMP ]### 
       type  = echo-request 
       code  = 0 
       chksum = 0xf7ff 
       id  = 0x0 
       seq  = 0x0 
###[ Padding ]### 
        load  = '\x00\x00\x00\x00\x00\x00' 

帧解析:

pkts=rdpcap(self.file_name) 

for pkt in pkts: 

    try: 
     if pkt.haslayer(Ether): 
      src  = pkt.getlayer(Ether).src 
      dst  = pkt.getlayer(Ether).dst 
      type = pkt.getlayer(Ether).type 
      # Do something 

     if pkt.haslayer(Dot1Q): 
      prio = pkt.getlayer(Dot1Q).prio 
      id  = pkt.getlayer(Dot1Q).id 
      vlan = pkt.getlayer(Dot1Q).vlan 
      type = pkt.getlayer(Dot1Q).type 
      # Do something 

    except: 
     raise `    

您可以通过pkt[Dot1Q:2]pkt[Dot1Q:3]等访问内部802.1Q标签pkt。如果数据包没有指定图层,适当IndexError引发异常:

In [3]: pkt 
Out[3]: <Ether dst=78:2B:CB:33:4B:9F src=D4:AE:52:89:BA:FA type=0x8100 |<Dot1Q prio=2 id=3 vlan=1 type=0x8100 |<Dot1Q prio=2 id=3 vlan=2 type=0x8100 |<Dot1Q prio=2 id=3 vlan=3 type=0x800 |<IP frag=0 proto=icmp dst=10.25.222.222 |<ICMP |>>>>>> 

In [4]: pkt[Dot1Q:1] 
Out[4]: <Dot1Q prio=2 id=3 vlan=1 type=0x8100 |<Dot1Q prio=2 id=3 vlan=2 type=0x8100 |<Dot1Q prio=2 id=3 vlan=3 type=0x800 |<IP frag=0 proto=icmp dst=10.25.222.222 |<ICMP |>>>>> 

In [5]: pkt[Dot1Q:2] 
Out[5]: <Dot1Q prio=2 id=3 vlan=2 type=0x8100 |<Dot1Q prio=2 id=3 vlan=3 type=0x800 |<IP frag=0 proto=icmp dst=10.25.222.222 |<ICMP |>>>> 

In [6]: pkt[Dot1Q:3] 
Out[6]: <Dot1Q prio=2 id=3 vlan=3 type=0x800 |<IP frag=0 proto=icmp dst=10.25.222.222 |<ICMP |>>> 

In [7]: pkt[Dot1Q:4] 
--------------------------------------------------------------------------- 
IndexError        Traceback (most recent call last) 
<ipython-input-7-a155defcb885> in <module>() 
----> 1 pkt[Dot1Q:4] 

/usr/local/lib/python2.7/dist-packages/scapy_real-2.2.0_dev-py2.7.egg/scapy/packet.pyc in __getitem__(self, cls) 
    770    elif type(lname) is not str: 
    771     lname = repr(lname) 
--> 772    raise IndexError("Layer [%s] not found" % lname) 
    773   return ret 
    774 

IndexError: Layer [Dot1Q] not found 

当然,你可以检查类型值,只验证它是0x8100后,尝试访问内层。

+0

非常好。谢谢Yoel! – 2015-01-27 13:58:09