《计算机网络基础 — 以太网》
《计算机网络基础 — 物理网络》
《计算机网络基础 — TCP/IP 网络模型》
《计算机网络基础 — Linux 内核网络协议栈》
《计算机网络基础 — 虚拟网络》
《计算机网络基础 — Linux 虚拟交换机》
路由(routing)是指数据包从源节点到目的节点过程中,决定端到端路径的行为。路由通常与桥接(Bridging)来对比,它们的主要区别在于桥接发生在 OSI 参考模型的第二层(数据链路层),而路由发生在第三层(网络层)。这一区别使二者在传递信息的过程中使用不同的信息(IP vs MAC),从而以不同的方式来完成其任务。
所有网络设备,无论是主机,路由器还是其他类型的网络节点(e.g. 网络连接的打印机),都需要决定在何处路由 TCP/IP 数据报文。路由表提供了做出这些决策所需的配置信息。类似于下图中非常简单的路由表用于定义典型本地主机可用的单个路由,并确定是否将数据包发送到默认网关路由器。
路由器通过转发三层数据包来实现网络互连。虽然路由器可以支持多种协议(如:TCP/IP、IPX/SPX、AppleTalk 等协议),但是在我国绝大多数路由器都运行着 TCP/IP 协议。路由器通常连接两个或多个由 IP 子网或点到点协议标识的逻辑端口,至少拥有 1 个物理端口。
路由器根据收到数据包中的目的 IP 地址以及路由器内部维护的路由表决定输出端口以及下一跳地址,并且重写数据链路层数据包头实现转发数据包(源 IP 和目标 IP 不发生变化,在网络的每一段传输时,源 MAC 和目标 MAC 发生变化,进行重新封装)。
路由器通过动态维护路由表(自适应路由)来反映当前的网络拓扑,并通过网络上其他路由器交换路由和链路信息来维护路由表。路由器连接着多个不同的网段,连接到同一路由器上的不同网段会被分割成不同的广播域,广播域之间的数据包转发需要路由器来完成。虽然具有 VLAN 功能的交换机也可以分割广播域,但是各广播域之间的通信交流仍然需要借助于路由器。
有两种方式来构建路由表:
R1(config)#ip route 192.168.1.3 255.255.255.255 172.16.0.2
。简单来说,每个 Router 都会连接多个 LAN,如果当前 Router 没有这个 LAN,那么 Router 就应该将数据包 下一跳 到连接这个 LAN 的 Router 上,之间可能隔着多个 Routers。
NOTE:需要注意的是,路由器功能生效的前提是连接一个 LAN 的路由网关接口必须配置了同一网段的网关 IP 地址。笔者经历过使用 DPDK 用户态数据面转发软件的场景,就是因为没有配置网管 IP 所以没有触发数据包的转发动作。无论是传统的路由交换组网场景,还是基于用户态内核旁路技术的自定义网络的组网场景,路由网关都是必要需要存在的。
Linux 本身就具备路由功能,有下述两种开启方式:
echo "1" > /proc/sys/net/ipv4/ip_forward
# vim /etc/sysctl.conf
net.ipv4.ip_forward=1
然后执行指令 sysctl -p
即时生效。
开启了路由功能之后的 Linux 服务器就相当于一个 Router,Linux 服务器的路由表就相当于 Router 的路由表,Linux 服务器上的网卡就相当于 Router Interface 常被作为 Gateway,数据包会根据路由表规则在这些 “网卡” 中选择下一跳。
iptables -t nat -A POSTROUTING -j MASQUERADE
NOTE:对于 Router 所有数据包都是 SNAT,所以不需要配置 DNAT 规则。
命令行下输入 route -n
或 netstat -rn
,就可以打印本机的路由表:
[root@localhost ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.18.22.1 0.0.0.0 UG 0 0 0 br-ex
172.18.22.0 0.0.0.0 255.255.255.0 U 0 0 0 br-ex
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 o-hm0
192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0
字段 | 说明 |
---|---|
Destination | 目的网段(或目的主机),0.0.0.0(或 default)表示默认路由 |
Gateway | 网关地址,0.0.0.0 或 * 表示当前路由记录对应的 Destination 跟本机处于同一个网段,通信时不需要经过网关 |
Genmask | 地址掩码,当路由项为默认路由时会设置为 0.0.0.0,当路由项为主机路由时会设置为 255.255.255.255 |
Flags | 标志,含义参考表格后面的解释 |
Metric | 跃点,到达指定网络所需的中转数(不在 Linux Kernel 中使用) |
Ref | 引用,路由项引用次数(不在 Linux Kernel 中使用) |
Use | 使用,路由项被路由软件查找的次数(不在 Linux Kernel 中使用) |
Iface | 接口 |
Flags 含义:
根据子网掩码的特征,可以将路由分为三种类型:
Destination Gateway Genmask Flags Metric Ref Use Iface
----------- ------- ------- ----- ------ --- --- -----
default 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
Destination Gateway Genmask Flags Metric Ref Use Iface
----------- ------- ------- ----- ------ --- --- -----
10.0.0.10 192.168.1.1 255.255.255.255 UH 0 0 0 eth0
Destination Gateway Genmask Flags Metric Ref Use Iface
----------- ------- ------- ----- ----- --- --- -----
192.19.12 192.168.1.1 255.255.255.0 UN 0 0 0 eth0
使用 ip route show
查看路由表项:
[root@localhost ~]# ip route show | column -t
default via 172.18.22.1 dev br-ex
172.18.22.0/24 dev br-ex proto kernel scope link src 172.18.22.200
192.168.0.0/24 dev o-hm0 proto kernel scope link src 192.168.0.96
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1
解释:
default via 172.18.22.1 dev br-ex
172.18.22.0/24 dev br-ex proto kernel scope link src 172.18.22.200
10.15.150.0/24 via 192.168.150.253 dev enp0s3 proto static metric 1
Linux 中可以自定义 1~252 个路由表,其中系统自身维护了 4 个路由表:
[root@localhost ~]# cat /etc/iproute2/rt_tables
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
查看指定的路由表项目:
ip route list table table_number
e.g.
[root@localhost ~]# ip route list table local
broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
broadcast 172.18.22.0 dev br-ex proto kernel scope link src 172.18.22.200
local 172.18.22.1 dev br-ex proto kernel scope host src 172.18.22.200
local 172.18.22.200 dev br-ex proto kernel scope host src 172.18.22.200
broadcast 172.18.22.255 dev br-ex proto kernel scope link src 172.18.22.200
broadcast 192.168.0.0 dev o-hm0 proto kernel scope link src 192.168.0.96
local 192.168.0.96 dev o-hm0 proto kernel scope host src 192.168.0.96
broadcast 192.168.0.255 dev o-hm0 proto kernel scope link src 192.168.0.96
broadcast 192.168.122.0 dev virbr0 proto kernel scope link src 192.168.122.1
local 192.168.122.1 dev virbr0 proto kernel scope host src 192.168.122.1
broadcast 192.168.122.255 dev virbr0 proto kernel scope link src 192.168.122.1
ip route add default via 172.18.22.1 dev br-ex
NOTE:当 Linux 上物理网卡(e.g. eth0)挂载到了 Linux Bridge(e.g. br-ex)上之后,默认路由的设备应该为 Bridge 设备,因为此时的物理网卡 IP 无效了。
ip route add [目的网段] via [网关] dev [接口] [table ]
e.g. 目标网段为 10.15.150.0/24 的数据包通过接口 enp0s3 转发到网关 192.168.150.253。
ip route add 10.15.150.0/24 via 192.168.150.253 dev enp0s3
ip route del [目标网段]
e.g.
ip route del 10.15.150.0/24