
1. 项目概述从攻击视角理解防御最近在复现一些经典的网络攻防场景发现很多朋友对防火墙规则的理解还停留在“开端口、关端口”的层面。实际上一个真正有效的防御策略必须建立在对攻击手法有清晰认知的基础上。这次我打算在Kali Linux这个“攻击者”常用的平台上反过来扮演“防御者”的角色用最经典的iptables工具来模拟构建一套对抗SSH暴力破解和Ping洪水攻击的动态防火墙规则。你可能会问为什么用Kali直接在CentOS或者Ubuntu上演示不更贴近生产环境吗我的考虑是Kali Linux预装了大量的安全测试工具这让我们可以非常方便地在本机就发起模拟攻击观察攻击流量并实时调整防御策略形成一个完整的“攻防闭环”实验环境。这比单纯地罗列几条iptables命令要有趣和深刻得多。通过这个实验你不仅能学会如何配置防火墙更能理解攻击是如何发生的以及每条防御规则背后的设计逻辑。无论你是运维工程师、安全爱好者还是正在学习网络安全的同学这套从攻击到防御的实战推演都能让你对网络边界安全有一个更立体的认识。2. 实验环境搭建与核心思路2.1 实验环境规划与准备工欲善其事必先利其器。我们先来明确并搭建实验环境。我使用的是VMware Workstation 17 Pro创建了一台Kali Linux虚拟机。这里的关键点在于网络配置。为了模拟最真实的攻防场景我建议将虚拟机的网络适配器设置为“桥接模式”。这样你的Kali虚拟机将和你宿主机在同一个局域网内拥有一个独立的IP地址可以完全模拟一台独立的主机进行网络通信。如果你使用NAT模式虽然也能上网但一些涉及外部网络访问的测试可能会受到虚拟网络结构的限制。安装好Kali后第一件事是更新系统并安装必要的工具。打开终端执行sudo apt update sudo apt upgrade -y sudo apt install -y iptables-persistent net-toolsiptables-persistent这个包非常重要它提供了netfilter-persistent服务能帮助我们保存iptables规则使其在系统重启后依然生效。否则你精心配置的规则重启后就消失了。接下来我们需要确保SSH服务是开启的因为我们要把它作为被攻击的目标。Kali默认可能没有开启SSH执行以下命令sudo systemctl enable ssh sudo systemctl start ssh sudo systemctl status ssh看到“active (running)”状态就说明成功了。记下你Kali虚拟机的IP地址使用ip a或ifconfig命令查看。注意在实验开始前请务必确认你的操作环境是隔离的虚拟机或专属测试网络。绝对不要在生产服务器或任何公共网络中进行此类攻击模拟以免触发真实的安全警报或对他人的服务造成影响。2.2 防御策略的核心设计思路面对SSH爆破和Ping洪水这两种截然不同的攻击我们的防御策略也需要“分而治之”。对于SSH暴力破解攻击者的特征是在短时间内从一个或多个源IP向你的22端口发起大量、高频的TCP连接尝试并使用不同的用户名密码组合进行认证。防御的核心思路不是完全阻断而是“异常行为识别与动态封禁”。我们无法预知哪个IP是攻击者但我们可以定义“异常”比如在60秒内对22端口的连接尝试超过5次这很可能就是爆破行为。iptables的recent模块正是为此而生它可以动态地维护一个“黑名单”将符合异常条件的IP地址临时加入其中在一段时间内拒绝其所有访问。对于Ping洪水攻击其本质是ICMP协议层面的流量泛洪。攻击者发送海量的ICMP Echo Requestping请求包耗尽目标的网络带宽或处理资源。防御这种攻击的思路更直接限速。我们允许正常的ping检测比如每秒几个包但坚决限制单位时间内通过的ICMP包数量将超过阈值的流量直接丢弃。iptables的limit模块可以完美实现基于令牌桶的流量速率限制。总结一下我们的战术用recent模块对付SSH爆破动态黑名单用limit模块对付Ping洪水流量整形。接下来我们就进入具体的规则配置环节。3. iptables规则链结构与基础配置解析在动手写规则之前必须对iptables的基本框架有个清晰的认识否则规则顺序一错满盘皆输。iptables通过“表”、“链”、“规则”三层结构来组织功能。表定义了规则的用途。我们最常用的是filter表负责过滤和nat表负责地址转换。本次实验我们只操作filter表。链数据包流经的检查点。filter表内置三条链INPUT处理发往本机的数据包。我们的防御规则主要就加在这里。FORWARD处理经过本机路由转发的数据包网关/路由器角色。本次实验不涉及。OUTPUT处理从本机发出的数据包。数据包的旅程是这样的当一个外部ping包或SSH连接请求到达你的Kali机器时它首先会进入INPUT链。链中的规则按从上到下的顺序逐一匹配。一旦匹配成功就执行该规则定义的动作如ACCEPT接受、DROP丢弃、REJECT拒绝并且不再继续匹配后续规则。如果所有规则都不匹配则执行该链的默认策略。因此规则的顺序至关重要。一个经典的最佳实践是先设置默认策略为DROP拒绝所有然后创建“白名单”规则放行必要的流量。但为了实验清晰我们先从宽松策略开始最后再收紧。首先我们清空所有现有规则并设置默认策略为ACCEPT避免一开始就把自己锁在外面sudo iptables -F # 清空所有链中的规则 sudo iptables -X # 删除用户自定义的链 sudo iptables -Z # 清零所有链的计数器 sudo iptables -P INPUT ACCEPT sudo iptables -P FORWARD ACCEPT sudo iptables -P OUTPUT ACCEPT接着我们创建一些无论如何都应该放行的基础规则这些规则应该放在最前面因为它们匹配的是我们确信无害的流量# 1. 允许本地回环接口(lo)的所有流量这是系统内部通信必需的 sudo iptables -A INPUT -i lo -j ACCEPT # 2. 允许所有已建立连接及相关连接的数据包通过。这是关键 # 它确保了由本机主动发起的连接如浏览网页的返回数据包不会被阻断。 sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT-m state --state ESTABLISHED,RELATED这条规则是防火墙的“文明之窗”。没有它你即使能发出请求也收不到任何回复网络体验会瞬间崩塌。把它放在靠前的位置能极大提升效率因为大多数流量都属于已建立的连接。4. 对抗SSH暴力破解动态黑名单实战现在我们来构建防御SSH爆破的核心规则。我们将使用recent模块来追踪和封禁可疑IP。4.1 理解recent模块的工作机制recent模块可以维护一个或多个动态IP列表如SSH_ATTACKER并提供了丰富的操作--set将匹配到的数据包的源IP地址加入指定列表。--update更新该IP在列表中的时间戳用于判断是否在时间窗口内。--rcheck检查源IP是否在列表中。--seconds与上述操作结合限定一个时间窗口。--hitcount在时间窗口内匹配到的次数。我们的策略设计如下当一个新的IP尝试连接SSH端口22时我们将其记录到SSH_ATTACKER列表--set。随后检查该IP在过去的60秒内是否是第2次或更多次尝试连接SSH--rcheck --seconds 60 --hitcount 2。如果是则立即丢弃该包并跳转到一条专门的“封禁”规则。封禁规则将拒绝该IP的所有后续访问并记录日志。4.2 逐步配置SSH防御规则让我们一行行来配置并理解每一行的意图# 步骤1创建一条独立的链来管理SSH相关规则使结构更清晰 sudo iptables -N SSH_PROTECT # 步骤2在SSH_PROTECT链中定义核心检测逻辑 # 规则2.1如果IP在60秒内尝试连接SSH超过5次则将其加入黑名单并记录日志 sudo iptables -A SSH_PROTECT -m recent --name SSH_ATTACKER --update --seconds 60 --hitcount 5 -j LOG --log-prefix [IPTABLES SSH BLOCK]: sudo iptables -A SSH_PROTECT -m recent --name SSH_ATTACKER --update --seconds 60 --hitcount 5 -j DROP # 规则2.2对于新的SSH连接尝试将其源IP记录到SSH_ATTACKER列表 sudo iptables -A SSH_PROTECT -m recent --name SSH_ATTACKER --set -j ACCEPT # 步骤3将SSH流量导向我们自定义的SSH_PROTECT链进行处理 # 这条规则插入到INPUT链的靠前位置在基础放行规则之后其他规则之前 sudo iptables -I INPUT 3 -p tcp --dport 22 -j SSH_PROTECT规则解读与顺序的重要性规则2.1和2.2的顺序不能颠倒。必须先检查是否超限--update再执行记录--set。如果反了那么第一次连接就会被--set记录紧接着--update检查时它发现自己已经在列表里且hitcount至少为1这可能导致合法用户的第一次连接就被误判。我们的参数是60秒内5次。这个阈值可以根据你的服务器公开程度和日志分析来调整。对于暴露在公网的服务器可以更严格如60秒3次对于内网测试可以宽松些。-j LOG规则用于在系统日志通常是/var/log/kern.log或/var/log/syslog中记录被封禁的尝试便于事后审计。生产环境建议开启。4.3 模拟攻击与验证效果规则配好了效果如何我们开另一个终端窗口来模拟攻击。使用hydra这个Kali自带的强大爆破工具进行测试。请确保你攻击的目标IP是你自己的Kali虚拟机IP。快速测试命令使用一个很小的用户密码字典做演示# 假设你的Kali IP是 192.168.1.100 # 此命令尝试用root用户和几个常见密码进行爆破速度很快。 hydra -l root -P /usr/share/wordlists/fasttrack.txt 192.168.1.100 ssh -t 4-t 4表示使用4个并行任务加快尝试速度。很快你应该能看到尝试失败的记录。此时查看你的防火墙日志和recent列表# 查看封禁日志 sudo tail -f /var/log/kern.log | grep IPTABLES SSH BLOCK # 查看当前的SSH_ATTACKER列表 sudo cat /proc/net/xt_recent/SSH_ATTACKER在日志中你会看到类似[IPTABLES SSH BLOCK]前缀的记录显示了被DROP的数据包信息。在/proc/net/xt_recent/SSH_ATTACKER文件中你会看到被加入列表的IP地址及其最新访问时间戳。现在尝试从被封锁的IP就是你运行hydra的宿主机再次SSH连接Kali会发现连接超时或被拒绝而来自其他未触发规则的IP的连接则不受影响。这就是动态黑名单在起作用。实操心得recent模块的列表存储在内存中重启后会消失。这就是为什么之前要安装iptables-persistent。但即使服务重启动态封禁的IP也会丢失。对于需要持久化封禁的恶意IP应考虑结合ipset工具将IP加入一个持久的集合并用iptables引用该集合进行DROP。5. 抵御Ping洪水攻击ICMP流量限速实战Ping洪水攻击旨在耗尽带宽或系统资源。我们的防御目标是允许正常的、低频率的ping用于网络诊断但坚决限制高速率的ping请求。5.1 使用limit模块进行流量整形limit模块使用令牌桶算法。你可以把它想象成一个水龙头和一个水桶。水龙头以固定的速率如--limit 1/second向桶里滴水令牌。每个数据包需要从桶里舀走一滴水一个令牌才能被放行。如果桶是空的数据包就被丢弃。我们为ICMP Echo Requestping请求类型的数据包设置一个速率限制。# 步骤1允许正常的、低频率的ping # 限制每秒最多通过3个ICMP Echo Request包--limit 3/second突发峰值允许达到5个--limit-burst 5 sudo iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 3/second --limit-burst 5 -j ACCEPT # 步骤2丢弃所有超出限制的ping请求 # 这条规则没有-m limit它会匹配上所有未被上一条规则接受的echo-request包即超限的包 sudo iptables -A INPUT -p icmp --icmp-type echo-request -j DROP规则解读--limit 3/second平均速率限制为每秒3个包。这是一个比较宽松的值正常网络诊断完全够用。--limit-burst 5令牌桶的初始容量和最大容量是5。这意味着在长时间没有ping之后突然来的前5个ping包会被立刻放行消耗初始令牌从第6个开始就必须遵循每秒3个的速率限制。规则顺序必须先放行符合限速的包-j ACCEPT再丢弃所有剩余的此类包-j DROP。因为iptables规则是顺序执行的一旦包被第一条规则接受就不会再匹配第二条。5.2 模拟攻击与效果验证我们可以用ping命令的洪水模式来测试。在宿主机或其他机器上向Kali虚拟机发起高速ping# 在攻击机器上执行-f 参数表示洪水模式flood会以尽可能快的速度发送ping包 ping -f 192.168.1.100或者使用更专业的hping3工具Kali自带sudo hping3 --icmp --flood 192.168.1.100回到Kali虚拟机打开终端实时监控ICMP包的接收情况# 使用 tcpdump 抓取ICMP包观察速率 sudo tcpdump -i eth0 icmp and icmp[icmptype]icmp-echo你会发现尽管攻击端在疯狂发送但Kali端接收到的ICMP Echo Request包的速率被稳定地限制在了大约每秒3个左右。同时你可以通过watch命令动态查看iptables对这条规则的匹配计数watch -n 1 sudo iptables -L INPUT -v -n | grep -A2 -B2 echo-request在输出中你会看到第一条ACCEPT规则的pkts计数器缓慢增长约3/秒而第二条DROP规则的pkts计数器飞速增长所有超限的包都被丢弃了。6. 规则优化、持久化与高级策略6.1 规则顺序优化与默认策略收紧目前我们的INPUT链规则顺序大致是放行本地回环。放行已建立连接。SSH动态防护规则。ICMP限速规则。默认策略是ACCEPT。这存在一个安全隐患除了我们明确处理的SSH和ICMP其他所有端口和服务如未关闭的HTTP、FTP等都对外完全敞开。作为安全加固的最后一步我们应该将默认策略改为DROP并只放行必要的服务。假设我们只需要SSH22端口和后续可能用于管理的HTTPS443端口那么增加规则并修改策略# 在INPUT链末尾在ICMP DROP规则之后增加以下规则 # 放行特定的、必要的入站服务端口 sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT # SSH (实际上已被前面的SSH_PROTECT链处理这里显式放行最终通过的) sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT # HTTPS # 最后将INPUT链和FORWARD链的默认策略设置为DROP # 注意一定要确保OUTPUT链策略为ACCEPT否则本机无法对外发起连接。 sudo iptables -P INPUT DROP sudo iptables -P FORWARD DROP # OUTPUT策略保持ACCEPT # sudo iptables -P OUTPUT ACCEPT重要警告在执行sudo iptables -P INPUT DROP之前必须确保你当前是通过SSH连接的会话不是唯一的活跃会话或者你直接在虚拟机本地终端操作。否则一旦规则生效你可能会立刻断开SSH连接并被锁在外面一个安全的做法是使用at命令设置一个定时任务在几分钟后执行修改默认策略的命令给你留下测试和回滚的时间窗口。6.2 配置持久化保存内存中的规则重启即失效。使用之前安装的iptables-persistent来保存# 保存IPv4规则 sudo netfilter-persistent save # 或直接使用 iptables-save 导出到文件再由 persistent 服务加载 sudo sh -c iptables-save /etc/iptables/rules.v4保存后重启系统或重启netfilter-persistent服务规则会自动加载sudo systemctl restart netfilter-persistent6.3 进阶策略探讨结合ipset管理大规模IP黑名单recent模块适合动态、短期的封禁。如果你有一个已知的恶意IP列表例如从威胁情报平台获取使用ipset会更高效。你可以创建一个IP地址的哈希集合然后在iptables规则中匹配这个集合一条规则就能封禁成千上万个IP对性能影响极小。sudo apt install ipset sudo ipset create malicious_ips hash:ip sudo ipset add malicious_ips 1.2.3.4 sudo iptables -I INPUT -m set --match-set malicious_ips src -j DROP记得也要保存ipset规则。使用日志分析工具联动更高级的防御可以结合rsyslog或systemd-journald收集防火墙日志然后使用fail2ban或自定义脚本进行分析。当发现某个IP在短时间内触发了多种攻击规则如SSH爆破Web扫描可以自动将其IP加入ipset永久黑名单实现智能化的主动防御。应对慢速攻击聪明的攻击者可能会把SSH尝试频率降低到每分钟一次从而绕过我们“60秒5次”的规则。应对这种“慢速爆破”需要调整时间窗口和阈值或者使用更复杂的异常检测算法这通常需要借助fail2ban这类工具更灵活的配置。7. 常见问题、排查技巧与实验复盘7.1 规则不生效排查步骤实录检查规则顺序使用sudo iptables -L INPUT -v -n --line-numbers查看规则列表和顺序。记住数据包是从上到下匹配的第一条匹配的规则决定其命运。确保你的放行规则如已建立连接、特定端口在拒绝规则之前。查看计数器上述命令中的pkts和bytes列显示了每条规则匹配到的数据包和字节数。如果你预期的规则计数器没有增加说明数据包被前面的规则匹配走了。检查协议和端口确认你写的协议-p tcp/udp/icmp和目标端口--dport是否正确。例如SSH是TCP 22端口。确认链和表确保规则添加到了正确的链INPUT/OUTPUT/FORWARD和表默认是filter表中。使用sudo iptables -t nat -L可以查看其他表。模拟测试在Kali本机可以用telnet或nc测试端口连通性用ping测试ICMP这有助于排除网络层面的问题。telnet localhost 22 # 测试本机SSH端口 ping -c 4 127.0.0.1 # 测试本机环回ICMP7.2 把自己锁在外面了怎么办这是新手常踩的坑。如果你在远程SSH会话中配置防火墙不小心阻断了自己可以按以下步骤恢复前提你还有物理或虚拟控制台VMware/VirtualBox的图形界面的访问权限。方法通过虚拟机控制台登录直接清空或重置防火墙规则。sudo iptables -F # 清空规则 sudo iptables -P INPUT ACCEPT # 恢复默认策略 sudo iptables -P FORWARD ACCEPT # 检查并保存 sudo netfilter-persistent save教训永远在本地终端或一个有“逃生通道”的环境下进行防火墙重大修改。使用at命令延迟执行高风险操作是很好的习惯。7.3 实验复盘与核心收获通过这个从攻击到防御的完整实验我们不仅仅是敲了几行iptables命令更重要的是建立了一种动态的、基于异常行为的防御思维。iptables不是一堵静态的墙而是一个可以编程的、智能的流量过滤器。核心收获INPUT链是防御入口对于服务器精心设计INPUT链规则是安全基石。状态跟踪是基础-m state --state ESTABLISHED,RELATED规则必须优先。模块化是利器recent用于状态追踪和动态封禁limit用于流量整形ipset用于管理大规模集合。顺序决定命运规则的排列顺序直接决定过滤逻辑务必谨慎。日志是眼睛关键拒绝规则加上-j LOG事后排查和攻击分析全靠它。持久化是保障配置完一定要保存否则前功尽弃。防火墙配置没有银弹需要根据实际业务流量模式不断调整阈值和规则。最好的学习方式就是像我们今天这样在一个安全的实验环境中主动发起攻击观察流量然后设计并验证防御规则。这种攻防对抗的视角能让你对网络安全有更深刻、更直观的理解。