iptables
是 Linux系统中用于管理网络包过滤的工具。它可以用来设置规则,以控制网络数据包的流动。iptables
可以用于防火墙、网络地址转换(NAT)和网络包过滤等多种用途。
本文章就带大家,入门iptables的使用,并配合一定样例,看看具体如何使用。
关于iptables
工作原理是基于内核中的netfilter
模块,可以通过在不同的链中添加规则来过滤、修改或重定向网络数据包。
可以说,iptables
是 Linux 系统中最常用的网络安全工具之一,在软件层面,大部份的个人服务器使用iptables
对Linux服务器端口进行管理,已经足够使用了。
当然,现在有很多新的网络数据包工具,比如:iptables
的继任者nftables
;但是,我目前还是更习惯用iptables
,也许后续再出其他工具的教程吧。
iptables 的官方文档可以在以下网址找到: https://www.netfilter.org/documentation
此外,iptables的Wiki 百科页面也提供了很多有用的信息和示例。
iptables就是防火墙?
很多人使用iptables
充当Linux的网络防火墙,这样当然可以,并且大多数情况满足个人防火墙需求。
但是,实际上iptables
不单单只能用于防火墙(拦截IP、封禁端口等);除了用作防火墙,iptables
还可以用于以下用途:
- 网络地址转换(NAT):可以使用
iptables
将一个 IP 地址转换为另一个 IP 地址,实现网络地址转换。 - 限制带宽:可以使用
iptables
限制特定主机或网络的带宽使用量。 - 端口转发:可以使用
iptables
将一个端口的流量转发到另一个端口,实现端口转发。 - 流量控制:可以使用
iptables
控制特定主机或网络的流量,限制其带宽使用量,实现限速等操作。 - 日志记录:可以使用
iptables
记录网络数据包的流向和状态,以便进行故障排除。
比如:转发tcp 8080
到tcp 8090
:
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 8090
总之,iptables
是一个非常强大的工具,可以用于多种网络管理任务。
iptables使用前
首先,作为一个内核工具。现在iptables
基本已经内置在Linux内。
- Ubuntu从版本8.04开始,默认支持iptables;
- Debian从版本3.1开始,默认支持iptables;
- CentOS从版本4开始,默认支持iptables;
在比较新的Linux发行版本,iptables已经默认支持并启动。在Debian高版本上,iptables
是一个独立的防火墙工具,它不依赖于systemd
或其他系统初始化和进程管理器。因此,即使systemd
没有提供iptables
服务。
如果你的系统没有自带iptables
,可以使用命令进行安装:
# Ubuntu/Debian
sudo apt install iptables
# CentOS
sudo yum install iptables
查看iptables
是否运行:
# 实际上这条命令是查看filter表的状态
sudo iptables -L
如果该命令能够正常输出防火墙规则,则说明iptables已经在运行中。如果该命令无法输出规则,则说明iptables未启动。在大多数情况下,iptables会随着系统启动而自动启动,您无需手动开启。
接下来,我们就来介绍介绍iptables
的使用。
基础概念
iptables是一个Linux系统下的防火墙工具,它通过定义表、链和规则来实现对网络数据包的过滤和转发控制。
每个链包含多个规则,规则是 iptables 中最基本的单位,用于匹配数据包和执行操作。每个规则都包含多个匹配条件和动作,匹配条件用于匹配数据包,动作用于执行操作,如 ACCEPT、DROP、REJECT 等。
- 表(Table):iptables中的表是一个逻辑容器,用于存储相关联的链和规则。Linux系统中默认包含4个表,分别是filter、nat、mangle和raw。其中,filter表用于过滤数据包,nat表用于网络地址转换,mangle表用于修改数据包的特定字段,raw表用于禁止Linux内核对数据包进行处理。
- 链(Chain):iptables中的链是一系列规则的集合,用于对数据包进行过滤和转发。Linux系统中默认包含3个链,分别是INPUT、FORWARD和OUTPUT。其中,INPUT链用于处理进入Linux系统的数据包,FORWARD链用于处理转发的数据包,OUTPUT链用于处理从Linux系统出去的数据包。用户可以自定义链,将其添加到表中。
- 规则(Rule):iptables中的规则是用于指定对数据包的处理方式。每个规则都包含一个匹配条件和一个动作。匹配条件可以是数据包的源地址、目的地址、协议类型、端口等等,动作可以是DROP(丢弃数据包)、ACCEPT(接受数据包)、REJECT(拒绝数据包)、SNAT(源地址转换)等等。
它们的关系图:
+------------------------+
| Table |
+------------------------+
| Chain 1 |
+------------------------+
| Chain 2 |
+------------------------+
| Chain 3 |
+------------------------+
| ... |
+------------------------+
| Chain N |
+------------------------+
| ... |
+------------------------+
| Rule 1 |
+------------------------+
| Rule 2 |
+------------------------+
| Rule 3 |
+------------------------+
| ... |
+------------------------+
| Rule M |
+------------------------+
综上所述,iptables的表、链、规则之间的关系是:表是一个逻辑容器,包含了多个链和规则;链是一系列规则的集合,用于对数据包进行过滤和转发;规则是用于指定对数据包的处理方式,包含一个匹配条件和一个动作。用户可以通过定义表、链和规则来实现对网络数据包的过滤和转发控制。
iptables
的数据包的流转流程可以参考下图:
iptables基础命令
iptables
的基础命令组成:
iptables [ -t 表名] 命令选项 [链名] [条件匹配] [-j 处理动作或跳转]
注:
-t 表名
在缺省状态下,默认为filter
表,即默认-t filter
。
命令选项:
-L
: 列出一个或所有链的规则-v
: 显示详细信息,包括每条规则的匹配句数量和匹配字节数-x
: 在v的基础上,禁止自动换算单位(K,M)-n
: 只显示ip地址和端口号,不显示域名和服务名称-I
: 插入到防火墙第一条生效-A
: 添加链是添加到最后一条-D
: 删除指定链中的某一条规则,按规则序号或内容确定要删除的规则-F
: 清空指定链中的所有规则,默认清空表中所有链的内容-X
: 删除指定表中用户自定义的规则链
举个例子,我们查看iptables
的全部Table(没有指定-t,实际指向filter):
sudo iptables -L
当然,如果你还想指定查找表下的某条链,你可以:
# 查找filter表下的WEB_BAN_IP链
sudo iptables -L WEB_BAN_IP
匹配条件:
-i
: 入站请求interface(网卡)-o
: 出站请求interface(网卡)-s
: 入站源地址-d
: 目标地址-p
: 指定规则协议,如tcp, udp,icmp等,可以使用 all 来指定所有协议--dport
: 目的端口,数据包的目的(dport)地址是80,就是要访问我本地的80端口--sport
: 来源端口 数据包的来源端口是(sport)80,就是对方的数据包是80端口发送过来的。
动作
ACCEPT
:允许数据包通过。DROP
:直接丢弃数据包,不给任何回应信息,这时候客户端会感觉自己的请求泥牛入海了,过了超时时间才会有反应。REJECT
:拒绝数据包通过,必要时会给数据发送端一个响应的信息,客户端刚请求就会收到拒绝的信息。(一般不使用REJECT(拒绝)行为,REJECT会带来安全隐患。)SNAT
:源地址转换,解决内网用户用同一个公网地址上网的问题。MASQUERADE
:是SNAT的一种特殊形式,适用于动态的、临时会变的ip上。DNAT
:目标地址转换。REDIRECT
:在本机做端口映射。LOG
:在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则,也就是说除了记录以外不对数据包做任何其他操作,仍然让下一条规则去匹配。
当然,上述的动作和匹配条件,组合我们常说的规则(规则放在表里~)。接下来,我们看看iptables的规则。
iptables规则
规则大致由两个逻辑单元组成:匹配条件和动作。
最常用的匹配条件是源地址
、目标地址
、源端口
、目标端口
;
最常用的动作有ACCEPT
(接受)、DROP
(丢弃)、REJECT
(拒绝)。
在实际操作 iptables 的过程中,是以“表”作为操作入口的,也就是-t
后跟表;以链为具体的规则。
查看链详情
上文我们说到,使用-L
可以查看表的详情,加上-v
参数,可以查看更多详情:
sudo iptables -vL
以上字段含义:
Chain WEB_BAN_IP
:表示规则链的名称,即WEB_BAN_IP
。(0 references)
:表示该规则链当前未被引用。pkts
:表示匹配该规则链的数据包数量。bytes
:表示匹配该规则链的数据包总字节数。target
:表示匹配该规则链的数据包将被发送到的目标,可以是另一个规则链或一个动作(如ACCEPT、DROP、REJECT等)。prot
:表示匹配该规则链的数据包的协议类型,如TCP、UDP、ICMP等。opt
:表示匹配该规则链的数据包的选项,如TCP标志位、IP地址等。in
:表示匹配该规则链的数据包的输入接口。out
:表示匹配该规则链的数据包的输出接口。source
:表示匹配该规则链的数据包的源IP地址或IP地址范围。destination
:表示匹配该规则链的数据包的目标IP地址或IP地址范围。
可以看到,我的WEB_BAN_IP
链上,已经有了数据。如何查看它们时候,还显示行标呢?
加上--line-numbers
参数即可:
sudo iptables -vL WEB_BAN_IP --line-numbers
删除链内规则
而删除就可以使用-D
命令:
# 删除第2项规则
sudo iptables -D WEB_BAN_IP 2
# 删除最后1项规则
sudo iptables -D WEB_BAN_IP -1
# 删除第2到4项规则
sudo iptables -D WEB_BAN_IP 2-4
当然,你也可以模糊匹配删除:
# 删除源IP为134.122.135.178
sudo iptables -D WEB_BAN_IP -s 134.122.135.178 -j DROP
# 删除源IP为134.122.135.178且目标动作为DROP
sudo iptables -D WEB_BAN_IP -s 134.122.135.178
添加链内规则
那么我这些规则是怎么添加的呢?
实际上,我是使用脚本扫描Nginx日志,对频繁请求网站的IP进行软件层面的流量封禁。所以,禁用的语句:
# 添加来源36.248.233.107,执行目标动作为丢弃
sudo iptables -I INPUT -s 36.248.233.107 -j DROP
当然,如果你想精确一些:
# 指定36.248.233.107无法通过TCP访问443端口(丢弃匹配包)
sudo iptables -A WEB_BAN_IP -s 36.248.233.107 -p tcp --dport 443 -j DROP
-A
选项表示添加规则,-s
选项指定源 IP 地址,36.248.233.107
是具体的 IP 地址,-p
选项指定协议类型,tcp
表示TCP
协议,--dport
选项指定目标端口,443
表示 HTTPS 默认端口,-j
选项指定目标动作,DROP
表示丢弃匹配的数据包。
这条规则的作用是禁止源 IP 地址为 36.248.233.107 的主机通过 TCP 协议访问 443 端口。
是不是有小伙伴好奇,我这个WEB_BAN_IP
是怎么来的?其实这个就是自定义链,接下来,我来介绍一下。
自定义iptables链
iptables中,如何自定义一个链并关联到Input内?
创建新链
使用以下命令在filter
表内创建一个名为WEB_BAN_IP
的新链:
# 默认filter
sudo iptables -N WEB_BAN_IP
# 你也可以指定filter
sudo -t filter -N WEB_BAN_IP
这个时候,这个链并没有被任何默认链进行引用;即使你现在对其增加规则,它也是不会生效的:
sudo iptables -vL WEB_BAN_IP
发现:Chain WEB_BAN_IP (0 references)
所以,我们需要引用。
引用新链接
使用以下命令将新链添加到INPUT链中:
sudo iptables -A INPUT -j WEB_BAN_IP
没错,通常情况下,
-j
后面跟的是预定义的操作,例如"DROP"、"REJECT"、"ACCEPT"等。但是,也可以使用-j
选项来指定自定义链的名称,以便在该链中执行更多的规则。在这种情况下,当匹配到规则时,数据包将被传递到指定的自定义链中,以便在该链中执行更多的规则。这可以帮助组织和管理iptables规则,使其更易于维护和修改。
现在,在WEB_BAN_IP
链中添加规则,这些规则将在数据包到达INPUT
链时执行。
# 允许22端口数据
sudo iptables -A WEB_BAN_IP -p tcp --dport 22 -j ACCEPT
# 丢弃其他数据
sudo iptables -A WEB_BAN_IP -j DROP
例如,上面的规则将允许TCP端口22的传入连接,并拒绝所有其他传入连接。
删除和清除
如果想删除mychain链及其规则,可以使用以下命令:
# 取消引用
sudo iptables -D INPUT -j WEB_BAN_IP
# 清空表
sudo iptables -F WEB_BAN_IP
# 删除表
sudo iptables -X WEB_BAN_IP
流量转发
iptables可以通过NAT表来进行流量转发,具体方法如下:
开启IP转发功能
首先需要开启Linux系统的IP转发功能,可以通过以下命令进行开启:
echo 1 > /proc/sys/net/ipv4/ip_forward
也可以修改/etc/sysctl.conf
文件中的net.ipv4.ip_forward
参数为1,使其永久生效。
添加转发规则
接下来,需要添加转发规则,将来自某个端口或IP地址的数据包转发到另一个端口或IP地址。
如果只是端口的转发,直接:
sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80
这条iptables规则中各个参数的解释:
-t nat
:这是指定iptables要操作的表,这里是"nat"表,用于网络地址转换(NAT)。-A PREROUTING
:这是指定要添加的规则的位置,这里是PREROUTING
链。PREROUTING
链用于在数据包进入路由之前修改它们的目的地IP地址。-p tcp
:这是指定要匹配的协议,这里是TCP协议。--dport 8080
:这是指定要匹配的目标端口号,这里是8080端口。-j REDIRECT
:这是指定要执行的动作,这里是重定向。--to-port 80
:这是指定重定向的目标端口号,这里是80端口。
综上所述,这条规则的作用是将进入系统的TCP协议、目标端口为8080的数据包重定向到80端口。
当然,如果你想跨网卡转发,就更复杂一些:
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination <eth1 IP>:80
sudo iptables -A FORWARD -i eth0 -p tcp --dport 80 -o eth1 -j ACCEPT
第一条规则:
-i eth0
:这是指定要匹配的输入接口,这里是eth0接口。-j DNAT
:这是指定要执行的动作,这里是目标地址转换(DNAT)。--to-destination <eth1 IP>:80
:这是指定目标地址转换的目标地址和端口号。<eth1 IP>
应该替换为eth1接口的IP地址,这里是将8080端口的流量转发到eth1接口上的80端口。
综上所述,第一条规则的作用是将进入系统的TCP协议、目标端口为8080的数据包的目标地址转换为eth1接口的IP地址,并将目标端口号修改为80。
第二条规则:
-A FORWARD
:这是指定要添加的规则的位置,这里是FORWARD链。FORWARD链用于控制转发数据包的流量。-i eth0
:这是指定要匹配的输入接口,这里是eth0接口。-o eth1
:这是指定要匹配的输出接口,这里是eth1接口。-j ACCEPT
:这是指定要执行的动作,这里是接受数据包。
综上所述,第二条规则的作用是允许进入系统的TCP协议、目标端口为80的数据包从eth0接口转发到eth1接口。
同时,一般端口转发和双网卡情况,发生在路由器内,在路由器内,我们还需要:
sudo iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
解释一下:
-j MASQUERADE
:指定动作为MASQUERADE,即对数据包进行源IP地址伪装(也称为SNAT),将源IP地址改为路由器的IP地址。
如果只有上述两条iptables规则,是可以将来自eth0接口的8080端口流量转发到eth1接口上的80端口的。但是,如果路由器上有其他网络接口,比如WAN口,那么在没有MASQUERADE规则的情况下,路由器上的其他网络接口将无法访问Internet。因此,通常情况下,在进行NAT转换时,都需要添加MASQUERADE规则,以便对从局域网内发出的流量进行源IP地址伪装,从而保证路由器上的其他网络接口可以正常访问Internet。
保存iptables
iptables
的规则存储在内核空间(操作系统内核运行的内存空间,位于内存内)中,而不是存储在磁盘上。当你添加一条规则时,iptables
会将它添加到内核的规则表中。因此,当你重新启动系统时,iptables
的规则将会丢失,因为它们没有被保存到磁盘上。
所以,我们来看看如何保存iptables
的配置。
导出iptables
使用iptables-save
命令,进行iptables
内的规则导出:
sudo iptables-save > iptables-Backup
比如我这里导出:
这样,就导出完成了。我们在重启后,表内文件被恢复或者清空,可以用这个文件进行恢复。
恢复iptables
如何还原内,其实也十分简单,使用iptables-restore
命令即可:
sudo iptables-restore < iptables-Backup
到此,就恢复完成了。
开机自动配置
如何实现开机自动配置呢?
你可以使用自己的脚本,加入系统的启动脚本内。也可以使用iptables-persistent
(CentOS上使用iptables-services
)。
首先查看系统当前是否有安装iptables-persistent
:
# Debian
sudo which iptables-persistent
# CentOS
sudo which iptables-services
如果没有安装:
# Debian上安装iptables-presistant
sudo apt install iptables-persistent
# CentOS上安装iptables-services
sudo yum install iptables-services
接下来看看如何保存。
Debian上,在安装了iptables-persistent
包并配置好规则后,我们只需要保存配置到/etc/iptables/rules.v4
和/etc/iptables/rules.v6
,这些规则会在系统启动时,由iptables-persistent
自动加载。
如果是在CentOS,那么只需要在配置好规则后,使用命令sudo service iptables save
即可保存配置,并在开机时候自动挂载。
END
好啦,本次的文章就到这里。虽然iptables
可以为系统提供强大的安全保护,但是它也是一个非常复杂和强大的工具,需要仔细地使用。
因此,在使用iptables
时,请务必小心谨慎,并确保了解正在执行的每个操作的含义和影响。
如果您想深入了解 iptables 的更多高级用法和技巧,建议查看官方文档或参考其他相关资料。