网络帧分析及总结

TCP/IP五层网络协议

  1. 应用层:是网络应用程序及其应用层协议存留的地方。因特网的应用层包括许多协议,常见的有HTTP(它为web文档提供了请求和传送)、SMTP(它提供了电子邮件报文的传输)和FTP(它提供了两个端系统之间的文件传送)。
  2. 传输层:负责为信源和信宿提供应用程序进程(包括同一终端上的不同进程)间的数据传输服务,这一层上主要定义了两个传输协议,传输控制协议即TCP和用户数据报协议UDP。
  3. 网络层:负责将数据报独立地从信源发送到信宿,主要解决路由选择、拥塞控制和网络互联等问题。
  4. 链路层:负责将IP数据报封装成合适在物理网络上传输的帧格式并传输,或将从物理网络接收到的帧解封,取出IP数据报交给网络层。
  5. 物理层:负责将比特流在结点间传输,即负责物理传输。该层的协议既与链路有关也与传输介质有关。

以太网帧

由于物理层更多的是与物理介质有关,所以直接从链路层开始分析。在链路层中,使用的最多的是以太网,而以太网帧因为历史原因存在多个版本,这里以IEEE802.3以太网帧格式为例介绍。

- 前导码:7个字节,用于数据传输过程中的双方发送、接收的速率的同步
- 帧开始符:1个字节,表明下一个字节开始是真实数据(目的MAC地址)
- 目的MAC地址:6个字节,指明帧的接受者
- 源MAC地址:6个字节,指明帧的发送者
- 类型/长度:2个字节,0-1500保留为长度域值,1536-65535保留为类型域值(0x0600-0xffff),通过wireshark抓包看到的,这2个字节指明帧中数据的协议类型,比如常见的IPv4中ip协议采用0x0800
- 数据:46~1500个字节,包含了上层协议传递下来的数据,如果加入数据字段后帧长度不够64字节,会在数据字段“填充至46字节”以使整个帧达到64字节(除去前导码和帧开始符的8个字节,包含帧尾FCS),即6+6+2+46+4=64
- 帧校验序列:4个字节,对接收网卡(主要是检测数据字段)提供判断是否传输错误的一种方法,如果发现错误,丢弃此帧。目前最为流行的用于FCS的算法是循环冗余校验(cyclic redundancy check –CRC)

备注:除去前导码和帧开始符,也可称为mac帧头,其定义如下所示,wireshark抓包一般看不到FCS,mac帧头都可以看到

typedef struct _MAC_FRAME_HEADER
{
 char m_cDstMacAddress[6];    //目的mac地址
 char m_cSrcMacAddress[6];    //源mac地址
 short m_cType;            //上一层协议类型,如0x0800代表上一层是IP协议,0x0806为arp
}__attribute__((packed))MAC_FRAME_HEADER,*PMAC_FRAME_HEADER;

typedef struct _MAC_FRAME_TAIL
{
 unsigned int m_sCheckSum;    //数据帧尾校验和
}__attribute__((packed))MAC_FRAME_TAIL, *PMAC_FRAME_TAIL;

