使用 iptables 在 Linux 中阻止 ICMP 流量

CompTIACompTIABeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

引言

在本实验中,你将学习如何使用 iptables,一个强大的 Linux 命令行防火墙工具,来阻止入站 ICMP 流量。你将配置一个防火墙规则来丢弃 ICMP 协议的报文,该协议通常被 ping 命令用于测试网络连通性。这是通过在协议级别控制网络访问来保护 Linux 系统的一项基本技能。

你将首先使用 nmap 执行初步的网络扫描,以评估系统的开放端口。然后,你将使用 ping 来验证 ICMP 流量最初是被允许的,从而建立一个基线。实验的核心是创建并应用一个特定的 iptables 规则来丢弃所有入站 ICMP 报文。最后,你将验证规则是否生效,并通过再次尝试 ping 你的机器来测试其有效性,确认请求现在已被成功阻止。

使用 nmap 扫描开放的 TCP 和 UDP 端口

在本步骤中,你将学习如何使用 nmap 工具扫描你自己的系统以查找开放的网络端口。网络端口是操作系统中通信的端点。当一个程序想要从网络接收信息时,它会在特定端口上“监听”。扫描开放端口是评估机器安全性的基本第一步,因为每个开放端口都代表着攻击者潜在的入口点。

首先,你需要安装 nmap,因为它不包含在基础环境中。在安装新软件之前更新你的包列表是一个好习惯。

运行以下命令更新包列表:

sudo apt-get update

现在,通过运行以下命令安装 nmap

sudo apt-get install -y nmap

你应该会看到输出表明 nmap 及其依赖项正在被安装。

接下来,你需要找到你机器的 IP 地址,以便告诉 nmap 要扫描什么。你可以使用 ip 命令找到它。

ip addr show

查找类似 eth0ens33 的条目。你的 IP 地址将列在 inet 旁边。它看起来会像 172.16.50.13/24

