网络数据包通过Netfilter时的工作流向

1. 简介

iptables实际上只是位于用户空间的一个面向系统管理员的Linux防火墙的管理工具,而真正实现防火墙功能的是netfilter,它是Linux内核中实现包过滤的内核模块,iptables对应在内核中的模块应该是ip_tables,我们查看系统内核中ip_tables的信息的时候可以看到ip_tables.ko这个模块是在netfilter这个目录下的。

image-20220419122016641

iptables的作用是为包过滤机制的实现提供规则,通过各种不同的规则,告诉netfilter对来自某些源,前往某些目的或具有某些协议特征的数据包应该如何处理,下面这张图很明了的说明了Netfilter和iptables之间的关系

Netfilter和iptables之间的关系

2. iptables的四表五链

为了更加方便的组织和管理防火墙规则,iptables采用了表和链的分层结构

其中,每个规则表相当于内核空间的一个容器,根据规则集的不同用途划分为默认的四个表,在每个表容器内又包括不同的规则链,根据处理数据包的不同时机划分为五种链

2.1 iptables 4表:

表名称 规则含义 包含的链 内核模块
filter 表 用来对数据包进行过滤,具体的规则要求决定如何处理一个数据包。 inputforwardoutput iptable_filter
nat 表 nat 全称:network address translation 网络地址转换,主要用来修改数据包的 IP 地址、端口号信息。 preroutingoutputpostrouting iptable_nat
mangle 表 主要用来修改数据包的服务类型,生存周期,为数据包设置标记,实现流量整形、策略路由等。 preroutinginputforwardoutputpostrouting iptable_mangle
raw 表 主要用来决定是否对数据包进行状态跟踪。 preroutingoutput iptable_raw

raw表只使用在PREROUTING链和OUTPUT链上,因为优先级最高,从而可以对收到的数据包在系统进行ip_conntrack(连接跟踪)前进行处理。一但用户使用了raw表,在某个链上,raw表处理完后,将跳过NAT表和ip_conntrack处理,即不再做地址转换和数据包的链接跟踪处理了。RAW表可以应用在那些不需要做nat的情况下,以提高性能。

应用最多的是filter和nat

2.2 iptables 5链:

在处理各种数据包时,根据防火墙规则的不同介入时机,iptables默认划分为五种不同的规则链:

PREROUTINGINPUTFORWARDOUTPUTPOSTROUTING

链名称 规则含义
prerouting 链 在对数据包做路由选择之前,将应用此链中的规则
input 链 当收到访问防火墙本机地址的数据包时,将应用此链中的规则
forward 链 当收到需要通过防火墙中转发给其他地址的数据包时,将应用此链中的规则,注意如果需要实现forward转发需要开启Linux内核中的ip_forward功能
output 链 当防火墙本机向外发送数据包时,做路由选择之后,将应用此链中的规则
postrouting 链 在对数据包做路由选择之后,将应用此链中的规则

这里需要强调的一点是FORWARD链,它是转发链,也就是说只有在网卡个数>=2的系统中才具有的功能:开启系统转发功能后,当网络层发现数据包并非发给本机时会从另一网卡转发出去。中间经过FORWARD链,FORWARD链上的规则由Filter表、Mangle表读取操作。

2.3 表和链的对应关系

这里写图片描述

3. 包过滤的匹配流程

当一个数据包到达防火墙以后,会优先选择哪一个表、哪一个链中的规则呢?

表的处理优先级:raw>mangle>nat>filter

规则链的应用顺序取决于数据的流向:

入站数据流向PREROUTING路由选择INPUT应用程序

转发数据流向PREROUTING路由选择FORWARDPOSTROUTING

出站数据流向路由选择OUTPUTPOSTROUTING

路由选择时机

规则链内部的处理规则:

按第一条规则……第二条规则的顺序进行匹配处理,遵循“匹配即停止”的原则, 一旦找到一条匹配规则将不再检查后续的其他规则,如果一直找不到匹配的规则,就按默认规则处理。

这里写图片描述

img

这些表并非必须全部使用,是可选的,最常用的是nat,filter

https://s5.51cto.com/oss/202112/07/ad5219a5b27aefe8b7213f1d6c29cbc1.png

3.1 单双网卡图示

来源

双网卡