IP帧

  • 上面说到的数据字段是上层协议传递下来的数据,而最常见的上层协议便是ip协议。
  • IP协议是TCP/IP协议族中最为核心的协议。它提供不可靠、无连接的服务,也即依赖其他层的协议进行差错控制。在局域网环境,IP协议往往被封装在以太网帧中传送。而所有的TCP、UDP、ICMP、IGMP数据都被封装在IP数据报中传送
  • ip帧的格式如下:
  • Version:版本,4位,用来表明IP协议实现的版本号,当前一般为IPv4,即0100,IPv6的为0110。这个字段确保可能运行不同IP版本的的设备之间的兼容性
  • IHL:报头长度,4位,以32比特的字(即4字节)来定义IP首部的长度,包括可选项。若该字段的值是5,即5*32=160比特=20字节。此字段最大值为60(15*32/8=60)字节,没有任何选项的ip头部为20字节
  • TOS:服务类型,8位,用于携带提供服务质量特征信息的字段,服务类型字段声明了数据报被网络系统传输时可以被怎样处理。其中前3比特为优先权子字段(Precedence,现已被忽略,各种终端都不采用)。第8比特保留未用。第4至第7比特分别代表延迟、吞吐量、可靠性和花费。当它们取值为1时分别代表要求最小时延、最大吞吐量、最高可靠性和最小费用。这4比特的服务类型中只能置其中1比特为1。可以全为0,若全为0则表示一般服务。例如:TELNET协议可能要求有最小的延迟,FTP协议(数据)可能要求有最大吞吐量,SNMP协议可能要求有最高可靠性,NNTP(Network News Transfer Protocol,网络新闻传输协议)可能要求最小费用,而ICMP协议可能无特殊要求(4比特全为0)。实际上,大部分主机会忽略这个字段,但一些动态路由协议如OSPF(Open Shortest Path First Protocol)、IS-IS(Intermediate System to Intermediate System Protocol)可以根据这些字段的值进行路由决策。
  • Total Length:总长度,16位,指明整个数据报的长度,按字节为计算。最大长度为65535(2^16=65536)字节
  • Identification:标识,16位,用来唯一地标识主机发送的每一份数据报。IP软件会在存储器中维持一个计数器,每产生一个数据段,计数器就加1,并将此值赋给标识字段。但这个“标识”并不是序号,因为IP是无连接服务,数据报不存在按序接收的问题。如数据报由于超过网络的MTU而必须分片时,这个标识字段的值就被复制到所有的数据报的标识字段中。相同的标识字段的值使分片后各数据报片最后能正确的重装成为原来的数据报
  • Flags:标志,3位,分别是(RF, DF, MF),目前只有DF, MF有效。DF(don’t fragment),置为0时表示可以分段,置为1是不能被分段;MF(more fragment),置为0时表示该数据段为最后一个数据段,置为1时表示后面还有被分割分段
  • Fragment offset:段偏移量,13位,指出较长的分组在分段后,某段在原分组的相对位置。也就是说相对用户字段的起点,该片从何处开始。段偏移以8个字节(有3位被flags占据)为偏移单位。这就是,每个分片的长度一定是8字节(64位)的整数倍
  • Time to live:生存期(TTL),8位,用来设置数据报最多可以经过的路由器数。由发送数据的源主机设置,通常为32、64、128等。每经过一个路由器,其值减1,直到0时该数据报被丢弃
  • Protcol:协议,8位,指明ip数据字段中的数据采用上层什么协议封装的。常见的有ICMP(1)、IGMP(2)、TCP(6)、UDP(17)
  • Header Checksum:头部校验和,16位,填充根据IP头部计算得到的校验和码。计算方法是:对头部中每个16比特进行二进制反码求和,和ICMP、IGMP、TCP、UDP不同,IP不对头部后的数据进行校验
  • Source Address:源ip地址,32位,如(192.168.1.2)
  • Destination Address:目的ip地址,32位,如(192.168.1.3)
  • Option:选项,n*32位。用来定义一些可选项:如记录路径、时间戳等。但这些选项很少被使用,同时并不是所有主机和路由器都支持这些选项。可选项字段的长度必须是32比特的整数倍,如果不足,必须填充0以达到此长度要求。根据报头长度(IHL)可以得到option的长度
  • Data:数据,不定长度,但受限于数据报的最大长度(65535)。这是在数据报中要传输的数据。它是一个完整的较高层报文或报文的一个分片

备注:IP帧头定义如下所示

typedef struct _IP_HEADER 
{
 char m_cVersionAndHeaderLen;       //版本信息(前4位),头长度(后4位)
 char m_cTypeOfService;            // 服务类型8位
 short m_sTotalLenOfPacket;        //数据包长度
 short m_sPacketID;              //数据包标识
 short m_sSliceinfo;               //分片使用
 char m_cTTL;                  //存活时间
 char m_cTypeOfProtocol;          //协议类型
 short m_sCheckSum;             //校验和
 unsigned int m_uiSourIp;          //源ip
 unsigned int m_uiDestIp;          //目的ip
} __attribute__((packed))IP_HEADER, *PIP_HEADER;

