Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux libpcap setfilter()函数与数据包丢失_Linux_Sip_Rtp_Pcap_Libpcap - Fatal编程技术网

Linux libpcap setfilter()函数与数据包丢失

Linux libpcap setfilter()函数与数据包丢失,linux,sip,rtp,pcap,libpcap,Linux,Sip,Rtp,Pcap,Libpcap,这是我在这里的第一个问题@stackoverflow 我正在为一些VoIP生产服务器编写一个监视工具,特别是一个嗅探工具,它允许使用Perl中的pcap库捕获与给定模式匹配的所有流量(VoIP呼叫) 我不能使用糟糕的选择性过滤器,例如“udp”,然后在我的应用程序代码中进行所有过滤,因为这将涉及太多流量,内核无法处理数据包丢失报告 然后,我要做的是在捕获过程中迭代地构建更具选择性的过滤器。开始时,我只捕获(所有)SIP信令流量和IP片段(模式匹配在任何情况下都必须在应用程序级别进行),然后当我在

这是我在这里的第一个问题@stackoverflow

我正在为一些VoIP生产服务器编写一个监视工具,特别是一个嗅探工具,它允许使用Perl中的pcap库捕获与给定模式匹配的所有流量(VoIP呼叫)

我不能使用糟糕的选择性过滤器,例如“udp”,然后在我的应用程序代码中进行所有过滤,因为这将涉及太多流量,内核无法处理数据包丢失报告

然后,我要做的是在捕获过程中迭代地构建更具选择性的过滤器。开始时,我只捕获(所有)SIP信令流量和IP片段(模式匹配在任何情况下都必须在应用程序级别进行),然后当我在SIP数据包中找到一些关于RTP的信息时,我使用特定IP和端口向实际筛选器字符串添加'or'子句,并使用setfilter()重新设置筛选器

基本上是这样的:

  • 初始筛选器:“(udp和端口5060)或(udp和ip[6:2]&0x1FF!=0)”->捕获所有SIP流量和ip片段

  • 更新的筛选器:“(udp和端口5060)或(udp和ip[6:2]&0x1FF!=0)或(主机ip和端口)”->还捕获特定ip、端口上的RTP

  • 更新的筛选器:“(udp和端口5060)或(udp和ip[6:2]&0x1FF!=0)或(主机ip和端口)或(主机IP2和端口2)”->也捕获第二个RTP流

  • 等等

    这工作得很好,因为我能够获得RTP流的“真实”数据包丢失以进行监控,而我的工具的选择性筛选版本较差,RTP数据包丢失百分比不可靠,因为内核丢弃数据包导致一些数据包丢失

    但让我们谈谈这种方法的缺点

    捕获时调用setfilter()涉及到这样一个事实,即libpcap在“更改筛选器时”将收到的数据包丢弃到pcap linux.c中的函数set_kernel_filter()的代码注释中所述(选中libpcap版本0.9和1.1)

    所以,当我调用setfilter()并且一些数据包到达IP碎片时,我确实丢失了一些碎片,而libpcap统计数据在最后没有报告这一点:我发现它正在挖掘跟踪

    现在,我理解了为什么这个操作是由libpcap完成的,但在我的情况下,我肯定不需要任何数据包丢弃(我不关心获得一些无关的流量)


    如果不修改libpcap的代码,您知道如何解决这个问题吗

    用更具体的过滤器启动一个新流程怎么样。您可以同时进行两个并行pcap捕获。经过一段时间(或检查两者是否收到相同的数据包),您可以停止原始数据包

    您能捕获所有RTP流量吗

    RTP流量的建议如下:

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

    正如链接所指出的,当DNS和可能的其他UDP数据包偶尔包含RTP数据包使用的头字节0x80时,您会得到一些误报,但是这个数字应该可以忽略不计,并且不足以导致内核丢失。

    圆孔方钉

    你有一个不太适合你需要的工具

    另一种选择是做一个第一级过滤器(如上所述,它捕获的比需要的多得多),并将其导入另一个工具,该工具实现您想要的更精细的过滤器(一直到每个调用案例)。如果由于RTP流量过大,第一级过滤器对内核来说太多,那么您可能需要做一些其他事情,比如保持进程的稳定以捕获单个调用(因此您不会更改“主”进程上的过滤器;它只是指示其他进程如何设置过滤器)

    是的,这可能意味着合并捕获,可以是动态的(将它们全部传递给“保存捕获”过程),也可以是事后的


    您确实意识到,如果不快速安装过滤器,您可能会错过RTP数据包。不要忘记,RTP数据包可能在200 OK到来之前(或正好同时到来)为发起者到来,并且它们可能在ACK到来之前(或在ACK之上)返回应答者。另外,不要忘记没有SDP的邀请(在200行中提供,在确认中回答)。等等等等:-)嗨,谢谢你的回答。我曾考虑过在每次需要“新过滤器”时生成进程,但最终我会有相当多的进程,并在最后完成合并捕获的任务。所以说实话,这是我本应该避免的菲,谢谢你的回答。不幸的是,在生产服务器上有大量的调用,所有的RTP通信量意味着几乎所有的通信量,而且非常多。很高兴了解这种过滤器,但在未来可能会很有用。关于媒体流,如果我在开始/结束时丢失了一些数据包,这不是一个大问题,前提是我在中间得到了完整的真实数据流:它应该足以检测到真实的数据包丢失(即,当没有内核数据包丢失发生时)。我最终认为多重过程也是唯一的解决方案。尽管我实现了一个修补libpcap的版本,它运行得很好,尽管并不总是很不幸。