iptables简介与实战

admin 2023年01月06日 469次浏览

1、iptables简介

1.1、概述

iptables 是 Linux 自带(centos7以后默认使用 firewalld,需要单独安装)的基于包过滤的防火墙工具,其可以对流入、流经、流过服务器的数据包进行精细控制。iptables 主要工作在 OSI 模型的二、三、四层

1.2、使用场景

  • 做系统主机防火墙,主要使用 filter 表的 INPUT 链
  • 做局域网共享上网使用,主要使用 nat 表的 POSTROUTING 链
  • 端口或 IP 映射,主要使用 nat 表的 PREROUTING 链
  • IP 一对一映射(DMZ)

1.3、iptables工作流程

iptables 采用数据包过滤机制工作,因此,它会对请求的数据包的包头数据进行分析,并根据预先设定的规则进行匹配,以决定该数据包是否可以进入主机

  • 防火墙是一层一层过滤的,按照配置配置规则的顺序从上到下,从前到后进行过滤
  • 如果匹配上了某一条规则,此时数据包就不会继续向下匹配其他规则了
  • 如果所有规则中都没有匹配上,则继续向下匹配,直到匹配默认规则,得到明确通过还是阻止
  • 防火墙的默认规则是对应链的所有规则执行完毕后才会执行,也就是最后一条规则

1.4、iptables的五表五链

1.4.1、五表(table)

iptables 中的“表”主要是指明使用 iptables 的功能

  • filter: 默认表,用于数据包过滤,包含内置的输入、转发和输出链
  • nat: 地址转换
  • mangle: 拆解报文做出修改,然后在封装报文(不常用)
  • raw: 关闭 nat 表上启用的链接追踪机制(不常用)
  • security: 用于强制访问控制(MAC)网络规则(不常用)

1.4.2、五链(chain)

  • PREROUTING: 作用于路由前
  • INPUT: 作用于外部进入到本机内
  • FORWARD: 经由本机向外转发
  • OUTPUT: 由本机内部向外发出
  • POSTROUTING: 第二次路由离开本机后

1.4.3、报文流向

  • 流入: PREROUTING --> INPUT
  • 流出: OUTPUT --> POSTROUTING
  • 转发: PREROUTING --> FORWARD --> POSTROUTING

1.4.4、各功能使用到的链

  • filter: INPUT、 FORWARD、OUTPUT
  • nat: PREROUTING(DNAT)、OUTPUT、POSTROUTING(SNAT)
  • mangle: PREROUTING、INPUT, FORWARD,、OUTPUT、POSTROUTING
  • raw: PREROUTING、OUTPUT
  • security: INPUT、FORWARD、OUTPUT

1.5、iptables规则

1.5.1、规则组成部分

iptables 的规则由报文的匹配条件、匹配到之后处理动作组成

  • 匹配条件

    根据协议报文特征指定,包括:基本匹配条件、扩展匹配条件

  • 处理动作

    处理动作包括:内建处理机制、自定义处理机制

注意:报文不会经过自定义链,只能在内置链上通过规则进行引用后生效

1.5.2、添加规则时的考量点

  • 要实现哪种功能

    判断添加在哪张表上

  • 报文流经的路径

    判断添加在哪个链上

  • 链上规则的次序

    • 同类规则(访问同一应用),匹配范围小的(精确匹配)放上面
    • 不同类规则(访问不同应用),匹配到报文频率较大的放上面
    • 将那些可由一条规则描述的多个规则合并为一个
    • 设置默认策略
  • 功能的优先级次序

    raw --> mangle --> nat --> filter

2、iptables命令

2.1常用命令

2.1.1、查询规则

  • 语法

    iptables -t 表名 -nvxL --line
    
  • 参数解释

    • -t:表名
    • -n:不解析IP地址
    • -v:会显示出计数器的信息,数据包的数量和大小
    • -x:选项表示显示计数器的精确值
    • –line:显示规则的序号
    • -L:链名
  • 示例

    [root@centos7_11 ~]# iptables -t filter -nvxL --line
    Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
    num      pkts      bytes target     prot opt in     out     source               destination
    1           3      252 ACCEPT     icmp --  *      *       192.168.137.12       0.0.0.0/0
    2          74     4674 ACCEPT     tcp  --  *      *       0.0.0.0/0            192.168.137.11       tcp dpt:22
    3          15     1212 DROP       all  --  *      *       192.168.137.12       0.0.0.0/0
    

2.1.2、添加规则

  • 语法

    # 在最后一条规则后面添加规则
    iptables -t 表名 -A 链名 匹配条件 -j 动作
    
    # 在规则最前面添加规则
    iptables -t 表名 -I 链名 匹配条件 -j 动作
    
    # 在指定位置添加规则
    iptables -t 表名 -I 链名 规则序号 匹配条件 -j 动作
    
  • 示例

    # 在最后一条规则后面添加规则
    [root@localhost ~]# iptables -t filter -A INPUT -s 192.168.137.12 -j DROP
    
    # 在规则最前面添加规则
    [root@localhost ~]# iptables -t filter -I INPUT -p icmp -s 192.168.137.12 -j ACCEPT
    
    # 在指定位置添加规则
    [root@localhost ~]# iptables -t filter -I INPUT 2 -p tcp -m tcp --dport 22 -d 192.168.137.11 -j ACCEPT
    

2.1.3、删除规则

  • 语法

    # 规则序号删除规则
    iptables -t 表名 -D 链名 规则序号
    
    # 根据具体的匹配条件与动作删除规则
    iptables -t 表名 -D 链名 匹配条件 -j 动作
    
    # 删除指定表的指定链中的所有规则
    iptables -t 表名 -F 链名
    
  • 示例

    # 规则序号删除规则
    [root@localhost ~]# iptables -t filter -D INPUT 2
    
    # 根据具体的匹配条件与动作删除规则
    [root@localhost ~]# iptables -t filter -D INPUT -p tcp -m tcp --dport 22 -d 192.168.137.11 -j ACCEPT
    
    # 删除指定表的指定链中的所有规则
    [root@localhost ~]# iptables -t filter -F
    

2.1.4、修改规则

  • 语法

    # 修改指定表中指定链的指定规则
    iptables -t 表名 -R 链名 规则序号 规则原本的匹配条件 -j 动作
    
    # 设置指定表的指定链的默认策略
    iptables -t 表名 -P 链名 动作
    
  • 示例

    # 修改指定表中指定链的指定规则
    [root@localhost ~]# iptables -t filter -R INPUT 1 -p icmp -s 192.168.137.12 -j DROP
    
    # 设置指定表的指定链的默认策略
    [root@localhost ~]# iptables -t filter -P INPUT ACCEPT
    

2.1.5、保存规则

在 centos7 中,使用 firewall 替代了原来的 iptables service,我们需要通过 yum 安装 iptables 与 iptables-services 即可,在centos7 中安装完 iptables-services 后,即可像 centos6 中一样,通过 service iptables save 命令保存规则了,规则保存在 /etc/sysconfig/iptables 文件中

# 保存规则
[root@localhost ~]# service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  确定  ]

# 查看已保存的规则
[root@localhost ~]# cat /etc/sysconfig/iptables
# Generated by iptables-save v1.4.21 on Thu Dec 29 22:50:25 2022
*filter
:INPUT ACCEPT [33:55612]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [73:5920]
-A INPUT -s 192.168.137.12/32 -p icmp -j DROP
-A INPUT -d 192.168.137.11/32 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -s 192.168.137.12/32 -j DROP
COMMIT
# Completed on Thu Dec 29 22:50:25 2022

2.1.6、加载规则

我们可以将 /etc/sysconfig/iptables 中的规则重新载入为当前的 iptables 规则,需要注意的是,未保存入 /etc/sysconfig/iptables 文件中的修改将会丢失或者被覆盖

使用 iptables-restore 命令可以从指定文件中重载规则

[root@localhost ~]# iptables-restore < /etc/sysconfig/iptables

2.2、自定义链

如果将所有规则都放在默认链中,假如需要修改某一个规则,则需要从头到尾检查每一条规则,以确保不会将某一服务的规则修改遗漏,如果规则较多,则是一个“大工程”

自定义链可以针对某一服务单独创建一个链,在该链中仅存在对某一服务的规则策略,因此修改相关策略就会相对简单很多,因为该链中不存在其他服务

2.2.1、创建自定义链

  • 语法

     iptables -t 表名 -N 链名
    
  • 示例

    [root@localhost ~]# iptables -t filter -N IN_SSH
    

2.2.2、引用自定义链

  • 语法

    iptables -t 表名 -I 默认链 规则 -j 自定义链名
    
  • 示例

    # 在自定义链中添加规则
    [root@localhost ~]# iptables -t filter -A IN_SSH -s 192.168.137.20 -j DROP
    [root@localhost ~]# iptables -t filter -I IN_SSH  -p icmp -s 192.168.137.20 -j ACCEPT
    
    # 在 INPUT 链中引用刚才创建的自定义链
    [root@localhost ~]# iptables -t filter -I INPUT -j IN_SSH
    
    # 查看规则列表
    [root@localhost ~]# iptables -xnvL --line
    Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
    num      pkts      bytes target     prot opt in     out     source               destination
    1         810    61708 IN_SSH     all  --  *      *       0.0.0.0/0            0.0.0.0/0
    2        1154    77680 ACCEPT     tcp  --  *      *       0.0.0.0/0            192.168.137.11       tcp dpt:22
    
    Chain IN_SSH (1 references)
    num      pkts      bytes target     prot opt in     out     source               destination
    1           3      252 ACCEPT     icmp --  *      *       192.168.137.20       0.0.0.0/0
    2         356    29904 DROP       all  --  *      *       192.168.137.20       0.0.0.0/0
    

2.2.3、删除自定义链

  • 删除自定义链需要满足两个条件

    • 自定义链没有被引用

    • 自定义链中没有任何规则

  • 语法

    iptables -t 表名 -X 链名
    
  • 示例

    # 清空自定义链中的规则
    [root@localhost ~]# iptables -t filter -F IN_SSH
    
    # 删除引用
    [root@localhost ~]# iptables -t filter -D INPUT 1
    
    # 删除自定义链
    [root@localhost ~]# iptables -t filter -X IN_SSH
    

2.2.4、重命令自定义链

如果自定义链在引用后被重命名,则在引用的规则中会同步修改自定义链的名称为重命名后的名称

  • 语法

    iptables -t 表名 -E old-chain-name new-chain-name
    
  • 示例

    [root@localhost ~]# iptables -t filter -E IN_SSH SSH
    

3、匹配条件

3.1、基本匹配

在匹配条件中,可以使用 ! 条件 来排除指定条件

  • 参数说明

    参数 解释
    -s ip地址 匹配源 ip 地址
    -d ip地址 匹配目的 ip 地址
    -p 匹配指定协议
    支持匹配的协议包含在 /etc/protocols
    -i 网络接口 匹配数据报文的流入接口
    该匹配条件仅能用于 PREROUTING、INPUT、FORWARD 链上
    -o 网络接口 匹配数据报文的流出接口
    该匹配条件仅能用于 FORWARD、OUTPUT、POSTROUTING 链上
  • 示例

    # 匹配源ip地址
    [root@localhost ~]# iptables -t filter -A INPUT -s 192.168.137.12 -j ACCEPT
    
    # 排除指定源ip地址
    [root@localhost ~]# iptables -t filter -A INPUT ! -s 192.168.137.1 -j DROP
    
    # 匹配目的ip地址
    [root@localhost ~]# iptables -t filter -A INPUT -d 192.168.137.11 -j ACCEPT
    
    # 匹配协议
    [root@localhost ~]# iptables -t filter -A INPUT -p icmp -j ACCEPT
    
    # 匹配流入接口
    [root@localhost ~]# iptables -t filter -A INPUT -i ens33 -j ACCEPT
    
    # 匹配流出接口
    [root@localhost ~]# iptables -t filter -A OUTPUT -o ens33 -j ACCEPT
    

3.2、扩展匹配

使用扩展匹配的语法为 -m 模块名 --规则选项 ,在扩展匹配条件中,同样可以使用 ! 条件 来排除指定条件

3.2.1、隐式扩展

使用 -p 协议名称 对指定的协议进行的扩展,可省略 -m 选项, -p tcp-m tcp 不冲突,-p 用于匹配报文的协议,-m 用于指定扩展模块的名称

  • 参数说明

    参数 解释
    –sport PORT[-PORT] 源端口,可以是单个端口或连续多个端口
    –dport PORT[-PORT] 目标端口,可以是单个端口或连续多个端口
    –tcp-flags LIST1 LIST2 检查 LIST1 所指明的所有标志位
    且这其中 LIST2 所表示出的所有标记位必须为 1,而余下的必须为 0;
    没在 LIST1 中指明的,不作检查
    可用标志位:SYN、ACK、 FIN、RST、PSH、URG
    –syn 用于匹配 tcp 新建连接的请求报文
    相当于使用 –tcp-flags SYN,RST,ACK,FIN SYN
  • 示例

    [root@localhost ~]# iptables -t filter -A OUTPUT -d 192.168.137.10 -p tcp -m tcp --sport 22 -j DROP
    [root@localhost ~]# iptables -t filter -A INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN -j REJECT
    [root@localhost ~]# iptables -t filter -A INPUT -p tcp -m tcp --dport 22 --tcp-flags ALL SYN -j REJECT
    [root@localhost ~]# iptables -t filter -A INPUT -p tcp -m tcp --dport 22 --syn -j REJECT
    

3.2.2、显式扩展

显式扩展必须使用 -m 显式指明使用的扩展模块,可以使用 rpm -ql iptables | grep "\.so" 查看支持的扩展

3.2.2.1、multiport扩展

multiport 扩展可以使用离散方式定义多端口匹配(最多指定 15 个端口)

  • 参数说明

    参数 解释
    –sports port[,port | port:port] 指明多个离散的源端口
    –dports port[,port | port:port] 指明多个离散的目标端口
    –ports port[,port | port:port] 指明多个离散的端口(双向控制)
  • 示例

    iptables -I INPUT -s 192.168.137.10 -d 192.168.137.100 -p tcp -m multiport --dports 22,80 -j ACCEPT
    iptables -I OUTPUT -d 192.168.137.100 -s 192.168.137.10 -p tcp -m multiport --sports 22,80 -j ACCEPT
    

3.2.2.2、iprange扩展

iprange扩展用于连续的 ip 地址范围时使用

  • 参数解释

    参数 解释
    –src-range 开始ip地址-结束ip地址 指定连续的源 ip 地址范围
    –dst-range 开始ip地址-结束ip地址 指定连续的目标 ip 地址范围
  • 示例

    [root@localhost ~]# iptables -I INPUT -d 192.168.137.100 -p tcp -m multiport --dports 22:23,80 -m iprange --src-range 192.168.137.1-192.168.137.10 -j ACCEPT
    [root@localhost ~]# iptables -I OUTPUT -s 192.168.137.100 -p tcp -m multiport --sports 22:23,80 -m iprange --dst-range 192.168.137.1-192.168.137.10 -j ACCEPT		
    

3.2.2.3、string扩展

检查报文中出现的字符串

  • 参数解释

    参数 解释
    –algo 字符串比对算法(必选项)
    –string 字符串 指定需要匹配的字符串
  • 示例

    [root@localhost ~]# iptables -I OUTPUT -m string --algo bm --string 'html' -j REJECT
    

3.2.2.4、time扩展

根据报文到达的时间与指定的时间范围进行匹配

注意:在使用 --timestart--timestop 参数时,需要搭配 --kerneltz 参数,否则 iptables 默认使用 UTC 时间,会比实际时间晚 8 个小时

  • 参数解释

    参数 解释
    –datestart 指定日期范围的开始日期,不可取反
    –datestop 指定日期范围的结束日期,不可取反
    –timestart 指定时间范围的开始时间,不可取反
    –timestop 指定时间范围的结束时间,不可取反
    –monthdays 指定那一天(1-31),可取反
    –weekdays 指定星期几(周一到周日),可取反
    –kerneltz 使用当前系统设置时区的时间,不加此参数,默认使用 UTC 时间
  • 示例

    [root@localhost ~]# iptables -t filter -I INPUT -p icmp -m time --timestart 16:00:00 --timestop 20:00:00 --kerneltz -j REJECT
    [root@localhost ~]# iptables -t filter -I INPUT -p icmp -m time --datestart 2023-1-5 --datestop 2023-1-6 -j DROP
    [root@localhost ~]# iptables -t filter -I INPUT -p icmp -m time --weekdays 3,5 -j DROP
    [root@localhost ~]# iptables -t filter -I INPUT -p icmp -m time --monthdays 5,7 -j DROP
    

