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