Ansible 防火墙设置

知识点:

如果使用Ansible去远程配置防火墙规则,方式有好几种,比如:
(1).可以通过shell模块远程执行iptables命令;
(2).可以在Ansible本地端写好iptables规则,然后传送到目标节点上通过iptables-restore来恢复规则;
(3).可以使用Ansible提供的iptables模块来远程设置防火墙规则。

下面是使用shell模块远程执行iptables命令来定义基本的防火墙规则。

---
- name: set firewall
  hosts: new
  gather_facts: false
  tasks: 
    - name: set iptables rule
      shell: |
        # 备份已有规则
        iptables-save > /tmp/iptables.bak$(date +"%F-%T")
        # 给它三板斧
        iptables -X
        iptables -F
        iptables -Z

        # 放行lo网卡和允许ping
        iptables -A INPUT -i lo -j ACCEPT
        iptables -A INPUT -p icmp -j ACCEPT

        # 放行关联和已建立连接的包,放行22、443、80端口
        iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
        iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
        iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
        iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT

        # 配置filter表的三链默认规则,INPUT链丢弃所有包
        iptables -P INPUT DROP
        iptables -P FORWARD DROP
        iptables -P OUTPUT ACCEPT

可以指定要禁用或放行的端口列表,然后通过循环的方式去配置相关规则,还可以指定协议,指定链的默认规则等等。

此处,我做个简单演示,只支持三种操作:
1.允许用户指定filter表中三链的默认规则
2.允许用户指定INPUT链放行的tcp端口号列表
3.允许执行用户指定的iptables

---
- name: set firewall
  hosts: new
  gather_facts: false
  vars: 
    allowed_tcp_ports: [22,80,443]
    default_policies:
      INPUT: DROP
      FORWARD: DROP
      OUTPUT: ACCEPT
    user_iptables_rule: 
      - iptables -A INPUT -p tcp -m tcp --dport 8000 -j ACCEPT
      - iptables -A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT

  tasks: 
    - block: 
      - name: backup and empty rules
        shell: |
          # 备份已有规则,并清空规则等
          iptables-save > /tmp/iptables.bak$(date +"%F-%T")
          iptables -X
          iptables -F
          iptables -Z

      - name: green light for lo interface and icmp protocol
        shell: |
          # 放行lo接口、ping和已建立连接的包
          iptables -A INPUT -i lo -j ACCEPT
          iptables -A INPUT -p icmp -j ACCEPT
          iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

      # 放行用户指定的tcp端口列表
      - name: allow for given tcp port
        shell: iptables -A INPUT -p tcp -m tcp --dport {{item}} -j ACCEPT
        loop: "{{ allowed_tcp_ports | default([]) }}"

      # 执行用户自定义的iptables命令
      - name: execute user iptables command
        shell: "{{item}}"
        loop: "{{user_iptables_rule | default([]) }}"

      # 设置filter表三链的默认规则
      - name: default policies for filter table
        shell: iptables -P {{item.key}} {{item.value}}
        loop: "{{ query('dict', default_policies | default({})) }}"

上面示例中,定义了三个变量,分别用于存放用户指定要放行的tcp端口、filter表中三链的默认规则以及用户自定义的iptables命令。这没什么可解释的,但需要注意的是有些task中使用了类似{{ allowed_tcp_ports | default([]) }}的代码,这表示当变量allowed_tcp_ports未定义时,则将该变量设置为空列表作为其默认值,以免因变量未定义而loop循环出错。对于本示例来说,直接使用{{ allowed_tcp_ports }}也是健壮的代码。