简体   繁体   English

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

[英]Scapy - sending IPv6 Router Advertisement failing with lifetime > 0

I am attempting to create a tool using Scapy to discover link-local IPv6 hosts by sending a fake router advertisement to the FF02::1 multicast address.我正在尝试使用 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)

Everything above the snip is mostly setting up the parameters of the router advertisement (ra_prefix, hw_addr, etc). snip 上面的所有内容主要是设置路由器广告的参数(ra_prefix、hw_addr 等)。 I've put the full script on pastebin to avoid cluttering the question: http://pastebin.com/4Q3JheXh我已经把完整的脚本放在 pastebin 上以避免混淆问题: http : //pastebin.com/4Q3JheXh

The problem with the above is that while Scapy is successfully sending the router advertisement packet, and I'm seeing neighbor solicitation responses, Scapy is exiting in error before I can view answers with sr().上面的问题是,虽然 Scapy 成功发送了路由器广告数据包,并且我看到了邻居请求响应,但在我可以使用 sr() 查看答案之前,Scapy 错误退出。

Full output:完整输出:

    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)

Interestingly, when I set validlifetime and preferredlifetime to 0, Scapy does not crash and burn.有趣的是,当我将validlifetimepreferredlifetime设置为 0 时,Scapy 不会崩溃和燃烧。 However, this is less than helpful, as a lifetime of 0 does not get me any responses.然而,这并没有什么帮助,因为 0 的生命周期不会让我得到任何回应。

Have I screwed up somewhere in the script, or is Scapy a little off when it comes to IPv6?有我搞砸了脚本的地方,或者是Scapy的,当涉及到的IPv6了一点?

You may want to try the fix proposed in Scapy's pull request #335 .您可能想尝试在 Scapy 的pull request #335 中提出的修复。

EDIT: the fixed has been merged, so all you have to do now if you have the same problem is upgrade Scapy!编辑:修复已经合并,所以如果你有同样的问题,你现在要做的就是升级 Scapy!

I would argue that scapy is a little dodgy in this respect.我认为scapy在这方面有点狡猾。 Your trackeback here:你的引用在这里:

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

Should contain the following:应包含以下内容:

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

That struct.pack has no chance of working, it at least should be:那个struct.pack没有工作的机会,它至少应该是:

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

So that struct.pack has no chance of receiving the two arguments needed for "HH".因此struct.pack没有机会接收“HH”所需的两个参数。 That is a bug.一个错误。

Since you do not care about the payload you can change the scapy code for ICMPv6MLQuery from:由于您不关心有效负载,您可以从以下位置更改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()

To

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()

ie kill the struct.pack altogether.即完全杀死struct.pack


On another note: this:另一个注意事项:这个:

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

May prevent you from receiving an answer (the NIC may decide that nothing could have arrived and ignore it).可能会阻止您收到答复(NIC 可能会认为什么都没有到达并忽略它)。 It is wise to configure at least some trivial route, eg明智的做法是至少配置一些简单的路由,例如

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM