Skip to main content

这个被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. 1. 在管理机上,更新 trusted-ips.txt 文件,在文件末尾添加新IP 10.0.0.188
  2. 2. 将新服务器 10.0.0.188 按照上述第3步的完整流程进行初始化配置(包括富规则)。
  3. 3. 将更新后的 trusted-ips.txt 文件分发到所有旧的服务器上。
  4. 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. 1. 在管理机上,从 trusted-ips.txt 文件中删除该服务器的IP。
  2. 2. 将更新后的 trusted-ips.txt 文件分发到所有需要保留的服务器上。
  3. 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%运维忽略的神器!

记得点赞收藏,说不定哪天就能救你一命! 😉