网络安全项目实战(三)--报文检测

6. TCP/IP协议栈及以太网帧

  • 目标
    • 了解TCP/IP协议栈的组织结构
    • 掌握以太网帧的数据格式定义
    • 能应用编码实现以太网帧的解析方法

6.1. TCP/IP 协议栈

TCP/IP网络协议栈分为应用层(Application)、传输层(Transport)、网络层(Network)和链路层(Link)四层。如下图所示(该图出自[TCPIP])。

两台计算机通过TCP/IP协议通讯的过程如下所示(该图出自[TCPIP])。 

传输层及其以下的机制由内核提供,应用层由用户进程提供(后面将介绍如何使用socket API编写应用程序),应用程序对通讯数据的含义进行解释,而传输层及其以下处理通讯的细节,将数据从一台计算机通过一定的路径发送到另一台计算机。应用层数据通过协议栈发到网络上时,每层协议都要加上一个数据首部(header),称为封装(Encapsulation),如下图所示(该图出自[TCPIP])。 

不同的协议层对数据包有不同的称谓,在传输层叫做段(segment),在网络层叫做数据报(datagram),在链路层叫做帧(frame)。数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,最后将应用层数据交给应用程序处理。我们在pcap文件中,所得到的package data数据就是一个以太网帧, 因此对“package data”的解析就是解析一个以太网帧

 

6.2. 以太网(RFC 894)帧格式

以太网的帧格式如下所示(该图出自[TCPIP]):

  • 源地址是指网卡的硬件地址(也叫MAC地址),长度是48位,是在网卡出厂时固化的。用ifconfig命令看一下,“HWaddr 00:15:F2:14:9E:3F”部分就是硬件地址。
  • 目的地址, 意义同源地址
  • 协议字段有三种值,分别对应IP、ARP、RARP。帧末尾是CRC校验码。

    以太网帧中的数据长度规定最小46字节,最大1500字节。

    ARP和RARP数据包的长度不够46字节,要在后面补填充位。

    最大值1500称为以太网的最大传输单元(MTU),不同的网络类型有不同的MTU,如果一个数据包从以太网路由到拨号链路上,数据包长度大于拨号链路的MTU了,则需要对数据包进行分片(fragmentation)。

    ifconfig命令的输出中也有“MTU:1500”。

    注意,MTU这个概念指数据帧中有效载荷的最大长度,不包括帧首部的长度。

 

6.3. 以太网栈头部

 // /usr/include/linux/if_ether.h 

struct ethhdr {
    unsigned char    h_dest[ETH_ALEN];    /* 目标mac地址    */
    unsigned char    h_source[ETH_ALEN];    /* 源mac地址    */
    __be16        h_proto;        /* 以太网类型    */
} __attribute__((packed));

6.4. 以太网帧解析代码

一下为以太网帧的核心解析代码


    MAC_FRM_HDR *mac_hdr; //define a Ethernet frame header  
    IP_HDR *ip_hdr;       //define a IP header  
    char *tmp1, *tmp2;  
    int AND_LOGIC = 0xFF;  

    mac_hdr = buf;  //buf is what we got from the socket program  
    ip_hdr = buf + sizeof(MAC_FRM_HDR);  
    //udp_hdr = buf + sizeof(MAC_FRM_HDR) + sizeof(IP_HDR); //if we want to analyses the UDP/TCP  

    tmp1 = mac_hdr->src_addr;  
    tmp2 = mac_hdr->dest_addr;  
    /* print the MAC addresses of source and receiving host */  
    printf("MAC: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X==>" "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",  
                tmp1[0]&AND_LOGIC, tmp1[1]&AND_LOGIC, tmp1[2]&AND_LOGIC,tmp1[3]&AND_LOGIC,  
                tmp1[4]&AND_LOGIC, tmp1[5]&AND_LOGIC,  
                tmp2[0]&AND_LOGIC, tmp2[1]&AND_LOGIC, tmp2[2]&AND_LOGIC,tmp2[3]&AND_LOGIC,  
                tmp2[4]&AND_LOGIC, tmp2[5]&AND_LOGIC);  

    tmp1 = (char*)&ip_hdr->ip_src;  
    tmp2 = (char*)&ip_hdr->ip_dest;  
    /* print the IP addresses of source and receiving host */  
    printf("IP: %d.%d.%d.%d => %d.%d.%d.%d",  
                 tmp1[0]&AND_LOGIC, tmp1[1]&AND_LOGIC, tmp1[2]&AND_LOGIC,tmp1[3]&AND_LOGIC,  
                 tmp2[0]&AND_LOGIC, tmp2[1]&AND_LOGIC, tmp2[2]&AND_LOGIC,tmp2[3]&AND_LOGIC);  
    /* print the IP protocol which was used by the socket communication */  
    switch(ip_hdr->ip_protocol) {  
             case IPPROTO_ICMP: LOGI("ICMP"); break;  
             case IPPROTO_IGMP: LOGI("IGMP"); break;  
             case IPPROTO_IPIP: LOGI("IPIP"); break;  
             case IPPROTO_TCP:  
         case IPPROTO_UDP:  
                                LOGI("Protocol: %s", ip_hdr->ip_protocol == IPPROTO_TCP ? "TCP" : "UDP");  
                                LOGI("Source port: %u, destination port: %u", udp_hdr->s_port, udp_hdr->d_port);  
                                break;  
             case IPPROTO_RAW: LOGI("RAW"); break;  
             default: printf("Unknown, please query in inclued/linux/in.h\n"); break;  
    }  