看图中深蓝色箭头的数据流向,数据包要到达用户层,需要经过PREROUTING链(路由前链)INPUT链(输入链),在这个链路中存放着用户设置的规则,这些规则根据功能不同又会被分组存放在RAW表Mangle表NAT表中。当数据包抵达PREROUTING链时,netfilter程序会依次RAW表Mangle表NAT表中取出针对PREROUTING链的用户规则并执行相应操作;同理,INPUT链上的规则也会被分组存放在Mangle表和Filter表中,netfilter程序会依次从这两个表中取出针对INPUT链设置的用户规则并执行相应操作。(特别强调,转发的数据包不经过 OUTPUT 链)
这里需要强调的一点是FORWARD链,它是转发链,也就是说只有在网卡个数>=2的系统中才具有的功能:开启系统转发功能后,当网络层发现数据包并非发给本机时会从另一网卡转发出去。中间经过FORWARD链,FORWARD链上的规则由Filter表、Mangle表读取操作。对于单网卡的系统中,上图应更改为:

单网卡

3.2 iptables常见情况

关键点在于发往iptables主机的数据包的目的地址是否是iptables主机本机。如果是,那我们就可以理解为常见的开启了iptables防火墙的网站服务器主机;如果不是,那就是走ip_forward进行转发,比如我们常见的NAT路由器的NAT服务和策略路由等。

1
cat /proc/sys/net/ipv4/ip_forward  #查看ip_forward状态

image-20220419134709463

4. iptables的配置

4.1 iptables 的基本语法命令格式

1
iptables [-t 表名] 管理选项 [链名] [匹配条件] [-j 控制类型]
  • 表名链名:指定iptables命令所操作的,未指定表名时将默认使用filter表;
  • 管理选项:表示iptables规则的操作方式,比如:插入增加删除查看等;
  • 匹配条件:指定要处理的数据包的特征,不符合指定条件的数据包不处理;
  • 控制类型:指数据包的处理方式,比如:允许accept拒绝reject丢弃drop日志LOG等;

iptables 管理选项

管理选项 含义 示例
-A 在指定链的末尾添加一条新的规则 iptables -A INPUT
-D 删除指定链中的某一条规则,可删除指定序号或具体内容 iptables -t nat -D INPUT
-I 在指定链中插入一条新规则,原本该位置上的规则会往后顺序移动,没有指定编号则为1 iptables -I INPUT
-R 修改、替换指定链中的某一条规则,可指定规则序号或具体内容 iptables -t nat -R INPUT
-L 列出指定链中所有的规则,未指定链名,则列出表中的所有链 iptables -t nat -L
-F 清空指定链中所有的规则,未指定链名,则清空表中的所有链
-P 设置指定链的默认策略
-n 使用数字形式显示输出结果 iptables -t nat -nvl
-v 查看规则列表时显示详细的信息
-h 查看命令帮助信息
–line-numbers 查看规则列表时,同时显示规则在链中的顺序号
-N或–new-chain 用命令中所指定的名称创建一个新链 iptables -N allowed-chain
-X 或 --delete-chain 如果指定链名,该命令删除这条自定义的链, 如果未指定链名,该命令删除所有自定义的链。此参数用于快速清除所有自定义的链,当然,默认的链无法删除。 iptables -X MY_OWN_chain

iptables 匹配规则:

  • [-i|o 网卡名称]:i是指定数据包从哪块网卡进入,o是指定数据包从哪块网卡输出

  • [-p 协议类型]:可以指定规则应用的协议,包含tcp、udp和icmp等

  • [-s 源IP地址]:源主机的IP地址或子网地址

  • [--sport 源端口号]:数据包的IP的源端口号

  • [-d目标IP地址]:目标主机的IP地址或子网地址

  • [--dport目标端口号]:数据包的IP的目标端口号

  • m:extend matches,这个选项用于提供更多的匹配参数,如:

    • -m state --state ESTABLISHED,RELATED
    • -m tcp --dport 22
    • -m multiport --dports 80,8080
    • -m icmp --icmp-type 8
  • <-j 动作>:处理数据包的动作,包括ACCEPT、DROP、REJECT等

具体实例参考 iptables常用实例备查

协议匹配

-p指定协议名,该通用协议匹配用于检查某些特定协议。 支持的协议有 TCPUDPICMPudplite icmpv6esp ah sctp mh、用逗号分隔的任何这三种协议的组合列表 以及 ALL (用于所有协议)。 ALL 是缺省匹配。可以使用 ! 符号,它表示不与该项匹配。

例1: 不允许任何主机ping本主机(默认在filter链添加规则)

1
2
3
4
5
6
$ iptables -A INPUT -p icmp -j REJECT

$ iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
REJECT icmp -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable

例2:接收除icmp之外的其他连接,!表示取反

1
2
3
4
5
6
$ iptables -A INPUT ! -p icmp -j ACCEPT

$ iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT !icmp -- 0.0.0.0/0 0.0.0.0/0

