iptables 详解

netfilter/iptables包过滤系统被称为单个实体,但它实际上由netfilteriptables两个组件组成。netfilter也称为内核空间(KernelSpace),是内核的一部分,由包过滤表组成,这些表包含内核用来控制包过滤处理的规则集;iptables也称为用户空间(UserSpace),是主要配置工具,iptables 使插入、修改和删除信息包过滤表中的规则变得容易。

netfilter

netfilter 选取了 5 个位置进行数据包操作:

  • PREROUTING:数据包流入网卡后进行路由前;
  • INPUT:数据包流入用户空间前;
  • FORWARD:设在不同的网卡之间;
  • OUTPUT:数据包流出用户空间前;
  • POSTROUTING:数据包进行路由后流出网卡前。

数据包流向

iptables - 数据包流向

  1. 数据包进入网卡后,首先进入PREROUTING链,然后进行路由;如果是发往本机的,则进入INPUT链;如果不是,且内核允许网卡间转发,则进入FORWARD链;
  2. 当数据包经过INPUT链后,它将进入用户空间,然后根据数据包的目的端口号,将其交给上层应用进行处理;
  3. 数据包经过FORWARD链后,将进入POSTROUTING链,POSTROUTING链处理完后,最后被送出网卡;
  4. 本机进程发出的数据包首先被OUTPUT链处理,然后进行路由,如果不是发往本机,则经过POSTROUTING链后被送出。

比如一个简单的 http 请求:curl -s http://www.zfl9.com/,流向如下:
去程
curl 向系统申请一个套接字资源,并获取一个随机高位端口,假设为 23333,然后向 www.zfl9.com:80(当然会先将 www.zfl9.com 解析为 IP,这里省略) 地址发送 http 请求包;该请求包首先被 OUTPUT 链处理,然后进行路由,因为不是发往本机,因此到达 POSTROUTING 链,最后被送出网卡。

回程
来自 www.zfl9.com:80 的响应数据包经过千山万水,来到了本机网卡,进入 PREROUTING 链,然后被进行路由;因为目的地址是本机,因此来到 INPUT 链,经过 INPUT 链后,根据目的端口号 23333 最终交给 curl 进行处理。

规则链和表

链、表、规则
首先需要搞清楚的三个概念就是:链(chain)表(table)规则(rule)

  • :即我们前面说的五个卡口(物理概念),PREROUTINGINPUTFORWARDOUTPUTPOSTROUTING
  • :为了方便管理而提出的逻辑概念,每个表都有其特定的功能;有rawmanglenatfilter四张表;
  • 规则:很容易理解,规则就是用于描述如何处理一个数据包的;描述一条规则时都会说明它所在的链和所在的表。

表的优先级
从左到右依次降低:raw -> mangle -> nat -> filter

  • raw,优先级最高,通常与NOTRACK一起使用,用于跳过连接跟踪(conntrack)和 nat 表的处理;
  • mangle,修改包头部的某些特殊条目,如 TOS、TTL、及打上特殊标记 MARK 等,以影响后面的路由决策;
  • nat,用于进行网络地址转换,如 SNAT(修改源地址)、DNAT(修改目的地址)、REDIRECT 重定向等;
  • filter,主要用于过滤数据包、丢弃非法数据包,如 DROP(丢弃)、REJECT(拒绝)、LOG(记录日志)等;

默认策略
默认策略只有两个动作:ACCEPT、DROP;当一个数据包未与该链中的任何规则匹配时,它将被默认策略处理;
也就是所谓的黑白名单,如果默认策略为 ACCEPT,则为黑名单模式,如果默认策略为 DROP,则为白名单模式。

连接跟踪
连接跟踪,顾名思义,就是跟踪并记录网络连接的状态。

Linux 会为每一个经过网络堆栈的数据包,都生成一个新的连接记录项(Connection Entry);此后,所有属于此连接的数据包都被唯一地分配给这个连接,并标识连接的状态。所谓的连接记录项,就是对每一个连接的状态(产生、传输及终止)进行跟踪记录;由所有记录项产生的表,即称为连接跟踪表

为什么需要连接跟踪?因为它是状态防火墙和 NAT 的实现基础

  • 状态防火墙,在 iptables 中,我们可以借助 conntrack、state 模块来根据数据包的连接状态进行规则配置。如果没有连接跟踪,那么根本不可能有什么状态可循!
  • NAT,网络地址转换就是修改数据包的源地址、源端口、目的地址、目的端口;如果没有连接跟踪,你根本不可能再找回数据包原本的地址信息!

Linux 默认会为所有连接都创建连接记录项,而维护连接跟踪表是有开销的,要命的是这个表还有大小限制;
因此,如果你在一个大流量的 Web 服务器上启用 iptables,很容易因为连接记录项过多而导致服务器拒绝连接!
那么有什么解决的办法呢?利用 raw 表的 NOTRACK 功能,让所有发往 80 端口的数据包跳过连接跟踪和 nat 表。
iptables -t raw -I PREROUTING -p tcp --dport 80 -j NOTRACK将所有发往 80/tcp 的数据包跳过 conntrack。

规则总体顺序

  1. 当一个数据包进入某个链时,首先按照表的优先级依次处理;
  2. 每个表中的规则都有序号(从 1 开始),数据包会根据规则序号依次进行匹配;
  3. 如果命中一条规则,则执行相应的动作;如果所有表的规则都未命中,则执行默认策略。

命令详解

应用例子

ipset模块

recent模块

iptables-recent 模块可有效预防 DDOS、CC 攻击;
还可以避免 ssh 暴力破解,具体请参考 - ssh 防暴力破解