配置防火墙白名单是保障服务器安全,特别是SSH服务安全的核心步骤。然而,许多管理员在使用firewalld时,常因误解其规则逻辑而陷入配置误区:看似启用了白名单,实则可能无意间开放了全局访问权限。其根本原因在于,firewalld的“服务”开放与“基于源IP的规则”是两套独立的过滤体系,错误地混合使用会导致安全策略失效。

核心结论:要实现严格的SSH IP白名单控制,必须使用rich-rule明确指定源地址。仅使用--add-service=ssh会绕过IP过滤逻辑,使白名单设置形同虚设。
配置SSH白名单必须使用富规则,而非简单开放服务
在firewalld的设计逻辑中,执行--add-service=ssh意味着“允许所有来源IP访问22端口”,这与“仅允许特定IP访问”的安全目标直接冲突。更复杂的是,若先全局开放了SSH服务,再追加基于IP的限制规则,firewalld的规则匹配顺序可能导致限制规则被覆盖,从而留下安全隐患。
- 常见错误操作:直接运行
firewall-cmd --permanent --add-service=ssh。这等同于向所有IP地址开放了SSH端口。 - 正确配置流程:首先,检查并移除任何已存在的全局SSH服务规则。随后,针对每一个需要授权的IP地址,使用
rich-rule创建独立的放行规则。 - 一个易忽略的细节:在编写规则时,源IP地址末尾的隐藏空格是常见错误源。例如
source address="1.1.2.4 ",这个尾随空格会导致规则无法被正确加载,通过firewall-cmd --permanent --list-all命令无法查看,但语法检查却可能通过。
设置允许规则需涵盖本机回环地址及可信管理IP
仅配置远程管理IP,可能引发“自我锁定”问题。例如,从跳板机连接服务器正常,但在服务器本地执行ssh localhost进行测试或端口转发时,连接却会失败。这是因为发往回环地址(127.0.0.1)的流量不经过物理网络接口,因此不匹配针对外部IP设置的规则。
- 必须明确放行本机地址:需专门添加一条针对127.0.0.1的规则:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="127.0.0.1" service name="ssh" accept'。 - 内网管理接口同样关键:如果服务器存在内网管理IP(例如192.168.10.5),也需要为其单独创建放行规则,不应假设放行某个网段即可自动包含。
- 仅支持IP或CIDR格式:firewalld的
source address字段仅接受IP地址或CIDR网段。填写"localhost"等主机名是无效的。
明确添加拒绝规则是构建清晰白名单策略的关键
firewalld的默认策略确实是拒绝(default: deny),但这仅对未匹配任何已有规则的流量生效。如果配置中只有若干条accept规则,那么其他IP的SSH连接尝试实际上会被默认丢弃(drop),而非拒绝(reject)。
两者存在显著区别:drop是静默丢弃数据包,客户端表现为连接超时;reject则是主动向客户端发送拒绝数据包,客户端会立即收到Connection refused的明确反馈。在运维故障排查时,明确的拒绝信号远比漫长的超时等待更易于诊断问题。因此,虽然非强制要求,但添加一条清晰的拒绝规则是更规范、更利于运维的做法。
- 建议添加明确的拒绝规则:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" service name="ssh" reject'。 - 规则顺序决定优先级:这条
reject规则必须放置在所有accept规则之后。因为firewalld按规则列表顺序进行匹配,首次匹配成功后即停止。若reject规则在前,则所有SSH连接都会被拒绝。 - 便于识别与审计:配置生效后,非白名单IP的客户端会立即收到拒绝响应,便于快速识别未授权访问尝试。
重载配置前必须验证语法与规则顺序
firewall-cmd --reload是一个高风险操作。它会清空所有当前运行的规则,并重新加载永久存储的配置。如果新配置存在错误,可能导致SSH服务瞬间中断,且由于旧规则已被清除,你将无法通过SSH重新连接进行修复。
- 加载前务必仔细核对:使用
firewall-cmd --permanent --list-all | grep -A 5 "rich rules"命令,仔细检查永久配置区域中的所有规则。确保所有accept规则均位于总的reject规则之前。 - 先临时测试,后永久生效:对于复杂的规则集,建议先使用
firewall-cmd --add-rich-rule=...(不加--permanent参数)将其添加到运行时环境进行测试。确认功能符合预期后,再将其转为永久规则。 - 保留应急管理会话:在执行reload操作前,务必保持至少一个已建立的SSH会话处于连接状态。等待reload完成后,在该会话中测试新的SSH连接(例如执行
ssh localhost或尝试新建连接),确认规则生效且配置正确后,再关闭这个作为“逃生通道”的连接。
最终重要提示:firewalld的规则引擎仅执行语法匹配,不进行语义层面的有效性验证。这意味着,即使你编写了类似source address="999.999.999.999"这样明显无效的IP地址,只要其格式符合CIDR规范,firewalld就会正常加载该规则。它不会检查该IP地址是否真实存在或是否路由可达。规则的正确性与有效性,完全依赖于管理员输入的准确性与严谨性。
