在虚拟化环境下镜像流量交给suricata分析,遇到了文件还原不完整的问题,同环境下使用tcpdump抓包查看可以看到捕获的数据包存在大包被截断的情况。这里分析一下为什么tcpdump会出现数据包被截断的情况以及什么条件下会触发该情况,suricata的问题不完全一致,但是基本思路是一样的。 虚拟机操作系统:CentOSLinuxrelease7。5。1804 参考libpcap版本:Date:TueNov500:10:1520190800,79817f数据包截断 tcpdump捕获的文件查看如图,可以看到捕获到的数据包不完整。 tcpdump捕获文件截断发生条件 因为所处虚拟化环境,外部转发进大数据包的情况比较多样,暂时不考虑外部,仅关注转发进大数据包后本地捕获被截断的情况,这里可以用http下载一个较大文件模拟。tcpdump参数中指定特定网卡,比如。这里如果指定网卡为any则不会发生截断。 sudotcpdumpieth0nntcpport9090wlongin。pcap网卡参数中gro、lro、tso、gso等各种offload相关配置均为off状态。suricata在启动时会主动设置相关配置到off。〔huyubogon〕ethtoolketh0grepoffloadtcpsegmentationoffload:offudpfragmentationoffload:offgenericsegmentationoffload:offgenericreceiveoffload:offlargereceiveoffload:off〔fixed〕rxvlanoffload:off〔fixed〕txvlanoffload:off〔fixed〕l2fwdoffload:off〔fixed〕hwtcoffload:off〔fixed〕rxudptunnelportoffload:off〔fixed〕截断原因 在截断发生条件的判断中已经发现tcpdump中指定网卡与设定为any时表现不同,对比两种参数运行时strace记录的系统调用区别,发现一个系统调用的参数有明显区别。setsockopt(3,SOLPACKET,PACKETRXRING,{blocksize4096,blocknr1310,framesize1600,framenr2620},16)0 这里与libpcap捕获数据包的方式有关,其使用AFPACKET捕获数据包,并使用mmap映射一个环形缓冲区用于保存内核拷贝给它的数据包,参考PACKETMMAP。 环形缓冲区的参数中需要设置每个数据包的最大尺寸,也就是framesize,如果设置的尺寸小于数据包实际尺寸,那么内核在拷贝数据包时只能做截断处理。 libpcap中该设置代码位于pcaplinux。c4139行函数createring中,在选择framesize大小的代码中注释也说明了其选择逻辑。首先其不会完全按照snapshotlength参数设置framesize,因为这会导致缓冲区中可以保存的数据包数量过少,进而导致捕获性能降低。其会在snapshotlength和可能的最大包尺寸中选择一个较小的值作为framesize。问题就出在这个可能的最大数据包尺寸。当gro及lro和其他offload相关配置均为关闭时,libpcap认为该以太网卡不会收到尺寸大于MTU的数据包,因此framesize会设置到一个比较小的值。libpcap判断offload配置的函数为ifacegetoffload。 libvirt虚拟化环境下,虚拟机对应的tap设备如果没有关闭gso和tso,虚拟机网卡就会收到大包,这里涉及到linux虚拟网络设备的实现,目前暂不分析。处理方式 截断发生的条件和原因已经找到,避免截断的方式也就很多样了。需要说一下是,suricata文档中明确说明需要关闭网卡的各种offload特性,是为了避免收到大数据包,因为大数据包会影响其对dsize的判断