Pages

Tuesday, 18 June 2019

Linux下的路由工具

net-tools VS iproute2

其实有不少关于这二者的文章。简单地说:iproute2 替代了 net-tools。《精通 Linux 内核网络》这本书提到:net-tools 与内核的交互是由 ioctl 实现的,而 iproute2 则是 netlink,后者提供了更强大的功能。这图不错:
这里主要介绍与路由有关的东西。

route -n

route 的输出与 route -n 并无太大不同,-n 参数经常见到,指的是 numerical,数字化的表示。输出的具体含义不妨 man 一下,OUTPUT 那有详细的解释。值得注意的是:
  1. 还记得上篇中提到的 0.0.0.0 吗?掩码 (Genmask) 为此值则代表默认路由 (default route)。
  2. 网关 (Gateway) 地址为 * 则代表未设置,numerical 显示为 0.0.0.0,为设置就代表分组不需要转发,发送者与接收者在同一个物理网络中咯。
  3. 度量 (Metric),上篇也提到过,值越小优先级越高。

vvl@xdlinux:~$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         202.130.120.254 0.0.0.0         UG    0      0        0 eth1
10.170.72.254   0.0.0.0         255.255.255.255 UH    0      0        0 ppp0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
202.130.120.124 0.0.0.0         255.255.255.224 U     0      0        0 eth1

这么理解上面的输出:
  1. 转发技术采用了下一条方法、特定网络方法与特定主机方法来简化路由表项目;
  2. 此主机有三个接口:eth1、ppp0、docker0;
  3. 与三个物理网络直接相连:202.130.120.124/27、172.17.0.0/16、10.170.72.254/25,其余网络的分组都通过默认网关 (202.130.120.254) 来转发;
  4. Flag 中的 U 代表此路由有效,G 代表采用此路由条目的分组需要经过网关转发, H 代表目标是一个主机而非一个网络。度量 (Metric) 都是最大 ——0,没有优先级的区别;
  5. 至于 Ref 与 Use,没懂。
查看 IPv6 的路由信息使用 route -A inet6,目前,显示的信息并看不太懂。

ip

关于这个,也可以用 manman ipman ip addrman ip route
还有,这文档写得挺好。

ip addr show

ip addr show 的输出内容包含了 ip link show 的内容。更多详细的信息参考这里:链路层网络层。找个实例解释下:
me@vvl:/etc/network$ ip addr
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:16:3c:7e:f5:54 brd ff:ff:ff:ff:ff:ff
    inet 104.160.173.87/27 brd 104.160.173.95 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2001:470:f2aa:0:216:3cff:fe7e:f554/64 scope global mngtmpaddr dynamic
       valid_lft 2591954sec preferred_lft 604754sec
    inet6 2610:150:c004:9::54/108 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::216:3cff:fe7e:f554/64 scope link
       valid_lft forever preferred_lft forever
两个条目,接口设备分别为 lo 与 eth0,前两行的信息是与硬件相关的,即链路层信息。
  1. LOOPBACK —— 环回地址;UP —— 设备启用;LOWER_UP —— 链路层的状态;BROADCAST、MULTICAST —— 广播、多播。
  2. 接着是最大传输单元 (Maximum transmission unit, MTU)、流量控制排队规则 (the traffic control queueing discipline, qdisc)、所属的群组 (group,/etc/iproute2/group 内存储了当前所有的群组,管理之用)、缓冲区传输队列长度 (buffer transmit queue length, qlen)。
  3. link/loopback 代表此接口为环回接口,而 link/ether 则是以太网 (Ethernet)。
  4. 紧跟这的是硬件地址,brd —— broadcast (广播)。有趣的是,全零有时候代表这个硬件地址待填充 (比如 ARP 请求)、网络接口卡 (NIC) 不存或者有毛病,等等,总之就是硬件不正常?环回地址哪来的 NIC 呢?笑~全一代表是本地广播地址 (只被当前网络中的主机接收)。
