suricata 3.2 源码分析(IP数据包分片重组流程)
2017-07-11 17:24
429 查看
在网络通信中如果发送的IP包超过MTU值就会将IP包拆分成多个包发送。那么在suricata中对于这种拆分开得IP包又是如何处理的呢?下面我们一步一步来分析。
判断数据包是不是分片包是在DecedeIPV4这个函数中做的,具体位置是在
数据包解析模块->DecodeEthernet->DecedeIPV4
在DecedeIPV4这个函数中有如下一段代码:
这就是专门用来处理IP分片数据包的了。
IPV4_GET_IPOFFSET(p) > 0 是判断p中的偏移是否大于0(除第一个分片包的offset为0外其余的offset都会大于0)。
IPV4_GET_MF(p) == 1 是判断p中的mf标志是否为1 (除最后一个分片包mf为0外其余的mf都为1)。
用逻辑或来判断,保证了只要是分片包就会进入分片处理的逻辑。
主要的逻辑处里都在Defrag函数中:
tracker为申请的一块内存,我理解是用来存放分片包的,tracker里面会保存一个原始IP包的所有分片,直到这些分片被重组成功。
DefragInsertFrag这个函数将新收到的p插入刚刚得到的tracker,如果p是最后一个分片,那么会返回一个重组后的packet结构的指针rp,否则返回NULL。
DefragInsertFrag函数的最下方有针对最后一个分片的处理
more_frags获取的是p的mf的值。
我们这里只看IPV4的处理,V6的逻辑一样。
Defrag4Reassemble重组了tracker中与p的identify相同的所有分片,并返回一个重组后的包rp
调用DecodeIPV4,传入rp,重走一遍没有分包的正常逻辑。
总结:
suricata会在分片数据包被重组完成后才会调用后续的处理流程解传输层的头信息。包重组实在receive线程完成的,这一过程对后续的worker线程是透明的。
判断数据包是不是分片包是在DecedeIPV4这个函数中做的,具体位置是在
数据包解析模块->DecodeEthernet->DecedeIPV4
在DecedeIPV4这个函数中有如下一段代码:
/* If a fragment, pass off for re-assembly. */ if (unlikely(IPV4_GET_IPOFFSET(p) > 0 || IPV4_GET_MF(p) == 1)) { Packet *rp = Defrag(tv, dtv, p, pq); if (rp != NULL) { PacketEnqueue(pq, rp); } p->flags |= PKT_IS_FRAGMENT; return TM_ECODE_OK; }
这就是专门用来处理IP分片数据包的了。
IPV4_GET_IPOFFSET(p) > 0 是判断p中的偏移是否大于0(除第一个分片包的offset为0外其余的offset都会大于0)。
IPV4_GET_MF(p) == 1 是判断p中的mf标志是否为1 (除最后一个分片包mf为0外其余的mf都为1)。
用逻辑或来判断,保证了只要是分片包就会进入分片处理的逻辑。
主要的逻辑处里都在Defrag函数中:
/* return a locked tracker or NULL */ tracker = DefragGetTracker(tv, dtv, p); if (tracker == NULL) return NULL; Packet *rp = DefragInsertFrag(tv, dtv, tracker, p, pq);
tracker为申请的一块内存,我理解是用来存放分片包的,tracker里面会保存一个原始IP包的所有分片,直到这些分片被重组成功。
DefragInsertFrag这个函数将新收到的p插入刚刚得到的tracker,如果p是最后一个分片,那么会返回一个重组后的packet结构的指针rp,否则返回NULL。
DefragInsertFrag函数的最下方有针对最后一个分片的处理
if (!more_frags) { tracker->seen_last = 1; } if (tracker->seen_last) { if (tracker->af == AF_INET) { r = Defrag4Reassemble(tv, tracker, p); if (r != NULL && tv != NULL && dtv != NULL) { StatsIncr(tv, dtv->counter_defrag_ipv4_reassembled); if (pq && DecodeIPV4(tv, dtv, r, (void *)r->ip4h, IPV4_GET_IPLEN(r), pq) != TM_ECODE_OK) { UNSET_TUNNEL_PKT(r); r->root = NULL; TmqhOutputPacketpool(tv, r); r = NULL; } else { PacketDefragPktSetupParent(p); } } } else if (tracker->af == AF_INET6) { r = Defrag6Reassemble(tv, tracker, p); if (r != NULL && tv != NULL && dtv != NULL) { StatsIncr(tv, dtv->counter_defrag_ipv6_reassembled); if (pq && DecodeIPV6(tv, dtv, r, (uint8_t *)r->ip6h, IPV6_GET_PLEN(r) + IPV6_HEADER_LEN, pq) != TM_ECODE_OK) { UNSET_TUNNEL_PKT(r); r->root = NULL; TmqhOutputPacketpool(tv, r); r = NULL; } else { PacketDefragPktSetupParent(p); } } } }
more_frags获取的是p的mf的值。
我们这里只看IPV4的处理,V6的逻辑一样。
Defrag4Reassemble重组了tracker中与p的identify相同的所有分片,并返回一个重组后的包rp
调用DecodeIPV4,传入rp,重走一遍没有分包的正常逻辑。
总结:
suricata会在分片数据包被重组完成后才会调用后续的处理流程解传输层的头信息。包重组实在receive线程完成的,这一过程对后续的worker线程是透明的。
相关文章推荐
- libnids-1.21 中 IP 分片重组分析 之数据结构与处理流程
- libnids-1.21 中 IP 分片重组分析之数据结构与处理流程
- libnids-1.21 中 IP 分片重组分析 之数据结构与处理流程
- libnids-1.21 中 IP 分片重组分析 之代码
- IP分片重组的分析和常见碎片攻击 v0.2
- suricata 3.1 源码分析24 (数据包解码模块执行)
- suricata 3.1 源码分析32 (FlowWorker处理流程1)
- IP分片重组的分析和常见碎片攻击 v0.2
- suricata 3.1 源码分析23 (数据包解码模块注册及初始化)
- suricata 3.1 源码分析30 (packet_pool处理流程)
- suricata 3.1 源码分析25 (数据包以太层解码)
- suricata 3.1 源码分析35 (FlowWorker处理流程4 - 流重用函数)
- IP分片重组的分析和常见碎片攻击 v0.2
- suricata 3.1 源码分析21 (数据包处理1)
- 计算机网络IP数据包的3个标志位以及IP数据报的分片和重组过程
- suricata 3.1 源码分析28 (数据包TCP解码)
- IP分片重组的分析和常见碎片攻击
- suricata 3.1 源码分析19 (数据包获取)
- suricata 3.1 源码分析20 (数据包封装)
- suricata 3.1 源码分析29 (数据包队列)