Features of receiving packets through raw socket on Linux
- Tutorial

Linux (unlike, for example, from FreeBSD) allows you to use raw sockets not only for sending, but also for receiving data. In this place there are interesting rakes that I stepped on. Now I hasten to show them to those who still do not know, so that everyone, using their favorite programming language, whether C ++ or Python, can try them out.
The essence of the rake is shown in the figure so that those who are already in the know do not waste their time.
I will write examples in C, but you can port them to other languages that provide the possibility of low-level work with the TCP \ IP stack in Linux.
Some concepts
Let me remind you that to initialize a raw socket, we pass a parameter indicating the type of protocol. For example, UDP:
socket(AF_INET, SOCK_RAW, IPPROTO_UDP)
I will call this protocol the level at which the raw socket works. In the example, we created a raw socket at the UDP level.
The raw socket level does not limit you in the formation of a packet for sending, you can independently configure both UDP and IP headers. But when you receive the data, the fun begins ...
Rake
Suppose we created 2 raw sockets at the UDP level and used one of them to send a UDP packet to a UDP echo server. Echo will return us UDP payload back. So, the TCP \ IP Stack will copy the received packet to all raw sockets of the level indicated in the Protocol IP field of the header of the received packet. I repeat once again - on EVERYTHING , even those that are open in other applications (for this reason, an application that operates on raw sockets can only be run with superuser rights). Since the UDP echo server responds with a UDP packet, all raw UDP level sockets will receive it.
We note one more important feature. Regardless of the raw socket level, a complete packet is delivered to it, including IP headers.
Thus, every raw socket in Linux is a sniffer at the level at which it was created. Keep this in mind when developing applications.
Example
I did not load the note with code. For those who are interested in trying, I
posted my example on github . There is a cmake project that collects a simple UDP echo server and an application that creates 2 raw UDP level sockets, one of which sends data, but both are sent to epoll waiting for a response. For the purity of the experiment, it is advisable to run the echo server and the example on different machines (do not forget to correct the code according to your IP-shnikami). For fun, you can run multiple instances of the example.
There is a good article for extracurricular reading .
Thank you for your attention and less rake!