后面的都是网络层信息了。
  1. inet —— IPv4,inet6 —— IPv6。
  2. scope —— 作用范围。这个 ip route 的输出也能看到。取值:全局 (global)、站点内部 (site,IPv6 专用,已被废弃)、本设备 (link)、主机内部 (host)。
  3. mngtmpaddr —— 我猜是 manage temporary addresses 的缩写,IPv6 专用。此标志代表这个地址是内核创建的一个临时地址,保护隐私用的。关键词:IPv6 Privacy Extensions 、RFC3041
  4. dynamic —— IPv6 专用,代表该地址是动态的。关键词:IPv6 stateless address configuration。
  5. 至于 eth0…
  6. valid_lft —— the valid lifetime of this address,preferred_lft —— the preferred lifetime of this address。

ip route

在谈这之前,需要写写 rt_tables,文件的位置在 /etc/iproute2/rt_tables。

rt_tables

rt_tables 简单来说就是通过给表的命名使得管理简单化。
我们都知道,分组如何传递是需要查找路由表的,但路由表唯一吗?答案是否定的。Linux 内核支持多个路由表,这些路由表由独一无二的非负整数 1 - 255 标记,0 号比较特殊。系统内置了以下的路由表:
  • 255 —— 本地路由表 (local)。由内核维护的一张特殊的路由表,不能由用户自行添加条目。
  • 254 —— 主路由表 (main)。如果没有指明路由所属的表,所有的路由都默认添加到这个表里。route 命令操作的表即是此表。
  • 253 —— 默认路由表 (default)。也是一张特殊的路由表。然,并不知道特殊在哪,而且初始时它是空的。
  • 0 —— unspec。据说操作此表会同时操作其他路由表。[摊手],并不知道如何使用。
非负整数为路由表的优先级,数值越小优先级越高。其实一般只用到 local 与 main 两个路由表。比如查看本地路由表条目:
me@vvl:~$ ip route list table local
broadcast 104.160.173.64 dev eth0  proto kernel  scope link  src 104.160.173.87
local 104.160.173.87 dev eth0  proto kernel  scope host  src 104.160.173.87
broadcast 104.160.173.95 dev eth0  proto kernel  scope link  src 104.160.173.87
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
本地路由表说明了此主机直接与哪些网络相连,以及寻路时路由表对特殊地址的处理方式 (比如本地地址与广播地址)。第一列说明此路由信息是针对本地地址还是本机上托管的广播地址,随后是 IP 地址,接着是目的地可通过哪个接口到达。proto 是 protocol 的缩写,kernel 的含义是这个条目是由内核自动配置的,/etc/iproute2/rt_protos 中有更多的选项。scope 已提到。src,source,暗示内核使用此接口出站的数据包选择哪个 IP 地址作为源地址,经常在一设备多 IP 地址的情况下使用。
ip route 与 ip route show main 等价,显示主路由表的信息。
me@me-U24:~$ ip route
default via 10.177.255.254 dev wlp1s0  proto static  metric 600
10.177.0.0/16 dev wlp1s0  proto kernel  scope link  src 10.177.96.99  metric 600
169.254.0.0/16 dev docker0  scope link  metric 1000
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1
第一条代表默认路由,via 10.177.255.254 的含义是不满足其他条目的数据包传递给网关 10.177.255.254,由它进行转发。第一条与第二条的度量都是 600,目的地在 10.177.0.0/16 网络中的数据包到底采用哪个条目呢?我也不知道…

参考资料

---------------
策略路由
原则型路由 (policy-based routing, PBR) 也称为策略路由 (policy route),是一种决定路由的方式,由网络管理者决定路由原则,再根据这些原则来决定路由。比如如下的两个场景:对所有来自网络 A 的数据包,选择 X 路径;其他的选择 Y 路径;对所有 TOS 为 A 的包选择路径 F,其他选择路径 K。这些路由策略的实现便用到了策略路由。

静态路由与策略路由的区别

为特定的网段指定特定的传输路径,可以采用静态路由的方式。这种办法针对少量的规则还可以轻松应对,但规则一旦增加,麻烦也就接踵而至,网段地址不断变化就必须及时更新路由表,否则… 如果可以根据用户访问进来的路径设定策略路由就会方便很多,而策略路由就是为此而生。

策略路由的种种

策略路由的实现需要使用多路由表 (Multiple Routing Tables),还需要使用规则 (rule)。
规则是策略性的关键性的新的概念。我们可以用自然语言这样描述规则,例如我门可以指定这样的规则:
  • 规则一:“所有来自 192.16.152.24 的 IP 包,使用路由表 10, 本规则的优先级别是 1500” —— 1500: from 192.16.152.24 lookup 10
  • 规则二:“所有的包,使用路由表 253,本规则的优先级别是 32767” —— 32767: from all lookup 32767
我们可以看到,规则包含 3 个要素:
  • 什么样的包,将应用本规则(所谓的 SELECTOR,可能是 filter 更能反映其作用);
  • 符合本规则的包将对其采取什么动作(ACTION),例如用那个表;
  • 本规则的优先级别。优先级别越高的规则越先匹配(数值越小优先级别越高)。
查看当前规则:
me@me-U24:~$ ip rule
0:  from all lookup local
32766:  from all lookup main
32767:  from all lookup default

一个实例:


网络拓扑图如上所示,达成以下目标:网段 192.168.2.0/24 经过路由 R2、R3 到达 R1 (路径为蓝色虚线),而网段 100.64.2.0/24 则仅经过路由 R2 便到达 R1 (路径为绿色实线)。

网络实现

环境为 VirtualBox 中配置的五台虚拟机 (设置启用网络 -> 网卡 -> 高级 -> 混杂模式 -> 允许虚拟电脑)。为了让这些设备互通,需要配置路由信息,静态路由太烦,动态路由~找到了 Quagga 这软件用于配置动态路由。
Quagga 是一个网络路由软件套件,为 Unix 平台,特别是 Linux,Solaris,FreeBSD 和 NetBSD 提供开放最短路径优先(OSPF),路由信息协议(RIP),边界网关协议(BGP)和 IS-IS 的实现。
Quagga 体系结构包括一个核心守护进程 —— zebra,它充当底层 Unix 内核的抽象层,Quagga 客户端利用 Unix 系统或 TCP 协议与 Zserv API 进行通信。正是这些 Zserv 客户端通常实现一个路由协议和通信路由更新到斑马守护进程。现有的 Zserv 实现是:

IPv4IPv6
zebra- kernel interface, static routes, zserv server
ripdripngd- RIPv1/RIPv2 for IPv4 and RIPng for IPv6
ospfdospf6d- OSPFv2 and OSPFv3
bgpd- BGPv4+ (including address family support for multicast and IPv6)
isisd- IS-IS with support for IPv4 and IPv6
externally, not part of Quagga package:
olsrd- OLSR wireless mesh routing through a plugin for olsrd
ldpd- MPLS Label Distribution Protocol (forked from OpenBSD ldpd)
bfdd- Bidirectional Forwarding Detection
必然使用简单的 RIP 协议啦,要注意的是 ripng only support for IPv6 … 先弄好这两个文件:
# /etc/quagga/zebra.conf
hostname net
password net
enable password net

# /etc/quagga/ripd.conf
hostname net
password net
enable password net

#ripd && zebra 启动之, ssh net@127.0.0.1 port 2602 连接到 ripd,配置;)后续的教程就不少了。弄好后,Device 1 与 Device 2 到达 R1 时经过的节点都只有 R2。

策略路由:

