【问题标题】:Scapy - sending IPv6 Router Advertisement failing with lifetime > 0Scapy - 发送 IPv6 路由器广告失败,生命周期 > 0
【发布时间】:2016-09-10 23:40:45
【问题描述】:

我正在尝试使用 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)

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

上面的问题是,当 Scapy 成功发送路由器广告数据包,并且我看到邻居请求响应时,Scapy 在我可以使用 sr() 查看答案之前错误地退出。

完整输出:

    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)

有趣的是,当我将 validlifetimepreferredlifetime 设置为 0 时,Scapy 不会崩溃和烧毁。但是,这并没有什么帮助,因为生命周期为 0 并没有得到任何回应。

我在脚本中的某个地方搞砸了,还是 Scapy 在 IPv6 方面有点偏离

【问题讨论】:

    标签: python networking ipv6 scapy


    【解决方案1】:

    您可能想尝试 Scapy 的 pull request #335 中提出的修复。

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

    【讨论】:

      【解决方案2】:

      我认为scapy 在这方面有点狡猾。您在此处的引用:

      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
      

      【讨论】:

      • 太棒了。从/usr/lib/python2.7/site-packages/scapy/layers/inet6.py 中删除这三行就可以了,正如所描述的那样。虽然我在此设备上没有默认 IPv6 路由,但它确实有链路本地路由 (fe80::/64),这似乎足以让 scapy 看到回复。非常感谢。
      猜你喜欢
      • 2013-01-24
      • 2021-09-23
      • 2011-09-12
      • 2015-12-08
      • 1970-01-01
      • 2021-06-14
      • 2021-09-27
      • 1970-01-01
      相关资源
      最近更新 更多