注意:此时还是可以ping通此机器的,因为定义的规则是接收除icmp之外的其他连接,只要非icmp协议的包就ACCEPT,但并不代表icmp包就要丢弃,实际上对于ICMP包并不会匹配到我们设置的规则,因而会继续寻找下一条规则,表中只有一条规则 所以最终会匹配到默认规则,而默认规则是ACCPET,所以依然被放行了。接下来如果将INPUT链的默认规则改为DROP就ping不通了(INPUT OUTPUT链不能设置默认REJECT):

1
2
3
4
5
6
$ iptables -P INPUT DROP  

$ iptables -nL
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT !icmp -- 0.0.0.0/0 0.0.0.0/0

地址匹配

iptables编写地址匹配的规则时用-s:表示源地址,-d:表示目标地址

例1:不允许192.168.100.200这个主机ping本主机

接口匹配

当本机有多个网卡时,可以使用-i选项去匹配报文是通过哪块网卡流入本机的。

例1:拒绝由网卡ens33流入的ping请求报文

1
2
3
4
5
6
$ iptables -A INPUT -i ens33 -p icmp -j DROP 

$ iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP icmp -- 0.0.0.0/0 0.0.0.0/0

-i 使用限制

-i选项是用于匹配报文流入的网卡的,也就是说,从本机发出的报文是不可能会使用到-i选项的,因为这些由本机发出的报文压根不是从网卡流入的,而是要通过网卡发出的,从这个角度考虑,-i选项的使用是有限制的。

为了更好的解释-i选项,一张iptables全局报文流向图,如下。

img

既然-i选项是用于判断报文是从哪个网卡流入的,那么,-i选项只能用于上图中的PREROUTING链、INPUT链、FORWARD链,这是-i选项的特殊性,因为它只是用于判断报文是从哪个网卡流入的,所以只能在上图中"数据流入流向"的链中与FORWARD链中存在,而上图中的"数据发出流向"经过的链中,是不可能使用-i选项的,比如上图中的OUTPUT链与POSTROUTING链,他们都不能使用-i选项。

-o 使用限制:

​ 理解完-i选项,再来理解-o选项就好办了。当主机有多块网卡时,可以使用-o选项,匹配报文将由哪块网卡流出,没错,-o选项与-i选项是相对的,-i选项用于匹配报文从哪个网卡流入,-o选项用于匹配报文将从哪个网卡流出。

-i选项只能用于PREROUTING链、INPUT链、FORWARD链,那么-o选项只能用于FORWARD链、OUTPUT链、POSTROUTING链。

因为-o选项是用于匹配报文将由哪个网卡"流出"的,所以与上图中的"数据进入流向"中的链没有任何缘分,所以,-o选项只能用于FORWARD链、OUTPUT链、POSTROUTING链中。

FORWARD链属于"中立",它能同时使用-i选项与-o选项。

扩展匹配(端口等)

"源地址"与"目标地址"属于基本匹配条件,而"源端口"与"目标端口"属于扩展匹配条件,上文中介绍到的匹配条件,都属于基本匹配条件。

基本匹配条件可以直接使用,而如果想要使用扩展匹配条件,则需要依赖一些扩展模块,或者说,在使用扩展匹配条件之前,需要指定相应的扩展模块。

使用选项--dport可以匹配报文的目标端口,–dport意为destination-port,即表示目标端口。

使用–dport选项时,必须事先指定了使用哪种协议,即必须先使用-p选项,示例如下:

例1:拒绝192.168.1.146的ssh连接(ssh端口为22)

1
$ iptables -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 22 -j REJECT

-m tcp表示使用tcp扩展模块,–dport表示tcp扩展模块中的一个扩展匹配条件,可用于匹配报文的目标端口。

注意,-p tcp与 -m tcp并不冲突,-p用于匹配报文的协议,-m 用于指定扩展模块的名称,正好,这个扩展模块也叫tcp。

上例中,也可以省略-m选项,iptables会"隐式"的指定扩展模块

当使用-p选项指定了报文的协议时,如果在没有使用-m指定对应的扩展模块名称的情况下,使用了扩展匹配条件, iptables默认会调用与-p选项对应的协议名称相同的模块。

例2:开放ftp访问,冒号表示端口的范围从20-21端口

