Iptables使用
通过iptables防火墙,用户可对与Linux系统进行交互的IP数据包执行高度的控制,而且这一控制是在Linux内核中实现。iptables策略是由一组有序的规则建立,它告诉内核应如何处理某些类别的数据包。iptables规则应用于一个表中的一个链,一个iptables链是一个规则集,这些规则按顺序与包含共同特征的数据包进行比较。
iptables基础介绍
表
表是iptables构建块,描述了其功能的大类,如包过滤或者网络地址转换(NAT)。iptables中共有四个表:filter、nat、mangle和raw,过滤规则应用于filter表,NAT规则应用于nat表。
链
每个表都有自己的一组内置链,对我们来说,最重要的内置链是filter表中的INPUT、OUTPUT和FORWARD链:
INPUT:当流入的数据包指向本地主机时,将经过INPUT链的检查。OUTPUT:OUTPUT链用于本地主机自身生成的数据包。FORWARD:FORWARD链管理经过Linux系统路由的数据包。
另外两个很重要的链是nat表中的PREROUTING和POSTROUTING链,分别用于IP路由之前和之后修改数据包的头部。
下图展示了数据包是如何通过nat和filter表的不同链:

由图可知,为了实现对Linux服务器的访问进行控制,主要就是针对filter表的INPUT链进行配置管理。
规则匹配
每个iptables规则都包含一组匹配以及一个目标,后者告诉iptables对于符合规则的数据包应该采取什么动作。常见的匹配规则如下:
- --source (-s) :匹配源
IP地址或者网络 - --destination (-d):匹配目标
IP地址或者网络 - --destination port (-dport): 匹配目标地址的端口号
- --protocol (-p):匹配协议
- --in-interface (-i):流入接口(例如:
eth0) - --out-interface (-o):流出接口
- --state:匹配一组连接状态
- --string:匹配应用层数据字节序列
目标
最后,iptables支持一组目标,用于在数据包匹配一个规则时触发一个动作。
- ACCEPT:允许数据包通过
- DROP:丢弃数据包
- LOG:将数据包信息记录到
syslog - REJECT:丢弃数据包,同时发送适当的响应报文
- RETURN:在调用链中继续处理数据包
在CentOS7中使用
CentOS7中默认使用的防火墙是firewalld,为了使用iptables,需要先禁用firewalld。
禁用firewalld
首先停止firewalld服务:
$ sudo systemctl stop firewalld
然后禁止firewalld服务开机自启动:
$ sudo systemctl disable firewalld
为了防止firewalld服务被其他服务再次启动:
$ sudo systemctl mask --now firewalld
安装iptables
先检查是否已经安装了iptables:
$ sudo systemctl status iptables
确认没有安装后通过包管理器进行安装:
$ sudo yum install iptables-services
安装成功后启动服务:
$ sudo systemctl start iptables
设置开机自启动:
$ sudo systemctl enable iptables
查看服务运行状态:
$ sudo systemctl status iptables
● iptables.service - IPv4 firewall with iptables
Loaded: loaded (/usr/lib/systemd/system/iptables.service; enabled; vendor preset: disabled)
Active: active (exited) since Thu 2019-12-19 13:31:35 CST; 1min 30s ago
Main PID: 2966 (code=exited, status=0/SUCCESS)
出现以上信息,则表明服务运行正常。接下来可查看当前的iptables默认规则:
$ sudo iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
113 6860 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT 66 packets, 6232 bytes)
pkts bytes target prot opt in out source destination
定义过滤规则
定义规则的命令格式如下:
$ sudo iptables -t <table> -A <chain> -i <interface> -p <protocol (tcp/udp) > -s <source> --dport <port no.> -j <target>
参数说明可参考上文中的操作选项归纳说明,这里的-t指定需定义规则的表,默认为filter。
开启HTTP(端口80)、SSH(端口22)和SSL(443)三个服务
$ sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
规则添加后查看如下:
$ sudo iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
69 4580 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
结果表明,所有访问80、22和443端口的TCP请求都被允许。
根据源IP地址限制访问
例如允许IP为192.168.1.3访问本机:
$ sudo iptables -A INPUT -s 192.168.1.3 -j ACCEPT
也可以通过DROP目标限制某一IP地址访问:
$ sudo iptables -A INPUT -s 192.168.1.3 -j DROP
如果需要限制源地址为IP段,可通过掩码设定:
$ sudo iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT
丢弃所有其他访问请求
定义好允许访问的规则之后,通常需要将其他未授权的访问请求都禁止掉,以达到访问控制的目的:
$ sudo iptables -A INPUT -j DROP
也可以通过定义整个INPUT链的策略来限制未授权的访问:
$ sudo iptables -P INPUT DROP
如果是远程修改
iptables规则,在限制全局访问时,一定要先开启远程连接的端口,比如SSH(端口22),否则容易造成远程连接中断。
删除规则
如果要删除所有规则,可使用-F选项(flush):
$ sudo iptables -F
如果需要删除其中某一条规则,首先要查看所有规则的编号:
$ sudo iptables -nvL --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 306 18777 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
2 8 563 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
3 9 611 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
4 45 2532 DROP all -- * * 0.0.0.0/0 0.0.0.0/0
在每条规则的开头就是编号,比如删除编号为3的规则:
$ sudo iptables -D INPUT 3
规则保存
之前对iptables规则的操作都是保存在内存中,如果系统重启,所有的操作都会丢失,因此在修改规则完成后,需要对其进行保存。
$ sudo service iptables save
典型设置脚本示例
#!/bin/sh
# 先允许所有
iptables -P INPUT ACCEPT
#清空所有默认规则
iptables -F
#清空所有自定义规则
iptables -X
#所有计数器归0
iptables -Z
#允许来自于lo接口的数据包(本地访问)
iptables -A INPUT -i lo -j ACCEPT
#开放22端口
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
#开放21端口(FTP)
iptables -A INPUT -p tcp --dport 21 -j ACCEPT
#开放80端口(HTTP)
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
#开放443端口(HTTPS)
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
#允许ping
iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT
#其他入站一律丢弃
iptables -P INPUT DROP
#所有出站一律绿灯
iptables -P OUTPUT ACCEPT
#所有转发一律丢弃
iptables -P FORWARD DROP
#保存上述规则
service iptables save
#重启服务
systemctl restart iptables
iptables操作选项归纳说明
查看选项
| 简写 | 选项 | 说明 |
|---|---|---|
| -L | --list chain rulenum | 列出所有链及规则,默认表为filter |
| -n | --numeric | IP地址和端口显示为数字 |
| -v | --verbose | 显示详细信息 |
| --line-numbers | 显示规则编号 |
链操作选项
| 简写 | 选项 | 说明 |
|---|---|---|
| -A | --append chain rule | 向链添加规则 |
| -D | --delete chain rulenum | 通过编号删除规则 |
| -I | --insert chain rulenum | 插入规则,默认编号为1 |
| -R | --replace chain rulenum | 替换规则,默认编号为1 |
| -F | --flush chain | 删除指定链所有规则,如未指定,则删除所有链规则 |
| -P | --policy chain target | 修改链政策 |
规则选项
| 简写 | 选项 | 说明 |
|---|---|---|
| -p | --proto proto | 协议。{tcp, udp, udplite, icmp, esp, ah, sctp}等 |
| -s | --source address/mask | 源IP地址 |
| -d | --destination address/mask | 目的IP地址 |
目标选项
| 简写 | 选项 | 说明 |
|---|---|---|
| -j | --jump target | 调整到目标 |
通用选项
| 简写 | 选项 | 说明 |
|---|---|---|
| -t | --table table | 指定表,默认为filter |
| -V | --version | 查看版本 |
补充
CentOS 7配置完后发现无法使用YUM包管理器,需添加如下规则:
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
如下:
Chain INPUT (policy DROP 58 packets, 6674 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
1309 109K ACCEPT tcp -- * * 10.42.6.0/24 0.0.0.0/0 tcp dpt:22
167 17907 ACCEPT tcp -- * * 10.0.0.0/8 0.0.0.0/0 tcp dpt:80
15809 27M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED