iptables防火墙详解
一、iptables概念
1、防火墙基础
1.1 防火墙概念
从逻辑上讲,防火墙可以大体分为主机防火墙和网络防火墙。网络防火墙和主机防火墙并不冲突,可以理解为,网络防火墙主外(集体), 主机防火墙主内(个人)
- 主机防火墙:针对于单个主机进行防护
- 网络防火墙:往往处于网络入口或边缘,针对于网络入口进行防护,服务于防火墙背后的本地局域网
从物理上讲,防火墙可以分为硬件防火墙和软件防火墙
- 硬件防火墙:在硬件级别实现部分防火墙功能,另一部分功能基于软件实现,性能高,成本高
- 软件防火墙:应用软件处理逻辑运行于通用硬件平台之上的防火墙,性能低,成本低
Linux防火墙体系主要工作在网络层,针对TCP/IP数据包实施过滤和限制,属于典型的包过滤防火墙(也称网络层防火墙);Linux防火墙体系基于内核编码实现,具有非常稳定的性能和高效率,因此被广泛的应用
1.2 Netfilter和iptables的区别
Netfilter:指的是Linux内核中实现包过滤防火墙的内部结构,不以程序或文件的形式存在,属于“内核态”(KernelSpace,又称内核空间)的防火墙功能体系(filter是过滤器的意思,netfilter即网络层过滤);Netfilter是Linux操作系统核心层内部的一个数据包处理模块,它具有网络地址转换(Network Address Translate)、数据包内容修改以及数据包过滤的防火墙功能
Iptables:指的是用来管理Linux防火墙的命令程序,通常位于/sbin/iptables
,属于“用户态”(UserSpace,又称用户空间)的防火墙管理体系(iptables: IP信息包过滤系统)。虽然我们使用service iptables start
启动iptables服务,但是其实准确的来说,iptables并没有一个守护进程,所以并不能算是真正意义上的服务,而应该算是内核提供的功能
2、Iptables的表、链结构
包过滤主要是网络层,针对IP数据包;体现在对包内的IP地址、端口等信息的处理上;而iptables作用是为包过滤机制的实现提供规则(或策略),通过各种不同的规则,告诉netfilter对来自某些源、前往某些目的或具有某些协议特征的数据包应该如何处理。iptables 默认维护着 4 个表和 5 个链,所有的防火墙策略规则都被分别写入这些表与链中
2.1 规则链
规则链上可能不止有一条规则,而是有很多条规则,当我们把这些规则串到一个链条上的时候,就形成了链,ip请求将这条链上的所有规则匹配一遍,如果有符合条件的规则,则执行规则对应的动作。
规则的作用是对数据包进行过滤或处理;链的作用是容纳各种防火墙规则;链的分类依据是处理数据包的不同时机
总共有五种5种规则链,分别是
- INPUT:处理入站数据包
- OUTPUT:处理出站数据包
- FORWARD:处理转发数据包
- POSTROUTING链:在进行路由选择后处理数据包(对数据链进行源地址修改转换)
- PREROUTING链:在进行路由选择前处理数据包(做目标地址转换)
INPUT、OUTPUT链主要用在"主机型防火墙"中,即主要针对服务器本机进行保护的防火墙;而FORWARD、PREROUTING、POSTROUTING链多用在"网络型防火墙"中
2.2 规则表
表的作用是容纳各种规则链;表的划分依据是防火墙规则的作用相似,默认包括4个规则表
-
raw表
确定是否对该数据包进行状态跟踪以及处理异常,表内包含两个链:OUTPUT、PREROUTING
-
mangle表
为数据包的TOS(服务类型)、TTL(生命周期)值,或者为数据包设置Mark标记,以实现流量整形、策略路由等高级应用。其对应iptable_mangle,表内包含五个链:PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD
-
nat表
修改数据包中的源、目标IP地址或端口;其对应的模块为iptable_nat,表内包括三个链:PREROUTING、POSTROUTING、OUTPUT(centos7中还有INPUT,centos6中没有)
PREROUTING链 – 处理刚到达本机并在路由转发前的数据包。它会转换数据包中的目标IP地址(destination ip address),通常用于DNAT(destination NAT)。POSTROUTING链 – 处理即将离开本机的数据包。它会转换数据包中的源IP地址(source ip address),通常用于SNAT(source NAT)。OUTPUT链 – 处理本机产生的数据包
-
filter表
确定是否放行该数据包(过滤);其对应的内核模块为iptable_filter,表内包含三个链:INPUT、FORWARD、OUTPUT
INPUT链 – 处理来自外部的数据。OUTPUT链 – 处理向外发送的数据。FORWARD链 – 将数据转发到本机的其他网卡设备上。
2.3 规则表之间的顺序
-
raw->mangle->nat->filter
-
规则链之间的顺序
- 入站:PREROUTING->INPUT
- 出站:OUTPUT->POSTROUTING
- 转发:PREROUTING->FORWARD->POSTROUTING
-
规则链内的匹配顺序
按顺序依次检查,匹配即停止(LOG策略例外),若找不到相匹配的规则,则按该链的默认策略处理
-
表和链的关系:表下面是链,表容纳链
3、规则
根据指定的匹配条件来尝试匹配每个流经此处的报文,一旦匹配成功,则由规则后面指定的处理动作进行处理
3.1 匹配条件
基本匹配条件
- 源地址Source IP,目标地址 Destination IP
扩展匹配条件
- 除了上述的条件可以用于匹配,还有很多其他的条件可以用于匹配,这些条件泛称为扩展条件,这些扩展条件其实也是netfilter中的一部分,只是以模块的形式存在,如果想要使用这些条件,则需要依赖对应的扩展模块。
- 源端口Source Port, 目标端口Destination Port
3.2 处理动作
处理动作在iptables中被称为target,动作也可以分为基本动作和扩展动作。此处列出一些常用的动作
ACCEPT:允许数据包通过
DROP:直接丢弃数据包,不给任何回应信息,这时候客户端会感觉自己的请求泥牛入海了,过了超时时间才会有反应
REJECT:拒绝数据包通过,必要时会给数据发送端一个响应的信息,客户端刚请求就会收到拒绝的信息
SNAT:源地址转换,解决内网用户用同一个公网地址上网的问题
MASQUERADE:是SNAT的一种特殊形式,适用于动态的、临时会变的ip上
DNAT:目标地址转换
REDIRECT:在本机做端口映射
LOG:在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则,也就是说除了记录以外不对数据包做任何其他操作,仍然让下一条规则去匹配
二、iptables规则管理
1、iptables规则操作
1.1 iptables信息查询
1 | # filter负责过滤功能,比如允许哪些IP地址访问,拒绝哪些IP地址访问,允许访问哪些端口,禁止访问哪些端口 |
1.2 规则添加
注意:添加规则时,规则的顺序非常重要,哪个先匹配就执行哪个,后面就算有一模一样的也不会执行
1 | # 在指定表的指定链的尾部添加一条规则,-A选项表示在对应链的末尾添加规则,省略-t选项时,表示默认操作filter表中的规则 |
1.3 规则删除
注意:如果没有保存规则,删除规则时请慎重
1 | # 按照规则序号删除规则,删除指定表的指定链的指定规则,-D选项表示删除对应链中的规则 |
1.4 规则修改
注意:如果使用-R选项修改规则中的动作,那么必须指明原规则中的原匹配条件,例如源IP,目标IP等,如果不写明会变成默认,建议直接新增后删除
1 | # 修改指定表中指定链的指定规则,-R选项表示修改对应链中的规则,使用-R选项时要同时指定对应的链以及规则对应的序号,并且规则中原本的匹配条件不可省略 |
1.5 规则保存
在默认的情况下,我们对"防火墙"所做出的修改都是"临时的",换句话说就是,当重启iptables服务或者重启服务器以后,我们平常添加的规则或者对规则所做出的修改都将消失,为了防止这种情况的发生,我们需要将规则"保存"
1 | # centos6中,使用"service iptables save"命令即可保存规则,规则默认保存在/etc/sysconfig/iptables文件中 |
最后是通用的方法,使用另一种方法保存iptables规则,就是使用iptables-save
命令
1 | # 使用iptables-save并不能保存当前的iptables规则,但是可以将当前的iptables规则以”保存后的格式”输出到屏幕上 |
2、iptables匹配条件
2.1 常用基本匹配条件
当规则中同时存在多个匹配条件时,多个条件之间默认存在"与"的关系,即报文必须同时满足所有条件,才能被规则匹配
1 | # --------------------匹配条件:目标IP地址 |
2.2 扩展匹配条件(基本)
基本匹配条件我们可以直接使用,而如果想要使用扩展匹配条件,则需要依赖一些扩展模块,或者说在使用扩展匹配条件之前,需要指定相应的扩展模块,使用-m 来选择扩展模块
1 | # 常用的扩展匹配条件,tcp扩展模块 |
2.3 扩展匹配条件(其他)
- iprange模块
-s选项与-d选项并不能一次性的指定一段连续的IP地址范围,如果我们需要指定一段连续的IP地址范围,可以使用iprange扩展模块。使用iprange扩展模块可以指定"一段连续的IP地址范围",用于匹配报文的源地址或者目标地址
—src-range:指定连续的源地址范围
—dst-range:指定连续的目标地址范围
1 | #示例 |
- string模块
使用string扩展模块,可以指定要匹配的字符串,如果报文中包含对应的字符串,则符合匹配条件,比如,如果报文中包含字符”OOXX”,我们就丢弃当前报文
—algo:指定对应的匹配算法,可用算法为bm、kmp,此选项为必需选项。
—string:指定需要匹配的字符串
1 | # -m string表示使用string模块,–algo bm表示使用bm算法去匹配指定的字符串,–string"OOXX"则表示我们想要匹配的字符串为"OOXX" |
- time模块
我们可以通过time扩展模块,根据时间段区匹配报文,如果报文到达的时间在指定的时间范围以内,则符合匹配条件
—timestart:用于指定时间范围的开始时间,不可取反
—timestop:用于指定时间范围的结束时间,不可取反
—weekdays:用于指定”星期几”,可取反
—monthdays:用于指定”几号”,可取反
—datestart:用于指定日期范围的开始日期,不可取反
—datestop:用于指定日期范围的结束时间,不可取反
1 | # "-m time"表示使用time扩展模块,–timestart选项用于指定起始时间,–timestop选项用于指定结束时间 |
- connlimit 模块
使用connlimit扩展模块,可以限制每个IP地址同时链接到server端的链接数量,注意:我们不用指定IP,其默认就是针对"每个客户端IP",即对单IP的并发连接数限制
—connlimit-above:单独使用此选项时,表示限制每个IP的链接数量。
—connlimit-mask:此选项不能单独使用,在使用–connlimit-above选项时,配合此选项,则可以针对"某类IP段内的一定数量的IP"进行连接数量的限制,如果不明白可以参考上文的详细解释。
1 | # 限制每个IP地址最多只能占用两个ssh链接远程到server端 |
- limit模块
connlimit模块是对连接数量进行限制的,limit模块是对"报文到达速率"进行限制的。用大白话说就是,如果我想要限制单位时间内流入的包的数量,就能用limit模块,我们可以以秒为单位进行限制,也可以以分钟、小时、天作为单位进行限制,比如,限制每秒中最多流入3个包,或者限制每分钟最多流入30个包都可以
—limit-burst:类比”令牌桶”算法,此选项用于指定令牌桶中令牌的最大数量,上文中已经详细的描述了”令牌桶”的概念,方便回顾
—limit:类比”令牌桶”算法,此选项用于指定令牌桶中生成新令牌的频率,可用时间单位有second、minute 、hour、day
1 | #示例 #注意,如下两条规则需配合使用,具体原因上文已经解释过,忘记了可以回顾 |
2.4 扩展匹配条件tcp-flags
—tcp-flags指的就是tcp头中的标志位,看来,在使用iptables时,我们可以通过此扩展匹配条件,去匹配tcp报文的头部的标识位,然后根据标识位的实际情况实现访问控制的功能
1 | # 复习之前的内容,这个也是tcp模块里的 |
2.5 udp扩展与icmp扩展
udp扩展模块,这个扩展模块中能用的匹配条件比较少,只有两个,就是–sport与–dport,即匹配报文的源端口与目标端口。
1 | # 放行samba服务的137与138这两个UDP端口 |
ICMP协议的全称为Internet Control Message Protocol,翻译为互联网控制报文协议,它主要用于探测网络上的主机是否可用,目标是否可达,网络是否通畅,路由是否可用等。—icmp-type:匹配icmp报文的具体类型
我们平常使用ping命令ping某主机时,如果主机可达,对应主机会对我们的ping请求做出回应(此处不考虑禁ping等情况),也就是说,我们发出ping请求,对方回应ping请求,虽然ping请求报文与ping回应报文都属于ICMP类型的报文,但是如果在概念上细分的话,它们所属的类型还是不同的,我们发出的ping请求属于类型8的icmp报文,而对方主机的ping回应报文则属于类型0的icmp报文
1 | # 要禁止所有icmp类型的报文进入本机 |
2.6 state扩展
state模块可以让iptables实现"连接追踪"机制,对于state模块而言的"连接"并不能与tcp的"连接"画等号,在TCP/IP协议簇中,UDP和ICMP是没有所谓的连接的,但是对于state模块来说,tcp报文、udp报文、icmp报文都是有连接状态的,我们可以这样认为,对于state模块而言,只要两台机器在"你来我往"的通信,就算建立起了连接,其中的报文可以分为5种状态,报文状态可以为NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED
- NEW:连接中的第一个包,状态就是NEW,我们可以理解为新连接的第一个包的状态为NEW。
- ESTABLISHED:我们可以把NEW状态包后面的包的状态理解为ESTABLISHED,表示连接已建立。
- RELATED:从字面上理解RELATED译为关系,但是这样仍然不容易理解,我们举个例子,比如FTP服务,FTP服务端会建立两个进程,一个命令进程,一个数据进程。命令进程负责服务端与客户端之间的命令传输(我们可以把这个传输过程理解成state中所谓的一个"连接",暂称为"命令连接")。数据进程负责服务端与客户端之间的数据传输 ( 我们把这个过程暂称为"数据连接" )。但是具体传输哪些数据,是由命令去控制的,所以,"数据连接"中的报文与"命令连接"是有关系的。那么,"数据连接"中的报文可能就是RELATED状态,因为这些报文与"命令连接"中的报文有关系。(注:如果想要对ftp进行连接追踪,需要单独加载对应的内核模块
nf_conntrack_ftp
,如果想要自动加载,可以配置/etc/sysconfig/iptables-config
文件) - INVALID:如果一个包没有办法被识别,或者这个包没有任何状态,那么这个包的状态就是INVALID,我们可以主动屏蔽状态为INVALID的报文。
- UNTRACKED:报文的状态为untracked时,表示报文未被追踪,当报文的状态为Untracked时通常表示无法找到相关的连接。
1 | # 只要放行状态为ESTABLISHED的报文即可,因为如果报文的状态为ESTABLISHED,那么报文肯定是之前发出的报文的回应 |
2.7 mac扩展
1 | # mac扩展用来匹配某个mac地址 |
三、iptables进阶与提高
1、iptables的黑白名单机制
报文在经过iptables的链时,会匹配链中的规则,遇到匹配的规则时,就执行对应的动作,如果链中的规则都无法匹配到当前报文,则使用链的默认策略(默认动作),链的默认策略通常设置为ACCEPT或者DROP。
那么,当链的默认策略设置为ACCEPT
时,如果对应的链中没有配置任何规则,就表示接受所有的报文,如果对应的链中存在规则,但是这些规则没有匹配到报文,报文还是会被接受。同理,当链的默认策略设置为DROP
时,如果对应的链中没有配置任何规则,就表示拒绝所有报文,如果对应的链中存在规则,但是这些规则没有匹配到报文,报文还是会被拒绝。
- 黑名单机制:当链的默认策略为ACCEPT时,链中的规则对应的动作应该为DROP或者REJECT,表示只有匹配到规则的报文才会被拒绝,没有被规则匹配到的报文都会被默认接受
- 白名单机制:当链的默认策略为DROP时,链中的规则对应的动作应该为ACCEPT,表示只有匹配到规则的报文才会被放行,没有被规则匹配到的报文都会被默认拒绝
1 | # 白名单机制 |
2、iptables自定义链
自定义链可以方便的管理不同的规则,方便后期规则的修改,但是需要注意的是,自定义链并不能直接使用,而是需要被默认链引用才能够使用
1 | # 创建自定义链 |
3、iptables之网络防火墙
3.1 概述
网络防火墙: 往往处于网络入口或边缘,针对于网络入口进行防护,服务于防火墙背后的本地局域网(有点类似路由器),网络防火墙往往处于网络的入口或者边缘,那么,如果想要使用iptables充当网络防火墙,iptables所在的主机则需要处于网络入口处。
不管是由外部主机发往内部主机的报文,还是由内部主机发往外部主机的报文,都需要经过iptables所在的主机,由iptables所在的主机进行"过滤并转发",所以,防火墙主机的主要工作就是"过滤并转发"
前文中,iptables都是作为**“主机防火墙”**的角色出现的,所以我们举例时,只用到了上图中的INPUT链与OUTPUT链,因为拥有"过滤功能"的链只有3条,INPUT、OUTPUT、FORWARD,当报文发往本机时,如果想要过滤,只能在INPUT链与OUTPUT链中实现,而此时,iptables的角色发生了转变,我们想要将iptables所在的主机打造成"网络防火墙",而刚才已经说过,网络防火墙的职责就是"过滤并转发",要想"过滤",只能在INPUT、OUTPUT、FORWARD三条链中实现,要想"转发",报文则只会经过FORWARD链(发往本机的报文才会经过INPUT链),所以,综上所述,iptables的角色变为"网络防火墙"时,规则只能定义在FORWARD链中。
3.2 实战demo
此处所描述的内网、外网与我们平常所说的公网、私网不同。此处描述的内外部网络你可以理解成两个网段,A网络与B网络,为了方便描述,我们把圆形内的主机称为内部主机,把上图中圆形所表示的网络称为内部网络,把圆形外的网络称为外部网络。
1 | ifconfig | awk '/inet/{print $1,$2}' |
4、iptables动作总结
4.1 常用动作之REJECT
之前用到了一些常用动作,比如ACCEPT、DROP、REJECT等。"动作"与"匹配条件"一样,也有"基础"与"扩展"之分。同样,使用扩展动作也需要借助扩展模块,但是,扩展动作可以直接使用,不用像使用"扩展匹配条件"那样指定特定的模块。之前用到的ACCEPT与DROP都属于基础动作;而REJECT则属于扩展动作。
1 | # -----------------------------动作REJECT---------------- |
4.2 常用动作之LOG
使用LOG动作,可以将符合条件的报文的相关信息记录到日志中,但当前报文具体是被"接受",还是被"拒绝",都由后面的规则控制,换句话说,LOG动作只负责记录匹配到的报文的相关信息,不负责对报文的其他处理,如果想要对报文进行进一步的处理,可以在之后设置具体规则,进行进一步的处理。
1 | # 举例 |
4.3 NAT相关动作(重要)
图中圆形所示的逻辑区域表示公司内网,网段为10.1.0.0/16
,主机B、C、D都属于内网主机,主机B比较特殊,同时扮演了网关与防火墙,主机B持有公司唯一的公网IP(我们用了一个假的公网IP),局域网内主机如果想与公网主机通讯,需要共享此公网IP,由B主机进行NAT,所以,我们为主机B准备了两块网卡,公网IP与私网IP分别配置到这两块网卡中
1 | # 如果想要NAT功能能够正常使用,需要开启Linux主机的核心转发功能。 |
四、总结
1、配置应用程序规则举例
1.1 SSH
1 | #-m state: 启用状态匹配模块(state matching module) |
1.2 HTTP
1 | # 1.删除现有规则 |
1.3 NAT规则实战
1 | # 把本地的mysql 3306端口映射出去变成63306,外面连接的语句是 |
2、iptables常用套路小结
-
规则的顺序非常重要
如果报文已经被前面的规则匹配到,IPTABLES则会对报文执行对应的动作,通常是ACCEPT或者REJECT,报文被放行或拒绝以后,即使后面的规则也能匹配到刚才放行或拒绝的报文,也没有机会再对报文执行相应的动作了(前面规则的动作为LOG时除外),所以,针对相同服务的规则,更严格的规则应该放在前面
-
当规则中有多个匹配条件时,条件之间默认存在"与"的关系
如果一条规则中包含了多个匹配条件,那么报文必须同时满足这个规则中的所有匹配条件,报文才能被这条规则匹配到。
-
在不考虑1的情况下,应该将更容易被匹配到的规则放置在前面
比如,你写了两条规则,一条针对sshd服务,一条针对web服务。假设,一天之内,有20000个请求访问web服务,有200个请求访问sshd服务,那么,应该将针对web服务的规则放在前面,针对sshd的规则放在后面,因为访问web服务的请求频率更高。如果将sshd的规则放在前面,当报文是访问web服务时,sshd的规则也要白白的验证一遍,由于访问web服务的频率更高,白白耗费的资源就更多;如果web服务的规则放在前面,由于访问web服务的频率更高,所以无用功会比较少。换句话说就是,在没有顺序要求的情况下,不同类别的规则,被匹配次数多的、匹配频率高的规则应该放在前面。
-
当IPTABLES所在主机作为网络防火墙时,在配置规则时,应着重考虑方向性,双向都要考虑,从外到内,从内到外。
-
在配置IPTABLES白名单时,往往会将链的默认策略设置为ACCEPT,通过在链的最后设置REJECT规则实现白名单机制,而不是将链的默认策略设置为DROP,如果将链的默认策略设置为DROP,当链中的规则被清空时,管理员的请求也将会被DROP掉。
参考文章:
https://www.zsythink.net/archives/tag/iptables/
https://zhuanlan.zhihu.com/p/279919870