IP协议协议--IP路由

《Linux高性能服务器编程》阅读笔记:

  简单来说,路由用于决定将数据报发送到目标机器的所经路径。它是IP协议的一个核心任务,即发生在TCP/IP四层模型中的网络层。确切的说,是发生在网络层的IP模块。

1. IP模块工作流程

  操作系统内核中的IP模块的工作流程如下图概括:
IP协议协议--IP路由_第1张图片

  绿色箭头表示IP数据报的数据走向:
  (1) IP模块接收到来自数据链路层的IP数据报后,对其头部执行CRC校验,确认无误后分解析其头部信息
  (2) 若该IP数据报的头部信息的可选项信息设置了源站选路选项(松散源路由选择/严格源路由选择),或者该IP数据包并非发送给本机,则IP模块调用数据报转发子模块来处理该数据报;若该IP数据报的头部中的目的IP地址为本机的某个IP地址,或者目的地址是广播地址,则根据IP数据报头部中的协议字段来决定将该报派发往哪个上层应用
  (3) 数据报转发子模块首先检查系统是否允许转发,若不允许则该IP数据报被丢弃;若允许则数据转发子模块对其执行相关操作后,将其交付输出子模块

  IP数据报应该发送至哪一个下一跳路由或者目标机器,以及经过哪张网卡来发送,这就是IP路由的过程,即图中的计算下一跳路由子模块。IP模块实现数据IP路由的核心数据结构是路由表。路由表是数据报的目标IP地址分类的依据,同一类型的IP地址的IP数据报将被发往相同的下一跳路由器或者目标机器。

  IP数据队列中存放的是所有等待发送的IP数据包,队列中存放着的除了是需要转发的IP数据报外,还包括本机上层应用的IP数据报,如ICMP报文、TCP报文段和UDP数据报(图中蓝色箭头走向)。

2. 路由表

  在Linux操作系统中可以使用route或者netstat命令查看路由表:

iter@iter-virtual-machine:~$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.239.2   0.0.0.0         UG    0      0        0 eth0
192.168.239.0   *               255.255.255.0   U     1      0        0 eth0
iter@iter-virtual-machine:~$ 

  路由表中含有2项,每项由8个字段组成:
IP协议协议--IP路由_第2张图片

  路由项1:
  (1) 目标地址default,即默认的路由项。
  (2) 选项包含“G”标志,说明下一跳是网关,其地址为192.168.239.2,即路由器的本地IP地址。路由器有两个IP地址,WAN是外网IP,一般由网络运营商动态分配。当然也可以是固定的,但需要购买,如服务器网站的IP地址即为固定的。LAN是路由器的固定局域网IP。

  路由项2:
  (1) 目标地址是192.168.239.0,指的是本地局域网。
  (2) 网关地址为*,表示数据报中的目的IP地址被被归类为此类型的IP地址的,该数据包不需要中转,可直接发送到目标机器。

3. IP路由机制

  前面说到,IP模块需要根据IP数据报的目的IP地址来对其分配路由,即给定数据报的目的IP地址,它将匹配路由表中的哪一项。分为3个步骤:
  (1) 查看路由表中和数据报的目的IP地址完全匹配的主机IP地址,若找到就是用该路由项;若找不到则转向步骤(2)
  (2) 查看路由表中和数据报的目的IP地址具有相同网段的IP地址(Gateway选项),若找到则使用该路由项,反之转向步骤(3)
  (3) 选择默认路由项,即数据报的下一跳路由是网关,即交付路由器转发

  所以对该机器而言,所有发送到IP地址为192.168.239.*的的机器的IP数据报都可以直接发送到目标机器,匹配的是路由项2,所有访问因特网(外网)的请求都将网关(路由器的本地IP地址)来转发(匹配路由项1,默认路由项)。

4. 路由表的更新

  IP模块准确、高效的转发IP数据报,依赖于能够更新以反映网络连接的变化路由表:
  (1) 添加主机为192.168.239.145的路由项,这样一来,所以通过本地发送到192.168.239.145机器的IP数据报都将通过eth0直接发送值目标机器的接收网卡

$ sudo route add -host 192.168.239.145 dev eth0

  (2) 删除网络192.168.239.0对应的路由项。前面说到,192.168.239.0表示本地局域网,这样一来,本机将无法访问局域网的任何其他机器,只能访问192.168.239.145机器

$ sudo route del -net 192.168.239.0 netmask 255.255.255.0

  (3) 删除默认路由项,这样做将使本机无法访问因特网

$ sudo route del default

  (4) 重新设置默认路由项,将其网关地址设置192.168.239.145而不是能直接访问因特网的路由器的本地IP地址

$ sudo route add default gw 192.168.239.145 dev eth0

  设置后的路由表结果如下:
