Libnet vs Raw Sockets for packet injection

4.3k views Asked by At

I need the opinion/advice of more experienced network programmers about some stuff regarding to packets injection on GNU/Linux systems. I'm working on a open source C++ library for packet injection and sniffing. The library is libcrafter. On the page there are a few examples to see how the library works.

I have a dilemma, and would appreciate your thoughts. Currently, the library "offer" two ways to write a packet on the wire. First, the packet is constructed:

Packet pck = IP()/UDP()/DNS();

1) and then is sent with the Send() function:

pck.Send("eth0");

2) OR using the RawSocketSend() function (which is an "experimental" function that I'm using for benchmarking but is available for the user):

pck.RawSocketSend(sd);

where sd is a socket descriptor. If the packet has a link layer protocol (like Ethernet) sd should be a PACKET socket descriptor. If not, should be a RAW socket descriptor.

The standard and documented way to send a packet is with the Send() method. Currently, the Send() method uses libnet for write the packet on the wire.

The thing is that the Send() function is by far more slow than the RawSocketSend()... I constantly have to do a lot of tricky and annoying stuff to adapt the way that libcrafter handle the protocols fields to properly use the libnet_build* functions (which results on a performance penalty). And each time I implement a protocol I have to take a look to libnet documentation and makes the development processes very tedious and slow. So, I was thinking to stop using libnet for packet injection and directly use RAW/PACKET sockets inside the Send() function.

Libcrafter is designed to handle all the tedious work of packet crafting (checksum calculations, byte ordering, header lengths, etc.) in a transparent way for the user. And everything works fine on the most popular GNU/Linux systems (Ubuntu, Fedora, Debian) using RAW/PACKET sockets (the RawSocketSend function).

The only reason why I use libnet is for portability issues. But I don't have the knowledge or intentions to port libcrafter to other system rather than GNU/Linux systems.

My questions are:

  1. Is prudent and safe to use RAW/PACKET sockets on a packet injection library for GNU/Linux?
  2. If I decide to stop using libnet, do you know some issues that I should take into account regarding to portability with RAW/PACKET sockets between GNU/Linux distros?
  3. The RAW/PACKET sockets interface may change in future versions of the kernel?

Thank you very much :-)

1

There are 1 answers

2
Guy L On

The beautiful thing about open source is that you can actually browse the source, so I've checked: http://code.google.com/p/libcrafter/source/browse/libcrafter/crafter/Packet.cpp

And saw that Packet::send isn't efficient: It does too many system calls (matching the device name to actual interface each time) and call libnet function which I guess open a socket each time and sends the packet. Anyhow it's too much overhead for sending a packet.

Send it raw, I haven't seen the function code but I guess it just uses send(). If i were you, If I wasn't satisfied from the sendRawPacket() function I'd simply send it using a row socket, I've seen that packet provides getRawBuffer() function.

for more information about raw sockets: http://www.tenouk.com/Module43a.html and try google.

For you questions:

1) I don't understand what do you mean by "safe"? The general answer is "Yes, carefully"

2) About portabilty, using raw sockets is part of the POSIX standard, so it will work on any linux dist, and probably on windows too. I don't know if libcraft is portable to windows, but it should run on any linux dist. And if not, you can contribute to library and make it portable.

3) I can't answer question regarding the future. again, It's POSIX standard that hasn't changed much in many years now, It might be changed in the future. I'm not a prophet but I don't see it change in the near future.

Guy