主机和网关(路由器)的本质区别在于主机从不把数据报从一个接口转发到另一个接口,而网关(路由器)则要转发数据报

当今大多数用户系统,IP层既可以配置为网关(路由器)的功能,也可以配置为主机的功能。

IP路由选择

在一般情况下,IP层可以发送本地生成的数据报(生成来源为TCP、UDP、ICMP以及IGMP),也可以转发数据报(网络接口接收到的)。

IP层在内存中维护有一个路由表。当收到一份数据报并进行发送时,都要对该表搜索一次。

当IP层收到来自某个网络接口的数据报时,IP层会首先检查数据报的目的地址是否为当前主机的IP地址之一或IP广播地址

  1. 如果是,数据报就被送到由IP首部协议字段所指定的协议模块进行处理。
  2. 如果不是,则要进行更进一步的判断,查看IP层是否被设置为网关(路由器)的功能
    1. 如果未设置,数据报被丢弃。
    2. 如果已设置,就会对数据报进行转发,转发原理如下:
      1. 搜索路由表,寻找能与数据报目的IP地址完全匹配的条目(网络号和主机号都匹配,即主机地址)。如果找到,则将报文发送该条目指定的下一站路由器或者直连的网络接口(取决于标志字段的值)。
      2. 搜索路由表,寻找能与目的网络号相匹配的条目(即网络地址)。同理,如果找到则将报文发送该条目指定的下一站路由器或者直连的网络接口(取决于标志字段的值)。
      3. 搜索路由表,寻找标为“默认(default)”的条目。如果找到,则把报文发送给该条目指定的下一站路由器。
      4. 如果1、2、3都不行,则向生成数据报的应用程序返回“主机不可达”或“网络不可达”错误。

路由表参数说明

netstat -rnroute -n命令都可以输出Linux环境的路由表信息,示例如下:

$ ifconfig
br-d384c85c5d7a: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
        ether 02:42:ba:2a:f5:b8  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:9a:b1:a7:ea  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.62.129  netmask 255.255.255.0  broadcast 192.168.62.255
        inet6 fe80::4e2c:72f3:2ac7:4a41  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:c4:dd:51  txqueuelen 1000  (Ethernet)
        RX packets 242  bytes 81175 (81.1 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 245  bytes 46680 (46.6 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 134  bytes 11914 (11.9 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 134  bytes 11914 (11.9 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.62.2    0.0.0.0         UG    100    0        0 ens33
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 ens33
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-d384c85c5d7a
192.168.0.102   192.168.62.2    255.255.255.255 UGH   0      0        0 ens33
192.168.62.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33

内核路由表参数说明如下:

参数说明
Destination目的主机或网段,比如上述192.168.0.102就是目的主机地址,主机号为0的为目的网段,全0的表示默认地址(默认路由)。
Gateway网关IP地址,如果不设置,则为“*”。直连主机或网络值为全0。
Genmask标识目的主机或网段的掩码,如果是目的主机则为255.255.255.255;如果是默认路由则为0.0.0.0
Flags路由标志,下面详细列出取值范围。
Metric路由距离,到达指定主机或网络所需的中转数。
Ref指明正在使用该路由的活动进程个数。Linux中不可用。
Iface该路由对应的用于转发数据报的网络接口。

Flags参数说明如下:

Flags说明
U表示该路由是启用状态。
G表明该路由是到一个网关(即需要一个外部网关来传递数据报)。用于区分间接路由和直接路由。如果没有设置该标志,说明目的主机或网段是和当前主机相连的。
H表明该路由是到一个主机(IP地址主机号不为0)。用于区分目的地是主机还是网络。如果没有该标志,则说明该路由是到一个网络。
D该路由是由重定向报文或后台进程创建的。
M该路由已被重定向报文或后台进程修改。
!拒绝路由。

路由种类

主机路由

目的地是主机或目的地址是主机地址的路由。

该路由带有H标志。

该路由的目的地址的主机号不为0,并且网络掩码为255.255.255.255

示例如下:

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.0.102   192.168.62.2    255.255.255.255 UGH   0      0        0 ens33

在该示例中,当前主机将数据报通过网关192.168.62.2发送到主机192.168.0.102上。

网络路由

目的地为一个网段,表明当前主机可以到达的网络。

目的地址的主机号为0,具体指定的网段由目的地址和网络掩码组合而成。

示例如下:

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-d384c85c5d7a
192.168.62.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33

在示例中

  1. 根据目的地址和网络掩码可以确定,3条路由指定的网段分别为172.17.0.0~172.17.255.255172.18.0.0~172.18.255.255以及192.168.62.0~192.168.62.255
  2. 根据标志可以推断,没有标志H表明这是一个网段;没有G表明这是直连路由(通过上面ifconfig命令的输出结果可以佐证)。

默认路由

目的地址为全0或者default时。

默认路由的标志为G,网络掩码为全0。

示例如下:

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.62.2    0.0.0.0         UG    100    0        0 ens33

配置静态路由

Linux下路由配置主要使用route命令,用法如下:

route [-CFvnNee] [-A family |-4|-6]
route  [-v] [-A family |-4|-6] add [-net|-host] target [netmask Nm] [gw Gw] [metric N] [mss M] [window W] [irtt I] [reject] [mod] [dyn] [reinstate] [[dev] If]
route  [-v] [-A family |-4|-6] del [-net|-host] target [gw Gw] [netmask Nm] [metric M] [[dev] If]
route  [-V] [--version] [-h] [--help]
参数说明
-n以数字形式显示路由表
del删除1个路由
add添加1个路由
target目的主机或网络地址(可以是IP地址或网络名)
-net目的地是1个网络
-host目的地是1个主机
netmask NM网络掩码,用于区分目的地址的网络掩码
gw GW转发数据报的网关
def if将路由强制关联到某个网络接口

示例如下:

# 添加访问127.0.0.0网段的路由,并绑定到lo接口
$ route add -net 127.0.0.0 netmask 255.0.0.0 metric 1024 dev lo
# 通过网络接口eth0访问192.56.76.x网段
$route add -net 192.56.76.0 netmask 255.255.255.0 metric 1024 dev eth0
# 删除路由
$route del -net 192.56.76.0 netmask 255.255.255.0
$route del default
# 拒绝访问到10.0.0.0网段
$route add -net 10.0.0.0 netmask 255.0.0.0 metric 1024 reject
# 添加IPv6路由,通过直连的eth0来进行访问
$route -6 add 2001:0002::/48 metric 1 dev eth0