1
2
3
4
5
[root@firewall ~]# iptables -I INPUT -p tcp --dport 20:21 -j ACCEPT
[root@firewall ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere tcp dpts:ftp-data:ftp

借助tcp扩展模块的–sport或者–dport都可以指定一个连续的端口范围,但是无法同时指定多个离散的、不连续的端口,如果想要同时指定多个离散的端口,需要借助另一个扩展模块,multiport模块

例3:允许开放25,80,110,143端口,以便访问邮件和网站服务

1
2
3
4
5
[root@firewall ~]# iptables -A INPUT -p tcp -m multiport --dport 25,80,110,143 -j ACCEPT
[root@firewall ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere multiport dports smtp,http,pop3,imap

例4:不允许192.168.100.110-192.168.100.150范围的主机经过防火墙转发数据包

1
2
3
4
5
6
7
8
9
[root@firewall ~]# iptables -A FORWARD -p tcp -m iprange --src-range 192.168.100.110-192.168.100.150 -j REJECT
[root@firewall ~]#
[root@firewall ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination
REJECT tcp -- anywhere anywhere source IP range 192.168.100.110-192.168.100.150 reject-with icmp-port-unreachable

状态匹配

编写iptables规则时使用“-m state --state 连接状态”的形式

常用的连接状态:

​ NEW:与任何连接无关的 ,一个连接的第一个报文,例如TCP连接中的SYN报文

​ ESTABLISHED:响应请求或者已经建立连接的,第一个成功穿越防火墙的报文之后所有的报文

​ RELATED:伴随连接的报文,即某个已经处于ESTABLISHED的连接所产生的报文,这些报文不属于第一条连接,但是的确是由第一条连接产生的。与已有连接有相关性,比如ftp数据连接

​ INVALID:无法判断状态的报文

例1:允许响应请求的连接放行

1
2
3
4
5
[root@firewall ~]# iptables -I INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
[root@firewall ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere state ESTABLISHED

https://www.cnblogs.com/wanstack/p/8352484.html

iptables 控制类型:

  • ACCEPT:允许数据包通过
  • DROP:直接丢弃数据包,不给任何回应信息
  • REJECT:拒绝数据包通过,必要时会给数据发送端一个响应的信息。
  • SNAT:源地址转换。在进入路由层面的route之前,重新改写源地址,目标地址不变,并在本机建立NAT表项,当数据返回时,根据NAT表将目的地址数据改写为数据发送出去时候的源地址,并发送给主机。解决内网用户用同一个公网地址上网的问题。
    MASQUERADE,是SNAT的一种特殊形式,适用于像adsl这种临时会变的ip上
  • DNAT:目标地址转换。和SNAT相反,IP包经过route之后、出本地的网络栈之前,重新修改目标地址,源地址不变,在本机建立NAT表项,当数据返回时,根据NAT表将源地址修改为数据发送过来时的目标地址,并发给远程主机。可以隐藏后端服务器的真实地址。
    REDIRECT:是DNAT的一种特殊形式,将网络包转发到本地host上(不管IP头部指定的目标地址是啥),方便在本机做端口转发。
  • LOG:在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则

除去最后一个LOG,前3条规则匹配数据包后,该数据包不会再往下继续匹配了,所以编写的规则顺序极其关键

4.2 配置实例

小实例

例1:给filter表INPUT链添加第一条规则,允许所有数据包访问本机

1
2
3
4
5
6
7
8
9
10
11
12
13
$ iptables -t filter -I INPUT -j ACCEPT 


$ iptables -t filter -nvL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 13 800 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 10 packets, 1296 bytes)
num pkts bytes target prot opt in out source destination

例2:给filter表追加一条规则,允许来自192.168.10.0/24网段的数据包访问本机

1
2
3
4
5
6
7
8
9
10
11
12
13
$ iptables -t filter -A INPUT -s 192.168.10.0/24 -j ACCEPT

$ iptables -t filter -nvL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 346 29802 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 ACCEPT all -- * * 192.168.10.0/24 0.0.0.0/0

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 33 packets, 4247 bytes)
num pkts bytes target prot opt in out source destination

例3:删除filter表中INPUT链中的第1条规则

1
2
3
4
5
6
7
8
9
10
11
12
$ iptables -t filter -D INPUT 1

$ iptables -t filter -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 192.168.10.0/24 anywhere

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

例4:设置filter表中FORWARD链的默认规则

1
2
3
4
5
6
7
8
9
10
11
12
$ iptables -t filter -P FORWARD DROP  

$ iptables -t filter -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 192.168.10.0/24 anywhere

Chain FORWARD (policy DROP)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

例5:清空filter表中所有规则

1
2
3
4
5
6
7
8
9
10
11
$ iptables -F           

$ iptables -t filter -L
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy DROP)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

注意:-F清空链时,默认策略不受影响,默认策略也不参与链内规则的顺序编排

配置SNAT、DNAT

  1. 创建三个namespace

    1
    2
    3
    4
    5
    6
    7
    8
    # 本地主机
    $ ip netns add PC

    # 路由
    $ ip netns add PC_ROUTE

    # 远程服务主机
    $ ip netns add Inter_Server
  2. 创建2对veth

    1
    2
    3
    $ ip link add PTR type veth peer name RTP

    $ ip link add RTS type veth peer name STR
  3. 将veth分别加入到创建的namespace中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # PTR加入到本地PC
    $ ip link set PTR netns PC

    # RTP RTS加入到中间路由
    $ ip link set RTP netns PC_ROUTE
    $ ip link set RTS netns PC_ROUTE

    # STR加入到远程服务主机
    $ ip link set STR netns Inter_Server
  4. 设置IP地址并启动网卡

    1
    2
    3
    4
    # 进入到PC的namespace bash中
    $ ip netns exec PC bash
    $ ip address add 192.168.0.2/24 dev PTR
    $ ip link set PTR up

    image-20220422151709864

    同理设置其他的IP

    1
    2
    3
    4
    # 进入到路由的namespace bash中
    $ ip netns exec PC_ROUTE bash
    $ ip address add 192.168.0.1/24 dev RTP
    $ ip address add 10.10.0.20/24 dev RTS
    1
    2
    3
    4
    5
    6
    7
    # 进入到远程服务的namespace bash中
    $ ip netns exec Inter_Server bash
    $ ip address add 10.10.0.10/24 dev STR
    #远程服务添加第二块网卡S_eth0
    $ ip link add S_eth0 type dummy
    $ ip address add 2.2.2.2/32 dev S_eth0
    $ ip link set S_eth0 up

    测试PC ping 路由,路由 ping 远程服务

    image-20220422152728632

  5. 添加PC、PC_ROUTE默认路由

    1
    2
    3
    4
    # PC默认路由
    route add default gw 192.168.0.1 dev PTR
    # PC_ROUTE默认路由,不设置默认网关
    route add default dev RTS

    此时PC与PC_ROUTE可以互通,PC_ROUTE与Inter_Server互通,PC与Inter_Server不通

    image-20220424111553890

  6. 添加SNAT规则

    1
    2
    3
    4
    5
    iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j SNAT --to 10.10.0.20
    # 适用于广域网为固定IP地址的情况,本例是这种情况

    # iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j MASQUERADE
    # 适用于广域网为动态分配IP地址的情况,典型例子是PPPoE

    在nat表上的POSTROUTING链对源地址为192.168.0.0/24网段的地址做源地址转换,转换成10.10.0.20,这样Inter_Server就可以返回数据包给PC_ROUTE然后PC_ROUTE根据nat表的记录转发给PC主机。

    image-20220424112750851

    但此时Inter_Server还不能主动ping通PC

    image-20220424112914187

  7. 添加DNAT规则将PC映射到PC_ROUTE

    1
    iptables -t nat -A PREROUTING -d 10.10.0.20 -j DNAT --to 192.168.0.2

    将发往10.10.0.20的数据包目的地址转换成192.168.0.2,然后再进行路由选择

    此时Inter_Server ping 10.10.0.20,数据包会被转发至192.168.0.2

    image-20220424113835491

ip rule、ip route、iptables

例子:公司内网要求192.168.0.100 以内的使用 10.0.0.1 网关上网 (电信),其他IP使用 20.0.0.1 (网通)上网。

  1. 首先要在网关服务器上添加一个默认路由,当然这个指向是绝大多数的IP的出口网关

    1
    ip route add default gw 20.0.0.1
  2. 之后通过 ip route 添加一个路由表:

    1
    2
    ip route add table 3 via 10.0.0.1 dev ethX 
    # ethx 是 10.0.0.1 所在的网卡, 3 是路由表的编号
  3. 之后添加 ip rule 规则:

    1
    2
    ip rule add fwmark 3 table 3 
    # fwmark 3 是标记,table 3 是路由表3 上边。 意思就是凡事标记了 3 的数据使用 table3 路由表
  4. 之后使用 iptables 给相应的数据打上标记:

    1
    iptables -A PREROUTING -t mangle -i eth0 -s 192.168.0.1 - 192.168.0.100 -j MARK --set-mark 3

因为 mangle 的处理是优先于 nat 和 fiter 表的,所以在数据包到达之后先打上标记,之后再通过 ip rule 规则,对应的数据包使用相应的路由表进行路由,最后读取路由表信息,将数据包送出网关。


深入理解iptables防火墙

wiki iptables

iptables的四表五链与NAT工作原理

同网段和不同网段的ARP协议

Linux下ip route、ip rule、iptables的关系

路由选择时机

Linux中的虚拟网络接口