Scapy - 发送IPv6路由器广告失败,生命周期> 0

时间:2016-09-10 23:40:45

标签: python networking ipv6 scapy

我正在尝试使用Scapy创建一个工具,通过向FF02 :: 1多播地址发送伪路由器通告来发现链路本地IPv6主机。

*SNIP*
router_advertisement = scapy.IPv6(src=ra_src_addr, dst='FF02::1')/scapy.ICMPv6ND_RA(routerlifetime=0, reachabletime=0)/scapy.ICMPv6NDOptSrcLLAddr(lladdr=hw_addr)/scapy.ICMPv6NDOptPrefixInfo(prefixlen=64, validlifetime=0x6, preferredlifetime=0x6, prefix='dead::')
answer, unanswer = scapy.sr(router_advertisement, timeout=10, multi=True)

for reply in answer:
    print(reply[1][scapy.Ether].src + ' : ' + reply[1]scapy.IPv6].src)

剪辑上方的所有内容主要是设置路由器广告的参数(ra_prefix,hw_addr等)。我已将完整的脚本放在pastebin上以避免混淆问题:http://pastebin.com/4Q3JheXh

上面的问题是,虽然Scapy成功发送了路由器广告包,并且我看到了邻居请求响应,但在我用sr()查看答案之前,Scapy正在退出错误。

完整输出:

    WARNING: No route found for IPv6 destination :: (no default route?)                                                                                                    
    Begin emission:                                                                                                                                                        
Finished to send 1 packets.
...Traceback (most recent call last):
  File "find_ipv6_local.py", line 40, in <module>
    answer, unanswer = scapy.sr(router_advertisement, timeout=10, multi=True)
  File "/usr/lib/python2.7/site-packages/scapy/sendrecv.py", line 317, in sr
    a,b=sndrcv(s,x,*args,**kargs)
  File "/usr/lib/python2.7/site-packages/scapy/sendrecv.py", line 141, in sndrcv
    h = r.hashret()
  File "/usr/lib/python2.7/site-packages/scapy/layers/inet6.py", line 423, in hashret
    return struct.pack("B", nh)+self.payload.hashret()
  File "/usr/lib/python2.7/site-packages/scapy/packet.py", line 711, in hashret
    return self.payload.hashret()
  File "/usr/lib/python2.7/site-packages/scapy/layers/inet6.py", line 1317, in hashret
    return struct.pack("HH",self.mladdr)+self.payload.hashret()
struct.error: pack expected 2 items for packing (got 1)

有趣的是,当我将 validlifetime preferredlifetime 设置为0时,Scapy不会崩溃并烧毁。但是,这不是很有用,因为0的生命周期不会给我任何回应。

在涉及到IPv6时,我是否已经搞砸了脚本中的某个地方,或者Scapy有点关闭

2 个答案:

答案 0 :(得分:1)

您可能想尝试Scapy pull request #335中提出的解决方法。

编辑:修复已合并,所以如果你遇到同样的问题,你现在要做的就是升级Scapy!

答案 1 :(得分:0)

我认为scapy在这方面有点狡猾。你的trackeback在这里:

return struct.pack("HH",self.mladdr)+self.payload.hashret()

应包含以下内容:

return struct.pack("HH", 0, 0)+""

struct.pack没有机会工作,至少应该是:

return struct.pack("HH", *self.mladdr)+self.payload.hashnet()

因此struct.pack没有机会接收“HH”所需的两个参数。那 是一个错误。

由于您不关心有效负载,因此您可以更改ICMPv6MLQuery的scapy代码:

class ICMPv6MLQuery(_ICMPv6ML): # RFC 2710
    name = "MLD - Multicast Listener Query"
    type   = 130
    mrd    = 10000
    mladdr = "::" # 10s for mrd
    overload_fields = {IPv6: { "dst": "ff02::1", "hlim": 1, "nh": 58 }} 
    def hashret(self):
        if self.mladdr != "::":
            return struct.pack("HH",self.mladdr)+self.payload.hashret()
        else:
            return self.payload.hashret()

class ICMPv6MLQuery(_ICMPv6ML): # RFC 2710
    name = "MLD - Multicast Listener Query"
    type   = 130
    mrd    = 10000
    mladdr = "::" # 10s for mrd
    overload_fields = {IPv6: { "dst": "ff02::1", "hlim": 1, "nh": 58 }} 
    def hashret(self):
        return self.payload.hashret()

即。完全杀死struct.pack

另一方面说明:

WARNING: No route found for IPv6 destination :: (no default route?)

可能会阻止您收到答案(NIC可能会确定没有任何内容可以到达并忽略它)。配置至少一些简单的路由是明智的,例如

$ route -6
Kernel IPv6 routing table
Destination               Next Hop                   Flag Met Ref Use If
::/0                      [::]                       U    256 0     0 eth0