7. IP 报文

  • 目标
    • 了解IP报文的组织结构
    • 掌握IP报文的分析方法。

7.1. IP数据报格式

IP数据报的格式如下(这里只讨论IPv4)(该图出自[TCPIP]):

 

  • 版本:IP报文版本号 IPV4:4,IPV6:6

  • 首部长度:IP header 长度,是4字节的整数倍, 没有选项,则一般为5(5x32bit=20B)

  • 8位服务类型:一般没有使用,详细参考RFC
  • 总长度:header+数据 总长度
  • 16位标识:IP 报文的唯一id,分片报文的id 相同,便于进行重组。
  • 3位标志:标明是否分片。是一个3位的控制字段,包含:
    • 保留位:1位
    • 不分段位:1位,取值:0(允许数据报分段)、1(数据报不能分段)
    • 更多段位:1位,取值:0(数据包后面没有包,该包为最后的包)、1(数据包后面有更多的包)
Bit 0: reserved, must be zero
Bit 1: (DF) 0 = May Fragment,  1 = Don't Fragment.
Bit 2: (MF) 0 = Last Fragment, 1 = More Fragments.

          0   1   2
        +---+---+---+
        |   | D | M |
        | 0 | F | F |
        +---+---+---+
  • 13位片偏移:参考下图。如果是第一片取值为0,第二片取值175,以此类推。

  • TTL:生存时间,即路由器的跳数,每经过一个路由器,该TTL 减一,因此路由器需要重新计算IP报文的校验和。
  • 8位协议:ICMP:1,TCP:6,UDP:17,其他的自行百度
  • 首部校验和:IP header校验和,接收端收到报文进行计算如果校验和错误,直接丢弃。
  • 源IP地址:无须解释
  • 目的IP地址:无须解释
  • 选项:这个一般也没有使用。详细参考RFC
  • 数据:上层的报文,如TCP 报文、UDP报文等。

7.2. IP报文头部

IP头部,总长度20字节


 // /usr/include/linux/ip.h
struct iphdr {
 #if defined(__LITTLE_ENDIAN_BITFIELD)
    __u8    ihl:4,     //首部长度
        version:4;    //版本 
 #elif defined (__BIG_ENDIAN_BITFIELD)
    __u8    version:4,    //版本
          ihl:4;          //首部长度
 #else
 #error    "Please fix <asm/byteorder.h>"
 #endif
    __u8    tos;      //服务类型
    __be16    tot_len;    //总长度
    __be16    id;         //标志
    __be16    frag_off;   //分片偏移
    __u8    ttl;         //生存时间
    __u8    protocol;     //协议
    __sum16    check;         //检验和
    __be32    saddr;      //源IP地址
    __be32    daddr;      //目的IP地址
    /*The options start here. */
};

关于协议类型定义

 // /usr/include/linux/netinet/in.h

/* Standard well-defined IP protocols.  */
enum
  {
    IPPROTO_IP = 0,       /* Dummy protocol for TCP.  */
#define IPPROTO_IP        IPPROTO_IP
    IPPROTO_ICMP = 1,       /* Internet Control Message Protocol.  */
#define IPPROTO_ICMP        IPPROTO_ICMP
    IPPROTO_IGMP = 2,       /* Internet Group Management Protocol. */
#define IPPROTO_IGMP        IPPROTO_IGMP
    IPPROTO_IPIP = 4,       /* IPIP tunnels (older KA9Q tunnels use 94).  */
#define IPPROTO_IPIP        IPPROTO_IPIP
    IPPROTO_TCP = 6,       /* Transmission Control Protocol.  */
#define IPPROTO_TCP        IPPROTO_TCP
    IPPROTO_EGP = 8,       /* Exterior Gateway Protocol.  */
#define IPPROTO_EGP        IPPROTO_EGP
    IPPROTO_PUP = 12,       /* PUP protocol.  */
#define IPPROTO_PUP        IPPROTO_PUP
    IPPROTO_UDP = 17,       /* User Datagram Protocol.  */
.....

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值