diff --git a/README.md b/README.md
index 3edfbf7..ff2ad45 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,47 @@
-# role_modele
+# role_nftables
-Modèle
\ No newline at end of file
+Ce rôle permet d'installer et configurer nftables.
+
+## Variables
+
+### nftables_rules_*
+
+Liste contenant un nom de fichier et une liste de règles. Les règles doivent être au format nftables.
+
+*Valeur par défaut: aucune*
+
+### nftables_tables_*
+
+Liste contenant un nom de fichier et la configuration de la table. La table doit être au format nftables.
+
+*Valeur par défaut: aucune*
+
+## Exemple d'utilisation
+
+### inventory.yml
+
+```yaml
+---
+
+all:
+ hosts:
+ host1.ykn.local:
+ host2.ykn.local:
+ children:
+ dnsservers:
+ hosts:
+ dnsmasq1.ykn.local:
+ dnsmasq2.ykn.local:
+```
+
+### host_vars/host1.ykn.local.yml
+
+```yaml
+---
+
+nftables_rules:
+ - filename: ansible
+ rules:
+ - ip saddr 192.168.50.12 tcp dport 22 accept
+ - ip6 saddr fd00:ff50::d012 tcp dport 22 accept
+```
diff --git a/defaults/main.yml b/defaults/main.yml
new file mode 100644
index 0000000..bedd20a
--- /dev/null
+++ b/defaults/main.yml
@@ -0,0 +1,5 @@
+---
+# defaults file for nftables
+
+nftables_rules: []
+nftables_tables: []
diff --git a/handlers/main.yml b/handlers/main.yml
new file mode 100644
index 0000000..b4120a6
--- /dev/null
+++ b/handlers/main.yml
@@ -0,0 +1,10 @@
+---
+# handlers file for nftables
+
+- name: Redémarrer nftables.service
+ ansible.builtin.systemd:
+ state: restarted
+ enabled: true
+ masked: false
+ name: nftables.service
+ become: true
diff --git a/meta/main.yml b/meta/main.yml
index c58bebf..23a4d0c 100644
--- a/meta/main.yml
+++ b/meta/main.yml
@@ -1,7 +1,7 @@
galaxy_info:
namespace: ykn
author: pulsar89.5
- description: Rôle modèle
+ description: Rôle de déploiement de nftables (pare-feu)
license: GPL-3.0-or-later
diff --git a/tasks/configuration.yml b/tasks/configuration.yml
new file mode 100644
index 0000000..026396f
--- /dev/null
+++ b/tasks/configuration.yml
@@ -0,0 +1,54 @@
+---
+# tasks file for nftables
+
+- name: Déployer la configuration générale
+ ansible.builtin.template:
+ owner: root
+ group: root
+ mode: u=rw,g=,o=
+ src: nftables.conf.j2
+ dest: /etc/nftables.conf
+ become: true
+ notify: Redémarrer nftables.service
+
+- name: Construire la liste des règles
+ ansible.builtin.set_fact:
+ nftables_rules: "{{ nftables_rules + specific }}"
+ when: specific | length > 0
+ loop: "{{ lookup('ansible.builtin.varnames', '^nftables_rules_.+', wantlist=True) }}"
+ vars:
+ specific: "{{ lookup('ansible.builtin.vars', item, default='') }}"
+
+- name: Construire la liste des tables
+ ansible.builtin.set_fact:
+ nftables_tables: "{{ nftables_tables + specific }}"
+ when: specific | length > 0
+ loop: "{{ lookup('ansible.builtin.varnames', '^nftables_tables_.+', wantlist=True) }}"
+ vars:
+ specific: "{{ lookup('ansible.builtin.vars', item, default='') }}"
+
+- name: Déployer les règles
+ ansible.builtin.template:
+ owner: root
+ group: root
+ mode: u=rw,g=,o=
+ src: "{{ role_path }}/templates/rules.conf.j2"
+ dest: "/srv/nftables/rules_{{ item.filename }}.conf"
+ loop: "{{ nftables_rules }}"
+ loop_control:
+ label: "{{ item.filename }}"
+ become: true
+ notify: Redémarrer nftables.service
+
+- name: Déployer les tables
+ ansible.builtin.template:
+ owner: root
+ group: root
+ mode: u=rw,g=,o=
+ src: "{{ role_path }}/templates/tables.conf.j2"
+ dest: "/srv/nftables/tables_{{ item.filename }}.conf"
+ loop: "{{ nftables_tables }}"
+ loop_control:
+ label: "{{ item.filename }}"
+ become: true
+ notify: Redémarrer nftables.service
diff --git a/tasks/installation.yml b/tasks/installation.yml
new file mode 100644
index 0000000..6c30564
--- /dev/null
+++ b/tasks/installation.yml
@@ -0,0 +1,17 @@
+---
+# tasks file for nftables
+
+- name: Installer le paquet
+ become: true
+ ansible.builtin.package:
+ state: present
+ name: nftables
+
+- name: Créer le dossier contenant la configuration
+ ansible.builtin.file:
+ owner: root
+ group: root
+ mode: u=rwx,g=rx,o=rx
+ state: directory
+ path: /srv/nftables
+ become: true
diff --git a/tasks/main.yml b/tasks/main.yml
new file mode 100644
index 0000000..a157ecc
--- /dev/null
+++ b/tasks/main.yml
@@ -0,0 +1,8 @@
+---
+# tasks file for nftables
+
+- name: Importer les tâches d'installation
+ ansible.builtin.import_tasks: installation.yml
+
+- name: Importer les tâches de configuration
+ ansible.builtin.import_tasks: configuration.yml
diff --git a/templates/nftables.conf.j2 b/templates/nftables.conf.j2
new file mode 100644
index 0000000..8df2dd3
--- /dev/null
+++ b/templates/nftables.conf.j2
@@ -0,0 +1,28 @@
+#!/usr/sbin/nft -f
+# {{ ansible_managed }}
+
+flush ruleset
+
+table inet filter {
+ chain input {
+ type filter hook input priority 0;
+
+ # accept any localhost traffic
+ iif lo accept
+
+ # accept traffic originated from us
+ ct state established,related accept
+
+ # accept neighbour discovery otherwise IPv6 connectivity breaks.
+ ip6 nexthdr icmpv6 icmpv6 type {nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert} accept
+
+ # include specifics rules
+ include "/srv/nftables/rules_*.conf"
+
+ # count and drop any other traffic
+ counter drop
+ }
+}
+
+# include more tables
+include "/srv/nftables/tables_*.conf"
diff --git a/templates/rules.conf.j2 b/templates/rules.conf.j2
new file mode 100644
index 0000000..81e015c
--- /dev/null
+++ b/templates/rules.conf.j2
@@ -0,0 +1,5 @@
+# {{ ansible_managed }}
+
+{% for rule in item.rules %}
+{{ rule }}
+{% endfor %}
diff --git a/templates/tables.conf.j2 b/templates/tables.conf.j2
new file mode 100644
index 0000000..cf8f928
--- /dev/null
+++ b/templates/tables.conf.j2
@@ -0,0 +1,57 @@
+# {{ ansible_managed }}
+
+{% if
+ item.ipv4_rules.prerouting | length > 0
+ or
+ item.ipv4_rules.postrouting | length > 0
+%}
+table ip {{ item.filename }} {
+{% if item.ipv4_rules.prerouting | length > 0 %}
+ chain prerouting {
+ type nat hook prerouting priority 0;
+
+{% for rule in item.ipv4_rules.prerouting %}
+ {{ rule }}
+{% endfor %}
+ }
+{% endif %}
+
+{% if item.ipv4_rules.postrouting | length > 0 %}
+ chain postrouting {
+ type nat hook postrouting priority 100; policy accept;
+
+{% for rule in item.ipv4_rules.postrouting %}
+ {{ rule }}
+{% endfor %}
+ }
+{% endif %}
+}
+{% endif %}
+
+{% if
+ item.ipv6_rules.prerouting | length > 0
+ or
+ item.ipv6_rules.postrouting | length > 0
+%}
+table ip6 {{ item.filename }} {
+{% if item.ipv6_rules.prerouting | length > 0 %}
+ chain prerouting {
+ type nat hook prerouting priority 0;
+
+{% for rule in item.ipv6_rules.prerouting %}
+ {{ rule }}
+{% endfor %}
+ }
+{% endif %}
+
+{% if item.ipv6_rules.postrouting | length > 0 %}
+ chain postrouting {
+ type nat hook postrouting priority 100; policy accept;
+
+{% for rule in item.ipv6_rules.postrouting %}
+ {{ rule }}
+{% endfor %}
+ }
+{% endif %}
+}
+{% endif %}