3.2.2.5、connlimit扩展

根据每客户端 ip(也可以是地址块)做并发连接数数量匹配

  • 参数解释

    参数 解释
    –connlimit-above n 连接的数量大于 n 就动作
    –connlimit-upto n 连接的数量小于或等于 n 就动作
  • 示例

    [root@localhost ~]# iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j DROP
    

4、执行的动作

参数 解释
ACCEP 接受(常用)
DROP 丢弃(常用)
REJECT 拒绝
RETURN 返回调用链
REDIRECT 端口重定向
LOG 记录日志(常用)
MARK 做防火墙标记
DNAT 目标地址转换(用于NAT地址转换)
SNAT 源地址转换(用于NAT地址转换)
MASQUERADE 地址伪装

5、NAT

5.1、数据包的流转

  • 数据包先经过 NAT 表的 PREROUTING 链

  • 经由路由判断确定这个数据包是否要进入本机

  • 若不进入本机,再经过 Filter 表的 FORWARD 链

  • 通过 NAT 表的 POSTROUTING 链,最后传送出去

5.2、NAT分类

  • SNAT

    只修改请求报文的源地址,用于私网转公网

  • DNAT

    只修改请求报文的目标地址,用于服务映射

5.3、nat表相关链

  • PREROUTING:用于 DNAT

  • OUTPUT

  • POSTROUTING:用于 SNAT

5.4、SNAT(源地址转换)

5.4.1、固定公网ip转换

  • 语法

    iptables -t nat -A POSTROUTING -s 内网地址 ! -d 内网地址 -j SNAT --to-source 公网ip
    
  • 示例

    # 开启Linux转发功能
    [root@localhost ~]# echo "1" > /proc/sys/net/ipv4/ip_forward
    
    # 允许内网中所有数据包通过
    [root@localhost ~]# iptables -A INPUT -i ens33 -j ACCEPT
    
    # SNAT
    [root@localhost ~]# iptables -t nat -A POSTROUTING -s 172.16.10.0/24 ! -d 172.16.10.0/24 -j SNAT --to-source 192.168.137.100
    
    # 查看NAT规则
    [root@localhost ~]# iptables -t nat -nxL --line
    Chain POSTROUTING (policy ACCEPT)
    num  target     prot opt source               destination
    1    SNAT       all  --  172.16.10.0/24      !172.16.10.0/24       to:192.168.137.100
    

5.4.2、动态公网ip(地址伪装)

  • 语法

    iptables -t nat -A POSTROUTING -s 内网地址 ! -d 内网地址 -j MASQUERADE
    
  • 示例

    # SNAT
    [root@localhost ~]# iptables -t nat -A POSTROUTING -s 172.16.10.0/24 ! -d 172.16.10.0/24 -j MASQUERADE
    
    # 查看NAT规则
    [root@localhost ~]# iptables -t nat -nxL --line
    Chain POSTROUTING (policy ACCEPT)
    num  target     prot opt source               destination
    1   MASQUERADE  all  --  172.16.10.0/24      !172.16.10.0/24
    

5.5、DNAT(目标地址转换)

  • 语法

    iptables -t nat -A PREROUTING -d EXT_IP -p tcp|udp --dport PORT -j DNAT --to-destination INTER_SERVER_IP[:PORT]
    
  • 示例

    # DNAT
    [root@localhost ~]# iptables -t nat -A PREROUTING -d 192.168.137.100 -p tcp --dport 80 -j DNAT --to-destination 172.16.10.10:80
    
    # 查看NAT规则
    [root@localhost ~]# iptables -t nat -nxL --line
    Chain PREROUTING (policy ACCEPT)
    num  target     prot opt source               destination
    1    DNAT       tcp  --  0.0.0.0/0            192.168.137.100      tcp dpt:80 to:172.16.10.10:80
    

5.6、链接跟踪表容量和超时时间设置

vim /etc/sysctl.conf
# 增加 ip_conntrack_max 值
net.ipv4.ip_conntrack_max = 393216
net.ipv4.netfilter.ip_conntrack_max = 393216

# 降低 ip_conntrack timeout 时间
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 300
net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 120
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 60
net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 120