7.2 Docker 网络基础
7.2 Docker 网络基础
Docker 本身的技术依赖于近年来Linux内核虚拟化技术的发展,所有Docker对Linux内核的特性有很强的依赖。Docker使用到的与Linux网络有关的主要技术有:网络命名空间(Network Namespace)、Vnet设备对、网桥、iptables和路由。
7.2.1 网络命名空间
为了支持网络协议栈的多个实例,Linux在网络栈中引入了命名空间,这些独立的协议栈被隔离到不同的命名空间中。处于不同命名空间中的网络栈是完全隔离的,彼此无法通信。
在Linux 的网络命名空间中可以有自己独立的路由表及独立的iptables 设置来提供包转发、NAT及IP 包过滤等功能。
为了隔离出独立的协议栈,需要纳入命名空间的元素有进程、套接字、网络设备等。
1. 网络命名空间的实现
为了支持独立的协议栈,相关的这些全局变量都必须被修改为协议栈私有。让这些全局变量成为一个Net Namespace变量的成员,然后协议栈函数调用加入一个Namespace 参数。

在新生成的私有命名空间中只有回环设备(名为 "lo"且是停止状态),其他设备默认都不存在,如果我们需要,则要一一手工建立。Docker窗口中的各类网络栈设备都是Docker Daemon在启动时自动创建和配置的。
所有的网络设备(物理的或虚拟接口、桥等在内核里都叫 Net Device)都只能属于一个命名空间。物理设备通常只能关联到 root 这个命名空间,虚拟网络设备则可以被创建并关联到一个给定的命名空间中,而且可以在这些命名空间之间移动。
让处于不同命名空间的网络相互通信。甚至和外部网络进行通信,使用 Veth设备对。Veth 设备对的一个重要作用就是打通互相看不到的协议栈之间的壁垒,它就像一条管子,一端连着这个命名空间的协议栈,另一端连接另一个网络命名空间协议栈。
2. 网络命名空间的操作
使用 iproue2 系列配置工具中的ip 命令来操作网络命名空间。命令需要使用root 执行
创建一个命名空间
ip netns add <name>
在命名空间中执行命令:
ip netns exec <name> <command>
也可以通过bash 命令进入内部的shell 界面,然后执行各种命令
ip netns exec <name> bash
3. 网络命名空间的实用技巧
我们可以在不同的网络命名空间之间转移设备,在设备里有一个重要属性 NETIF_F_NETNS_LOCAL ,如果这个属性为 on ,就不能被转移到其他命名空间中,Veth设备属于可以转移的设备,而很多其他设备如 :lo设备、vxlan设备、ppp设备、bridge设备等都是不可以转移的,执行转移操作会报错
[root@master ~]# ip netns show
k8s
[root@master ~]# ip link set lo netns k8s
RTNETLINK answers: Invalid argument
如何知道这些设备是否可以转移呢,使用ethtool 工具查看
[root@master ~]# ethtool -k lo | grep netns-local
netns-local: on [fixed]
[root@master ~]# ethtool -k veth2c4886df | grep netns-local
netns-local: off [fixed]
[root@master ~]#
netns-local 的值是 on 不可以转移 ,值是 Off 可以转移 。
7.2.2 Veth 设备对
引入Veth设备是为了在不同命名空间之间通信,利用它可以直接将两个网络命名空间连接起来。由于要连接两个命名空间,所以Veth 设备都是成对出现的,很像一对以太网卡。
1、Veth设备对的操作命令
接下来看看如何创建Veth设备对,如何连接到不同的命名空间,并设备他们的地址,让它们通信。
[root@hadoop1 ~]# ip link show
……
4: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 12:77:87:39:b6:6d brd ff:ff:ff:ff:ff:ff
5: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 6a:32:37:f0:41:89 brd ff:ff:ff:ff:ff:ff
两个设备生成了,一个veth0 ,它的peer 是veth1 。
现在这两个设备都在自己命名空间,将其中一个设备移动到别的命名空间。
[root@hadoop1 ~]# ip netns add netns1 #如果有就不需要创建
[root@hadoop1 ~]# ip link set veth1 netns netns1
这时可在外面这个命名空间再查看设备情况
[root@hadoop1 ~]# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 00:16:3e:01:04:93 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT
link/ether 02:42:5d:97:ee:44 brd ff:ff:ff:ff:ff:ff
5: veth0@if4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 6a:32:37:f0:41:89 brd ff:ff:ff:ff:ff:ff link-netnsid 0
只剩下veth0 设备了,已经看不到 veth1
在netns1 网络命名空间中可以看到veth1 设备,符合预期
[root@hadoop1 ~]# ip netns exec netns1 bash
[root@hadoop1 ~]# ip link show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: veth1@if5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 12:77:87:39:b6:6d brd ff:ff:ff:ff:ff:ff link-netnsid 0
[root@hadoop1 ~]#
现在看到的结果是,两个不同的命名空间各自有一个Veth的“网线头”,各显示为一个Device(在Docker的实现里面,它除了将Veth放入容器内,还将它的名字改成了 eth0)
因为两个网卡现在还没有地址,所以无法通信,接着分配IP地址。
[root@hadoop1 ~]# ip addr add 10.1.1.1/24 dev veth1
[root@hadoop1 ~]# ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: veth1@if5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether 12:77:87:39:b6:6d brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.1.1.1/24 scope global veth1
valid_lft forever preferred_lft forever
[root@hadoop1 ~]#
再启动它们
[root@hadoop1 ~]# ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: veth1@if5: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN qlen 1000
link/ether 12:77:87:39:b6:6d brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.1.1.1/24 scope global veth1
valid_lft forever preferred_lft forever
设置外面的命名空间下的veth0 设备
[root@hadoop1 ~]# ip addr add 10.1.1.2/24 dev veth0
[root@hadoop1 ~]# ip link veth0 up
现在两个网络命名空间可以互相通信了。
[root@hadoop1 ~]# ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from 10.1.1.1: icmp_seq=2 ttl=64 time=0.046 ms
^C
--- 10.1.1.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.046/0.048/0.050/0.002 ms
#
[root@hadoop1 ~]# ip netns exec netns1 ping 10.1.1.2
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.039 ms
64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=0.039 ms
64 bytes from 10.1.1.2: icmp_seq=3 ttl=64 time=0.033 ms
^C
--- 10.1.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.033/0.037/0.039/0.003 ms
至此,我们就能理解Veth设备对的原理和用法了。在Docker 内部,Veth设置对也是连通容器与宿主机的主要网络设备,离开它是不行的。
2、设备对如果查看对端
我们在操作Veth设备对时,有一些实用技巧。
一旦将Veth 设备对对端放入另一个命名空间,在本命名空间中就看不到它了,那么我们怎么知道这个veth 设备的对端在哪里呢,使用ethtool
[root@hadoop1 ~]# ip netns exec netns1 ethtool -S veth1
NIC statistics:
peer_ifindex: 5
[root@hadoop1 ~]# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 00:16:3e:01:04:93 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT
link/ether 02:42:5d:97:ee:44 brd ff:ff:ff:ff:ff:ff
5: veth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT qlen 1000
link/ether 6a:32:37:f0:41:89 brd ff:ff:ff:ff:ff:ff link-netnsid 0
可以看到 5 就是veth0 设备。它们互为peer 。
7.2.3 网桥
网桥是一个二层的虚拟网络设备,把若干个网络接口“连接”起来,以使得网络接口之间的报文能够互相转发。网桥能够解析收发的报文,读取目录MAC 地址的信息,和自己记录的MAC表结合,来决策报文的转发目标网络接口。为了实现这些功能,网桥学习源MAC地址(二层网桥转发的依据就是MAC地址)在转发报文时,网桥只需要向特定网口进行转发,来避免不必要的网络交换。如果它遇到一个自己从未学习到的地址,就无法知道这个报文应该向哪个接口转发,就将报文广播给所有的网络接口(报应来源的网络接口除外)。
当网络拓扑产生变化,设备被移动到另一个端口上,网桥设备无法感知这个变化 ,所以网桥对学习的MAC地址表加上超时时间(默认为5min)。如果网桥收到对应端口MAC地址回发的包,则重置超时时间,否则过了超时时间后,就认为设备已经还在那个端口上了,它会重新广播发送。
Linux 内核支持网口的桥接(目前只支持以太网接口)。但是与单纯的交换机不同。交换机只是一个二层设备,对于接收到的报文,要么转发,要么丢弃。运行着Linux内核的机器本身就是一台主机,有可能是网络报文的目的地,其收到的报文除了转发和丢弃,还可能被送到网络协议栈的上层(网络层),从而被自己(这台主机本身的协议栈)消化,所以我们即可以把网桥看作一个二层设备,也可以把它看作一个三层设备。
1、Linux 网桥的实现
Linux内核通过一个虚拟的网桥设备(Net Device)来实现桥接的。这个虚拟设备可以绑定若干个以太网口设备,从而将它们桥接起来。这种Net Device 网桥和普通的设备不同,它可以有一个IP地址。
网桥设备br0 绑定了 eth0 和 eth1 。对于网络协议栈的上层来说,只看到br0 就行。因为桥接是在数据链路层实现的,上层不需要关心桥接的细节,所以协议栈上层需要发送的报文被送到 br0 ,网桥设备的处理代码判断该转发到 eth0 还是 eth1 ,或者两者皆转发;反过来,从eth0 或从eth1 接收到的报文被提交给网桥的处理代码,在这里会判断报文应该被转发、丢弃还是被提交到协议栈上层。
而有时 eth0,eth1 也可能作为报文的源地址或者目的地址,直接参与报文的发送与接收,从而绕过网桥。
2、网桥的常用操作命令
Docker 自动完成了对网桥的创建和维护
新增一个网桥设备:
brctl addbr xxxxxx
之后可以为网桥增加网口,在Linux 中,一个网口就是一个物理网卡,将物理网卡和网桥连接起来
brctl addif xxxxx ethx
网桥的物理网卡作为一个网口,由于在链路层工作,就不再需要 IP 地址了,这样上面的IP 地址自然失效。
ifconfig ethx 0.0.0.0
给网桥配置一个 IP 地址
ifconfig brxxx xxx.xxx.xxx.xxx
brctl 使用说明
如果没有brctl ,安装一下bridge-utils
Usage: brctl [commands]
commands:
addbr <bridge> add bridge
delbr <bridge> delete bridge
addif <bridge> <device> add interface to bridge
delif <bridge> <device> delete interface from bridge
hairpin <bridge> <port> {on|off} turn hairpin on/off
setageing <bridge> <time> set ageing time
setbridgeprio <bridge> <prio> set bridge priority
setfd <bridge> <time> set bridge forward delay
sethello <bridge> <time> set hello time
setmaxage <bridge> <time> set max message age
setpathcost <bridge> <port> <cost> set path cost
setportprio <bridge> <port> <prio> set port priority
show [ <bridge> ] show a list of bridges
showmacs <bridge> show a list of mac addrs
showstp <bridge> show bridge stp info
stp <bridge> {on|off} turn stp on/off
7.2.4 iptables 和Netfilter
在Linux网络协议栈中有一组回调函数挂接点,通过这些挂接点挂接的钩子函数可以在Linux网络栈处理数据包的过程中对数据包进行一些操作,例如过滤、修改、丢弃等。整个挂接点技术叫作 Netfilter 和 iptables 。
Netfilter 负责内核中执行各种挂载的规则,运行在内核模式中;而iptables 是在用户模式下运行的进程,负责协助和维护内核中netfilter 的各种规则表。二者互相配合来实现整个Linux网络协议栈中灵活的数据包处理机制。
netfilter 可以挂接的规则点有5个
1. 规则表
这些挂接点能挂接的规则也分不同的类型(也就是规则表Table),我们可以在不同类型的Table中加入我们的规则,目前主要支持的Table类型有 RAW、MANGLE、NAT和 FILTER 。
上述4个Table (规则链)的优先级是 RAW 最高,FILTER 最低。
在实例应用中,不同的挂接点需要的规则类型通常不同,例如,在 Input 的挂接点上明显不需要 FILTER 过滤规则,因为根据目标地址已经选择好本机上的上层协议栈了,所以无须再挂接 FILTER 过滤规则。目前Linux 系统支持的不同挂接点能挂接的规则类型如下:
当Linux协议栈的数据处理运行到挂接点时,它会依次调用挂接点所有的挂钩函数,直到数据包的处理结果是明确地接受或者拒绝。
2. 处理规则
每个规则的特性都分为以下几部分。
- 表类型(准备干什么事情)
- 什么挂接点 (什么时候起作用)
- 匹配的参数是什么 (针对什么样的数据包)
- 匹配后有什么动作(匹配后具体的操作是什么)
(1) 匹配的参数
匹配的参数用于对数据包或者TCP 数据连接的状态进行匹配。当有多个条件存在时,它们一起发挥作用,来达到只针对某部分数据进行修改的目的。常见的匹配参数如下: - 流入、流出的网络接口
- 来源、目的地址
- 协议类型
- 来源、目的端口
(2) 匹配后的动作
一旦有数据匹配,就会执行相应的去动作。动作类型既可以是标准的预定义的几个动作,也可以是自定义的模块注册的动作,或者是一个新的规则链,以便更好地组织一组动作。
iptables 命令
iptables 命令用于协助用户维护各种规则。我们在使用 Kubernetes、Docker 的过程中,通常都会去查看相关的Netfilter 配置。
查看系统中已有规则的方法:
iptables-save
: 按照命令的方式打印 iptables 的内容iptables -vnL
: 以另一种格式显示Netfilter 表的内容。
7.2.5 路由
Linux 系统包含一个完整的路由功能,当IP层在处理数据发送或者转发时,会使用路由表来决定发往哪里。
路由功能由IP 层维护的一张路由表来实现。路由表中的数据一般是以条目形式存在的,一个典型的路由表条目通常包含以下主要的条目项:
- 目的IP 地址
- 下一个路由器的IP 地址
- 标志:目的地址是主机地址还是网络地址,标志中可以得出下一个路由器是真实路由器还是相连的接口。
- 网络接口规范
1. 路由表的创建
Linux 的路由表至少包括两个表(当启用策略路由时,还是有其他表): 一个是LOCAL、别一个是MAIN。 在LOCAL表中会包含所有的本地设备地址。LOCAL 路由表是在配置网络设备地址时自动创建的。LOCAL表用于供Linux 协议识别本地地址,以及进行本地各个不同网络接口之间的数据转发。
可以通过下面的命令查看LOCAL表的内容:
local 表的 type 有 local 和 broadcast 类型
main 表没有type
[root@master ~]# ip route show table local type local
local 10.0.2.15 dev enp0s3 proto kernel scope host src 10.0.2.15
local 10.244.0.0 dev flannel.1 proto kernel scope host src 10.244.0.0
local 10.244.0.1 dev cni0 proto kernel scope host src 10.244.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
local 172.17.0.1 dev docker0 proto kernel scope host src 172.17.0.1
local 192.168.200.1 dev enp0s8 proto kernel scope host src 192.168.200.1
#
[root@master ~]# ip route show table local type broadcast
broadcast 10.0.2.0 dev enp0s3 proto kernel scope link src 10.0.2.15
broadcast 10.0.2.255 dev enp0s3 proto kernel scope link src 10.0.2.15
broadcast 10.244.0.0 dev cni0 proto kernel scope link src 10.244.0.1
broadcast 10.244.0.255 dev cni0 proto kernel scope link src 10.244.0.1
broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
broadcast 172.17.0.0 dev docker0 proto kernel scope link src 172.17.0.1
broadcast 172.17.255.255 dev docker0 proto kernel scope link src 172.17.0.1
broadcast 192.168.200.0 dev enp0s8 proto kernel scope link src 192.168.200.1
broadcast 192.168.200.255 dev enp0s8 proto kernel scope link src 192.168.200.1
[root@master ~]#
MAIN 表用于各类网络IP 地址的转发。它的建立既可以使用静态配置完成,也只可以使用动态路由发现协议生成。动态路由发现协议一般使用组播功能来通过发送路由发现数据,动态地交换和获取网络的路由信息,并更新到路由表中。
Linux 下支持路由发现协议的开源软件有许多,常用的有 Quagga
、Zebra
等。
2. 路由表的查看
使用 ip route list 命令查看当前的路由表
[root@master ~]# ip route list
default via 10.0.2.2 dev enp0s3 proto dhcp metric 100
10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15 metric 100
10.244.0.0/24 dev cni0 proto kernel scope link src 10.244.0.1
10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink
10.244.2.0/24 via 10.244.2.0 dev flannel.1 onlink
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.200.0/24 dev enp0s8 proto kernel scope link src 192.168.200.1 metric 101
netstat -nr 是另一个查看路由表的工具
[root@master ~]# netstat -nr
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 10.0.2.2 0.0.0.0 UG 0 0 0 enp0s3
10.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 enp0s3
10.244.0.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
10.244.1.0 10.244.1.0 255.255.255.0 UG 0 0 0 flannel.1
10.244.2.0 10.244.2.0 255.255.255.0 UG 0 0 0 flannel.1
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.200.0 0.0.0.0 255.255.255.0 U 0 0 0 enp0s8
补充: 策略路由
ip rule show
查看策略数据库的内容,即当前系统使用的路由规则
[root@master ~]# ip rule show
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
策略路由由三部分组成:
part1:优先级,也就是上图中的0, 32766, 32767,数字越小优先级越高。
part2:条件,比如from all, from 135.105.115.149
part3:操作,比如lookup main 、 lookup 231
综上:32765: from 135.105.115.149 lookup 231 代表的含义是, 源地址是135.105.115.149的IP包,根据231号路由表进行路由。
- 使用
ip rule show
或cat /etc/iproute2/rt_tables
命令来查看目前使用了哪些路由表 - 使用
ip route show [table id | name]
命令来查看路由表的内容
[root@master ~]# ip rule show
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
[root@master ~]# cat /etc/iproute2/rt_tables
#
## reserved values
#
255 local
254 main
253 default
0 unspec
#
## local
#
#1 inr.ruhep
[root@master ~]# ip route show table main
default via 10.0.2.2 dev enp0s3 proto dhcp metric 100
10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15 metric 100
10.244.0.0/24 dev cni0 proto kernel scope link src 10.244.0.1
10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink
10.244.2.0/24 via 10.244.2.0 dev flannel.1 onlink
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.200.0/24 dev enp0s8 proto kernel scope link src 192.168.200.1 metric 101
在默认情况下,Linux系统创建了4张路由表,这四个路由表的功能如下 :
- 系统保留表:table id 0
- local:table id 255,本地路由表存有本地接口地址,广播地址,以及NAT地址 。由系统自动维护,管理员不能操作此表 。
- main:table id 254,主路由表,使用传统命令route -n所看到的路由表就是main的内容。Linux系统在默认情况下使用这份路由表的内容来传输数据包。正常情况下,只要配置好网卡的网络设置,便会自动生成main路由表的内容。
如上图所示,- 因为我们的设备上有eth0及eth1两块网卡,且为其设置的IP分别是192.168.1.1/24和192.168.2.1/24,因此路由表内的第1行告诉系统,如果有数据包要送到92.168.1.0/24这个网段,就直接将数据包由eth0接口送出即可,而本机临近这个网段的IP是192.168.1.1,第2行同理;以上这两行是只要将计算机网卡上的IP设置好,并在网络服务重启之后,默认就会生成的路由,无需特别的设置,类似与路由器中的直连路由。
- 最后一行是默认路由,表示如果数据包不是送往192.168.1.0/24及192.168.2.0/24的网段时,那么数据包将统一转发给192.168.1.254的主机(一般是路由器)去处理,而192.168.1.254就是我们在网络配置中所设置的默认网关。
- default:table id 253, 默认路由表,这个路由表在默认情况下内容为空 ,一般可将默认路由添加在该表中。
使用 ip route add
命令添加路由到所需的路由表中,route命令默认添加路由到main表,ip命令不指定路由表也默认添加到main表中,使用 ip route del
同理
在添加rule规则时,必须先确定好条件、优先级别及路由表ID,此后才可以执行添加规则的操作。ip rule add
- 条件: 条件是用来决定哪类数据包可以符合这项规则,而可用来匹配的字段为Source IP、Destination IP、Type of Service、fwmark及dev等,这些字段的使用方式如下
- Source IP:根据来源端IP来决定数据包参考哪个路由表发送出去。
- Destination IP: 根据目的端IP来决定数据包参考哪个路由表发送出去。
- dev: 使用数据包输入的接口来作为判断依据
我们希望凡是由eth2接口送入的数据包都由eth0接口转发出去,由eth3接口送入的数据包都由eth1接口转发出去。以下命令组合将能满足我们的要求ip rule add dev eth2 table 1
ip rule add dev eth3 table 3
- 优先级别
前面介绍了规则中条件的使用方式,接下来要讨论的是优先级别。优先级别用数字来表示,其范围由0~4亿多个。 添加规则时,如果没有特别设置优先级别,那么,优先级别默认会从32766开始递减,如32765、32764……,如果我们需要特别设置优先级别,可以在ip rule add命令的最后加上prio XXX参数。 - 路由表id:在Linux的基于策略的路由中,路由表用ID来表示。
注:创建完路由规则若需立即生效须执行以下命令,用以刷新路由缓冲
ip route flush cache
如果在添加路由或者规则的时候指定了 table ,建议提前在 /etc/iproute2/rt_table 中创建table 值,id 越小,优先级越高(0-255)
[root@master ~]# ip route add 1.1.1.1/32 dev enp0s8 table 10
[root@master ~]# ip route show table 10
1.1.1.1 dev enp0s8 scope link
[root@master ~]# ip rule show
0: from all lookup local
32764: from all iif enp0s8 lookup 10
32765: from all lookup main
32767: from all lookup default
删除规则
ip命令提供的删除规则的方式十分灵活,例如,要删除下列第2条规则,可以分别使用“优先级别”、“条件”及“路由表”当中任何一个唯一的值来设置所需删除的规则