尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Firewalld配置IP白名单:精准控制服务器访问权限的实战指南

Firewalld配置IP白名单:精准控制服务器访问权限的实战指南 1. 项目概述与核心价值在服务器运维和网络安全领域防火墙是守护系统安全的第一道防线。很多刚接触 CentOS 7、Rocky Linux 或 RHEL 系列系统的朋友在部署了应用比如 MySQL、Nginx 或者一个自研的 Web 服务之后最头疼的问题之一就是如何精确地控制谁能访问我的服务默认情况下firewalld 可能开放了端口但也意味着对全网开放这无疑是将自己的服务暴露在潜在风险之下。我见过太多因为防火墙配置不当导致数据库被扫描、服务被恶意请求甚至服务器被入侵的案例。“firewalld配置只允许指定IP地址访问”这个需求本质上就是在实现基于源IP的访问控制白名单。这不仅仅是开个端口那么简单它关乎到最小权限原则的落地——只允许必要的、可信的流量进入。无论是为了限制内部管理后台的访问来源还是为了只允许某个合作伙伴的服务器调用你的API接口亦或是保护一个临时搭建的测试环境这个技能都至关重要。接下来我将以一个十年运维老兵的经验带你从零开始彻底搞懂如何在 firewalld 中实现精准的IP白名单控制避开那些手册上不会写的“坑”。2. firewalld 基础概念与方案选型在动手敲命令之前我们必须先理解 firewalld 的工作模型这能帮你从根本上明白我们每一步在做什么而不是死记硬背命令。2.1 firewalld 的核心逻辑区域、服务与规则firewalld 和传统的 iptables 一个显著区别在于它引入了“区域”的概念。你可以把区域想象成一套预设的、针对不同信任级别网络的规则包。比如public区域适用于不可信的公共网络默认只允许少数服务如 SSH而trusted区域则允许所有流量。我们常用的操作比如firewall-cmd --add-servicehttp实际上是在当前激活的区域通常是public里添加一条允许访问“http服务”其本质是预定义了端口80/tcp的规则。但这条规则是无差别的任何来源的IP都可以访问。我们的目标是要创建一条带有源地址约束的规则。在 firewalld 中实现这个目标主要有两种路径它们各有优劣。2.2 方案对比富规则 vs. 直接规则为了让你清晰地做出选择我把两种核心方案的关键信息整理成了下面的表格特性维度富规则直接规则本质firewalld 提供的高级、易读的规则语法。直接向底层iptables或nftables插入原生规则。可读性高。命令本身就像一句英语清晰表达了“允许来自某IP的某端口访问”。低。需要熟悉 iptables/nftables 的语法对新手不友好。管理性好。规则由 firewalld 统一管理--list-all可以查看--reload后规则持久化。差。firewalld 不直接管理其内容--list-all看不到需要额外命令查看。灵活性较高。能方便地处理端口、协议、源IP、日志、限速等组合。极高。可以直接使用 iptables/nftables 的所有强大功能。推荐场景绝大多数情况。需要精细控制端口和IP且希望规则易于维护。特殊需求如需要复杂的报文标记、连接跟踪或 firewalld 富规则不支持的模块。持久化使用--permanent参数即可。必须将规则写入/etc/firewalld/direct.xml或通过--permanent模式下的--add-passthrough才能持久化步骤繁琐。我的经验之谈对于“只允许指定IP访问某个端口”这个需求富规则是首选方案。它完美契合 firewalld 的设计哲学既保证了功能的实现又兼顾了配置的可读性和可维护性。除非你有非常特殊的网络过滤需求否则不要轻易使用直接规则那会让你后续的运维和排查变得异常困难。3. 核心实战使用富规则配置IP白名单理论清晰了我们进入实战环节。假设我们有一台服务器IP是192.168.1.100上面运行着 MySQL 数据库端口3306。现在我们只允许 IP 为10.0.0.50的管理服务器和10.0.0.51的备份服务器访问它。3.1 环境检查与初始状态确认在开始任何配置前先检查你的战场。这能避免很多“我明明配置了为什么不行”的问题。# 1. 查看 firewalld 状态确保其正在运行 sudo systemctl status firewalld # 如果未运行则启动并设置开机自启 sudo systemctl start firewalld sudo systemctl enable firewalld # 2. 查看当前激活的区域和默认规则 sudo firewall-cmd --list-all执行--list-all后你会看到类似这样的输出public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: ssh dhcpv6-client ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:重点关注services和rich rules部分。现在rich rules是空的。3.2 添加第一条IP白名单规则临时生效现在添加一条允许10.0.0.50访问3306/tcp端口的富规则。注意此时不加--permanent参数规则是临时生效的重启 firewalld 服务就会丢失。这个模式非常适合测试。sudo firewall-cmd --add-rich-rulerule familyipv4 source address10.0.0.50 port protocoltcp port3306 accept让我们拆解这条命令rule familyipv4指定规则针对 IPv4 地址。如果你的源IP是 IPv6则需要改为ipv6。source address10.0.0.50规则的核心指定源IP地址。这里可以是一个单IP也可以是一个网段如10.0.0.0/24。port protocoltcp port3306指定允许访问的协议和端口。accept对匹配的流量执行“接受”动作。添加后立即验证sudo firewall-cmd --list-rich-rules你应该能看到刚刚添加的规则。3.3 添加第二条规则并测试连通性用同样的方法添加允许10.0.0.51的规则。sudo firewall-cmd --add-rich-rulerule familyipv4 source address10.0.0.51 port protocoltcp port3306 accept现在从10.0.0.50或10.0.0.51服务器上尝试连接192.168.1.100:3306应该是通的。但是这里有一个巨大的“坑”你很可能发现从其他任意IP也能连接上这是因为在默认的public区域策略中target是default。default的行为是如果流量没有匹配到任何一条明确的accept规则则根据区域中定义的services和ports来决定。而我们在第一步检查时发现services里并没有mysql3306端口。那么问题出在哪关键在于你是否曾经为了方便直接添加过--add-port3306/tcp# 如果你曾经执行过这样的命令就会导致问题 sudo firewall-cmd --add-port3306/tcp这条命令会在当前区域添加一条允许任何源IP访问3306端口的规则。这条规则和我们后面添加的富规则是并行的。防火墙规则是按顺序匹配的但 firewalld 对富规则和普通端口规则的管理方式可能导致一个“漏洞”即使没有明确添加端口在某些版本或配置下默认行为也可能不是“默认拒绝”。实操心得白名单的精髓是“先关门再开窗”配置白名单的正确姿势不是仅仅添加允许的规则而是要确保默认情况下该端口对其他所有IP是拒绝的。在 firewalld 中最稳妥的方法是首先确保该端口没有通过--add-service或--add-port被全局开放。其次只通过富规则来添加允许特定IP访问的规则。这样只有白名单IP的流量能被accept其他流量因为没有匹配任何规则最终会被区域的默认策略通常是default即拒绝处理。3.4 清理冲突规则并固化配置假设我们之前错误地全局开放了3306端口现在需要清理并建立正确的白名单。# 1. 移除之前错误添加的全局端口规则如果存在 sudo firewall-cmd --remove-port3306/tcp # 2. 移除之前临时添加的富规则为了重新以永久方式添加 sudo firewall-cmd --remove-rich-rulerule familyipv4 source address10.0.0.50 port protocoltcp port3306 accept sudo firewall-cmd --remove-rich-rulerule familyipv4 source address10.0.0.51 port protocoltcp port3306 accept # 3. 以永久方式--permanent重新添加富规则 sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source address10.0.0.50 port protocoltcp port3306 accept sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source address10.0.0.51 port protocoltcp port3306 accept # 4. 重新加载防火墙配置使永久规则立即生效 sudo firewall-cmd --reload # 5. 最终确认 sudo firewall-cmd --list-all sudo firewall-cmd --list-rich-rules经过以上步骤你的防火墙规则就干净且正确了。--list-all输出中ports项应该为空而rich rules项下有你添加的两条规则。此时只有10.0.0.50和10.0.0.51能访问 3306 端口。4. 高级配置与生产环境考量掌握了基本操作我们来看看更复杂和贴近生产环境的场景。4.1 允许多个IP或整个网段白名单IP很少只有一个。你可以添加多个富规则也可以使用CIDR格式的网段。# 允许单个IP sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source address203.0.113.10 port protocoltcp port443 accept # 允许一个C类子网256个IP sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source address192.168.2.0/24 port protocoltcp port22 accept # 允许一个非常具体的IP范围例如从 .100 到 .120 # firewalld富规则不支持直接的IP范围需要拆分为多条规则或使用ipset见下文4.2 使用IPSet管理大规模IP列表当需要管理的白名单IP有几十上百个时为每个IP写一条富规则既繁琐又低效。这时就该ipset出场了。IPSet 是内核中的一个框架可以高效地存储大量IP地址、网段甚至端口并被防火墙规则引用。# 1. 创建一个名为“trusted_servers”的ipset存储IPv4地址类型为hash:ip sudo firewall-cmd --permanent --new-ipsettrusted_servers --typehash:ip --optionfamilyinet # 2. 向ipset中添加IP地址 sudo firewall-cmd --permanent --ipsettrusted_servers --add-entry10.0.0.50 sudo firewall-cmd --permanent --ipsettrusted_servers --add-entry10.0.0.51 sudo firewall-cmd --permanent --ipsettrusted_servers --add-entry10.1.2.0/24 # 3. 创建一条引用该ipset的富规则开放80和443端口 sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source ipsettrusted_servers port protocoltcp port80 accept sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source ipsettrusted_servers port protocoltcp port443 accept # 4. 重载配置 sudo firewall-cmd --reload # 5. 查看ipset内容 sudo firewall-cmd --info-ipsettrusted_servers使用 ipset 后当你需要新增一个白名单IP时只需将其添加到trusted_servers这个集合中所有引用此集合的防火墙规则会自动生效管理效率大大提升。4.3 为不同服务配置不同白名单一台服务器通常运行多个服务。你可以通过组合不同的端口和源IP实现精细化的访问控制。# 场景Web管理后台8080端口只允许办公室IP段访问API服务3000端口允许合作伙伴IP访问。 # 办公室网段 sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source address172.16.1.0/24 port protocoltcp port8080 accept # 合作伙伴A sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source address198.51.100.25 port protocoltcp port3000 accept # 合作伙伴B sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source address203.0.113.77 port protocoltcp port3000 accept sudo firewall-cmd --reload4.4 规则的删除与修改配置不可能一成不变白名单IP需要增删改。# 查看所有富规则 sudo firewall-cmd --list-rich-rules # 删除一条特定的富规则必须与添加时的规则字符串完全一致 sudo firewall-cmd --permanent --remove-rich-rulerule familyipv4 source address10.0.0.51 port protocoltcp port3306 accept # 从ipset中删除一个条目 sudo firewall-cmd --permanent --ipsettrusted_servers --remove-entry10.0.0.51 # 重载使删除生效 sudo firewall-cmd --reload注意事项--remove-rich-rule要求后面的规则字符串必须与添加时完全一致包括空格和引号。最稳妥的方法是先--list-rich-rules复制出完整规则再用于删除。5. 深度排查当规则不生效时怎么办即使按照步骤操作有时也会遇到“规则明明配了但就是不通”的情况。别慌按照以下流程排查99%的问题都能定位。5.1 系统化排查流程确认规则已正确加载并生效# 查看当前运行时规则不含--permanent sudo firewall-cmd --list-rich-rules # 查看永久配置规则 sudo firewall-cmd --permanent --list-rich-rules确保你看到的规则和预期一致。特别注意源IP地址、端口号和协议是否正确。检查默认区域与接口绑定# 查看当前激活的区域和绑定的网络接口 sudo firewall-cmd --get-active-zones流量是从哪个网卡进来的这个网卡被绑定到了哪个区域你的富规则是否添加在了正确的区域如果你有多个网卡如 eth0 对内网 eth1 对公网需要确认规则加在了流量流入的区域。检查是否有更宽泛的规则覆盖了白名单规则这是最常见的原因之一。回忆或检查你是否做过firewall-cmd --add-servicemysql全局开放了3306firewall-cmd --add-port3306/tcp全局开放了3306或者在trusted区域配置了规则而你的接口恰好在trusted区域。 使用sudo firewall-cmd --list-all仔细查看services和ports项。使用tcpdump进行抓包验证数据包是否到达服务器这是终极的证明手段。在服务器上监听对应端口sudo tcpdump -i eth0 -nn tcp port 3306然后从客户端尝试连接。如果在服务器上能看到来自客户端IP的SYN包说明网络链路和服务器监听是正常的问题一定出在防火墙规则上。如果看不到任何包那么问题可能在于网络路由、客户端防火墙或中间网络设备。检查底层iptables/nftables规则firewalld 最终会生成 iptables 或 nftables 规则。直接查看它们有时能发现 firewalld 命令行工具的显示问题。# 如果后端是 iptables sudo iptables -nL --line-numbers | grep -A 5 -B 5 3306 # 如果后端是 nftables sudo nft list ruleset在输出中寻找你的源IP和目标端口看对应的规则动作是ACCEPT还是被其他规则DROP/REJECT。5.2 常见问题速查表为了方便你快速定位我把常见问题、原因和解决方案整理如下问题现象可能原因解决方案白名单IP无法访问1. 规则未生效未reload2. 规则添加到了错误的区域3. 源IP地址写错末尾.0或.2554. 客户端自身有出向防火墙1. 执行firewall-cmd --reload2. 用--get-active-zones确认用--zoneXXX指定区域添加规则3. 仔细核对IP用ping或nslookup确认4. 关闭客户端防火墙或添加出站规则测试非白名单IP居然能访问1. 存在全局开放的端口/服务规则2. 区域默认策略为ACCEPT3. 规则语法错误未被正确解析1.--list-all检查并移除冲突的services/ports2. 检查区域target不应为ACCEPT3. 删除并重新添加富规则注意引号和格式规则添加失败报语法错误1. 命令格式错误引号不匹配2. 使用了不支持的参数或格式1. 检查命令中的单引号、双引号是否成对2. 查阅firewall-cmd --help和firewalld.richlanguage手册页重启服务器后规则丢失规则只添加了运行时未加--permanent始终使用--permanent参数添加永久规则或添加后执行firewall-cmd --runtime-to-permanent进行保存5.3 一个真实的排错案例有一次我配置一台跳板机只允许运维网段10.10.10.0/24访问SSH。配置后同网段内一台IP为10.10.10.100的机器却无法连接。排查过程如下firewall-cmd --list-rich-rules显示规则存在。tcpdump显示能收到来自10.10.10.100的SYN包。检查iptables -nL发现有一条顺序更靠前的规则DROP all -- 0.0.0.0/0 0.0.0.0/0它来自某个旧的、未清理的直接规则它先于我们的富规则匹配并丢弃了所有流量。使用firewall-cmd --direct --remove-rule ipv4 filter INPUT 1删除了那条陈旧的直接规则。问题解决。教训firewalld 的“直接规则”和富规则可能产生难以预料的交互。保持配置的简洁和统一尽量避免混用多种配置方式。6. 安全加固与最佳实践配置好白名单只是第一步遵循以下最佳实践能让你的防火墙更稳固。6.1 最小权限与默认拒绝这是安全的基本原则。对于任何服务初始状态应该是拒绝所有访问。然后像雕刻一样只凿出必要的通道白名单规则。永远不要先--add-port全局开放再加白名单限制这个顺序在心理和操作上都是错误的。6.2 使用专用区域进行逻辑隔离不要把所有规则都堆在public区域。可以为不同类型的服务器创建专用区域。# 创建一个名为‘internal-svc’的区域用于部署内部服务 sudo firewall-cmd --permanent --new-zoneinternal-svc # 设置该区域默认策略为拒绝显式声明更安全 sudo firewall-cmd --permanent --zoneinternal-svc --set-targetDROP # 将内网网卡如eth1绑定到此区域 sudo firewall-cmd --permanent --zoneinternal-svc --change-interfaceeth1 # 在此区域添加白名单规则 sudo firewall-cmd --permanent --zoneinternal-svc --add-rich-rulerule familyipv4 source address10.10.0.0/16 port protocoltcp port3306 accept sudo firewall-cmd --reload这样eth1网卡上的流量就由internal-svc区域管理规则集更清晰与其他面向公网的接口如eth0在public区域完全隔离。6.3 变更管理与备份防火墙配置是系统的重要资产必须有变更记录和备份。备份配置定期备份/etc/firewalld/目录。sudo cp -a /etc/firewalld /etc/firewalld.backup.$(date %Y%m%d)使用版本控制对于重要的服务器可以考虑将firewalld的配置文件如zones/*.xml,ipsets/*.xml纳入 Git 等版本控制系统管理。变更前测试在重要生产环境变更前先在测试环境验证。使用--timeout参数可以添加临时规则到期自动删除用于测试窗口。sudo firewall-cmd --add-rich-rulerule familyipv4 source address192.168.1.200 port protocoltcp port8080 accept --timeout300这条规则将在300秒后自动消失。6.4 结合日志进行审计对于特别重要的规则可以添加日志记录便于事后审计和异常流量分析。sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source address10.0.0.50 port protocoltcp port22 log prefixSSH_ACCESS: levelinfo accept这条规则在允许10.0.0.50访问SSH的同时会在系统日志如/var/log/messages或journalctl中记录一条前缀为 “SSH_ACCESS: ” 的日志。通过监控这些日志你可以清晰地知道谁在什么时候访问了服务。防火墙配置不是一劳永逸的事情尤其是白名单IP随着业务发展需要增减。建立一个简单的维护流程比如使用 Ansible、SaltStack 等自动化工具来管理防火墙规则或者至少维护一个文档记录所有白名单IP及其对应的业务用途这会在未来某个深夜进行故障排查时拯救你。记住清晰的规则和清晰的记录是运维工作里对抗混乱最有效的武器。
返回列表