ricsanfre.firewall

Ansible角色:防火墙

CI

在Linux上安装和配置基于nftables的防火墙。

要求

无。

角色变量

可用的变量如下所列,并附带默认值(见defaults\main.yaml)。

启用NAT和流量转发

  • firewall_forward_enabled :在给定主机上启用或禁用流量转发支持。[默认 : false].
  • firewall_nat_enabled :在给定主机上启用或禁用NAT支持。[默认 : false].

定义默认开放端口

  • in_tcp_port :允许通过这些端口的入站TCP流量。[默认 : { ssh }].
  • in_udp_port :允许通过这些端口的入站UDP流量。[默认 : { snmp }].
  • out_tcp_port :允许通过这些端口的出站TCP流量。[默认 : { http, https, ssh }].
  • out_udp_port :允许通过这些端口的出站UDP流量。[默认 : { domain, bootps, ntp }].

规则字典

对于每个ip表中的链(输入链、输出链、转发链)和nat表(nat-prerouting和nat-postrouting),nft规则存储在字典中,可以在组和主机级别覆盖。

变量、定义集和全局规则

由不同的规则链和全局链规则使用的一组变量和定义,可以从其他链使用规则jump global调用。

define sets global chain
nft_define_default nft_set_default nft_global_default
nft_define_group nft_set_group nft_global_group_rules
nft_define_host nft_set_host nft_global_host_rules

IP表规则

输入链 输出链 转发链
nft_input_default_rules nft_output_default_rules nft_forward_default_rules
nft_input_group_rules nft_output_group_rules nft_forward_group_rules
nft_input_host_rules nft_output_host_rules nft_forward_host_rules

NAT表规则

转发链 后转链
nft_nat_default_prerouting_rules nft_nat_default_postrouting_rules
nft_nat_group_prerouting_rules nft_nat_group_postrouting_rules
nft_nat_host_prerouting_rules nft_nat_host_postrouting_rules

每种规则字典类型将被合并,并按键的字母顺序应用规则(使用000到999作为前缀)。因此:

  • nft_*_default_rules :为所有节点定义默认规则。您可以在group_vars/all中定义它。
  • nft_*_group_rules :可以添加规则并覆盖由nft_*_default_rulesnft_*_rules定义的规则。您可以在group_vars/group_servers中定义它。
  • nft_*_host_rules :可以添加规则并覆盖由nft_*_default_rulesnft_*_group_rulesnft_*_rules定义的规则。您可以在host_vars/specific_host中定义它。

默认nftables配置

默认情况下,角色将生成以下配置文件:

/etc/nftables.conf

#!/usr/sbin/nft -f
# Ansible管理

# 清理
flush ruleset

include "/etc/nftables.d/defines.nft"

table inet filter {
    chain global {
        # 000 状态管理
        ct state established,related accept
        ct state invalid drop
    }
    include "/etc/nftables.d/sets.nft"
    include "/etc/nftables.d/filter-input.nft"
    include "/etc/nftables.d/filter-output.nft"
}

/etc/nftables.d/defines.nft

  # 广播和多播
  define badcast_addr = { 255.255.255.255, 224.0.0.1, 224.0.0.251 }

  # 广播和多播
  define ip6_badcast_addr = { ff02::16 }

  # in_tcp_accept
  define in_tcp_accept = { ssh }

  # in_udp_accept
  define in_udp_accept = { snmp }

  # out_tcp_accept
  define out_tcp_accept = { http, https, ssh }

  # out_udp_accept
  define out_udp_accept = { domain, bootps , ntp }

/etc/nftables.d/sets.nft

  set blackhole {
        type ipv4_addr;
        elements = $badcast_addr
    }

  set in_tcp_accept {
        type inet_service; flags interval;
        elements = $in_tcp_accept
    }

  set in_udp_accept {
        type inet_service; flags interval;
        elements = $in_udp_accept
    }

  set ip6blackhole {
        type ipv6_addr;
        elements = $ip6_badcast_addr
    }

  set out_tcp_accept {
        type inet_service; flags interval;
        elements = $out_tcp_accept
    }

  set out_udp_accept {
        type inet_service; flags interval;
        elements = $out_udp_accept
    }

/etc/nftables.d/filter-input.nft

chain input {
        # 000 策略
        type filter hook input priority 0; policy drop;
        # 005 全局
        jump global
        # 010 拒绝不需要的
        ip daddr @blackhole counter drop
        # 011 拒绝不需要的ipv6
        ip6 daddr @ip6blackhole counter drop
        # 015 本地主机
        iif lo accept
        # 050 icmp
        meta l4proto {icmp,icmpv6} accept
        # 200 输入udp接收
        udp dport @in_udp_accept ct state new accept
        # 210 输入tcp接收
        tcp dport @in_tcp_accept ct state new accept
  }

