简体   繁体   中英

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.

*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). I've put the full script on pastebin to avoid cluttering the question: 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().

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. However, this is less than helpful, as a lifetime of 0 does not get me any responses.

Have I screwed up somewhere in the script, or is Scapy a little off when it comes to IPv6?

You may want to try the fix proposed in Scapy's 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!

I would argue that scapy is a little dodgy in this respect. 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:

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

So that struct.pack has no chance of receiving the two arguments needed for "HH". That is a bug.

Since you do not care about the payload you can change the scapy code for ICMPv6MLQuery from:

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.


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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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