TCP帧

  • TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。当应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,TCP则把数据流分割成适当长度的报文段,最大传输段大小(MSS)通常受该计算机连接的网络的数据链路层的最大传送单元(MTU)限制。之后TCP把数据包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。
  • TCP是一种可靠的、面向连接的字节流服务。源主机在传送数据前需要先和目标主机建立连接。然后,在此连接上,被编号的数据段按序收发。同时,要求对每个数据段进行确认,保证了可靠性。如果在指定的时间内没有收到目标主机对所发数据段的确认,源主机将再次发送该数据段。
  • tcp帧的格式如下:
  • src port:源端口,2个字节,0-65535之间的任意端口,一般由基于TCP应用程序的用户进程随机选择1023-65535间的端口
  • dst port:目的端口,2个字节,指明接收者所用的端口号,一般由应用程序来指定
  • Sequence number:顺序号,4个字节,用来标识从 TCP 源端向 TCP 目的端发送的数据字节流,它表示在这个报文段中的第一个数据字节的顺序号。如果将字节流看作在两个应用程序间的单向流动,则 TCP 用顺序号对每个字节进行计数。序号是 32bit 的无符号数,序号到达 (2^32) - 1 后又从 0 开始。当建立一个新的连接时, SYN 标志变 1 ,顺序号字段包含由这个主机选择的该连接的初始顺序号 ISN( Initial Sequence Number )
  • Acknowledgement number:确认号,4个字节,包含发送确认的一端所期望收到的下一个顺序号。因此,确认序号应当是上次已成功收到数据字节顺序号加 1 。只有 ACK 标志为 1 时确认序号字段才有效
  • Offset:报头长度,4位,给出报头中 32bit 字的数目。需要这个值是因为任选字段的长度是可变的。这个字段占 4bit , 即TCP 最多有 60(15*4) 字节的首部,没有任何选项的tcp头部长度为20字节
  • Resrvd:保留区域,6位,保留给将来使用,目前必须置为0
  • Control Flags:(6位)控制位包括
    • URG:为 1 表示紧急指针有效,为 0 则忽略紧急指针值
    • ACK:为 1 表示确认号有效,为 0 表示报文中不包含确认信息,忽略确认号字段
    • PSH:为 1 表示是带有 PUSH 标志的数据,指示接收方应该尽快将这个报文段交给应用层而不用等待缓冲区装满
    • RST:用于复位由于主机崩溃或其他原因而出现错误的连接。它还可以用于拒绝非法的报文段和拒绝连接请求。一般情况下,如果收到一个 RST 为 1 的报文,那么一定发生了某些问题
    • SYN:同步序号,为 1 表示连接请求,用于建立连接和使顺序号同步( synchronize )
    • FIN:用于释放连接,为 1 表示发送方已经没有数据发送了,即关闭本方数据流
  • Window Size:窗口大小,2个字节,表示从确认号开始,本报文的源方可以接收的字节数,即源方接收窗口大小。窗口大小是一个 16bit 字段,因而窗口大小最大为 65535(2^16 - 1),用于流控
  • Checksum:校验和,2个字节,对整个的 TCP 报文段(包括 TCP 头部和 TCP 数据),以 16 位字进行计算所得。这是一个强制性的字段,要求由发送端计算和存储,并由接收端进行验证
  • Urgent Pointer:紧急指针,2个字节,是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。 只有当URG 标志置 1 时紧急指针才有效
  • Option and Pad:选项和填充,n*4字节,常见的可选字段是最长报文大小 MSS(Maximum Segment Size) 。每个连接方通常都在通信的第一个报文段(为建立连接而设置 SYN 标志的那个段)中指明这个选项,它指明本端所能接收的最大长度的报文段。选项长度不一定是 32 位字的整数倍,所以要加填充位,使得报头长度成为整字数,通过offset报头长度可以得到option的长度,可能包括”窗口扩大因子”、”时间戳”等选项
  • Data:数据,不定长度,为上层协议封装好的数据

备注:TCP帧头及option定义如下所示

typedef struct _TCP_HEADER 
{
 short m_sSourPort;              // 源端口号16bit
 short m_sDestPort;              // 目的端口号16bit
 unsigned int m_uiSequNum;         // 序列号32bit
 unsigned int m_uiAcknowledgeNum;  // 确认号32bit
 short m_sHeaderLenAndFlag;        // 前4位:TCP头长度;中6位:保留;后6位:标志位
 short m_sWindowSize;            // 窗口大小16bit
 short m_sCheckSum;              // 检验和16bit
 short m_surgentPointer;           // 紧急数据偏移量16bit
}__attribute__((packed))TCP_HEADER, *PTCP_HEADER;

typedef struct _TCP_OPTIONS
{
 char m_ckind;
 char m_cLength;
 char m_cContext[32];
}__attribute__((packed))TCP_OPTIONS, *PTCP_OPTIONS;

option选项补充说明
1. kind(8bit)+Length(8bit,整个选项的长度,包含前两部分)+内容(如果有的话)
2. KIND = 1表示 无操作NOP,无后面的部分
3. KIND = 2表示 maximum segment 后面的LENGTH就是maximum segment选项的长度(以byte为单位,1+1+内容部分长度)
4. KIND = 3表示 windows scale 后面的LENGTH就是 windows scale选项的长度(以byte为单位,1+1+内容部分长度)
5. KIND = 4表示 SACK permitted LENGTH为2,没有内容部分
6. KIND = 5表示这是一个SACK包 LENGTH为2,没有内容部分
7. KIND = 8表示时间戳,LENGTH为10,含8个字节的时间戳

补充tcp的三次握手(建立连接),四次挥手(释放连接)

三次握手:
1. 客户端发送一个 SYN 报文段( SYN 为 1 )指明客户端打算连接的服务器的端口,以及初始顺序号( ISN ) (客户端—-》服务端)
2. 服务器发回包含服务器的初始顺序号( ISN )的 SYN 报文段( SYN 为 1 )作为应答。同时,将确认号设置为客户的 ISN 加 1 以对客户的 SYN 报文段进行确认( ACK 也为 1 )(服务端—-》客户端)
3. 客户端必须将确认号设置为服务器的 ISN 加 1 以对服务器的 SYN 报文段进行确认( ACK 为 1 ),该报文通知目的主机双方已完成连接建立(客户端—-》服务端)

四次挥手:
1. 客户端发送一个FIN(FIN为1),用来关闭客户端到服务器的数据传送 (客户端—-》服务端)
2. 服务器收到这个FIN,它发回一个ACK(ACK为1),确认序号为收到的序号加1 (服务端—-》客户端)
3. 服务器关闭与客户端的连接,发送一个FIN给客户端 (服务端—-》客户端)
4. 客户端发回ACK报文确认,并将确认序号设置为收到序号加1 (客户端—-》服务端)

四次挥手的目的在于如果客户端因为数据发送完毕而想要关闭,便发送FIN。服务端收到FIN后,但可能还存在数据需要发给客户端,所以服务端先发ACK作为应答。当服务端也发送完毕之后,再发回FIN作为关闭连接。客户端收到FIN后,发送ACK,然后关闭连接。

UDP帧

  • UDP协议全称是用户数据报协议(User Datagram Protocol),在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。由于udp传输不是可靠性服务的,所以帧结构较为简单,而且处理,发送速率高,所以经常被用作音频、视频和普通数据的传输协议,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
  • UDP是一种不可靠的、无连接的数据报服务。源主机在传送数据前不需要和目标主机建立连接。数据被冠以源、目标端口号等UDP报头字段后直接发往目的主机。这时,每个数据段的可靠性依靠上层协议来保证。在传送数据较少、较小的情况下,UDP比TCP更加高效。
  • udp帧的格式如下:
  • src port:源端口,2个字节,作用与TCP数据段中的端口号字段相同,用来标识源端和目标端的应用进程
  • dst port:目的端口,2个字节,指明接收者所用的端口号,一般由应用程序来指定
  • Length:数据长度,2个字节,指明了包括首部在内的UDP报文段长度
  • Checksum:检验和,2个字节,指整个UDP报文头和UDP所带的数据的校验和(也包括伪报文头)。伪报文头不包括在真正的UDP报文头中,但是它可以保证UDP数据被正确的主机收到了,和TCP不同的是,对UDP来说,此字段是可选项,而TCP数据段中的校验和字段是必须有的
  • Data:数据字段,不定长度,为上层协议封装好的数据

http帧

  • http属于应用层协议,自由度更高,是面向文本的,报文中的每一个字段都是一些ASCII码串,各个字段的长度是不确定的。报文类型可以分为两种:请求报文和响应报文。
  • http请求帧的格式如下:
  • 写成段式的话是:
<request-line>
<headers>
<blank-line>
<request-body>
  • 请求行
    请求行包括了请求方法、URL、协议版本,它们之间用空格分隔,且都不定长度,所以我们输入的URL是不允许带有空格的。请求方法包括,常用的POST(将表单数据存入请求体里面,多数用于上传数据), GET(将请求参数都放置在URL+?后,参数之间用&连接,用于获取数据), HEAD(服务端只返回响应头,所以处理响应速度快,用于检测请求是否可用)。
  • 请求头
    每一行以键/值的形式写入,键值间用:分割,多个值之间以;分割,每行以回车符换行符为结束。常见的键包括,User-Agent:产生请求的浏览器类型;Accept:客户端可识别的内容类型列表;Host:请求的主机名,允许多个域名同处一个IP地址;Range:指定请求实体的一个或者多个子范围,采用多线程下载时可以设置该键。要注意请求头与请求体间的一个空行,它表示通知服务端没有更多请求头了,下面的都是请求体。
  • 请求体
    请求数据不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。
  • http响应帧的格式如下:
  • 写成段式的话是:
<status-line>
<headers>
<blank-line>
<request-body>
  • 状态行
    状态包括协议版本,状态码,状态码描述,常见的一个状态行的例子是( HTTP/1.1 200 OK ),200表示请求正常,更多的状态码可以查有关资料。
  • 响应头
    与请求头类似,通过键/值的形式向客户端传递关键消息,常见的有:Content-Type:用于向接收方指示实体的介质类型;Content-Range:用于向接收方指示实体的传送范围;Content-Length:用于向接收方指示实体的传送长度;Date:传送时系统的日期与时间。
  • 响应体
    服务端真正返回的文本数据,如果客户端请求一个网页的话,该数据段将填充请求的html文本。给一个响应头的例子:
HTTP/1.1 200 OK  
Date: Thu, 28 Apr 2016 23:59:59 GMT  
Content-Type: text/html;charset=ISO-8859-1  
Content-Length: 122  
<html>  
<head>  
<title>Test</title>  
</head>  
<body>  
<p>hello</p>  
</body>  
</html> 

猜你喜欢

转载自blog.csdn.net/cpyname/article/details/78500207