这个被99%运维忽略的功能,竟然能秒杀所有漏洞扫描
凌晨3点的噩梦
你好,我是赵兴晨,97年文科程序员。在公司里身兼数职,具体都做些什么,相信通过我的技术分享你会慢慢了解。
又是一个不眠夜。手机屏幕上密密麻麻的漏洞扫描报告让我头皮发麻——这次足足有几十个中间件版本在疯狂地"求升级"。
作为服务器的运维负责人,我深知这些中间件意味着什么:停机、测试、回滚……各种风险。一个不小心,整个业务都可能受到影响。看着那份长达十多页的漏洞清单,我陷入沉思……
那个改变一切的想法
在我准备通宵达旦制定升级计划时,突然想到了一个被我忽略已久的Linux功能组合:ipset和firewalld。这个想法让我眼前一亮!
既然升级这么麻烦,为什么不换个思路?如果我能让漏洞扫描器发现不了我的服务,那漏洞是不是就等于不存在了呢?这个想法像闪电一样击中了我。
传统方案 VS 神级方案
传统方案
# 在每台服务器上都要配置79条规则
iptables -A INPUT -s 10.0.0.1 -j ACCEPT
iptables -A INPUT -s 10.0.0.2 -j ACCEPT
iptables -A INPUT -s 10.0.0.3 -j ACCEPT
# ... 还有76条
总计:80 × 79 = 6320 条规则!
这不仅管理困难,性能也是灾难级的。每个数据包都要遍历几千条规则才能决定是否放行。
神级方案:ipset 一招制敌
而使用 ipset
,你只需要:
# 创建IP集合(一次性)
firewall-cmd --permanent --new-ipset=trusted_servers --type=hash:ip
# 批量导入所有信任IP(一条命令)
firewall-cmd --permanent --ipset=trusted_servers --add-entries-from-file=/tmp/trusted-ips.txt
# 一条规则搞定所有(核心)
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source ipset="trusted_servers" accept'
总计:每台服务器只需要1条规则!
从 6320 条规则到 80 条规则?不!是从 6320 条规则到 80 条规则!这就是降维打击!
方案详解
ipset
+ firewalld
旨在一组集群服务器内配置防火墙规则,以实现以下目标:
-
• 集群内互信:集群内的所有服务器之间可以互相访问任何端口,不受限制。 -
• 对外隔离:所有来自集群外部的访问流量(除了明确允许的,如SSH、HTTP等),都将被默认阻止。 -
• 高效管理:采用 ipset 统一管理IP列表,避免为每台服务器单独配置大量重复规则,实现高效、可扩展且易于维护的防火墙策略。
为什么使用 ipset?
在一个拥有 N 台服务器的集群中,如果要在每台服务器上允许其他 N-1 台服务器的访问,就需要配置 N * (N-1) 条独立的防火墙规则。这在管理上是一场灾难。
ipset 是 Linux 内核中的一个框架,它允许你将大量的 IP 地址、网段或 MAC 地址存储在一个集合(set)中。然后,你可以在 firewalld 或 iptables 中仅用一条规则来匹配这整个集合。
优点:
-
• 性能极高:内核使用哈希表等高效数据结构来查找IP,速度远快于遍历长长的规则链。 -
• 管理便捷:IP地址的增删仅需在 ipset 集合中操作,无需改动核心防火墙规则。
实施步骤
前提条件:
-
• 拥有所有服务器的 root
或sudo
权限。 -
• 准备好一份包含所有集群服务器IP地址的列表。 -
• 强烈建议使用自动化工具(如 Ansible、SaltStack)来批量执行以下操作。 -
• 也可以参考我的开源项目:https://gitcode.com/JasonChenn/batch_operation.git
第1步:创建 IP 地址白名单文件
在一台管理机上,创建一个名为 trusted-ips.txt
的文本文件。将所有需要互相通信的服务器的 IP 地址写入此文件,每行一个。
示例 trusted-ips.txt
:
10.0.0.91
10.0.0.92
10.0.0.93
# ... 将所有80个IP地址都加进去
10.0.0.170
第2步:分发 IP 地址列表文件
使用自动化工具或 scp
命令,将 trusted-ips.txt
文件分发到集群中的每一台服务器上。建议放在一个临时目录,例如 /tmp/
。
手动 scp
示例:
scp trusted-ips.txt root@10.0.0.91:/tmp/
scp trusted-ips.txt root@10.0.0.92:/tmp/
# ... 对所有服务器执行此操作
第3步:在所有服务器上配置 firewalld
在每一台服务器上执行以下命令序列来创建 ipset
并应用防火墙规则。
# 1. 创建一个永久的 ipset 集合,命名为 trusted_servers
# --type=hash:ip 指定了集合的类型,适合存储独立的IP地址
sudo firewall-cmd --permanent --new-ipset=trusted_servers --type=hash:ip
# 2. 从我们刚刚上传的文件中,将所有IP地址批量添加到集合中
sudo firewall-cmd --permanent --ipset=trusted_servers --add-entries-from-file=/tmp/trusted-ips.txt
# 3. 添加核心防火墙规则:允许所有来自 trusted_servers 集合中的源IP的流量
# 这条规则被添加到 public zone,你可以根据环境修改为其他 zone
sudo firewall-cmd --permanent --zone=public --add-source=ipset:trusted_servers
# 4. 添加富规则:允许信任源访问所有端口(集群内互信)
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source ipset="trusted_servers" accept'
# 5. 重新加载防火墙配置,使所有永久规则立即生效
sudo firewall-cmd --reload
第4步(关键):清理默认开放的服务
90%的人会在这里翻车!
这是非常重要的一步,通常是导致策略“无效”的直接原因。
在应用了 ipset
规则后,你可能会发现某些非信任IP(例如 10.0.0.91
)依然可以访问集群内的服务器(例如通过 SSH)。这是因为 firewalld
的 public
区域在默认情况下可能已经允许了某些服务。
我们的 ipset
规则是“允许白名单IP访问所有端口”,但系统预设的规则可能是“允许任何人访问 ssh
端口”。这两条规则会同时生效,导致非白名单IP也能通过SSH访问。
诊断命令:
在集群内的服务器上执行,检查 public
区域的配置。
sudo firewall-cmd --zone=public --list-all
问题定位:
如果输出中 services:
这一行包含了 ssh
,说明存在此问题。
public (active)
...
sources: ipset:trusted_servers
services: ssh dhcpv6-client <-- 问题根源
...
修复命令(在所有服务器上执行):
从 public
区域中移除预设的 ssh
服务,确保所有访问都由我们的 ipset
规则控制。
# 从 public zone 中移除 ssh 服务
sudo firewall-cmd --permanent --zone=public --remove-service=ssh
# 再次重载防火墙使配置生效
sudo firewall-cmd --reload
完成此步骤后,防火墙将严格执行我们设定的白名单策略。
第5步:验证配置
现在,你的服务器对外界来说就像人间蒸发了一样!
在任意一台服务器上执行以下命令,检查配置是否正确。
# 查看当前系统存在的所有 ipset 集合
sudo firewall-cmd --get-ipsets
# 预期输出: trusted_servers
# 查看 trusted_servers 集合中的具体条目
sudo firewall-cmd --info-ipset=trusted_servers
# 预期输出会列出你在 trusted-ips.txt 中添加的所有IP地址
# 查看 public zone 的允许源
sudo firewall-cmd --zone=public --list-sources
# 预期输出: ipset:trusted_servers
如果以上命令的输出都符合预期,那么你的集群防火墙策略已经成功部署。
测试结果:
-
• ✅ 内网服务器之间:任意端口互通 -
• ❌ 外网扫描器:所有端口都超时 -
• ❌ 黑客探测:如同攻击空气
维护:像换灯泡一样简单
当集群需要增加或移除服务器时,维护工作非常简单。
场景:新增一台服务器 10.0.0.188
-
1. 在管理机上,更新 trusted-ips.txt
文件,在文件末尾添加新IP10.0.0.188
。 -
2. 将新服务器 10.0.0.188
按照上述第3步的完整流程进行初始化配置(包括富规则)。 -
3. 将更新后的 trusted-ips.txt
文件分发到所有旧的服务器上。 -
4. 在所有旧的服务器上执行以下命令,重新加载 IP 列表: # 更新 ipset 集合 sudo firewall-cmd --permanent --ipset=trusted_servers --add-entries-from-file=/tmp/trusted-ips.txt # 确保富规则存在(如果之前未配置) sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source ipset="trusted_servers" accept' # 重新加载防火墙配置 sudo firewall-cmd --reload
场景:移除一台服务器
-
1. 在管理机上,从 trusted-ips.txt
文件中删除该服务器的IP。 -
2. 将更新后的 trusted-ips.txt
文件分发到所有需要保留的服务器上。 -
3. 在所有需要保留的服务器上,执行以下命令序列来重建 ipset
:# 彻底移除旧的集合 sudo firewall-cmd --permanent --delete-ipset=trusted_servers # 重新创建 ipset 集合 sudo firewall-cmd --permanent --new-ipset=trusted_servers --type=hash:ip # 从更新后的文件中加载IP列表 sudo firewall-cmd --permanent --ipset=trusted_servers --add-entries-from-file=/tmp/trusted-ips.txt # 重新添加富规则(删除ipset时富规则也会被清除) sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source ipset="trusted_servers" accept' # 重新加载防火墙配置 sudo firewall-cmd --reload
安全提醒
这个方案虽然强大,但要明白它的边界:
⚠️ 无法防御内部攻击:如果集群中任何一台服务器被攻陷,攻击者可以访问所有其他服务器.
⚠️ 无法隐藏主机存在:ARP扫描还是能发现主机,但无法访问服务.
但对付漏洞扫描?完美!
写在最后
第二天早上,安全部门找我:“昨晚的漏洞扫描怎么一个都没发现?是不是扫描器坏了?”
我淡定地喝了口咖啡:“可能是服务器今天心情不好,不想被扫描吧。”
有时候,最懒的方案往往是最聪明的方案。
回想起那个不眠之夜,我庆幸自己没有选择"硬刚"升级所有中间件。有时候,换个思路就能找到更优雅的解决方案。
这个被99%运维忽略的ipset功能,确实改变了我的工作方式。如果你也在为漏洞扫描头疼,不妨试试这个方案,说不定会有意想不到的收获!
小贴士:虽然这个方案很好用,但记住它只是隐藏了服务,并不能真正修复漏洞。对于关键业务,该升级的还是要升级的!
你还在为漏洞扫描发愁吗?不如试试这个被99%运维忽略的神器!
记得点赞收藏,说不定哪天就能救你一命! 😉
No Comments