Linux 系统安全:深入了解 iptables 防火墙
对于使用 Linux 操作系统的用户而言,保护设备安全至关重要。Linux 提供了多种安全工具,其中 iptables
是一个功能强大的命令行防火墙,它具备高度的灵活性和卓越的保护能力。
然而,由于 iptables
是一个命令行工具,初学者可能需要一些时间来熟悉它的用法。
本文将通过实际示例,为系统管理员和 Linux 学习者详细介绍常见的 iptables
命令,帮助大家快速掌握这一重要工具。
什么是 iptables?
iptables
是 Linux 系统内置的软件防火墙。它允许用户创建并定义规则,从而直接或间接地控制网络流量。通过 iptables
,您可以设定规则来允许或阻止特定端口、源 IP 地址、网络接口等的流量。
当规则被定义后,所有流量都必须经过这些规则的检查。例如,对于每一个新的连接,iptables
会检查是否存在与该连接匹配的预定义规则。如果存在,则应用该规则。如果没有匹配的规则,则会执行默认规则。
要使用 iptables
,您需要使用以下命令:
$ iptables -L -n -v
该命令的参数含义如下:
-L
:列出所有规则。-n
:以数字格式显示输出,提高性能。-v
:以详细格式显示输出。
如果直接运行不带任何参数的 iptables
命令,系统会返回以下提示信息:
iptables v1.8.7 (nf_tables): no command specified Try `iptables -h' or 'iptables --help' for more information.
如果出现类似“找不到命令 iptables”的错误,则需要手动安装它。使用以下命令在您的 Linux 发行版上安装 iptables
:
$ sudo apt-get install iptables
如果您的系统中已预装 iptables
,则会看到类似如下的输出:
#output Reading package lists... Done Building dependency tree... Done Reading state information... Done iptables is already the newest version (1.8.7-1ubuntu5). iptables set to manually installed. 0 upgraded, 0 newly installed, 0 to remove, and 35 not upgraded.
什么是防火墙?
防火墙是保护系统、网络和个人计算机的最基本安全措施之一。它可以是基于硬件或软件的,其核心是通过规则来实现保护。
大多数防火墙都具有高度可定制性,允许用户创建和编辑规则。例如,通过端口扫描可以帮助过滤掉来自互联网的数据包。此外,您还可以根据源 IP 地址或网络接口来允许或阻止特定的服务。
Linux 系统内置了 iptables
防火墙,您也可以使用其他独立的 Linux 防火墙来增强系统的安全性。
为什么需要 iptables 来配置防火墙?
既然有像 ufw
和 firewalld
这样优秀的命令行防火墙替代工具,为什么还要使用 iptables
呢?此外,还有一些简单易用且功能更丰富的独立 Linux 防火墙可供选择。
那么,iptables
在配置防火墙方面的优势是什么呢?原因包括:
- 它提供了极高的灵活性,您可以直接在数据包级别设置规则。
- 一旦掌握了其工作原理,
iptables
相对容易使用。 - 它可以直接有效地阻止不必要的网络流量。
- 它还可以将数据包重定向到备用 IP 地址。
- 它有助于保护您的系统免受拒绝服务 (DoS) 攻击。
- 以及更多!
了解 iptables 架构及其与 Netfilter 的关系
为了更深入地理解 iptables
,我们需要了解它的架构。首先,这将帮助我们理清 iptables
的不同组件。然后,我们可以利用这些组件来编写防火墙规则。
在讨论 iptables
时,我们不可避免地会提到 Netfilter。您可以将 Netfilter 视为 iptables
的“大哥”。它构建于 iptables
之上,提供了更丰富的功能来管理防火墙。实际上,iptables
是 Netfilter 实现强大防火墙功能的一种手段。
iptables
是 Netfilter 内核级钩子的命令行界面。这些钩子可以与 Linux 网络堆栈交互,从而影响最深层次的数据包处理。
那么,iptables
的架构是怎样的呢?
表 (Tables)
iptables
架构始于“表”。表负责规则的组织。每个表都根据其所做的决策类型进行分类。简单来说,表通过特定方式处理数据包,简化了整个数据包的处理流程。
iptables
提供了以下不同的表:
- filter 表:用于指定数据包过滤的决策类型。它决定数据包是否应该到达目的地。
- nat 表:用于指定地址转换的决策类型。数据包的路由在此处根据 NAT 网络确定。如果数据包无法访问 NAT,它会跳过并尝试搜索非 NAT 网络。
- mangle 表:管理数据包的特殊处理需求。例如,您可以配置它来修改数据包的标头信息,如 TTL 值。
- raw 表:允许您处理
iptables
防火墙的状态方面。通过此表,您可以在 Linux 内核开始跟踪其状态之前,根据数据包的“状态”来路由它们。它主要用于标记数据包,无论连接跟踪系统是否处理它们。如果数据包未被跟踪,则将其设置为NOTRACK
目标。
链 (Chains)
在“表”中,我们有“链”。
链在数据包旅程的不同阶段执行深入的数据包检查。例如,您可以在数据包到达端口或网络接口时检查它们。这使您可以在数据包被发送到系统进程之前做出决策。
和表类似,您也会得到不同的链,包括:
- PREROUTING 链:处理刚刚到达网络接口的数据包。
- INPUT 链:处理传入的连接请求。处理完成后,数据包将被传递给本地进程。
- OUTPUT 链:处理由本地进程产生的数据包。
- FORWARD 链:管理不适用于本地系统的数据包。它充当其他目标系统(如路由器)的载体。
- POSTROUTING 链:处理即将通过网络接口离开的数据包。
并非所有链都适用于每个表。例如,FORWARD
链仅在 mangle
、filter
和 security
表中可用。同样,POSTROUTING
链在 mangle
和 nat (SNAT)
上可用。只有 OUTPUT
链在所有表中都可用。
目标 (Target)
接下来是“目标”。当数据包到达时,它会通过链来寻找最匹配的规则。如果符合规则,则会执行相关的操作,然后将数据包移动到目标,最终决定数据包的命运。
在许多情况下,数据包可能不符合任何规则。这时,默认策略(目标)就发挥作用了。
目标可以是 ACCEPT
、DROP
和 REJECT
。这些是决定数据包命运的终止目标。
ACCEPT
:接受数据包。DROP
:丢弃数据包,使发送方无法得知系统是否存在。REJECT
:拒绝数据包。
此外,还有一些非终止目标,主要用于存储有关数据包的信息。
最常见的 iptables 命令及示例
在开始执行 iptables
命令之前,请确保:
- 您具有运行命令的管理权限。如果命令因权限不足而失败,请在命令前添加
sudo
。 - 本文并非关于如何在 Ubuntu 上配置
iptables
的教程。 - 我们将使用适用于 IPv4 的
iptables
命令。如果您要使用 IPv6,请使用ip6tables
。
检查 iptables 状态
要检查当前的 iptables
状态,请运行以下命令:
$ iptables -L -n -v
#output Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination
上面的输出包含了大量的信息,但也暗示了一个未激活的防火墙。因为目前所有链都设置为接受,并且没有任何规则。
您需要开始添加规则来激活防火墙。
向链中添加规则
添加规则时,它始终附加到链中。因此,您必须使用 -A
(追加)选项。其语法如下:
$ sudo iptables - A
但是,当您运行此命令时,它会返回以下错误:
iptables v1.8.7 (nf_tables): option "-A" requires an argument Try `iptables -h' or 'iptables --help' for more information.
以下是一些可用于添加规则的参数:
-i
:代表接口。在此,您可以指定要为其添加规则的接口,如ppp0
、eth0
等。-p
:代表协议。在此,您可以指定用于过滤数据包的协议,如ICMP
、TCP
、UDP
等。如果希望规则适用于所有协议,请使用all
。-s
:表示源地址,指定流量的来源(可以是 IP 地址或主机名)。--dport
:dport
代表目标端口,指定数据包的目标端口号。--j
:表示目标 (TARGET) 参数,指定目标名称,如ACCEPT
、DROP
或RETURN
。
编写命令时,必须按照以下顺序:
$ sudo iptables -A <chain-name> -i <interface-name> - p <protocool-name> - s <source> --dport <port no.> -j <target>
保存对 iptables 的更改
添加规则后,可以使用 iptables -save
命令保存更改。
$ sudo iptables -save
输出如下所示:
[email protected]:~$ sudo iptables-save
# Generated by iptables-save v1.8.7 on Sun May 14 13:37:34 2023
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 392 -j REJECT --reject-with icmp-port-unreachable
-A OUTPUT -o lo -j ACCEPT
COMMIT
# Completed on Sun May 14 13:37:34 2023
手动持久化规则
默认情况下,iptables
不会自动保存规则。因此,如果重启计算机,所有规则都将被删除。您需要使用以下命令来确保不必重新配置 iptables
。
对于 IPv4 规则,请运行:
$ sudo iptables-save > /etc/iptables/rules.v4
对于 IPv6 规则,请运行:
$ sudo iptables-save > /etc/iptables/rules.v6
自动持久化规则
要使规则在重启后仍然存在并自动应用,您需要安装 iptables-persistent
包。
请使用以下命令进行安装:
$ sudo apt-get install iptables-persistent
系统会弹出窗口,请按回车键选择 <Yes>
。
如果您使用的是 IPv4 表,则会显示 IPv4 规则。如果您使用的是 IPv6,则会显示相应的窗口。
注意:该软件包仅加载您保存的 iptables
规则。因此,无论何时更改 iptables
,都需要使用 iptables -save
命令保存。
重启后重新加载规则
保存规则后,您必须使用以下命令恢复它们:
$ sudo iptables-restore < /etc/iptables/rules.v4
以及
$ sudo iptables-restore < /etc/iptables/rules.v6
在本地主机上启用流量/启用环回
要在本地主机上启用流量,请使用以下命令:
$ sudo iptables -A INPUT -i lo -j ACCEPT
其中,lo
代表所有本地主机通信的环回接口。
同样,我们可以允许数据包通过环回接口离开:
$ sudo iptables -A OUTPUT -o lo -j ACCEPT
要检查规则的变化,请运行 iptables -L -n -V
命令:
#output Chain INPUT (policy ACCEPT 0 packets, 0 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 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination
在特定端口上启用流量
您可以在特定端口上启用 ACCEPT
或 REJECT
流量。
例如,SSL、HTTP 和 SSH 端口对于应用程序的正常运行至关重要。您可以向 ACCEPT
数据包添加规则,确保这些端口按预期工作。
对于 SSL,请运行以下命令:
$ sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
对于 HTTP,请运行以下命令:
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
允许 eth0
接口上的所有 HTTP 流量:
$ iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT $ iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
对于 SSH,请运行以下命令:
$ sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
允许 eth0
接口上的所有传入 SSH 流量:
$ iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT $ iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
另一个示例是为您的自定义应用程序在特定端口上启用端口流量。假设您的自定义应用使用端口 233。
要打开此端口的连接,请运行:
$ sudo iptables -A INPUT -p tcp --dport 233 -j ACCEPT
同样,您也可以使用 REJECT
目标选项禁用特定端口的连接。
让我们阻止端口 392 的所有连接:
$ sudo iptables -A INPUT -p tcp --dport 392 -j REJECT
要检查规则是否生效,请运行 iptables -L -n -v
命令:
#output Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 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 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:233 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:392 reject-with icmp-port-unreachable Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 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
删除现有规则
要删除现有规则,请运行以下命令:
$ iptables -F
或者
$ iptables --flush
注意:如果您尚未保存规则,则它们将永久丢失,无法使用 iptables -restore
恢复。
删除带有行号的规则
要删除特定规则,您需要获取带有行号的规则列表:
$ sudo iptables -L --line-numbers
#output Chain INPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh 2 ACCEPT tcp -- anywhere anywhere tcp dpt:http 3 ACCEPT tcp -- anywhere anywhere tcp dpt:https 4 ACCEPT tcp -- anywhere anywhere tcp dpt:233 5 REJECT tcp -- anywhere anywhere tcp dpt:392 reject-with icmp-port-unreachable
如果要删除 INPUT
链中的第 4 条规则,请运行以下命令:
$ sudo iptables -D INPUT 4
然后,再次运行 iptables -n -v -L
命令:
#output Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 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 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:392 reject-with icmp-port-unreachable
仅显示 INPUT 或 OUTPUT 链规则
要仅显示 INPUT
链规则,请运行以下命令:
$ sudo iptables -L INPUT -n -v --line-numbers
#ouput Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 2 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 3 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 4 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:392 reject-with icmp-port-unreachable
如果您只想查看 OUTPUT
链规则,请运行:
$ sudo iptables -L OUTPUT -n -v --line-numbers
#output Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
启动/停止/重启防火墙
如果您使用的是 RHEL/Fedora Linux 或 CentOS,则可以通过运行命令来启动、停止或重启防火墙。
$ service iptables stop $ service iptables start $ service iptables restart
您也可以使用 systemctl
命令。
但是,这些命令不适用于 Ubuntu。
在特定位置插入规则
如果要将规则插入到特定位置,必须使用以下命令。
首先,检查规则:
$ sudo iptables -L INPUT -n --line-numbers
#output Chain INPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 2 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 3 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 4 REJECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:392 reject-with icmp-port-unreachable
如果在 2 和 3 之间插入规则,请运行以下命令:
$ sudo iptables -I INPUT 3 -s 252.32.1.2 -j DROP
现在,检查更新后的规则:
#output Chain INPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 2 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 3 DROP all -- 252.32.1.2 0.0.0.0/0 4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 5 REJECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:392 reject-with icmp-port-unreachable
阻止传入流量但允许传出流量
您需要输入以下命令来阻止所有传入流量:
$ iptables -P INPUT DROP $ iptables -P FORWARD DROP $ iptables -P OUTPUT ACCEPT $ iptables -A INPUT -m state --state NEW,ESTABLISHED -j ACCEPT $ iptables -L -v -n
这样,您可以 ping 或下载数据包,但会阻止任何未知的传入流量。
阻止特定 IP 地址
要阻止特定 IP 地址,请运行以下命令:
$ iptables -A INPUT -s 14.23.59.9 -J DROP
您也可以定义一个变量来存储要阻止的 IP 地址,然后运行命令:
BLOCK_THE_IP = “a.b.c.d”
然后运行:
$ iptables -A INPUT -s “BLOCK_THE_IP” -j DROP
注意:将“abcd”更改为您要阻止的 IP 地址。
允许系统从外部 ping
您可以允许外部用户 ping 您的服务器,以使您的网络可被发现:
$ sudo iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT $ sudo iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
允许内部网络与外部网络对话
运行以下命令,允许内部网络(如 eth0
)连接到外部网络(如 eth1
):
$ sudo iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
允许出站 DNS
要允许 DNS 连接到您的服务器,请运行以下命令:
$ iptables -A OUTPUT -p udp -o eth0 --dport 53 -j ACCEPT $ iptables -A INPUT -p udp -i eth0 --sport 53 -j ACCEPT
允许来自特定网络的 Rsync
如果您使用 Rsync 命令,并希望通过特定网络启用它,请运行以下命令:
iptables -A INPUT -i eth0 -p tcp -s 192.168.101.0/24 --dport 873 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 873 -m state --state ESTABLISHED -j ACCEPT
阻塞端口
运行以下命令来阻止特定端口的传入请求:
iptables -A INPUT -p tcp --dport 80 -j DROP iptables -A INPUT -i eth1 -p tcp --dport 80 -j DROP
阻止到特定 IP 地址的传出流量
您可以通过运行以下命令来阻止流向任何 IP 地址的流量:
$ host -t a techblik.com.com
# 输出
techblik.com.com 的地址是 172.66.40.93
要阻止流向此特定 IP 地址的传出流量,请运行以下命令:
iptables -A OUTPUT -d 72.66.40.93 -j DROP
同样,您也可以屏蔽 Instagram、Twitter 和 Facebook 等社交媒体平台。
通过运行以下命令查找社交媒体 IP 地址:
$ host -t a social-media-web-adrress.com
例如,对于 Instagram,它将是:
$ host -t a www.instagram.com
现在,您需要找到该特定社交媒体平台的 IP 地址的 CIDR:
$ whois 185.89.219.11 | grep CIDR
注意:您可能需要通过运行 sudo apt-get install whois
来安装 whois
包。
现在,按以下格式输入 CIDR 值:
$ iptables - A OUTPUT -p tcp -d CIDR-value -j DROP
注意:确保相应地更改 CIDR 值。
允许或阻止 ICMP Ping 请求
要允许或阻止 ICMP ping 请求,请运行以下命令:
$ iptables -A INPUT -p icmp --icmp-type echo-request -j DROP $ iptables -A INPUT -i eth1 -p icmp --icmp-type echo-request -j DROP
打开特定范围的端口
要打开一系列端口,请运行以下命令:
$ iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 8933: 8500 -j ACCEPT
列出 NAT 规则
要列出 NAT 规则,请运行以下命令:
$ sudo iptables -t nat -L -n -v
或者
$ sudo iptables -t nat -v -L -n --line-number
重置数据包计数器
要检查当前的 iptables 计数器:
$ sudo iptables -L -n -v
要重置或清除计数器,请运行以下命令:
$ sudo iptables -Z $ sudo iptables -L -n -v
仅重置 INPUT
链计数器,请运行:
$ iptables -Z INPUT
要重置特定规则的计数器