root@debian~#echo "200 custom" >> /etc/iproute2/rt_tables #添加新路由表项至 rt_tables
root@debian~#ip rule add from 192.168.2.0/24 lookup custom #指定源为网段 192.168.2.0/24 的分组查找路由表 custom
root@debian~#ip route add default via 100.64.0.3 table custom #设置此路由表中的默认路由

目标达成,路径如拓扑图所示。

喔,写完之后,突然想起一个东西:主机填写网关后,路由表上表现的信息就是增加一默认路由条目
------------------------------------------------------------------

静态路由和策略路由的配置实践

前言

一般在多网卡的网络访问关系中我们通常根据目标 IP 地址段来添加静态路由 (static-routes),在主机系统配置层面这个需求一般都比较简单也不需要使用非常复杂的命令,说实话如果不是因为开发测试中心同事的乱入启发,我也不会发现还有策略路由这样一种灵活通用的配置方法来实现 Linux 多网卡多路由的设定,灰常感谢。
策略路由的出现在某些业务场景下可能更优于静态路由

扩展阅读:

静态路由表和策略路由的区别

通常我们维护静态路由表会手工填写所有 IP 地址段的路由规则,使用命令或者写入配置文件永久生效,先以 Windows/Linux/AIX 常用方法为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#Windows 静态路由 
-- 键入 route -p add [目标] [mask < 网络掩码 & gt;] [网关] [metric < 度量值 & gt;] [if < 接口 & gt;]
route print
route delete
route -p add 172.16.19.0 mask 255.255.255.0 198.15.0.1

#RHEL 静态路由 
vi /etc/sysconfig/network
default via 192.168.3.1 dev eth0
10.211.6.0/24 via 192.168.3.1 dev eth0
10.0.0.0/8 via 10.212.52.1 dev eth1

#CentOS 静态路由 
ip route add 172.16.5.0/24 via 10.0.0.101 dev eth0
vim /etc/sysconfig/network-scripts/route-eth0
172.16.5.0/24 via 10.0.0.101

#SuSE 静态路由 
vim /etc/sysconfig/network/routes
default 192.168.3.1 - -
10.211.6.0 192.168.3.1 255.255.255.0 eth0
10.0.0.0 10.212.52.1 255.0.0.0 eth1

#AIX 静态路由 
smitty mkroute
172.20.14.0/24 gw 172.23.14.254

这种办法针对少量的规则还可以轻松应对,但规则一旦增加麻烦也就接踵而至,网段地址不断变化就必须及时更新路由表,否则其他用户就无法访问。如果可以根据用户访问进来的路径设定策略路由就会方便很多,而 rt_tables 就是为此而生。

Linux 添加静态路由最佳实践

按照 RedHat 官方介绍有三种方式添加永久静态路由,这里只列举最佳方式

临时路由

以下两种方法可以立即生效,但重启后会消失,切记使用场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

#route 命令参数,使用 route 命令,查看本机路由直接输入 route -n 回车即可 
add     增加路由 
del     删除路由 
-net    设置到某个网段的路由 
-host   设置到某台主机的路由 
gw      出口网关 IP 地址 
dev     出口网关 物理设备名 

# 添加路由 
route add -net 192.168.0.0/24 gw 192.168.0.1
route add -host 192.168.1.1 dev 192.168.0.1
# 删除路由 
route del -net 192.168.0.0/24 gw 192.168.0.1
# 添加默认路由 
route add default gw 192.168.0.1

# 使用 ip route 命令和 route 命令类似 
add 增加路由 
del 删除路由 
via 网关出口 IP 地址 
dev 网关出口 物理设备名 

# 添加路由 
ip route add 192.168.0.0/24 via 192.168.0.1
ip route add 192.168.1.1 dev 192.168.0.1
# 删除路由 
ip route del 192.168.0.0/24 via 192.168.0.1
# 增加默认路由 
ip route add default via 192.168.0.1 dev eth0

永久路由

该方法需要重启网络会造成短暂的网络服务中断,但重启后优先级大于 rc.local 方式不会影响 nfs

1
2
3
4
5
6
7
8
9
# 可以通过临时命令立即生效 
route add -net 192.168.3.0/24 gw 192.168.3.254

# 在 / etc/sysconfig/static-routes 文件里添加如下内容 (没有 static-routes 的话就手动建立一个这样的文件)
any net 192.168.3.0/24 gw 192.168.3.254
any net 10.250.228.128 netmask 255.255.255.192 gw 10.250.228.129

# 如果是生产系统可以考虑暂时不重启服务避免网络中断 
service network restart

rt_tables

rt_tables 简单来说就是通过给表的命名使得管理简单化
大部分人习惯直接将路由表优先级号码直接作为表的名称来使用,这样做的好处是非常直观和简明的表达了表所在优先级的位置,但是当表的优先级结构出现变动时,我们对巨大的路由表的修改就显得很烦琐和费事了。
在 / etc/iproute2 / 目录下, 有这么一个文件 rt_tables, 只要对它进行改动,我们将很容易的完成路由表优先级结构的变动。(数值越小优先级别越高)
当路由表的优先级发生变化的时候,我们只需要编辑 / etc/iproute2/rt_tables 这个文件就可以直接改变路由表的优先级次序。

1
2
3
4
5
6
7
8
9
10
11
12
13
cat /etc/iproute2/rt_tables

#
# reserved values
#
255    local
254    main
253    default
0    unspec
#
# local
#
#1    inr.ruhep

Linux 最多可以支持 255 张路由表,其中有 3 张表是内置的:
表 255 本地路由表(Local table) 本地接口地址,广播地址,已及 NAT 地址都放在这个表。该路由表由系统自动维护,管理员不能直接修改。
表 254 主路由表(Main table) 如果没有指明路由所属的表,所有的路由都默认都放在这个表里,一般来说,旧的路由工具(如 route)所添加的路由都会加到这个表。一般是普通的路由。
表 253 默认路由表 (Default table) 一般来说默认的路由都放在这张表,但是如果特别指明放的也可以是所有的网关路由。
表 0 保留

策略性路由应用及分析 (iproute2)

策略性路由
  策略性是指对于 IP 包的路由是以网络管理员根据需要定下的一些策略为主要依据进行路由的。例如我们可以有这样的策略:“所有来直自网 A 的包,选择 X 路径;其他选择 Y 路径”,或者是 “所有 TOS 为 A 的包选择路径 F;其他选者路径 K”。
  Cisco 的网络操作系统 (Cisco IOS) 从 11.0 开始就采用新的策略性路由机制。而 Linux 是在内核 2.1 开始采用策略性路由机制的。策略性路由机制与传统的路由算法相比主要是引入了多路由表以及规则的概念。
多路由表(multiple Routing Tables)
  传统的路由算法是仅使用一张路由表的。但是在有些情形底下,我们是需要使用多路由表的。例如一个子网通过一个路由器与外界相连,路由器与外界有两条线路相连,其中一条的速度比较快,一条的速度比较慢。对于子网内的大多数用户来说对速度并没有特殊的要求,所以可以让他们用比较慢的路由;但是子网内有一些特殊的用户却是对速度的要求比较苛刻,所以他们需要使用速度比较快的路由。如果使用一张路由表上述要求是无法实现的,而如果根据源地址或其它参数,对不同的用户使用不同的路由表,这样就可以大大提高路由器的性能。
规则(rule)
  规则是策略性的关键性的新的概念。我们可以用自然语言这样描述规则,例如我门可以指定这样的规则:
  规则一:“所有来自 192.16.152.24 的 IP 包,使用路由表 10, 本规则的优先级别是 1500”
  规则二:“所有的包,使用路由表 253,本规则的优先级别是 32767”
  我们可以看到,规则包含 3 个要素:
  什么样的包,将应用本规则(所谓的 SELECTOR,可能是 filter 更能反映其作用);
  符合本规则的包将对其采取什么动作(ACTION),例如用那个表;
  本规则的优先级别。优先级别越高的规则越先匹配(数值越小优先级别越高)。

