Compare commits

...

125 Commits

Author SHA1 Message Date
Jeremy Gardais ce8974c77a
Update git.ipr domain 2023-11-09 10:46:53 +01:00
Jeremy Gardais 4c728cb70a
Release v2.0.1 2021-08-26 09:57:04 +02:00
Jeremy Gardais c7512f7b13
Separate repo update from install task (fix #24) 2021-08-25 15:34:03 +02:00
Jeremy Gardais 97440461df
Merge branch 'VTimofeenko-gentoo_molecule' 2021-08-25 15:28:15 +02:00
Vladimir Timofeenko 542f562c41
Added molecule tests for Gentoo
This commit adds molecule tests for Gentoo.

Since the tests run inside docker and on systemd system, the host system
also needs to run systemd.

The tests create volumes in /srv/ so that artifacts that take a long
time to build and synchronize are reused between test runs.

This specific commit also fixes the error in ipr-cnrs/nftables#24
2021-08-20 16:50:28 -07:00
Jeremy Gardais 2902c9b77e
Release v2.0.0 2021-08-19 16:34:45 +02:00
Jeremy Gardais be2b941e79
Merge branch 'improve-systemd-unit' 2021-08-19 15:24:32 +02:00
Jeremy Gardais 4267dd455e
Add Molecule tests for systemd unit 2021-08-19 13:56:26 +02:00
Jeremy Gardais 68c5d4e9f7
Remove recurse on fail2ban custom directory
Molecule idempotence test
2021-08-18 16:02:22 +02:00
Jeremy Gardais 34c2668912
Fix systemd directories permissions 2021-08-13 11:52:04 +02:00
Jeremy Gardais 1a5e044ebb
Move systemd "Protect" options to override file
Rebase after Gentoo related commits
2021-08-13 11:51:54 +02:00
Jeremy Gardais 477f4f722c
Ensure to disable nftables unit from old target 2021-08-13 11:50:41 +02:00
Jeremy Gardais a34e5441a9
Start nftables systemd unit earlier
Source: nftables 0.9.8-3.1 from Debian Bullseye
Thanks to @kravietz − PR #19
2021-08-13 11:50:41 +02:00
Jeremy Gardais abdc15191b
Add infos about Fail2ban integration 2021-08-13 11:50:41 +02:00
Jeremy Gardais ac61739f91
Automatically add overrides for fail2ban unit 2021-08-13 11:50:40 +02:00
Jeremy Gardais 5001448a81
Drop fail2ban restart from nftables unit
Rebase after Gentoo related commits
2021-08-13 11:50:31 +02:00
Jeremy Gardais 28cf15ee42
Manage Fail2ban in the "systemd way"
Thanks to @FinweVI !

Rebase after Gentoo related commits
2021-08-13 11:48:27 +02:00
Jeremy Gardais 5dbf5b9b1c
Merge branch 'VTimofeenko-master' 2021-08-13 11:37:58 +02:00
Jeremy Gardais fd52a88be0
Merge branch 'master' of https://github.com/VTimofeenko/nftables into VTimofeenko-master 2021-08-13 11:37:44 +02:00
Vladimir Timofeenko a442b8f637
Added ability to specify nft bin location
Gentoo installs nft binary into /sbin/nft in accordance with the
filesystem spec:

https://devmanual.gentoo.org/general-concepts/filesystem/

This commit adds the ability to specify the location of nft binary
through variable nft__bin_location.

By default it is set to "/usr/sbin/nft".
2021-08-11 08:50:37 -07:00
Jeremy Gardais bac335be11 Merge remote-tracking branch 'github/add_molecule' 2021-08-09 17:07:05 +02:00
Paweł Krawczyk e696d9b482
Restore systemd-fedora-latest image 2021-08-09 10:38:07 +01:00
Paweł Krawczyk 40c632734f
Restore systemd-debian-latest image 2021-08-09 10:32:28 +01:00
Paweł Krawczyk 6a491d63f0
Add separate scenario for Archlinux with custom Dockerfile 2021-08-09 10:05:17 +01:00
Paweł Krawczyk ad499e949f
Leave systems that work for now 2021-08-08 23:48:08 +01:00
Paweł Krawczyk a8a41dfc91
Fix syntax 2021-08-08 23:39:52 +01:00
Paweł Krawczyk 0030b9bfcb
Add archlinux platform 2021-08-08 23:37:47 +01:00
Paweł Krawczyk a75f5bc391
Add volumes to all images 2021-08-08 23:27:47 +01:00
Paweł Krawczyk 32c4ab5215
Because we just can't have init in one place... 2021-08-08 23:19:44 +01:00
Paweł Krawczyk c8fd17d52b
Add Debian and Fedora 2021-08-08 22:14:36 +01:00
Paweł Krawczyk 7e31500c36
Fix variable name 2021-08-08 22:14:21 +01:00
Paweł Krawczyk 0669fe1623
Test for key files generated by the role 2021-08-08 21:48:02 +01:00
Paweł Krawczyk a0fd38056a
Adjust test to differences between CentOS and Debian 2021-08-08 21:40:13 +01:00
Paweł Krawczyk d73b5bbc8f
Debug rules prior to verification 2021-08-08 21:27:18 +01:00
Paweł Krawczyk 73bc1c464b
Fix ansible-lint config location 2021-08-08 21:16:06 +01:00
Paweł Krawczyk 95321f21f9
Mute role-name warnings 2021-08-08 21:01:57 +01:00
Paweł Krawczyk 9940f37baa
Mute lint warnings related to testing 2021-08-08 20:55:56 +01:00
Paweł Krawczyk 5e7b20680b
Fix systemd-ubuntu 2021-08-08 20:47:20 +01:00
Paweł Krawczyk 4eb6a5ae3b
Run ubuntu as privileged 2021-08-08 20:09:42 +01:00
Paweł Krawczyk be4f52b728
Use jrei/systemd-ubuntu 2021-08-08 19:43:58 +01:00
Paweł Krawczyk a5aa2c6e4a
Add some actual verification tasks 2021-08-08 19:09:08 +01:00
Paweł Krawczyk a6f7fde29a
Try centos-systemd 2021-08-08 17:59:44 +01:00
Paweł Krawczyk 8bd7607c09
Typo 2021-08-08 15:52:26 +01:00
Paweł Krawczyk 9fabd5a845
Use Molecule provisioned images 2021-08-08 15:41:28 +01:00
Paweł Krawczyk 9fd12fe790
Skip lint for now 2021-08-07 23:37:58 +01:00
Paweł Krawczyk 3b55e70281
Remove empty lines (yamllint) 2021-08-07 23:35:43 +01:00
Paweł Krawczyk 5416e20904
Fix YAML syntax 2021-08-07 23:30:37 +01:00
Paweł Krawczyk 06fecc68b2
Use robertdebock/molecule-action 2021-08-07 23:29:36 +01:00
Paweł Krawczyk da74b7d2b1
Add Debian scenario 2021-08-07 22:40:29 +01:00
Paweł Krawczyk d786479bc1
Try to run with systemd 2021-08-07 14:20:52 +01:00
Paweł Krawczyk 340f4f83e4
Just run on Alpine 2021-08-07 14:15:13 +01:00
Paweł Krawczyk 652863dd97
OS family for CentOS is RedHat 2021-08-07 14:14:39 +01:00
Paweł Krawczyk 85bb753dd4
Use another action 2021-08-07 14:12:13 +01:00
Paweł Krawczyk b96b750f8d
Try centos/systemd 2021-08-07 14:05:10 +01:00
Paweł Krawczyk 811bd11e9d
Do not remove iptables on test instances 2021-08-07 14:01:35 +01:00
Paweł Krawczyk 26eb76412f
Add config for Arch and Alpine 2021-08-07 13:53:23 +01:00
Paweł Krawczyk 574d9c46b8
Disable other images for now 2021-08-07 13:33:10 +01:00
Paweł Krawczyk 06c594f11b
Debug os family detection in GitHub Actions 2021-08-07 13:32:43 +01:00
Paweł Krawczyk 37919bb428
Do not create inventory 2021-08-07 13:28:36 +01:00
Paweł Krawczyk 9dae659fec
Init Ansible dir 2021-08-07 13:06:08 +01:00
Paweł Krawczyk 933cf1df4e
Create inventory file 2021-08-07 13:04:49 +01:00
Paweł Krawczyk 5df70d971f
Try using matrix with action-molecule 2021-08-07 12:44:26 +01:00
Paweł Krawczyk 6084cfce83
Add task names as required by ansible-lint 2021-08-07 12:18:09 +01:00
Paweł Krawczyk 8fad9d75fd
Update cache on package install 2021-08-07 11:47:32 +01:00
Paweł Krawczyk 82270dc5ef
Specify namespace to allow automatic role path resolution in Molecule 2021-08-07 11:41:14 +01:00
Vladimir Timofeenko 97044bc28f
Added default variables for Gentoo
Gentoo package name for nftables is 'net-firewall/nftables'
2021-08-06 16:20:49 -07:00
Jeremy Gardais adc627ebc0 Merge remote-tracking branch 'github/add_molecule' 2021-08-06 16:09:20 +02:00
Paweł Krawczyk 564038c06e
Add Molecule test scenario 2021-08-06 10:28:16 +01:00
Paweł Krawczyk eafc04a360
Version should be string (ansible-lint) 2021-08-06 10:27:44 +01:00
Jeremy Gardais 0cb79c2a47
Update CHANGELOG.md 2021-03-12 10:32:25 +01:00
Jeremy Gardais a71b9c3a62
Merge branch 'p-rintz-backup_toggle' 2021-03-12 10:23:30 +01:00
Jeremy Gardais 7639f2bbbf
Merge branch 'backup_toggle' of https://github.com/p-rintz/nftables into p-rintz-backup_toggle 2021-03-12 09:54:06 +01:00
Jeremy Gardais f7dffda808
Merge branch 'p-rintz-feature_forwarding' 2021-03-12 09:42:10 +01:00
Philipp Rintz ab5c105419
Make config backup configurable by using nft_backup_conf variable. 2021-03-12 09:28:45 +01:00
Jeremy Gardais 60b7d49555
Merge branch 'feature_forwarding' of https://github.com/p-rintz/nftables into p-rintz-feature_forwarding 2021-03-09 18:02:31 +01:00
Jeremy Gardais db3fbdc9b4
New examples usecases (mostly for playbooks) 2021-03-09 17:55:55 +01:00
Jeremy Gardais 9eff3cd1d0
Remove everything related to in_udp_accept
See conversation in PR #13 (summary : cause it was empty by
 default and the role currently doesn't manage it well)
2021-03-04 10:36:17 +01:00
Philipp Rintz 51d768539f
Add forward chain variables to README.md 2021-03-03 13:57:36 +01:00
Philipp Rintz e0658c0661
Added the option to manage the forwarding firewall table. 2021-03-03 13:57:36 +01:00
Philipp Rintz 3be5c95180
Add nft_custom_includes option for optional includes in the main filter table. 2021-03-03 13:57:36 +01:00
Jeremy Gardais 4576ec6ed4
Ansible-lint: Fix line longer than 160 chars 2021-01-05 15:58:43 +01:00
Jeremy Gardais e9a83261fa
Release v1.7.0 2021-01-04 16:53:16 +01:00
Jeremy Gardais 0df963cd86
Merge branch 'p-rintz-master' 2021-01-04 15:23:43 +01:00
Philipp Rintz 639a9f7109 Fix formatting mistake in defaults/main.yml 2020-12-30 17:23:18 +01:00
Philipp Rintz 19ee0ed2bc Change variable names + add debug toggle. 2020-12-30 17:15:14 +01:00
Philipp Rintz b3e26a435e Allow for undefined group variables for merged_groups. 2020-12-01 16:17:01 +01:00
Philipp Rintz 3d5edb45b9 Add additional variables to README 2020-11-29 15:36:26 +01:00
Philipp Rintz 65d7414785 Added merged_groups info to README. 2020-11-29 15:29:22 +01:00
Philipp Rintz 2b61973d1c Fix error when variables were empty 2020-11-11 15:27:08 +01:00
Philipp Rintz 290a86e906 Support merged firewall rules for multiple groups per host.
- Multiple groups for a single server will now lead to all firewall
    rules being merged instead of overwritten.
2020-11-10 21:17:11 +01:00
Jeremy Gardais 6e1c48ee99 Use var to include defines.nft file − Fix #9 2020-06-02 09:22:17 +02:00
Jeremy Gardais b8d55b5822 Merge branch 'aardbol-patch-4' 2020-06-02 09:15:09 +02:00
Leonardo f6c6df3dc6 added missing icmpv6 output rule 2020-06-02 09:11:51 +02:00
Jeremy Gardais 472badee55 Merge branch 'aardbol-patch-3' 2020-06-02 09:02:57 +02:00
Leonardo 1f91776374 Another playbook example
It was hard for me to learn how to use the role and override the default rules. Therefore I want to contribute another example
2020-06-02 09:01:54 +02:00
Jeremy Gardais 1fe24f01e4 Merge branch 'aardbol-patch-1' - input ICMPv6 2020-06-02 08:35:38 +02:00
Leonardo 15c0bf1625
Allow icmp(v6)
Allow pings and icmp traffic for both ipv4 and ipv6
2020-05-24 09:51:27 +02:00
Jeremy Gardais 88348aedab New v1.6.0 release 2020-04-21 09:57:55 +02:00
Jeremy Gardais 221de0cc89 Reload nftables service to apply new rules
Fix #3 Github
2020-04-21 09:53:57 +02:00
Jeremy Gardais 72551575df Fix the 10 minutes delay at first run (fix #1)! 2020-04-21 08:40:31 +02:00
Jeremy Gardais 74b864e2cb Block ipv6 multicast by default 2020-04-21 08:31:51 +02:00
Jeremy Gardais 8f36904af7
Add libiptc0 to the list of old package to remove
libiptc0 is an iptables dependency.
2019-05-31 20:02:19 +02:00
Jeremy Gardais 5dee91df3e
Turn nft_old_pkg_list into a list as expected 2019-05-31 15:28:45 +02:00
Jeremy Gardais dddc46282d
Merge branch 'JulienVdG-ansible-2-7-deprecation-fix' 2019-05-09 13:53:27 +02:00
Julien Viard de Galbert 5394cedc2a Fix deprecation warning with ansible 2.7
[DEPRECATION WARNING]: Invoking "apt" only once while using a loop via
squash_actions is deprecated. Instead of using a loop to supply multiple
items and specifying `name: "{{ item }}"`, please use
`name: ['{{ nft_old_pkg_list }}']` and remove the loop.
This feature will be removed in version 2.11.

Signed-off-by: Julien Viard de Galbert <julien@vdg.name>
2019-05-07 00:00:48 +02:00
Jeremy Gardais 7750b03e26
Include set definitions in nat table 2019-04-16 18:57:31 +02:00
Jeremy Gardais bcc3fc6f85
Manage a NAT table with pre and postrouting chains 2019-04-16 16:11:02 +02:00
Jeremy Gardais 095e03f1b2
Include Nat rules files in main configuration 2019-04-16 15:59:08 +02:00
Jeremy Gardais 63b3bb2c13
Generate Nat table rules files 2019-04-16 15:48:30 +02:00
Jeremy Gardais b77d492da2
Order and clean comments in defaults/main.yml file 2019-04-16 15:21:48 +02:00
Jeremy Gardais a5199dc0f2
Clean tasks name and comments in tasks/main.yml file 2019-04-16 14:10:11 +02:00
Jeremy Gardais 4047d64c76
Add a variable to manage custom content (table, include,…) 2019-04-16 11:50:30 +02:00
Jeremy Gardais b0da91bb73
Improve vars description/comments in default/main 2019-04-15 15:29:48 +02:00
Jeremy Gardais 83675dfe48
Allow to disable "Protect" in systemd unit 2019-03-15 11:13:26 +01:00
Jeremy Gardais 7ace36ed6e
Fix E405 Remote package tasks should have a retry 2019-02-27 13:31:25 +01:00
Jeremy Gardais 2dcf0ab10e
Use to_nice_json to manage packages list 2019-02-27 13:28:27 +01:00
Jeremy Gardais f47be2bebe
Add possibility to restart Fail2ban service 2018-08-07 11:03:29 +02:00
Jeremy Gardais fb43eeeb47
Set empty dependencies line to fix Galaxy warning 2018-08-06 15:19:06 +02:00
Jeremy Gardais bf9a8450b5
The role now might require Ansible 2.5
According to the version available in Debian Stable backports.
2018-08-06 15:11:32 +02:00
Jeremy Gardais 1c3d0284d5
Add a additionnal level for all vars for all hosts
It can be defined in group_vars/all .
2018-08-06 15:09:20 +02:00
Jeremy Gardais 733b546e56
Fix deprecation warning for state "installed" 2018-07-25 15:09:04 +02:00
Jeremy Gardais 485f7fa83d
Move two task in systemd handler (try to fix #1)
Try to fix the long delay at the first run.
2018-07-25 15:08:44 +02:00
Jeremy Gardais bf9080fcb3
Set a variable to enable/disable Nftables 2018-05-16 14:38:33 +02:00
Jeremy Gardais 0a909641b5 Reload systemd daemons only if unit file change. 2018-02-06 17:28:41 +01:00
Jeremy Gardais eb93ff65f9 Provide the systemd unit. 2018-02-06 17:17:48 +01:00
36 changed files with 1991 additions and 199 deletions

4
.ansible-lint Normal file
View File

@ -0,0 +1,4 @@
skip_list:
- command-instead-of-module
- no-changed-when
- role-name

23
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,23 @@
---
name: ipr-cnrs.nftables.molecule
on:
push:
branches: [master]
pull_request:
branches: [master]
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
with:
path: "${{ github.repository }}"
- name: molecule
uses: robertdebock/molecule-action@2.6.17

33
.yamllint Normal file
View File

@ -0,0 +1,33 @@
---
# Based on ansible-lint config
extends: default
rules:
braces:
max-spaces-inside: 1
level: error
brackets:
max-spaces-inside: 1
level: error
colons:
max-spaces-after: -1
level: error
commas:
max-spaces-after: -1
level: error
comments: disable
comments-indentation: disable
document-start: disable
empty-lines:
max: 3
level: error
hyphens:
level: error
indentation: disable
key-duplicates: enable
line-length: disable
new-line-at-end-of-file: disable
new-lines:
type: unix
trailing-spaces: disable
truthy: disable

View File

@ -1,3 +1,102 @@
## v2.0.1
### Added
* Molecule tests for Gentoo (many thanks to @VTimofeenko ! PR #25).
### Fixed
* Separate repositories update from installation task (fix #24).
## v2.0.0
### Added
* New examples usecases (mostly for playbooks) in README.md.
* New rules (disable by default) can be define in *forward* chain (thanks to
@p-rintz PR #14).
* Possibility to toggle file's backup (thanks to @p-rintz PR #15).
* Gentoo-specific variables (thanks to @VTimofeenko PR #22).
* Ability to specify nft binary path through **nft__bin_location** (thanks to @VTimofeenko PR #22).
* Manage Fail2ban in the "systemd way" (thanks to @FinweVI PR #16).
* Molecule tests (on Archlinux, Ubuntu, CentOS, Debian and Fedora) (many thanks to @kravietz ! PR #23).
* Support for Debian Bullseye (everything should now works fine).
### Removed
* Remove everything related to **in_udp_accept** (see conversation in
[Github PR #13](https://github.com/ipr-cnrs/nftables/pull/13)).
Cause it was empty by default and the role currently doesn't manage it very
well. Take a look to new examples in README.md to find your preferred solution
(re-adding it, new simple/multi-ports filter rule,…).
### Fixed
* Ansible-lint: Fix line longer than 160 chars.
* Start nftables systemd unit earlier (thanks to @kravietz PR #19).
* Ensure to disable nftables systemd unit from old target (PR #20).
* Move systemd "Protect" options for nftables to specific override.conf file (PR #20).
## v1.7.0
### Features
* Allow to merge group variables with **nft_merged_groups** (#11 #12).
### Enhancements
* Debug var with **nft_debug** (useful to set up merging group variables).
* Extra example to override default variables.
### Fix
* Add missing ICMPv6 rule.
## v1.6.0
### Features
* Able to manage a new NAT table (with prerouting and postrouting chains).
* Block ipv6 multicast by default.
### Enhancements
* Clean tasks name and comments in tasks/main.yml file.
* Order and clean comments in defaults/main.yml file.
* Reload rules instead of restart to avoid to loose rulebase due to invalid syntax (#3 Github).
### Fix
* Fix deprecation warning with ansible 2.7: Invoking "apt" only once while
using a loop via squash_actions is deprecated.
* Turn nft_old_pkg_list into a list.
* Add libiptc0 (iptables dependency) to the list of old package to remove.
* The 10 minutes delay at first run (#1)!
## v1.5.0
### Enhancements
* Add a variable to disable "Protect" instructions in systemd unit.
* Improve vars description/comments in default/main.yml.
* Add a variable to manage custom content (table, include,…).
## v1.4.1
### Fix
* Set empty dependencies line to fix Galaxy warning.
* Add possibility to restart Fail2ban service.
* Use to_nice_json to manage packages list.
* Fix E405 Remote package tasks should have a retry.
## v1.4.0
### Enhancements
* Set a variable to enable/disable the support of Nftables.
* Move two tasks in systemd handler (try to fix #1).
* Add a additionnal level for all vars for all hosts (group_vars/all).
### Fix
* Deprecation warning for state "installed".
* The role now might require Ansible 2.5 (available in Debian Stable backports).
## v1.3.1
### Fix
* Reload systemd daemons only if unit file change.
## v1.3.0
### Features
* Provide the systemd unit.
## v1.2.3
* Rename firewall table to filter table (most use on Debian).
@ -12,7 +111,7 @@
### Features
* Allow icmpv6 outgoing traffic.
## v1.2
## v1.2.0
### Features
* Ensure to remove old packages (iptables,…).
@ -20,7 +119,7 @@
### Fixes
* Ensure to create the the directory to store the differents configuration files (/etc/nftables.d).
## v1.1
## v1.1.0
### Features
* Manage nftables service at startup.
@ -33,7 +132,7 @@
* Remove DHCP incoming packets. The connection is started by the host, don't need incoming rule.
* Allow outgoing OpenPGP HTTP requests.
## v1.0
## v1.0.0
### Features
* Install `nftables` package for Debian based distros.

420
README.md
View File

@ -1,68 +1,104 @@
# Nftables
1. [Overview](#overview)
2. [Role Variables](#role-variables)
1. [Role Variables](#role-variables)
* [OS Specific Variables](#os-specific-variables)
* [Rules Dictionaries](#rules-dictionaries)
3. [Example Playbook](#example-playbook)
4. [Known Issue](#known-issue)
5. [Configuration](#configuration)
6. [Development](#development)
7. [License](#license)
8. [Author Information](#author-information)
1. [Examples](#examples)
* [With playbooks](#with-playbooks)
* [With group_vars and host_vars](#with-group_vars-and-host_vars)
1. [Configuration](#configuration)
* [Fail2ban integration](#fail2ban-integration)
1. [Development](#development)
1. [License](#license)
1. [Author Information](#author-information)
## Overview
A role to manage Nftables rules and packages.
Highly inspired by [Mike Gleason firewall role][mikegleasonjr firewall github] (3 levels of rules definition and template), thanks! I hope i haven't complexify his philosophy… ^^
Highly inspired by [Mike Gleason firewall role][mikegleasonjr firewall github]
(3 levels of rules definition and template), thanks! I hope i haven't
complexify his philosophy… (I'm pretty sure, i now did complexify it :D) ^^
## Role Variables
* **nft_pkg_manage**: If `nftables` package(s) should be managed with this role [default: `true`].
* **nft_pkg_state**: State of new `nftables` package(s) [default: `installed`].
* **nft_enabled**: Enable or disable support for Nftables [default: `true`].
* **nft_pkg_state**: State of new `nftables` package(s) [default: `present`].
* **nft_old_pkg_list**: The list of useless packages to remove (such as Iptables,…) [default: `iptables`].
* **nft_old_pkg_state**: State of old package(s) [default: `absent`].
* **nft_old_pkg_manage**: If old package(s) should be managed with this role [default: `true`].
* **nft_conf_dir_path**: Directory to store the differents Nftables configuration files [default: `/etc/nftables.d`].
* **nft_main_conf_path**: Main configuration file loaded by systemd unit [default: `/etc/nftables.conf`].
* **nft_main_conf_content**: Template used to generate the previous main configuration file [default: `etc/nftables.conf.j2`].
* **nft_input_conf_path**: Input configuration file include in main configuration file [default: `{{ nft_conf_dir_path }}filter-input.nft`].
* **nft_input_conf_path**: Input configuration file include in main configuration file [default: `{{ nft_conf_dir_path }}/filter-input.nft`].
* **nft_input_conf_content**: Template used to generate the previous input configuration file [default: `etc/nftables.d/filter-input.nft.j2`].
* **nft_output_conf_path**: Output configuration file include in main configuration file [default: `{{ nft_conf_dir_path }}filter-output.nft`].
* **nft_output_conf_path**: Output configuration file include in main configuration file [default: `{{ nft_conf_dir_path }}/filter-output.nft`].
* **nft_output_conf_content**: Template used to generate the previous output configuration file [default: `etc/nftables.d/filter-output.nft.j2`].
* **nft_define_conf_path**: Vars definition file include in main configuration file [default: `{{ nft_conf_dir_path }}defines.nft`].
* **nft_forward_conf_path**: forward configuration file include in main configuration file [default: `{{ nft_conf_dir_path }}/filter-forward.nft`].
* **nft_forward_conf_content**: Template used to generate the previous forward configuration file [default: `etc/nftables.d/filter-forward.nft.j2`].
* **nft_define_conf_path**: Vars definition file include in main configuration file [default: `{{ nft_conf_dir_path }}/defines.nft`].
* **nft_define_conf_content**: Template used to generate the previous vars definition file [default: `etc/nftables.d/defines.nft.j2`].
* **nft_sets_conf_path**: Sets and maps definition file include in main configuration file [default: `{{ nft_conf_dir_path }}sets.nft`].
* **nft_sets_conf_path**: Sets and maps definition file include in main configuration file [default: `{{ nft_conf_dir_path }}/sets.nft`].
* **nft_sets_conf_content**: Template used to generate the previous sets and maps definition file [default: `etc/nftables.d/sets.nft.j2`].
* **nft_global_default_rules**: Set default rules for `global` chain. Other chains will jump to `global` before apply their specific rules.
* **nft_global_group_rules**: You can add `global` rules or override those defined by **nft_global_default_rules** for a group.
* **nft_global_host_rules:**: Hosts can also add or override `global` rules.
* **nft_global_rules**: You can add `global` rules or override those defined by **nft_global_default_rules** for all hosts.
* **nft_global_group_rules**: You can add `global` rules or override those defined by **nft_global_default_rules** and **nft_global_rules** for a group.
* **nft_global_host_rules**: Hosts can also add or override all previours rules.
* **nft__custom_content**: Custom content (tables, include,…) to add in Nftables configuration [default: `''`].
* **nft_input_default_rules**: Set default rules for `input` chain.
* **nft_input_group_rules**: You can add `input` rules or override those defined by **nft_input_default_rules** for a group.
* **nft_input_host_rules:**: Hosts can also add or override `input` rules.
* **nft_input_rules**: You can add `input` rules or override those defined by **nft_input_default_rules** for all hosts.
* **nft_input_group_rules**: You can add `input` rules or override those defined by **nft_input_default_rules** and **nft_input_rules** for a group.
* **nft_input_host_rules:**: Hosts can also add or override all previous `input` rules.
* **nft_output_default_rules**: Set default rules for `output` chain.
* **nft_output_group_rules**: You can add `output` rules or override those defined by **nft_output_default_rules** for a group.
* **nft_output_host_rules:**: Hosts can also add or override `output` rules.
* **nft_output_rules**: You can add `output` rules or override those defined by **nft_output_default_rules** for all hosts.
* **nft_output_group_rules**: You can add `output` rules or override those defined by **nft_output_default_rules** and **nft_output_rules** for a group.
* **nft_output_host_rules**: Hosts can also add or override all previous `output` rules.
* **nft_forward_default_rules**: Set default rules for `forward` chain.
* **nft_forward_rules**: You can add `forward` rules or override those defined by **nft_forward_default_rules** for all hosts.
* **nft_forward_group_rules**: You can add `forward` rules or override those defined by **nft_forward_default_rules** and **nft_forward_rules** for a group.
* **nft_forward_host_rules**: Hosts can also add or override all previous `forward` rules.
* **nft__forward_table_manage**: If the forward table should be managed [default: `False`].
* **nft__nat_table_manage**: If the nat table should be managed [default: `False`].
* **nft__nat_default_prerouting_rules**: Set default rules for `prerouting` chain of **nat** table.
* **nft__nat_prerouting_rules**: Set rules for `prerouting` chain of **nat** table for all hosts in the Ansible inventory.
* **nft__nat_group_prerouting_rules**: Set rules for `prerouting` chain of **nat** table for hosts in specific Ansible inventory group.
* **nft__nat_host_prerouting_rules**: Set rules for `prerouting` chain of **nat** table for specific hosts the Ansible inventory.
* **nft__nat_prerouting_conf_path**: Prerouting configuration file include in the main configuration [default: `{{ nft_conf_dir_path }}/nat-prerouting.nft`].
* **nft__nat_prerouting_conf_content**: Template used to generate the previous prerouting configuration file [default: `etc/nftables.d/nat-prerouting.nft.j2`].
* **nft__nat_default_postrouting_rules**: Set default rules for `postrouting` chain of **nat** table.
* **nft__nat_postrouting_rules**: Set rules for `postrouting` chain of **nat** table for all hosts in the Ansible inventory.
* **nft__nat_group_postrouting_rules**: Set rules for `postrouting` chain of **nat** table for hosts in specific Ansible inventory group.
* **nft__nat_host_postrouting_rules**: Set rules for `postrouting` chain of **nat** table for specific hosts the Ansible inventory.
* **nft__nat_postrouting_conf_path**: postrouting configuration file include in the main configuration [default: `{{ nft_conf_dir_path }}/nat-postrouting.nft`].
* **nft__nat_postrouting_conf_content**: Template used to generate the previous postrouting configuration file [default: `etc/nftables.d/nat-postrouting.nft.j2`].
* **nft_define_default**: Set default vars available in all rules.
* **nft_define_group**: You can add vars or override those defined by **nft_define_default** for groups.
* **nft_define_host**: You can add or override existant vars.
* **nft_define**: You can add vars or override those defined by **nft_define_default** for all hosts.
* **nft_define_group**: You can add vars or override those defined by **nft_define_default** and **nft_define** for a group.
* **nft_define_host**: You can add or override all previous vars.
* **nft_service_manage**: If `nftables` service should be managed with this role [default: `true`].
* **nft_service_name**: `nftables` service name [default: `nftables`].
* **nft_service_enabled**: Set `nftables` service available at startup [default: `true`].
* **nft__service_protect**: If systemd unit should protect system and home [default: `true`].
* **nft_merged_groups** : If variables from the hosts Ansible groups should be merged [default : `false`].
* **nft_merged_groups_dir** : The dictionary where the nftables group rules, named like the Ansible groups, are located in [default : `vars/`].
* **nft_debug** : Toggle more verbose output on/off. [default: 'false'].
### OS Specific Variables
Please see default value by Operating System file in [vars][vars directory] directory.
* **nft_pkg_list**: The list of package(s) to provide `nftables`.
* **nft__bin_location** : Path to `nftables` executable. [default : `/usr/sbin/nft`]
### Rules Dictionaries
Each type of rules dictionaries will be merged and rules will be applied in the alphabetical order of the keys (the reason to use 000 to 999 as prefix). So:
* **nft_*_default_rules**: Define default rules for all nodes. You can define it in `group_vars/all`.
* **nft_*_group_rules**: Can add rules and override those defined by **nft_*_default_rules**. You can define it in `group_vars/webservers`.
* **nft_*_host_rules**: Can add rules and override those define by **nft_*_default_rules** and **nft_*_group_rules**. You can define it in `host_vars/www.local.domain`.
* **nft_*_rules**: Can add rules and override those defined by **nft_*_default_rules**. You can define it in `group_vars/all`.
* **nft_*_group_rules**: Can add rules and override those defined by **nft_*_default_rules** and **nft_*_rules**. You can define it in `group_vars/webservers`.
* If 'nft_merged_groups' is set to true, multiple group rules from the ansible groups will also be merged together.
* **nft_*_host_rules**: Can add rules and override those define by **nft_*_default_rules**, **nft_*_group_rules** and **nft_*_rules**. You can define it in `host_vars/www.local.domain`.
`defaults/main.yml`:
@ -72,6 +108,9 @@ nft_global_default_rules:
005 state management:
- 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: {}
@ -84,10 +123,9 @@ nft_input_default_rules:
- ip daddr @blackhole counter drop
015 localhost:
- iif lo accept
200 input udp accepted:
- udp dport @in_udp_accept ct state new accept
210 input tcp accepted:
- tcp dport @in_tcp_accept ct state new accept
nft_input_rules: {}
nft_input_group_rules: {}
nft_input_host_rules: {}
@ -100,10 +138,12 @@ nft_output_default_rules:
- oif lo accept
050 icmp:
- ip protocol icmp accept
- ip6 nexthdr icmpv6 counter accept
200 output udp accepted:
- udp dport @out_udp_accept ct state new accept
210 output tcp accepted:
- tcp dport @out_tcp_accept ct state new accept
nft_output_rules: {}
nft_output_group_rules: {}
nft_output_host_rules: {}
@ -116,15 +156,13 @@ nft_define_default:
input tcp accepted:
name: in_tcp_accept
value: '{ ssh }'
input udp accepted:
name: in_udp_accept
value: 'none'
output tcp accepted:
name: out_tcp_accept
value: '{ http, https, hkp }'
output udp accepted:
name: out_udp_accept
value: '{ bootps, domain, ntp }'
nft_define: {}
nft_define_group: {}
nft_define_host: {}
@ -136,14 +174,13 @@ nft_set_default:
in_tcp_accept:
- type inet_service; flags interval;
- elements = $in_tcp_accept
in_udp_accept:
- type inet_service; flags interval;
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: {}
```
@ -201,7 +238,6 @@ table inet filter {
jump global
ip daddr @blackhole counter packets 0 bytes 0 drop
iif "lo" accept
udp dport @in_udp_accept ct state new accept
tcp dport @in_tcp_accept ct state new accept
}
@ -216,17 +252,268 @@ table inet filter {
}
```
## Example Playbook
## Examples
* Manage Nftables with defaults vars:
### With playbooks
<details>
<summary>Manage Nftables with defaults vars (<i>click to expand</i>)</summary>
<!-- have to be followed by an empty line! -->
``` yml
- hosts: serverXYZ
roles:
- role: ipr-cnrs.nftables
```
</details>
* Use default rules with allow incoming ICMP and count dropped input packets:
<details>
<summary>Add a new <b>simple</b> filter rule for incoming traffic (eg. 1 port for UDP/torrent) (<i>click to expand</i>)</summary>
``` yml
- 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** or **nft_input_host_rules** variables can
also be used.
* The weight (`400`) allow to order all merged rules (from
<b>nft_input_*rules</b> dictionaries).
* The text following the weight (`input torrent accepted`) is a small
description that will be added as a comment in **nft_input_conf_path** file
on the remote host.
</details>
<details>
<summary>Add a new <b>multi-ports</b> filter rule for incoming traffic (eg. TCP/http, https, http-alt,…) (<i>click to expand</i>)</summary>
``` yml
- 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** or **nft_input_host_rules** variables can
also be used.
* The weight (`400`) allow to order all merged rules (from
<b>nft_input_*rules</b> dictionaries).
* The text following the weight (`input http accepted`) is a small
description that will be added as a comment in **nft_input_conf_path** file
on the remote host.
* In this case, brackets are useful and define a anonymous set. For a single
element (port, IP address,…), brackets are overkill and the singleton
definition is enought.
</details>
<details>
<summary>Add a new rule with a variable (<i>click to expand</i>)</summary>
Nftables variables can be useful if you define somes generic rules for all hosts
with such variables (called with **$**) and override variable's value for some
groups or hosts.
``` yml
- hosts: serverXYZ
vars:
- nft_define_group:
input http accepted:
desc: HTTP and 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. Add a new variable with **define** for HTTP ports.
1. Add a new rule for incoming traffic and use the previous defined variable.
1. Result of `nft list ruleset` on the remote host will be :
``` bash
table inet filter {
chain input {
tcp dport { http, https } ct state new accept
}
}
```
* No mention of `$in_http_accept` variable.
* **nft_define** or **nft_define_host** variables can also be used.
* **nft_input_rules** or **nft_input_host_rules** variables can also be used.
* The weight (`400`) allow to order all merged rules (from
<b>nft_input_*rules</b> dictionaries).
* The text following the weight (`input http accepted`) is a small description
that will be added as a comment in **nft_input_conf_path** file on
the remote host.
</details>
<details>
<summary>Add a new rule with a named set (<i>click to expand</i>)</summary>
Quite similar to Nftables variables, **named set** can be useful if you define
somes generic rules and sets (eg. for all hosts) and override only the set in
some case (eg. for a group or some hosts).
In addition to variables, it is possible to add content to named sets on the
fly from the host without completely rewrite the rule.
``` yml
- 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. Add a new named set with <b>nft_set_group</b> dictionary (eg. for torrent ports).
1. Add a new rule for incoming traffic and use the previous defined set.
1. On the remote host, if you try to add a port to this set : `nft add element inet filter in_udp_accept \{ 6999 \}`
1. Result of `nft list ruleset` on the remote host will now be :
``` bash
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** or **nft_set_host** variables can also be used.
* **nft_input_rules** or **nft_input_host_rules** variables can also be used.
* The weight (`200`) allow to order all merged rules (from
<b>nft_input_*rules</b> dictionaries).
* The text following the weight (`input upd accepted`) is a small description
that will be added as a comment in **nft_input_conf_path** file on
the remote host.
</details>
<details>
<summary>Override a default rule with 2 new rules (<i>click to expand</i>)</summary>
``` yml
- 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. Get rule description from `defaults/main.yml` file (eg. `050 icmp`).
1. Drop any ICMP request that doesn't come from 192.168.0.0 network.
1. Ensure the request is less or equal to 84 bytes and set up a limit
to 10 requests per minute.
* **nft_input_rules** or **nft_input_group_rules** variables can also be used.
* The weight (`050`) allow to order all merged rules (from
<b>nft_input_*rules</b> dictionaries).
* The text following the weight (`icmp`) is a small description that
will be added as a comment in **nft_input_conf_path** file on
the remote host.
</details>
<details>
<summary>Override some of the default defined sets (<i>click to expand</i>)</summary>
``` yml
- hosts: serverXYZ
vars:
- nft_define:
input tcp accepted:
desc: Custom SSH port and torrent
name: in_tcp_accept
value: '{ 2201, 6881 }'
roles:
- role: ipr-cnrs.nftables
```
1. Get item name (eg. `input tcp accepted`) and variable name
(eg. `in_tcp_accept`) from `defaults/main.yml` file.
1. Set a new value (eg. `'{ 2201, 6881 }'`).
1. You can add a `desc` attribute that will be set as a comment in
**nft_input_conf_path** file on the remote host.
* **nft_define_group** or **nft_define_host** variables can also be used.
</details>
<details>
<summary>Override all default rules (eg. for outgoing traffic) (<i>click to expand</i>)</summary>
If the default rules are too permissive, if you already override most of them,…
In some case, i guess, it can be interesting to redefine the default variable :
``` yml
- hosts: serverXYZ
vars:
nft_output_default_rules:
000 policy:
- type filter hook output priority 0; policy drop;
005 state management:
- ct state established,related accept
- ct state invalid drop
015 localhost:
- oif lo accept
050 my rule for XXX hosts and services:
- tcp dport 2000 ip saddr { xxx.xxx.xxx.xxx, yyy.yyy.yyy.yyy } ct state new accept
250 reset-ssh: # allow the host to reset SSH connections to avoid 10 min delay from Ansible controller
- tcp sport ssh tcp flags { rst, psh | ack } counter accept
roles:
- role: ipr-cnrs.nftables
```
* At least, don't forget to :
1. set a default `policy`.
1. manage already `established` state.
1. accept `rst, psh | ack` flags for **ssh** to avoid a 10 minutes delay at
the first run of this Nftables role (see #1).
* Then add your own rules with the wanted weight to order all merged rules (from
<b>nft_output_*rules</b> dictionaries) and descriptions.
</details>
<details>
<summary>Remove a default rule (<i>click to expand</i>)</summary>
``` yml
- hosts: serverXYZ
vars:
nft_output_host_rules:
210 output tcp accepted:
-
roles:
- role: ipr-cnrs.nftables
```
1. Get rule description from `defaults/main.yml` file (`210 output tcp accepted`).
1. The default policy for outgoing traffic (**drop**) will now be applied to
ports defined in **out_tcp_accept** variable. Be sure of what you are doing.
1. The rule will no longer be present in `nft list ruleset` result, just a
comment will remain (`210 output tcp accepted`) in **nft_output_conf_path**
file on the remote host.
* **nft_output_rules** or **nft_output_group_rules** variables can also be used.
* The weight (`210`) allow to order all merged rules (from
<b>nft_output_*rules</b> dictionaries).
</details>
### With group_vars and host_vars
<details>
<summary>Use default rules and allow, for <b>first_group</b>, incoming ICMP and count both ICMP and default policy (<b>drop</b>) packets (<i>click to expand</i>)</summary>
`group_vars/first_group`:
@ -237,33 +524,70 @@ nft_input_group_rules:
999 count policy packet:
- counter
```
</details>
## Known Issue
<details>
<summary>Use merged group rules from multiple ansible groups (<i>click to expand</i>)</summary>
* The first run of a playbook may be long (~8 minutes) just after the (re)start of `nftables` service.
* Probably due to Ansible/OpenSSH Specific default Settings, the outgoing connections for Ansible/SSH will be blocked:
```
trace id d7c3a8dc inet filter output packet: oif "ens18" ip saddr REMOTE_HOST ip daddr MY_HOST ip dscp 0x02 ip ecn not-ect ip ttl 64 ip id 56799 ip length 420 tcp sport ssh tcp dport 53922 tcp flags == 0x18 tcp window 1452
```
* This only happen at the first run on new clean host. The next runs will works without any delay.
1. Enable to merge group's variables :
``` yml
- hosts: serverXYZ
vars:
nft_merged_groups: true
nft_merged_groups_dir: vars/
roles:
- role: ipr-cnrs.nftables
```
1. Put extra rules inside the "vars" folder named after your ansible groups for serverXYZ :
* `vars/first_group`:
``` yaml
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`:
``` yaml
nft_input_group_rules:
021 LAN:
- iif eth0 accept
```
1. These rulesets, from the two groups, will be merged if the host is a member
of these groups.
</details>
## Configuration
This role will:
* Install `nftables` on the system.
* Enable `nftables` service by default at startup.
* Generate a default configuration file which include all following files and loaded by systemd unit.
* Generate a default configuration file which include all following files and
loaded by systemd unit.
* Generate input and output rules files include called by the main configuration file.
* Generate vars in a file and sets and maps in another file.
* Restart `nftables` service.
* (re)Start `nftables` service at first run.
* Reload `nftables` service at next runs to avoid to let the host without firewall
rules due to invalid syntax.
### Fail2ban integration
Before Debian Bullseye, systemd unit for Fail2ban doesn't come with a decent
integration with Nftables.
So this role will create override file for `fail2ban` unit, even if it's not
(yet) available on the host, in order to :
* Start `fail2ban` unit after `nftables`.
* Restart `fail2ban` unit when `nftables` unit restart.
## Development
This source code comes from our [Gogs instance][nftables source] and the [Github repo][nftables github] exist just to be able to send the role to Ansible Galaxy…
This source code comes from our [Gitea instance][nftables source] and the
[Github repo][nftables github] exist just to be able to send the role to Ansible
Galaxy…
But feel free to send issue/PR here :)
Thanks to this [hook][gogs to github hook], Github automatically got updates from our [Gogs instance][nftables source] :)
Thanks to this [hook][gogs to github hook], Github automatically got updates from our [Gitea instance][nftables source] :)
## License
@ -272,11 +596,11 @@ Thanks to this [hook][gogs to github hook], Github automatically got updates fro
## Author Information
Jérémy Gardais
* Source: [on IPR's Gogs][nftables source]
* Source: [on IPR's Gitea][nftables source]
* [IPR][ipr website] (Institut de Physique de Rennes)
[gogs to github hook]: https://stackoverflow.com/a/21998477
[nftables source]: https://git.ipr.univ-rennes1.fr/cellinfo/ansible.nftables
[nftables source]: https://git.ipr.univ-rennes.fr/cellinfo/ansible.nftables
[nftables github]: https://github.com/ipr-cnrs/nftables
[wtfpl website]: http://www.wtfpl.net/about/
[ipr website]: https://ipr.univ-rennes1.fr/

View File

@ -1,34 +1,266 @@
---
# defaults file for nftables
# .. vim: foldmarker=[[[,]]]:foldmethod=marker
#
# ipr-cnrs.nftables default variables
# ===================================
# packages
nft_pkg_manage: true
nft_pkg_state: 'installed'
nft_old_pkg_list: 'iptables'
# Packages and installation [[[
# -----------------------------
# .. envvar:: nft_enabled [[[
#
# Enable or disable support for Nftables on a given host. Disabling this
# option does not remove existing installation and configuration.
#
nft_enabled: true
# ]]]
# .. envvar:: nft_pkg_state [[[
#
# What is the desired state for Nftables packages? Possible options:
#
# ``present``
# Default. Nftables packages will be installed.
#
# ``absent``
# Ensure to remove Nftables related packages.
nft_pkg_state: 'present'
# ]]]
# .. envvar:: nft_old_pkg_list [[[
#
# List of old Iptables packages to remove to avoid duplicate firewall.
#
nft_old_pkg_list:
- 'iptables'
- 'libiptc0'
# ]]]
# .. envvar:: nft_old_pkg_state [[[
#
# What is the desired state for Iptables packages? Possible options:
#
# ``absent``
# Default. Ensure to remove Iptables related packages.
#
# ``present``
# Iptables packages will be kept.
nft_old_pkg_state: 'absent'
# ]]]
# .. envvar:: nft_old_pkg_manage [[[
#
# If the old Iptables packages should be managed? Possible options:
#
# ``true``
# Default. Ensure to apply the required state for Iptables related packages.
#
# ``false``
# Iptables packages will not be touched.
nft_old_pkg_manage: true
# ]]]
# ]]]
# Nftables global rules [[[
# -------------------------
# files
nft_conf_dir_path: '/etc/nftables.d'
nft_main_conf_path: '/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_define_conf_path: '{{ nft_conf_dir_path }}/defines.nft'
nft_define_conf_content: 'etc/nftables.d/defines.nft.j2'
nft_set_conf_path: '{{ nft_conf_dir_path }}/sets.nft'
nft_set_conf_content: 'etc/nftables.d/sets.nft.j2'
# rules
# .. envvar:: nft_global_default_rules [[[
#
# List of global rules (applied on all tables) to configure for all hosts
# inherited from this role.
nft_global_default_rules:
005 state management:
- ct state established,related accept
- ct state invalid drop
# ]]]
# .. envvar:: nft_global_rules [[[
#
# List of global rules (applied on all tables) to configure for all hosts
# in the Ansible inventory.
nft_global_rules: {}
# ]]]
# .. envvar:: nft_merged_groups [[[
#
# Enable or disable the ability to merge multiple firewall group variables
nft_merged_groups: false
# ]]]
# .. envvar:: nft_merged_groups_dir [[[
#
# The directory to read the group firewall rules from.
# Relative to the playbook directory.
nft_merged_groups_dir: vars/
# ]]]
# .. envvar:: nft_global_group_rules [[[
#
# List of global rules (applied on all tables) to configure for hosts in
# specific Ansible inventory group.
nft_global_group_rules: {}
# ]]]
# .. envvar:: nft_global_host_rules [[[
#
# List of global rules (applied on all tables) to configure for specific hosts
# in the Ansible inventory.
nft_global_host_rules: {}
# ]]]
# .. envvar:: nft__custom_content [[[
#
# Custom content (tables, include,…) to add in Nftables configuration.
nft__custom_content: ''
# ]]]
# .. envvar:: nft_custom_includes [[[
#
# Custom includes to add into the main Nftables filter configuration.
nft_custom_includes: ''
# ]]]
# .. envvar:: nft_conf_dir_path [[[
#
# Path to the sub directory for Nftables configuration files.
#
# Should be an absolut path and this var will be used in all *_path vars.
nft_conf_dir_path: '/etc/nftables.d'
# ]]]
# .. envvar:: nft_main_conf_path [[[
#
# Path to the main configuration file called by the Systemd Nftables service.
#
# Should be an absolut path.
nft_main_conf_path: '/etc/nftables.conf'
# ]]]
# .. envvar:: nft_main_conf_content [[[
#
# Template used to provide the previous main configuration file.
#
# Must be a relative path from default/ directory of this role or from your
# Ansible inventory directory.
nft_main_conf_content: 'etc/nftables.conf.j2'
# ]]]
# ]]]
# Nftables vars definition [[[
# ----------------------------
#
# These lists allow to define some vars that can be used in nftables rules.
# See the official Nftables wiki page for more informations and examples:
# https://wiki.nftables.org/wiki-nftables/index.php/Scripting#Defining_variables
# .. envvar:: nft_define_default [[[
#
# List of vars definition to configure for all hosts inherited from this role.
nft_define_default:
broadcast and multicast:
desc: 'broadcast and multicast'
name: badcast_addr
value: '{ 255.255.255.255, 224.0.0.1, 224.0.0.251 }'
ip6 broadcast and multicast:
desc: 'broadcast and multicast'
name: ip6_badcast_addr
value: '{ ff02::16 }'
input tcp accepted:
name: in_tcp_accept
value: '{ ssh }'
output tcp accepted:
name: out_tcp_accept
value: '{ http, https, hkp }'
output udp accepted:
name: out_udp_accept
value: '{ bootps, domain, ntp }'
# ]]]
# .. envvar:: nft_define [[[
#
# List of vars definition to configure for all hosts in the Ansible inventory.
nft_define: {}
# ]]]
# .. envvar:: nft_define_group [[[
#
# List of vars definition to configure for hosts in specific
# Ansible inventory group.
nft_define_group: {}
# ]]]
# .. envvar:: nft_define_host [[[
#
# List of vars definition to configure for specific hosts
# in the Ansible inventory.
nft_define_host: {}
# ]]]
# .. envvar:: nft_define_conf_path [[[
#
# Path to the defined vars file to include in the main configuration file
# in order to use the previous defined lists.
#
# Should include the '{{ nft_conf_dir_path }}' var or be an absolut path.
nft_define_conf_path: '{{ nft_conf_dir_path }}/defines.nft'
# ]]]
# .. envvar:: nft_define_conf_content [[[
#
# Template used to provide the previous defined vars file.
#
# Must be a relative path from default/ directory of this role or from your
# Ansible inventory directory.
nft_define_conf_content: 'etc/nftables.d/defines.nft.j2'
# ]]]
# ]]]
# Nftables sets definition [[[
# ----------------------------
#
# These "set" lists allow to define sets that can be used in Nftables rules.
# See the official Nftables wiki page for more informations and examples:
# https://wiki.nftables.org/wiki-nftables/index.php/Sets
# .. envvar:: nft_define_default [[[
#
# List of sets to configure for all hosts inherited from this role.
nft_set_default:
blackhole:
- type ipv4_addr;
- elements = $badcast_addr
ip6blackhole:
- type ipv6_addr;
- elements = $ip6_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
# ]]]
# .. envvar:: nft_set [[[
#
# List of sets to configure for all hosts in the Ansible inventory.
nft_set: {}
# ]]]
# .. envvar:: nft_set_group [[[
#
# List of sets to configure for hosts in specific Ansible inventory group.
nft_set_group: {}
# ]]]
# .. envvar:: nft_set_host [[[
#
# List of sets to configure for specific hosts in the Ansible inventory.
nft_set_host: {}
# ]]]
# .. envvar:: nft_set_conf_path [[[
#
# Path to the "sets" file to include in the main configuration file
# in order to use the previous defined lists.
#
# Should include the '{{ nft_conf_dir_path }}' var or be an absolut path.
nft_set_conf_path: '{{ nft_conf_dir_path }}/sets.nft'
# ]]]
# .. envvar:: nft_set_conf_content [[[
#
# Template used to provide the previous "sets" file.
#
# Must be a relative path from default/ directory of this role or from your
# Ansible inventory directory.
nft_set_conf_content: 'etc/nftables.d/sets.nft.j2'
# ]]]
# ]]]
# inet filter table rules [[[
# ---------------------------
#
# All these rules will be set up in an inet table in order to filter the
# input and output traffic.
# .. envvar:: nft_input_default_rules [[[
#
# List of input rules to configure for all hosts inherited from this role.
nft_input_default_rules:
000 policy:
- type filter hook input priority 0; policy drop;
@ -36,15 +268,50 @@ nft_input_default_rules:
- jump global
010 drop unwanted:
- ip daddr @blackhole counter drop
011 drop unwanted ipv6:
- ip6 daddr @ip6blackhole counter drop
015 localhost:
- iif lo accept
200 input udp accepted:
- udp dport @in_udp_accept ct state new accept
050 icmp:
- meta l4proto {icmp,icmpv6} accept
210 input tcp accepted:
- tcp dport @in_tcp_accept ct state new accept
# ]]]
# .. envvar:: nft_input_rules [[[
#
# List of input rules to configure for all hosts in the Ansible inventory.
nft_input_rules: {}
# ]]]
# .. envvar:: nft_input_group_rules [[[
#
# List of input rules to configure for hosts in specific Ansible inventory group.
nft_input_group_rules: {}
# ]]]
# .. envvar:: nft_input_host_rules [[[
#
# List of input rules to configure for specific hosts in the Ansible inventory.
nft_input_host_rules: {}
# ]]]
# .. envvar:: nft_input_conf_path [[[
#
# Path to the input rules file for the filter table to include in the main
# configuration file in order to use the previous defined lists.
#
# Should include the '{{ nft_conf_dir_path }}' var or be an absolut path.
nft_input_conf_path: '{{ nft_conf_dir_path }}/filter-input.nft'
# ]]]
# .. envvar:: nft_input_conf_content [[[
#
# Template used to provide the previous input rules file.
#
# Must be a relative path from default/ directory of this role or from your
# Ansible inventory directory.
nft_input_conf_content: 'etc/nftables.d/filter-input.nft.j2'
# ]]]
# .. envvar:: nft_output_default_rules [[[
#
# List of output rules to configure for all hosts inherited from this role.
nft_output_default_rules:
000 policy:
- type filter hook output priority 0; policy drop;
@ -59,50 +326,296 @@ nft_output_default_rules:
- udp dport @out_udp_accept ct state new accept
210 output tcp accepted:
- tcp dport @out_tcp_accept ct state new accept
250 reset-ssh: # allow the host to reset SSH connections to avoid 10 min delay from Ansible controller
- tcp sport ssh tcp flags { rst, psh | ack } counter accept
# ]]]
# .. envvar:: nft_output_rules [[[
#
# List of output rules to configure for all hosts in the Ansible inventory.
nft_output_rules: {}
# ]]]
# .. envvar:: nft_output_group_rules [[[
#
# List of output rules to configure for hosts in specific Ansible inventory group.
nft_output_group_rules: {}
# ]]]
# .. envvar:: nft_output_host_rules [[[
#
# List of output rules to configure for specific hosts in the Ansible inventory.
nft_output_host_rules: {}
# ]]]
# .. envvar:: nft_output_conf_path [[[
#
# Path to the output rules file for the filter table to include in the main
# configuration file in order to use the previous defined lists.
#
# Should include the '{{ nft_conf_dir_path }}' var or be an absolut path.
nft_output_conf_path: '{{ nft_conf_dir_path }}/filter-output.nft'
# ]]]
# .. envvar:: nft_output_conf_content [[[
#
# Template used to provide the previous output rules file.
#
# Must be a relative path from default/ directory of this role or from your
# Ansible inventory directory.
nft_output_conf_content: 'etc/nftables.d/filter-output.nft.j2'
# ]]]
# .. envvar:: nft__forward_table_manage [[[
#
# If the forward table should be managed? Possible options are:
#
# ``False``
# Default. The forward table is not managed and rules will not be added.
#
# ``True``
# Add the forwarding rules that follow.
nft__forward_table_manage: false
# ]]]
# .. envvar:: nft_forward_default_rules [[[
#
# List of forward rules to configure for all hosts inherited from this role.
nft_forward_default_rules:
000 policy:
- type filter hook forward priority 0; policy drop;
005 global:
- jump global
# ]]]
# .. envvar:: nft_forward_rules [[[
#
# List of forward rules to configure for all hosts in the Ansible inventory.
nft_forward_rules: {}
# ]]]
# .. envvar:: nft_forward_group_rules [[[
#
# List of forward rules to configure for hosts in specific Ansible inventory group.
nft_forward_group_rules: {}
# ]]]
# .. envvar:: nft_forward_host_rules [[[
#
# List of forward rules to configure for specific hosts in the Ansible inventory.
nft_forward_host_rules: {}
# ]]]
# .. envvar:: nft_forward_conf_path [[[
#
# Path to the forward rules file for the filter table to include in the main
# configuration file in order to use the previous defined lists.
#
# Should include the '{{ nft_conf_dir_path }}' var or be an absolut path.
nft_forward_conf_path: '{{ nft_conf_dir_path }}/filter-forward.nft'
# ]]]
# .. envvar:: nft_forward_conf_content [[[
#
# Template used to provide the previous forward rules file.
#
# Must be a relative path from default/ directory of this role or from your
# Ansible inventory directory.
nft_forward_conf_content: 'etc/nftables.d/filter-forward.nft.j2'
# ]]]
# ]]]
# ip nat table rules [[[
# ---------------------------
#
# All these rules will be set up in an ip table in order to perform some
# Network Address Translation (NAT).
# define nft vars
nft_define_default:
broadcast and multicast:
desc: 'broadcast and multicast'
name: badcast_addr
value: '{ 255.255.255.255, 224.0.0.1, 224.0.0.251 }'
input tcp accepted:
name: in_tcp_accept
value: '{ ssh }'
input udp accepted:
name: in_udp_accept
value: 'none'
output tcp accepted:
name: out_tcp_accept
value: '{ http, https, hkp }'
output udp accepted:
name: out_udp_accept
value: '{ bootps, domain, ntp }'
nft_define_group: {}
nft_define_host: {}
# .. envvar:: nft__nat_table_manage [[[
#
# If the nat table should be managed? Possible options are:
#
# ``False``
# Default. The nat table is not managed and rules will not be added.
#
# ``True``
# Add the pre and postrouting rules that follow.
nft__nat_table_manage: False
# ]]]
# .. envvar:: nft__nat_default_prerouting_rules [[[
#
# List of prerouting rules to configure for all hosts inherited from this role.
nft__nat_default_prerouting_rules:
000 policy:
- type nat hook prerouting priority 0;
# ]]]
# .. envvar:: nft__nat_prerouting_rules [[[
#
# List of prerouting rules to configure for all hosts in the Ansible inventory.
nft__nat_prerouting_rules: {}
# ]]]
# .. envvar:: nft__nat_group_prerouting_rules [[[
#
# List of prerouting rules to configure for hosts in specific
# Ansible inventory group.
nft__nat_group_prerouting_rules: {}
# ]]]
# .. envvar:: nft__nat_host_prerouting_rules [[[
#
# List of prerouting rules to configure for specific hosts
# in the Ansible inventory.
nft__nat_host_prerouting_rules: {}
# ]]]
# .. envvar:: nft__nat_prerouting_conf_path [[[
#
# Path to the prerouting rules file for the nat table to include in the main
# configuration file in order to use the previous defined lists.
#
# Should include the '{{ nft_conf_dir_path }}' var or be an absolut path.
nft__nat_prerouting_conf_path: '{{ nft_conf_dir_path }}/nat-prerouting.nft'
# ]]]
# .. envvar:: nft__nat_prerouting_conf_content [[[
#
# Template used to provide the previous prerouting rules file.
#
# Must be a relative path from default/ directory of this role or from your
# Ansible inventory directory.
nft__nat_prerouting_conf_content: 'etc/nftables.d/nat-prerouting.nft.j2'
# ]]]
# sets and maps
nft_set_default:
blackhole:
- type ipv4_addr;
- elements = $badcast_addr
in_tcp_accept:
- type inet_service; flags interval;
- elements = $in_tcp_accept
in_udp_accept:
- type inet_service; flags interval;
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_group: {}
nft_set_host: {}
# .. envvar:: nft__nat_default_postrouting_rules [[[
#
# List of postrouting rules to configure for all hosts inherited from this role.
nft__nat_default_postrouting_rules:
000 policy:
- type nat hook postrouting priority 100;
# ]]]
# .. envvar:: nft__nat_postrouting_rules [[[
#
# List of postrouting rules to configure for all hosts in the Ansible inventory.
nft__nat_postrouting_rules: {}
# ]]]
# .. envvar:: nft__nat_group_postrouting_rules [[[
#
# List of postrouting rules to configure for hosts in specific
# Ansible inventory group.
nft__nat_group_postrouting_rules: {}
# ]]]
# .. envvar:: nft__nat_host_postrouting_rules [[[
#
# List of postrouting rules to configure for specific hosts
# in the Ansible inventory.
nft__nat_host_postrouting_rules: {}
# ]]]
# .. envvar:: nft__nat_postrouting_conf_path [[[
#
# Path to the postrouting rules file for the nat table to include in the main
# configuration file in order to use the previous defined lists.
#
# Should include the '{{ nft_conf_dir_path }}' var or be an absolut path.
nft__nat_postrouting_conf_path: '{{ nft_conf_dir_path }}/nat-postrouting.nft'
# ]]]
# .. envvar:: nft__nat_postrouting_conf_content [[[
#
# Template used to provide the previous postrouting rules file.
#
# Must be a relative path from default/ directory of this role or from your
# Ansible inventory directory.
nft__nat_postrouting_conf_content: 'etc/nftables.d/nat-postrouting.nft.j2'
# ]]]
# ]]]
# Service management [[[
# ----------------------
# service
# .. envvar:: nft_service_manage [[[
#
# If the Nftables service should be managed? Possible options are:
#
# ``True``
# Default. The service is started.
#
# ``False``
# The service will not be touched.
nft_service_manage: true
# ]]]
# .. envvar:: nft_service_name [[[
#
# The service name to manage.
nft_service_name: 'nftables'
# ]]]
# .. envvar:: nft_service_enabled [[[
#
# If the Nftables service should be enabled at startup? Possible options are:
#
# ``True``
# Default. The service is enabled.
#
# ``False``
# The service is disabled from startup.
nft_service_enabled: true
# ]]]
# .. envvar:: nft_service_unit_path [[[
#
# Path to store Nftables service.
nft_service_unit_path: '/lib/systemd/system/nftables.service'
# ]]]
# .. envvar:: nft_service_unit_content [[[
#
# Template used to provide systemd unit for Nftables service.
nft_service_unit_content: 'lib/systemd/system/nftables.service.j2'
# ]]]
# .. envvar:: nft__service_override_path [[[
#
# Path to store Nftables custom conf.
nft__service_override_path: '/etc/systemd/system/nftables.service.d/override.conf'
# ]]]
# .. envvar:: nft__service_override_content [[[
#
# Template used to provide systemd custom conf for Nftables service.
nft__service_override_content: 'etc/systemd/system/nftables.service.d/override.conf.j2'
# ]]]
# .. envvar:: nft__service_protect [[[
#
# If the systemd unit should have the Protect directives? Possible options:
#
# ``True``
# Default. Directives will be set (ProtectSystem, ProtectHome,…).
#
# ``False``
# The directives will be ignored.
nft__service_protect: true
# ]]]
# .. envvar:: nft__fail2ban_service_unit_path [[[
#
# Path to store Fail2Ban custom conf.
nft__fail2ban_service_unit_path: '/etc/systemd/system/fail2ban.service.d/override.conf'
# ]]]
# .. envvar:: nft__fail2ban_service_unit_content [[[
#
# Template used to provide systemd custom conf for Fail2Ban service.
nft__fail2ban_service_unit_content: 'etc/systemd/system/fail2ban.service.d/override.conf.j2'
# ]]]
#
# .. envvar:: nft_debug [[[
#
# Toggle on/off more verbose output. Possible options are:
#
# ''Flase''
# Default. No additional output will be given.
#
# ''True''
# More verbose output.
nft_debug: False
# .. envvar:: nft_backup_conf [[[
#
# If the nftables config files should be backuped when changed?
# Possible optionsare:
#
# ``True``
# Default. Backup all nftables config files inside the nftables directory.
#
# ``False``
# Configs will not be backuped.
nft_backup_conf: True
# ]]]
# ]]]
# ]]]
# OS specific variables defaults [[[
# ----------------------------------
# .. envvar:: nft__bin_location [[[
#
# Specify Nftables executable location.
#
nft__bin_location: '/usr/sbin/nft'
# ]]]
# ]]]

View File

@ -1,5 +1,23 @@
---
# handlers file for nftables
- name: restart nftables service
service: name={{ nft_service_name }} state=restarted
when: nft_service_manage
# (re)Start will be called at first run
- name: Restart nftables service
systemd:
daemon_reload: '{{ (nftables__register_systemd_service.changed | default(False)) or
(nftables__register_fail2ban_service.changed | default(False)) or
(nftables__register_fix_systemd_target.changed | default(False)) or
(nftables__register_systemd_custom.changed | default(False)) }}'
state: 'restarted'
name: '{{ nft_service_name }}'
enabled: '{{ nft_service_enabled }}'
when: ansible_service_mgr == 'systemd' and nft_service_manage
# Reload will avoid to loose Nftables rulebase if an invalid syntax is added
- name: Reload nftables service
systemd:
state: 'reloaded'
name: '{{ nft_service_name }}'
when: ansible_service_mgr == 'systemd' and
nft_service_manage and
not nftables__register_systemd_service.changed

View File

@ -1,22 +1,34 @@
---
dependencies: []
galaxy_info:
author: "Jérémy Gardais"
namespace: ipr-cnrs
role_name: nftables
description: "Manage Nftables rules and packages"
license: WTFPL
company: IPR
issue_tracker_url: https://git.ipr.univ-rennes1.fr/cellinfo/ansible.nftables/issues
min_ansible_version: 2.2
issue_tracker_url: https://git.ipr.univ-rennes.fr/cellinfo/ansible.nftables/issues
min_ansible_version: '2.5'
platforms:
- name: Debian
versions:
- bullseye
- buster
- stretch
#- name: opensuse
# versions:
# - all
# - 12.1
# - 12.2
# - 12.3
# - 13.1
# - 13.2
- name: Archlinux
versions:
- all
- name: Fedora
versions:
- all
- name: Gentoo
versions:
- all
- name: Ubuntu
versions:
- focal
galaxy_tags:
- system
- nftables

View File

@ -0,0 +1,7 @@
FROM archlinux:latest
ENV container=docker
RUN pacman -Sy --noconfirm python
VOLUME ["/sys/fs/cgroup", "/tmp", "/run"]
CMD ["/usr/sbin/init"]

View File

@ -0,0 +1,9 @@
---
- name: Converge
hosts: all
gather_facts: yes
roles:
- role: ipr-cnrs.nftables
nft_debug: true
# can't remove iptables on an instance with docker
nft_old_pkg_manage: false

View File

@ -0,0 +1,19 @@
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: archlinux
image: archlinux:latest
command: /usr/sbin/init
privileged: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
tmpfs:
- /run
- /tmp
provisioner:
name: ansible
verifier:
name: ansible

View File

@ -0,0 +1,92 @@
---
# This is an example playbook to execute Ansible tests.
- name: Verify
hosts: all
gather_facts: false
tasks:
- name: check for nftables.d
stat:
path: /etc/nftables.d
register: p
- name: check nftables.d
assert:
that:
- p.stat.exists and p.stat.isdir
- name: check for nftables.conf
stat:
path: /etc/nftables.conf
register: p
- name: check nftables.conf
assert:
that:
- p.stat.exists
- name: check for filter-input.nft
stat:
path: /etc/nftables.d/filter-input.nft
register: p
- name: check filter-input.nft
assert:
that:
- p.stat.exists
- name: list rules
command: nft list ruleset
register: nft
- name: debug rules
debug: var=nft
- name: check rules
assert:
that:
# The whole line is:
# type filter hook input priority 0; policy drop;
# However on CentOS will return "priority 0", while Debian will
# show "priority filter"
- '"type filter hook input" in nft.stdout'
- '"type filter hook output" in nft.stdout'
- name: check for fail2ban systemd custom dir
stat:
path: /etc/systemd/system/fail2ban.service.d
register: f2b_systemd_dir
- name: check fail2ban systemd custom dir
assert:
that:
- f2b_systemd_dir.stat.exists and f2b_systemd_dir.stat.isdir
- name: check for fail2ban systemd override
stat:
path: /etc/systemd/system/fail2ban.service.d/override.conf
register: f2b_systemd_override
- name: check fail2ban systemd override
assert:
that:
- f2b_systemd_override.stat.exists
- name: service status - active
command: systemctl is-active nftables.service
register: status
- name: check service status
assert:
that:
- 'status.stdout == "active"'
- name: service status - enabled
command: systemctl is-enabled nftables.service
register: status
- name: check service status
assert:
that:
- 'status.stdout == "enabled"'

View File

@ -0,0 +1,9 @@
---
- name: Converge
hosts: all
gather_facts: yes
roles:
- role: ipr-cnrs.nftables
nft_debug: true
# can't remove iptables on an instance with docker
nft_old_pkg_manage: false

View File

@ -0,0 +1,55 @@
---
dependency:
name: galaxy
lint: |
set -e
yamllint .
ansible-lint
driver:
name: docker
platforms:
- name: systemd-ubuntu-latest
image: jrei/systemd-ubuntu:latest
command: /usr/sbin/init
privileged: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
tmpfs:
- /run
- /tmp
- name: systemd-centos-latest
image: centos/systemd:latest
command: /usr/sbin/init
privileged: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
tmpfs:
- /run
- /tmp
- name: systemd-debian-latest
image: jrei/systemd-debian:latest
command: /sbin/init
privileged: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
tmpfs:
- /run
- /tmp
- name: systemd-fedora-latest
image: jrei/systemd-fedora:latest
command: /usr/sbin/init
privileged: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
tmpfs:
- /run
- /tmp
provisioner:
name: ansible
verifier:
name: ansible

View File

@ -0,0 +1,92 @@
---
# This is an example playbook to execute Ansible tests.
- name: Verify
hosts: all
gather_facts: false
tasks:
- name: check for nftables.d
stat:
path: /etc/nftables.d
register: p
- name: check nftables.d
assert:
that:
- p.stat.exists and p.stat.isdir
- name: check for nftables.conf
stat:
path: /etc/nftables.conf
register: p
- name: check nftables.conf
assert:
that:
- p.stat.exists
- name: check for filter-input.nft
stat:
path: /etc/nftables.d/filter-input.nft
register: p
- name: check filter-input.nft
assert:
that:
- p.stat.exists
- name: list rules
command: nft list ruleset
register: nft
- name: debug rules
debug: var=nft
- name: check rules
assert:
that:
# The whole line is:
# type filter hook input priority 0; policy drop;
# However on CentOS will return "priority 0", while Debian will
# show "priority filter"
- '"type filter hook input" in nft.stdout'
- '"type filter hook output" in nft.stdout'
- name: check for fail2ban systemd custom dir
stat:
path: /etc/systemd/system/fail2ban.service.d
register: f2b_systemd_dir
- name: check fail2ban systemd custom dir
assert:
that:
- f2b_systemd_dir.stat.exists and f2b_systemd_dir.stat.isdir
- name: check for fail2ban systemd override
stat:
path: /etc/systemd/system/fail2ban.service.d/override.conf
register: f2b_systemd_override
- name: check fail2ban systemd override
assert:
that:
- f2b_systemd_override.stat.exists
- name: service status - active
command: systemctl is-active nftables.service
register: status
- name: check service status
assert:
that:
- 'status.stdout == "active"'
- name: service status - enabled
command: systemctl is-enabled nftables.service
register: status
- name: check service status
assert:
that:
- 'status.stdout == "enabled"'

View File

@ -0,0 +1,5 @@
FROM gentoo/stage3:systemd
ENV container=docker
VOLUME ["/sys/fs/cgroup"]
CMD ["/sbin/init"]

View File

@ -0,0 +1,9 @@
---
- name: Converge
hosts: all
gather_facts: yes
roles:
- role: ipr-cnrs.nftables
nft_debug: true
# can't remove iptables on an instance with docker
nft_old_pkg_manage: false

View File

@ -0,0 +1,21 @@
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: Gentoo
image: gentoo/stage3:systemd
command: /sbin/init
privileged: true
volumes:
- /srv/gentoo-molecule/gentoo-repo:/var/db/repos/gentoo
- /srv/gentoo-molecule/binpkgs:/var/cache/binpkgs
- /sys/fs/cgroup:/sys/fs/cgroup:ro
tmpfs:
- /run
- /tmp
provisioner:
name: ansible
verifier:
name: ansible

View File

@ -0,0 +1,34 @@
# Taken from https://github.com/VTimofeenko/portage-overlay-cfg on commit d8914035e236c4f3819985098dd1ae36551bfc52
# If bugs are found check that repository
# Since Gentoo builds from source, to save time on molecule tests, we should reuse artifacts as much as possible
# This playbook performs the initial setup of a Gentoo container
# It configures portage to try to use prebuilt packages if available and to save the built packages.
---
- name: Run preparation playbook
hosts: Gentoo
tasks:
- name: Enable buildpkg feature
lineinfile:
line: "FEATURES='buildpkg'"
dest: /etc/portage/make.conf
state: present
- name: Enable trying to install from binpkgs by default
lineinfile:
line: "EMERGE_DEFAULT_OPTS='--usepkg'"
dest: /etc/portage/make.conf
state: present
- name: Synchronize gentoo repository if needed
block:
- name: Check if there is anything in the repo
find:
paths: '/var/db/repos/gentoo/'
register: find_files_in_repo
- name: Synchronize the repo if needed
command: "emaint sync -a"
when: find_files_in_repo.matched == 0
- name: Install equery, needed for package check
# Command, because equery does not exist yet
command: emerge --changed-use --oneshot app-portage/gentoolkit
changed_when: false
# The rest of the original file is specific to that role and not needed here

View File

@ -0,0 +1,92 @@
---
# This is an example playbook to execute Ansible tests.
- name: Verify
hosts: all
gather_facts: false
tasks:
- name: check for nftables.d
stat:
path: /etc/nftables.d
register: p
- name: check nftables.d
assert:
that:
- p.stat.exists and p.stat.isdir
- name: check for nftables.conf
stat:
path: /etc/nftables.conf
register: p
- name: check nftables.conf
assert:
that:
- p.stat.exists
- name: check for filter-input.nft
stat:
path: /etc/nftables.d/filter-input.nft
register: p
- name: check filter-input.nft
assert:
that:
- p.stat.exists
- name: list rules
command: nft list ruleset
register: nft
- name: debug rules
debug: var=nft
- name: check rules
assert:
that:
# The whole line is:
# type filter hook input priority 0; policy drop;
# However on CentOS will return "priority 0", while Debian will
# show "priority filter"
- '"type filter hook input" in nft.stdout'
- '"type filter hook output" in nft.stdout'
- name: check for fail2ban systemd custom dir
stat:
path: /etc/systemd/system/fail2ban.service.d
register: f2b_systemd_dir
- name: check fail2ban systemd custom dir
assert:
that:
- f2b_systemd_dir.stat.exists and f2b_systemd_dir.stat.isdir
- name: check for fail2ban systemd override
stat:
path: /etc/systemd/system/fail2ban.service.d/override.conf
register: f2b_systemd_override
- name: check fail2ban systemd override
assert:
that:
- f2b_systemd_override.stat.exists
- name: service status - active
command: systemctl is-active nftables.service
register: status
- name: check service status
assert:
that:
- 'status.stdout == "active"'
- name: service status - enabled
command: systemctl is-enabled nftables.service
register: status
- name: check service status
assert:
that:
- 'status.stdout == "enabled"'

View File

@ -1,37 +1,90 @@
---
# .. vim: foldmarker=[[[,]]]:foldmethod=marker
#
# tasks file for nftables
- name: Load specific OS vars for nft
include_vars: "{{ item }}"
- name: Check for group files
become: no
delegate_to: localhost
stat:
path: "{{ nft_merged_groups_dir ~ groupname }}"
register: nftables_group_rules
loop: "{{ group_names }}"
loop_control:
loop_var: groupname
- name: Debug nftables_group_rules
debug: var=nftables_group_rules
when: nft_debug
- name: Import nftables-variables if nft_merged_groups is set
when: nft_merged_groups and varfile.stat.exists
include_vars:
file: "{{ nft_merged_groups_dir ~ varfile.groupname }}"
name: "{{ varfile.groupname }}"
loop: "{{ nftables_group_rules.results }}"
loop_control:
loop_var: varfile
- name: Combine Rules when nft_merged_groups is set
when: nft_merged_groups and
((hostvars[inventory_hostname][varfile.groupname] is defined) and
(hostvars[inventory_hostname][varfile.groupname]|length > 0)) and
varfile.stat.exists
set_fact:
nft_combined_rules: "{{ nft_combined_rules | default({}) | combine ( hostvars[inventory_hostname][varfile.groupname], recursive=True ) }}"
loop: "{{ nftables_group_rules.results }}"
loop_control:
loop_var: varfile
- name: Debug nft_combined_rules
debug: var=nft_combined_rules
when: nft_debug
- name: Debug ansible_os_family
debug: var=ansible_os_family
when: nft_debug
- name: Load specific OS vars for nftables
include_vars: "{{ osname }}"
with_first_found:
- "{{ ansible_distribution|lower }}-{{ ansible_distribution_version }}.yml"
- "{{ ansible_distribution|lower }}.yml"
- "{{ ansible_os_family|lower }}.yml"
loop_control:
loop_var: osname
# package {{{
- name: INSTALL Manage nftables packages
# Manage packages [[[1
- name: Update repositories
package:
name: '{{ item }}'
update_cache: true
when: (nft_enabled|bool and
ansible_os_family not in [ 'Gentoo' ])
- name: Ensure Nftables packages are in their desired state
package:
name: '{{ nft_pkg_list | list }}'
state: '{{ nft_pkg_state }}'
with_items:
- '{{ nft_pkg_list }}'
when: nft_pkg_manage
register: pkg_install_result
until: pkg_install_result is success
when: nft_enabled|bool
- name: INSTALL Remove iptables packages
apt:
name: '{{ item }}'
- name: Ensure old Iptables packages are in their desired state
package:
name: '{{ nft_old_pkg_list | list }}'
state: '{{ nft_old_pkg_state }}'
with_items:
- '{{ nft_old_pkg_list }}'
when: nft_old_pkg_manage
# }}}
register: pkg_remove_result
until: pkg_remove_result is success
when: (nft_enabled|bool and
nft_old_pkg_manage|bool)
# conf {{{
- name: CONFIG create nftables.d dir
# Common configuration [[[1
- name: Ensure to create nftables.d directory
file:
path: "{{ nft_conf_dir_path }}"
state: directory
mode: 0755
when: nft_enabled|bool
- name: CONFIG generate main conf file
template:
@ -40,28 +93,9 @@
owner: root
group: root
mode: 0755
backup: yes
notify: restart nftables service
- name: CONFIG generate input rules file
template:
src: "{{ nft_input_conf_content }}"
dest: "{{ nft_input_conf_path }}"
owner: root
group: root
mode: 0755
backup: yes
notify: restart nftables service
- name: CONFIG generate output rules file
template:
src: "{{ nft_output_conf_content }}"
dest: "{{ nft_output_conf_path }}"
owner: root
group: root
mode: 0755
backup: yes
notify: restart nftables service
backup: "{{ nft_backup_conf }}"
notify: ['Reload nftables service']
when: nft_enabled|bool
- name: CONFIG generate vars definition file
template:
@ -70,25 +104,147 @@
owner: root
group: root
mode: 0755
backup: yes
notify: restart nftables service
backup: "{{ nft_backup_conf }}"
notify: ['Reload nftables service']
when: nft_enabled|bool
- name: CONFIG generate sets and maps file
- name: CONFIG generate sets file
template:
src: "{{ nft_set_conf_content }}"
dest: "{{ nft_set_conf_path }}"
owner: root
group: root
mode: 0755
backup: yes
notify: restart nftables service
# }}}
backup: "{{ nft_backup_conf }}"
notify: ['Reload nftables service']
when: nft_enabled|bool
# service {{{
- name: SERVICE manage '{{ nft_service_name }}'
service:
name: '{{ nft_service_name }}'
state: started
enabled: '{{ nft_service_enabled }}'
when: nft_service_manage
# }}}
# Filter table content [[[1
- name: Filter table - generate input rules file
template:
src: "{{ nft_input_conf_content }}"
dest: "{{ nft_input_conf_path }}"
owner: root
group: root
mode: 0755
backup: "{{ nft_backup_conf }}"
notify: ['Reload nftables service']
when: nft_enabled|bool
- name: Filter table - generate output rules file
template:
src: "{{ nft_output_conf_content }}"
dest: "{{ nft_output_conf_path }}"
owner: root
group: root
mode: 0755
backup: "{{ nft_backup_conf }}"
notify: ['Reload nftables service']
when: nft_enabled|bool
- name: Filter table - generate forward rules file
template:
src: "{{ nft_forward_conf_content }}"
dest: "{{ nft_forward_conf_path }}"
owner: root
group: root
mode: 0755
backup: yes
notify: ['Reload nftables service']
when: (nft_enabled|bool and
nft__forward_table_manage|bool)
# Nat table content [[[1
- name: Nat table - generate prerouting rules file
template:
src: "{{ nft__nat_prerouting_conf_content }}"
dest: "{{ nft__nat_prerouting_conf_path }}"
owner: root
group: root
mode: 0755
backup: "{{ nft_backup_conf }}"
notify: ['Reload nftables service']
when: (nft_enabled|bool and
nft__nat_table_manage|bool)
- name: Nat table - generate postrouting rules file
template:
src: "{{ nft__nat_postrouting_conf_content }}"
dest: "{{ nft__nat_postrouting_conf_path }}"
owner: root
group: root
mode: 0755
backup: "{{ nft_backup_conf }}"
notify: ['Reload nftables service']
when: (nft_enabled|bool and
nft__nat_table_manage|bool)
# Manage nftables service [[[1
- name: Install nftables Debian systemd service unit
template:
src: '{{ nft_service_unit_content }}'
dest: '{{ nft_service_unit_path }}'
owner: 'root'
group: 'root'
mode: '0644'
register: nftables__register_systemd_service
when: (nft_enabled|bool and
nft_service_manage|bool)
notify: ['Restart nftables service']
- name: Ensure to remove nftables systemd service from old target
file:
path: '/etc/systemd/system/multi-user.target.wants/nftables.service'
state: absent
register: nftables__register_fix_systemd_target
when: (nft_enabled|bool and
nft_service_manage|bool)
notify: ['Restart nftables service']
# Manage custom nftables service [[[1
- name: Create Nftables custom directory for systemd service
file:
path: "{{ nft__service_override_path | dirname }}"
state: directory
mode: '0755'
when:
- nft_enabled|bool
- nft_service_manage|bool
- not nft__service_protect|bool
- name: Add Nftables systemd custom configuration
template:
src: '{{ nft__service_override_content }}'
dest: '{{ nft__service_override_path }}'
owner: 'root'
group: 'root'
mode: '0644'
register: nftables__register_systemd_custom
when:
- nft_enabled|bool
- nft_service_manage|bool
- not nft__service_protect|bool
notify: ['Restart nftables service']
# Manage custom fail2ban service [[[1
- name: Create Fail2Ban custom directory for systemd service
file:
path: "{{ nft__fail2ban_service_unit_path | dirname }}"
state: directory
mode: '0755'
when:
- nft_enabled|bool
- nft_service_manage|bool
- name: Install Debian Fail2Ban custom service
template:
src: '{{ nft__fail2ban_service_unit_content }}'
dest: '{{ nft__fail2ban_service_unit_path }}'
owner: 'root'
group: 'root'
mode: '0644'
register: nftables__register_fail2ban_service
when:
- nft_enabled|bool
- nft_service_manage|bool
notify: ['Restart nftables service']

View File

@ -1,27 +1,58 @@
#!/usr/sbin/nft -f
#jinja2: lstrip_blocks: "True", trim_blocks: "True"
#!{{ nft__bin_location }} -f
# {{ ansible_managed }}
{% set globalmerged = nft_global_default_rules.copy() %}
{% set _ = globalmerged.update(nft_global_rules) %}
{% set _ = globalmerged.update(nft_global_group_rules) %}
{% if nft_merged_groups and hostvars[inventory_hostname]['nft_combined_rules'].nft_global_group_rules is defined%}
{% set _ = globalmerged.update(hostvars[inventory_hostname]['nft_combined_rules'].nft_global_group_rules) %}
{% endif %}
{% set _ = globalmerged.update(nft_global_host_rules) %}
# clean
flush ruleset
include "/etc/nftables.d/defines.nft"
include "{{ nft_define_conf_path }}"
table inet filter {
chain global {
{% for group, rules in globalmerged|dictsort %}
# {{ group }}
{% if not rules %}
{% if not rules %}
# (none)
{% endif %}
{% for rule in rules %}
{% endif %}
{% for rule in rules %}
{{ rule }}
{% endfor %}
{% endfor %}
{% endfor %}
}
include "{{ nft_set_conf_path }}"
include "{{ nft_input_conf_path }}"
include "{{ nft_output_conf_path }}"
{% if nft__forward_table_manage %}
include "{{ nft_forward_conf_path }}"
{% endif %}
{% if nft_custom_includes | default() %}
{% if nft_custom_includes is string %}
include "{{ nft_custom_includes }}"
{% elif nft_custom_includes is iterable and (nft_custom_includes is not string and nft_custom_includes is not mapping) %}
{% for include in nft_custom_includes %}
include "{{ include }}"
{% endfor %}
{% endif %}
{% endif %}
}
{% if nft__nat_table_manage %}
# Additionnal table for Network Address Translation (NAT)
table ip nat {
include "{{ nft_set_conf_path }}"
include "{{ nft__nat_prerouting_conf_path }}"
include "{{ nft__nat_postrouting_conf_path }}"
}
{% endif %}
{% if nft__custom_content|d() %}
# Custom content from ipr-cnrs.nftables
{{ nft__custom_content }}
{% endif %}

View File

@ -1,15 +1,19 @@
#jinja2: lstrip_blocks: "True", trim_blocks: "True"
# {{ ansible_managed }}
{% set definemerged = nft_define_default.copy() %}
{% set _ = definemerged.update(nft_define) %}
{% set _ = definemerged.update(nft_define_group) %}
{% if nft_merged_groups and hostvars[inventory_hostname]['nft_combined_rules'].nft_define_group is defined%}
{% set _ = definemerged.update(hostvars[inventory_hostname]['nft_combined_rules'].nft_define_group) %}
{% endif %}
{% set _ = definemerged.update(nft_define_host) %}
{% for definition in definemerged.values() %}
{% if definition.desc is defined %}
{% if definition.desc is defined %}
# {{ definition.desc }}
{% else %}
{% else %}
# {{ definition.name }}
{% endif %}
{% endif %}
define {{ definition.name }} = {{ definition.value }}
{% endfor %}

View File

@ -0,0 +1,21 @@
#jinja2: lstrip_blocks: "True", trim_blocks: "True"
# {{ ansible_managed }}
{% set forwardmerged = nft_forward_default_rules.copy() %}
{% set _ = forwardmerged.update(nft_forward_rules) %}
{% set _ = forwardmerged.update(nft_forward_group_rules) %}
{% if nft_merged_groups and hostvars[inventory_hostname]['nft_combined_rules'].nft_forward_group_rules is defined %}
{% set _ = forwardmerged.update(hostvars[inventory_hostname]['nft_combined_rules'].nft_forward_group_rules) %}
{% endif %}
{% set _ = forwardmerged.update(nft_forward_host_rules) %}
chain forward {
{% for group, rules in forwardmerged|dictsort %}
# {{ group }}
{% if not rules %}
# (none)
{% endif %}
{% for rule in rules %}
{{ rule }}
{% endfor %}
{% endfor %}
}

View File

@ -1,16 +1,21 @@
#jinja2: lstrip_blocks: "True", trim_blocks: "True"
# {{ ansible_managed }}
{% set inputmerged = nft_input_default_rules.copy() %}
{% set _ = inputmerged.update(nft_input_rules) %}
{% set _ = inputmerged.update(nft_input_group_rules) %}
{% if nft_merged_groups and hostvars[inventory_hostname]['nft_combined_rules'].nft_input_group_rules is defined %}
{% set _ = inputmerged.update(hostvars[inventory_hostname]['nft_combined_rules'].nft_input_group_rules) %}
{% endif %}
{% set _ = inputmerged.update(nft_input_host_rules) %}
chain input {
{% for group, rules in inputmerged|dictsort %}
# {{ group }}
{% if not rules %}
{% if not rules %}
# (none)
{% endif %}
{% for rule in rules %}
{% endif %}
{% for rule in rules %}
{{ rule }}
{% endfor %}
{% endfor %}
{% endfor %}
}

View File

@ -1,16 +1,21 @@
#jinja2: lstrip_blocks: "True", trim_blocks: "True"
# {{ ansible_managed }}
{% set outputmerged = nft_output_default_rules.copy() %}
{% set _ = outputmerged.update(nft_output_rules) %}
{% set _ = outputmerged.update(nft_output_group_rules) %}
{% if nft_merged_groups and hostvars[inventory_hostname]['nft_combined_rules'].nft_output_group_rules is defined %}
{% set _ = outputmerged.update(hostvars[inventory_hostname]['nft_combined_rules'].nft_output_group_rules) %}
{% endif %}
{% set _ = outputmerged.update(nft_output_host_rules) %}
chain output {
{% for group, rules in outputmerged|dictsort %}
# {{ group }}
{% if not rules %}
{% if not rules %}
# (none)
{% endif %}
{% for rule in rules %}
{% endif %}
{% for rule in rules %}
{{ rule }}
{% endfor %}
{% endfor %}
{% endfor %}
}

View File

@ -0,0 +1,21 @@
#jinja2: lstrip_blocks: "True", trim_blocks: "True"
# {{ ansible_managed }}
{% set postroutingmerged = nft__nat_default_postrouting_rules.copy() %}
{% set _ = postroutingmerged.update(nft__nat_postrouting_rules) %}
{% set _ = postroutingmerged.update(nft__nat_group_postrouting_rules) %}
{% if nft_merged_groups and hostvars[inventory_hostname]['nft_combined_rules'].nft__nat_group_postrouting_rules is defined %}
{% set _ = postroutingmerged.update(hostvars[inventory_hostname]['nft_combined_rules'].nft__nat_group_postrouting_rules) %}
{% endif %}
{% set _ = postroutingmerged.update(nft__nat_host_postrouting_rules) %}
chain postrouting {
{% for group, rules in postroutingmerged|dictsort %}
# {{ group }}
{% if not rules %}
# (none)
{% endif %}
{% for rule in rules %}
{{ rule }}
{% endfor %}
{% endfor %}
}

View File

@ -0,0 +1,21 @@
#jinja2: lstrip_blocks: "True", trim_blocks: "True"
# {{ ansible_managed }}
{% set preroutingmerged = nft__nat_default_prerouting_rules.copy() %}
{% set _ = preroutingmerged.update(nft__nat_prerouting_rules) %}
{% set _ = preroutingmerged.update(nft__nat_group_prerouting_rules) %}
{% if nft_merged_groups and hostvars[inventory_hostname]['nft_combined_rules'].nft__nat_group_prerouting_rules is defined %}
{% set _ = preroutingmerged.update(hostvars[inventory_hostname]['nft_combined_rules'].nft__nat_group_prerouting_rules) %}
{% endif %}
{% set _ = preroutingmerged.update(nft__nat_host_prerouting_rules) %}
chain prerouting {
{% for group, rules in preroutingmerged|dictsort %}
# {{ group }}
{% if not rules %}
# (none)
{% endif %}
{% for rule in rules %}
{{ rule }}
{% endfor %}
{% endfor %}
}

View File

@ -1,15 +1,20 @@
#jinja2: lstrip_blocks: "True", trim_blocks: "True"
# {{ ansible_managed }}
{% set setmerged = nft_set_default.copy() %}
{% set _ = setmerged.update(nft_set) %}
{% set _ = setmerged.update(nft_set_group) %}
{% if nft_merged_groups and hostvars[inventory_hostname]['nft_combined_rules'].nft_set_group is defined %}
{% set _ = setmerged.update(hostvars[inventory_hostname]['nft_combined_rules'].nft_set_group) %}
{% endif %}
{% set _ = setmerged.update(nft_set_host) %}
{% for set, rules in setmerged|dictsort %}
{% if rules %}
{% if rules %}
set {{ set }} {
{% for rule in rules %}
{% for rule in rules %}
{{ rule }}
{% endfor %}
{% endfor %}
}
{% endif %}
{% endif %}
{% endfor %}

View File

@ -0,0 +1,8 @@
# {{ ansible_managed }}
[Unit]
After=network.target iptables.service firewalld.service ip6tables.service ipset.service nftables.service
PartOf=firewalld.service nftables.service
[Install]
WantedBy=multi-user.target nftables.service

View File

@ -0,0 +1,7 @@
# {{ ansible_managed }}
[Service]
{% if not nft__service_protect %}
ProtectSystem=no
ProtectHome=no
{% endif %}

View File

@ -0,0 +1,21 @@
# {{ ansible_managed }}
[Unit]
Description={{ nft_service_name }}
Documentation=man:nft(8) http://wiki.nftables.org
Wants=network-pre.target
Before=network-pre.target shutdown.target
Conflicts=shutdown.target
DefaultDependencies=no
[Service]
Type=oneshot
RemainAfterExit=yes
StandardInput=null
ProtectSystem=full
ProtectHome=true
ExecStart={{ nft__bin_location }} -f {{ nft_main_conf_path }}
ExecReload={{ nft__bin_location }} -f {{ nft_main_conf_path }}
ExecStop={{ nft__bin_location }} flush ruleset
[Install]
WantedBy=sysinit.target

4
vars/alpine.yml Normal file
View File

@ -0,0 +1,4 @@
---
# vars file for Alpine
nft_pkg_list:
- nftables

4
vars/archlinux.yml Normal file
View File

@ -0,0 +1,4 @@
---
# vars file for Archlinux-based distros
nft_pkg_list:
- nftables

5
vars/gentoo.yml Normal file
View File

@ -0,0 +1,5 @@
---
# vars file for Gentoo
nft_pkg_list:
- net-firewall/nftables
nft__bin_location: "/sbin/nft"

4
vars/redhat.yml Normal file
View File

@ -0,0 +1,4 @@
---
# vars file for Centos-based distros
nft_pkg_list:
- nftables