diff --git a/roles/nftables/defaults/main.yaml b/roles/nftables/defaults/main.yaml new file mode 100644 index 0000000..f90a042 --- /dev/null +++ b/roles/nftables/defaults/main.yaml @@ -0,0 +1,70 @@ +--- +# nftables_ufw_package_name: ufw +# nftables_ufw_package_state: absent + +# nftables_package_name: nftables +# nftables_package_state: present + +# nftables_service_name: nftables +# nftables_service_state: started +# nftables_service_enabled: true + +# nftables_config_path: /etc/nftables.conf + +nftables_builtin_defines: + REQUIRED_ICMPV6_TYPES: + - 1-4 + - 130-136 + - 141-143 + - 148-149 + - 151-153 + TRACEROUTE_UDP_PORTS: 33434-33534 + +nftables_builtin_sets: + blackhole4: + - type ipv4_addr + - flags interval + blackhole6: + - type ipv6_addr + - flags interval + tcp_input_accept: + - type inet_service + - flags interval + - elements = { ssh } + udp_input_accept: + - type inet_service + - flags interval + +nftables_input_builtin_rules: + - type filter hook input priority filter; policy drop; + - ip saddr @blackhole4 drop + - ip6 saddr @blackhole6 drop + - ct state established,related accept + - ct state invalid drop + - iifname "lo" accept + - icmpv6 type $REQUIRED_ICMPV6_TYPES accept + - icmpv6 type echo-request accept + - icmp type echo-request accept + - tcp dport @tcp_input_accept accept + - udp dport @udp_input_accept accept + # this should be last because these ports could be allowed + - udp dport $TRACEROUTE_UDP_PORTS reject + +nftables_forward_builtin_rules: + - type filter hook forward priority filter; policy drop; + - ct state { established, related } accept + +nftables_output_builtin_rules: + - type filter hook output priority filter; policy accept; + - ip daddr @blackhole4 drop + - ip6 daddr @blackhole6 drop + - ct state { established, related } accept + +# nftables_sets: +# {} +# +# nftables_input_rules: +# [] +# +# nftables_output_rules: +# [] diff --git a/roles/nftables/handlers/main.yaml b/roles/nftables/handlers/main.yaml new file mode 100644 index 0000000..39aef62 --- /dev/null +++ b/roles/nftables/handlers/main.yaml @@ -0,0 +1,10 @@ +--- +- name: reload nftables + ansible.builtin.service: + name: "{{ nftables_service_name | default('nftables') }}" + state: reloaded + +- name: restart nftables + ansible.builtin.service: + name: "{{ nftables_service_name | default('nftables') }}" + state: restarted diff --git a/roles/nftables/tasks/Ubuntu.yaml b/roles/nftables/tasks/Ubuntu.yaml new file mode 100644 index 0000000..4360e15 --- /dev/null +++ b/roles/nftables/tasks/Ubuntu.yaml @@ -0,0 +1,5 @@ +--- +- name: remove ufw + ansible.builtin.package: + name: "{{ nftables_ufw_package_name | default('ufw') }}" + state: "{{ nftables_ufw_package_state | default('absent') }}" diff --git a/roles/nftables/tasks/configure.yaml b/roles/nftables/tasks/configure.yaml new file mode 100644 index 0000000..3b34d0c --- /dev/null +++ b/roles/nftables/tasks/configure.yaml @@ -0,0 +1,16 @@ +--- +- name: configure rules + ansible.builtin.template: + src: nftables.conf.j2 + dest: "{{ nftables_config_path | default('/etc/nftables.conf') }}" + owner: root + group: root + mode: 0600 + notify: + - restart nftables + +- name: manage service + ansible.builtin.service: + name: "{{ nftables_service_name | default('nftables') }}" + state: "{{ nftables_service_state | default('started') }}" + enabled: "{{ nftables_service_enabled | default(true) }}" diff --git a/roles/nftables/tasks/default.yaml b/roles/nftables/tasks/default.yaml new file mode 100644 index 0000000..e69de29 diff --git a/roles/nftables/tasks/install.yaml b/roles/nftables/tasks/install.yaml new file mode 100644 index 0000000..1daaaa0 --- /dev/null +++ b/roles/nftables/tasks/install.yaml @@ -0,0 +1,5 @@ +--- +- name: remove ufw + ansible.builtin.package: + name: "{{ nftables_package_name | default('nftables') }}" + state: "{{ nftables_package_state | default('present') }}" diff --git a/roles/nftables/tasks/main.yaml b/roles/nftables/tasks/main.yaml new file mode 100644 index 0000000..63873a4 --- /dev/null +++ b/roles/nftables/tasks/main.yaml @@ -0,0 +1,28 @@ +--- +- name: gather OS specific variables + ansible.builtin.include_vars: "{{ lookup('ansible.builtin.first_found', params) }}" + vars: + params: + files: + - "{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yaml" + - "{{ ansible_distribution }}.yaml" + - "{{ ansible_os_family }}.yaml" + - "default.yaml" + paths: + - vars + +- name: run os specific tasks + ansible.builtin.include_tasks: "{{ lookup('ansible.builtin.first_found', params) }}" + vars: + params: + files: + - "{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yaml" + - "{{ ansible_distribution }}.yaml" + - "{{ ansible_os_family }}.yaml" + - "default.yaml" + paths: + - tasks + +- include_tasks: install.yaml + +- include_tasks: configure.yaml diff --git a/roles/nftables/templates/nftables.conf.j2 b/roles/nftables/templates/nftables.conf.j2 new file mode 100644 index 0000000..51db0ae --- /dev/null +++ b/roles/nftables/templates/nftables.conf.j2 @@ -0,0 +1,82 @@ +table inet filter { +{% if nftables_builtin_defines is mapping %} +{% for name, cfg in nftables_builtin_defines.items() %} +{% if cfg is string %} + define {{ name }} = {{ cfg }} +{% elif cfg is sequence %} + define {{ name }} = { +{% for elem in cfg %} + {{ elem }}, +{% endfor %} + } +{% endif %} +{% endfor %} +{% endif %} +{% if nftables_defines is mapping %} +{% for name, cfg in nftables_defines.items() %} + define {{ name }} = { +{% for elem in cfg %} + {{ elem }}, +{% endfor %} + } +{% endfor %} +{% endif %} + +{% if nftables_builtin_sets is mapping %} +{% for name, cfg in nftables_builtin_sets.items() %} + set {{ name }} { +{% for elem in cfg %} + {{ elem }} +{% endfor %} + } +{% endfor %} +{% endif %} +{% if nftables_sets is mapping %} +{% for name, cfg in nftables_sets.items() %} + set {{ name }} { +{% for elem in cfg %} + {{ elem }} +{% endfor %} + } +{% endfor %} +{% endif %} + + chain input { +{% if nftables_input_builtin_rules is sequence %} +{% for rule in nftables_input_builtin_rules %} + {{ rule }} +{% endfor %} +{% endif %} +{% if nftables_input_rules is sequence %} +{% for rule in nftables_input_rules %} + {{ rule }} +{% endfor %} +{% endif %} + } + + chain forward { +{% if nftables_forward_builtin_rules is sequence %} +{% for rule in nftables_forward_builtin_rules %} + {{ rule }} +{% endfor %} +{% endif %} +{% if nftables_forward_rules is sequence %} +{% for rule in nftables_forward_rules %} + {{ rule }} +{% endfor %} +{% endif %} + } + + chain output { +{% if nftables_output_builtin_rules is sequence %} +{% for rule in nftables_output_builtin_rules %} + {{ rule }} +{% endfor %} +{% endif %} +{% if nftables_output_rules is sequence %} +{% for rule in nftables_output_rules %} + {{ rule }} +{% endfor %} +{% endif %} + } +} diff --git a/roles/nftables/vars/default.yaml b/roles/nftables/vars/default.yaml new file mode 100644 index 0000000..e69de29