Pregunta

Does Scapy bypass Dummynet (IPFW in general)?

It really looks like it does. I'm adding a large extra delay to each outgoing and incoming packet, and everything slows down apart from packets sent with Scapy.

$ ipfw add pipe 1 from any to any
$ ipfw pipe 1 config delay 500ms
$ ping www.google.com
PING www.l.google.com (173.194.34.18) 56(84) bytes of data.
64 bytes from par03s02-in-f18.1e100.net (173.194.34.18): icmp_req=1 ttl=54 time=1011 ms
64 bytes from par03s02-in-f18.1e100.net (173.194.34.18): icmp_req=2 ttl=54 time=1010 ms

So it seems OK. But as soon as I send packets with Scapy, here's what happens:

>>> from scapy.all import *
>>> p = IP(dst="www.google.com", ttl=1) / TCP(sport=222, dport=2999)
>>> ans,unans = sr(p*3)
>>> ans[0][1].time - ans[0][0].sent_time
0.0002701282501220703  #usual value for such RTT

Is there any way to force it to pass through dummynet?

EDIT If only I had another machine at my disposal, I could use dummynet there and direct all my traffic to it, before it gets into the Internet. I would prefer to do everything locally, though.

¿Fue útil?

Solución

The author of Scapy replied to me in Scapy's mailing list:

Try the same solution as for this question: http://trac.secdev.org/scapy/wiki/FAQ#Icantping127.0.0.1.Scapydoesnotworkwith127.0.0.1orontheloopbackinterface (using raw sockets)

It worked! Here's the paragraph from the above link :

I can't ping 127.0.0.1. Scapy does not work with 127.0.0.1 or on theloopback interface

The loopback interface is a very special interface. Packets going through it are not really assembled and dissassembled. The kernel routes the packet to its destination while it is still stored an internal structure. What you see with tcpdump -i lo is only a fake to make you think everything is normal. The kernel is not aware of what Scapy is doing behind his back, so what you see on the loopback interface is also a fake. Except this one did not come from a local structure. Thus the kernel will never receive it.

In order to speak to local applications, you need to build your packets one layer upper, using a PF_INET/SOCK_RAW socket instead of a PF_PACKET/SOCK_RAW (or its equivalent on other systems than Linux) :

>>> conf.L3socket
<class __main__.L3PacketSocket at 0xb7bdf5fc>
>>> conf.L3socket=L3RawSocket
>>> sr1(IP(dst="127.0.0.1")/ICMP())
<IP  version=4L ihl=5L tos=0x0 len=28 id=40953 flags= frag=0L ttl=64 proto=ICMP chksum=0xdce5 src=127.0.0.1 dst=127.0.0.1 options='' |<ICMP  type=echo-reply code=0 chksum=0xffff id=0x0 seq=0x0 |>>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top