【博客271】筛选UDP报文进行分析时,不要基于端口过滤

内容: 记录用端口过滤来筛选UDP报文时,会出现遗漏的情况

先细说以下分片:

1、IP分片是IP协议在传输数据包时,将数据报文分为若干分片进行传输,并在目标系统中进行重组。

2、不同的链路类型规定有不同最大长度的链路层数据帧,称为链路层MTU(最大传输单元)。常见以太网
的MTU为1500,若IP协议在传输数据包时,IP报文长度大于转发接口的MTU,则将数据报文分为若干分片
进行传输,分片报文到达接收方时,由接收方完成重组。

3、对于不同的传输层协议,在IP层上,需不需要进行分片是不同的,比如,对TCP来说:

它是尽量避免分片的。因为当在IP层进行了分片后,如果其中的某片数据丢失,则需对整个数据报进行重
传。因为IP层本身没有超时重传机制,当来自TCP报文段的某一片丢失后,TCP在超时后重发整个TCP报文
段,该报文段对应于一份IP数据报,没有办法只重传数据报中的一个数据报片。而且如果对数据报分片的
是中间路由器,而不是起始端系统,那么起始端系统就无法知道数据报是如何被分片的,因此基于这种原
因,TCP是经常要避免分片的。
	
* TCP层是如何避免IP层分片方法:

TCP在建立连接时会进行3次握手,而在这3次握手中,客户端和服务端通常会协商一个值,那就是MSS,用
来表示本段所能接收的最大长度的报文段。MSS=MTU-TCP首部大小-IP首部大小,MTU通过查询链路层得知。
当两端确认好MSS后进行通信,TCP层往IP层传输数据时,如果TCP层缓冲区的大小大于MSS,那么TCP层都
会将其中的数据分组进行传输,这样就避免了在IP层进行分片。

4、对于UDP而言,由于UDP是没有MSS的,且不需要保证可靠性的,没有超时和重传机制,这使得UDP很容易
导致IP分片。那么UDP分片后,分片机制如何运行?

对于每份IP数据报来说,其16位标识字段都包含一个唯一值。在数据报被分片时,这个值同时被复制到每个
片中。在IP首部中,我们看到有一个占了3位的标志字段,其中第1位作为保留字段;第2位分段用来表示一
个数据报是否允许在IP层被分片;而第3位更多分片字段,则是当数据报被分片时,让接收端知道在什么时候
完成所有的分片组装,除了最后一片外,其他每个组成数据报的片都要把该比特置1* 而如果将其中的分段标志比特位置1,表示不允许IP层对数据报进行分片。例如当路由器收到一份需要分片
  的数据报,而在IP首部又设置了不分片(DF)的标志比特,路由器会丢弃数据报并发送一个ICMP差错报文
  IP首部中13位的偏移量字段表示IP分片在整个数据流中的位置,第一个数据报分片的偏移量置为0,而后续
  的分片偏移量则是根据网络的MTU大小设置,且必须为8的整数倍。

* 需要注意的是,任何传输层的首部只出现在第一片数据中,后续报文均不带传输层信息。这个信息也是
  本文中心。

* 同时分片也是容易引起攻击:

  1、黑客构造的分片报文,但不向接收方发送最后一个分片报文,导致接收方要为所有的分片报文分配内存
  空间,可由于最后一个分片报文永远不会达到,接收方的内存得不到及时的释放(接收方会启动一个分片
  重组的定时器,在一定时间内如果无法完成重组,将向发送方发送ICMP重组超时差错报文,,只要这种攻
  击的分片报文发送的足够多、足够快,很容易占满接收方内存,让接收方无内存资源处理正常的业务,从
  而达到DOS的攻击效果。
  
  2、黑客构造的分片报文,但是报文的偏移字段和实际不一致,比如后续的报文偏移字段更小,此时若有
     计算机协议栈的设计是计算偏移值,以分配空间来储存新到的内容,此时,后续报文的偏移更小,则
     相减会变为负值,而负值用unsigned来存储就变成非常大的数,此时为偏移值分配的空间无比大,使
     程序崩溃。

UDP报文在发给本地网卡的时候不会分片,而发给其它电脑若超过MTU则会分片:

不分片的情况见上篇博客分析:
【博客270】UDP报文数据大于MTU也不一定会分片!

分片情况分析:

//发送端代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#define MAXBUF 60000
int main(int argc, char const *argv[])
{
    int s = 0;
    int n = 0;
    int reuse = 1;
    int port = 5555;
    struct sockaddr_in srv;
    char buf[MAXBUF] = {0};

    for (int i = 0; i < 60000; i++)
    {
        buf[i] = 'k';
    }
    buf[59999] = '\0';
    /*解析参数*/
    if (argc != 2)
    {
        printf("Usage:%s ServerIP\n", argv[0]);
        return -1;
    }
 
    bzero(&srv, sizeof(srv));
    srv.sin_family = PF_INET;
    srv.sin_addr.s_addr = inet_addr(argv[1]);
    srv.sin_port = htons(port);
    /*创建 UDP 套节字*/
    s = socket(AF_INET, SOCK_DGRAM, 0);
    if(s<0){
        perror("socket");
        return -1;
    }
        /*通过套节字 s 向服务器发送数据*/
        if ((n = sendto(s, buf, strlen(buf), 0, (struct sockaddr *) &srv, sizeof(struct sockaddr))) < 0)
        {
            perror("sendto");
            return -1;
        }else{
            printf("send to %s(port=%d) len %d:%s\n", argv[1], port, n, buf);
        }
}

发送给另外一个非本地ip地址:
在这里插入图片描述
抓取报文分析:此时出现了分片
在这里插入图片描述
看第一片和其它分片的区别:
在这里插入图片描述
其它片:每片都是一样的,但都跟第一片不一样
在这里插入图片描述
区别:

16b6b其实这样子的组合是k字母的ascii码组合,即数据内容,因为我发送的内容是k字符

2、第一片出现了传输层首部的信息,也就是UDP报文的信息,但是后续的分片报文直接就是6b6b等数据
   内容

3、那么如果此时你按照端口去过滤就会出现问题,因为你后续分片是不带UDP首部信息,那么按照端口
   过滤就不会显示这些报文了,造成分析时丢失了一些数据源,结果将出现误差

展示过滤端口与不过滤端口:

1、不过滤端口时,查到了所有的分片
在这里插入图片描述
2、过滤端口时,只能看到了第一片会被解释成UDP并且符合要求,后面都不会被展示:
在这里插入图片描述
注意:另一个IP地址回复一个ICMP差错报文是因为对方端口并没有开放

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值