环境配置

服务器 A 和 B 为双网卡,操作系统为 rhel_7.1_64
网卡显示名称IP 地址子网掩码网关备注
ens4f0172.31.192.201255.255.255.0172.31.192.254服务器 A
ens9f0172.31.196.1255.255.255.0172.31.196.254服务器 A
ens4f0172.31.192.202255.255.255.0172.31.192.254服务器 B
ens9f0172.31.196.2255.255.255.0172.31.196.254服务器 B
/172.25.168.44255.255.255.0172.25.168.254接入测试
网络配置,以服务器 A 为例,注意注释默认网关

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cat /etc/sysconfig/network-scripts/ifcfg-ens4f0

DEVICE=ens4f0
ONBOOT=yes
BOOTPROTO=static
TYPE=Ethernet
IPADDR=172.31.192.201
NETMASK=255.255.255.0
#GATEWAY=172.31.192.254

cat /etc/sysconfig/network-scripts/ifcfg-ens9f0

DEVICE=ens9f0
ONBOOT=yes
BOOTPROTO=static
TYPE=Ethernet
IPADDR=172.31.196.1
NETMASK=255.255.255.0
#GATEWAY=172.31.196.254

策略路由配置

注意配置名称一定要吻合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 编辑 rt_tables
echo "192 net_192" >> /etc/iproute2/rt_tables
echo "196 net_196" >> /etc/iproute2/rt_tables

# 清空 net_192 路由表 
ip route flush table net_192
# 添加一个路由规则到 net_192 表,这条规则是 net_192 这个路由表中数据包默认使用源 IP 172.31.192.201 通过 ens4f0 走网关 172.31.192.254
ip route add default via 172.31.192.254 dev ens4f0 src 172.31.192.201 table net_192
# 来自 172.31.192.201 的数据包,使用 net_192 路由表的路由规则 
ip rule add from 172.31.192.201 table net_192

# 清空 net_196 路由表 
ip route flush table net_196
# 添加一个路由规则到 net_196 表,这条规则是 net_196 这个路由表中数据包默认使用源 IP 172.31.196.1 通过 ens9f0 走网关 172.31.196.254
ip route add default via 172.31.196.254 dev ens9f0 src 172.31.196.1 table net_196
# 来自 172.31.196.1 的数据包,使用 net_196 路由表的路由规则 
ip rule add from 172.31.196.1 table net_196

# 添加默认网关 
route add default gw 172.31.192.254

# 如果需要自启动生效可以写进配置文件也可以加入 rc.local
vi /etc/rc.local

ip route flush table net_192
ip route add default via 172.31.192.254 dev ens4f0 src 172.31.192.201 table net_192
ip rule add from 172.31.192.201 table net_192
ip route flush table net_196
ip route add default via 172.31.196.254 dev ens9f0 src 172.31.196.1 table net_196
ip rule add from 172.31.196.1 table net_196
route add default gw 172.31.192.254

# 查看路由表 
route -n

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
169.254.0.0     0.0.0.0         255.255.0.0     U     1006   0        0 ens9f0
169.254.0.0     0.0.0.0         255.255.0.0     U     1008   0        0 ens4f0
169.254.0.0     0.0.0.0         255.255.0.0     U     1014   0        0 br-ex
169.254.0.0     0.0.0.0         255.255.0.0     U     1015   0        0 br-int
172.31.192.0    0.0.0.0         255.255.255.0   U     0      0        0 ens4f0
172.31.196.0    0.0.0.0         255.255.255.0   U     0      0        0 ens9f0

# 在接入测试服务器上验证连通性 
ping 172.31.192.201
ping 172.31.196.1





No comments:

Post a Comment