iptables防火墙
1. 简介
iptables
实际上只是位于用户空间的一个面向系统管理员的Linux防火墙的管理工具,而真正实现防火墙功能的是netfilter
,它是Linux内核中实现包过滤的内核模块,iptables
对应在内核中的模块应该是ip_tables
,我们查看系统内核中ip_tables
的信息的时候可以看到ip_tables.ko
这个模块是在netfilter
这个目录下的。
iptables的作用是为包过滤机制的实现提供规则,通过各种不同的规则,告诉netfilter对来自某些源,前往某些目的或具有某些协议特征的数据包应该如何处理,下面这张图很明了的说明了Netfilter和iptables之间的关系
2. iptables的四表五链
为了更加方便的组织和管理防火墙规则,iptables采用了表和链的分层结构
其中,每个规则表相当于内核空间的一个容器,根据规则集的不同用途划分为默认的四个表,在每个表容器内又包括不同的规则链,根据处理数据包的不同时机划分为五种链
2.1 iptables 4表:
表名称 | 规则含义 | 包含的链 | 内核模块 |
---|---|---|---|
filter 表 | 用来对数据包进行过滤,具体的规则要求决定如何处理一个数据包。 | input 、forward 、output |
iptable_filter |
nat 表 | nat 全称:network address translation 网络地址转换,主要用来修改数据包的 IP 地址、端口号信息。 | prerouting 、output 、postrouting |
iptable_nat |
mangle 表 | 主要用来修改数据包的服务类型,生存周期,为数据包设置标记,实现流量整形、策略路由等。 | prerouting 、input 、forward 、output 、postrouting |
iptable_mangle |
raw 表 | 主要用来决定是否对数据包进行状态跟踪。 | prerouting 、output |
iptable_raw |
raw表只使用在
PREROUTING
链和OUTPUT
链上,因为优先级最高,从而可以对收到的数据包在系统进行ip_conntrack(连接跟踪)前进行处理。一但用户使用了raw表,在某个链上,raw表处理完后,将跳过NAT表和ip_conntrack处理,即不再做地址转换和数据包的链接跟踪处理了。RAW表可以应用在那些不需要做nat的情况下,以提高性能。
应用最多的是filter和nat。
2.2 iptables 5链:
在处理各种数据包时,根据防火墙规则的不同介入时机,iptables默认划分为五种不同的规则链:
PREROUTING
,INPUT
,FORWARD
,OUTPUT
,POSTROUTING
链名称 | 规则含义 |
---|---|
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
→路由选择
→FORWARD
→POSTROUTING
出站数据流向:路由选择
→OUTPUT
→POSTROUTING
规则链内部的处理规则:
按第一条规则……第二条规则的顺序进行匹配处理,遵循“匹配即停止”的原则, 一旦找到一条匹配规则将不再检查后续的其他规则,如果一直找不到匹配的规则,就按默认规则处理。
这些表并非必须全部使用,是可选的,最常用的是nat
,filter
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状态 |
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
指定协议名,该通用协议匹配用于检查某些特定协议。 支持的协议有TCP
、UDP
、ICMP
、udplite
、icmpv6
、esp
、ah
、sctp
、mh
、用逗号分隔的任何这三种协议的组合列表 以及ALL
(用于所有协议)。ALL
是缺省匹配。可以使用!
符号,它表示不与该项匹配。
例1: 不允许任何主机ping本主机(默认在filter链添加规则)
1 | iptables -A INPUT -p icmp -j REJECT |
例2:接收除icmp之外的其他连接,!
表示取反
1 | iptables -A INPUT ! -p icmp -j ACCEPT |
注意:此时还是可以ping通此机器的,因为定义的规则是接收除icmp之外的其他连接
,只要非icmp
协议的包就ACCEPT,但并不代表icmp
包就要丢弃,实际上对于ICMP包并不会匹配到我们设置的规则,因而会继续寻找下一条规则,表中只有一条规则 所以最终会匹配到默认规则,而默认规则是ACCPET,所以依然被放行了。接下来如果将INPUT链的默认规则改为DROP就ping不通了(INPUT OUTPUT链不能设置默认REJECT):
1 | iptables -P INPUT DROP |
地址匹配
iptables编写地址匹配的规则时用-s:表示源地址,-d:表示目标地址
例1:不允许192.168.100.200这个主机ping本主机
接口匹配
当本机有多个网卡时,可以使用-i
选项去匹配报文是通过哪块网卡流入本机的。
例1:拒绝由网卡ens33流入的ping请求报文
1 | iptables -A INPUT -i ens33 -p icmp -j DROP |
-i 使用限制:
-i
选项是用于匹配报文流入的网卡的,也就是说,从本机发出的报文是不可能会使用到-i
选项的,因为这些由本机发出的报文压根不是从网卡流入的,而是要通过网卡发出的,从这个角度考虑,-i选项的使用是有限制的。
为了更好的解释-i选项,一张iptables全局报文流向图,如下。
既然-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 | [root@firewall ~]# iptables -I INPUT -p tcp --dport 20:21 -j ACCEPT |
借助tcp扩展模块的–sport或者–dport都可以指定一个连续的端口范围,但是无法同时指定多个离散的、不连续的端口,如果想要同时指定多个离散的端口,需要借助另一个扩展模块,multiport模块
。
例3:允许开放25,80,110,143端口,以便访问邮件和网站服务
1 | [root@firewall ~]# iptables -A INPUT -p tcp -m multiport --dport 25,80,110,143 -j ACCEPT |
例4:不允许192.168.100.110-192.168.100.150范围的主机经过防火墙转发数据包
1 | [root@firewall ~]# iptables -A FORWARD -p tcp -m iprange --src-range 192.168.100.110-192.168.100.150 -j REJECT |
状态匹配
编写iptables规则时使用“-m state --state 连接状态”的形式
常用的连接状态:
NEW:与任何连接无关的 ,一个连接的第一个报文,例如TCP连接中的SYN报文
ESTABLISHED:响应请求或者已经建立连接的,第一个成功穿越防火墙的报文之后所有的报文
RELATED:伴随连接的报文,即某个已经处于
ESTABLISHED
的连接所产生的报文,这些报文不属于第一条连接,但是的确是由第一条连接产生的。与已有连接有相关性,比如ftp数据连接 INVALID:无法判断状态的报文
例1:允许响应请求的连接放行
1 | [root@firewall ~]# iptables -I INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT |
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 | iptables -t filter -I INPUT -j ACCEPT |
例2:给filter表追加一条规则,允许来自192.168.10.0/24
网段的数据包访问本机
1 | iptables -t filter -A INPUT -s 192.168.10.0/24 -j ACCEPT |
例3:删除filter表中INPUT链中的第1条规则
1 | iptables -t filter -D INPUT 1 |
例4:设置filter表中FORWARD链的默认规则
1 | iptables -t filter -P FORWARD DROP |
例5:清空filter表中所有规则
1 | iptables -F |
注意:-F清空链时,默认策略不受影响,默认策略也不参与链内规则的顺序编排
配置SNAT、DNAT
-
创建三个namespace
1
2
3
4
5
6
7
8本地主机
ip netns add PC
路由
ip netns add PC_ROUTE
远程服务主机
ip netns add Inter_Server -
创建2对veth
1
2
3ip link add PTR type veth peer name RTP
ip link add RTS type veth peer name STR -
将veth分别加入到创建的namespace中
1
2
3
4
5
6
7
8
9PTR加入到本地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 -
设置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同理设置其他的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 RTS1
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 远程服务
-
添加PC、PC_ROUTE默认路由
1
2
3
4PC默认路由
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不通
-
添加SNAT规则
1
2
3
4
5iptables -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主机。
但此时Inter_Server还不能主动ping通PC
-
添加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
ip rule、ip route、iptables
例子:公司内网要求192.168.0.100 以内的使用 10.0.0.1 网关上网 (电信),其他IP使用 20.0.0.1 (网通)上网。
-
首先要在网关服务器上添加一个默认路由,当然这个指向是绝大多数的IP的出口网关
1
ip route add default gw 20.0.0.1
-
之后通过 ip route 添加一个路由表:
1
2ip route add table 3 via 10.0.0.1 dev ethX
ethx 是 10.0.0.1 所在的网卡, 3 是路由表的编号 -
之后添加 ip rule 规则:
1
2ip rule add fwmark 3 table 3
fwmark 3 是标记,table 3 是路由表3 上边。 意思就是凡事标记了 3 的数据使用 table3 路由表 -
之后使用 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 规则,对应的数据包使用相应的路由表进行路由,最后读取路由表信息,将数据包送出网关。