firewalld 不支持原生时间规则,但可通过 cron 定时执行 firewall-cmd 增删富规则实现时段控制;例如工作日 8:00 开放 HTTP、18:00 关闭,所有操作热生效且无需 reload。

firewalld 本身不直接支持基于时间的规则调度(比如“只在 9:00–18:00 开放 SSH”),它没有内置的 time-range 或 schedule 语法。但你可以通过与系统级时间服务协同 + 动态规则管理的方式,间接、可靠地实现基于时间的访问控制策略。
关键思路是:用 cron 定时触发 firewall-cmd 命令,在指定时刻启用或禁用某条规则。这种方式轻量、可控、无需额外组件,且完全兼容 firewalld 的永久/运行时双模式。
✅ 步骤一:准备可切换的规则(富规则或服务)
先定义两条互斥的规则状态——例如“允许 Web 访问”和“拒绝 Web 访问”,用 --add-rich-rule 和 --remove-rich-rule 控制开关。
比如,限制外部对 HTTP(端口 80)的访问,仅在工作日 8:00–18:00 开放:
# 创建一条“允许来自任意地址的 HTTP 访问”的富规则(临时生效) firewall-cmd --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port port="80" protocol="tcp" accept' # 永久保存该规则(后续 reload 仍存在) firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port port="80" protocol="tcp" accept'
对应地,你也可以预先写好一条“拒绝所有 HTTP 入站”的规则(用于非工作时段),或直接用 --remove-rich-rule 清除允许规则即可恢复默认策略(前提是默认 zone 是 public,其默认策略为 REJECT 入站)。
⚠️ 注意:firewalld 的 rich rule 不支持
--permanent --remove-rich-rule(不支持反向删除永久规则),所以推荐做法是——只用--add-rich-rule添加规则,用--remove-rich-rule临时移除;永久规则统一用--reload或重启后失效。更稳妥的做法是:
- 所有时间相关规则都不加
--permanent,只在 cron 中动态增删;- 或者用两个独立的自定义 zone(如
work-hours/off-hours),通过firewall-cmd --set-default-zone=切换(但切换 zone 影响面大,一般不推荐用于单服务控制)。
✅ 步骤二:编写定时任务(cron)
使用系统 cron 在指定时间自动执行 firewall-cmd 命令。
示例:工作日早 8 点开放 HTTP,晚 6 点关闭
编辑 root 的 crontab:
sudo crontab -e
添加以下两行:
# 工作日 08:00 开放 HTTP 0 8 * * 1-5 /usr/bin/firewall-cmd --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port port="80" protocol="tcp" accept' >/dev/null 2>&1 # 工作日 18:00 关闭 HTTP(移除上一条规则) 0 18 * * 1-5 /usr/bin/firewall-cmd --remove-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port port="80" protocol="tcp" accept' >/dev/null 2>&1
✅ 说明:
-
1-5表示周一至周五(Linux cron 中 1=周一,7=周日); - 使用绝对路径
/usr/bin/firewall-cmd避免环境变量缺失; -
>/dev/null 2>&1抑制输出,避免邮件告警; - 规则增删是瞬时生效的,无需
--reload(rich rule 支持热更新)。
✅ 步骤三:验证与调试
-
查看当前生效的 rich rule:
firewall-cmd --list-rich-rules
-
检查 cron 是否正常运行:
systemctl status cron # 或 crond journalctl -u cron -n 20 --no-pager
-
手动测试开关:
sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" port port="22" protocol="tcp" accept' sudo firewall-cmd --remove-rich-rule='rule family="ipv4" source address="192.168.10.0/24" port port="22" protocol="tcp" accept'
? 进阶建议:多时段 + 多服务组合控制
若需更复杂策略(如“周一凌晨 2–5 点单独开放备份端口”),可:
- 为每个时段/服务定义唯一标识的 rich rule(例如加注释或用不同 source IP 段);
- 编写 shell 脚本封装增删逻辑,再由 cron 调用(便于复用和日志记录);
- 结合
systemd.timer替代 cron(更现代、支持依赖与日志集成)。
例如脚本 /usr/local/bin/toggle-web-access.sh:
#!/bin/bash case "$1" in on) firewall-cmd --add-rich-rule='rule family="ipv4" port port="80" protocol="tcp" accept' ;; off) firewall-cmd --remove-rich-rule='rule family="ipv4" port port="80" protocol="tcp" accept' ;; esac
然后在 cron 中调用:0 8 * * 1-5 /usr/local/bin/toggle-web-access.sh on
不复杂但容易忽略的是:firewalld 的时间控制本质是“事件驱动式开关”,不是“条件匹配式过滤”。只要规则增删及时、cron 可靠、权限正确,就能稳定支撑办公网、运维窗口、发布灰度等典型场景。


















