libpcap setfilter()函数和数据包丢失
这是我的第一个问题@stackoverflow。libpcap setfilter()函数和数据包丢失
我正在写一些VoIP的生产服务器,特别是嗅工具,允许捕获所有通信(VoIP电话)相匹配使用PCAP库在Perl中给定模式的监视工具。
我不能使用差的选择性过滤器,例如, “udp”,然后在我的应用程序的代码中进行所有过滤,因为这将涉及过多的流量,并且内核不会处理报告丢包。
我要做的则是反复建立捕获过程中更具有选择性过滤器成为可能。一开始我只捕获(所有)SIP信令流量和IP分段(模式匹配必须在任何情况下在应用层完成),那么当我找到一些关于RTP到SIP分组的信息时,我会在分组中添加'或'子句具有特定IP和PORT的实际过滤器字符串,并使用setfilter()重新设置过滤器。
所以基本上是这样的:
初始过滤器: “(UDP和端口5060)或(UDP和IP [6:2]!& 0x1FFF的= 0)” - >捕获所有SIP流量和IP分段
更新的过滤器:“(udp和端口5060)或(udp和ip [6:2] & 0x1fff!= 0)或(主机IP和端口PORT)” - >也捕获RTP具体的IP,端口
更新过滤器:“(UDP和端口5060)或(udp和ip [6:2] & 0x1fff!= 0)或(主机IP和端口PORT)或(主机IP2和端口PORT2)“ - >捕获第二个RTP流
依此类推。
这工作得很好,因为我能够获得RTP的“真实”数据包丢失流监测的目的,而与我的工具的一个贫穷的选择滤波器的版本,RTP数据包丢失率是不可靠的,因为由于内核丢包造成一些数据包丢失。
但让我们来看看这种方法的缺点。
捕获时调用setfilter()涉及如下事实:libpcap将函数set_kernel_filter()的代码注释中所收到的“更改过滤器”的数据包丢弃到pcap-linux.c中(检查libpcap版本0.9和1.1)。
因此,当我调用setfilter()并且某些数据包到达IP分段时,我会放松一些碎片,并且最终没有通过libpcap统计数据报告:我发现它在挖掘痕迹。
现在,我明白了为什么这个动作是通过libpcap的做的原因,但对我来说我绝对不需要有任何丢包(我不在乎得到一些相关的流量)。
你会对如何解决这个问题是不是修改libpcap的代码进行任何想法?
如何使用更具体的过滤器启动新过程。你可以同时进行两个并行pcap捕捉。经过一段时间(或检查两者都收到相同的数据包),您可以停止原始数据。
你能抓住所有的RTP流量吗?
从capture filters用于RTP流的建议是:
udp[1] & 1 != 1 && udp[3] & 1 != 1 && udp[8] & 0x80 == 0x80 && length < 250
为纽带所指出的,你会得到一些假阳性,其中DNS和其他可能的UDP数据包偶尔包含头字节,0x80的,由RTP使用数据包,但数量应该可以忽略不计,不足以导致内核丢失。
嗨,谢谢你的答案。不幸的是,在生产服务器上有大量的呼叫,所有的RTP流量几乎意味着所有的流量,而且很多。很高兴知道这种过滤器,但未来可能会有用。 – Guido 2010-12-06 10:43:29
圆孔,方形钉。
你有一个不太适合你需要的工具。
另一个选择是做一级过滤器(如上所述,捕获比想要的多得多的数据)并将其传送到另一个工具中,实现您想要的更精细的过滤器(直至每次调用的情况)。如果由于RTP流量过大,第一级过滤器对于内核来说太多了,那么您可能需要做其他事情,比如保持一个稳定的进程来捕获单个调用(所以您不要更改“主”过程;它只是指导其他人如何设置他们的过滤器。)
是的,这可能意味着合并捕捉,或者在飞行中(将它们全部传递给“保存捕捉”过程)或事后。
如果你不安装你的过滤器快速你会意识到你可能会错过RTP数据包。不要忘记,在200 OK进入(或在一起)之前,RTP数据包可以进入发起者,并且他们可以在ACK(或在其之上)之前回到应答者。另外不要忘记INVITE没有SDP(在200 OK中提供,在ACK中回答)。等等等等:-)
关于媒体流,如果我在开始/结束时错过了一些数据包,那么它不是一个大问题,前提是我在中间得到完整的真实数据流:它应该足以检测*真正的数据包丢失(即当没有内核数据包丢失时发生)。我最终认为多进程也是唯一的解决方案。尽管我实现了一个修补libpcap的版本,并且它工作得很好,即使并非总是不幸。 – Guido 2010-12-20 10:16:17
嗨,谢谢你的回答。每次需要“新过滤器”时,我都会考虑产卵过程,但最终我会得到相当多的过程,并且还会在最后合并捕获任务。所以老实说,这是我想避免.. P – Guido 2010-12-03 10:06:18