ipr-cnrs.nftables

Nftables

  1. 概述
  2. 角色变量
  3. 示例
  4. 配置
  5. 开发
  6. 许可证
  7. 作者信息

概述

一个用于管理Nftables规则和软件包的角色。

深受 Mike Gleason的防火墙角色 的启发,感谢!我希望我没有使他的理念变得复杂……(我现在很确定,我确实让它复杂了 :D)^^

角色变量

  • nft_enabled:启用或禁用对Nftables的支持 [默认值:true]。
  • nft_pkg_state:新nftables软件包的状态 [默认值:present]。
  • nft_old_pkg_list:要移除的无用软件包列表(如Iptables等)[默认值:iptables]。
  • nft_old_pkg_state:旧软件包的状态 [默认值:absent]。
  • nft_old_pkg_manage:如果应该使用此角色管理旧软件包 [默认值:true]。
  • nft_conf_dir_path:存储不同Nftables配置文件的目录 [默认值:/etc/nftables.d]。
  • nft_main_conf_path:由systemd单元加载的主配置文件 [默认值:/etc/nftables.conf]。
  • nft_main_conf_content:用于生成上一个主配置文件的模板 [默认值:etc/nftables.conf.j2]。
  • nft_input_conf_path:包含在主配置文件中的输入配置文件 [默认值:{{ nft_conf_dir_path }}/filter-input.nft]。
  • nft_input_conf_content:用于生成上一个输入配置文件的模板 [默认值:etc/nftables.d/filter-input.nft.j2]。
  • nft_output_conf_path:包含在主配置文件中的输出配置文件 [默认值:{{ nft_conf_dir_path }}/filter-output.nft]。
  • nft_output_conf_content:用于生成上一个输出配置文件的模板 [默认值:etc/nftables.d/filter-output.nft.j2]。
  • nft_forward_conf_path:包含在主配置文件中的转发配置文件 [默认值:{{ nft_conf_dir_path }}/filter-forward.nft]。
  • nft_forward_conf_content:用于生成上一个转发配置文件的模板 [默认值:etc/nftables.d/filter-forward.nft.j2]。
  • nft_define_conf_path:包含在主配置文件中的变量定义文件 [默认值:{{ nft_conf_dir_path }}/defines.nft]。
  • nft_define_conf_content:用于生成上一个变量定义文件的模板 [默认值:etc/nftables.d/defines.nft.j2]。
  • nft_sets_conf_path:包含在主配置文件中的集合和映射定义文件 [默认值:{{ nft_conf_dir_path }}/sets.nft]。
  • nft_sets_conf_content:用于生成上一个集合和映射定义文件的模板 [默认值:etc/nftables.d/sets.nft.j2]。
  • nft_global_default_rules:为global链设置默认规则。其他链将在应用其特定规则之前跳转到global
  • nft_global_rules:您可以向所有主机添加global规则或覆盖由nft_global_default_rules定义的规则。
  • nft_global_group_rules:您可以为一个组添加global规则或覆盖由nft_global_default_rulesnft_global_rules定义的规则。
  • nft_global_host_rules:主机也可以添加或覆盖所有先前的规则。
  • nft__custom_content:要添加到Nftables配置中的自定义内容(表、包含等)[默认值:'']。
  • nft_input_default_rules:为input链设置默认规则。
  • nft_input_rules:您可以向所有主机添加input规则或覆盖由nft_input_default_rules定义的规则。
  • nft_input_group_rules:您可以为一个组添加input规则或覆盖由nft_input_default_rulesnft_input_rules定义的规则。
  • nft_input_host_rules:主机也可以添加或覆盖所有先前的input规则。
  • nft_output_default_rules:为output链设置默认规则。
  • nft_output_rules:您可以向所有主机添加output规则或覆盖由nft_output_default_rules定义的规则。
  • nft_output_group_rules:您可以为一个组添加output规则或覆盖由nft_output_default_rulesnft_output_rules定义的规则。
  • nft_output_host_rules:主机也可以添加或覆盖所有先前的output规则。
  • nft_forward_default_rules:为forward链设置默认规则。
  • nft_forward_rules:您可以向所有主机添加forward规则或覆盖由nft_forward_default_rules定义的规则。
  • nft_forward_group_rules:您可以为一个组添加forward规则或覆盖由nft_forward_default_rulesnft_forward_rules定义的规则。
  • nft_forward_host_rules:主机也可以添加或覆盖所有先前的forward规则。
  • nft__forward_table_manage:如果应该管理转发表 [默认值:False]。
  • nft__nat_table_manage:如果应该管理NAT表 [默认值:False]。
  • nft__nat_default_prerouting_rules:为NAT表的prerouting链设置默认规则。
  • nft__nat_prerouting_rules:为Ansible清单中的所有主机设置NAT表的prerouting链规则。
  • nft__nat_group_prerouting_rules:为特定Ansible清单组中的主机设置NAT表的prerouting链规则。
  • nft__nat_host_prerouting_rules:为特定Ansible清单中的主机设置NAT表的prerouting链规则。
  • nft__nat_prerouting_conf_path:包含在主配置文件中的prerouting配置文件 [默认值:{{ nft_conf_dir_path }}/nat-prerouting.nft]。
  • nft__nat_prerouting_conf_content:用于生成上一个prerouting配置文件的模板 [默认值:etc/nftables.d/nat-prerouting.nft.j2]。
  • nft__nat_default_postrouting_rules:为NAT表的postrouting链设置默认规则。
  • nft__nat_postrouting_rules:为Ansible清单中的所有主机设置NAT表的postrouting链规则。
  • nft__nat_group_postrouting_rules:为特定Ansible清单组中的主机设置NAT表的postrouting链规则。
  • nft__nat_host_postrouting_rules:为特定Ansible清单中的主机设置NAT表的postrouting链规则。
  • nft__nat_postrouting_conf_path:包含在主配置文件中的postrouting配置文件 [默认值:{{ nft_conf_dir_path }}/nat-postrouting.nft]。
  • nft__nat_postrouting_conf_content:用于生成上一个postrouting配置文件的模板 [默认值:etc/nftables.d/nat-postrouting.nft.j2]。
  • nft_define_default:设置在所有规则中可用的默认变量。
  • nft_define:您可以向所有主机添加变量或覆盖由nft_define_default定义的变量。
  • nft_define_group:您可以为一个组添加变量或覆盖由nft_define_defaultnft_define定义的变量。
  • nft_define_host:您可以添加或覆盖所有先前的变量。
  • nft_service_manage:如果应该使用此角色管理nftables服务 [默认值:true]。
  • nft_service_namenftables服务名称 [默认值:nftables]。
  • nft_service_enabled:设置nftables服务在启动时可用 [默认值:true]。
  • nft__service_protect:如果systemd单元应该保护系统和主目录 [默认值:true]。
  • nft_merged_groups:如果主机Ansible组中的变量应合并 [默认值:false]。
  • nft_merged_groups_dir:存放命名为Ansible组的nftables组规则的字典 [默认值:vars/]。
  • nft_debug:切换更多详细输出的开/关 [默认值:'false']。

操作系统特定变量

请查看[变量][vars目录]目录中按操作系统文件的默认值。

  • nft_pkg_list:提供nftables的软件包列表。
  • nft__bin_locationnftables可执行文件的路径 [默认值:/usr/sbin/nft]。

规则模板

nft_templates字典包含了一组实用规则,旨在标准化并准备好在您的防火墙中使用。例如,{{ nft_templates.allow_mdns }}将展开为以下规则,覆盖IPv4和IPv6的mDNS:

  - meta l4proto udp ip6 daddr ff02::fb    udp dport mdns counter accept comment "mDNS IPv6 service discovery"
  - meta l4proto udp ip  daddr 224.0.0.251 udp dport mdns counter accept comment "mDNS IPv4 service discovery"

在自定义规则集中预期的用法:

nft_host_input_rules:
  ...
  010 allow mdns: "{{ nft_templates.allow_mdns }}"

除此之外,nft_templates字典还包含实现RFC 4890、RFC 7126和RFC 9288中定义的转发和输入流量防火墙的完整建议的规则。有关详细信息和示例,请参见defaults/main.yml

规则字典

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

  • nft_*_default_rules:为所有节点定义默认规则。您可以在group_vars/all中定义它。
  • nft_*_rules:可以添加规则并覆盖nft_*_default_rules定义的规则。您可以在group_vars/all中定义它。
  • nft_*_group_rules:可以添加规则并覆盖nft_*_default_rulesnft_*_rules定义的规则。您可以在group_vars/webservers中定义它。
    • 如果nft_merged_groups设置为true,则来自ansible组的多个组规则也将被合并。
  • nft_*_host_rules:可以添加规则并覆盖nft_*_default_rulesnft_*_group_rulesnft_*_rules定义的规则。您可以在host_vars/www.local.domain中定义它。

defaults/main.yml

# 规则
nft_global_default_rules:
  005 状态管理:
    - ct state established,related accept
    - ct state invalid drop
nft_global_rules: {}
nft_merged_groups: false
nft_merged_groups_dir: vars/
nft_global_group_rules: {}
nft_global_host_rules: {}

nft_input_default_rules:
  000 策略:
    - type filter hook input priority 0; policy drop;
  005 全局:
    - jump global
  010 丢弃不必要的:
    - ip daddr @blackhole counter drop
  015 localhost:
    - iif lo accept
  210 输入TCP接受:
    - tcp dport @in_tcp_accept ct state new accept
nft_input_rules: {}
nft_input_group_rules: {}
nft_input_host_rules: {}

nft_output_default_rules:
  000 策略:
    - type filter hook output priority 0; policy drop;
  005 全局:
    - jump global
  015 localhost:
    - 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
nft_output_rules: {}
nft_output_group_rules: {}
nft_output_host_rules: {}

# 定义nft变量
nft_define_default:
  广播和多播:
    desc: '广播和多播'
    name: badcast_addr
    value: '{ 255.255.255.255, 224.0.0.1, 224.0.0.251 }'
  输入TCP接受:
    name: in_tcp_accept
    value: '{ ssh }'
  输出TCP接受:
    name: out_tcp_accept
    value: '{ http, https, hkp }'
  输出UDP接受:
    name: out_udp_accept
    value: '{ bootps, domain, ntp }'
nft_define: {}
nft_define_group: {}
nft_define_host: {}

# 集合和映射
nft_set_default:
  blackhole:
    - type ipv4_addr;
    - elements = $badcast_addr
  in_tcp_accept:
    - type inet_service; flags interval;
    - elements = $in_tcp_accept
  out_tcp_accept:
    - type inet_service; flags interval;
    - elements = $out_tcp_accept
  out_udp_accept:
    - type inet_service; flags interval;
    - elements = $out_udp_accept
nft_set: {}
nft_set_group: {}
nft_set_host: {}

这些默认设置将生成以下配置:

#!/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"
}

您可以通过在主机上显示规则集获取所有规则和定义:$ nft list ruleset

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

    set out_tcp_accept {
        type inet_service
        flags interval
        elements = { http, https, hkp }
    }

    set out_udp_accept {
        type inet_service
        flags interval
        elements = { domain, bootps, ntp }
    }

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

    chain input {
        type filter hook input priority 0; policy drop;
        jump global
        ip daddr @blackhole counter packets 0 bytes 0 drop
    }

    chain output {
        type filter hook output priority 0; policy drop;
        jump global
        oif "lo" accept
        ip protocol icmp accept
        udp dport @out_udp_accept ct state new accept
        tcp dport @out_tcp_accept ct state new accept
    }
}

示例

与剧本一起使用

使用默认变量管理Nftables(点击展开
- hosts: serverXYZ
  roles:
    - role: ipr-cnrs.nftables
为传入流量添加一个新的简单过滤规则(例如1个UDP/torrent端口)(点击展开
- hosts: serverXYZ
  vars:
      nft_input_rules:
        400 input torrent accepted:
          - udp dport 6881 ct state new accept
  roles:
    - role: ipr-cnrs.nftables
  • nft_input_group_rulesnft_input_host_rules变量也可以使用。
  • 权重(400)允许按顺序合并所有规则(来自nft_input_*rules字典)。
  • 跟在权重后面的文本(input torrent accepted)是一个将在nft_input_conf_path文件中作为注释添加的小描述。
为传入流量添加一个新的多端口过滤规则(例如TCP/http、https、http-alt等)(点击展开
- hosts: serverXYZ
  vars:
      nft_input_rules:
        400 input http accepted:
          - tcp dport { 80, 443, 8080-8082 } ct state new accept
  roles:
    - role: ipr-cnrs.nftables
  • nft_input_group_rulesnft_input_host_rules变量也可以使用。
  • 权重(400)允许按顺序合并所有规则(来自nft_input_*rules字典)。
  • 跟在权重后面的文本(input http accepted)是一个将在nft_input_conf_path文件中作为注释添加的小描述。
  • 在这种情况下,括号是有用的,定义了一个匿名集合。对于单个元素(端口、IP地址等),括号是多余的,单元素定义已经足够。
添加一个带有变量的新规则(点击展开

Nftables变量在为所有主机定义一些通用规则时非常有用,可以使用这样的变量(以**$**开头),并为某些组或主机覆盖变量的值。

- hosts: serverXYZ
  vars:
    - nft_define_group:
        input http accepted:
          desc: HTTP和HTTPS
          name: in_http_accept
          value: '{ 80, 443 }'
      nft_input_group_rules:
        400 input http accepted:
          - tcp dport $in_http_accept ct state new accept
  roles:
    - role: ipr-cnrs.nftables
  1. 使用define添加一个新的变量来表示HTTP端口。
  2. 为传入流量添加一个新的规则,并使用之前定义的变量。
  3. 在远程主机上,nft list ruleset的结果将是:
    table inet filter {
            …
    
            chain input {
                    …
                    tcp dport { http, https } ct state new accept
                    …
            }
            …
    }
    
    • 不会提及$in_http_accept变量。
  • nft_definenft_define_host变量也可以使用。
  • nft_input_rulesnft_input_host_rules变量也可以使用。
  • 权重(400)允许按顺序合并所有规则(来自nft_input_*rules字典)。
  • 跟在权重后面的文本(input http accepted)是一个将在nft_input_conf_path文件中作为注释添加的小描述。
添加一个带有命名集合的新规则(点击展开

与Nftables变量类似,命名集合在定义一些通用规则和集合(例如,适用于所有主机)并仅在某些情况下覆盖集合时非常有用(例如,对于某个组或某些主机)。

除了变量之外,还可以从主机实时添加内容到命名集合,而无需完全重写规则。

- hosts: serverXYZ
  vars:
      nft_set_group:
        in_udp_accept:
          - type inet_service; flags interval;
          - elements = { 6881-6887, 6889 }
      nft_input_group_rules:
        200 input udp accepted:
          - udp dport @in_udp_accept ct state new accept
  roles:
    - role: ipr-cnrs.nftables
  1. 使用nft_set_group字典添加一个新的命名集合(例如,适用于torrent端口)。
  2. 为传入流量添加一个新的规则,并使用之前定义的集合。
  3. 在远程主机上,如果您尝试向此集合中添加一个端口:nft add element inet filter in_udp_accept \{ 6999 \}
  4. 在远程主机上,nft list ruleset的结果现在将是:
    table inet filter {
            …
            set in_udp_accept {
                    type inet_service
                    flags interval
                    elements = { 6881-6887, 6889, 6999 }
            }
            chain input {
                    …
                    udp dport @in_udp_accept ct state new accept
                    …
            }
            …
    }
    
  • nft_setnft_set_host变量也可以使用。
  • nft_input_rulesnft_input_host_rules变量也可以使用。
  • 权重(200)允许按顺序合并所有规则(来自nft_input_*rules字典)。
  • 跟在权重后面的文本(input udp accepted)是一个将在nft_input_conf_path文件中作为注释添加的小描述。
用两个新规则覆盖默认规则(点击展开
- hosts: serverXYZ
  vars:
      nft_input_host_rules:
        050 icmp:
          - ip protocol icmp  ip saddr != 192.168.0.0/24  counter drop
          - ip protocol icmp  icmp type echo-request  ip length <= 84  counter limit rate 10/minute  accept
  roles:
    - role: ipr-cnrs.nftables
  1. defaults/main.yml文件获取规则描述(例如,050 icmp)。
  2. 丢弃不来自192.168.0.0网络的任何ICMP请求。
  3. 确保请求长度小于或等于84字节,并设置每分钟10个请求的限制。
  • nft_input_rulesnft_input_group_rules变量也可以使用。
  • 权重(050)允许按顺序合并所有规则(来自nft_input_*rules字典)。
  • 跟在权重后面的文本(icmp)是一个将在nft_input_conf_path文件中作为注释添加的小描述。
覆盖一些默认定义的集合(点击展开
- hosts: serverXYZ
  vars:
    - nft_define:
      input tcp accepted:
        desc: 自定义SSH端口和torrent
        name: in_tcp_accept
        value: '{ 2201, 6881 }'
  roles:
    - role: ipr-cnrs.nftables
  1. defaults/main.yml文件获取项目名称(例如,input tcp accepted)和变量名称(例如,in_tcp_accept)。
  2. 设置新值(例如,'{ 2201, 6881 }')。
  3. 您可以添加一个desc属性,该属性将作为注释设置在远程主机的nft_input_conf_path文件中。
  • nft_define_groupnft_define_host变量也可以使用。
覆盖所有默认规则(例如对于传出流量)(点击展开

如果默认规则过于宽松,或者您已经覆盖了大部分规则,在某些情况下,重新定义默认变量可能很有趣:

- hosts: serverXYZ
  vars:
      nft_output_default_rules:
        000 策略:
          - type filter hook output priority 0; policy drop;
        005 状态管理:
          - ct state established,related accept
          - ct state invalid drop
        015 localhost:
          - oif lo accept
        050 针对XXX主机和服务的我的规则:
          - tcp dport 2000  ip saddr { xxx.xxx.xxx.xxx, yyy.yyy.yyy.yyy }  ct state new  accept
        250 reset-ssh:  # 允许主机重置SSH连接,以避免来自Ansible控制器的10分钟延迟
          - tcp sport ssh tcp flags { rst, psh | ack } counter accept
  roles:
    - role: ipr-cnrs.nftables
  • 最后,不要忘记:
    1. 设置默认policy
    2. 管理已established的状态。
    3. 接受sshrst, psh | ack标志,以避免在首次运行此Nftables角色时出现10分钟的延迟(见#1)。
  • 然后根据需求使用所需权重添加您自己的规则以排序合并的规则(来自nft_output_*rules字典)和描述。
移除默认规则(点击展开
- hosts: serverXYZ
  vars:
      nft_output_host_rules:
        210 output tcp accepted:
          -
  roles:
    - role: ipr-cnrs.nftables
  1. defaults/main.yml文件获取规则描述(210 output tcp accepted)。
  2. 默认的出站流量策略(drop)现在将应用于out_tcp_accept变量中定义的端口。请确保您知道自己在做什么。
  3. 此规则将不再出现在nft list ruleset结果中,仅在远程主机的nft_output_conf_path文件中留下一个注释(210 output tcp accepted)。
  • nft_output_rulesnft_output_group_rules变量也可以使用。
  • 权重(210)允许按顺序合并所有规则(来自nft_output_*rules字典)。

与group_vars和host_vars一起使用

使用默认规则,并允许first_group传入ICMP并计数ICMP和默认策略(drop)数据包(点击展开

group_vars/first_group

nft_input_group_rules:
  020 icmp:
    - ip protocol icmp icmp type echo-request ip length <= 84 counter limit rate 1/minute accept
  999 count policy packet:
    - counter
使用来自多个ansible组的合并组规则(点击展开
  1. 启用合并组的变量:
    - hosts: serverXYZ
      vars:
        nft_merged_groups: true
        nft_merged_groups_dir: vars/
      roles:
        - role: ipr-cnrs.nftables
    
  2. 将额外规则放入名为服务器XYZ的“vars”文件夹中:
    • vars/first_group
      nft_input_group_rules:
        020 icmp:
          - ip protocol icmp icmp type echo-request ip length <= 84 counter limit rate 1/minute accept
        999 count policy packet:
          - counter
      
    • vars/second_group
      nft_input_group_rules:
        021 LAN:
          - iif eth0 accept
      
  3. 如果主机是这些组的成员,则来自两个组的这些规则集将被合并。

配置

此角色将:

  • 在系统上安装nftables
  • 默认启用nftables服务以便在启动时可用。
  • 生成默认配置文件,包含所有以下文件并由systemd单元加载。
  • 生成输入和输出规则文件,包括主配置文件中调用。
  • 在一个文件中生成变量,在另一个文件中生成集合和映射。
  • 确保nftables在启动时已启动和启用。
  • 在第一次运行或修改systemd单元时(重新)启动nftables服务。
  • 在下一次运行中重新加载nftables服务,以避免由于语法无效而使主机失去防火墙规则。

与Fail2ban集成

在Debian Bullseye之前,Fail2ban的systemd单元并没有很好的与Nftables集成。 此角色将为fail2ban单元创建覆盖文件,除非nft_fail2ban_service_override设置为false。默认情况下,即使在主机上尚不可用,也会添加此覆盖。这确保:

  • fail2ban单元在nftables单元之后启动。
  • nftables单元重新启动时,重新启动fail2ban单元。

开发

此源代码来自我们的Gitea实例,而Github repo只是为了能够将角色发送到Ansible Galaxy。

但欢迎在这里发送问题/PR :)

感谢这个钩子,Github会自动从我们的Gitea实例获取更新 :)

许可证

WTFPL

作者信息

Jérémy Gardais

  • IPR(雷恩物理研究所)
关于项目

Manage Nftables rules and packages

安装
ansible-galaxy install ipr-cnrs.nftables
许可证
Unknown
下载
99.3k
拥有者
Institut de Physique de Rennes https://ipr.univ-rennes1.fr/ Tutelles CNRS et Université Rennes 1