使用 Ansible 批量部署防火墙规则,虽然可以直接推送脚本,但最稳妥的方式是调用系统自带的防火墙模块(如 firewalld、iptables 或 ufw),这样能确保状态可控且支持回滚。若业务场景特殊必须使用脚本,请参考文中的备选方案。
先说结论:自动化防火墙变更属于高风险操作,必须确保有带外管理权限(如控制台)以防锁死,优先使用 Ansible 内置模块维持状态幂等性。
- 适合:多台服务器需要统一端口策略、定期合规检查或批量开放业务端口的场景。
- 先准备:确认目标机器防火墙后端类型(firewalld/iptables/ufw),并保留至少一个不受影响的 SSH 会话或控制台访问权限。
- 验收:执行后立刻验证业务端口连通性,并确认 SSH 连接未中断,保留回滚 playbook 以备不时之需。
前置准备:安装集合与确认环境
使用 ansible.posix.firewalld 模块前,必须确保控制节点已安装对应的集合包,否则执行时会报错模块找不到。
ansible-galaxy collection install ansible.posix
同时编写 Inventory 文件,明确目标主机分组,避免误伤管理节点:
[webservers]
192.168.1.10
192.168.1.11
核心方案:使用 firewalld 模块(推荐)
以下是一个基于 firewalld 模块的最小化 playbook 示例,支持服务名和自定义端口,并设置了超时控制:
---
- name: Batch deploy firewall rules
hosts: webservers
tasks:
- name: Allow HTTP traffic and custom port
ansible.posix.firewalld:
service: http
port: 8080/tcp
permanent: true
state: enabled
immediate: true
become: true
timeout: 30
若目标机器使用 iptables 原生服务,可替换为 iptables 模块;若为 Ubuntu 早期版本,可能需使用 ufw 模块。
备选方案:安全执行自定义脚本
若必须使用自定义脚本(如复杂的 iptables 规则),请使用 script 模块而非 shell,并确保脚本内部不包含关闭 SSH 端口的逻辑。建议在脚本执行前添加一条临时放行规则:
- name: Run custom firewall script safely
script: /path/to/firewall_script.sh
become: true
timeout: 60
应急回滚:还原策略 Playbook
生产环境必须准备回滚方案。以下 playbook 用于快速关闭刚才开放的端口,恢复至默认状态:
---
- name: Rollback firewall rules
hosts: webservers
tasks:
- name: Disable HTTP and custom port
ansible.posix.firewalld:
service: http
port: 8080/tcp
permanent: true
state: disabled
immediate: true
become: true
怎么验证是否生效
1. 检查防火墙状态
登录目标机器,根据使用的后端执行检查命令:
# firewalld
firewall-cmd `--list-all`
# iptables
iptables -L -n
# ufw
ufw status verbose
2. 验证端口连通性
从另一台机器使用 telnet、nc 或 curl 测试目标端口是否可达。同时保持当前的 SSH 会话不要关闭,直到确认新规则不影响现有管理通道。
常见坑与排查
1. 缺少集合报错
若提示 could not find module,请先执行 ansible-galaxy collection install ansible.posix 安装集合。
2. 规则顺序问题
防火墙规则通常按顺序匹配。如果默认策略是 DROP,而允许规则被添加到了末尾且前面有拒绝规则,可能导致生效失败。Ansible 模块通常处理了追加逻辑,但仍需注意默认策略设置。
3. 永久生效与即时生效
部分模块区分 permanent(重启后生效)和 immediate(当前生效)。若只配永久不配即时,需重启防火墙服务才生效,这期间可能存在空窗期或业务中断。
4. 混合管理冲突
避免同时使用 firewalld 和 iptables 命令直接操作同一套规则,这会导致状态不一致。Ansible 任务应统一接管,禁止人工手动干预混用。