IP协议协议--IP路由_第3张图片
注:新的路由表项1的Flags被设置了H标志。

  需要说明的是,通过route命令或者其他工具修改路由表是静态的路由更新方式,对于大型的路由器,它们则通常通过BGP(Border Gateway Protocol,边际网关协议)、RIP(Routing Informatiuon Protocol,路由信息协议)、OSPF等协议来发现路径,并更新自己的路由表,这是动态的、自动的更新方式。

5. IP数据报的转发

  前文提到,IP模块收到的IP数据报若不是发送给本机、或者可选项信息设置了源站选路选项,该数据报将会被交付给数据报转发子模块处理。路由器都能执行数据报的转发操作(这是路由器的基本功能嘛),而主机一般只发送和接收数据报,可以通过修改主机的/proc/sys/net/ipv4/ip_forward参数为1来使能主机的数据报转发功能(该参数默认为0)。在IP地址为192.168.239.145的Ubuntu11.04机器上:

# echo 1 > /proc/sys/net/ipv4/ip_forward

  对于允许IP数据报转发功能的主机或者路由器,其转发操作执行流程如下:
  (1) 检查IP数据报头部信息的TTL值(生存时间),若TTL为0则丢弃数据报
  (2) 查看IP数据报头部可选信息的严格源路由选项,若该选项被设置则检测数据报的目的IP地址是否是本机的某个IP地址,若不是则发送一个ICMP源站选路失败报文给发送端;若有必要会给源端发送一个ICMP重定向报文以告诉源端一个更合理的下一跳路由器
  (3) TTL值减1
  (4) 处理IP头部选项
  (5) 若有必要则执行IP分片操作

6. ICMP重定向

  上文讲到“若有必要会给源端发送一个ICMP重定向报文以告诉源端一个更合理的下一跳路由器”,也就是说ICMP重定向报文也能更新机器的路由表。ICMP重定向的报文格式如下:
IP协议协议--IP路由_第4张图片

  补充一下ICMP协议的基础知识:
  ICMP是网络层中重要的协议,它是IP协议的补充,主要用于检测网络检测。ICMP的前4字节内容是固定的:
  (1) 8位类型字段:用于区分报文类型的,该字段ICMP报文分为两大类,一类是差错报文,主要用来回应网络错误,比如目标地址不可达(类型值为3)和重定向(类型值为5);另一类是查询报文,用来查询网络信息,如ping应用程序就是使用ICMP报文查看目标是否可达(类型值为8)
  (2) 8位代码字段:有的ICMP报文还是用8位代码字段进一步细分不同的条件,如重定向报文使用代码值是0表对网络重定向,代码值为1表对主机重定向
  (3) 16位校验和:校验和对于整个报文(包括头部和内容部分)进行CRC校验以检验报文是否损坏。

  所以可得这里的ICMP报文的类型值为5,代码字段值为1。ICMP重定向报文的数据部分为接收方提供了:
  (1) 应该使用的路由器的IP地址
  (2) 引起重定向的IP数据报的源端IP地址(被包含在原始IP数据报的头部信息中)

  接收主机根据这两个信息就可以知道引起重定向的IP数据报应该使用哪个路由器来转发,并以此更新自身的路由表。通常是更新路由表缓冲而非直接更新路由表。

  另外,一般来说主机只能接收ICMP重定向报文而路由器只能发送ICMP重定向报文:
/proc/sys/net/ipv4/conf/all/send_redirects内核参数指定是否发送ICMP重定向报文
/proc/sys/net/ipv4/conf/all/accept_redirects内核参数指定是否允许接收ICMP重定向报文

iter@iter-virtual-machine:~$ ping www.baidu.com
PING www.a.shifen.com (14.215.177.39) 56(84) bytes of data.
From 192.168.239.145: icmp_seq=1 Redirect Host(New nexthop: 192.168.239.145)
64 bytes from 192.168.239.145: icmp_seq=1 ttl=128 time=6.67 ms
64 bytes from 192.168.239.145: icmp_seq=2 ttl=128 time=6.26 ms
64 bytes from 192.168.239.145: icmp_seq=3 ttl=128 time=6.98 ms
^C

--- www.a.shifen.com ping statistics ---
7 packets transmitted, 7 received, 0% packet loss, time 6009ms
rtt min/avg/max/mdev = 6.264/7.424/11.727/1.771 ms

  从ping命令的输出来看,Ubuntu11.04给Ubuntu14.0发送了一个ICMP重定向报文告诉其通过192.168.239.145访问目标机器,这是更合理的路由方式。当机器收到该ICMP重定向报文后更新其路由表缓冲,并使用新的路由方式发送后续数据报。

你可能感兴趣的:(Linux系统/网络编程,Linux编程)