Libpcap setfilter () function and packet loss

This is my first question here @stackoverflow.

I am writing a monitoring tool for some VoIP production servers, in particular, a sniff tool that allows you to capture all traffic (VoIP calls) that matches a given pattern using the pcap library in Perl.

I can’t use bad selective filters, for example, udp, and then do all the filtering in the application code, because it will be caused by excessive traffic, and the kernel will not cope with the message about packet loss.

What I do then is iteratively build a more selective filter that can be used during capture. At first, I only capture (all) SIP signaling traffic and IP fragments (pattern matching should be done at the application level anyway), then when I find some information about RTP in SIP packets, I add sentences or sentences to the actual line filter with specific IP and PORT and re-set the filter using setfilter ().

So basically something like this:

  • Source filter: "(udp and port 5060) or (udp and ip [6: 2] and 0x1fff! = 0)" β†’ captures all SIP traffic and IP fragments

  • Updated filter: "(udp and port 5060) or (udp and ip [6: 2] and 0x1fff! = 0) or (host IP and port PORT)" β†’ Also captures RTP for a specific IP address, PORT

  • Updated filter: "(udp and port 5060) or (udp and ip [6: 2] and 0x1fff! = 0) or (host IP address and PORT port) or (host IP2 and PORT2 port)" β†’ Captures the second stream RTP as well

Etc.

This works very well, since I can get a β€œreal” packet loss of RTP streams for monitoring purposes, while with a poor sample filter version of my tool, the percentage of loss of RTP packets was unreliable, because there were some packets that were missing due to a packet drop by the kernel .

But let's move on to the disadvantage of this approach.

The call to setfilter () during capture includes the fact that libpcap discards packets received "when the filter was changed", as indicated in the code comments for the set_kernel_filter () function, in pcap-linux.c (versions of libpcap version 0.9 and 1.1 have been verified) )

So, what happens when I call setfilter () and some packets arrive in IP fragmentation, I lose some fragments, and this is not reported in the libpcap statistics at the end: I noticed that it is digging into traces.

Now I understand the reason why this action is performed by libpcap, but in my case I definitely do not need to refuse the package (I do not want to receive some unrelated traffic).

Do you have an idea on how to solve this problem that does not change the libpcap code?

+4
source share
3 answers

How about starting a new process with a more specific filter. You can have two parallel pcap captures at once. After a while (or checking that both received the same packages), you can stop the original.

+1
source

Can you just capture all the RTP traffic?

From the capture filters suggestion for RTP traffic:

udp[1] & 1 != 1 && udp[3] & 1 != 1 && udp[8] & 0x80 == 0x80 && length < 250 

As you can see from the link, you will get several false positives when DNS and, possibly, other UDP packets sometimes contain a header byte, 0x80, used by RTP packets, however, the number should be small and not enough to cause a kernel crash.

+1
source

Round hole, square pin.

You have a tool that does not fit your needs.

Another option is to make a first-level filter (as indicated above, which captures much more than necessary) and transfer it to another tool that implements a finer filter (before the case that is required for each call). If this first-level filter is too much for the kernel due to heavy RTP traffic, you may need to do something else, for example, keep stable processes to capture individual calls (therefore, you do not change the filter to the β€œmain” one, the process simply instructs others how to set filters.)

Yes, this can mean a merger of captures, either on the fly (transfer all of them to the process of "save capture"), or after the fact.

You understand that you can skip RTP packets anyway if you don't install your filters quickly. Do not forget that RTP packets may appear to the sender before 200 OK (or immediately together), and they may return to the responder before the ACK (or on top of it). Also don't forget INVITE without SDP (200 OK sentence, ACK response). Etc, etc .:-)

+1
source

All Articles