ipr-cnrs.nftables
Nftables
概述
一个用于管理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_rules和nft_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_rules和nft_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_rules和nft_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_rules和nft_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_default和nft_define定义的变量。
- nft_define_host:您可以添加或覆盖所有先前的变量。
- nft_service_manage:如果应该使用此角色管理
nftables
服务 [默认值:true
]。 - nft_service_name:
nftables
服务名称 [默认值: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_location:
nftables
可执行文件的路径 [默认值:/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_rules和nft_*_rules定义的规则。您可以在
group_vars/webservers
中定义它。- 如果
nft_merged_groups
设置为true,则来自ansible组的多个组规则也将被合并。
- 如果
- nft_*_host_rules:可以添加规则并覆盖nft_*_default_rules、nft_*_group_rules和nft_*_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_rules或nft_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_rules或nft_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
- 使用define添加一个新的变量来表示HTTP端口。
- 为传入流量添加一个新的规则,并使用之前定义的变量。
- 在远程主机上,
nft list ruleset
的结果将是:table inet filter { … chain input { … tcp dport { http, https } ct state new accept … } … }
- 不会提及
$in_http_accept
变量。
- 不会提及
- nft_define或nft_define_host变量也可以使用。
- nft_input_rules或nft_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
- 使用nft_set_group字典添加一个新的命名集合(例如,适用于torrent端口)。
- 为传入流量添加一个新的规则,并使用之前定义的集合。
- 在远程主机上,如果您尝试向此集合中添加一个端口:
nft add element inet filter in_udp_accept \{ 6999 \}
- 在远程主机上,
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_set或nft_set_host变量也可以使用。
- nft_input_rules或nft_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
- 从
defaults/main.yml
文件获取规则描述(例如,050 icmp
)。 - 丢弃不来自192.168.0.0网络的任何ICMP请求。
- 确保请求长度小于或等于84字节,并设置每分钟10个请求的限制。
- nft_input_rules或nft_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
- 从
defaults/main.yml
文件获取项目名称(例如,input tcp accepted
)和变量名称(例如,in_tcp_accept
)。 - 设置新值(例如,
'{ 2201, 6881 }'
)。 - 您可以添加一个
desc
属性,该属性将作为注释设置在远程主机的nft_input_conf_path文件中。
- nft_define_group 或 nft_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
- 最后,不要忘记:
- 设置默认
policy
。 - 管理已
established
的状态。 - 接受ssh的
rst, psh | ack
标志,以避免在首次运行此Nftables角色时出现10分钟的延迟(见#1)。
- 设置默认
- 然后根据需求使用所需权重添加您自己的规则以排序合并的规则(来自nft_output_*rules字典)和描述。
移除默认规则(点击展开)
- hosts: serverXYZ
vars:
nft_output_host_rules:
210 output tcp accepted:
-
roles:
- role: ipr-cnrs.nftables
- 从
defaults/main.yml
文件获取规则描述(210 output tcp accepted
)。 - 默认的出站流量策略(
drop
)现在将应用于out_tcp_accept变量中定义的端口。请确保您知道自己在做什么。 - 此规则将不再出现在
nft list ruleset
结果中,仅在远程主机的nft_output_conf_path文件中留下一个注释(210 output tcp accepted
)。
- nft_output_rules或nft_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组的合并组规则(点击展开)
- 启用合并组的变量:
- hosts: serverXYZ vars: nft_merged_groups: true nft_merged_groups_dir: vars/ roles: - role: ipr-cnrs.nftables
- 将额外规则放入名为服务器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
- 如果主机是这些组的成员,则来自两个组的这些规则集将被合并。
配置
此角色将:
- 在系统上安装
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实例获取更新 :)
许可证
作者信息
Jérémy Gardais
- IPR(雷恩物理研究所)
ansible-galaxy install ipr-cnrs.nftables