美文网首页
第二章|ip协议

第二章|ip协议

作者: dongshixiao | 来源:发表于2018-03-25 11:07 被阅读0次

    ip协议是tcp/ip协议族的核心协议,也是socket网络编程的基础之一。
    ip头部信息:出现在每个ip数据报中,用于指定ip通信的源端ip地址、目的端ip地址,指导ip分片和重组,以及指定部分通信行为。
    ip数据报的路由和转发:发生在除目标机器之外的所有主机和路由器上,他们决定数据报是否应该转发以及如何转发。

    ip服务的特点

    • ip协议是tcp/ip协议族的动力
      他为上层协议提供无状态、无连接、不可靠的服务。
      a.无状态:是指ip通信双方不同步传输数据的状态信息,因此所有ip数据的发送、传输和接收都是互相独立的、没有上下文关系的。
      缺点是无法处理乱序和重复的ip数据报。
      优点是简单、高效。无须为保持通信的状态而分配一些内核资源。也无需每次传输数据都携带状态信息。
      b.无连接:是指ip通信双方都不长久地维持对方的任何信息,上层协议每次发送数据的时候,都必须明确置顶对方的ip地址。
      c.不可靠:指ip协议不能保证ip数据报准确的达到接收端,他只是承诺尽最大努力。很多情况都会导致ip数据报发送失败。无论哪种情况,发送端ip模块一旦检测到ip数据报发送失败,就通知上层协议发送失败,而不会视图重传。因此,使用ip服务的上层协议(比如tcp协议)需要自己实现数据确认、超时重传等机制已达到可靠传输的目的。

    ipv4头部结构

    ipv4头部结构

    4位版本号:ipv4 值为4
    4位头部长度:标识该ip头部有多少个32bit(4字节),因为4位最大能表示15,所以ip头部长度是60字节。
    8位服务类型:包括3位优先权字段(现已经被忽略),4位TOS字段和1位保留字段(必须置0)。4位TOS字段表示:最小延时,最大吞吐量,最高可靠性和最小费用。其中最多有一个能置为1。应用程序需要根据实际需求来设置他。比如ssh、telent登录程序需要的是最小延时的服务,ftp需要最大吞吐量的服务。
    16位总长度:指的是整个ip数据报的长度,以字节为单位。最大长度位65535(2的16次方-1)字节,但是由于,MTU限制,长度超过MTU的数据报都将被分片传输,所以实际传输的ip数据报的长度都远远没有达到最大值。截下来三个字段描述了如何实现分片。
    16位标识:唯一的表示主机发送的每一个数据报。其初始值由系统随机生成:每发送一个数据报其值就+1。该值在数据分片时被复制到每一个分片中,因此同一个数据报的所有分片都具有相同的标识值。
    3位标志:第一位保留,第二位表示“禁止分片”。如果设置了这个位,ip模块将不对数据报进行分片。在这种情况下,如果ip数据报的长度超过了MTU的话,ip模块将丢弃该数据报并返回一个ICMP差错报文。第三位表示“更多分片”。除了数据报的最后一个分片外,其他分片都置为1
    13位分片偏移:是分片相对原始ip数据报开始处(仅指数据部分)的偏移。实际的偏移值是该值左移三位(乘8)后得到的。由于这个原因,除了最后一个ip分片外,每个ip分片的数据部分的长度必须是8的整数倍(这样才能保证后面的ip分片拥有一个合适的偏移量)。
    8位生存时间:是数据报到达目的地之前允许经过的路由器跳数。TTL值被发送端设置(常见值64)。数据报在转发过程中。没经过一个路由,该值就被路由器-1。当TTL值为0时,路由器将丢失数据报,并向源端发送一个ICMP差错报文。TTL值可以防止数据报陷入路由循环。
    8位协议:用来区分上层协议。/etc/protocols文件定义了所有上层协议对应的prococol字段的数值,其中ICMP是1、TCP是6、UDP是17。
    16头部校验和:由发送端填充,接收端对其使用CRC算法以校验ip数据报头部(仅校验头部)在传输过程中是否损坏。
    32位的源端ip地址和目的端ip地址用来标识数据报的发送端和接收端。一般情况下,这两个地址在整个数据报的传递过程中保持不变,而不论他中间经过多少中转路由器。
    选项:是可变的可选信息,这部分最多包含40字节,因为ip头部最长是60字节(包含前面20字节固定部分)。可用的ip选项包含:1.记录路由:告诉数据报途径所有路由器都将自己的ip地址填入ip头部选项部分,这样我们就可以跟踪数据报的传递路径。2.时间戳:告诉每个路由器都将数据报被转发的时间(或时间与ip地址对)填入ip头部的选项部分,这样就可以测量途径路由之间的数据报传输时间。3.松散源路由选择:指定一个路由器ip地址列表,数据报发送过程中必须经过其中所有的路由器。4.严格源路由选择:和松散源路由选择类似,不过数据报只能经过被指定的路由器。

    使用tcpdump观察ipv4头部结构

    season@ubuntu:~$ sudo tcpdump -ntx -i lo
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
    

    另开终端

    season@ubuntu:~$ telnet 127.0.0.1
    Trying 127.0.0.1...
    Connected to 127.0.0.1.
    Escape character is '^]'.
    Ubuntu 16.04.3 LTS
    ubuntu login: season 
    Password: 
    

    观察tcpdump输出的第一个数据包

    IP 127.0.0.1.59410 > 127.0.0.1.23: Flags [S], seq 2072306840, win 43690, options [mss 65495,sackOK,TS val 190789224 ecr 0,nop,wscale 7], length 0
        0x0000:  4510 003c bdf1 4000 4006 7eb8 7f00 0001
        0x0010:  7f00 0001 e812 0017 7b84 e498 0000 0000
        0x0020:  a002 aaaa fe30 0000 0204 ffd7 0402 080a
        0x0030:  0b5f 3668 0000 0000 0103 0307
    ....
    

    该数据包描述的是一个ip数据报。由于我们是使用telent登录本机,所以ip数据报的源端ip地址和目的端ip地址都是127.0.0.1。telent服务器程序使用的端口号是23。telent客户端程序使用临时端口号59410与服务器通信。
    Flags [S], seq , win , options 都是tcp头部信息
    length指出该ip数据报所携带的应用程序数据的长度。
    tcpdump中 -x 选项 使之输出数据包的二进制码。
    参考表:
    0x0000: 4510 003c bdf1(a5da) 4000 4006 7eb8(96cf) 7f00 0001


    ipv4头部各个字段详解

    ip分片

    MTU:通信术语 最大传输单元(Maximum Transmission Unit,MTU)是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位)

    当ip数据报的长度超过帧的MTU时,他将被分片传输。分片可能发生在发送端,也可能发生在中转路由器上,而且可能在传输过程中被多次分片,但只有在最终的目标机器上,这些分片才会被内核中的ip模块重新组装。

    ip头部中三个字段给ip的分片和重组提供了足够的信息:数据报标识、标志和片偏移。一个数据报的分片都具有自己的ip头部,他们具有相同的标识值,但具有不同的片偏移。并且除了最后一个分片外,其他分片都将设置MF标志。每个分片的ip头部的总长度字段被设置为该分片的长度。

    发送一个1501字节的ip数据报


    携带ICMP报文的ip数据报被分片

    长度位1501字节的ip数据报被拆分成两个ip分片,第一个ip分片的长度位1500字节,第二个ip分片的长度为21字节,每个ip分片都包含自己的ip头部(20字节),且第一个ip分片的ip头部设置了MF标志,而第二个ip分片的ip头部则没有设置该标志,因为他已经是最后一个分片了。原始ip数据报中的ICMP头部内容被完整的复制到了第一个ip分片中,第二个ip分片不包含ICMP头部信息,因为ip模块重组该ICMP报文的时候只需要一份ICMP头部信息,重复传送这个信息没有任何益处。1473字节的ICMP报文数据的前1472字节被ip模块复制到第一个ip分片中,使其总长度位1500字节,从而满足MTU的要求,而多出的最后一个字节则被复制到第二个ip分片中。

    • 使用tcpdump输出ip数据报的两个分片
    season@ubuntu:~$ sudo tcpdump -ntv -i ens33 icmp
    tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
    

    另开终端

    season@ubuntu:~$ ping 192.168.30.109 -c 1 -s 1473
    PING 192.168.30.109 (192.168.30.109) 1473(1501) bytes of data.
    1481 bytes from 192.168.30.109: icmp_seq=1 ttl=64 time=0.192 ms
    
    --- 192.168.30.109 ping statistics ---
    1 packets transmitted, 1 received, 0% packet loss, time 0ms
    rtt min/avg/max/mdev = 0.192/0.192/0.192/0.000 ms
    

    输出信息:

    IP (tos 0x0, ttl 64, id 16003, offset 0, flags [+], proto ICMP (1), length 1500)
        192.168.30.108 > 192.168.30.109: ICMP echo request, id 4019, seq 1, length 1480
    IP (tos 0x0, ttl 64, id 16003, offset 1480, flags [none], proto ICMP (1), length 21)
        192.168.30.108 > 192.168.30.109: ip-proto-1
    
    IP (tos 0x0, ttl 64, id 61550, offset 0, flags [+], proto ICMP (1), length 1500)
        192.168.30.109 > 192.168.30.108: ICMP echo reply, id 4019, seq 1, length 1480
    IP (tos 0x0, ttl 64, id 61550, offset 1480, flags [none], proto ICMP (1), length 21)
        192.168.30.109 > 192.168.30.108: ip-proto-1
    

    这两个IP 分片的标识值都是16003,说明它们是同一个IP数据报的分片。第一个分片的片偏移值为0,而第二个则是1480。很显然,第二个分片的片偏移值实际上也是第一个分片的ICMP报文的长度。第一个分片设置了MF 标志以表示还有后续分片,所以tcpdump输出“flags [+]”。而第二个分片则没有设置任何标志,所tcpdump 输出“flags [none]”。这个两个分片的长度分别为1500字节和21字节。
    最后,IP层传递给数据链路层的数据可能是一个完整的IP数据报,也可能是一个IP分
    片,它们统称为IP 分组(packet)。

    ip模块的工作流程

    ip模块基本工作流程

    从右往左分析:
    当ip模块接收到来自数据链路层的ip数据报时,首先对该数据报的头部做CRC校验,确认无误之后就分析头部的具体信息
    如果设置了源站选路选项(松散源/严格源理由选择)或者不是发送给本机,则ip模块调用数据报转发子模块来处理该数据报。如果数据报是发送给本机,则检测头部协议字段来决定他派给哪个上层应用(分用)。
    数据报转发子模块:首先检测系统是否允许转发,如不允许就讲数据报丢弃。如允许将对数据报执行一些操作,然后将他交给ip数据报输出子模块。
    计算下一跳路由:ip路由的过程,ip数据报应该发送到哪个下一跳(或者目标机器),以及经过哪个网卡来发送。
    ip输出队列:存放的是所有等待发送的ip数据报,其中除了需要转发的ip数据报外,还包括封装了本机上层数据(ICMP报文、TCP报文段和UDP数据报)的ip数据报。

    路由机制

    使用route命令查看路由表

    season@ubuntu:~$ route
    内核 IP 路由表
    目标            网关            子网掩码        标志  跃点   引用  使用 接口
    default         192.168.30.2    0.0.0.0         UG    100    0        0 ens33
    link-local      *               255.255.0.0     U     1000   0        0 ens33
    192.168.30.0    *               255.255.255.0   U     100    0        0 ens33
    
    路由表内容

    ip转发

    上文提到,不是发送给本机的ip数据报将由数据报转发子模块处理。路由器都能执行数据报的转发操作,而主机一般只发送和接收数据报,这是因为主机上的
    内核参数被设置为0

    season@ubuntu:~$ cat /proc/sys/net/ipv4/ip_forward
    0
    

    可以修改为1,使他具有数据报转发功能。
    转发操作:
    a.检查数据报头部的TTL值,如果TTL为0,则丢弃该数据报。
    b.检查数据报头部的严格源路由选项,如果该项被设置,则检测数据报的目标ip地址是否是本机的某个ip地址。如果不是,则发丝冰一个ICMP源站选路失败报文给发送端。
    c.如果有必要,则给源端发送一个ICMP重定向报文,以告诉他一个更合理的下一跳路由器。
    d.将TTL值减一。
    e.处理ip头部选项。
    f.如果有必要,则执行ip分片操作。

    ipv6固定头部结构

    ipv6头部是由40字节的固定头部和可变长的扩展头部(下面介绍)组成


    ipv6固定头部结构

    4位版本号:指定ip协议的版本,ipv6是6。
    8位通信类型:指示数据流通信类型或优先级,和ipv4中的TOS类似。
    20位流标签:是ipv6新增加的字段。用于某些对连接的服务质量有特殊要求的通信,比如音频或视频等实时数据传输。
    16位净荷长度:指的是ipv6扩展头部和应用程序数据长度之和,不包括固定头部长度。
    8位下一个包头:指出紧跟ipv6固定头部后的包头类型,如扩展头或某个上层协议头(比如TCP、UDP或者ICMP),它类似于ipv4头部中的协议字段,且相同的取值有相同的含义。
    8位跳数限制:和ipv4中的TTL含义一样。
    ipv6用128位(16字节)来表示ip地址。
    32位表示ipv4地址一般用点分十进制来表示,而ipv6地址则用十六进制字符串表示。比如:FE80:0000:0000:0000:1234:5678:0000:0012。ipv6用‘:’分割成8组,每组包含2字节,但是这种表示方法过于麻烦,可以使用所谓的零压缩法来将其简写,也就是省略连续的、全零的组。比如上面的例子可以表示位:FE80::1234:5678:0000:0012。不过零压缩法对一个ipv6地址只能使用一次。

    ipv6扩展头部参考表

    ipv6扩展头部

    附:

    TCP/IP:
    数据链路层:ARP,RARP
    网络层: IP,ICMP,IGMP
    传输层:TCP ,UDP,UGP
    应用层:Telnet,FTP,SMTP,SNMP

    OSI:
    数据链路层:Frame Relay, HDLC, PPP, IEEE 802.3/802.2, FDDI, ATM, IEEE 802.5/802.2
    网络层:IP,IPX,AppleTalk DDP
    传输层:TCP,UDP,SPX
    会话层:RPC,SQL,NFS,NetBIOS,names,AppleTalk,ASP,DECnet,SCP
    表示层:TIFF,GIF,JPEG,PICT,ASCII,EBCDIC,encryption,MPEG,MIDI,HTML
    应用层:FTP,WWW,Telnet,NFS,SMTP,Gateway,SNMP

    相关文章

      网友评论

          本文标题:第二章|ip协议

          本文链接:https://www.haomeiwen.com/subject/jwiqcftx.html