如何从输出中识别你的 IP 地址:

  1. 查找状态为 state UP 的接口(通常是 eth0
  2. 找到以 inet 开头(不是 inet6)的行
  3. 只取 / 前面的 IP 地址部分(例如,如果你看到 inet 172.16.50.13/24,你的 IP 地址是 172.16.50.13
  4. 忽略带有 IP 127.0.0.1 的回环接口(lo

在本次实验的其余部分,我们将使用 <your_IP_address> 作为你实际 IP 地址的占位符。

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:16:3e:04:c3:1d brd ff:ff:ff:ff:ff:ff
    altname enp0s5
    altname ens5
    inet 172.16.50.13/24 metric 100 brd 172.16.50.255 scope global dynamic eth0
       valid_lft 1892159940sec preferred_lft 1892159940sec
    inet6 fe80::216:3eff:fe04:c31d/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:1d:45:49:f8 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

现在你已准备好执行你的第一次扫描。让我们开始扫描开放的 TCP(传输控制协议)端口。TCP 是一个面向连接的协议,用于许多常见服务,如 SSH(端口 22)和 HTTP(端口 80)。nmap 中的 -sT 选项执行 TCP 连接扫描。

重要提示:<your_IP_address> 替换为你从上一步找到的实际 IP 地址。例如,如果你的 IP 是 172.16.50.13,命令将是 nmap -sT 172.16.50.13

用你找到的 IP 替换 <your_IP_address> 并运行命令:

nmap -sT <your_IP_address>

输出将列出处于“open”状态的端口。你的系统默认可能开放了 SSH 端口(22),并且可能在其他端口上运行了额外的服务。

Starting Nmap 7.80 ( https://nmap.org ) at 2025-07-01 14:08 CST
Nmap scan report for iZrj93qpoj98oqswu96cqfZ (172.16.50.13)
Host is up (0.00013s latency).
Not shown: 997 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
3000/tcp open  ppp
3001/tcp open  nessus

Nmap done: 1 IP address (1 host up) scanned in 0.06 seconds

接下来,让我们扫描 UDP(用户数据报协议)端口。UDP 是一个无连接协议,用于 DNS(端口 53)和 DHCP(端口 67/68)等服务。UDP 扫描可能比 TCP 扫描慢且不太可靠。使用 sudo 可以为 UDP 扫描提供更好的结果。-sU 选项告诉 nmap 执行 UDP 扫描。

请记住:<your_IP_address> 替换为你从上一步找到的实际 IP 地址。

用你的 IP 替换 <your_IP_address> 并运行命令:

sudo nmap -sU <your_IP_address>

输出可能显示端口为 open|filtered。这意味着 nmap 无法确定端口是开放的还是被防火墙阻止了扫描。这是 UDP 扫描的常见结果。

Starting Nmap 7.80 ( https://nmap.org ) at 2025-07-01 14:09 CST
Nmap scan report for iZrj93qpoj98oqswu96cqfZ (172.16.50.13)
Host is up (0.0000060s latency).
Not shown: 998 closed ports
PORT     STATE         SERVICE
68/udp   open|filtered dhcpc
5353/udp open|filtered zeroconf

Nmap done: 1 IP address (1 host up) scanned in 1.29 seconds

通过完成这些扫描,你已成功识别出在你机器上监听网络连接的服务。

使用 ping 验证初始网络连通性

在本步骤中,你将使用 ping 命令来验证在实施任何防火墙规则之前,你的系统是否对网络请求有响应。ping 命令向目标主机发送 ICMP(互联网控制报文协议)“回显请求”报文。如果主机可达并且配置为响应,它将发送回一个“回显应答”报文。这是测试基本网络连通性的基本方法。

在我们创建防火墙规则来阻止此类流量之前,我们必须首先确认该流量当前是被允许的。这可以确保当我们稍后测试规则时,我们可以确定是规则导致了阻止,而不是其他已存在的网络问题。

我们将 ping“回环”地址 127.0.0.1。这个特殊的 IP 地址始终指向你自己的机器,允许你测试本地网络堆栈,而无需外部连接,甚至无需知道你机器分配的 IP 地址。

为了只发送四个报文然后停止,我们将使用 -c 4 选项。这一点很重要,因为如果没有它,ping 将会持续运行,直到你手动用 Ctrl+C 停止它。

打开你的终端并运行以下命令:

ping -c 4 127.0.0.1

你应该会看到输出显示发送了四个报文并接收了四个报文,这表明你的系统正在正确响应 ICMP 请求。

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.045 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.055 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.052 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.053 ms

--- 127.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3070ms
rtt min/avg/max/mdev = 0.045/0.051/0.055/0.003 ms

0% packet loss(0% 丢包率)这一行确认了连接工作正常。现在你已经建立了一个基线,你已准备好配置防火墙规则来阻止这种精确类型的通信。

创建 iptables 规则以丢弃 ICMP 报文

在本步骤中,你将使用 iptables 配置一个简单的防火墙规则。iptables 是 Linux 内核中用于管理网络数据包过滤规则的标准命令行工具。我们将创建一个规则来阻止你之前用 ping 命令测试过的 ICMP 流量。

iptables 通过一系列表(tables)、链(chains)和规则(rules)来工作。

  • 表 (Tables):这些是为特定目的收集的链的集合。最常用的是 filter 表,它是默认表,用于数据包过滤。
  • 链 (Chains):这些是按顺序检查的规则列表。对于入站流量,使用 INPUT 链。
  • 规则 (Rules):规则指定数据包的标准(如其协议或源地址)以及目标(对数据包做什么,例如 ACCEPTDROP)。

首先,让我们检查当前规则集。由于 iptables 修改内核设置,你必须使用 sudo-L 选项列出默认 filter 表中的规则。

sudo iptables -L

你将看到三个默认链:INPUTFORWARDOUTPUT。在此环境中,你可能会注意到 Docker 已经在 FORWARD 链中创建了一些规则,并为容器网络添加了自定义链。INPUTOUTPUT 链对于常规流量仍在使用默认的 ACCEPT 策略。

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy DROP)
target     prot opt source               destination
DOCKER-USER  all  --  anywhere             anywhere
DOCKER-ISOLATION-STAGE-1  all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (1 references)
target     prot opt source               destination

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

Chain DOCKER-ISOLATION-STAGE-2 (1 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

Chain DOCKER-USER (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere

现在,让我们添加一条规则来阻止入站 ICMP 报文。我们将把新规则追加(-A)到 INPUT 链。

命令的构造如下:

  • sudo iptables: 管理防火墙的命令。
  • -A INPUT: 将规则追加到 INPUT 链。
  • -p icmp: 此规则适用于使用 icmp 协议的报文。
  • -j DROP: 如果报文匹配,则跳转到 DROP 目标,该目标会静默丢弃报文,而不发送响应。

运行以下命令创建规则:

sudo iptables -A INPUT -p icmp -j DROP

如果成功,此命令不会产生任何输出。你现在已指示内核防火墙丢弃来自任何源的所有入站 ICMP 报文。

验证防火墙规则并测试阻止效果

在最后这个步骤中,你将确认你的新防火墙规则已成功添加,然后通过再次尝试 ping 你的系统来测试其效果。这种验证过程在网络管理中至关重要,以确保安全策略得到正确实施。

首先,让我们再次查看规则列表,以查看你的新添加项。通过运行与之前相同的命令,你可以看到防火墙的当前状态。

sudo iptables -L

你现在应该在 INPUT 链下看到你的新规则。输出清楚地显示,匹配 icmp 协议的报文将被发送到 DROP 目标。

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       icmp --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

既然你已确认规则已生效,让我们来测试一下。运行你在步骤 2 中使用的相同 ping 命令。

ping -c 4 127.0.0.1

这次,你将看不到任何回复。该命令会挂起几秒钟然后退出。输出将显示 100% packet loss(100% 丢包率)。这是预期行为,因为内核防火墙现在正在静默丢弃入站 ICMP 报文,正如你所指示的那样。

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.

--- 127.0.0.1 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3055ms

你已成功阻止了 ICMP 流量!你用 iptables 创建的规则不是持久性的,在系统重启后会被清除。但是,了解如何手动删除规则是一个好习惯。你可以使用 -D(delete,删除)标志来完成此操作,指定你添加的完全相同的规则。

让我们删除该规则以恢复连通性。

sudo iptables -D INPUT -p icmp -j DROP

为了确认规则已删除且连通性已恢复,请最后再运行一次 ping

ping -c 2 127.0.0.1

现在 ping 应该会成功,这证实你已成功删除了防火墙规则。

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.048 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.058 ms

--- 127.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1024ms
rtt min/avg/max/mdev = 0.048/0.053/0.058/0.005 ms

总结

在本实验中,你学习了如何在 Linux 系统上执行初步的网络侦察。你首先安装了 nmap 工具,以便在确定机器的 IP 地址后扫描开放的 TCP 和 UDP 端口。在此之后,你使用 ping 命令建立了网络连接的基线,该命令确认系统成功接收并响应 ICMP 流量。

本次实验的核心是使用 iptables 防火墙工具来操作网络流量。你构建并向 INPUT 链应用了一个特定规则,以 DROP 所有入站 ICMP 报文,从而有效地阻止了像 ping 这样的工具。为了完成这个过程,你通过列出当前的 iptables 规则集来验证新规则是否生效,然后通过再次尝试 ping 该机器来测试阻止效果,确认请求现在已超时,符合预期。