diff --git a/CHANGELOG.md b/CHANGELOG.md index 81e0003..5300aa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Possibility to toggle file's backup (thanks to @p-rintz − PR #15). * Gentoo-specific variables * Ability to specify nft binary path through **nft__bin_location** +* Manage Fail2ban in the "systemd way" (thanks to @FinweVI − PR #16). ### Removed * Remove everything related to **in_udp_accept** (see conversation in PR #13). @@ -16,6 +17,9 @@ ### 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. +* Move systemd "Protect" options for nftables to specific override.conf file. ## v1.7.0 diff --git a/README.md b/README.md index 677987c..454af6a 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ * [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) @@ -79,7 +80,6 @@ complexify his philosophy… (I'm pretty sure, i now did complexify it :D) ^^ * **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__fail2ban_service** : If the Nftables service should also restart the Fail2ban service [default : `False`]. * **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']. @@ -570,6 +570,15 @@ This role will : * 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 [Gitea instance][nftables source] and the diff --git a/defaults/main.yml b/defaults/main.yml index 75904ee..9891ebc 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -551,6 +551,16 @@ nft_service_unit_path: '/lib/systemd/system/nftables.service' # 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 : @@ -562,18 +572,18 @@ nft_service_unit_content: 'lib/systemd/system/nftables.service.j2' # The directives will be ignored. nft__service_protect: true # ]]] -# .. envvar:: nft__fail2ban_service [[[ + +# .. envvar:: nft__fail2ban_service_unit_path [[[ # -# If the Nftables systemd unit should also restart Fail2ban service. Possible -# options are : -# -# ``False`` -# Default. Nftables service will not affect Fail2ban service. -# -# ``True`` -# Any Nftables service (re)start will also restart Fail2ban service. -nft__fail2ban_service: False +# 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: diff --git a/handlers/main.yml b/handlers/main.yml index cb7e015..764dbae 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -4,7 +4,10 @@ # (re)Start will be called at first run - name: Restart nftables service systemd: - daemon_reload: '{{ nftables__register_systemd_service.changed | default(False) }}' + 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 }}' diff --git a/molecule/archlinux/verify.yml b/molecule/archlinux/verify.yml index 3ac7ebe..8eb5316 100644 --- a/molecule/archlinux/verify.yml +++ b/molecule/archlinux/verify.yml @@ -26,7 +26,7 @@ that: - p.stat.exists - - name: check for nftables.conf + - name: check for filter-input.nft stat: path: /etc/nftables.d/filter-input.nft register: p @@ -53,6 +53,26 @@ - '"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 diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml index 3ac7ebe..8eb5316 100644 --- a/molecule/default/verify.yml +++ b/molecule/default/verify.yml @@ -26,7 +26,7 @@ that: - p.stat.exists - - name: check for nftables.conf + - name: check for filter-input.nft stat: path: /etc/nftables.d/filter-input.nft register: p @@ -53,6 +53,26 @@ - '"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 diff --git a/tasks/main.yml b/tasks/main.yml index 3746cc7..7f00a04 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -174,8 +174,8 @@ when: (nft_enabled|bool and nft__nat_table_manage|bool) -# Manage service [[[1 -- name: Install Debian systemd service unit +# Manage nftables service [[[1 +- name: Install nftables Debian systemd service unit template: src: '{{ nft_service_unit_content }}' dest: '{{ nft_service_unit_path }}' @@ -185,4 +185,61 @@ register: nftables__register_systemd_service when: (nft_enabled|bool and nft_service_manage|bool) - notify: ['Restart nftables service'] \ No newline at end of file + 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'] diff --git a/templates/etc/systemd/system/fail2ban.service.d/override.conf.j2 b/templates/etc/systemd/system/fail2ban.service.d/override.conf.j2 new file mode 100644 index 0000000..25eb25f --- /dev/null +++ b/templates/etc/systemd/system/fail2ban.service.d/override.conf.j2 @@ -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 diff --git a/templates/etc/systemd/system/nftables.service.d/override.conf.j2 b/templates/etc/systemd/system/nftables.service.d/override.conf.j2 new file mode 100644 index 0000000..0ee48c1 --- /dev/null +++ b/templates/etc/systemd/system/nftables.service.d/override.conf.j2 @@ -0,0 +1,7 @@ +# {{ ansible_managed }} + +[Service] +{% if not nft__service_protect %} +ProtectSystem=no +ProtectHome=no +{% endif %} diff --git a/templates/lib/systemd/system/nftables.service.j2 b/templates/lib/systemd/system/nftables.service.j2 index 87c51f5..7909452 100644 --- a/templates/lib/systemd/system/nftables.service.j2 +++ b/templates/lib/systemd/system/nftables.service.j2 @@ -2,25 +2,20 @@ [Unit] Description={{ nft_service_name }} Documentation=man:nft(8) http://wiki.nftables.org -;Before=fail2ban.service +Wants=network-pre.target +Before=network-pre.target shutdown.target +Conflicts=shutdown.target +DefaultDependencies=no [Service] Type=oneshot RemainAfterExit=yes StandardInput=null -{% if nft__service_protect %} ProtectSystem=full ProtectHome=true -{% endif %} -{% if nft__fail2ban_service %} -ExecStart={{ nft__bin_location }} -f {{ nft_main_conf_path }} ; /bin/systemctl restart fail2ban.service -ExecReload={{ nft__bin_location }} -f {{ nft_main_conf_path }} ; /bin/systemctl restart fail2ban.service -ExecStop=/bin/systemctl stop fail2ban.service ; {{ nft__bin_location }} flush ruleset -{% else %} ExecStart={{ nft__bin_location }} -f {{ nft_main_conf_path }} ExecReload={{ nft__bin_location }} -f {{ nft_main_conf_path }} ExecStop={{ nft__bin_location }} flush ruleset -{% endif %} [Install] -WantedBy=multi-user.target +WantedBy=sysinit.target