/etc/nftables.d/filter-output.nft

chain output {
        # 000 策略
        type filter hook output priority 0; policy drop;
        # 005 全局
        jump global
        # 015 本地主机
        oif lo accept
        # 050 icmp
        ip protocol icmp accept
        ip6 nexthdr icmpv6 counter accept
        # 200 输出udp接收
        udp dport @out_udp_accept ct state new accept
        # 210 输出tcp接收
        tcp dport @out_tcp_accept ct state new accept
        # 250 reset-ssh
        tcp sport ssh tcp flags { rst, psh | ack } counter accept
  }

并且主机上的规则集如下(通过执行nft list ruleset命令显示):

table inet filter {
        set blackhole {
                type ipv4_addr
                elements = { 224.0.0.1, 224.0.0.251,
                             255.255.255.255 }
        }

        set in_tcp_accept {
                type inet_service
                flags interval
                elements = { 22 }
        }

        set in_udp_accept {
                type inet_service
                flags interval
                elements = { 161 }
        }

        set ip6blackhole {
                type ipv6_addr
                elements = { ff02::16 }
        }

        set out_tcp_accept {
                type inet_service
                flags interval
                elements = { 22, 80, 443 }
        }

        set out_udp_accept {
                type inet_service
                flags interval
                elements = { 53, 67, 123 }
        }

        chain global {
                ct state established,related accept
                ct state invalid drop
        }

        chain input {
                type filter hook input priority filter; policy drop;
                jump global
                ip daddr @blackhole counter packets 0 bytes 0 drop
                ip6 daddr @ip6blackhole counter packets 0 bytes 0 drop
                iif "lo" accept
                meta l4proto { icmp, ipv6-icmp } accept
                udp dport @in_udp_accept ct state new accept
                tcp dport @in_tcp_accept ct state new accept
        }

        chain output {
                type filter hook output priority filter; policy drop;
                jump global
                oif "lo" accept
                ip protocol icmp accept
                ip6 nexthdr ipv6-icmp counter packets 0 bytes 0 accept
                udp dport @out_udp_accept ct state new accept
                tcp dport @out_tcp_accept ct state new accept
                tcp sport 22 tcp flags { rst, psh | ack } counter packets 0 bytes 0 accept
        }
}

依赖

示例剧本

应用默认规则

在主机上安装和配置防火墙,并使用默认规则。

- hosts: serverx
  roles:
    - ricsanfre.firewall

group_vars/all.yml中,您可以为所有主机覆盖默认规则:

nft_input_default_rules:
  000 策略:
    - type filter hook input priority 0; policy drop;
  005 全局:
    - jump global
  010 拒绝不需要的:
    - ip daddr @blackhole counter drop
  011 拒绝不需要的ipv6:
    - ip6 daddr @ip6blackhole counter drop
  015 本地主机:
    - iif lo accept
  050 icmp:
    - meta l4proto {icmp,icmpv6} accept
  200 输入udp接收:
    - udp dport @in_udp_accept ct state new accept
  210 输入tcp接收:
    - tcp dport @in_tcp_accept ct state new accept

在组级别修改默认规则

允许webservers组的HTTP入站流量:

group_vars/webservers.yml中可以通过修改in_tcp_port来实现:

in_tcp_port: { ssh, http }

或添加一个新的特定规则:

nft_input_group_rule:
  220 输入web接受:
    - tcp dport http ct state new accept

在主机级别修改默认+组规则

secureweb主机打开HTTPS入站流量,在host_vars/secureweb.yml中,您希望打开HTTPS并移除对HTTP的访问:

nft_input_group_rule:
  220 输入web接受: []
  230 输入安全web接受:
    - tcp dport https ct state new accept

可以删除默认规则

要“删除”规则,您只需将现有字典键赋值为空列表: 示例:禁用ICMP入站流量

nft_input_host_rules:
  050 icmp: []

在特定的group_vars/group.yml中,删除允许所有出站流量的默认规则:

nft_output_group_rules:
  000 策略:
    - type filter hook output priority 0;
  005 全局:
    -
  015 本地主机:
    -
  050 icmp:
    -
  200 输出udp接收:
    -
  210 输出tcp接收:
    -
  250 reset-ssh:
    -

000 策略默认规则被覆盖为接受所有流量,其余规则被删除。

总结一下,nft_X_host_rules中的规则将覆盖nft_X_group_rules中的规则,而nft_X_group_rules中的规则将覆盖nft_X_default_rules中的规则。

许可证

MIT/BSD

作者信息

Ricardo Sanchez (ricsanfre)

关于项目

Nftables-based firewall installation and configuration role

安装
ansible-galaxy install ricsanfre.firewall
许可证
mit
下载
11.1k
拥有者
Telecom engineer.